zone.c revision 279265
1/*
2 * Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003  Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id$ */
19
20/*! \file */
21
22#include <config.h>
23#include <errno.h>
24
25#include <isc/file.h>
26#include <isc/hex.h>
27#include <isc/mutex.h>
28#include <isc/pool.h>
29#include <isc/print.h>
30#include <isc/random.h>
31#include <isc/ratelimiter.h>
32#include <isc/refcount.h>
33#include <isc/rwlock.h>
34#include <isc/serial.h>
35#include <isc/stats.h>
36#include <isc/stdtime.h>
37#include <isc/strerror.h>
38#include <isc/string.h>
39#include <isc/taskpool.h>
40#include <isc/thread.h>
41#include <isc/timer.h>
42#include <isc/util.h>
43
44#include <dns/acache.h>
45#include <dns/acl.h>
46#include <dns/adb.h>
47#include <dns/callbacks.h>
48#include <dns/db.h>
49#include <dns/dbiterator.h>
50#include <dns/dnssec.h>
51#include <dns/events.h>
52#include <dns/journal.h>
53#include <dns/keydata.h>
54#include <dns/keytable.h>
55#include <dns/keyvalues.h>
56#include <dns/log.h>
57#include <dns/master.h>
58#include <dns/masterdump.h>
59#include <dns/message.h>
60#include <dns/name.h>
61#include <dns/nsec.h>
62#include <dns/nsec3.h>
63#include <dns/peer.h>
64#include <dns/private.h>
65#include <dns/rbt.h>
66#include <dns/rcode.h>
67#include <dns/rdata.h>
68#include <dns/rdataclass.h>
69#include <dns/rdatalist.h>
70#include <dns/rdataset.h>
71#include <dns/rdatasetiter.h>
72#include <dns/rdatastruct.h>
73#include <dns/rdatatype.h>
74#include <dns/request.h>
75#include <dns/resolver.h>
76#include <dns/result.h>
77#include <dns/rriterator.h>
78#include <dns/soa.h>
79#include <dns/ssu.h>
80#include <dns/stats.h>
81#include <dns/time.h>
82#include <dns/tsig.h>
83#include <dns/update.h>
84#include <dns/xfrin.h>
85#include <dns/zone.h>
86#include <dns/zt.h>
87
88#include <dst/dst.h>
89
90#define ZONE_MAGIC			ISC_MAGIC('Z', 'O', 'N', 'E')
91#define DNS_ZONE_VALID(zone)		ISC_MAGIC_VALID(zone, ZONE_MAGIC)
92
93#define NOTIFY_MAGIC			ISC_MAGIC('N', 't', 'f', 'y')
94#define DNS_NOTIFY_VALID(notify)	ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
95
96#define STUB_MAGIC			ISC_MAGIC('S', 't', 'u', 'b')
97#define DNS_STUB_VALID(stub)		ISC_MAGIC_VALID(stub, STUB_MAGIC)
98
99#define ZONEMGR_MAGIC			ISC_MAGIC('Z', 'm', 'g', 'r')
100#define DNS_ZONEMGR_VALID(stub)		ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
101
102#define LOAD_MAGIC			ISC_MAGIC('L', 'o', 'a', 'd')
103#define DNS_LOAD_VALID(load)		ISC_MAGIC_VALID(load, LOAD_MAGIC)
104
105#define FORWARD_MAGIC			ISC_MAGIC('F', 'o', 'r', 'w')
106#define DNS_FORWARD_VALID(load)		ISC_MAGIC_VALID(load, FORWARD_MAGIC)
107
108#define IO_MAGIC			ISC_MAGIC('Z', 'm', 'I', 'O')
109#define DNS_IO_VALID(load)		ISC_MAGIC_VALID(load, IO_MAGIC)
110
111/*%
112 * Ensure 'a' is at least 'min' but not more than 'max'.
113 */
114#define RANGE(a, min, max) \
115		(((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
116
117#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
118
119/*%
120 * Key flags
121 */
122#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
123#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
124#define ALG(x) dst_key_alg(x)
125
126/*
127 * Default values.
128 */
129#define DNS_DEFAULT_IDLEIN 3600		/*%< 1 hour */
130#define DNS_DEFAULT_IDLEOUT 3600	/*%< 1 hour */
131#define MAX_XFER_TIME (2*3600)		/*%< Documented default is 2 hours */
132#define RESIGN_DELAY 3600		/*%< 1 hour */
133
134#ifndef DNS_MAX_EXPIRE
135#define DNS_MAX_EXPIRE	14515200	/*%< 24 weeks */
136#endif
137
138#ifndef DNS_DUMP_DELAY
139#define DNS_DUMP_DELAY 900		/*%< 15 minutes */
140#endif
141
142typedef struct dns_notify dns_notify_t;
143typedef struct dns_stub dns_stub_t;
144typedef struct dns_load dns_load_t;
145typedef struct dns_forward dns_forward_t;
146typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
147typedef struct dns_io dns_io_t;
148typedef ISC_LIST(dns_io_t) dns_iolist_t;
149typedef struct dns_signing dns_signing_t;
150typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
151typedef struct dns_nsec3chain dns_nsec3chain_t;
152typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
153typedef struct dns_keyfetch dns_keyfetch_t;
154typedef struct dns_asyncload dns_asyncload_t;
155
156#define DNS_ZONE_CHECKLOCK
157#ifdef DNS_ZONE_CHECKLOCK
158#define LOCK_ZONE(z) \
159	 do { LOCK(&(z)->lock); \
160	      INSIST((z)->locked == ISC_FALSE); \
161	     (z)->locked = ISC_TRUE; \
162		} while (0)
163#define UNLOCK_ZONE(z) \
164	do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
165#define LOCKED_ZONE(z) ((z)->locked)
166#define TRYLOCK_ZONE(result, z) \
167	do { \
168	      result = isc_mutex_trylock(&(z)->lock); \
169	      if (result == ISC_R_SUCCESS) {  \
170		     INSIST((z)->locked == ISC_FALSE); \
171		     (z)->locked = ISC_TRUE; \
172	      } \
173	} while (0)
174#else
175#define LOCK_ZONE(z) LOCK(&(z)->lock)
176#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
177#define LOCKED_ZONE(z) ISC_TRUE
178#define TRYLOCK_ZONE(result, z) \
179	do { result = isc_mutex_trylock(&(z)->lock); } while (0)
180#endif
181
182#ifdef ISC_RWLOCK_USEATOMIC
183#define ZONEDB_INITLOCK(l)	isc_rwlock_init((l), 0, 0)
184#define ZONEDB_DESTROYLOCK(l)	isc_rwlock_destroy(l)
185#define ZONEDB_LOCK(l, t)	RWLOCK((l), (t))
186#define ZONEDB_UNLOCK(l, t)	RWUNLOCK((l), (t))
187#else
188#define ZONEDB_INITLOCK(l)	isc_mutex_init(l)
189#define ZONEDB_DESTROYLOCK(l)	DESTROYLOCK(l)
190#define ZONEDB_LOCK(l, t)	LOCK(l)
191#define ZONEDB_UNLOCK(l, t)	UNLOCK(l)
192#endif
193
194struct dns_zone {
195	/* Unlocked */
196	unsigned int		magic;
197	isc_mutex_t		lock;
198#ifdef DNS_ZONE_CHECKLOCK
199	isc_boolean_t		locked;
200#endif
201	isc_mem_t		*mctx;
202	isc_refcount_t		erefs;
203
204#ifdef ISC_RWLOCK_USEATOMIC
205	isc_rwlock_t		dblock;
206#else
207	isc_mutex_t		dblock;
208#endif
209	dns_db_t		*db;		/* Locked by dblock */
210
211	/* Locked */
212	dns_zonemgr_t		*zmgr;
213	ISC_LINK(dns_zone_t)	link;		/* Used by zmgr. */
214	isc_timer_t		*timer;
215	unsigned int		irefs;
216	dns_name_t		origin;
217	char			*masterfile;
218	dns_masterformat_t	masterformat;
219	char			*journal;
220	isc_int32_t		journalsize;
221	dns_rdataclass_t	rdclass;
222	dns_zonetype_t		type;
223	unsigned int		flags;
224	unsigned int		options;
225	unsigned int		db_argc;
226	char			**db_argv;
227	isc_time_t		expiretime;
228	isc_time_t		refreshtime;
229	isc_time_t		dumptime;
230	isc_time_t		loadtime;
231	isc_time_t		notifytime;
232	isc_time_t		resigntime;
233	isc_time_t		keywarntime;
234	isc_time_t		signingtime;
235	isc_time_t		nsec3chaintime;
236	isc_time_t		refreshkeytime;
237	isc_uint32_t		refreshkeyinterval;
238	isc_uint32_t		refreshkeycount;
239	isc_uint32_t		refresh;
240	isc_uint32_t		retry;
241	isc_uint32_t		expire;
242	isc_uint32_t		minimum;
243	isc_stdtime_t		key_expiry;
244	isc_stdtime_t		log_key_expired_timer;
245	char			*keydirectory;
246
247	isc_uint32_t		maxrefresh;
248	isc_uint32_t		minrefresh;
249	isc_uint32_t		maxretry;
250	isc_uint32_t		minretry;
251
252	isc_sockaddr_t		*masters;
253	dns_name_t		**masterkeynames;
254	isc_boolean_t		*mastersok;
255	unsigned int		masterscnt;
256	unsigned int		curmaster;
257	isc_sockaddr_t		masteraddr;
258	dns_notifytype_t	notifytype;
259	isc_sockaddr_t		*notify;
260	dns_name_t		**notifykeynames;
261	unsigned int		notifycnt;
262	isc_sockaddr_t		notifyfrom;
263	isc_task_t		*task;
264	isc_task_t		*loadtask;
265	isc_sockaddr_t		notifysrc4;
266	isc_sockaddr_t		notifysrc6;
267	isc_sockaddr_t		xfrsource4;
268	isc_sockaddr_t		xfrsource6;
269	isc_sockaddr_t		altxfrsource4;
270	isc_sockaddr_t		altxfrsource6;
271	isc_sockaddr_t		sourceaddr;
272	dns_xfrin_ctx_t		*xfr;		/* task locked */
273	dns_tsigkey_t		*tsigkey;	/* key used for xfr */
274	/* Access Control Lists */
275	dns_acl_t		*update_acl;
276	dns_acl_t		*forward_acl;
277	dns_acl_t		*notify_acl;
278	dns_acl_t		*query_acl;
279	dns_acl_t		*queryon_acl;
280	dns_acl_t		*xfr_acl;
281	isc_boolean_t		update_disabled;
282	isc_boolean_t		zero_no_soa_ttl;
283	dns_severity_t		check_names;
284	ISC_LIST(dns_notify_t)	notifies;
285	dns_request_t		*request;
286	dns_loadctx_t		*lctx;
287	dns_io_t		*readio;
288	dns_dumpctx_t		*dctx;
289	dns_io_t		*writeio;
290	isc_uint32_t		maxxfrin;
291	isc_uint32_t		maxxfrout;
292	isc_uint32_t		idlein;
293	isc_uint32_t		idleout;
294	isc_event_t		ctlevent;
295	dns_ssutable_t		*ssutable;
296	isc_uint32_t		sigvalidityinterval;
297	isc_uint32_t		sigresigninginterval;
298	dns_view_t		*view;
299	dns_acache_t		*acache;
300	dns_checkmxfunc_t	checkmx;
301	dns_checksrvfunc_t	checksrv;
302	dns_checknsfunc_t	checkns;
303	/*%
304	 * Zones in certain states such as "waiting for zone transfer"
305	 * or "zone transfer in progress" are kept on per-state linked lists
306	 * in the zone manager using the 'statelink' field.  The 'statelist'
307	 * field points at the list the zone is currently on.  It the zone
308	 * is not on any such list, statelist is NULL.
309	 */
310	ISC_LINK(dns_zone_t)	statelink;
311	dns_zonelist_t		*statelist;
312	/*%
313	 * Statistics counters about zone management.
314	 */
315	isc_stats_t		*stats;
316	/*%
317	 * Optional per-zone statistics counters.  Counted outside of this
318	 * module.
319	 */
320	dns_zonestat_level_t	statlevel;
321	isc_boolean_t		requeststats_on;
322	isc_stats_t		*requeststats;
323	dns_stats_t		*rcvquerystats;
324	isc_uint32_t		notifydelay;
325	dns_isselffunc_t	isself;
326	void			*isselfarg;
327
328	char *			strnamerd;
329	char *			strname;
330	char *			strrdclass;
331	char *			strviewname;
332
333	/*%
334	 * Serial number for deferred journal compaction.
335	 */
336	isc_uint32_t		compact_serial;
337	/*%
338	 * Keys that are signing the zone for the first time.
339	 */
340	dns_signinglist_t	signing;
341	dns_nsec3chainlist_t	nsec3chain;
342	/*%
343	 * Signing / re-signing quantum stopping parameters.
344	 */
345	isc_uint32_t		signatures;
346	isc_uint32_t		nodes;
347	dns_rdatatype_t		privatetype;
348
349	/*%
350	 * Autosigning/key-maintenance options
351	 */
352	isc_uint32_t		keyopts;
353
354	/*%
355	 * True if added by "rndc addzone"
356	 */
357	isc_boolean_t           added;
358
359	/*%
360	 * whether this is a response policy zone
361	 */
362	isc_boolean_t           is_rpz;
363
364	/*%
365	 * Serial number update method.
366	 */
367	dns_updatemethod_t	updatemethod;
368
369	/*%
370	 * whether ixfr is requested
371	 */
372	isc_boolean_t		requestixfr;
373
374	/*%
375	 * Outstanding forwarded UPDATE requests.
376	 */
377	dns_forwardlist_t	forwards;
378
379	dns_zone_t		*raw;
380	dns_zone_t		*secure;
381
382	isc_boolean_t		sourceserialset;
383	isc_uint32_t		sourceserial;
384};
385
386typedef struct {
387	dns_diff_t	*diff;
388	isc_boolean_t	offline;
389} zonediff_t;
390
391#define zonediff_init(z, d) \
392	do { \
393		zonediff_t *_z = (z); \
394		(_z)->diff = (d); \
395		(_z)->offline = ISC_FALSE; \
396	} while (0)
397
398#define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
399#define DNS_ZONE_SETFLAG(z,f) do { \
400		INSIST(LOCKED_ZONE(z)); \
401		(z)->flags |= (f); \
402		} while (0)
403#define DNS_ZONE_CLRFLAG(z,f) do { \
404		INSIST(LOCKED_ZONE(z)); \
405		(z)->flags &= ~(f); \
406		} while (0)
407	/* XXX MPA these may need to go back into zone.h */
408#define DNS_ZONEFLG_REFRESH	0x00000001U	/*%< refresh check in progress */
409#define DNS_ZONEFLG_NEEDDUMP	0x00000002U	/*%< zone need consolidation */
410#define DNS_ZONEFLG_USEVC	0x00000004U	/*%< use tcp for refresh query */
411#define DNS_ZONEFLG_DUMPING	0x00000008U	/*%< a dump is in progress */
412#define DNS_ZONEFLG_HASINCLUDE	0x00000010U	/*%< $INCLUDE in zone file */
413#define DNS_ZONEFLG_LOADED	0x00000020U	/*%< database has loaded */
414#define DNS_ZONEFLG_EXITING	0x00000040U	/*%< zone is being destroyed */
415#define DNS_ZONEFLG_EXPIRED	0x00000080U	/*%< zone has expired */
416#define DNS_ZONEFLG_NEEDREFRESH	0x00000100U	/*%< refresh check needed */
417#define DNS_ZONEFLG_UPTODATE	0x00000200U	/*%< zone contents are
418						 * uptodate */
419#define DNS_ZONEFLG_NEEDNOTIFY	0x00000400U	/*%< need to send out notify
420						 * messages */
421#define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U	/*%< generate a journal diff on
422						 * reload */
423#define DNS_ZONEFLG_NOMASTERS	0x00001000U	/*%< an attempt to refresh a
424						 * zone with no masters
425						 * occurred */
426#define DNS_ZONEFLG_LOADING	0x00002000U	/*%< load from disk in progress*/
427#define DNS_ZONEFLG_HAVETIMERS	0x00004000U	/*%< timer values have been set
428						 * from SOA (if not set, we
429						 * are still using
430						 * default timer values) */
431#define DNS_ZONEFLG_FORCEXFER	0x00008000U	/*%< Force a zone xfer */
432#define DNS_ZONEFLG_NOREFRESH	0x00010000U
433#define DNS_ZONEFLG_DIALNOTIFY	0x00020000U
434#define DNS_ZONEFLG_DIALREFRESH	0x00040000U
435#define DNS_ZONEFLG_SHUTDOWN	0x00080000U
436#define DNS_ZONEFLAG_NOIXFR	0x00100000U	/*%< IXFR failed, force AXFR */
437#define DNS_ZONEFLG_FLUSH	0x00200000U
438#define DNS_ZONEFLG_NOEDNS	0x00400000U
439#define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
440#define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
441#define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
442#define DNS_ZONEFLG_REFRESHING	0x04000000U	/*%< Refreshing keydata */
443#define DNS_ZONEFLG_THAW	0x08000000U
444#define DNS_ZONEFLG_LOADPENDING	0x10000000U	/*%< Loading scheduled */
445#define DNS_ZONEFLG_NODELAY	0x20000000U
446#define DNS_ZONEFLG_SENDSECURE  0x40000000U
447
448#define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
449#define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
450
451/* Flags for zone_load() */
452#define DNS_ZONELOADFLAG_NOSTAT	0x00000001U	/* Do not stat() master files */
453#define DNS_ZONELOADFLAG_THAW	0x00000002U	/* Thaw the zone on successful
454						   load. */
455
456#define UNREACH_CHACHE_SIZE	10U
457#define UNREACH_HOLD_TIME	600	/* 10 minutes */
458
459#define CHECK(op) \
460	do { result = (op); \
461		if (result != ISC_R_SUCCESS) goto failure; \
462	} while (0)
463
464struct dns_unreachable {
465	isc_sockaddr_t	remote;
466	isc_sockaddr_t	local;
467	isc_uint32_t	expire;
468	isc_uint32_t	last;
469	isc_uint32_t	count;
470};
471
472struct dns_zonemgr {
473	unsigned int		magic;
474	isc_mem_t *		mctx;
475	int			refs;		/* Locked by rwlock */
476	isc_taskmgr_t *		taskmgr;
477	isc_timermgr_t *	timermgr;
478	isc_socketmgr_t *	socketmgr;
479	isc_taskpool_t *	zonetasks;
480	isc_taskpool_t *	loadtasks;
481	isc_task_t *		task;
482	isc_pool_t *		mctxpool;
483	isc_ratelimiter_t *	notifyrl;
484	isc_ratelimiter_t *	refreshrl;
485	isc_rwlock_t		rwlock;
486	isc_mutex_t		iolock;
487	isc_rwlock_t		urlock;
488
489	/* Locked by rwlock. */
490	dns_zonelist_t		zones;
491	dns_zonelist_t		waiting_for_xfrin;
492	dns_zonelist_t		xfrin_in_progress;
493
494	/* Configuration data. */
495	isc_uint32_t		transfersin;
496	isc_uint32_t		transfersperns;
497	unsigned int		serialqueryrate;
498
499	/* Locked by iolock */
500	isc_uint32_t		iolimit;
501	isc_uint32_t		ioactive;
502	dns_iolist_t		high;
503	dns_iolist_t		low;
504
505	/* Locked by urlock. */
506	/* LRU cache */
507	struct dns_unreachable	unreachable[UNREACH_CHACHE_SIZE];
508};
509
510/*%
511 * Hold notify state.
512 */
513struct dns_notify {
514	unsigned int		magic;
515	unsigned int		flags;
516	isc_mem_t		*mctx;
517	dns_zone_t		*zone;
518	dns_adbfind_t		*find;
519	dns_request_t		*request;
520	dns_name_t		ns;
521	isc_sockaddr_t		dst;
522	dns_tsigkey_t		*key;
523	ISC_LINK(dns_notify_t)	link;
524};
525
526#define DNS_NOTIFY_NOSOA	0x0001U
527
528/*%
529 *	dns_stub holds state while performing a 'stub' transfer.
530 *	'db' is the zone's 'db' or a new one if this is the initial
531 *	transfer.
532 */
533
534struct dns_stub {
535	unsigned int		magic;
536	isc_mem_t		*mctx;
537	dns_zone_t		*zone;
538	dns_db_t		*db;
539	dns_dbversion_t		*version;
540};
541
542/*%
543 *	Hold load state.
544 */
545struct dns_load {
546	unsigned int		magic;
547	isc_mem_t		*mctx;
548	dns_zone_t		*zone;
549	dns_db_t		*db;
550	isc_time_t		loadtime;
551	dns_rdatacallbacks_t	callbacks;
552};
553
554/*%
555 *	Hold forward state.
556 */
557struct dns_forward {
558	unsigned int		magic;
559	isc_mem_t		*mctx;
560	dns_zone_t		*zone;
561	isc_buffer_t		*msgbuf;
562	dns_request_t		*request;
563	isc_uint32_t		which;
564	isc_sockaddr_t		addr;
565	dns_updatecallback_t	callback;
566	void			*callback_arg;
567	ISC_LINK(dns_forward_t)	link;
568};
569
570/*%
571 *	Hold IO request state.
572 */
573struct dns_io {
574	unsigned int	magic;
575	dns_zonemgr_t	*zmgr;
576	isc_boolean_t	high;
577	isc_task_t	*task;
578	ISC_LINK(dns_io_t) link;
579	isc_event_t	*event;
580};
581
582/*%
583 *	Hold state for when we are signing a zone with a new
584 *	DNSKEY as result of an update.
585 */
586struct dns_signing {
587	unsigned int		magic;
588	dns_db_t		*db;
589	dns_dbiterator_t	*dbiterator;
590	dns_secalg_t		algorithm;
591	isc_uint16_t		keyid;
592	isc_boolean_t		delete;
593	isc_boolean_t		done;
594	ISC_LINK(dns_signing_t)	link;
595};
596
597struct dns_nsec3chain {
598	unsigned int			magic;
599	dns_db_t			*db;
600	dns_dbiterator_t		*dbiterator;
601	dns_rdata_nsec3param_t		nsec3param;
602	unsigned char			salt[255];
603	isc_boolean_t			done;
604	isc_boolean_t			seen_nsec;
605	isc_boolean_t			delete_nsec;
606	isc_boolean_t			save_delete_nsec;
607	ISC_LINK(dns_nsec3chain_t)	link;
608};
609/*%<
610 * 'dbiterator' contains a iterator for the database.  If we are creating
611 * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
612 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
613 * iterated.
614 *
615 * 'nsec3param' contains the parameters of the NSEC3 chain being created
616 * or removed.
617 *
618 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
619 *
620 * 'seen_nsec' will be set to true if, while iterating the zone to create a
621 * NSEC3 chain, a NSEC record is seen.
622 *
623 * 'delete_nsec' will be set to true if, at the completion of the creation
624 * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
625 * are in the process of deleting the NSEC chain.
626 *
627 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
628 * so it can be recovered in the event of a error.
629 */
630
631struct dns_keyfetch {
632	dns_fixedname_t name;
633	dns_rdataset_t keydataset;
634	dns_rdataset_t dnskeyset;
635	dns_rdataset_t dnskeysigset;
636	dns_zone_t *zone;
637	dns_db_t *db;
638	dns_fetch_t *fetch;
639};
640
641/*%
642 * Hold state for an asynchronous load
643 */
644struct dns_asyncload {
645	dns_zone_t *zone;
646	dns_zt_zoneloaded_t loaded;
647	void *loaded_arg;
648};
649
650#define HOUR 3600
651#define DAY (24*HOUR)
652#define MONTH (30*DAY)
653
654#define SEND_BUFFER_SIZE 2048
655
656static void zone_settimer(dns_zone_t *, isc_time_t *);
657static void cancel_refresh(dns_zone_t *);
658static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
659			  const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
660static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
661     ISC_FORMAT_PRINTF(3, 4);
662static void queue_xfrin(dns_zone_t *zone);
663static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
664				  dns_diff_t *diff, dns_diffop_t op,
665				  dns_name_t *name, dns_ttl_t ttl,
666				  dns_rdata_t *rdata);
667static void zone_unload(dns_zone_t *zone);
668static void zone_expire(dns_zone_t *zone);
669static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
670static void zone_idetach(dns_zone_t **zonep);
671static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
672				   isc_boolean_t dump);
673static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
674static inline void zone_detachdb(dns_zone_t *zone);
675static isc_result_t default_journal(dns_zone_t *zone);
676static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
677static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
678				  isc_time_t loadtime, isc_result_t result);
679static void zone_needdump(dns_zone_t *zone, unsigned int delay);
680static void zone_shutdown(isc_task_t *, isc_event_t *);
681static void zone_loaddone(void *arg, isc_result_t result);
682static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
683				   isc_time_t loadtime);
684static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
685static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
686static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
687static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
688static isc_result_t zone_send_secureserial(dns_zone_t *zone,
689					   isc_uint32_t serial);
690
691#if 0
692/* ondestroy example */
693static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
694#endif
695
696static void refresh_callback(isc_task_t *, isc_event_t *);
697static void stub_callback(isc_task_t *, isc_event_t *);
698static void queue_soa_query(dns_zone_t *zone);
699static void soa_query(isc_task_t *, isc_event_t *);
700static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
701		     dns_stub_t *stub);
702static int message_count(dns_message_t *msg, dns_section_t section,
703			 dns_rdatatype_t type);
704static void notify_cancel(dns_zone_t *zone);
705static void notify_find_address(dns_notify_t *notify);
706static void notify_send(dns_notify_t *notify);
707static isc_result_t notify_createmessage(dns_zone_t *zone,
708					 unsigned int flags,
709					 dns_message_t **messagep);
710static void notify_done(isc_task_t *task, isc_event_t *event);
711static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
712static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
713static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
714static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
715					     dns_zone_t *zone);
716static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
717static void zonemgr_free(dns_zonemgr_t *zmgr);
718static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
719				  isc_task_t *task, isc_taskaction_t action,
720				  void *arg, dns_io_t **iop);
721static void zonemgr_putio(dns_io_t **iop);
722static void zonemgr_cancelio(dns_io_t *io);
723
724static isc_result_t
725zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
726		 unsigned int *soacount, isc_uint32_t *serial,
727		 isc_uint32_t *refresh, isc_uint32_t *retry,
728		 isc_uint32_t *expire, isc_uint32_t *minimum,
729		 unsigned int *errors);
730
731static void zone_freedbargs(dns_zone_t *zone);
732static void forward_callback(isc_task_t *task, isc_event_t *event);
733static void zone_saveunique(dns_zone_t *zone, const char *path,
734			    const char *templat);
735static void zone_maintenance(dns_zone_t *zone);
736static void zone_notify(dns_zone_t *zone, isc_time_t *now);
737static void dump_done(void *arg, isc_result_t result);
738static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
739				     isc_uint16_t keyid, isc_boolean_t delete);
740static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
741				dns_dbnode_t *node, dns_name_t *name,
742				dns_diff_t *diff);
743static void zone_rekey(dns_zone_t *zone);
744static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
745
746#define ENTER zone_debuglog(zone, me, 1, "enter")
747
748static const unsigned int dbargc_default = 1;
749static const char *dbargv_default[] = { "rbt" };
750
751#define DNS_ZONE_JITTER_ADD(a, b, c) \
752	do { \
753		isc_interval_t _i; \
754		isc_uint32_t _j; \
755		_j = isc_random_jitter((b), (b)/4); \
756		isc_interval_set(&_i, _j, 0); \
757		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
758			dns_zone_log(zone, ISC_LOG_WARNING, \
759				     "epoch approaching: upgrade required: " \
760				     "now + %s failed", #b); \
761			isc_interval_set(&_i, _j/2, 0); \
762			(void)isc_time_add((a), &_i, (c)); \
763		} \
764	} while (0)
765
766#define DNS_ZONE_TIME_ADD(a, b, c) \
767	do { \
768		isc_interval_t _i; \
769		isc_interval_set(&_i, (b), 0); \
770		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
771			dns_zone_log(zone, ISC_LOG_WARNING, \
772				     "epoch approaching: upgrade required: " \
773				     "now + %s failed", #b); \
774			isc_interval_set(&_i, (b)/2, 0); \
775			(void)isc_time_add((a), &_i, (c)); \
776		} \
777	} while (0)
778
779typedef struct nsec3param nsec3param_t;
780struct nsec3param {
781	unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
782	unsigned int length;
783	isc_boolean_t nsec;
784	isc_boolean_t replace;
785	ISC_LINK(nsec3param_t)	link;
786};
787typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
788struct np3event {
789	isc_event_t event;
790	nsec3param_t params;
791};
792
793/*%
794 * Increment resolver-related statistics counters.  Zone must be locked.
795 */
796static inline void
797inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
798	if (zone->stats != NULL)
799		isc_stats_increment(zone->stats, counter);
800}
801
802/***
803 ***	Public functions.
804 ***/
805
806isc_result_t
807dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
808	isc_result_t result;
809	dns_zone_t *zone;
810	isc_time_t now;
811
812	REQUIRE(zonep != NULL && *zonep == NULL);
813	REQUIRE(mctx != NULL);
814
815	TIME_NOW(&now);
816	zone = isc_mem_get(mctx, sizeof(*zone));
817	if (zone == NULL)
818		return (ISC_R_NOMEMORY);
819
820	zone->mctx = NULL;
821	isc_mem_attach(mctx, &zone->mctx);
822
823	result = isc_mutex_init(&zone->lock);
824	if (result != ISC_R_SUCCESS)
825		goto free_zone;
826
827	result = ZONEDB_INITLOCK(&zone->dblock);
828	if (result != ISC_R_SUCCESS)
829		goto free_mutex;
830
831	/* XXX MPA check that all elements are initialised */
832#ifdef DNS_ZONE_CHECKLOCK
833	zone->locked = ISC_FALSE;
834#endif
835	zone->db = NULL;
836	zone->zmgr = NULL;
837	ISC_LINK_INIT(zone, link);
838	result = isc_refcount_init(&zone->erefs, 1);	/* Implicit attach. */
839	if (result != ISC_R_SUCCESS)
840		goto free_dblock;
841	zone->irefs = 0;
842	dns_name_init(&zone->origin, NULL);
843	zone->strnamerd = NULL;
844	zone->strname = NULL;
845	zone->strrdclass = NULL;
846	zone->strviewname = NULL;
847	zone->masterfile = NULL;
848	zone->masterformat = dns_masterformat_none;
849	zone->keydirectory = NULL;
850	zone->journalsize = -1;
851	zone->journal = NULL;
852	zone->rdclass = dns_rdataclass_none;
853	zone->type = dns_zone_none;
854	zone->flags = 0;
855	zone->options = 0;
856	zone->keyopts = 0;
857	zone->db_argc = 0;
858	zone->db_argv = NULL;
859	isc_time_settoepoch(&zone->expiretime);
860	isc_time_settoepoch(&zone->refreshtime);
861	isc_time_settoepoch(&zone->dumptime);
862	isc_time_settoepoch(&zone->loadtime);
863	zone->notifytime = now;
864	isc_time_settoepoch(&zone->resigntime);
865	isc_time_settoepoch(&zone->keywarntime);
866	isc_time_settoepoch(&zone->signingtime);
867	isc_time_settoepoch(&zone->nsec3chaintime);
868	isc_time_settoepoch(&zone->refreshkeytime);
869	zone->refreshkeyinterval = 0;
870	zone->refreshkeycount = 0;
871	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
872	zone->retry = DNS_ZONE_DEFAULTRETRY;
873	zone->expire = 0;
874	zone->minimum = 0;
875	zone->maxrefresh = DNS_ZONE_MAXREFRESH;
876	zone->minrefresh = DNS_ZONE_MINREFRESH;
877	zone->maxretry = DNS_ZONE_MAXRETRY;
878	zone->minretry = DNS_ZONE_MINRETRY;
879	zone->masters = NULL;
880	zone->masterkeynames = NULL;
881	zone->mastersok = NULL;
882	zone->masterscnt = 0;
883	zone->curmaster = 0;
884	zone->notify = NULL;
885	zone->notifykeynames = NULL;
886	zone->notifytype = dns_notifytype_yes;
887	zone->notifycnt = 0;
888	zone->task = NULL;
889	zone->loadtask = NULL;
890	zone->update_acl = NULL;
891	zone->forward_acl = NULL;
892	zone->notify_acl = NULL;
893	zone->query_acl = NULL;
894	zone->queryon_acl = NULL;
895	zone->xfr_acl = NULL;
896	zone->update_disabled = ISC_FALSE;
897	zone->zero_no_soa_ttl = ISC_TRUE;
898	zone->check_names = dns_severity_ignore;
899	zone->request = NULL;
900	zone->lctx = NULL;
901	zone->readio = NULL;
902	zone->dctx = NULL;
903	zone->writeio = NULL;
904	zone->timer = NULL;
905	zone->idlein = DNS_DEFAULT_IDLEIN;
906	zone->idleout = DNS_DEFAULT_IDLEOUT;
907	zone->log_key_expired_timer = 0;
908	ISC_LIST_INIT(zone->notifies);
909	isc_sockaddr_any(&zone->notifysrc4);
910	isc_sockaddr_any6(&zone->notifysrc6);
911	isc_sockaddr_any(&zone->xfrsource4);
912	isc_sockaddr_any6(&zone->xfrsource6);
913	isc_sockaddr_any(&zone->altxfrsource4);
914	isc_sockaddr_any6(&zone->altxfrsource6);
915	zone->xfr = NULL;
916	zone->tsigkey = NULL;
917	zone->maxxfrin = MAX_XFER_TIME;
918	zone->maxxfrout = MAX_XFER_TIME;
919	zone->ssutable = NULL;
920	zone->sigvalidityinterval = 30 * 24 * 3600;
921	zone->sigresigninginterval = 7 * 24 * 3600;
922	zone->view = NULL;
923	zone->acache = NULL;
924	zone->checkmx = NULL;
925	zone->checksrv = NULL;
926	zone->checkns = NULL;
927	ISC_LINK_INIT(zone, statelink);
928	zone->statelist = NULL;
929	zone->stats = NULL;
930	zone->requeststats_on = ISC_FALSE;
931	zone->statlevel = dns_zonestat_none;
932	zone->requeststats = NULL;
933	zone->rcvquerystats = NULL;
934	zone->notifydelay = 5;
935	zone->isself = NULL;
936	zone->isselfarg = NULL;
937	ISC_LIST_INIT(zone->signing);
938	ISC_LIST_INIT(zone->nsec3chain);
939	zone->signatures = 10;
940	zone->nodes = 100;
941	zone->privatetype = (dns_rdatatype_t)0xffffU;
942	zone->added = ISC_FALSE;
943	zone->is_rpz = ISC_FALSE;
944	ISC_LIST_INIT(zone->forwards);
945	zone->raw = NULL;
946	zone->secure = NULL;
947	zone->sourceserial = 0;
948	zone->sourceserialset = ISC_FALSE;
949
950	zone->magic = ZONE_MAGIC;
951
952	/* Must be after magic is set. */
953	result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
954	if (result != ISC_R_SUCCESS)
955		goto free_erefs;
956
957	ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
958		       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
959		       NULL, NULL);
960	*zonep = zone;
961	return (ISC_R_SUCCESS);
962
963 free_erefs:
964	isc_refcount_decrement(&zone->erefs, NULL);
965	isc_refcount_destroy(&zone->erefs);
966
967 free_dblock:
968	ZONEDB_DESTROYLOCK(&zone->dblock);
969
970 free_mutex:
971	DESTROYLOCK(&zone->lock);
972
973 free_zone:
974	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
975	return (result);
976}
977
978/*
979 * Free a zone.  Because we require that there be no more
980 * outstanding events or references, no locking is necessary.
981 */
982static void
983zone_free(dns_zone_t *zone) {
984	isc_mem_t *mctx = NULL;
985	dns_signing_t *signing;
986	dns_nsec3chain_t *nsec3chain;
987
988	REQUIRE(DNS_ZONE_VALID(zone));
989	REQUIRE(isc_refcount_current(&zone->erefs) == 0);
990	REQUIRE(zone->irefs == 0);
991	REQUIRE(!LOCKED_ZONE(zone));
992	REQUIRE(zone->timer == NULL);
993	REQUIRE(zone->zmgr == NULL);
994
995	/*
996	 * Managed objects.  Order is important.
997	 */
998	if (zone->request != NULL)
999		dns_request_destroy(&zone->request); /* XXXMPA */
1000	INSIST(zone->readio == NULL);
1001	INSIST(zone->statelist == NULL);
1002	INSIST(zone->writeio == NULL);
1003
1004	if (zone->task != NULL)
1005		isc_task_detach(&zone->task);
1006	if (zone->loadtask != NULL)
1007		isc_task_detach(&zone->loadtask);
1008
1009	/* Unmanaged objects */
1010	for (signing = ISC_LIST_HEAD(zone->signing);
1011	     signing != NULL;
1012	     signing = ISC_LIST_HEAD(zone->signing)) {
1013		ISC_LIST_UNLINK(zone->signing, signing, link);
1014		dns_db_detach(&signing->db);
1015		dns_dbiterator_destroy(&signing->dbiterator);
1016		isc_mem_put(zone->mctx, signing, sizeof *signing);
1017	}
1018	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
1019	     nsec3chain != NULL;
1020	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
1021		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1022		dns_db_detach(&nsec3chain->db);
1023		dns_dbiterator_destroy(&nsec3chain->dbiterator);
1024		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1025	}
1026	if (zone->masterfile != NULL)
1027		isc_mem_free(zone->mctx, zone->masterfile);
1028	zone->masterfile = NULL;
1029	if (zone->keydirectory != NULL)
1030		isc_mem_free(zone->mctx, zone->keydirectory);
1031	zone->keydirectory = NULL;
1032	zone->journalsize = -1;
1033	if (zone->journal != NULL)
1034		isc_mem_free(zone->mctx, zone->journal);
1035	zone->journal = NULL;
1036	if (zone->stats != NULL)
1037		isc_stats_detach(&zone->stats);
1038	if (zone->requeststats != NULL)
1039		isc_stats_detach(&zone->requeststats);
1040	if(zone->rcvquerystats != NULL )
1041		dns_stats_detach(&zone->rcvquerystats);
1042	if (zone->db != NULL)
1043		zone_detachdb(zone);
1044	if (zone->acache != NULL)
1045		dns_acache_detach(&zone->acache);
1046	zone_freedbargs(zone);
1047	RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
1048		      == ISC_R_SUCCESS);
1049	RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
1050		      == ISC_R_SUCCESS);
1051	zone->check_names = dns_severity_ignore;
1052	if (zone->update_acl != NULL)
1053		dns_acl_detach(&zone->update_acl);
1054	if (zone->forward_acl != NULL)
1055		dns_acl_detach(&zone->forward_acl);
1056	if (zone->notify_acl != NULL)
1057		dns_acl_detach(&zone->notify_acl);
1058	if (zone->query_acl != NULL)
1059		dns_acl_detach(&zone->query_acl);
1060	if (zone->queryon_acl != NULL)
1061		dns_acl_detach(&zone->queryon_acl);
1062	if (zone->xfr_acl != NULL)
1063		dns_acl_detach(&zone->xfr_acl);
1064	if (dns_name_dynamic(&zone->origin))
1065		dns_name_free(&zone->origin, zone->mctx);
1066	if (zone->strnamerd != NULL)
1067		isc_mem_free(zone->mctx, zone->strnamerd);
1068	if (zone->strname != NULL)
1069		isc_mem_free(zone->mctx, zone->strname);
1070	if (zone->strrdclass != NULL)
1071		isc_mem_free(zone->mctx, zone->strrdclass);
1072	if (zone->strviewname != NULL)
1073		isc_mem_free(zone->mctx, zone->strviewname);
1074	if (zone->ssutable != NULL)
1075		dns_ssutable_detach(&zone->ssutable);
1076
1077	/* last stuff */
1078	ZONEDB_DESTROYLOCK(&zone->dblock);
1079	DESTROYLOCK(&zone->lock);
1080	isc_refcount_destroy(&zone->erefs);
1081	zone->magic = 0;
1082	mctx = zone->mctx;
1083	isc_mem_put(mctx, zone, sizeof(*zone));
1084	isc_mem_detach(&mctx);
1085}
1086
1087/*
1088 * Returns ISC_TRUE iff this the signed side of an inline-signing zone.
1089 * Caller should hold zone lock.
1090 */
1091static inline isc_boolean_t
1092inline_secure(dns_zone_t *zone) {
1093	REQUIRE(DNS_ZONE_VALID(zone));
1094	if (zone->raw != NULL)
1095		return (ISC_TRUE);
1096	return (ISC_FALSE);
1097}
1098
1099/*
1100 * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone
1101 * Caller should hold zone lock.
1102 */
1103static inline isc_boolean_t
1104inline_raw(dns_zone_t *zone) {
1105	REQUIRE(DNS_ZONE_VALID(zone));
1106	if (zone->secure != NULL)
1107		return (ISC_TRUE);
1108	return (ISC_FALSE);
1109}
1110
1111/*
1112 *	Single shot.
1113 */
1114void
1115dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1116	char namebuf[1024];
1117
1118	REQUIRE(DNS_ZONE_VALID(zone));
1119	REQUIRE(rdclass != dns_rdataclass_none);
1120
1121	/*
1122	 * Test and set.
1123	 */
1124	LOCK_ZONE(zone);
1125	REQUIRE(zone->rdclass == dns_rdataclass_none ||
1126		zone->rdclass == rdclass);
1127	zone->rdclass = rdclass;
1128
1129	if (zone->strnamerd != NULL)
1130		isc_mem_free(zone->mctx, zone->strnamerd);
1131	if (zone->strrdclass != NULL)
1132		isc_mem_free(zone->mctx, zone->strrdclass);
1133
1134	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1135	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1136	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1137	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1138
1139	if (inline_secure(zone))
1140		dns_zone_setclass(zone->raw, rdclass);
1141	UNLOCK_ZONE(zone);
1142}
1143
1144dns_rdataclass_t
1145dns_zone_getclass(dns_zone_t *zone) {
1146	REQUIRE(DNS_ZONE_VALID(zone));
1147
1148	return (zone->rdclass);
1149}
1150
1151void
1152dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1153	REQUIRE(DNS_ZONE_VALID(zone));
1154
1155	LOCK_ZONE(zone);
1156	zone->notifytype = notifytype;
1157	UNLOCK_ZONE(zone);
1158}
1159
1160isc_result_t
1161dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1162	isc_result_t result;
1163	unsigned int soacount;
1164
1165	REQUIRE(DNS_ZONE_VALID(zone));
1166	REQUIRE(serialp != NULL);
1167
1168	LOCK_ZONE(zone);
1169	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1170	if (zone->db != NULL) {
1171		result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1172					  serialp, NULL, NULL, NULL, NULL,
1173					  NULL);
1174		if (result == ISC_R_SUCCESS && soacount == 0)
1175			result = ISC_R_FAILURE;
1176	} else
1177		result = DNS_R_NOTLOADED;
1178	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1179	UNLOCK_ZONE(zone);
1180
1181	return (result);
1182}
1183
1184isc_uint32_t
1185dns_zone_getserial(dns_zone_t *zone) {
1186	isc_result_t result;
1187	isc_uint32_t serial;
1188
1189	result = dns_zone_getserial2(zone, &serial);
1190	if (result != ISC_R_SUCCESS)
1191		serial = 0; /* XXX: not really correct, but no other choice */
1192
1193	return (serial);
1194}
1195
1196/*
1197 *	Single shot.
1198 */
1199void
1200dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1201	char namebuf[1024];
1202
1203	REQUIRE(DNS_ZONE_VALID(zone));
1204	REQUIRE(type != dns_zone_none);
1205
1206	/*
1207	 * Test and set.
1208	 */
1209	LOCK_ZONE(zone);
1210	REQUIRE(zone->type == dns_zone_none || zone->type == type);
1211	zone->type = type;
1212
1213	if (zone->strnamerd != NULL)
1214		isc_mem_free(zone->mctx, zone->strnamerd);
1215
1216	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1217	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1218	UNLOCK_ZONE(zone);
1219}
1220
1221static void
1222zone_freedbargs(dns_zone_t *zone) {
1223	unsigned int i;
1224
1225	/* Free the old database argument list. */
1226	if (zone->db_argv != NULL) {
1227		for (i = 0; i < zone->db_argc; i++)
1228			isc_mem_free(zone->mctx, zone->db_argv[i]);
1229		isc_mem_put(zone->mctx, zone->db_argv,
1230			    zone->db_argc * sizeof(*zone->db_argv));
1231	}
1232	zone->db_argc = 0;
1233	zone->db_argv = NULL;
1234}
1235
1236isc_result_t
1237dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1238	size_t size = 0;
1239	unsigned int i;
1240	isc_result_t result = ISC_R_SUCCESS;
1241	void *mem;
1242	char **tmp, *tmp2;
1243
1244	REQUIRE(DNS_ZONE_VALID(zone));
1245	REQUIRE(argv != NULL && *argv == NULL);
1246
1247	LOCK_ZONE(zone);
1248	size = (zone->db_argc + 1) * sizeof(char *);
1249	for (i = 0; i < zone->db_argc; i++)
1250		size += strlen(zone->db_argv[i]) + 1;
1251	mem = isc_mem_allocate(mctx, size);
1252	if (mem != NULL) {
1253		tmp = mem;
1254		tmp2 = mem;
1255		tmp2 += (zone->db_argc + 1) * sizeof(char *);
1256		for (i = 0; i < zone->db_argc; i++) {
1257			*tmp++ = tmp2;
1258			strcpy(tmp2, zone->db_argv[i]);
1259			tmp2 += strlen(tmp2) + 1;
1260		}
1261		*tmp = NULL;
1262	} else
1263		result = ISC_R_NOMEMORY;
1264	UNLOCK_ZONE(zone);
1265	*argv = mem;
1266	return (result);
1267}
1268
1269isc_result_t
1270dns_zone_setdbtype(dns_zone_t *zone,
1271		   unsigned int dbargc, const char * const *dbargv) {
1272	isc_result_t result = ISC_R_SUCCESS;
1273	char **new = NULL;
1274	unsigned int i;
1275
1276	REQUIRE(DNS_ZONE_VALID(zone));
1277	REQUIRE(dbargc >= 1);
1278	REQUIRE(dbargv != NULL);
1279
1280	LOCK_ZONE(zone);
1281
1282	/* Set up a new database argument list. */
1283	new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1284	if (new == NULL)
1285		goto nomem;
1286	for (i = 0; i < dbargc; i++)
1287		new[i] = NULL;
1288	for (i = 0; i < dbargc; i++) {
1289		new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1290		if (new[i] == NULL)
1291			goto nomem;
1292	}
1293
1294	/* Free the old list. */
1295	zone_freedbargs(zone);
1296
1297	zone->db_argc = dbargc;
1298	zone->db_argv = new;
1299	result = ISC_R_SUCCESS;
1300	goto unlock;
1301
1302 nomem:
1303	if (new != NULL) {
1304		for (i = 0; i < dbargc; i++)
1305			if (new[i] != NULL)
1306				isc_mem_free(zone->mctx, new[i]);
1307		isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1308	}
1309	result = ISC_R_NOMEMORY;
1310
1311 unlock:
1312	UNLOCK_ZONE(zone);
1313	return (result);
1314}
1315
1316void
1317dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1318	char namebuf[1024];
1319	REQUIRE(DNS_ZONE_VALID(zone));
1320
1321	LOCK_ZONE(zone);
1322	if (zone->view != NULL)
1323		dns_view_weakdetach(&zone->view);
1324	dns_view_weakattach(view, &zone->view);
1325
1326	if (zone->strviewname != NULL)
1327		isc_mem_free(zone->mctx, zone->strviewname);
1328	if (zone->strnamerd != NULL)
1329		isc_mem_free(zone->mctx, zone->strnamerd);
1330
1331	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1332	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1333	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1334	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1335
1336	if (inline_secure(zone))
1337		dns_zone_setview(zone->raw, view);
1338
1339	UNLOCK_ZONE(zone);
1340}
1341
1342dns_view_t *
1343dns_zone_getview(dns_zone_t *zone) {
1344	REQUIRE(DNS_ZONE_VALID(zone));
1345
1346	return (zone->view);
1347}
1348
1349
1350isc_result_t
1351dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1352	isc_result_t result;
1353	char namebuf[1024];
1354
1355	REQUIRE(DNS_ZONE_VALID(zone));
1356	REQUIRE(origin != NULL);
1357
1358	LOCK_ZONE(zone);
1359	if (dns_name_dynamic(&zone->origin)) {
1360		dns_name_free(&zone->origin, zone->mctx);
1361		dns_name_init(&zone->origin, NULL);
1362	}
1363	result = dns_name_dup(origin, zone->mctx, &zone->origin);
1364
1365	if (zone->strnamerd != NULL)
1366		isc_mem_free(zone->mctx, zone->strnamerd);
1367	if (zone->strname != NULL)
1368		isc_mem_free(zone->mctx, zone->strname);
1369
1370	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1371	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1372	zone_name_tostr(zone, namebuf, sizeof namebuf);
1373	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1374
1375	if (result == ISC_R_SUCCESS && inline_secure(zone))
1376		result = dns_zone_setorigin(zone->raw, origin);
1377	UNLOCK_ZONE(zone);
1378	return (result);
1379}
1380
1381void
1382dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1383	REQUIRE(DNS_ZONE_VALID(zone));
1384	REQUIRE(acache != NULL);
1385
1386	LOCK_ZONE(zone);
1387	if (zone->acache != NULL)
1388		dns_acache_detach(&zone->acache);
1389	dns_acache_attach(acache, &zone->acache);
1390	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1391	if (zone->db != NULL) {
1392		isc_result_t result;
1393
1394		/*
1395		 * If the zone reuses an existing DB, the DB needs to be
1396		 * set in the acache explicitly.  We can safely ignore the
1397		 * case where the DB is already set.  If other error happens,
1398		 * the acache will not work effectively.
1399		 */
1400		result = dns_acache_setdb(acache, zone->db);
1401		if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1402			UNEXPECTED_ERROR(__FILE__, __LINE__,
1403					 "dns_acache_setdb() failed: %s",
1404					 isc_result_totext(result));
1405		}
1406	}
1407	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1408	UNLOCK_ZONE(zone);
1409}
1410
1411static isc_result_t
1412dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1413	char *copy;
1414
1415	if (value != NULL) {
1416		copy = isc_mem_strdup(zone->mctx, value);
1417		if (copy == NULL)
1418			return (ISC_R_NOMEMORY);
1419	} else {
1420		copy = NULL;
1421	}
1422
1423	if (*field != NULL)
1424		isc_mem_free(zone->mctx, *field);
1425
1426	*field = copy;
1427	return (ISC_R_SUCCESS);
1428}
1429
1430isc_result_t
1431dns_zone_setfile(dns_zone_t *zone, const char *file) {
1432	return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1433}
1434
1435isc_result_t
1436dns_zone_setfile2(dns_zone_t *zone, const char *file,
1437		  dns_masterformat_t format) {
1438	isc_result_t result = ISC_R_SUCCESS;
1439
1440	REQUIRE(DNS_ZONE_VALID(zone));
1441
1442	LOCK_ZONE(zone);
1443	result = dns_zone_setstring(zone, &zone->masterfile, file);
1444	if (result == ISC_R_SUCCESS) {
1445		zone->masterformat = format;
1446		result = default_journal(zone);
1447	}
1448	UNLOCK_ZONE(zone);
1449
1450	return (result);
1451}
1452
1453const char *
1454dns_zone_getfile(dns_zone_t *zone) {
1455	REQUIRE(DNS_ZONE_VALID(zone));
1456
1457	return (zone->masterfile);
1458}
1459
1460static isc_result_t
1461default_journal(dns_zone_t *zone) {
1462	isc_result_t result;
1463	char *journal;
1464
1465	REQUIRE(DNS_ZONE_VALID(zone));
1466	REQUIRE(LOCKED_ZONE(zone));
1467
1468	if (zone->masterfile != NULL) {
1469		/* Calculate string length including '\0'. */
1470		int len = strlen(zone->masterfile) + sizeof(".jnl");
1471		journal = isc_mem_allocate(zone->mctx, len);
1472		if (journal == NULL)
1473			return (ISC_R_NOMEMORY);
1474		strcpy(journal, zone->masterfile);
1475		strcat(journal, ".jnl");
1476	} else {
1477		journal = NULL;
1478	}
1479	result = dns_zone_setstring(zone, &zone->journal, journal);
1480	if (journal != NULL)
1481		isc_mem_free(zone->mctx, journal);
1482	return (result);
1483}
1484
1485isc_result_t
1486dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1487	isc_result_t result = ISC_R_SUCCESS;
1488
1489	REQUIRE(DNS_ZONE_VALID(zone));
1490
1491	LOCK_ZONE(zone);
1492	result = dns_zone_setstring(zone, &zone->journal, journal);
1493	UNLOCK_ZONE(zone);
1494
1495	return (result);
1496}
1497
1498char *
1499dns_zone_getjournal(dns_zone_t *zone) {
1500	REQUIRE(DNS_ZONE_VALID(zone));
1501
1502	return (zone->journal);
1503}
1504
1505/*
1506 * Return true iff the zone is "dynamic", in the sense that the zone's
1507 * master file (if any) is written by the server, rather than being
1508 * updated manually and read by the server.
1509 *
1510 * This is true for slave zones, stub zones, key zones, and zones that
1511 * allow dynamic updates either by having an update policy ("ssutable")
1512 * or an "allow-update" ACL with a value other than exactly "{ none; }".
1513 */
1514isc_boolean_t
1515dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) {
1516	REQUIRE(DNS_ZONE_VALID(zone));
1517
1518	if (zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1519	    zone->type == dns_zone_key ||
1520	    (zone->type == dns_zone_redirect && zone->masters != NULL))
1521		return (ISC_TRUE);
1522
1523	/* If !ignore_freeze, we need check whether updates are disabled.  */
1524	if (zone->type == dns_zone_master &&
1525	    (!zone->update_disabled || ignore_freeze) &&
1526	    ((zone->ssutable != NULL) ||
1527	     (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1528		return (ISC_TRUE);
1529
1530	return (ISC_FALSE);
1531
1532}
1533
1534/*
1535 * Set the response policy index and information for a zone.
1536 */
1537isc_result_t
1538dns_zone_rpz_enable(dns_zone_t *zone) {
1539	/*
1540	 * Only RBTDB zones can be used for response policy zones,
1541	 * because only they have the code to load the create the summary data.
1542	 * Only zones that are loaded instead of mmap()ed create the
1543	 * summary data and so can be policy zones.
1544	 */
1545	if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1546	    strcmp(zone->db_argv[0], "rbt64") != 0)
1547		return (ISC_R_NOTIMPLEMENTED);
1548
1549	zone->is_rpz = ISC_TRUE;
1550
1551	return (ISC_R_SUCCESS);
1552}
1553
1554isc_boolean_t
1555dns_zone_get_rpz(dns_zone_t *zone) {
1556	return (zone->is_rpz);
1557}
1558
1559/*
1560 * If a zone is a response policy zone, mark its new database.
1561 */
1562isc_result_t
1563dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1564#ifdef BIND9
1565	if (zone->is_rpz)
1566		return (dns_db_rpz_enabled(db, NULL));
1567#endif
1568	return (ISC_R_SUCCESS);
1569}
1570
1571static isc_result_t
1572zone_load(dns_zone_t *zone, unsigned int flags) {
1573	isc_result_t result;
1574	isc_time_t now;
1575	isc_time_t loadtime, filetime;
1576	dns_db_t *db = NULL;
1577	isc_boolean_t rbt, hasraw;
1578
1579	REQUIRE(DNS_ZONE_VALID(zone));
1580
1581	LOCK_ZONE(zone);
1582	hasraw = inline_secure(zone);
1583	if (hasraw) {
1584		result = zone_load(zone->raw, flags);
1585		if (result != ISC_R_SUCCESS) {
1586			UNLOCK_ZONE(zone);
1587			return(result);
1588		}
1589		LOCK_ZONE(zone->raw);
1590	}
1591
1592	TIME_NOW(&now);
1593
1594	INSIST(zone->type != dns_zone_none);
1595
1596	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1597		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1598			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1599		result = DNS_R_CONTINUE;
1600		goto cleanup;
1601	}
1602
1603	INSIST(zone->db_argc >= 1);
1604
1605	rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1606	      strcmp(zone->db_argv[0], "rbt64") == 0;
1607
1608	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1609		/*
1610		 * The zone has no master file configured.
1611		 */
1612		result = ISC_R_SUCCESS;
1613		goto cleanup;
1614	}
1615
1616	if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) {
1617		/*
1618		 * This is a slave, stub, or dynamically updated
1619		 * zone being reloaded.  Do nothing - the database
1620		 * we already have is guaranteed to be up-to-date.
1621		 */
1622		if (zone->type == dns_zone_master)
1623			result = DNS_R_DYNAMIC;
1624		else
1625			result = ISC_R_SUCCESS;
1626		goto cleanup;
1627	}
1628
1629	/*
1630	 * Store the current time before the zone is loaded, so that if the
1631	 * file changes between the time of the load and the time that
1632	 * zone->loadtime is set, then the file will still be reloaded
1633	 * the next time dns_zone_load is called.
1634	 */
1635	TIME_NOW(&loadtime);
1636
1637	/*
1638	 * Don't do the load if the file that stores the zone is older
1639	 * than the last time the zone was loaded.  If the zone has not
1640	 * been loaded yet, zone->loadtime will be the epoch.
1641	 */
1642	if (zone->masterfile != NULL) {
1643		/*
1644		 * The file is already loaded.	If we are just doing a
1645		 * "rndc reconfig", we are done.
1646		 */
1647		if (!isc_time_isepoch(&zone->loadtime) &&
1648		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1649			result = ISC_R_SUCCESS;
1650			goto cleanup;
1651		}
1652
1653		result = isc_file_getmodtime(zone->masterfile, &filetime);
1654		if (result == ISC_R_SUCCESS) {
1655			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1656			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1657			    isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1658				dns_zone_log(zone, ISC_LOG_DEBUG(1),
1659					     "skipping load: master file "
1660					     "older than last load");
1661				result = DNS_R_UPTODATE;
1662				goto cleanup;
1663			}
1664			loadtime = filetime;
1665		}
1666	}
1667
1668	/*
1669	 * Built in zones (with the exception of empty zones) don't need
1670	 * to be reloaded.
1671	 */
1672	if (zone->type == dns_zone_master &&
1673	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
1674	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1675	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1676		result = ISC_R_SUCCESS;
1677		goto cleanup;
1678	}
1679
1680	if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1681	     (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
1682	    rbt) {
1683		if (zone->masterfile == NULL ||
1684		    !isc_file_exists(zone->masterfile)) {
1685			if (zone->masterfile != NULL) {
1686				dns_zone_log(zone, ISC_LOG_DEBUG(1),
1687					     "no master file");
1688			}
1689			zone->refreshtime = now;
1690			if (zone->task != NULL)
1691				zone_settimer(zone, &now);
1692			result = ISC_R_SUCCESS;
1693			goto cleanup;
1694		}
1695	}
1696
1697	dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1698
1699	result = dns_db_create(zone->mctx, zone->db_argv[0],
1700			       &zone->origin, (zone->type == dns_zone_stub) ?
1701			       dns_dbtype_stub : dns_dbtype_zone,
1702			       zone->rdclass,
1703			       zone->db_argc - 1, zone->db_argv + 1,
1704			       &db);
1705
1706	if (result != ISC_R_SUCCESS) {
1707		dns_zone_log(zone, ISC_LOG_ERROR,
1708			     "loading zone: creating database: %s",
1709			     isc_result_totext(result));
1710		goto cleanup;
1711	}
1712	dns_db_settask(db, zone->task);
1713
1714	if (! dns_db_ispersistent(db)) {
1715		if (zone->masterfile != NULL) {
1716			result = zone_startload(db, zone, loadtime);
1717		} else {
1718			result = DNS_R_NOMASTERFILE;
1719			if (zone->type == dns_zone_master ||
1720			    (zone->type == dns_zone_redirect &&
1721			     zone->masters == NULL)) {
1722				dns_zone_log(zone, ISC_LOG_ERROR,
1723					     "loading zone: "
1724					     "no master file configured");
1725				goto cleanup;
1726			}
1727			dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1728				     "no master file configured: continuing");
1729		}
1730	}
1731
1732	if (result == DNS_R_CONTINUE) {
1733		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1734		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1735			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1736		goto cleanup;
1737	}
1738
1739	result = zone_postload(zone, db, loadtime, result);
1740
1741 cleanup:
1742	if (hasraw)
1743		UNLOCK_ZONE(zone->raw);
1744	UNLOCK_ZONE(zone);
1745	if (db != NULL)
1746		dns_db_detach(&db);
1747	return (result);
1748}
1749
1750isc_result_t
1751dns_zone_load(dns_zone_t *zone) {
1752	return (zone_load(zone, 0));
1753}
1754
1755isc_result_t
1756dns_zone_loadnew(dns_zone_t *zone) {
1757	return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1758}
1759
1760static void
1761zone_asyncload(isc_task_t *task, isc_event_t *event) {
1762	dns_asyncload_t *asl = event->ev_arg;
1763	dns_zone_t *zone = asl->zone;
1764	isc_result_t result = ISC_R_SUCCESS;
1765
1766	UNUSED(task);
1767
1768	REQUIRE(DNS_ZONE_VALID(zone));
1769
1770	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1771		result = ISC_R_CANCELED;
1772	isc_event_free(&event);
1773	if (result == ISC_R_CANCELED ||
1774	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
1775		goto cleanup;
1776
1777	zone_load(zone, 0);
1778
1779	LOCK_ZONE(zone);
1780	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1781	UNLOCK_ZONE(zone);
1782
1783	/* Inform the zone table we've finished loading */
1784	if (asl->loaded != NULL)
1785		(asl->loaded)(asl->loaded_arg, zone, task);
1786
1787 cleanup:
1788	isc_mem_put(zone->mctx, asl, sizeof (*asl));
1789	dns_zone_idetach(&zone);
1790}
1791
1792isc_result_t
1793dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
1794	isc_event_t *e;
1795	dns_asyncload_t *asl = NULL;
1796	isc_result_t result = ISC_R_SUCCESS;
1797
1798	REQUIRE(DNS_ZONE_VALID(zone));
1799
1800	if (zone->zmgr == NULL)
1801		return (ISC_R_FAILURE);
1802
1803	asl = isc_mem_get(zone->mctx, sizeof (*asl));
1804	if (asl == NULL)
1805		CHECK(ISC_R_NOMEMORY);
1806
1807	asl->zone = NULL;
1808	asl->loaded = done;
1809	asl->loaded_arg = arg;
1810
1811	e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
1812			       DNS_EVENT_ZONELOAD,
1813			       zone_asyncload, asl,
1814			       sizeof(isc_event_t));
1815	if (e == NULL)
1816		CHECK(ISC_R_NOMEMORY);
1817
1818	LOCK_ZONE(zone);
1819	zone_iattach(zone, &asl->zone);
1820	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1821	isc_task_send(zone->loadtask, &e);
1822	UNLOCK_ZONE(zone);
1823
1824	return (ISC_R_SUCCESS);
1825
1826  failure:
1827	if (asl != NULL)
1828		isc_mem_put(zone->mctx, asl, sizeof (*asl));
1829	return (result);
1830}
1831
1832isc_boolean_t
1833dns__zone_loadpending(dns_zone_t *zone) {
1834	REQUIRE(DNS_ZONE_VALID(zone));
1835
1836	return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)));
1837}
1838
1839isc_result_t
1840dns_zone_loadandthaw(dns_zone_t *zone) {
1841	isc_result_t result;
1842
1843	if (inline_raw(zone))
1844		result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW);
1845	else
1846		result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1847
1848	switch (result) {
1849	case DNS_R_CONTINUE:
1850		/* Deferred thaw. */
1851		break;
1852	case DNS_R_UPTODATE:
1853	case ISC_R_SUCCESS:
1854	case DNS_R_SEENINCLUDE:
1855		zone->update_disabled = ISC_FALSE;
1856		break;
1857	case DNS_R_NOMASTERFILE:
1858		zone->update_disabled = ISC_FALSE;
1859		break;
1860	default:
1861		/* Error, remain in disabled state. */
1862		break;
1863	}
1864	return (result);
1865}
1866
1867static unsigned int
1868get_master_options(dns_zone_t *zone) {
1869	unsigned int options;
1870
1871	options = DNS_MASTER_ZONE;
1872	if (zone->type == dns_zone_slave ||
1873	    (zone->type == dns_zone_redirect && zone->masters == NULL))
1874		options |= DNS_MASTER_SLAVE;
1875	if (zone->type == dns_zone_key)
1876		options |= DNS_MASTER_KEY;
1877	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1878		options |= DNS_MASTER_CHECKNS;
1879	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1880		options |= DNS_MASTER_FATALNS;
1881	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1882		options |= DNS_MASTER_CHECKNAMES;
1883	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1884		options |= DNS_MASTER_CHECKNAMESFAIL;
1885	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1886		options |= DNS_MASTER_CHECKMX;
1887	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1888		options |= DNS_MASTER_CHECKMXFAIL;
1889	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1890		options |= DNS_MASTER_CHECKWILDCARD;
1891	if (inline_secure(zone) || (zone->type == dns_zone_master &&
1892	    ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1893	      zone->ssutable != NULL)))
1894		options |= DNS_MASTER_RESIGN;
1895	return (options);
1896}
1897
1898static void
1899zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1900	dns_load_t *load = event->ev_arg;
1901	isc_result_t result = ISC_R_SUCCESS;
1902	unsigned int options;
1903
1904	REQUIRE(DNS_LOAD_VALID(load));
1905
1906	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1907		result = ISC_R_CANCELED;
1908	isc_event_free(&event);
1909	if (result == ISC_R_CANCELED)
1910		goto fail;
1911
1912	options = get_master_options(load->zone);
1913
1914	result = dns_master_loadfileinc3(load->zone->masterfile,
1915					 dns_db_origin(load->db),
1916					 dns_db_origin(load->db),
1917					 load->zone->rdclass, options, 0,
1918					 &load->callbacks, task,
1919					 zone_loaddone, load,
1920					 &load->zone->lctx, load->zone->mctx,
1921					 load->zone->masterformat);
1922	if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1923	    result != DNS_R_SEENINCLUDE)
1924		goto fail;
1925	return;
1926
1927 fail:
1928	zone_loaddone(load, result);
1929}
1930
1931static void
1932get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
1933	isc_result_t result;
1934	unsigned int soacount;
1935
1936	LOCK(&raw->lock);
1937	if (raw->db != NULL) {
1938		result = zone_get_from_db(raw, raw->db, NULL, &soacount,
1939					  &rawdata->sourceserial,
1940					  NULL, NULL, NULL, NULL,
1941					  NULL);
1942		if (result == ISC_R_SUCCESS && soacount > 0U)
1943			rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
1944	}
1945	UNLOCK(&raw->lock);
1946}
1947
1948static void
1949zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1950	const char me[] = "zone_gotwritehandle";
1951	dns_zone_t *zone = event->ev_arg;
1952	isc_result_t result = ISC_R_SUCCESS;
1953	dns_dbversion_t *version = NULL;
1954	dns_masterrawheader_t rawdata;
1955
1956	REQUIRE(DNS_ZONE_VALID(zone));
1957	INSIST(task == zone->task);
1958	ENTER;
1959
1960	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1961		result = ISC_R_CANCELED;
1962	isc_event_free(&event);
1963	if (result == ISC_R_CANCELED)
1964		goto fail;
1965
1966	LOCK_ZONE(zone);
1967	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1968	if (zone->db != NULL) {
1969		const dns_master_style_t *output_style;
1970
1971		dns_db_currentversion(zone->db, &version);
1972		dns_master_initrawheader(&rawdata);
1973		if (inline_secure(zone))
1974			get_raw_serial(zone->raw, &rawdata);
1975		if (zone->type == dns_zone_key)
1976			output_style = &dns_master_style_keyzone;
1977		else
1978			output_style = &dns_master_style_default;
1979		result = dns_master_dumpinc3(zone->mctx, zone->db, version,
1980					     output_style, zone->masterfile,
1981					     zone->task, dump_done, zone,						     &zone->dctx, zone->masterformat,
1982					     &rawdata);
1983		dns_db_closeversion(zone->db, &version, ISC_FALSE);
1984	} else
1985		result = ISC_R_CANCELED;
1986	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1987	UNLOCK_ZONE(zone);
1988	if (result != DNS_R_CONTINUE)
1989		goto fail;
1990	return;
1991
1992 fail:
1993	dump_done(zone, result);
1994}
1995
1996/*
1997 * Save the raw serial number for inline-signing zones.
1998 * (XXX: Other information from the header will be used
1999 * for other purposes in the future, but for now this is
2000 * all we're interested in.)
2001 */
2002static void
2003zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2004	if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
2005		return;
2006
2007	zone->sourceserial = header->sourceserial;
2008	zone->sourceserialset = ISC_TRUE;
2009}
2010
2011void
2012dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2013	if (zone == NULL)
2014		return;
2015
2016	LOCK_ZONE(zone);
2017	zone_setrawdata(zone, header);
2018	UNLOCK_ZONE(zone);
2019}
2020
2021static isc_result_t
2022zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2023	dns_load_t *load;
2024	isc_result_t result;
2025	isc_result_t tresult;
2026	unsigned int options;
2027
2028	result = dns_zone_rpz_enable_db(zone, db);
2029	if (result != ISC_R_SUCCESS)
2030		return (result);
2031	options = get_master_options(zone);
2032	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
2033		options |= DNS_MASTER_MANYERRORS;
2034
2035	if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2036		load = isc_mem_get(zone->mctx, sizeof(*load));
2037		if (load == NULL)
2038			return (ISC_R_NOMEMORY);
2039
2040		load->mctx = NULL;
2041		load->zone = NULL;
2042		load->db = NULL;
2043		load->loadtime = loadtime;
2044		load->magic = LOAD_MAGIC;
2045
2046		isc_mem_attach(zone->mctx, &load->mctx);
2047		zone_iattach(zone, &load->zone);
2048		dns_db_attach(db, &load->db);
2049		dns_rdatacallbacks_init(&load->callbacks);
2050		load->callbacks.rawdata = zone_setrawdata;
2051		zone_iattach(zone, &load->callbacks.zone);
2052		result = dns_db_beginload(db, &load->callbacks.add,
2053					  &load->callbacks.add_private);
2054		if (result != ISC_R_SUCCESS)
2055			goto cleanup;
2056		result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask,
2057				       zone_gotreadhandle, load,
2058				       &zone->readio);
2059		if (result != ISC_R_SUCCESS) {
2060			/*
2061			 * We can't report multiple errors so ignore
2062			 * the result of dns_db_endload().
2063			 */
2064			(void)dns_db_endload(load->db,
2065					     &load->callbacks.add_private);
2066			goto cleanup;
2067		} else
2068			result = DNS_R_CONTINUE;
2069	} else {
2070		dns_rdatacallbacks_t callbacks;
2071
2072		dns_rdatacallbacks_init(&callbacks);
2073		callbacks.rawdata = zone_setrawdata;
2074		zone_iattach(zone, &callbacks.zone);
2075		result = dns_db_beginload(db, &callbacks.add,
2076					  &callbacks.add_private);
2077		if (result != ISC_R_SUCCESS) {
2078			zone_idetach(&callbacks.zone);
2079			return (result);
2080		}
2081		result = dns_master_loadfile3(zone->masterfile,
2082					      &zone->origin, &zone->origin,
2083					      zone->rdclass, options, 0,
2084					      &callbacks, zone->mctx,
2085					      zone->masterformat);
2086		tresult = dns_db_endload(db, &callbacks.add_private);
2087		if (result == ISC_R_SUCCESS)
2088			result = tresult;
2089		zone_idetach(&callbacks.zone);
2090	}
2091
2092	return (result);
2093
2094 cleanup:
2095	load->magic = 0;
2096	dns_db_detach(&load->db);
2097	zone_idetach(&load->zone);
2098	zone_idetach(&load->callbacks.zone);
2099	isc_mem_detach(&load->mctx);
2100	isc_mem_put(zone->mctx, load, sizeof(*load));
2101	return (result);
2102}
2103
2104static isc_boolean_t
2105zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2106	      dns_name_t *owner)
2107{
2108	isc_result_t result;
2109	char ownerbuf[DNS_NAME_FORMATSIZE];
2110	char namebuf[DNS_NAME_FORMATSIZE];
2111	char altbuf[DNS_NAME_FORMATSIZE];
2112	dns_fixedname_t fixed;
2113	dns_name_t *foundname;
2114	int level;
2115
2116	/*
2117	 * "." means the services does not exist.
2118	 */
2119	if (dns_name_equal(name, dns_rootname))
2120		return (ISC_TRUE);
2121
2122	/*
2123	 * Outside of zone.
2124	 */
2125	if (!dns_name_issubdomain(name, &zone->origin)) {
2126		if (zone->checkmx != NULL)
2127			return ((zone->checkmx)(zone, name, owner));
2128		return (ISC_TRUE);
2129	}
2130
2131	if (zone->type == dns_zone_master)
2132		level = ISC_LOG_ERROR;
2133	else
2134		level = ISC_LOG_WARNING;
2135
2136	dns_fixedname_init(&fixed);
2137	foundname = dns_fixedname_name(&fixed);
2138
2139	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2140			     0, 0, NULL, foundname, NULL, NULL);
2141	if (result == ISC_R_SUCCESS)
2142		return (ISC_TRUE);
2143
2144	if (result == DNS_R_NXRRSET) {
2145		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2146				     0, 0, NULL, foundname, NULL, NULL);
2147		if (result == ISC_R_SUCCESS)
2148			return (ISC_TRUE);
2149	}
2150
2151	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2152	dns_name_format(name, namebuf, sizeof namebuf);
2153	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2154	    result == DNS_R_EMPTYNAME) {
2155		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2156			level = ISC_LOG_WARNING;
2157		dns_zone_log(zone, level,
2158			     "%s/MX '%s' has no address records (A or AAAA)",
2159			     ownerbuf, namebuf);
2160		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2161	}
2162
2163	if (result == DNS_R_CNAME) {
2164		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2165		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2166			level = ISC_LOG_WARNING;
2167		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2168			dns_zone_log(zone, level,
2169				     "%s/MX '%s' is a CNAME (illegal)",
2170				     ownerbuf, namebuf);
2171		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2172	}
2173
2174	if (result == DNS_R_DNAME) {
2175		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2176		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2177			level = ISC_LOG_WARNING;
2178		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2179			dns_name_format(foundname, altbuf, sizeof altbuf);
2180			dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2181				     " '%s' (illegal)", ownerbuf, namebuf,
2182				     altbuf);
2183		}
2184		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2185	}
2186
2187	if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2188		return ((zone->checkmx)(zone, name, owner));
2189
2190	return (ISC_TRUE);
2191}
2192
2193static isc_boolean_t
2194zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2195	       dns_name_t *owner)
2196{
2197	isc_result_t result;
2198	char ownerbuf[DNS_NAME_FORMATSIZE];
2199	char namebuf[DNS_NAME_FORMATSIZE];
2200	char altbuf[DNS_NAME_FORMATSIZE];
2201	dns_fixedname_t fixed;
2202	dns_name_t *foundname;
2203	int level;
2204
2205	/*
2206	 * "." means the services does not exist.
2207	 */
2208	if (dns_name_equal(name, dns_rootname))
2209		return (ISC_TRUE);
2210
2211	/*
2212	 * Outside of zone.
2213	 */
2214	if (!dns_name_issubdomain(name, &zone->origin)) {
2215		if (zone->checksrv != NULL)
2216			return ((zone->checksrv)(zone, name, owner));
2217		return (ISC_TRUE);
2218	}
2219
2220	if (zone->type == dns_zone_master)
2221		level = ISC_LOG_ERROR;
2222	else
2223		level = ISC_LOG_WARNING;
2224
2225	dns_fixedname_init(&fixed);
2226	foundname = dns_fixedname_name(&fixed);
2227
2228	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2229			     0, 0, NULL, foundname, NULL, NULL);
2230	if (result == ISC_R_SUCCESS)
2231		return (ISC_TRUE);
2232
2233	if (result == DNS_R_NXRRSET) {
2234		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2235				     0, 0, NULL, foundname, NULL, NULL);
2236		if (result == ISC_R_SUCCESS)
2237			return (ISC_TRUE);
2238	}
2239
2240	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2241	dns_name_format(name, namebuf, sizeof namebuf);
2242	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2243	    result == DNS_R_EMPTYNAME) {
2244		dns_zone_log(zone, level,
2245			     "%s/SRV '%s' has no address records (A or AAAA)",
2246			     ownerbuf, namebuf);
2247		/* XXX950 make fatal for 9.5.0. */
2248		return (ISC_TRUE);
2249	}
2250
2251	if (result == DNS_R_CNAME) {
2252		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2253		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2254			level = ISC_LOG_WARNING;
2255		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2256			dns_zone_log(zone, level,
2257				     "%s/SRV '%s' is a CNAME (illegal)",
2258				     ownerbuf, namebuf);
2259		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2260	}
2261
2262	if (result == DNS_R_DNAME) {
2263		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2264		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2265			level = ISC_LOG_WARNING;
2266		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2267			dns_name_format(foundname, altbuf, sizeof altbuf);
2268			dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2269				     "DNAME '%s' (illegal)", ownerbuf, namebuf,
2270				     altbuf);
2271		}
2272		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2273	}
2274
2275	if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2276		return ((zone->checksrv)(zone, name, owner));
2277
2278	return (ISC_TRUE);
2279}
2280
2281static isc_boolean_t
2282zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2283		dns_name_t *owner)
2284{
2285	isc_boolean_t answer = ISC_TRUE;
2286	isc_result_t result, tresult;
2287	char ownerbuf[DNS_NAME_FORMATSIZE];
2288	char namebuf[DNS_NAME_FORMATSIZE];
2289	char altbuf[DNS_NAME_FORMATSIZE];
2290	dns_fixedname_t fixed;
2291	dns_name_t *foundname;
2292	dns_rdataset_t a;
2293	dns_rdataset_t aaaa;
2294	int level;
2295
2296	/*
2297	 * Outside of zone.
2298	 */
2299	if (!dns_name_issubdomain(name, &zone->origin)) {
2300		if (zone->checkns != NULL)
2301			return ((zone->checkns)(zone, name, owner, NULL, NULL));
2302		return (ISC_TRUE);
2303	}
2304
2305	if (zone->type == dns_zone_master)
2306		level = ISC_LOG_ERROR;
2307	else
2308		level = ISC_LOG_WARNING;
2309
2310	dns_fixedname_init(&fixed);
2311	foundname = dns_fixedname_name(&fixed);
2312	dns_rdataset_init(&a);
2313	dns_rdataset_init(&aaaa);
2314
2315	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2316			     DNS_DBFIND_GLUEOK, 0, NULL,
2317			     foundname, &a, NULL);
2318
2319	if (result == ISC_R_SUCCESS) {
2320		dns_rdataset_disassociate(&a);
2321		return (ISC_TRUE);
2322	} else if (result == DNS_R_DELEGATION)
2323		dns_rdataset_disassociate(&a);
2324
2325	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2326	    result == DNS_R_GLUE) {
2327		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2328				     DNS_DBFIND_GLUEOK, 0, NULL,
2329				     foundname, &aaaa, NULL);
2330		if (tresult == ISC_R_SUCCESS) {
2331			dns_rdataset_disassociate(&aaaa);
2332			return (ISC_TRUE);
2333		}
2334		if (tresult == DNS_R_DELEGATION)
2335			dns_rdataset_disassociate(&aaaa);
2336		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2337			/*
2338			 * Check glue against child zone.
2339			 */
2340			if (zone->checkns != NULL)
2341				answer = (zone->checkns)(zone, name, owner,
2342							 &a, &aaaa);
2343			if (dns_rdataset_isassociated(&a))
2344				dns_rdataset_disassociate(&a);
2345			if (dns_rdataset_isassociated(&aaaa))
2346				dns_rdataset_disassociate(&aaaa);
2347			return (answer);
2348		}
2349	}
2350
2351	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2352	dns_name_format(name, namebuf, sizeof namebuf);
2353	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2354	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2355		const char *what;
2356		isc_boolean_t required = ISC_FALSE;
2357		if (dns_name_issubdomain(name, owner)) {
2358			what = "REQUIRED GLUE ";
2359			required = ISC_TRUE;
2360		 } else if (result == DNS_R_DELEGATION)
2361			what = "SIBLING GLUE ";
2362		else
2363			what = "";
2364
2365		if (result != DNS_R_DELEGATION || required ||
2366		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2367			dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2368				     "address records (A or AAAA)",
2369				     ownerbuf, namebuf, what);
2370			/*
2371			 * Log missing address record.
2372			 */
2373			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2374				(void)(zone->checkns)(zone, name, owner,
2375						      &a, &aaaa);
2376			/* XXX950 make fatal for 9.5.0. */
2377			/* answer = ISC_FALSE; */
2378		}
2379	} else if (result == DNS_R_CNAME) {
2380		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2381			     ownerbuf, namebuf);
2382		/* XXX950 make fatal for 9.5.0. */
2383		/* answer = ISC_FALSE; */
2384	} else if (result == DNS_R_DNAME) {
2385		dns_name_format(foundname, altbuf, sizeof altbuf);
2386		dns_zone_log(zone, level,
2387			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
2388			     ownerbuf, namebuf, altbuf);
2389		/* XXX950 make fatal for 9.5.0. */
2390		/* answer = ISC_FALSE; */
2391	}
2392
2393	if (dns_rdataset_isassociated(&a))
2394		dns_rdataset_disassociate(&a);
2395	if (dns_rdataset_isassociated(&aaaa))
2396		dns_rdataset_disassociate(&aaaa);
2397	return (answer);
2398}
2399
2400static isc_boolean_t
2401zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2402		     dns_rdataset_t *rdataset)
2403{
2404	dns_rdataset_t tmprdataset;
2405	isc_result_t result;
2406	isc_boolean_t answer = ISC_TRUE;
2407	isc_boolean_t format = ISC_TRUE;
2408	int level = ISC_LOG_WARNING;
2409	char ownerbuf[DNS_NAME_FORMATSIZE];
2410	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2411	unsigned int count1 = 0;
2412
2413	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2414		level = ISC_LOG_ERROR;
2415
2416	dns_rdataset_init(&tmprdataset);
2417	for (result = dns_rdataset_first(rdataset);
2418	     result == ISC_R_SUCCESS;
2419	     result = dns_rdataset_next(rdataset)) {
2420		dns_rdata_t rdata1 = DNS_RDATA_INIT;
2421		unsigned int count2 = 0;
2422
2423		count1++;
2424		dns_rdataset_current(rdataset, &rdata1);
2425		dns_rdataset_clone(rdataset, &tmprdataset);
2426		for (result = dns_rdataset_first(&tmprdataset);
2427		     result == ISC_R_SUCCESS;
2428		     result = dns_rdataset_next(&tmprdataset)) {
2429			dns_rdata_t rdata2 = DNS_RDATA_INIT;
2430			count2++;
2431			if (count1 >= count2)
2432				continue;
2433			dns_rdataset_current(&tmprdataset, &rdata2);
2434			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2435				if (format) {
2436					dns_name_format(owner, ownerbuf,
2437							sizeof ownerbuf);
2438					dns_rdatatype_format(rdata1.type,
2439							     typebuf,
2440							     sizeof(typebuf));
2441					format = ISC_FALSE;
2442				}
2443				dns_zone_log(zone, level, "%s/%s has "
2444					     "semantically identical records",
2445					     ownerbuf, typebuf);
2446				if (level == ISC_LOG_ERROR)
2447					answer = ISC_FALSE;
2448				break;
2449			}
2450		}
2451		dns_rdataset_disassociate(&tmprdataset);
2452		if (!format)
2453			break;
2454	}
2455	return (answer);
2456}
2457
2458static isc_boolean_t
2459zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2460	dns_dbiterator_t *dbiterator = NULL;
2461	dns_dbnode_t *node = NULL;
2462	dns_fixedname_t fixed;
2463	dns_name_t *name;
2464	dns_rdataset_t rdataset;
2465	dns_rdatasetiter_t *rdsit = NULL;
2466	isc_boolean_t ok = ISC_TRUE;
2467	isc_result_t result;
2468
2469	dns_fixedname_init(&fixed);
2470	name = dns_fixedname_name(&fixed);
2471	dns_rdataset_init(&rdataset);
2472
2473	result = dns_db_createiterator(db, 0, &dbiterator);
2474	if (result != ISC_R_SUCCESS)
2475		return (ISC_TRUE);
2476
2477	for (result = dns_dbiterator_first(dbiterator);
2478	     result == ISC_R_SUCCESS;
2479	     result = dns_dbiterator_next(dbiterator)) {
2480		result = dns_dbiterator_current(dbiterator, &node, name);
2481		if (result != ISC_R_SUCCESS)
2482			continue;
2483
2484		result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2485		if (result != ISC_R_SUCCESS)
2486			continue;
2487
2488		for (result = dns_rdatasetiter_first(rdsit);
2489		     result == ISC_R_SUCCESS;
2490		     result = dns_rdatasetiter_next(rdsit)) {
2491			dns_rdatasetiter_current(rdsit, &rdataset);
2492			if (!zone_rrset_check_dup(zone, name, &rdataset))
2493				ok = ISC_FALSE;
2494			dns_rdataset_disassociate(&rdataset);
2495		}
2496		dns_rdatasetiter_destroy(&rdsit);
2497		dns_db_detachnode(db, &node);
2498	}
2499
2500	if (node != NULL)
2501		dns_db_detachnode(db, &node);
2502	dns_dbiterator_destroy(&dbiterator);
2503
2504	return (ok);
2505}
2506
2507static isc_boolean_t
2508isspf(const dns_rdata_t *rdata) {
2509	char buf[1024];
2510	const unsigned char *data = rdata->data;
2511	unsigned int rdl = rdata->length, i = 0, tl, len;
2512
2513	while (rdl > 0U) {
2514		len = tl = *data;
2515		++data;
2516		--rdl;
2517		INSIST(tl <= rdl);
2518		if (len > sizeof(buf) - i - 1)
2519			len = sizeof(buf) - i - 1;
2520		memmove(buf + i, data, len);
2521		i += len;
2522		data += tl;
2523		rdl -= tl;
2524	}
2525
2526	if (i < 6U)
2527		return(ISC_FALSE);
2528
2529	buf[i] = 0;
2530	if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
2531		return (ISC_TRUE);
2532	return (ISC_FALSE);
2533}
2534
2535static isc_boolean_t
2536integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2537	dns_dbiterator_t *dbiterator = NULL;
2538	dns_dbnode_t *node = NULL;
2539	dns_rdataset_t rdataset;
2540	dns_fixedname_t fixed;
2541	dns_fixedname_t fixedbottom;
2542	dns_rdata_mx_t mx;
2543	dns_rdata_ns_t ns;
2544	dns_rdata_in_srv_t srv;
2545	dns_rdata_t rdata;
2546	dns_name_t *name;
2547	dns_name_t *bottom;
2548	isc_result_t result;
2549	isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
2550
2551	dns_fixedname_init(&fixed);
2552	name = dns_fixedname_name(&fixed);
2553	dns_fixedname_init(&fixedbottom);
2554	bottom = dns_fixedname_name(&fixedbottom);
2555	dns_rdataset_init(&rdataset);
2556	dns_rdata_init(&rdata);
2557
2558	result = dns_db_createiterator(db, 0, &dbiterator);
2559	if (result != ISC_R_SUCCESS)
2560		return (ISC_TRUE);
2561
2562	result = dns_dbiterator_first(dbiterator);
2563	while (result == ISC_R_SUCCESS) {
2564		result = dns_dbiterator_current(dbiterator, &node, name);
2565		if (result != ISC_R_SUCCESS)
2566			goto cleanup;
2567
2568		/*
2569		 * Is this name visible in the zone?
2570		 */
2571		if (!dns_name_issubdomain(name, &zone->origin) ||
2572		    (dns_name_countlabels(bottom) > 0 &&
2573		     dns_name_issubdomain(name, bottom)))
2574			goto next;
2575
2576		/*
2577		 * Don't check the NS records at the origin.
2578		 */
2579		if (dns_name_equal(name, &zone->origin))
2580			goto checkmx;
2581
2582		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2583					     0, 0, &rdataset, NULL);
2584		if (result != ISC_R_SUCCESS)
2585			goto checkmx;
2586		/*
2587		 * Remember bottom of zone.
2588		 */
2589		dns_name_copy(name, bottom, NULL);
2590
2591		result = dns_rdataset_first(&rdataset);
2592		while (result == ISC_R_SUCCESS) {
2593			dns_rdataset_current(&rdataset, &rdata);
2594			result = dns_rdata_tostruct(&rdata, &ns, NULL);
2595			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2596			if (!zone_check_glue(zone, db, &ns.name, name))
2597				ok = ISC_FALSE;
2598			dns_rdata_reset(&rdata);
2599			result = dns_rdataset_next(&rdataset);
2600		}
2601		dns_rdataset_disassociate(&rdataset);
2602		goto next;
2603
2604 checkmx:
2605		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2606					     0, 0, &rdataset, NULL);
2607		if (result != ISC_R_SUCCESS)
2608			goto checksrv;
2609		result = dns_rdataset_first(&rdataset);
2610		while (result == ISC_R_SUCCESS) {
2611			dns_rdataset_current(&rdataset, &rdata);
2612			result = dns_rdata_tostruct(&rdata, &mx, NULL);
2613			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2614			if (!zone_check_mx(zone, db, &mx.mx, name))
2615				ok = ISC_FALSE;
2616			dns_rdata_reset(&rdata);
2617			result = dns_rdataset_next(&rdataset);
2618		}
2619		dns_rdataset_disassociate(&rdataset);
2620
2621 checksrv:
2622		if (zone->rdclass != dns_rdataclass_in)
2623			goto next;
2624		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2625					     0, 0, &rdataset, NULL);
2626		if (result != ISC_R_SUCCESS)
2627			goto checkspf;
2628		result = dns_rdataset_first(&rdataset);
2629		while (result == ISC_R_SUCCESS) {
2630			dns_rdataset_current(&rdataset, &rdata);
2631			result = dns_rdata_tostruct(&rdata, &srv, NULL);
2632			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2633			if (!zone_check_srv(zone, db, &srv.target, name))
2634				ok = ISC_FALSE;
2635			dns_rdata_reset(&rdata);
2636			result = dns_rdataset_next(&rdataset);
2637		}
2638		dns_rdataset_disassociate(&rdataset);
2639
2640 checkspf:
2641		/*
2642		 * Check if there is a type TXT spf record without a type SPF
2643		 * RRset being present.
2644		 */
2645		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
2646			goto next;
2647		if (zone->rdclass != dns_rdataclass_in)
2648			goto next;
2649		have_spf = have_txt = ISC_FALSE;
2650		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
2651					     0, 0, &rdataset, NULL);
2652		if (result == ISC_R_SUCCESS) {
2653			dns_rdataset_disassociate(&rdataset);
2654			have_spf = ISC_TRUE;
2655		}
2656		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
2657					     0, 0, &rdataset, NULL);
2658		if (result != ISC_R_SUCCESS)
2659			goto notxt;
2660		result = dns_rdataset_first(&rdataset);
2661		while (result == ISC_R_SUCCESS) {
2662			dns_rdataset_current(&rdataset, &rdata);
2663			have_txt = isspf(&rdata);
2664			dns_rdata_reset(&rdata);
2665			if (have_txt)
2666				break;
2667			result = dns_rdataset_next(&rdataset);
2668		}
2669		dns_rdataset_disassociate(&rdataset);
2670
2671 notxt:
2672		if (have_spf != have_txt) {
2673			char namebuf[DNS_NAME_FORMATSIZE];
2674			const char *found = have_txt ? "TXT" : "SPF";
2675			const char *need = have_txt ? "SPF" : "TXT";
2676
2677			dns_name_format(name, namebuf, sizeof(namebuf));
2678			dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found SPF/%s "
2679				     "record but no SPF/%s record found, add "
2680				     "matching type %s record", namebuf, found,
2681				     need, need);
2682		}
2683
2684 next:
2685		dns_db_detachnode(db, &node);
2686		result = dns_dbiterator_next(dbiterator);
2687	}
2688
2689 cleanup:
2690	if (node != NULL)
2691		dns_db_detachnode(db, &node);
2692	dns_dbiterator_destroy(&dbiterator);
2693
2694	return (ok);
2695}
2696
2697/*
2698 * OpenSSL verification of RSA keys with exponent 3 is known to be
2699 * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
2700 * if they are in use.
2701 */
2702static void
2703zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2704	dns_dbnode_t *node = NULL;
2705	dns_dbversion_t *version = NULL;
2706	dns_rdata_dnskey_t dnskey;
2707	dns_rdata_t rdata = DNS_RDATA_INIT;
2708	dns_rdataset_t rdataset;
2709	isc_result_t result;
2710	isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2711	const char *algorithm;
2712
2713	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2714	if (result != ISC_R_SUCCESS)
2715		goto cleanup;
2716
2717	dns_db_currentversion(db, &version);
2718	dns_rdataset_init(&rdataset);
2719	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2720				     dns_rdatatype_none, 0, &rdataset, NULL);
2721	if (result != ISC_R_SUCCESS)
2722		goto cleanup;
2723
2724	for (result = dns_rdataset_first(&rdataset);
2725	     result == ISC_R_SUCCESS;
2726	     result = dns_rdataset_next(&rdataset))
2727	{
2728		dns_rdataset_current(&rdataset, &rdata);
2729		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2730		INSIST(result == ISC_R_SUCCESS);
2731
2732		if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2733		     dnskey.algorithm == DST_ALG_RSAMD5) &&
2734		     dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2735		     dnskey.data[1] == 3)
2736		{
2737			if (dnskey.algorithm == DST_ALG_RSASHA1) {
2738				logit = !foundrsa;
2739				foundrsa = ISC_TRUE;
2740				algorithm = "RSASHA1";
2741			} else {
2742				logit = !foundmd5;
2743				foundmd5 = ISC_TRUE;
2744				algorithm = "RSAMD5";
2745			}
2746			if (logit)
2747				dns_zone_log(zone, ISC_LOG_WARNING,
2748					     "weak %s (%u) key found "
2749					     "(exponent=3)", algorithm,
2750					     dnskey.algorithm);
2751			if (foundrsa && foundmd5)
2752				break;
2753		}
2754		dns_rdata_reset(&rdata);
2755	}
2756	dns_rdataset_disassociate(&rdataset);
2757
2758 cleanup:
2759	if (node != NULL)
2760		dns_db_detachnode(db, &node);
2761	if (version != NULL)
2762		dns_db_closeversion(db, &version, ISC_FALSE);
2763}
2764
2765static void
2766resume_signingwithkey(dns_zone_t *zone) {
2767	dns_dbnode_t *node = NULL;
2768	dns_dbversion_t *version = NULL;
2769	dns_rdata_t rdata = DNS_RDATA_INIT;
2770	dns_rdataset_t rdataset;
2771	isc_result_t result;
2772	dns_db_t *db = NULL;
2773
2774	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2775	if (zone->db != NULL)
2776		dns_db_attach(zone->db, &db);
2777	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2778	if (db == NULL)
2779		goto cleanup;
2780
2781	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2782	if (result != ISC_R_SUCCESS)
2783		goto cleanup;
2784
2785	dns_db_currentversion(db, &version);
2786	dns_rdataset_init(&rdataset);
2787	result = dns_db_findrdataset(db, node, version,
2788				     zone->privatetype,
2789				     dns_rdatatype_none, 0,
2790				     &rdataset, NULL);
2791	if (result != ISC_R_SUCCESS) {
2792		INSIST(!dns_rdataset_isassociated(&rdataset));
2793		goto cleanup;
2794	}
2795
2796	for (result = dns_rdataset_first(&rdataset);
2797	     result == ISC_R_SUCCESS;
2798	     result = dns_rdataset_next(&rdataset))
2799	{
2800		dns_rdataset_current(&rdataset, &rdata);
2801		if (rdata.length != 5 ||
2802		    rdata.data[0] == 0 || rdata.data[4] != 0) {
2803			dns_rdata_reset(&rdata);
2804			continue;
2805		}
2806
2807		result = zone_signwithkey(zone, rdata.data[0],
2808					  (rdata.data[1] << 8) | rdata.data[2],
2809					  ISC_TF(rdata.data[3]));
2810		if (result != ISC_R_SUCCESS) {
2811			dns_zone_log(zone, ISC_LOG_ERROR,
2812				     "zone_signwithkey failed: %s",
2813				     dns_result_totext(result));
2814		}
2815		dns_rdata_reset(&rdata);
2816	}
2817	dns_rdataset_disassociate(&rdataset);
2818
2819 cleanup:
2820	if (db != NULL) {
2821		if (node != NULL)
2822			dns_db_detachnode(db, &node);
2823		if (version != NULL)
2824			dns_db_closeversion(db, &version, ISC_FALSE);
2825		dns_db_detach(&db);
2826	}
2827}
2828
2829static isc_result_t
2830zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2831	dns_nsec3chain_t *nsec3chain, *current;
2832	dns_dbversion_t *version = NULL;
2833	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
2834	isc_result_t result;
2835	isc_time_t now;
2836	unsigned int options = 0;
2837	char saltbuf[255*2+1];
2838	char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
2839	dns_db_t *db = NULL;
2840	int i;
2841
2842	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2843	if (zone->db != NULL)
2844		dns_db_attach(zone->db, &db);
2845	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2846
2847	if (db == NULL) {
2848		result = ISC_R_SUCCESS;
2849		goto cleanup;
2850	}
2851
2852	dns_db_currentversion(db, &version);
2853	result = dns_nsec_nseconly(db, version, &nseconly);
2854	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
2855	dns_db_closeversion(db, &version, ISC_FALSE);
2856	if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
2857		result = ISC_R_SUCCESS;
2858		goto cleanup;
2859	}
2860
2861	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2862	if (nsec3chain == NULL) {
2863		result = ISC_R_NOMEMORY;
2864		goto cleanup;
2865	}
2866
2867	nsec3chain->magic = 0;
2868	nsec3chain->done = ISC_FALSE;
2869	nsec3chain->db = NULL;
2870	nsec3chain->dbiterator = NULL;
2871	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2872	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2873	nsec3chain->nsec3param.hash = nsec3param->hash;
2874	nsec3chain->nsec3param.iterations = nsec3param->iterations;
2875	nsec3chain->nsec3param.flags = nsec3param->flags;
2876	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2877	memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2878	nsec3chain->nsec3param.salt = nsec3chain->salt;
2879	nsec3chain->seen_nsec = ISC_FALSE;
2880	nsec3chain->delete_nsec = ISC_FALSE;
2881	nsec3chain->save_delete_nsec = ISC_FALSE;
2882
2883	if (nsec3param->flags == 0)
2884		strlcpy(flags, "NONE", sizeof(flags));
2885	else {
2886		flags[0] = '\0';
2887		if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2888			strlcat(flags, "REMOVE", sizeof(flags));
2889		if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) {
2890			if (flags[0] == '\0')
2891				strlcpy(flags, "INITIAL", sizeof(flags));
2892			else
2893				strlcat(flags, "|INITIAL", sizeof(flags));
2894		}
2895		if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2896			if (flags[0] == '\0')
2897				strlcpy(flags, "CREATE", sizeof(flags));
2898			else
2899				strlcat(flags, "|CREATE", sizeof(flags));
2900		}
2901		if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2902			if (flags[0] == '\0')
2903				strlcpy(flags, "NONSEC", sizeof(flags));
2904			else
2905				strlcat(flags, "|NONSEC", sizeof(flags));
2906		}
2907		if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2908			if (flags[0] == '\0')
2909				strlcpy(flags, "OPTOUT", sizeof(flags));
2910			else
2911				strlcat(flags, "|OPTOUT", sizeof(flags));
2912		}
2913	}
2914	if (nsec3param->salt_length == 0)
2915		strlcpy(saltbuf, "-", sizeof(saltbuf));
2916	else
2917		for (i = 0; i < nsec3param->salt_length; i++)
2918			sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2919	dns_zone_log(zone, ISC_LOG_INFO,
2920		     "zone_addnsec3chain(%u,%s,%u,%s)",
2921		      nsec3param->hash, flags, nsec3param->iterations,
2922		      saltbuf);
2923
2924	for (current = ISC_LIST_HEAD(zone->nsec3chain);
2925	     current != NULL;
2926	     current = ISC_LIST_NEXT(current, link)) {
2927		if (current->db == db &&
2928		    current->nsec3param.hash == nsec3param->hash &&
2929		    current->nsec3param.iterations == nsec3param->iterations &&
2930		    current->nsec3param.salt_length == nsec3param->salt_length
2931		    && !memcmp(current->nsec3param.salt, nsec3param->salt,
2932			       nsec3param->salt_length))
2933			current->done = ISC_TRUE;
2934	}
2935
2936	dns_db_attach(db, &nsec3chain->db);
2937	if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2938		options = DNS_DB_NONSEC3;
2939	result = dns_db_createiterator(nsec3chain->db, options,
2940				       &nsec3chain->dbiterator);
2941	if (result == ISC_R_SUCCESS)
2942		dns_dbiterator_first(nsec3chain->dbiterator);
2943	if (result == ISC_R_SUCCESS) {
2944		dns_dbiterator_pause(nsec3chain->dbiterator);
2945		ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2946				       nsec3chain, link);
2947		nsec3chain = NULL;
2948		if (isc_time_isepoch(&zone->nsec3chaintime)) {
2949			TIME_NOW(&now);
2950			zone->nsec3chaintime = now;
2951			if (zone->task != NULL)
2952				zone_settimer(zone, &now);
2953		}
2954	}
2955
2956	if (nsec3chain != NULL) {
2957		if (nsec3chain->db != NULL)
2958			dns_db_detach(&nsec3chain->db);
2959		if (nsec3chain->dbiterator != NULL)
2960			dns_dbiterator_destroy(&nsec3chain->dbiterator);
2961		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2962	}
2963
2964 cleanup:
2965	if (db != NULL)
2966		dns_db_detach(&db);
2967	return (result);
2968}
2969
2970static void
2971resume_addnsec3chain(dns_zone_t *zone) {
2972	dns_dbnode_t *node = NULL;
2973	dns_dbversion_t *version = NULL;
2974	dns_rdataset_t rdataset;
2975	isc_result_t result;
2976	dns_rdata_nsec3param_t nsec3param;
2977	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
2978	dns_db_t *db = NULL;
2979
2980	if (zone->privatetype == 0)
2981		return;
2982
2983	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2984	if (zone->db != NULL)
2985		dns_db_attach(zone->db, &db);
2986	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2987	if (db == NULL)
2988		goto cleanup;
2989
2990	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2991	if (result != ISC_R_SUCCESS)
2992		goto cleanup;
2993
2994	dns_db_currentversion(db, &version);
2995
2996	result = dns_nsec_nseconly(db, version, &nseconly);
2997	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
2998
2999	dns_rdataset_init(&rdataset);
3000	result = dns_db_findrdataset(db, node, version,
3001				     zone->privatetype, dns_rdatatype_none,
3002				     0, &rdataset, NULL);
3003	if (result != ISC_R_SUCCESS) {
3004		INSIST(!dns_rdataset_isassociated(&rdataset));
3005		goto cleanup;
3006	}
3007
3008	for (result = dns_rdataset_first(&rdataset);
3009	     result == ISC_R_SUCCESS;
3010	     result = dns_rdataset_next(&rdataset))
3011	{
3012		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3013		dns_rdata_t rdata = DNS_RDATA_INIT;
3014		dns_rdata_t private = DNS_RDATA_INIT;
3015
3016		dns_rdataset_current(&rdataset, &private);
3017		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3018						sizeof(buf)))
3019			continue;
3020		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3021		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3022		if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3023		    ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3024		{
3025			result = zone_addnsec3chain(zone, &nsec3param);
3026			if (result != ISC_R_SUCCESS) {
3027				dns_zone_log(zone, ISC_LOG_ERROR,
3028					     "zone_addnsec3chain failed: %s",
3029					     dns_result_totext(result));
3030			}
3031		}
3032	}
3033	dns_rdataset_disassociate(&rdataset);
3034 cleanup:
3035	if (db != NULL) {
3036		if (node != NULL)
3037			dns_db_detachnode(db, &node);
3038		if (version != NULL)
3039			dns_db_closeversion(db, &version, ISC_FALSE);
3040		dns_db_detach(&db);
3041	}
3042}
3043
3044static void
3045set_resigntime(dns_zone_t *zone) {
3046	dns_rdataset_t rdataset;
3047	dns_fixedname_t fixed;
3048	unsigned int resign;
3049	isc_result_t result;
3050	isc_uint32_t nanosecs;
3051	dns_db_t *db = NULL;
3052
3053	dns_rdataset_init(&rdataset);
3054	dns_fixedname_init(&fixed);
3055
3056	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3057	if (zone->db != NULL)
3058		dns_db_attach(zone->db, &db);
3059	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3060	if (db == NULL) {
3061		isc_time_settoepoch(&zone->resigntime);
3062		return;
3063	}
3064
3065	result = dns_db_getsigningtime(db, &rdataset,
3066				       dns_fixedname_name(&fixed));
3067	if (result != ISC_R_SUCCESS) {
3068		isc_time_settoepoch(&zone->resigntime);
3069		goto cleanup;
3070	}
3071
3072	resign = rdataset.resign - zone->sigresigninginterval;
3073	dns_rdataset_disassociate(&rdataset);
3074	isc_random_get(&nanosecs);
3075	nanosecs %= 1000000000;
3076	isc_time_set(&zone->resigntime, resign, nanosecs);
3077 cleanup:
3078	dns_db_detach(&db);
3079	return;
3080}
3081
3082static isc_result_t
3083check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3084	dns_dbnode_t *node = NULL;
3085	dns_rdataset_t rdataset;
3086	dns_dbversion_t *version = NULL;
3087	dns_rdata_nsec3param_t nsec3param;
3088	isc_boolean_t ok = ISC_FALSE;
3089	isc_result_t result;
3090	dns_rdata_t rdata = DNS_RDATA_INIT;
3091	isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
3092				dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE;
3093
3094	dns_rdataset_init(&rdataset);
3095	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3096	if (result != ISC_R_SUCCESS) {
3097		dns_zone_log(zone, ISC_LOG_ERROR,
3098			     "nsec3param lookup failure: %s",
3099			     dns_result_totext(result));
3100		return (result);
3101	}
3102	dns_db_currentversion(db, &version);
3103
3104	result = dns_db_findrdataset(db, node, version,
3105				     dns_rdatatype_nsec3param,
3106				     dns_rdatatype_none, 0, &rdataset, NULL);
3107	if (result == ISC_R_NOTFOUND) {
3108		INSIST(!dns_rdataset_isassociated(&rdataset));
3109		result = ISC_R_SUCCESS;
3110		goto cleanup;
3111	}
3112	if (result != ISC_R_SUCCESS) {
3113		INSIST(!dns_rdataset_isassociated(&rdataset));
3114		dns_zone_log(zone, ISC_LOG_ERROR,
3115			     "nsec3param lookup failure: %s",
3116			     dns_result_totext(result));
3117		goto cleanup;
3118	}
3119
3120	/*
3121	 * For dynamic zones we must support every algorithm so we can
3122	 * regenerate all the NSEC3 chains.
3123	 * For non-dynamic zones we only need to find a supported algorithm.
3124	 */
3125	for (result = dns_rdataset_first(&rdataset);
3126	     result == ISC_R_SUCCESS;
3127	     result = dns_rdataset_next(&rdataset))
3128	{
3129		dns_rdataset_current(&rdataset, &rdata);
3130		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3131		dns_rdata_reset(&rdata);
3132		INSIST(result == ISC_R_SUCCESS);
3133		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3134		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3135		{
3136			dns_zone_log(zone, ISC_LOG_WARNING,
3137			     "nsec3 test \"unknown\" hash algorithm found: %u",
3138				     nsec3param.hash);
3139			ok = ISC_TRUE;
3140		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3141			if (dynamic) {
3142				dns_zone_log(zone, ISC_LOG_ERROR,
3143					     "unsupported nsec3 hash algorithm"
3144					     " in dynamic zone: %u",
3145					     nsec3param.hash);
3146				result = DNS_R_BADZONE;
3147				/* Stop second error message. */
3148				ok = ISC_TRUE;
3149				break;
3150			} else
3151				dns_zone_log(zone, ISC_LOG_WARNING,
3152				     "unsupported nsec3 hash algorithm: %u",
3153					     nsec3param.hash);
3154		} else
3155			ok = ISC_TRUE;
3156	}
3157	if (result == ISC_R_NOMORE)
3158		result = ISC_R_SUCCESS;
3159
3160	if (!ok) {
3161		result = DNS_R_BADZONE;
3162		dns_zone_log(zone, ISC_LOG_ERROR,
3163			     "no supported nsec3 hash algorithm");
3164	}
3165
3166 cleanup:
3167	if (dns_rdataset_isassociated(&rdataset))
3168		dns_rdataset_disassociate(&rdataset);
3169	dns_db_closeversion(db, &version, ISC_FALSE);
3170	dns_db_detachnode(db, &node);
3171	return (result);
3172}
3173
3174/*
3175 * Set the timer for refreshing the key zone to the soonest future time
3176 * of the set (current timer, keydata->refresh, keydata->addhd,
3177 * keydata->removehd).
3178 */
3179static void
3180set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3181		    isc_stdtime_t now)
3182{
3183	const char me[] = "set_refreshkeytimer";
3184	isc_stdtime_t then;
3185	isc_time_t timenow, timethen;
3186	char timebuf[80];
3187
3188	ENTER;
3189	then = key->refresh;
3190	if (key->addhd > now && key->addhd < then)
3191		then = key->addhd;
3192	if (key->removehd > now && key->removehd < then)
3193		then = key->removehd;
3194
3195	TIME_NOW(&timenow);
3196	if (then > now)
3197		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
3198	else
3199		timethen = timenow;
3200	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
3201	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
3202		zone->refreshkeytime = timethen;
3203
3204	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
3205	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
3206	zone_settimer(zone, &timenow);
3207}
3208
3209/*
3210 * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3211 * If the key zone is changed, set '*changed' to ISC_TRUE.
3212 */
3213static isc_result_t
3214create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3215	       dns_diff_t *diff, dns_keytable_t *keytable,
3216	       dns_keynode_t **keynodep, isc_boolean_t *changed)
3217{
3218	const char me[] = "create_keydata";
3219	isc_result_t result = ISC_R_SUCCESS;
3220	isc_buffer_t keyb, dstb;
3221	unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3222	dns_rdata_keydata_t keydata;
3223	dns_rdata_dnskey_t dnskey;
3224	dns_rdata_t rdata = DNS_RDATA_INIT;
3225	dns_keynode_t *keynode;
3226	isc_stdtime_t now;
3227	isc_region_t r;
3228	dst_key_t *key;
3229
3230	REQUIRE(keynodep != NULL);
3231	keynode = *keynodep;
3232
3233	ENTER;
3234	isc_stdtime_get(&now);
3235
3236	/* Loop in case there's more than one key. */
3237	while (result == ISC_R_SUCCESS) {
3238		dns_keynode_t *nextnode = NULL;
3239
3240		key = dns_keynode_key(keynode);
3241		if (key == NULL)
3242			goto skip;
3243
3244		isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3245		CHECK(dst_key_todns(key, &dstb));
3246
3247		/* Convert DST key to DNSKEY. */
3248		dns_rdata_reset(&rdata);
3249		isc_buffer_usedregion(&dstb, &r);
3250		dns_rdata_fromregion(&rdata, dst_key_class(key),
3251				     dns_rdatatype_dnskey, &r);
3252
3253		/* DSTKEY to KEYDATA. */
3254		CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3255		CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3256					     NULL));
3257
3258		/* KEYDATA to rdata. */
3259		dns_rdata_reset(&rdata);
3260		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3261		CHECK(dns_rdata_fromstruct(&rdata,
3262					   zone->rdclass, dns_rdatatype_keydata,
3263					   &keydata, &keyb));
3264
3265		/* Add rdata to zone. */
3266		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3267				    dst_key_name(key), 0, &rdata));
3268		*changed = ISC_TRUE;
3269		/* Refresh new keys from the zone apex as soon as possible. */
3270		set_refreshkeytimer(zone, &keydata, now);
3271
3272 skip:
3273		result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3274		if (result != ISC_R_NOTFOUND) {
3275			dns_keytable_detachkeynode(keytable, &keynode);
3276			keynode = nextnode;
3277		}
3278	}
3279
3280	if (keynode != NULL)
3281		dns_keytable_detachkeynode(keytable, &keynode);
3282	*keynodep = NULL;
3283
3284	return (ISC_R_SUCCESS);
3285
3286  failure:
3287	return (result);
3288}
3289
3290/*
3291 * Remove from the key zone all the KEYDATA records found in rdataset.
3292 */
3293static isc_result_t
3294delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3295	       dns_name_t *name, dns_rdataset_t *rdataset)
3296{
3297	dns_rdata_t rdata = DNS_RDATA_INIT;
3298	isc_result_t result, uresult;
3299
3300	for (result = dns_rdataset_first(rdataset);
3301	     result == ISC_R_SUCCESS;
3302	     result = dns_rdataset_next(rdataset)) {
3303		dns_rdata_reset(&rdata);
3304		dns_rdataset_current(rdataset, &rdata);
3305		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3306					name, 0, &rdata);
3307		if (uresult != ISC_R_SUCCESS)
3308			return (uresult);
3309	}
3310	if (result == ISC_R_NOMORE)
3311		result = ISC_R_SUCCESS;
3312	return (result);
3313}
3314
3315/*
3316 * Compute the DNSSEC key ID for a DNSKEY record.
3317 */
3318static isc_result_t
3319compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3320	    dns_keytag_t *tag)
3321{
3322	isc_result_t result;
3323	dns_rdata_t rdata = DNS_RDATA_INIT;
3324	unsigned char data[4096];
3325	isc_buffer_t buffer;
3326	dst_key_t *dstkey = NULL;
3327
3328	isc_buffer_init(&buffer, data, sizeof(data));
3329	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3330			     dns_rdatatype_dnskey, dnskey, &buffer);
3331
3332	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3333	if (result == ISC_R_SUCCESS)
3334		*tag = dst_key_id(dstkey);
3335	dst_key_free(&dstkey);
3336
3337	return (result);
3338}
3339
3340/*
3341 * Add key to the security roots.
3342 */
3343static void
3344trust_key(dns_zone_t *zone, dns_name_t *keyname,
3345	  dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
3346	isc_result_t result;
3347	dns_rdata_t rdata = DNS_RDATA_INIT;
3348	unsigned char data[4096];
3349	isc_buffer_t buffer;
3350	dns_keytable_t *sr = NULL;
3351	dst_key_t *dstkey = NULL;
3352
3353	/* Convert dnskey to DST key. */
3354	isc_buffer_init(&buffer, data, sizeof(data));
3355	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3356			     dns_rdatatype_dnskey, dnskey, &buffer);
3357
3358	result = dns_view_getsecroots(zone->view, &sr);
3359	if (result != ISC_R_SUCCESS)
3360		goto failure;
3361
3362	CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
3363	CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
3364	dns_keytable_detach(&sr);
3365
3366  failure:
3367	if (dstkey != NULL)
3368		dst_key_free(&dstkey);
3369	if (sr != NULL)
3370		dns_keytable_detach(&sr);
3371	return;
3372}
3373
3374/*
3375 * Add a null key to the security roots for so that all queries
3376 * to the zone will fail.
3377 */
3378static void
3379fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
3380	isc_result_t result;
3381	dns_keytable_t *sr = NULL;
3382
3383	result = dns_view_getsecroots(zone->view, &sr);
3384	if (result == ISC_R_SUCCESS) {
3385		dns_keytable_marksecure(sr, keyname);
3386		dns_keytable_detach(&sr);
3387	}
3388}
3389
3390/*
3391 * Scan a set of KEYDATA records from the key zone.  The ones that are
3392 * valid (i.e., the add holddown timer has expired) become trusted keys.
3393 */
3394static void
3395load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
3396	isc_result_t result;
3397	dns_rdata_t rdata = DNS_RDATA_INIT;
3398	dns_rdata_keydata_t keydata;
3399	dns_rdata_dnskey_t dnskey;
3400	isc_mem_t *mctx = zone->mctx;
3401	int trusted = 0, revoked = 0, pending = 0;
3402	isc_stdtime_t now;
3403	dns_keytable_t *sr = NULL;
3404
3405	isc_stdtime_get(&now);
3406
3407	result = dns_view_getsecroots(zone->view, &sr);
3408	if (result == ISC_R_SUCCESS) {
3409		dns_keytable_delete(sr, name);
3410		dns_keytable_detach(&sr);
3411	}
3412
3413	/* Now insert all the accepted trust anchors from this keydata set. */
3414	for (result = dns_rdataset_first(rdataset);
3415	     result == ISC_R_SUCCESS;
3416	     result = dns_rdataset_next(rdataset)) {
3417		dns_rdata_reset(&rdata);
3418		dns_rdataset_current(rdataset, &rdata);
3419
3420		/* Convert rdata to keydata. */
3421		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
3422		if (result == ISC_R_UNEXPECTEDEND)
3423			continue;
3424		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3425
3426		/* Set the key refresh timer. */
3427		set_refreshkeytimer(zone, &keydata, now);
3428
3429		/* If the removal timer is nonzero, this key was revoked. */
3430		if (keydata.removehd != 0) {
3431			revoked++;
3432			continue;
3433		}
3434
3435		/*
3436		 * If the add timer is still pending, this key is not
3437		 * trusted yet.
3438		 */
3439		if (now < keydata.addhd) {
3440			pending++;
3441			continue;
3442		}
3443
3444		/* Convert keydata to dnskey. */
3445		dns_keydata_todnskey(&keydata, &dnskey, NULL);
3446
3447		/* Add to keytables. */
3448		trusted++;
3449		trust_key(zone, name, &dnskey, mctx);
3450	}
3451
3452	if (trusted == 0 && pending != 0) {
3453		char namebuf[DNS_NAME_FORMATSIZE];
3454		dns_name_format(name, namebuf, sizeof namebuf);
3455		dns_zone_log(zone, ISC_LOG_ERROR,
3456			     "No valid trust anchors for '%s'!", namebuf);
3457		dns_zone_log(zone, ISC_LOG_ERROR,
3458			     "%d key(s) revoked, %d still pending",
3459			     revoked, pending);
3460		dns_zone_log(zone, ISC_LOG_ERROR,
3461			     "All queries to '%s' will fail", namebuf);
3462		fail_secure(zone, name);
3463	}
3464}
3465
3466static isc_result_t
3467do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3468	     dns_diff_t *diff)
3469{
3470	dns_diff_t temp_diff;
3471	isc_result_t result;
3472
3473	/*
3474	 * Create a singleton diff.
3475	 */
3476	dns_diff_init(diff->mctx, &temp_diff);
3477	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3478
3479	/*
3480	 * Apply it to the database.
3481	 */
3482	result = dns_diff_apply(&temp_diff, db, ver);
3483	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3484	if (result != ISC_R_SUCCESS) {
3485		dns_difftuple_free(tuple);
3486		return (result);
3487	}
3488
3489	/*
3490	 * Merge it into the current pending journal entry.
3491	 */
3492	dns_diff_appendminimal(diff, tuple);
3493
3494	/*
3495	 * Do not clear temp_diff.
3496	 */
3497	return (ISC_R_SUCCESS);
3498}
3499
3500static isc_result_t
3501update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3502	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3503	      dns_rdata_t *rdata)
3504{
3505	dns_difftuple_t *tuple = NULL;
3506	isc_result_t result;
3507	result = dns_difftuple_create(diff->mctx, op,
3508				      name, ttl, rdata, &tuple);
3509	if (result != ISC_R_SUCCESS)
3510		return (result);
3511	return (do_one_tuple(&tuple, db, ver, diff));
3512}
3513
3514static isc_result_t
3515update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3516		  isc_mem_t *mctx, dns_updatemethod_t method) {
3517	dns_difftuple_t *deltuple = NULL;
3518	dns_difftuple_t *addtuple = NULL;
3519	isc_uint32_t serial;
3520	isc_result_t result;
3521
3522	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3523	CHECK(dns_difftuple_copy(deltuple, &addtuple));
3524	addtuple->op = DNS_DIFFOP_ADD;
3525
3526	serial = dns_soa_getserial(&addtuple->rdata);
3527	serial = dns_update_soaserial(serial, method);
3528	dns_soa_setserial(serial, &addtuple->rdata);
3529	CHECK(do_one_tuple(&deltuple, db, ver, diff));
3530	CHECK(do_one_tuple(&addtuple, db, ver, diff));
3531	result = ISC_R_SUCCESS;
3532
3533	failure:
3534	if (addtuple != NULL)
3535		dns_difftuple_free(&addtuple);
3536	if (deltuple != NULL)
3537		dns_difftuple_free(&deltuple);
3538	return (result);
3539}
3540
3541/*
3542 * Write all transactions in 'diff' to the zone journal file.
3543 */
3544static isc_result_t
3545zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial,
3546	     const char *caller)
3547{
3548	const char me[] = "zone_journal";
3549	const char *journalfile;
3550	isc_result_t result = ISC_R_SUCCESS;
3551	dns_journal_t *journal = NULL;
3552	unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
3553
3554	ENTER;
3555	journalfile = dns_zone_getjournal(zone);
3556	if (journalfile != NULL) {
3557		result = dns_journal_open(zone->mctx, journalfile, mode,
3558					  &journal);
3559		if (result != ISC_R_SUCCESS) {
3560			dns_zone_log(zone, ISC_LOG_ERROR,
3561				     "%s:dns_journal_open -> %s",
3562				     caller, dns_result_totext(result));
3563			return (result);
3564		}
3565
3566		if (sourceserial != NULL)
3567			dns_journal_set_sourceserial(journal, *sourceserial);
3568
3569		result = dns_journal_write_transaction(journal, diff);
3570		if (result != ISC_R_SUCCESS) {
3571			dns_zone_log(zone, ISC_LOG_ERROR,
3572				     "%s:dns_journal_write_transaction -> %s",
3573				     caller, dns_result_totext(result));
3574		}
3575		dns_journal_destroy(&journal);
3576	}
3577
3578	return (result);
3579}
3580
3581/*
3582 * Create an SOA record for a newly-created zone
3583 */
3584static isc_result_t
3585add_soa(dns_zone_t *zone, dns_db_t *db) {
3586	isc_result_t result;
3587	dns_rdata_t rdata = DNS_RDATA_INIT;
3588	unsigned char buf[DNS_SOA_BUFFERSIZE];
3589	dns_dbversion_t *ver = NULL;
3590	dns_diff_t diff;
3591
3592	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3593
3594	dns_diff_init(zone->mctx, &diff);
3595	result = dns_db_newversion(db, &ver);
3596	if (result != ISC_R_SUCCESS) {
3597		dns_zone_log(zone, ISC_LOG_ERROR,
3598			     "add_soa:dns_db_newversion -> %s",
3599			     dns_result_totext(result));
3600		goto failure;
3601	}
3602
3603	/* Build SOA record */
3604	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3605				    0, 0, 0, 0, 0, buf, &rdata);
3606	if (result != ISC_R_SUCCESS) {
3607		dns_zone_log(zone, ISC_LOG_ERROR,
3608			     "add_soa:dns_soa_buildrdata -> %s",
3609			     dns_result_totext(result));
3610		goto failure;
3611	}
3612
3613	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3614			       &zone->origin, 0, &rdata);
3615
3616failure:
3617	dns_diff_clear(&diff);
3618	if (ver != NULL)
3619		dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3620
3621	return (result);
3622}
3623
3624/*
3625 * Synchronize the set of initializing keys found in managed-keys {}
3626 * statements with the set of trust anchors found in the managed-keys.bind
3627 * zone.  If a domain is no longer named in managed-keys, delete all keys
3628 * from that domain from the key zone.	If a domain is mentioned in in
3629 * managed-keys but there are no references to it in the key zone, load
3630 * the key zone with the initializing key(s) for that domain.
3631 */
3632static isc_result_t
3633sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3634	isc_result_t result = ISC_R_SUCCESS;
3635	isc_boolean_t changed = ISC_FALSE;
3636	isc_boolean_t commit = ISC_FALSE;
3637	dns_rbtnodechain_t chain;
3638	dns_fixedname_t fn;
3639	dns_name_t foundname, *origin;
3640	dns_keynode_t *keynode = NULL;
3641	dns_view_t *view = zone->view;
3642	dns_keytable_t *sr = NULL;
3643	dns_dbversion_t *ver = NULL;
3644	dns_diff_t diff;
3645	dns_rriterator_t rrit;
3646
3647	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3648
3649	dns_name_init(&foundname, NULL);
3650	dns_fixedname_init(&fn);
3651	origin = dns_fixedname_name(&fn);
3652
3653	dns_diff_init(zone->mctx, &diff);
3654
3655	CHECK(dns_view_getsecroots(view, &sr));
3656
3657	result = dns_db_newversion(db, &ver);
3658	if (result != ISC_R_SUCCESS) {
3659		dns_zone_log(zone, ISC_LOG_ERROR,
3660			     "sync_keyzone:dns_db_newversion -> %s",
3661			     dns_result_totext(result));
3662		goto failure;
3663	}
3664
3665	/*
3666	 * Walk the zone DB.  If we find any keys whose names are no longer
3667	 * in managed-keys (or *are* in trusted-keys, meaning they are
3668	 * permanent and not RFC5011-maintained), delete them from the
3669	 * zone.  Otherwise call load_secroots(), which loads keys into
3670	 * secroots as appropriate.
3671	 */
3672	dns_rriterator_init(&rrit, db, ver, 0);
3673	for (result = dns_rriterator_first(&rrit);
3674	     result == ISC_R_SUCCESS;
3675	     result = dns_rriterator_nextrrset(&rrit)) {
3676		dns_rdataset_t *rdataset = NULL;
3677		dns_name_t *rrname = NULL;
3678		isc_uint32_t ttl;
3679
3680		dns_rriterator_current(&rrit, &rrname, &ttl,
3681				       &rdataset, NULL);
3682		if (!dns_rdataset_isassociated(rdataset)) {
3683			dns_rriterator_destroy(&rrit);
3684			goto failure;
3685		}
3686
3687		if (rdataset->type != dns_rdatatype_keydata)
3688			continue;
3689
3690		result = dns_keytable_find(sr, rrname, &keynode);
3691		if ((result != ISC_R_SUCCESS &&
3692		     result != DNS_R_PARTIALMATCH) ||
3693		    dns_keynode_managed(keynode) == ISC_FALSE) {
3694			CHECK(delete_keydata(db, ver, &diff,
3695					     rrname, rdataset));
3696			changed = ISC_TRUE;
3697		} else {
3698			load_secroots(zone, rrname, rdataset);
3699		}
3700
3701		if (keynode != NULL)
3702			dns_keytable_detachkeynode(sr, &keynode);
3703	}
3704	dns_rriterator_destroy(&rrit);
3705
3706	/*
3707	 * Now walk secroots to find any managed keys that aren't
3708	 * in the zone.  If we find any, we add them to the zone.
3709	 */
3710	RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3711	dns_rbtnodechain_init(&chain, zone->mctx);
3712	result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3713	if (result == ISC_R_NOTFOUND)
3714		result = ISC_R_NOMORE;
3715	while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3716		dns_rbtnode_t *rbtnode = NULL;
3717
3718		dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3719		if (rbtnode->data == NULL)
3720			goto skip;
3721
3722		dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3723		if (dns_keynode_managed(keynode)) {
3724			dns_fixedname_t fname;
3725			dns_name_t *keyname;
3726			dst_key_t *key;
3727
3728			key = dns_keynode_key(keynode);
3729			dns_fixedname_init(&fname);
3730
3731			if (key == NULL)   /* fail_secure() was called. */
3732				goto skip;
3733
3734			keyname = dst_key_name(key);
3735			result = dns_db_find(db, keyname, ver,
3736					     dns_rdatatype_keydata,
3737					     DNS_DBFIND_NOWILD, 0, NULL,
3738					     dns_fixedname_name(&fname),
3739					     NULL, NULL);
3740			if (result != ISC_R_SUCCESS)
3741				result = create_keydata(zone, db, ver, &diff,
3742							sr, &keynode, &changed);
3743			if (result != ISC_R_SUCCESS)
3744				break;
3745		}
3746  skip:
3747		result = dns_rbtnodechain_next(&chain, &foundname, origin);
3748		if (keynode != NULL)
3749			dns_keytable_detachkeynode(sr, &keynode);
3750	}
3751	RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3752
3753	if (result == ISC_R_NOMORE)
3754		result = ISC_R_SUCCESS;
3755
3756	if (changed) {
3757		/* Write changes to journal file. */
3758		CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
3759					zone->updatemethod));
3760		CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
3761
3762		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3763		zone_needdump(zone, 30);
3764		commit = ISC_TRUE;
3765	}
3766
3767 failure:
3768	if (result != ISC_R_SUCCESS &&
3769	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3770		dns_zone_log(zone, ISC_LOG_ERROR,
3771			     "unable to synchronize managed keys: %s",
3772			     dns_result_totext(result));
3773		isc_time_settoepoch(&zone->refreshkeytime);
3774	}
3775	if (keynode != NULL)
3776		dns_keytable_detachkeynode(sr, &keynode);
3777	if (sr != NULL)
3778		dns_keytable_detach(&sr);
3779	if (ver != NULL)
3780		dns_db_closeversion(db, &ver, commit);
3781	dns_diff_clear(&diff);
3782
3783	return (result);
3784}
3785
3786isc_result_t
3787dns_zone_synckeyzone(dns_zone_t *zone) {
3788	isc_result_t result;
3789	dns_db_t *db = NULL;
3790
3791	if (zone->type != dns_zone_key)
3792		return (DNS_R_BADZONE);
3793
3794	CHECK(dns_zone_getdb(zone, &db));
3795
3796	LOCK_ZONE(zone);
3797	result = sync_keyzone(zone, db);
3798	UNLOCK_ZONE(zone);
3799
3800 failure:
3801	if (db != NULL)
3802		dns_db_detach(&db);
3803	return (result);
3804}
3805
3806static void
3807maybe_send_secure(dns_zone_t *zone) {
3808	isc_result_t result;
3809
3810	/*
3811	 * We've finished loading, or else failed to load, an inline-signing
3812	 * 'secure' zone.  We now need information about the status of the
3813	 * 'raw' zone.  If we failed to load, then we need it to send a
3814	 * copy of its database; if we succeeded, we need it to send its
3815	 * serial number so that we can sync with it.  If it has not yet
3816	 * loaded, we set a flag so that it will send the necessary
3817	 * information when it has finished loading.
3818	 */
3819	if (zone->raw->db != NULL) {
3820		if (zone->db != NULL) {
3821			isc_uint32_t serial;
3822			unsigned int soacount;
3823
3824			result = zone_get_from_db(zone->raw, zone->raw->db,
3825						  NULL, &soacount, &serial, NULL,
3826						  NULL, NULL, NULL, NULL);
3827			if (result == ISC_R_SUCCESS && soacount > 0U)
3828				zone_send_secureserial(zone->raw, serial);
3829		} else
3830			zone_send_securedb(zone->raw, zone->raw->db);
3831
3832	} else
3833		DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
3834}
3835
3836static isc_boolean_t
3837zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
3838	isc_result_t result;
3839	isc_boolean_t answer = ISC_FALSE;
3840	dns_diff_t diff;
3841
3842	dns_diff_init(mctx, &diff);
3843	result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
3844	if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
3845		answer = ISC_TRUE;
3846	dns_diff_clear(&diff);
3847	return (answer);
3848}
3849
3850/*
3851 * The zone is presumed to be locked.
3852 * If this is a inline_raw zone the secure version is also locked.
3853 */
3854static isc_result_t
3855zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3856	      isc_result_t result)
3857{
3858	unsigned int soacount = 0;
3859	unsigned int nscount = 0;
3860	unsigned int errors = 0;
3861	isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3862	isc_time_t now;
3863	isc_boolean_t needdump = ISC_FALSE;
3864	isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3865	isc_boolean_t nomaster = ISC_FALSE;
3866	unsigned int options;
3867
3868	INSIST(LOCKED_ZONE(zone));
3869	if (inline_raw(zone))
3870		INSIST(LOCKED_ZONE(zone->secure));
3871
3872	TIME_NOW(&now);
3873
3874	/*
3875	 * Initiate zone transfer?  We may need a error code that
3876	 * indicates that the "permanent" form does not exist.
3877	 * XXX better error feedback to log.
3878	 */
3879	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3880		if (zone->type == dns_zone_slave ||
3881		    zone->type == dns_zone_stub ||
3882		    (zone->type == dns_zone_redirect &&
3883		     zone->masters == NULL)) {
3884			if (result == ISC_R_FILENOTFOUND)
3885				dns_zone_log(zone, ISC_LOG_DEBUG(1),
3886					     "no master file");
3887			else if (result != DNS_R_NOMASTERFILE)
3888				dns_zone_log(zone, ISC_LOG_ERROR,
3889					     "loading from master file %s "
3890					     "failed: %s",
3891					     zone->masterfile,
3892					     dns_result_totext(result));
3893		} else if (zone->type == dns_zone_master &&
3894			   inline_secure(zone) && result == ISC_R_FILENOTFOUND)
3895		{
3896			dns_zone_log(zone, ISC_LOG_DEBUG(1),
3897				     "no master file, requesting db");
3898			maybe_send_secure(zone);
3899		} else {
3900			int level = ISC_LOG_ERROR;
3901			if (zone->type == dns_zone_key &&
3902			    result == ISC_R_FILENOTFOUND)
3903				level = ISC_LOG_DEBUG(1);
3904			dns_zone_log(zone, level,
3905				     "loading from master file %s failed: %s",
3906				     zone->masterfile,
3907				     dns_result_totext(result));
3908			nomaster = ISC_TRUE;
3909		}
3910
3911		if (zone->type != dns_zone_key)
3912			goto cleanup;
3913	}
3914
3915	dns_zone_log(zone, ISC_LOG_DEBUG(2),
3916		     "number of nodes in database: %u",
3917		     dns_db_nodecount(db));
3918
3919	if (result == DNS_R_SEENINCLUDE)
3920		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3921	else
3922		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3923
3924	/*
3925	 * If there's no master file for a key zone, then the zone is new:
3926	 * create an SOA record.  (We do this now, instead of later, so that
3927	 * if there happens to be a journal file, we can roll forward from
3928	 * a sane starting point.)
3929	 */
3930	if (nomaster && zone->type == dns_zone_key) {
3931		result = add_soa(zone, db);
3932		if (result != ISC_R_SUCCESS)
3933			goto cleanup;
3934	}
3935
3936	/*
3937	 * Apply update log, if any, on initial load.
3938	 */
3939	if (zone->journal != NULL &&
3940	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
3941	    ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3942	{
3943		if (zone->type == dns_zone_master &&
3944		    (zone->update_acl != NULL || zone->ssutable != NULL))
3945			options = DNS_JOURNALOPT_RESIGN;
3946		else
3947			options = 0;
3948		result = dns_journal_rollforward2(zone->mctx, db, options,
3949						  0, zone->journal);
3950		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
3951		    result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
3952		    result != ISC_R_RANGE) {
3953			dns_zone_log(zone, ISC_LOG_ERROR,
3954				     "journal rollforward failed: %s",
3955				     dns_result_totext(result));
3956			goto cleanup;
3957
3958
3959		}
3960		if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
3961			dns_zone_log(zone, ISC_LOG_ERROR,
3962				     "journal rollforward failed: "
3963				     "journal out of sync with zone");
3964			goto cleanup;
3965		}
3966		dns_zone_log(zone, ISC_LOG_DEBUG(1),
3967			     "journal rollforward completed "
3968			     "successfully: %s",
3969			     dns_result_totext(result));
3970		if (result == ISC_R_SUCCESS)
3971			needdump = ISC_TRUE;
3972	}
3973
3974	/*
3975	 * Obtain ns, soa and cname counts for top of zone.
3976	 */
3977	INSIST(db != NULL);
3978	result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
3979				  &refresh, &retry, &expire, &minimum,
3980				  &errors);
3981	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
3982		dns_zone_log(zone, ISC_LOG_ERROR,
3983			     "could not find NS and/or SOA records");
3984	}
3985
3986	/*
3987	 * Check to make sure the journal is up to date, and remove the
3988	 * journal file if it isn't, as we wouldn't be able to apply
3989	 * updates otherwise.
3990	 */
3991	if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) &&
3992	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
3993		isc_uint32_t jserial;
3994		dns_journal_t *journal = NULL;
3995
3996		result = dns_journal_open(zone->mctx, zone->journal,
3997					  DNS_JOURNAL_READ, &journal);
3998		if (result == ISC_R_SUCCESS) {
3999			jserial = dns_journal_last_serial(journal);
4000			dns_journal_destroy(&journal);
4001		} else {
4002			jserial = serial;
4003			result = ISC_R_SUCCESS;
4004		}
4005
4006		if (jserial != serial) {
4007			dns_zone_log(zone, ISC_LOG_INFO,
4008				     "journal file is out of date: "
4009				     "removing journal file");
4010			if (remove(zone->journal) < 0 && errno != ENOENT) {
4011				char strbuf[ISC_STRERRORSIZE];
4012				isc__strerror(errno, strbuf, sizeof(strbuf));
4013				isc_log_write(dns_lctx,
4014					      DNS_LOGCATEGORY_GENERAL,
4015					      DNS_LOGMODULE_ZONE,
4016					      ISC_LOG_WARNING,
4017					      "unable to remove journal "
4018					      "'%s': '%s'",
4019					      zone->journal, strbuf);
4020			}
4021		}
4022	}
4023
4024	dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
4025
4026	/*
4027	 * Master / Slave / Stub zones require both NS and SOA records at
4028	 * the top of the zone.
4029	 */
4030
4031	switch (zone->type) {
4032	case dns_zone_dlz:
4033	case dns_zone_master:
4034	case dns_zone_slave:
4035	case dns_zone_stub:
4036	case dns_zone_redirect:
4037		if (soacount != 1) {
4038			dns_zone_log(zone, ISC_LOG_ERROR,
4039				     "has %d SOA records", soacount);
4040			result = DNS_R_BADZONE;
4041		}
4042		if (nscount == 0) {
4043			dns_zone_log(zone, ISC_LOG_ERROR,
4044				     "has no NS records");
4045			result = DNS_R_BADZONE;
4046		}
4047		if (result != ISC_R_SUCCESS)
4048			goto cleanup;
4049		if (zone->type == dns_zone_master && errors != 0) {
4050			result = DNS_R_BADZONE;
4051			goto cleanup;
4052		}
4053		if (zone->type != dns_zone_stub &&
4054		    zone->type != dns_zone_redirect) {
4055			result = check_nsec3param(zone, db);
4056			if (result != ISC_R_SUCCESS)
4057				goto cleanup;
4058		}
4059		if (zone->type == dns_zone_master &&
4060		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4061		    !integrity_checks(zone, db)) {
4062			result = DNS_R_BADZONE;
4063			goto cleanup;
4064		}
4065		if (zone->type == dns_zone_master &&
4066		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4067		    !zone_check_dup(zone, db)) {
4068			result = DNS_R_BADZONE;
4069			goto cleanup;
4070		}
4071
4072		if (zone->db != NULL) {
4073			unsigned int oldsoacount;
4074
4075			/*
4076			 * This is checked in zone_replacedb() for slave zones
4077			 * as they don't reload from disk.
4078			 */
4079			result = zone_get_from_db(zone, zone->db, NULL,
4080						  &oldsoacount, &oldserial,
4081						  NULL, NULL, NULL, NULL,
4082						  NULL);
4083			RUNTIME_CHECK(result == ISC_R_SUCCESS);
4084			RUNTIME_CHECK(soacount > 0U);
4085			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4086			    !isc_serial_gt(serial, oldserial)) {
4087				isc_uint32_t serialmin, serialmax;
4088
4089				INSIST(zone->type == dns_zone_master);
4090
4091				if (serial == oldserial &&
4092				    zone_unchanged(zone->db, db, zone->mctx)) {
4093					dns_zone_log(zone, ISC_LOG_INFO,
4094						     "ixfr-from-differences: "
4095						     "unchanged");
4096					return(ISC_R_SUCCESS);
4097				}
4098
4099				serialmin = (oldserial + 1) & 0xffffffffU;
4100				serialmax = (oldserial + 0x7fffffffU) &
4101					     0xffffffffU;
4102				dns_zone_log(zone, ISC_LOG_ERROR,
4103					     "ixfr-from-differences: "
4104					     "new serial (%u) out of range "
4105					     "[%u - %u]", serial, serialmin,
4106					     serialmax);
4107				result = DNS_R_BADZONE;
4108				goto cleanup;
4109			} else if (!isc_serial_ge(serial, oldserial))
4110				dns_zone_log(zone, ISC_LOG_ERROR,
4111					     "zone serial (%u/%u) has gone "
4112					     "backwards", serial, oldserial);
4113			else if (serial == oldserial && !hasinclude &&
4114				 strcmp(zone->db_argv[0], "_builtin") != 0)
4115				dns_zone_log(zone, ISC_LOG_ERROR,
4116					     "zone serial (%u) unchanged. "
4117					     "zone may fail to transfer "
4118					     "to slaves.", serial);
4119		}
4120
4121		if (zone->type == dns_zone_master &&
4122		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
4123		    zone->sigresigninginterval < (3 * refresh) &&
4124		    dns_db_issecure(db))
4125		{
4126			dns_zone_log(zone, ISC_LOG_WARNING,
4127				     "sig-re-signing-interval less than "
4128				     "3 * refresh.");
4129		}
4130
4131		zone->refresh = RANGE(refresh,
4132				      zone->minrefresh, zone->maxrefresh);
4133		zone->retry = RANGE(retry,
4134				    zone->minretry, zone->maxretry);
4135		zone->expire = RANGE(expire, zone->refresh + zone->retry,
4136				     DNS_MAX_EXPIRE);
4137		zone->minimum = minimum;
4138		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4139
4140		if (zone->type == dns_zone_slave ||
4141		    zone->type == dns_zone_stub ||
4142		    (zone->type == dns_zone_redirect &&
4143		     zone->masters != NULL)) {
4144			isc_time_t t;
4145			isc_uint32_t delay;
4146
4147			result = isc_file_getmodtime(zone->journal, &t);
4148			if (result != ISC_R_SUCCESS)
4149				result = isc_file_getmodtime(zone->masterfile,
4150							     &t);
4151			if (result == ISC_R_SUCCESS)
4152				DNS_ZONE_TIME_ADD(&t, zone->expire,
4153						  &zone->expiretime);
4154			else
4155				DNS_ZONE_TIME_ADD(&now, zone->retry,
4156						  &zone->expiretime);
4157
4158			delay = isc_random_jitter(zone->retry,
4159						  (zone->retry * 3) / 4);
4160			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
4161			if (isc_time_compare(&zone->refreshtime,
4162					     &zone->expiretime) >= 0)
4163				zone->refreshtime = now;
4164		}
4165
4166		break;
4167
4168	case dns_zone_key:
4169		result = sync_keyzone(zone, db);
4170		if (result != ISC_R_SUCCESS)
4171			goto cleanup;
4172		break;
4173
4174	default:
4175		UNEXPECTED_ERROR(__FILE__, __LINE__,
4176				 "unexpected zone type %d", zone->type);
4177		result = ISC_R_UNEXPECTED;
4178		goto cleanup;
4179	}
4180
4181	/*
4182	 * Check for weak DNSKEY's.
4183	 */
4184	if (zone->type == dns_zone_master)
4185		zone_check_dnskeys(zone, db);
4186
4187	/*
4188	 * Schedule DNSSEC key refresh.
4189	 */
4190	if (zone->type == dns_zone_master &&
4191	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
4192		zone->refreshkeytime = now;
4193
4194#if 0
4195	/* destroy notification example. */
4196	{
4197		isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
4198						    DNS_EVENT_DBDESTROYED,
4199						    dns_zonemgr_dbdestroyed,
4200						    zone,
4201						    sizeof(isc_event_t));
4202		dns_db_ondestroy(db, zone->task, &e);
4203	}
4204#endif
4205
4206	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4207	if (zone->db != NULL) {
4208		result = zone_replacedb(zone, db, ISC_FALSE);
4209		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4210		if (result != ISC_R_SUCCESS)
4211			goto cleanup;
4212	} else {
4213		zone_attachdb(zone, db);
4214		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4215		DNS_ZONE_SETFLAG(zone,
4216				 DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
4217		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
4218		    inline_raw(zone))
4219		{
4220			if (zone->secure->db == NULL)
4221				zone_send_securedb(zone, db);
4222			else
4223				zone_send_secureserial(zone, serial);
4224		}
4225	}
4226
4227	/*
4228	 * Finished loading inline-signing zone; need to get status
4229	 * from the raw side now.
4230	 */
4231	if (zone->type == dns_zone_master && inline_secure(zone))
4232		maybe_send_secure(zone);
4233
4234
4235	result = ISC_R_SUCCESS;
4236
4237	if (needdump) {
4238		if (zone->type == dns_zone_key)
4239			zone_needdump(zone, 30);
4240		else
4241			zone_needdump(zone, DNS_DUMP_DELAY);
4242	}
4243
4244	if (zone->task != NULL) {
4245		if (zone->type == dns_zone_master) {
4246			set_resigntime(zone);
4247			resume_signingwithkey(zone);
4248			resume_addnsec3chain(zone);
4249		}
4250
4251		if (zone->type == dns_zone_master &&
4252		    !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4253		    dns_zone_isdynamic(zone, ISC_FALSE) &&
4254		    dns_db_issecure(db)) {
4255			dns_name_t *name;
4256			dns_fixedname_t fixed;
4257			dns_rdataset_t next;
4258
4259			dns_rdataset_init(&next);
4260			dns_fixedname_init(&fixed);
4261			name = dns_fixedname_name(&fixed);
4262
4263			result = dns_db_getsigningtime(db, &next, name);
4264			if (result == ISC_R_SUCCESS) {
4265				isc_stdtime_t timenow;
4266				char namebuf[DNS_NAME_FORMATSIZE];
4267				char typebuf[DNS_RDATATYPE_FORMATSIZE];
4268
4269				isc_stdtime_get(&timenow);
4270				dns_name_format(name, namebuf, sizeof(namebuf));
4271				dns_rdatatype_format(next.covers,
4272						     typebuf, sizeof(typebuf));
4273				dns_zone_log(zone, ISC_LOG_DEBUG(3),
4274					     "next resign: %s/%s in %d seconds",
4275					     namebuf, typebuf,
4276					     next.resign - timenow -
4277					     zone->sigresigninginterval);
4278				dns_rdataset_disassociate(&next);
4279			} else
4280				dns_zone_log(zone, ISC_LOG_WARNING,
4281					     "signed dynamic zone has no "
4282					     "resign event scheduled");
4283		}
4284
4285		zone_settimer(zone, &now);
4286	}
4287
4288	if (! dns_db_ispersistent(db))
4289		dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
4290			     dns_db_issecure(db) ? " (DNSSEC signed)" : "");
4291
4292	zone->loadtime = loadtime;
4293	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
4294	return (result);
4295
4296 cleanup:
4297	if (zone->type == dns_zone_slave ||
4298	    zone->type == dns_zone_stub ||
4299	    zone->type == dns_zone_key ||
4300	    (zone->type == dns_zone_redirect && zone->masters != NULL)) {
4301		if (zone->journal != NULL)
4302			zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
4303		if (zone->masterfile != NULL)
4304			zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
4305
4306		/* Mark the zone for immediate refresh. */
4307		zone->refreshtime = now;
4308		if (zone->task != NULL)
4309			zone_settimer(zone, &now);
4310		result = ISC_R_SUCCESS;
4311	} else if (zone->type == dns_zone_master ||
4312		   zone->type == dns_zone_redirect) {
4313		if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND))
4314			dns_zone_log(zone, ISC_LOG_ERROR,
4315				     "not loaded due to errors.");
4316		else if (zone->type == dns_zone_master)
4317			result = ISC_R_SUCCESS;
4318	}
4319
4320	return (result);
4321}
4322
4323static isc_boolean_t
4324exit_check(dns_zone_t *zone) {
4325	REQUIRE(LOCKED_ZONE(zone));
4326
4327	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
4328		/*
4329		 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
4330		 */
4331		INSIST(isc_refcount_current(&zone->erefs) == 0);
4332		return (ISC_TRUE);
4333	}
4334	return (ISC_FALSE);
4335}
4336
4337static isc_boolean_t
4338zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
4339	      dns_name_t *name, isc_boolean_t logit)
4340{
4341	isc_result_t result;
4342	char namebuf[DNS_NAME_FORMATSIZE];
4343	char altbuf[DNS_NAME_FORMATSIZE];
4344	dns_fixedname_t fixed;
4345	dns_name_t *foundname;
4346	int level;
4347
4348	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
4349		return (ISC_TRUE);
4350
4351	if (zone->type == dns_zone_master)
4352		level = ISC_LOG_ERROR;
4353	else
4354		level = ISC_LOG_WARNING;
4355
4356	dns_fixedname_init(&fixed);
4357	foundname = dns_fixedname_name(&fixed);
4358
4359	result = dns_db_find(db, name, version, dns_rdatatype_a,
4360			     0, 0, NULL, foundname, NULL, NULL);
4361	if (result == ISC_R_SUCCESS)
4362		return (ISC_TRUE);
4363
4364	if (result == DNS_R_NXRRSET) {
4365		result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
4366				     0, 0, NULL, foundname, NULL, NULL);
4367		if (result == ISC_R_SUCCESS)
4368			return (ISC_TRUE);
4369	}
4370
4371	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
4372	    result == DNS_R_EMPTYNAME) {
4373		if (logit) {
4374			dns_name_format(name, namebuf, sizeof namebuf);
4375			dns_zone_log(zone, level, "NS '%s' has no address "
4376				     "records (A or AAAA)", namebuf);
4377		}
4378		return (ISC_FALSE);
4379	}
4380
4381	if (result == DNS_R_CNAME) {
4382		if (logit) {
4383			dns_name_format(name, namebuf, sizeof namebuf);
4384			dns_zone_log(zone, level, "NS '%s' is a CNAME "
4385				     "(illegal)", namebuf);
4386		}
4387		return (ISC_FALSE);
4388	}
4389
4390	if (result == DNS_R_DNAME) {
4391		if (logit) {
4392			dns_name_format(name, namebuf, sizeof namebuf);
4393			dns_name_format(foundname, altbuf, sizeof altbuf);
4394			dns_zone_log(zone, level, "NS '%s' is below a DNAME "
4395				     "'%s' (illegal)", namebuf, altbuf);
4396		}
4397		return (ISC_FALSE);
4398	}
4399
4400	return (ISC_TRUE);
4401}
4402
4403static isc_result_t
4404zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
4405		 dns_dbversion_t *version, unsigned int *nscount,
4406		 unsigned int *errors, isc_boolean_t logit)
4407{
4408	isc_result_t result;
4409	unsigned int count = 0;
4410	unsigned int ecount = 0;
4411	dns_rdataset_t rdataset;
4412	dns_rdata_t rdata;
4413	dns_rdata_ns_t ns;
4414
4415	dns_rdataset_init(&rdataset);
4416	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
4417				     dns_rdatatype_none, 0, &rdataset, NULL);
4418	if (result == ISC_R_NOTFOUND) {
4419		INSIST(!dns_rdataset_isassociated(&rdataset));
4420		goto success;
4421	}
4422	if (result != ISC_R_SUCCESS) {
4423		INSIST(!dns_rdataset_isassociated(&rdataset));
4424		goto invalidate_rdataset;
4425	}
4426
4427	result = dns_rdataset_first(&rdataset);
4428	while (result == ISC_R_SUCCESS) {
4429		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
4430		    (zone->type == dns_zone_master ||
4431		     zone->type == dns_zone_slave)) {
4432			dns_rdata_init(&rdata);
4433			dns_rdataset_current(&rdataset, &rdata);
4434			result = dns_rdata_tostruct(&rdata, &ns, NULL);
4435			RUNTIME_CHECK(result == ISC_R_SUCCESS);
4436			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
4437			    !zone_check_ns(zone, db, version, &ns.name, logit))
4438				ecount++;
4439		}
4440		count++;
4441		result = dns_rdataset_next(&rdataset);
4442	}
4443	dns_rdataset_disassociate(&rdataset);
4444
4445 success:
4446	if (nscount != NULL)
4447		*nscount = count;
4448	if (errors != NULL)
4449		*errors = ecount;
4450
4451	result = ISC_R_SUCCESS;
4452
4453 invalidate_rdataset:
4454	dns_rdataset_invalidate(&rdataset);
4455
4456	return (result);
4457}
4458
4459static isc_result_t
4460zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
4461		 unsigned int *soacount,
4462		 isc_uint32_t *serial, isc_uint32_t *refresh,
4463		 isc_uint32_t *retry, isc_uint32_t *expire,
4464		 isc_uint32_t *minimum)
4465{
4466	isc_result_t result;
4467	unsigned int count;
4468	dns_rdataset_t rdataset;
4469	dns_rdata_t rdata = DNS_RDATA_INIT;
4470	dns_rdata_soa_t soa;
4471
4472	dns_rdataset_init(&rdataset);
4473	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
4474				     dns_rdatatype_none, 0, &rdataset, NULL);
4475	if (result == ISC_R_NOTFOUND) {
4476		INSIST(!dns_rdataset_isassociated(&rdataset));
4477		if (soacount != NULL)
4478			*soacount = 0;
4479		if (serial != NULL)
4480			*serial = 0;
4481		if (refresh != NULL)
4482			*refresh = 0;
4483		if (retry != NULL)
4484			*retry = 0;
4485		if (expire != NULL)
4486			*expire = 0;
4487		if (minimum != NULL)
4488			*minimum = 0;
4489		result = ISC_R_SUCCESS;
4490		goto invalidate_rdataset;
4491	}
4492	if (result != ISC_R_SUCCESS) {
4493		INSIST(!dns_rdataset_isassociated(&rdataset));
4494		goto invalidate_rdataset;
4495	}
4496
4497	count = 0;
4498	result = dns_rdataset_first(&rdataset);
4499	while (result == ISC_R_SUCCESS) {
4500		dns_rdata_init(&rdata);
4501		dns_rdataset_current(&rdataset, &rdata);
4502		count++;
4503		if (count == 1) {
4504			result = dns_rdata_tostruct(&rdata, &soa, NULL);
4505			RUNTIME_CHECK(result == ISC_R_SUCCESS);
4506		}
4507
4508		result = dns_rdataset_next(&rdataset);
4509		dns_rdata_reset(&rdata);
4510	}
4511	dns_rdataset_disassociate(&rdataset);
4512
4513	if (soacount != NULL)
4514		*soacount = count;
4515
4516	if (count > 0) {
4517		if (serial != NULL)
4518			*serial = soa.serial;
4519		if (refresh != NULL)
4520			*refresh = soa.refresh;
4521		if (retry != NULL)
4522			*retry = soa.retry;
4523		if (expire != NULL)
4524			*expire = soa.expire;
4525		if (minimum != NULL)
4526			*minimum = soa.minimum;
4527	} else {
4528		if (soacount != NULL)
4529			*soacount = 0;
4530		if (serial != NULL)
4531			*serial = 0;
4532		if (refresh != NULL)
4533			*refresh = 0;
4534		if (retry != NULL)
4535			*retry = 0;
4536		if (expire != NULL)
4537			*expire = 0;
4538		if (minimum != NULL)
4539			*minimum = 0;
4540	}
4541
4542	result = ISC_R_SUCCESS;
4543
4544 invalidate_rdataset:
4545	dns_rdataset_invalidate(&rdataset);
4546
4547	return (result);
4548}
4549
4550/*
4551 * zone must be locked.
4552 */
4553static isc_result_t
4554zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
4555		 unsigned int *soacount, isc_uint32_t *serial,
4556		 isc_uint32_t *refresh, isc_uint32_t *retry,
4557		 isc_uint32_t *expire, isc_uint32_t *minimum,
4558		 unsigned int *errors)
4559{
4560	isc_result_t result;
4561	isc_result_t answer = ISC_R_SUCCESS;
4562	dns_dbversion_t *version = NULL;
4563	dns_dbnode_t *node;
4564
4565	REQUIRE(db != NULL);
4566	REQUIRE(zone != NULL);
4567
4568	dns_db_currentversion(db, &version);
4569
4570	node = NULL;
4571	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
4572	if (result != ISC_R_SUCCESS) {
4573		answer = result;
4574		goto closeversion;
4575	}
4576
4577	if (nscount != NULL || errors != NULL) {
4578		result = zone_count_ns_rr(zone, db, node, version,
4579					  nscount, errors, ISC_TRUE);
4580		if (result != ISC_R_SUCCESS)
4581			answer = result;
4582	}
4583
4584	if (soacount != NULL || serial != NULL || refresh != NULL
4585	    || retry != NULL || expire != NULL || minimum != NULL) {
4586		result = zone_load_soa_rr(db, node, version, soacount,
4587					  serial, refresh, retry, expire,
4588					  minimum);
4589		if (result != ISC_R_SUCCESS)
4590			answer = result;
4591	}
4592
4593	dns_db_detachnode(db, &node);
4594 closeversion:
4595	dns_db_closeversion(db, &version, ISC_FALSE);
4596
4597	return (answer);
4598}
4599
4600void
4601dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
4602	REQUIRE(DNS_ZONE_VALID(source));
4603	REQUIRE(target != NULL && *target == NULL);
4604	isc_refcount_increment(&source->erefs, NULL);
4605	*target = source;
4606}
4607
4608void
4609dns_zone_detach(dns_zone_t **zonep) {
4610	dns_zone_t *zone;
4611	dns_zone_t *raw = NULL;
4612	dns_zone_t *secure = NULL;
4613	unsigned int refs;
4614	isc_boolean_t free_now = ISC_FALSE;
4615
4616	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4617
4618	zone = *zonep;
4619
4620	isc_refcount_decrement(&zone->erefs, &refs);
4621
4622	if (refs == 0) {
4623		LOCK_ZONE(zone);
4624		/*
4625		 * We just detached the last external reference.
4626		 */
4627		if (zone->task != NULL) {
4628			/*
4629			 * This zone is being managed.	Post
4630			 * its control event and let it clean
4631			 * up synchronously in the context of
4632			 * its task.
4633			 */
4634			isc_event_t *ev = &zone->ctlevent;
4635			isc_task_send(zone->task, &ev);
4636		} else {
4637			/*
4638			 * This zone is not being managed; it has
4639			 * no task and can have no outstanding
4640			 * events.  Free it immediately.
4641			 */
4642			/*
4643			 * Unmanaged zones should not have non-null views;
4644			 * we have no way of detaching from the view here
4645			 * without causing deadlock because this code is called
4646			 * with the view already locked.
4647			 */
4648			INSIST(zone->view == NULL);
4649			free_now = ISC_TRUE;
4650			raw = zone->raw;
4651			zone->raw = NULL;
4652			secure = zone->secure;
4653			zone->secure = NULL;
4654		}
4655		UNLOCK_ZONE(zone);
4656	}
4657	*zonep = NULL;
4658	if (free_now) {
4659		if (raw != NULL)
4660			dns_zone_detach(&raw);
4661		if (secure != NULL)
4662			dns_zone_idetach(&secure);
4663		zone_free(zone);
4664	}
4665}
4666
4667void
4668dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4669	REQUIRE(DNS_ZONE_VALID(source));
4670	REQUIRE(target != NULL && *target == NULL);
4671	LOCK_ZONE(source);
4672	zone_iattach(source, target);
4673	UNLOCK_ZONE(source);
4674}
4675
4676static void
4677zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4678
4679	/*
4680	 * 'source' locked by caller.
4681	 */
4682	REQUIRE(LOCKED_ZONE(source));
4683	REQUIRE(DNS_ZONE_VALID(source));
4684	REQUIRE(target != NULL && *target == NULL);
4685	INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
4686	source->irefs++;
4687	INSIST(source->irefs != 0);
4688	*target = source;
4689}
4690
4691static void
4692zone_idetach(dns_zone_t **zonep) {
4693	dns_zone_t *zone;
4694
4695	/*
4696	 * 'zone' locked by caller.
4697	 */
4698	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4699	zone = *zonep;
4700	REQUIRE(LOCKED_ZONE(*zonep));
4701	*zonep = NULL;
4702
4703	INSIST(zone->irefs > 0);
4704	zone->irefs--;
4705	INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4706}
4707
4708void
4709dns_zone_idetach(dns_zone_t **zonep) {
4710	dns_zone_t *zone;
4711	isc_boolean_t free_needed;
4712
4713	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4714	zone = *zonep;
4715	*zonep = NULL;
4716
4717	LOCK_ZONE(zone);
4718	INSIST(zone->irefs > 0);
4719	zone->irefs--;
4720	free_needed = exit_check(zone);
4721	UNLOCK_ZONE(zone);
4722	if (free_needed)
4723		zone_free(zone);
4724}
4725
4726isc_mem_t *
4727dns_zone_getmctx(dns_zone_t *zone) {
4728	REQUIRE(DNS_ZONE_VALID(zone));
4729
4730	return (zone->mctx);
4731}
4732
4733dns_zonemgr_t *
4734dns_zone_getmgr(dns_zone_t *zone) {
4735	REQUIRE(DNS_ZONE_VALID(zone));
4736
4737	return (zone->zmgr);
4738}
4739
4740void
4741dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4742	REQUIRE(DNS_ZONE_VALID(zone));
4743
4744	LOCK_ZONE(zone);
4745	if (value)
4746		DNS_ZONE_SETFLAG(zone, flags);
4747	else
4748		DNS_ZONE_CLRFLAG(zone, flags);
4749	UNLOCK_ZONE(zone);
4750}
4751
4752void
4753dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4754{
4755	REQUIRE(DNS_ZONE_VALID(zone));
4756
4757	LOCK_ZONE(zone);
4758	if (value)
4759		zone->options |= option;
4760	else
4761		zone->options &= ~option;
4762	UNLOCK_ZONE(zone);
4763}
4764
4765unsigned int
4766dns_zone_getoptions(dns_zone_t *zone) {
4767
4768	REQUIRE(DNS_ZONE_VALID(zone));
4769
4770	return (zone->options);
4771}
4772
4773void
4774dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4775{
4776	REQUIRE(DNS_ZONE_VALID(zone));
4777
4778	LOCK_ZONE(zone);
4779	if (value)
4780		zone->keyopts |= keyopt;
4781	else
4782		zone->keyopts &= ~keyopt;
4783	UNLOCK_ZONE(zone);
4784}
4785
4786unsigned int
4787dns_zone_getkeyopts(dns_zone_t *zone) {
4788
4789	REQUIRE(DNS_ZONE_VALID(zone));
4790
4791	return (zone->keyopts);
4792}
4793
4794isc_result_t
4795dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4796	REQUIRE(DNS_ZONE_VALID(zone));
4797
4798	LOCK_ZONE(zone);
4799	zone->xfrsource4 = *xfrsource;
4800	UNLOCK_ZONE(zone);
4801
4802	return (ISC_R_SUCCESS);
4803}
4804
4805isc_sockaddr_t *
4806dns_zone_getxfrsource4(dns_zone_t *zone) {
4807	REQUIRE(DNS_ZONE_VALID(zone));
4808	return (&zone->xfrsource4);
4809}
4810
4811isc_result_t
4812dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4813	REQUIRE(DNS_ZONE_VALID(zone));
4814
4815	LOCK_ZONE(zone);
4816	zone->xfrsource6 = *xfrsource;
4817	UNLOCK_ZONE(zone);
4818
4819	return (ISC_R_SUCCESS);
4820}
4821
4822isc_sockaddr_t *
4823dns_zone_getxfrsource6(dns_zone_t *zone) {
4824	REQUIRE(DNS_ZONE_VALID(zone));
4825	return (&zone->xfrsource6);
4826}
4827
4828isc_result_t
4829dns_zone_setaltxfrsource4(dns_zone_t *zone,
4830			  const isc_sockaddr_t *altxfrsource)
4831{
4832	REQUIRE(DNS_ZONE_VALID(zone));
4833
4834	LOCK_ZONE(zone);
4835	zone->altxfrsource4 = *altxfrsource;
4836	UNLOCK_ZONE(zone);
4837
4838	return (ISC_R_SUCCESS);
4839}
4840
4841isc_sockaddr_t *
4842dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4843	REQUIRE(DNS_ZONE_VALID(zone));
4844	return (&zone->altxfrsource4);
4845}
4846
4847isc_result_t
4848dns_zone_setaltxfrsource6(dns_zone_t *zone,
4849			  const isc_sockaddr_t *altxfrsource)
4850{
4851	REQUIRE(DNS_ZONE_VALID(zone));
4852
4853	LOCK_ZONE(zone);
4854	zone->altxfrsource6 = *altxfrsource;
4855	UNLOCK_ZONE(zone);
4856
4857	return (ISC_R_SUCCESS);
4858}
4859
4860isc_sockaddr_t *
4861dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4862	REQUIRE(DNS_ZONE_VALID(zone));
4863	return (&zone->altxfrsource6);
4864}
4865
4866isc_result_t
4867dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4868	REQUIRE(DNS_ZONE_VALID(zone));
4869
4870	LOCK_ZONE(zone);
4871	zone->notifysrc4 = *notifysrc;
4872	UNLOCK_ZONE(zone);
4873
4874	return (ISC_R_SUCCESS);
4875}
4876
4877isc_sockaddr_t *
4878dns_zone_getnotifysrc4(dns_zone_t *zone) {
4879	REQUIRE(DNS_ZONE_VALID(zone));
4880	return (&zone->notifysrc4);
4881}
4882
4883isc_result_t
4884dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4885	REQUIRE(DNS_ZONE_VALID(zone));
4886
4887	LOCK_ZONE(zone);
4888	zone->notifysrc6 = *notifysrc;
4889	UNLOCK_ZONE(zone);
4890
4891	return (ISC_R_SUCCESS);
4892}
4893
4894isc_sockaddr_t *
4895dns_zone_getnotifysrc6(dns_zone_t *zone) {
4896	REQUIRE(DNS_ZONE_VALID(zone));
4897	return (&zone->notifysrc6);
4898}
4899
4900static isc_boolean_t
4901same_addrs(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4902	     isc_uint32_t count)
4903{
4904	unsigned int i;
4905
4906	for (i = 0; i < count; i++)
4907		if (!isc_sockaddr_equal(&old[i], &new[i]))
4908			return (ISC_FALSE);
4909	return (ISC_TRUE);
4910}
4911
4912static isc_boolean_t
4913same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
4914	unsigned int i;
4915
4916	if (old == NULL && new == NULL)
4917		return (ISC_TRUE);
4918	if (old == NULL || new == NULL)
4919		return (ISC_FALSE);
4920
4921	for (i = 0; i < count; i++) {
4922		if (old[i] == NULL && new[i] == NULL)
4923			continue;
4924		if (old[i] == NULL || new[i] == NULL ||
4925		     !dns_name_equal(old[i], new[i]))
4926			return (ISC_FALSE);
4927	}
4928	return (ISC_TRUE);
4929}
4930
4931static void
4932clear_addresskeylist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
4933		     unsigned int *countp, isc_mem_t *mctx)
4934{
4935	unsigned int count;
4936	isc_sockaddr_t *addrs;
4937	dns_name_t **keynames;
4938
4939	REQUIRE(countp != NULL && addrsp != NULL && keynamesp != NULL);
4940
4941	count = *countp;
4942	*countp = 0;
4943	addrs = *addrsp;
4944	*addrsp = NULL;
4945	keynames = *keynamesp;
4946	*keynamesp = NULL;
4947
4948	if (addrs != NULL)
4949		isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
4950
4951	if (keynames != NULL) {
4952		unsigned int i;
4953		for (i = 0; i < count; i++) {
4954			if (keynames[i] != NULL) {
4955				dns_name_free(keynames[i], mctx);
4956				isc_mem_put(mctx, keynames[i],
4957					    sizeof(dns_name_t));
4958				keynames[i] = NULL;
4959			}
4960		}
4961		isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
4962	}
4963}
4964
4965static isc_result_t
4966set_addrkeylist(unsigned int count,
4967		const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
4968		dns_name_t **names, dns_name_t ***newnamesp,
4969		isc_mem_t *mctx)
4970{
4971	isc_result_t result;
4972	isc_sockaddr_t *newaddrs = NULL;
4973	dns_name_t **newnames = NULL;
4974	unsigned int i;
4975
4976	REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
4977	REQUIRE(newnamesp != NULL && *newnamesp == NULL);
4978
4979	newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
4980	if (newaddrs == NULL)
4981		return (ISC_R_NOMEMORY);
4982	memmove(newaddrs, addrs, count * sizeof(*newaddrs));
4983
4984	newnames = NULL;
4985	if (names != NULL) {
4986		newnames = isc_mem_get(mctx, count * sizeof(*newnames));
4987		if (newnames == NULL) {
4988			isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
4989			return (ISC_R_NOMEMORY);
4990		}
4991		for (i = 0; i < count; i++)
4992			newnames[i] = NULL;
4993		for (i = 0; i < count; i++) {
4994			if (names[i] != NULL) {
4995				newnames[i] = isc_mem_get(mctx,
4996							 sizeof(dns_name_t));
4997				if (newnames[i] == NULL)
4998					goto allocfail;
4999				dns_name_init(newnames[i], NULL);
5000				result = dns_name_dup(names[i], mctx,
5001						      newnames[i]);
5002				if (result != ISC_R_SUCCESS) {
5003				allocfail:
5004					for (i = 0; i < count; i++)
5005						if (newnames[i] != NULL)
5006							dns_name_free(
5007							       newnames[i],
5008							       mctx);
5009					isc_mem_put(mctx, newaddrs,
5010						    count * sizeof(*newaddrs));
5011					isc_mem_put(mctx, newnames,
5012						    count * sizeof(*newnames));
5013					return (ISC_R_NOMEMORY);
5014				}
5015			}
5016		}
5017	}
5018
5019	*newaddrsp = newaddrs;
5020	*newnamesp = newnames;
5021	return (ISC_R_SUCCESS);
5022}
5023
5024isc_result_t
5025dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
5026		       isc_uint32_t count)
5027{
5028	return (dns_zone_setalsonotifywithkeys(zone, notify, NULL, count));
5029}
5030
5031isc_result_t
5032dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5033			       dns_name_t **keynames, isc_uint32_t count)
5034{
5035	isc_result_t result;
5036	isc_sockaddr_t *newaddrs = NULL;
5037	dns_name_t **newnames = NULL;
5038
5039	REQUIRE(DNS_ZONE_VALID(zone));
5040	REQUIRE(count == 0 || notify != NULL);
5041	if (keynames != NULL)
5042		REQUIRE(count != 0);
5043
5044	LOCK_ZONE(zone);
5045
5046	if (count == zone->notifycnt &&
5047	    same_addrs(zone->notify, notify, count) &&
5048	    same_keynames(zone->notifykeynames, keynames, count))
5049		goto unlock;
5050
5051	clear_addresskeylist(&zone->notify, &zone->notifykeynames,
5052			     &zone->notifycnt, zone->mctx);
5053
5054	if (count == 0)
5055		goto unlock;
5056
5057	/*
5058	 * Set up the notify and notifykey lists
5059	 */
5060	result = set_addrkeylist(count, notify, &newaddrs,
5061				 keynames, &newnames, zone->mctx);
5062	if (result != ISC_R_SUCCESS)
5063		goto unlock;
5064
5065	/*
5066	 * Everything is ok so attach to the zone.
5067	 */
5068	zone->notify = newaddrs;
5069	zone->notifykeynames = newnames;
5070	zone->notifycnt = count;
5071 unlock:
5072	UNLOCK_ZONE(zone);
5073	return (ISC_R_SUCCESS);
5074}
5075
5076isc_result_t
5077dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
5078		    isc_uint32_t count)
5079{
5080	isc_result_t result;
5081
5082	result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
5083	return (result);
5084}
5085
5086isc_result_t
5087dns_zone_setmasterswithkeys(dns_zone_t *zone,
5088			    const isc_sockaddr_t *masters,
5089			    dns_name_t **keynames,
5090			    isc_uint32_t count)
5091{
5092	isc_result_t result = ISC_R_SUCCESS;
5093	isc_sockaddr_t *newaddrs = NULL;
5094	dns_name_t **newnames = NULL;
5095	isc_boolean_t *newok;
5096	unsigned int i;
5097
5098	REQUIRE(DNS_ZONE_VALID(zone));
5099	REQUIRE(count == 0 || masters != NULL);
5100	if (keynames != NULL) {
5101		REQUIRE(count != 0);
5102	}
5103
5104	LOCK_ZONE(zone);
5105	/*
5106	 * The refresh code assumes that 'masters' wouldn't change under it.
5107	 * If it will change then kill off any current refresh in progress
5108	 * and update the masters info.  If it won't change then we can just
5109	 * unlock and exit.
5110	 */
5111	if (count != zone->masterscnt ||
5112	    !same_addrs(zone->masters, masters, count) ||
5113	    !same_keynames(zone->masterkeynames, keynames, count)) {
5114		if (zone->request != NULL)
5115			dns_request_cancel(zone->request);
5116	} else
5117		goto unlock;
5118
5119	/*
5120	 * This needs to happen before clear_addresskeylist() sets
5121	 * zone->masterscnt to 0:
5122	 */
5123	if (zone->mastersok != NULL) {
5124		isc_mem_put(zone->mctx, zone->mastersok,
5125			    zone->masterscnt * sizeof(isc_boolean_t));
5126		zone->mastersok = NULL;
5127	}
5128	clear_addresskeylist(&zone->masters, &zone->masterkeynames,
5129			     &zone->masterscnt, zone->mctx);
5130	/*
5131	 * If count == 0, don't allocate any space for masters, mastersok or
5132	 * keynames so internally, those pointers are NULL if count == 0
5133	 */
5134	if (count == 0)
5135		goto unlock;
5136
5137	/*
5138	 * mastersok must contain count elements
5139	 */
5140	newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
5141	if (newok == NULL) {
5142		result = ISC_R_NOMEMORY;
5143		isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
5144		goto unlock;
5145	};
5146	for (i = 0; i < count; i++)
5147		newok[i] = ISC_FALSE;
5148
5149	/*
5150	 * Now set up the masters and masterkey lists
5151	 */
5152	result = set_addrkeylist(count, masters, &newaddrs,
5153				 keynames, &newnames, zone->mctx);
5154	if (result != ISC_R_SUCCESS) {
5155		isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
5156		goto unlock;
5157	}
5158
5159	/*
5160	 * Everything is ok so attach to the zone.
5161	 */
5162	zone->curmaster = 0;
5163	zone->mastersok = newok;
5164	zone->masters = newaddrs;
5165	zone->masterkeynames = newnames;
5166	zone->masterscnt = count;
5167	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
5168
5169 unlock:
5170	UNLOCK_ZONE(zone);
5171	return (result);
5172}
5173
5174isc_result_t
5175dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
5176	isc_result_t result = ISC_R_SUCCESS;
5177
5178	REQUIRE(DNS_ZONE_VALID(zone));
5179
5180	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5181	if (zone->db == NULL)
5182		result = DNS_R_NOTLOADED;
5183	else
5184		dns_db_attach(zone->db, dpb);
5185	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5186
5187	return (result);
5188}
5189
5190void
5191dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
5192	REQUIRE(DNS_ZONE_VALID(zone));
5193	REQUIRE(zone->type == dns_zone_staticstub);
5194
5195	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5196	REQUIRE(zone->db == NULL);
5197	dns_db_attach(db, &zone->db);
5198	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5199}
5200
5201/*
5202 * Co-ordinates the starting of routine jobs.
5203 */
5204
5205void
5206dns_zone_maintenance(dns_zone_t *zone) {
5207	const char me[] = "dns_zone_maintenance";
5208	isc_time_t now;
5209
5210	REQUIRE(DNS_ZONE_VALID(zone));
5211	ENTER;
5212
5213	LOCK_ZONE(zone);
5214	TIME_NOW(&now);
5215	zone_settimer(zone, &now);
5216	UNLOCK_ZONE(zone);
5217}
5218
5219static inline isc_boolean_t
5220was_dumping(dns_zone_t *zone) {
5221	isc_boolean_t dumping;
5222
5223	REQUIRE(LOCKED_ZONE(zone));
5224
5225	dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
5226	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
5227	if (!dumping) {
5228		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
5229		isc_time_settoepoch(&zone->dumptime);
5230	}
5231	return (dumping);
5232}
5233
5234static isc_result_t
5235find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
5236	       isc_mem_t *mctx, unsigned int maxkeys,
5237	       dst_key_t **keys, unsigned int *nkeys)
5238{
5239	isc_result_t result;
5240	dns_dbnode_t *node = NULL;
5241	const char *directory = dns_zone_getkeydirectory(zone);
5242
5243	CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
5244	memset(keys, 0, sizeof(*keys) * maxkeys);
5245	result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
5246					  directory, mctx, maxkeys, keys,
5247					  nkeys);
5248	if (result == ISC_R_NOTFOUND)
5249		result = ISC_R_SUCCESS;
5250 failure:
5251	if (node != NULL)
5252		dns_db_detachnode(db, &node);
5253	return (result);
5254}
5255
5256static isc_result_t
5257offline(dns_db_t *db, dns_dbversion_t *ver, zonediff_t *zonediff,
5258	dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
5259{
5260	isc_result_t result;
5261
5262	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
5263		return (ISC_R_SUCCESS);
5264	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
5265			       name, ttl, rdata);
5266	if (result != ISC_R_SUCCESS)
5267		return (result);
5268	rdata->flags |= DNS_RDATA_OFFLINE;
5269	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
5270			       name, ttl, rdata);
5271	zonediff->offline = ISC_TRUE;
5272	return (result);
5273}
5274
5275static void
5276set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
5277{
5278	unsigned int delta;
5279	char timebuf[80];
5280
5281	zone->key_expiry = when;
5282	if (when <= now) {
5283		dns_zone_log(zone, ISC_LOG_ERROR,
5284			     "DNSKEY RRSIG(s) have expired");
5285		isc_time_settoepoch(&zone->keywarntime);
5286	} else if (when < now + 7 * 24 * 3600) {
5287		isc_time_t t;
5288		isc_time_set(&t, when, 0);
5289		isc_time_formattimestamp(&t, timebuf, 80);
5290		dns_zone_log(zone, ISC_LOG_WARNING,
5291			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
5292			     timebuf);
5293		delta = when - now;
5294		delta--;		/* loop prevention */
5295		delta /= 24 * 3600;	/* to whole days */
5296		delta *= 24 * 3600;	/* to seconds */
5297		isc_time_set(&zone->keywarntime, when - delta, 0);
5298	}  else {
5299		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
5300		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
5301		dns_zone_log(zone, ISC_LOG_NOTICE,
5302			     "setting keywarntime to %s", timebuf);
5303	}
5304}
5305
5306/*
5307 * Helper function to del_sigs(). We don't want to delete RRSIGs that
5308 * have no new key.
5309 */
5310static isc_boolean_t
5311delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
5312	  isc_boolean_t *warn)
5313{
5314	unsigned int i = 0;
5315	isc_boolean_t have_ksk = ISC_FALSE, have_zsk = ISC_FALSE;
5316	isc_boolean_t have_pksk = ISC_FALSE, have_pzsk = ISC_FALSE;
5317
5318	for (i = 0; i < nkeys; i++) {
5319		if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
5320			continue;
5321		if (dst_key_isprivate(keys[i])) {
5322			if (KSK(keys[i]))
5323				have_ksk = have_pksk = ISC_TRUE;
5324			else
5325				have_zsk = have_pzsk = ISC_TRUE;
5326		} else {
5327			if (KSK(keys[i]))
5328				have_ksk = ISC_TRUE;
5329			else
5330				have_zsk = ISC_TRUE;
5331		}
5332	}
5333
5334	if (have_zsk && have_ksk && !have_pzsk)
5335		*warn = ISC_TRUE;
5336
5337	/*
5338	 * It's okay to delete a signature if there is an active key
5339	 * with the same algorithm to replace it.
5340	 */
5341	if (have_pksk || have_pzsk)
5342		return (ISC_TRUE);
5343
5344	/*
5345	 * Failing that, it is *not* okay to delete a signature
5346	 * if the associated public key is still in the DNSKEY RRset
5347	 */
5348	for (i = 0; i < nkeys; i++) {
5349		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
5350		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
5351			return (ISC_FALSE);
5352	}
5353
5354	/*
5355	 * But if the key is gone, then go ahead.
5356	 */
5357	return (ISC_TRUE);
5358}
5359
5360/*
5361 * Delete expired RRsigs and any RRsigs we are about to re-sign.
5362 * See also update.c:del_keysigs().
5363 */
5364static isc_result_t
5365del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5366	 dns_rdatatype_t type, zonediff_t *zonediff, dst_key_t **keys,
5367	 unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
5368{
5369	isc_result_t result;
5370	dns_dbnode_t *node = NULL;
5371	dns_rdataset_t rdataset;
5372	unsigned int i;
5373	dns_rdata_rrsig_t rrsig;
5374	isc_boolean_t found, changed;
5375	isc_int64_t warn = 0, maybe = 0;
5376
5377	dns_rdataset_init(&rdataset);
5378
5379	if (type == dns_rdatatype_nsec3)
5380		result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5381	else
5382		result = dns_db_findnode(db, name, ISC_FALSE, &node);
5383	if (result == ISC_R_NOTFOUND)
5384		return (ISC_R_SUCCESS);
5385	if (result != ISC_R_SUCCESS)
5386		goto failure;
5387	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
5388				     (isc_stdtime_t) 0, &rdataset, NULL);
5389	dns_db_detachnode(db, &node);
5390
5391	if (result == ISC_R_NOTFOUND) {
5392		INSIST(!dns_rdataset_isassociated(&rdataset));
5393		return (ISC_R_SUCCESS);
5394	}
5395	if (result != ISC_R_SUCCESS) {
5396		INSIST(!dns_rdataset_isassociated(&rdataset));
5397		goto failure;
5398	}
5399
5400	changed = ISC_FALSE;
5401	for (result = dns_rdataset_first(&rdataset);
5402	     result == ISC_R_SUCCESS;
5403	     result = dns_rdataset_next(&rdataset)) {
5404		dns_rdata_t rdata = DNS_RDATA_INIT;
5405
5406		dns_rdataset_current(&rdataset, &rdata);
5407		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5408		RUNTIME_CHECK(result == ISC_R_SUCCESS);
5409
5410		if (type != dns_rdatatype_dnskey) {
5411			isc_boolean_t warn = ISC_FALSE, deleted = ISC_FALSE;
5412			if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
5413				result = update_one_rr(db, ver, zonediff->diff,
5414					       DNS_DIFFOP_DELRESIGN, name,
5415					       rdataset.ttl, &rdata);
5416				if (incremental)
5417					changed = ISC_TRUE;
5418				if (result != ISC_R_SUCCESS)
5419					break;
5420				deleted = ISC_TRUE;
5421			}
5422			if (warn) {
5423				/*
5424				 * At this point, we've got an RRSIG,
5425				 * which is signed by an inactive key.
5426				 * An administrator needs to provide a new
5427				 * key/alg, but until that time, we want to
5428				 * keep the old RRSIG.  Marking the key as
5429				 * offline will prevent us spinning waiting
5430				 * for the private part.
5431				 */
5432				if (incremental && !deleted) {
5433					result = offline(db, ver, zonediff,
5434							 name, rdataset.ttl,
5435							 &rdata);
5436					changed = ISC_TRUE;
5437					if (result != ISC_R_SUCCESS)
5438						break;
5439				}
5440
5441				/*
5442				 * Log the key id and algorithm of
5443				 * the inactive key with no replacement
5444				 */
5445				if (zone->log_key_expired_timer <= now) {
5446					char origin[DNS_NAME_FORMATSIZE];
5447					char algbuf[DNS_NAME_FORMATSIZE];
5448					dns_name_format(&zone->origin, origin,
5449							sizeof(origin));
5450					dns_secalg_format(rrsig.algorithm,
5451							  algbuf,
5452							  sizeof(algbuf));
5453					dns_zone_log(zone, ISC_LOG_WARNING,
5454						     "Key %s/%s/%d "
5455						     "missing or inactive "
5456						     "and has no replacement: "
5457						     "retaining signatures.",
5458						     origin, algbuf,
5459						     rrsig.keyid);
5460					zone->log_key_expired_timer = now +
5461									3600;
5462				}
5463			}
5464			continue;
5465		}
5466
5467		/*
5468		 * RRSIG(DNSKEY) requires special processing.
5469		 */
5470		found = ISC_FALSE;
5471		for (i = 0; i < nkeys; i++) {
5472			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
5473			    rrsig.keyid == dst_key_id(keys[i])) {
5474				found = ISC_TRUE;
5475				/*
5476				 * Mark offline RRSIG(DNSKEY).
5477				 * We want the earliest offline expire time
5478				 * iff there is a new offline signature.
5479				 */
5480				if (!dst_key_inactive(keys[i]) &&
5481				    !dst_key_isprivate(keys[i]))
5482				{
5483					isc_int64_t timeexpire =
5484					   dns_time64_from32(rrsig.timeexpire);
5485					if (warn != 0 && warn > timeexpire)
5486						warn = timeexpire;
5487					if (rdata.flags & DNS_RDATA_OFFLINE) {
5488						if (maybe == 0 ||
5489						    maybe > timeexpire)
5490							maybe = timeexpire;
5491						break;
5492					}
5493					if (warn == 0)
5494						warn = maybe;
5495					if (warn == 0 || warn > timeexpire)
5496						warn = timeexpire;
5497					result = offline(db, ver, zonediff,
5498							 name, rdataset.ttl,
5499							 &rdata);
5500					changed = ISC_TRUE;
5501					break;
5502				}
5503				result = update_one_rr(db, ver, zonediff->diff,
5504						       DNS_DIFFOP_DELRESIGN,
5505						       name, rdataset.ttl,
5506						       &rdata);
5507				break;
5508			}
5509		}
5510
5511		/*
5512		 * If there is not a matching DNSKEY then
5513		 * delete the RRSIG.
5514		 */
5515		if (!found)
5516			result = update_one_rr(db, ver, zonediff->diff,
5517					       DNS_DIFFOP_DELRESIGN, name,
5518					       rdataset.ttl, &rdata);
5519		if (result != ISC_R_SUCCESS)
5520			break;
5521	}
5522
5523	if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0)
5524		dns_db_resigned(db, &rdataset, ver);
5525
5526	dns_rdataset_disassociate(&rdataset);
5527	if (result == ISC_R_NOMORE)
5528		result = ISC_R_SUCCESS;
5529	if (warn > 0) {
5530#if defined(STDTIME_ON_32BITS)
5531		isc_stdtime_t stdwarn = (isc_stdtime_t)warn;
5532		if (warn == stdwarn)
5533#endif
5534			set_key_expiry_warning(zone, (isc_stdtime_t)warn, now);
5535#if defined(STDTIME_ON_32BITS)
5536		else
5537			dns_zone_log(zone, ISC_LOG_ERROR,
5538				     "key expiry warning time out of range");
5539#endif
5540	}
5541 failure:
5542	if (node != NULL)
5543		dns_db_detachnode(db, &node);
5544	return (result);
5545}
5546
5547static isc_result_t
5548add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5549	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
5550	 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
5551	 isc_stdtime_t expire, isc_boolean_t check_ksk,
5552	 isc_boolean_t keyset_kskonly)
5553{
5554	isc_result_t result;
5555	dns_dbnode_t *node = NULL;
5556	dns_rdataset_t rdataset;
5557	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
5558	unsigned char data[1024]; /* XXX */
5559	isc_buffer_t buffer;
5560	unsigned int i, j;
5561
5562	dns_rdataset_init(&rdataset);
5563	isc_buffer_init(&buffer, data, sizeof(data));
5564
5565	if (type == dns_rdatatype_nsec3)
5566		result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5567	else
5568		result = dns_db_findnode(db, name, ISC_FALSE, &node);
5569	if (result == ISC_R_NOTFOUND)
5570		return (ISC_R_SUCCESS);
5571	if (result != ISC_R_SUCCESS)
5572		goto failure;
5573	result = dns_db_findrdataset(db, node, ver, type, 0,
5574				     (isc_stdtime_t) 0, &rdataset, NULL);
5575	dns_db_detachnode(db, &node);
5576	if (result == ISC_R_NOTFOUND) {
5577		INSIST(!dns_rdataset_isassociated(&rdataset));
5578		return (ISC_R_SUCCESS);
5579	}
5580	if (result != ISC_R_SUCCESS) {
5581		INSIST(!dns_rdataset_isassociated(&rdataset));
5582		goto failure;
5583	}
5584
5585	for (i = 0; i < nkeys; i++) {
5586		isc_boolean_t both = ISC_FALSE;
5587
5588		if (!dst_key_isprivate(keys[i]))
5589			continue;
5590
5591		if (check_ksk && !REVOKE(keys[i])) {
5592			isc_boolean_t have_ksk, have_nonksk;
5593			if (KSK(keys[i])) {
5594				have_ksk = ISC_TRUE;
5595				have_nonksk = ISC_FALSE;
5596			} else {
5597				have_ksk = ISC_FALSE;
5598				have_nonksk = ISC_TRUE;
5599			}
5600			for (j = 0; j < nkeys; j++) {
5601				if (j == i || ALG(keys[i]) != ALG(keys[j]))
5602					continue;
5603				if (REVOKE(keys[j]))
5604					continue;
5605				if (KSK(keys[j]))
5606					have_ksk = ISC_TRUE;
5607				else
5608					have_nonksk = ISC_TRUE;
5609				both = have_ksk && have_nonksk;
5610				if (both)
5611					break;
5612			}
5613		}
5614		if (both) {
5615			if (type == dns_rdatatype_dnskey) {
5616				if (!KSK(keys[i]) && keyset_kskonly)
5617					continue;
5618			} else if (KSK(keys[i]))
5619				continue;
5620		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
5621				continue;
5622
5623		/* Calculate the signature, creating a RRSIG RDATA. */
5624		isc_buffer_clear(&buffer);
5625		CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
5626				      &inception, &expire,
5627				      mctx, &buffer, &sig_rdata));
5628		/* Update the database and journal with the RRSIG. */
5629		/* XXX inefficient - will cause dataset merging */
5630		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
5631				    name, rdataset.ttl, &sig_rdata));
5632		dns_rdata_reset(&sig_rdata);
5633		isc_buffer_init(&buffer, data, sizeof(data));
5634	}
5635
5636 failure:
5637	if (dns_rdataset_isassociated(&rdataset))
5638		dns_rdataset_disassociate(&rdataset);
5639	if (node != NULL)
5640		dns_db_detachnode(db, &node);
5641	return (result);
5642}
5643
5644static void
5645zone_resigninc(dns_zone_t *zone) {
5646	const char *me = "zone_resigninc";
5647	dns_db_t *db = NULL;
5648	dns_dbversion_t *version = NULL;
5649	dns_diff_t _sig_diff;
5650	zonediff_t zonediff;
5651	dns_fixedname_t fixed;
5652	dns_name_t *name;
5653	dns_rdataset_t rdataset;
5654	dns_rdatatype_t covers;
5655	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
5656	isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
5657	isc_result_t result;
5658	isc_stdtime_t now, inception, soaexpire, expire, stop;
5659	isc_uint32_t jitter;
5660	unsigned int i;
5661	unsigned int nkeys = 0;
5662	unsigned int resign;
5663
5664	ENTER;
5665
5666	dns_rdataset_init(&rdataset);
5667	dns_fixedname_init(&fixed);
5668	dns_diff_init(zone->mctx, &_sig_diff);
5669	zonediff_init(&zonediff, &_sig_diff);
5670
5671	/*
5672	 * Zone is frozen or automatic resigning is disabled.
5673	 * Pause for 5 minutes.
5674	 */
5675	if (zone->update_disabled ||
5676	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
5677	{
5678		result = ISC_R_FAILURE;
5679		goto failure;
5680	}
5681
5682	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5683	dns_db_attach(zone->db, &db);
5684	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5685
5686	result = dns_db_newversion(db, &version);
5687	if (result != ISC_R_SUCCESS) {
5688		dns_zone_log(zone, ISC_LOG_ERROR,
5689			     "zone_resigninc:dns_db_newversion -> %s",
5690			     dns_result_totext(result));
5691		goto failure;
5692	}
5693
5694	result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
5695				zone_keys, &nkeys);
5696	if (result != ISC_R_SUCCESS) {
5697		dns_zone_log(zone, ISC_LOG_ERROR,
5698			     "zone_resigninc:find_zone_keys -> %s",
5699			     dns_result_totext(result));
5700		goto failure;
5701	}
5702
5703	isc_stdtime_get(&now);
5704	inception = now - 3600;	/* Allow for clock skew. */
5705	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5706	/*
5707	 * Spread out signatures over time if they happen to be
5708	 * clumped.  We don't do this for each add_sigs() call as
5709	 * we still want some clustering to occur.
5710	 */
5711	isc_random_get(&jitter);
5712	expire = soaexpire - jitter % 3600;
5713	stop = now + 5;
5714
5715	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5716	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5717
5718	name = dns_fixedname_name(&fixed);
5719	result = dns_db_getsigningtime(db, &rdataset, name);
5720	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
5721		dns_zone_log(zone, ISC_LOG_ERROR,
5722			     "zone_resigninc:dns_db_getsigningtime -> %s",
5723			     dns_result_totext(result));
5724	}
5725
5726	i = 0;
5727	while (result == ISC_R_SUCCESS) {
5728		resign = rdataset.resign - zone->sigresigninginterval;
5729		covers = rdataset.covers;
5730		dns_rdataset_disassociate(&rdataset);
5731
5732		/*
5733		 * Stop if we hit the SOA as that means we have walked the
5734		 * entire zone.  The SOA record should always be the most
5735		 * recent signature.
5736		 */
5737		/* XXXMPA increase number of RRsets signed pre call */
5738		if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
5739		    resign > stop)
5740			break;
5741
5742		result = del_sigs(zone, db, version, name, covers, &zonediff,
5743				  zone_keys, nkeys, now, ISC_TRUE);
5744		if (result != ISC_R_SUCCESS) {
5745			dns_zone_log(zone, ISC_LOG_ERROR,
5746				     "zone_resigninc:del_sigs -> %s",
5747				     dns_result_totext(result));
5748			break;
5749		}
5750
5751		result = add_sigs(db, version, name, covers, zonediff.diff,
5752				  zone_keys, nkeys, zone->mctx, inception,
5753				  expire, check_ksk, keyset_kskonly);
5754		if (result != ISC_R_SUCCESS) {
5755			dns_zone_log(zone, ISC_LOG_ERROR,
5756				     "zone_resigninc:add_sigs -> %s",
5757				     dns_result_totext(result));
5758			break;
5759		}
5760		result	= dns_db_getsigningtime(db, &rdataset,
5761						dns_fixedname_name(&fixed));
5762		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
5763			result = ISC_R_SUCCESS;
5764			break;
5765		}
5766		if (result != ISC_R_SUCCESS)
5767			dns_zone_log(zone, ISC_LOG_ERROR,
5768			     "zone_resigninc:dns_db_getsigningtime -> %s",
5769				     dns_result_totext(result));
5770	}
5771
5772	if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
5773		goto failure;
5774
5775	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5776			  &zonediff, zone_keys, nkeys, now, ISC_TRUE);
5777	if (result != ISC_R_SUCCESS) {
5778		dns_zone_log(zone, ISC_LOG_ERROR,
5779			     "zone_resigninc:del_sigs -> %s",
5780			     dns_result_totext(result));
5781		goto failure;
5782	}
5783
5784	/*
5785	 * Did we change anything in the zone?
5786	 */
5787	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
5788		/*
5789		 * Commit the changes if any key has been marked as offline.			 */
5790		if (zonediff.offline)
5791			dns_db_closeversion(db, &version, ISC_TRUE);
5792		goto failure;
5793	}
5794
5795	/* Increment SOA serial if we have made changes */
5796	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
5797				   zone->updatemethod);
5798	if (result != ISC_R_SUCCESS) {
5799		dns_zone_log(zone, ISC_LOG_ERROR,
5800			     "zone_resigninc:update_soa_serial -> %s",
5801			     dns_result_totext(result));
5802		goto failure;
5803	}
5804
5805	/*
5806	 * Generate maximum life time signatures so that the above loop
5807	 * termination is sensible.
5808	 */
5809	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5810			  zonediff.diff, zone_keys, nkeys, zone->mctx,
5811			  inception, soaexpire, check_ksk, keyset_kskonly);
5812	if (result != ISC_R_SUCCESS) {
5813		dns_zone_log(zone, ISC_LOG_ERROR,
5814			     "zone_resigninc:add_sigs -> %s",
5815			     dns_result_totext(result));
5816		goto failure;
5817	}
5818
5819	/* Write changes to journal file. */
5820	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
5821
5822	/* Everything has succeeded. Commit the changes. */
5823	dns_db_closeversion(db, &version, ISC_TRUE);
5824
5825 failure:
5826	dns_diff_clear(&_sig_diff);
5827	for (i = 0; i < nkeys; i++)
5828		dst_key_free(&zone_keys[i]);
5829	if (version != NULL) {
5830		dns_db_closeversion(zone->db, &version, ISC_FALSE);
5831		dns_db_detach(&db);
5832	} else if (db != NULL)
5833		dns_db_detach(&db);
5834	if (result == ISC_R_SUCCESS) {
5835		set_resigntime(zone);
5836		LOCK_ZONE(zone);
5837		zone_needdump(zone, DNS_DUMP_DELAY);
5838		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5839		UNLOCK_ZONE(zone);
5840	} else {
5841		/*
5842		 * Something failed.  Retry in 5 minutes.
5843		 */
5844		isc_interval_t ival;
5845		isc_interval_set(&ival, 300, 0);
5846		isc_time_nowplusinterval(&zone->resigntime, &ival);
5847	}
5848}
5849
5850static isc_result_t
5851next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
5852	    dns_name_t *newname, isc_boolean_t bottom)
5853{
5854	isc_result_t result;
5855	dns_dbiterator_t *dbit = NULL;
5856	dns_rdatasetiter_t *rdsit = NULL;
5857	dns_dbnode_t *node = NULL;
5858
5859	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
5860	CHECK(dns_dbiterator_seek(dbit, oldname));
5861	do {
5862		result = dns_dbiterator_next(dbit);
5863		if (result == ISC_R_NOMORE)
5864			CHECK(dns_dbiterator_first(dbit));
5865		CHECK(dns_dbiterator_current(dbit, &node, newname));
5866		if (bottom && dns_name_issubdomain(newname, oldname) &&
5867		    !dns_name_equal(newname, oldname)) {
5868			dns_db_detachnode(db, &node);
5869			continue;
5870		}
5871		/*
5872		 * Is this node empty?
5873		 */
5874		CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
5875		result = dns_rdatasetiter_first(rdsit);
5876		dns_db_detachnode(db, &node);
5877		dns_rdatasetiter_destroy(&rdsit);
5878		if (result != ISC_R_NOMORE)
5879			break;
5880	} while (1);
5881 failure:
5882	if (node != NULL)
5883		dns_db_detachnode(db, &node);
5884	if (dbit != NULL)
5885		dns_dbiterator_destroy(&dbit);
5886	return (result);
5887}
5888
5889static isc_boolean_t
5890signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5891		dns_rdatatype_t type, dst_key_t *key)
5892{
5893	isc_result_t result;
5894	dns_rdataset_t rdataset;
5895	dns_rdata_t rdata = DNS_RDATA_INIT;
5896	dns_rdata_rrsig_t rrsig;
5897
5898	dns_rdataset_init(&rdataset);
5899	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
5900				     type, 0, &rdataset, NULL);
5901	if (result != ISC_R_SUCCESS) {
5902		INSIST(!dns_rdataset_isassociated(&rdataset));
5903		return (ISC_FALSE);
5904	}
5905	for (result = dns_rdataset_first(&rdataset);
5906	     result == ISC_R_SUCCESS;
5907	     result = dns_rdataset_next(&rdataset)) {
5908		dns_rdataset_current(&rdataset, &rdata);
5909		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5910		INSIST(result == ISC_R_SUCCESS);
5911		if (rrsig.algorithm == dst_key_alg(key) &&
5912		    rrsig.keyid == dst_key_id(key)) {
5913			dns_rdataset_disassociate(&rdataset);
5914			return (ISC_TRUE);
5915		}
5916		dns_rdata_reset(&rdata);
5917	}
5918	dns_rdataset_disassociate(&rdataset);
5919	return (ISC_FALSE);
5920}
5921
5922static isc_result_t
5923add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5924	 dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
5925	 dns_diff_t *diff)
5926{
5927	dns_fixedname_t fixed;
5928	dns_name_t *next;
5929	dns_rdata_t rdata = DNS_RDATA_INIT;
5930	isc_result_t result;
5931	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
5932
5933	dns_fixedname_init(&fixed);
5934	next = dns_fixedname_name(&fixed);
5935
5936	CHECK(next_active(db, version, name, next, bottom));
5937	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
5938				  &rdata));
5939	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
5940			    &rdata));
5941 failure:
5942	return (result);
5943}
5944
5945static isc_result_t
5946sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
5947	    dns_dbversion_t *version, isc_boolean_t build_nsec3,
5948	    isc_boolean_t build_nsec, dst_key_t *key,
5949	    isc_stdtime_t inception, isc_stdtime_t expire,
5950	    unsigned int minimum, isc_boolean_t is_ksk,
5951	    isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
5952	    dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
5953{
5954	isc_result_t result;
5955	dns_rdatasetiter_t *iterator = NULL;
5956	dns_rdataset_t rdataset;
5957	dns_rdata_t rdata = DNS_RDATA_INIT;
5958	isc_buffer_t buffer;
5959	unsigned char data[1024];
5960	isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
5961		      seen_nsec3, seen_ds;
5962	isc_boolean_t bottom;
5963
5964	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5965	if (result != ISC_R_SUCCESS) {
5966		if (result == ISC_R_NOTFOUND)
5967			result = ISC_R_SUCCESS;
5968		return (result);
5969	}
5970
5971	dns_rdataset_init(&rdataset);
5972	isc_buffer_init(&buffer, data, sizeof(data));
5973	seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
5974	seen_nsec3 = seen_ds = ISC_FALSE;
5975	for (result = dns_rdatasetiter_first(iterator);
5976	     result == ISC_R_SUCCESS;
5977	     result = dns_rdatasetiter_next(iterator)) {
5978		dns_rdatasetiter_current(iterator, &rdataset);
5979		if (rdataset.type == dns_rdatatype_soa)
5980			seen_soa = ISC_TRUE;
5981		else if (rdataset.type == dns_rdatatype_ns)
5982			seen_ns = ISC_TRUE;
5983		else if (rdataset.type == dns_rdatatype_ds)
5984			seen_ds = ISC_TRUE;
5985		else if (rdataset.type == dns_rdatatype_dname)
5986			seen_dname = ISC_TRUE;
5987		else if (rdataset.type == dns_rdatatype_nsec)
5988			seen_nsec = ISC_TRUE;
5989		else if (rdataset.type == dns_rdatatype_nsec3)
5990			seen_nsec3 = ISC_TRUE;
5991		if (rdataset.type != dns_rdatatype_rrsig)
5992			seen_rr = ISC_TRUE;
5993		dns_rdataset_disassociate(&rdataset);
5994	}
5995	if (result != ISC_R_NOMORE)
5996		goto failure;
5997	if (seen_ns && !seen_soa)
5998		*delegation = ISC_TRUE;
5999	/*
6000	 * Going from insecure to NSEC3.
6001	 * Don't generate NSEC3 records for NSEC3 records.
6002	 */
6003	if (build_nsec3 && !seen_nsec3 && seen_rr) {
6004		isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
6005		CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
6006					  unsecure, diff));
6007		(*signatures)--;
6008	}
6009	/*
6010	 * Going from insecure to NSEC.
6011	 * Don't generate NSEC records for NSEC3 records.
6012	 */
6013	if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
6014		/* Build and add NSEC. */
6015		bottom = (seen_ns && !seen_soa) || seen_dname;
6016		/*
6017		 * Build a NSEC record except at the origin.
6018		 */
6019		if (!dns_name_equal(name, dns_db_origin(db))) {
6020			CHECK(add_nsec(db, version, name, node, minimum,
6021				       bottom, diff));
6022			/* Count a NSEC generation as a signature generation. */
6023			(*signatures)--;
6024		}
6025	}
6026	result = dns_rdatasetiter_first(iterator);
6027	while (result == ISC_R_SUCCESS) {
6028		dns_rdatasetiter_current(iterator, &rdataset);
6029		if (rdataset.type == dns_rdatatype_soa ||
6030		    rdataset.type == dns_rdatatype_rrsig)
6031			goto next_rdataset;
6032		if (rdataset.type == dns_rdatatype_dnskey) {
6033			if (!is_ksk && keyset_kskonly)
6034				goto next_rdataset;
6035		} else if (is_ksk)
6036			goto next_rdataset;
6037		if (*delegation &&
6038		    rdataset.type != dns_rdatatype_ds &&
6039		    rdataset.type != dns_rdatatype_nsec)
6040			goto next_rdataset;
6041		if (signed_with_key(db, node, version, rdataset.type, key))
6042			goto next_rdataset;
6043		/* Calculate the signature, creating a RRSIG RDATA. */
6044		isc_buffer_clear(&buffer);
6045		CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
6046				      &expire, mctx, &buffer, &rdata));
6047		/* Update the database and journal with the RRSIG. */
6048		/* XXX inefficient - will cause dataset merging */
6049		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
6050				    name, rdataset.ttl, &rdata));
6051		dns_rdata_reset(&rdata);
6052		(*signatures)--;
6053 next_rdataset:
6054		dns_rdataset_disassociate(&rdataset);
6055		result = dns_rdatasetiter_next(iterator);
6056	}
6057	if (result == ISC_R_NOMORE)
6058		result = ISC_R_SUCCESS;
6059	if (seen_dname)
6060		*delegation = ISC_TRUE;
6061 failure:
6062	if (dns_rdataset_isassociated(&rdataset))
6063		dns_rdataset_disassociate(&rdataset);
6064	if (iterator != NULL)
6065		dns_rdatasetiter_destroy(&iterator);
6066	return (result);
6067}
6068
6069/*
6070 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
6071 */
6072static isc_result_t
6073updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6074	     dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
6075{
6076	isc_result_t result;
6077	dns_rdataset_t rdataset;
6078	dns_dbnode_t *node = NULL;
6079
6080	CHECK(dns_db_getoriginnode(db, &node));
6081	if (update_only) {
6082		dns_rdataset_init(&rdataset);
6083		result = dns_db_findrdataset(db, node, version,
6084					     dns_rdatatype_nsec,
6085					     dns_rdatatype_none,
6086					     0, &rdataset, NULL);
6087		if (dns_rdataset_isassociated(&rdataset))
6088			dns_rdataset_disassociate(&rdataset);
6089		if (result == ISC_R_NOTFOUND)
6090			goto success;
6091		if (result != ISC_R_SUCCESS)
6092			goto failure;
6093	}
6094	CHECK(delete_nsec(db, version, node, name, diff));
6095	CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
6096 success:
6097	result = ISC_R_SUCCESS;
6098 failure:
6099	if (node != NULL)
6100		dns_db_detachnode(db, &node);
6101	return (result);
6102}
6103
6104static isc_result_t
6105updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
6106		  dns_dbversion_t *version, isc_boolean_t build_nsec3,
6107		  dns_ttl_t minimum, dns_diff_t *diff)
6108{
6109	isc_result_t result;
6110	dns_dbnode_t *node = NULL;
6111	dns_rdataset_t rdataset;
6112	dns_rdata_t rdata = DNS_RDATA_INIT;
6113	unsigned char data[5];
6114	isc_boolean_t seen_done = ISC_FALSE;
6115	isc_boolean_t have_rr = ISC_FALSE;
6116
6117	dns_rdataset_init(&rdataset);
6118	result = dns_db_getoriginnode(signing->db, &node);
6119	if (result != ISC_R_SUCCESS)
6120		goto failure;
6121
6122	result = dns_db_findrdataset(signing->db, node, version,
6123				     zone->privatetype, dns_rdatatype_none,
6124				     0, &rdataset, NULL);
6125	if (result == ISC_R_NOTFOUND) {
6126		INSIST(!dns_rdataset_isassociated(&rdataset));
6127		result = ISC_R_SUCCESS;
6128		goto failure;
6129	}
6130	if (result != ISC_R_SUCCESS) {
6131		INSIST(!dns_rdataset_isassociated(&rdataset));
6132		goto failure;
6133	}
6134	for (result = dns_rdataset_first(&rdataset);
6135	     result == ISC_R_SUCCESS;
6136	     result = dns_rdataset_next(&rdataset)) {
6137		dns_rdataset_current(&rdataset, &rdata);
6138		/*
6139		 * If we don't match the algorithm or keyid skip the record.
6140		 */
6141		if (rdata.length != 5 ||
6142		    rdata.data[0] != signing->algorithm ||
6143		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
6144		    rdata.data[2] != (signing->keyid & 0xff)) {
6145			have_rr = ISC_TRUE;
6146			dns_rdata_reset(&rdata);
6147			continue;
6148		}
6149		/*
6150		 * We have a match.  If we were signing (!signing->delete)
6151		 * and we already have a record indicating that we have
6152		 * finished signing (rdata.data[4] != 0) then keep it.
6153		 * Otherwise it needs to be deleted as we have removed all
6154		 * the signatures (signing->delete), so any record indicating
6155		 * completion is now out of date, or we have finished signing
6156		 * with the new record so we no longer need to remember that
6157		 * we need to sign the zone with the matching key across a
6158		 * nameserver re-start.
6159		 */
6160		if (!signing->delete && rdata.data[4] != 0) {
6161			seen_done = ISC_TRUE;
6162			have_rr = ISC_TRUE;
6163		} else
6164			CHECK(update_one_rr(signing->db, version, diff,
6165					    DNS_DIFFOP_DEL, &zone->origin,
6166					    rdataset.ttl, &rdata));
6167		dns_rdata_reset(&rdata);
6168	}
6169	if (result == ISC_R_NOMORE)
6170		result = ISC_R_SUCCESS;
6171	if (!signing->delete && !seen_done) {
6172		/*
6173		 * If we were signing then we need to indicate that we have
6174		 * finished signing the zone with this key.  If it is already
6175		 * there we don't need to add it a second time.
6176		 */
6177		data[0] = signing->algorithm;
6178		data[1] = (signing->keyid >> 8) & 0xff;
6179		data[2] = signing->keyid & 0xff;
6180		data[3] = 0;
6181		data[4] = 1;
6182		rdata.length = sizeof(data);
6183		rdata.data = data;
6184		rdata.type = zone->privatetype;
6185		rdata.rdclass = dns_db_class(signing->db);
6186		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
6187				    &zone->origin, rdataset.ttl, &rdata));
6188	} else if (!have_rr) {
6189		dns_name_t *origin = dns_db_origin(signing->db);
6190		/*
6191		 * Rebuild the NSEC/NSEC3 record for the origin as we no
6192		 * longer have any private records.
6193		 */
6194		if (build_nsec3)
6195			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
6196						  minimum, ISC_FALSE, diff));
6197		CHECK(updatesecure(signing->db, version, origin, minimum,
6198				   ISC_TRUE, diff));
6199	}
6200
6201 failure:
6202	if (dns_rdataset_isassociated(&rdataset))
6203		dns_rdataset_disassociate(&rdataset);
6204	if (node != NULL)
6205		dns_db_detachnode(signing->db, &node);
6206	return (result);
6207}
6208
6209/*
6210 * If 'active' is set then we are not done with the chain yet so only
6211 * delete the nsec3param record which indicates a full chain exists
6212 * (flags == 0).
6213 */
6214static isc_result_t
6215fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
6216		 isc_boolean_t active, dns_rdatatype_t privatetype,
6217		 dns_diff_t *diff)
6218{
6219	dns_dbnode_t *node = NULL;
6220	dns_name_t *name = dns_db_origin(db);
6221	dns_rdata_t rdata = DNS_RDATA_INIT;
6222	dns_rdataset_t rdataset;
6223	dns_rdata_nsec3param_t nsec3param;
6224	isc_result_t result;
6225	isc_buffer_t buffer;
6226	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
6227	dns_ttl_t ttl = 0;
6228	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
6229
6230	dns_rdataset_init(&rdataset);
6231
6232	result = dns_db_getoriginnode(db, &node);
6233	RUNTIME_CHECK(result == ISC_R_SUCCESS);
6234	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6235				     0, 0, &rdataset, NULL);
6236	if (result == ISC_R_NOTFOUND)
6237		goto try_private;
6238	if (result != ISC_R_SUCCESS)
6239		goto failure;
6240
6241	/*
6242	 * Preserve the existing ttl.
6243	 */
6244	ttl = rdataset.ttl;
6245
6246	/*
6247	 * Delete all NSEC3PARAM records which match that in nsec3chain.
6248	 */
6249	for (result = dns_rdataset_first(&rdataset);
6250	     result == ISC_R_SUCCESS;
6251	     result = dns_rdataset_next(&rdataset)) {
6252
6253		dns_rdataset_current(&rdataset, &rdata);
6254		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6255
6256		if (nsec3param.hash != chain->nsec3param.hash ||
6257		    (active && nsec3param.flags != 0) ||
6258		    nsec3param.iterations != chain->nsec3param.iterations ||
6259		    nsec3param.salt_length != chain->nsec3param.salt_length ||
6260		    memcmp(nsec3param.salt, chain->nsec3param.salt,
6261			   nsec3param.salt_length)) {
6262			dns_rdata_reset(&rdata);
6263			continue;
6264		}
6265
6266		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6267				    name, rdataset.ttl, &rdata));
6268		dns_rdata_reset(&rdata);
6269	}
6270	if (result != ISC_R_NOMORE)
6271		goto failure;
6272
6273	dns_rdataset_disassociate(&rdataset);
6274
6275 try_private:
6276
6277	if (active)
6278		goto add;
6279
6280	result = dns_nsec_nseconly(db, ver, &nseconly);
6281	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
6282
6283	/*
6284	 * Delete all private records which match that in nsec3chain.
6285	 */
6286	result = dns_db_findrdataset(db, node, ver, privatetype,
6287				     0, 0, &rdataset, NULL);
6288	if (result == ISC_R_NOTFOUND)
6289		goto add;
6290	if (result != ISC_R_SUCCESS)
6291		goto failure;
6292
6293	for (result = dns_rdataset_first(&rdataset);
6294	     result == ISC_R_SUCCESS;
6295	     result = dns_rdataset_next(&rdataset)) {
6296		dns_rdata_t private = DNS_RDATA_INIT;
6297		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
6298
6299		dns_rdataset_current(&rdataset, &private);
6300		if (!dns_nsec3param_fromprivate(&private, &rdata,
6301						buf, sizeof(buf)))
6302			continue;
6303		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6304
6305		if ((!nsec3ok &&
6306		     (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
6307		    nsec3param.hash != chain->nsec3param.hash ||
6308		    nsec3param.iterations != chain->nsec3param.iterations ||
6309		    nsec3param.salt_length != chain->nsec3param.salt_length ||
6310		    memcmp(nsec3param.salt, chain->nsec3param.salt,
6311			   nsec3param.salt_length)) {
6312			dns_rdata_reset(&rdata);
6313			continue;
6314		}
6315
6316		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6317				    name, rdataset.ttl, &private));
6318		dns_rdata_reset(&rdata);
6319	}
6320	if (result != ISC_R_NOMORE)
6321		goto failure;
6322
6323  add:
6324	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
6325		result = ISC_R_SUCCESS;
6326		goto failure;
6327	}
6328
6329	/*
6330	 * Add a NSEC3PARAM record which matches that in nsec3chain but
6331	 * with all flags bits cleared.
6332	 *
6333	 * Note: we do not clear chain->nsec3param.flags as this change
6334	 * may be reversed.
6335	 */
6336	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
6337	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
6338				   dns_rdatatype_nsec3param,
6339				   &chain->nsec3param, &buffer));
6340	rdata.data[1] = 0;	/* Clear flag bits. */
6341	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
6342
6343  failure:
6344	dns_db_detachnode(db, &node);
6345	if (dns_rdataset_isassociated(&rdataset))
6346		dns_rdataset_disassociate(&rdataset);
6347	return (result);
6348}
6349
6350static isc_result_t
6351delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6352	    dns_name_t *name, dns_diff_t *diff)
6353{
6354	dns_rdataset_t rdataset;
6355	isc_result_t result;
6356
6357	dns_rdataset_init(&rdataset);
6358
6359	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6360				     0, 0, &rdataset, NULL);
6361	if (result == ISC_R_NOTFOUND)
6362		return (ISC_R_SUCCESS);
6363	if (result != ISC_R_SUCCESS)
6364		return (result);
6365	for (result = dns_rdataset_first(&rdataset);
6366	     result == ISC_R_SUCCESS;
6367	     result = dns_rdataset_next(&rdataset)) {
6368		dns_rdata_t rdata = DNS_RDATA_INIT;
6369
6370		dns_rdataset_current(&rdataset, &rdata);
6371		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6372				    rdataset.ttl, &rdata));
6373	}
6374	if (result == ISC_R_NOMORE)
6375		result = ISC_R_SUCCESS;
6376 failure:
6377	dns_rdataset_disassociate(&rdataset);
6378	return (result);
6379}
6380
6381static isc_result_t
6382deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6383		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
6384		    dns_diff_t *diff)
6385{
6386	dns_rdataset_t rdataset;
6387	dns_rdata_nsec3_t nsec3;
6388	isc_result_t result;
6389
6390	dns_rdataset_init(&rdataset);
6391	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
6392				     0, 0, &rdataset, NULL);
6393	if (result == ISC_R_NOTFOUND)
6394		return (ISC_R_SUCCESS);
6395	if (result != ISC_R_SUCCESS)
6396		return (result);
6397
6398	for (result = dns_rdataset_first(&rdataset);
6399	     result == ISC_R_SUCCESS;
6400	     result = dns_rdataset_next(&rdataset)) {
6401		dns_rdata_t rdata = DNS_RDATA_INIT;
6402
6403		dns_rdataset_current(&rdataset, &rdata);
6404		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
6405		if (nsec3.hash != param->hash ||
6406		    nsec3.iterations != param->iterations ||
6407		    nsec3.salt_length != param->salt_length ||
6408		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
6409			continue;
6410		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6411				    rdataset.ttl, &rdata));
6412	}
6413	if (result == ISC_R_NOMORE)
6414		result = ISC_R_SUCCESS;
6415 failure:
6416	dns_rdataset_disassociate(&rdataset);
6417	return (result);
6418}
6419
6420static isc_result_t
6421need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
6422		const dns_rdata_nsec3param_t *param,
6423		isc_boolean_t *answer)
6424{
6425	dns_dbnode_t *node = NULL;
6426	dns_rdata_t rdata = DNS_RDATA_INIT;
6427	dns_rdata_nsec3param_t myparam;
6428	dns_rdataset_t rdataset;
6429	isc_result_t result;
6430
6431	*answer = ISC_FALSE;
6432
6433	result = dns_db_getoriginnode(db, &node);
6434	RUNTIME_CHECK(result == ISC_R_SUCCESS);
6435
6436	dns_rdataset_init(&rdataset);
6437
6438	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6439				     0, 0, &rdataset, NULL);
6440	if (result == ISC_R_SUCCESS) {
6441		dns_rdataset_disassociate(&rdataset);
6442		dns_db_detachnode(db, &node);
6443		return (result);
6444	}
6445	if (result != ISC_R_NOTFOUND) {
6446		dns_db_detachnode(db, &node);
6447		return (result);
6448	}
6449
6450	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6451				     0, 0, &rdataset, NULL);
6452	if (result == ISC_R_NOTFOUND) {
6453		*answer = ISC_TRUE;
6454		dns_db_detachnode(db, &node);
6455		return (ISC_R_SUCCESS);
6456	}
6457	if (result != ISC_R_SUCCESS) {
6458		dns_db_detachnode(db, &node);
6459		return (result);
6460	}
6461
6462	for (result = dns_rdataset_first(&rdataset);
6463	     result == ISC_R_SUCCESS;
6464	     result = dns_rdataset_next(&rdataset)) {
6465		dns_rdataset_current(&rdataset, &rdata);
6466		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
6467		dns_rdata_reset(&rdata);
6468		/*
6469		 * Ignore any NSEC3PARAM removals.
6470		 */
6471		if (NSEC3REMOVE(myparam.flags))
6472			continue;
6473		/*
6474		 * Ignore the chain that we are in the process of deleting.
6475		 */
6476		if (myparam.hash == param->hash &&
6477		    myparam.iterations == param->iterations &&
6478		    myparam.salt_length == param->salt_length &&
6479		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
6480			continue;
6481		/*
6482		 * Found an active NSEC3 chain.
6483		 */
6484		break;
6485	}
6486	if (result == ISC_R_NOMORE) {
6487		*answer = ISC_TRUE;
6488		result = ISC_R_SUCCESS;
6489	}
6490
6491 failure:
6492	if (dns_rdataset_isassociated(&rdataset))
6493		dns_rdataset_disassociate(&rdataset);
6494	dns_db_detachnode(db, &node);
6495	return (result);
6496}
6497
6498static isc_result_t
6499update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
6500	    dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
6501	    isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
6502	    isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
6503	    zonediff_t *zonediff)
6504{
6505	dns_difftuple_t *tuple;
6506	isc_result_t result;
6507
6508	for (tuple = ISC_LIST_HEAD(diff->tuples);
6509	     tuple != NULL;
6510	     tuple = ISC_LIST_HEAD(diff->tuples)) {
6511		result = del_sigs(zone, db, version, &tuple->name,
6512				  tuple->rdata.type, zonediff,
6513				  zone_keys, nkeys, now, ISC_FALSE);
6514		if (result != ISC_R_SUCCESS) {
6515			dns_zone_log(zone, ISC_LOG_ERROR,
6516				     "update_sigs:del_sigs -> %s",
6517				     dns_result_totext(result));
6518			return (result);
6519		}
6520		result = add_sigs(db, version, &tuple->name,
6521				  tuple->rdata.type, zonediff->diff,
6522				  zone_keys, nkeys, zone->mctx, inception,
6523				  expire, check_ksk, keyset_kskonly);
6524		if (result != ISC_R_SUCCESS) {
6525			dns_zone_log(zone, ISC_LOG_ERROR,
6526				     "update_sigs:add_sigs -> %s",
6527				     dns_result_totext(result));
6528			return (result);
6529		}
6530
6531		do {
6532			dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
6533			while (next != NULL &&
6534			       (tuple->rdata.type != next->rdata.type ||
6535				!dns_name_equal(&tuple->name, &next->name)))
6536				next = ISC_LIST_NEXT(next, link);
6537			ISC_LIST_UNLINK(diff->tuples, tuple, link);
6538			dns_diff_appendminimal(zonediff->diff, &tuple);
6539			INSIST(tuple == NULL);
6540			tuple = next;
6541		} while (tuple != NULL);
6542	}
6543	return (ISC_R_SUCCESS);
6544}
6545
6546/*
6547 * Incrementally build and sign a new NSEC3 chain using the parameters
6548 * requested.
6549 */
6550static void
6551zone_nsec3chain(dns_zone_t *zone) {
6552	const char *me = "zone_nsec3chain";
6553	dns_db_t *db = NULL;
6554	dns_dbnode_t *node = NULL;
6555	dns_dbversion_t *version = NULL;
6556	dns_diff_t _sig_diff;
6557	dns_diff_t nsec_diff;
6558	dns_diff_t nsec3_diff;
6559	dns_diff_t param_diff;
6560	zonediff_t zonediff;
6561	dns_fixedname_t fixed;
6562	dns_fixedname_t nextfixed;
6563	dns_name_t *name, *nextname;
6564	dns_rdataset_t rdataset;
6565	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
6566	dns_nsec3chainlist_t cleanup;
6567	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6568	isc_int32_t signatures;
6569	isc_boolean_t check_ksk, keyset_kskonly;
6570	isc_boolean_t delegation;
6571	isc_boolean_t first;
6572	isc_result_t result;
6573	isc_stdtime_t now, inception, soaexpire, expire;
6574	isc_uint32_t jitter;
6575	unsigned int i;
6576	unsigned int nkeys = 0;
6577	isc_uint32_t nodes;
6578	isc_boolean_t unsecure = ISC_FALSE;
6579	isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
6580	isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
6581	dns_rdatasetiter_t *iterator = NULL;
6582	isc_boolean_t buildnsecchain;
6583	isc_boolean_t updatensec = ISC_FALSE;
6584	dns_rdatatype_t privatetype = zone->privatetype;
6585
6586	ENTER;
6587
6588	dns_rdataset_init(&rdataset);
6589	dns_fixedname_init(&fixed);
6590	name = dns_fixedname_name(&fixed);
6591	dns_fixedname_init(&nextfixed);
6592	nextname = dns_fixedname_name(&nextfixed);
6593	dns_diff_init(zone->mctx, &param_diff);
6594	dns_diff_init(zone->mctx, &nsec3_diff);
6595	dns_diff_init(zone->mctx, &nsec_diff);
6596	dns_diff_init(zone->mctx, &_sig_diff);
6597	zonediff_init(&zonediff, &_sig_diff);
6598	ISC_LIST_INIT(cleanup);
6599
6600	/*
6601	 * Updates are disabled.  Pause for 5 minutes.
6602	 */
6603	if (zone->update_disabled) {
6604		result = ISC_R_FAILURE;
6605		goto failure;
6606	}
6607
6608	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6609	dns_db_attach(zone->db, &db);
6610	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6611
6612	result = dns_db_newversion(db, &version);
6613	if (result != ISC_R_SUCCESS) {
6614		dns_zone_log(zone, ISC_LOG_ERROR,
6615			     "zone_nsec3chain:dns_db_newversion -> %s",
6616			     dns_result_totext(result));
6617		goto failure;
6618	}
6619
6620	result = find_zone_keys(zone, db, version, zone->mctx,
6621				DNS_MAXZONEKEYS, zone_keys, &nkeys);
6622	if (result != ISC_R_SUCCESS) {
6623		dns_zone_log(zone, ISC_LOG_ERROR,
6624			     "zone_nsec3chain:find_zone_keys -> %s",
6625			     dns_result_totext(result));
6626		goto failure;
6627	}
6628
6629	isc_stdtime_get(&now);
6630	inception = now - 3600;	/* Allow for clock skew. */
6631	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6632
6633	/*
6634	 * Spread out signatures over time if they happen to be
6635	 * clumped.  We don't do this for each add_sigs() call as
6636	 * we still want some clustering to occur.
6637	 */
6638	isc_random_get(&jitter);
6639	expire = soaexpire - jitter % 3600;
6640
6641	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6642	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6643
6644	/*
6645	 * We keep pulling nodes off each iterator in turn until
6646	 * we have no more nodes to pull off or we reach the limits
6647	 * for this quantum.
6648	 */
6649	nodes = zone->nodes;
6650	signatures = zone->signatures;
6651	LOCK_ZONE(zone);
6652	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6653	UNLOCK_ZONE(zone);
6654	first = ISC_TRUE;
6655
6656	if (nsec3chain != NULL)
6657		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6658	/*
6659	 * Generate new NSEC3 chains first.
6660	 */
6661	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6662		LOCK_ZONE(zone);
6663		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6664
6665		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6666		if (nsec3chain->done || nsec3chain->db != zone->db) {
6667			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
6668			ISC_LIST_APPEND(cleanup, nsec3chain, link);
6669		}
6670		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6671		UNLOCK_ZONE(zone);
6672		if (ISC_LIST_TAIL(cleanup) == nsec3chain)
6673			goto next_addchain;
6674
6675		/*
6676		 * Possible future db.
6677		 */
6678		if (nsec3chain->db != db) {
6679			goto next_addchain;
6680		}
6681
6682		if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
6683			goto next_addchain;
6684
6685		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6686
6687		if (nsec3chain->delete_nsec) {
6688			delegation = ISC_FALSE;
6689			dns_dbiterator_pause(nsec3chain->dbiterator);
6690			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
6691			goto next_addnode;
6692		}
6693		/*
6694		 * On the first pass we need to check if the current node
6695		 * has not been obscured.
6696		 */
6697		delegation = ISC_FALSE;
6698		unsecure = ISC_FALSE;
6699		if (first) {
6700			dns_fixedname_t ffound;
6701			dns_name_t *found;
6702			dns_fixedname_init(&ffound);
6703			found = dns_fixedname_name(&ffound);
6704			result = dns_db_find(db, name, version,
6705					     dns_rdatatype_soa,
6706					     DNS_DBFIND_NOWILD, 0, NULL, found,
6707					     NULL, NULL);
6708			if ((result == DNS_R_DELEGATION ||
6709			    result == DNS_R_DNAME) &&
6710			    !dns_name_equal(name, found)) {
6711				/*
6712				 * Remember the obscuring name so that
6713				 * we skip all obscured names.
6714				 */
6715				dns_name_copy(found, name, NULL);
6716				delegation = ISC_TRUE;
6717				goto next_addnode;
6718			}
6719		}
6720
6721		/*
6722		 * Check to see if this is a bottom of zone node.
6723		 */
6724		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6725		if (result == ISC_R_NOTFOUND)	/* Empty node? */
6726			goto next_addnode;
6727		if (result != ISC_R_SUCCESS)
6728			goto failure;
6729
6730		seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
6731			ISC_FALSE;
6732		for (result = dns_rdatasetiter_first(iterator);
6733		     result == ISC_R_SUCCESS;
6734		     result = dns_rdatasetiter_next(iterator)) {
6735			dns_rdatasetiter_current(iterator, &rdataset);
6736			INSIST(rdataset.type != dns_rdatatype_nsec3);
6737			if (rdataset.type == dns_rdatatype_soa)
6738				seen_soa = ISC_TRUE;
6739			else if (rdataset.type == dns_rdatatype_ns)
6740				seen_ns = ISC_TRUE;
6741			else if (rdataset.type == dns_rdatatype_dname)
6742				seen_dname = ISC_TRUE;
6743			else if (rdataset.type == dns_rdatatype_ds)
6744				seen_ds = ISC_TRUE;
6745			else if (rdataset.type == dns_rdatatype_nsec)
6746				seen_nsec = ISC_TRUE;
6747			dns_rdataset_disassociate(&rdataset);
6748		}
6749		dns_rdatasetiter_destroy(&iterator);
6750		/*
6751		 * Is there a NSEC chain than needs to be cleaned up?
6752		 */
6753		if (seen_nsec)
6754			nsec3chain->seen_nsec = ISC_TRUE;
6755		if (seen_ns && !seen_soa && !seen_ds)
6756			unsecure = ISC_TRUE;
6757		if ((seen_ns && !seen_soa) || seen_dname)
6758			delegation = ISC_TRUE;
6759
6760		/*
6761		 * Process one node.
6762		 */
6763		dns_dbiterator_pause(nsec3chain->dbiterator);
6764		result = dns_nsec3_addnsec3(db, version, name,
6765					    &nsec3chain->nsec3param,
6766					    zone->minimum, unsecure,
6767					    &nsec3_diff);
6768		if (result != ISC_R_SUCCESS) {
6769			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6770				     "dns_nsec3_addnsec3 -> %s",
6771				     dns_result_totext(result));
6772			goto failure;
6773		}
6774
6775		/*
6776		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
6777		 * two signatures.  Additionally there will, in general, be
6778		 * two signature generated below.
6779		 *
6780		 * If we are only changing the optout flag the cost is half
6781		 * that of the cost of generating a completely new chain.
6782		 */
6783		signatures -= 4;
6784
6785		/*
6786		 * Go onto next node.
6787		 */
6788 next_addnode:
6789		first = ISC_FALSE;
6790		dns_db_detachnode(db, &node);
6791		do {
6792			result = dns_dbiterator_next(nsec3chain->dbiterator);
6793
6794			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
6795				dns_dbiterator_pause(nsec3chain->dbiterator);
6796				CHECK(fixup_nsec3param(db, version, nsec3chain,
6797						       ISC_FALSE, privatetype,
6798						       &param_diff));
6799				LOCK_ZONE(zone);
6800				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6801						link);
6802				UNLOCK_ZONE(zone);
6803				ISC_LIST_APPEND(cleanup, nsec3chain, link);
6804				goto next_addchain;
6805			}
6806			if (result == ISC_R_NOMORE) {
6807				dns_dbiterator_pause(nsec3chain->dbiterator);
6808				if (nsec3chain->seen_nsec) {
6809					CHECK(fixup_nsec3param(db, version,
6810							       nsec3chain,
6811							       ISC_TRUE,
6812							       privatetype,
6813							       &param_diff));
6814					nsec3chain->delete_nsec = ISC_TRUE;
6815					goto same_addchain;
6816				}
6817				CHECK(fixup_nsec3param(db, version, nsec3chain,
6818						       ISC_FALSE, privatetype,
6819						       &param_diff));
6820				LOCK_ZONE(zone);
6821				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6822						link);
6823				UNLOCK_ZONE(zone);
6824				ISC_LIST_APPEND(cleanup, nsec3chain, link);
6825				goto next_addchain;
6826			} else if (result != ISC_R_SUCCESS) {
6827				dns_zone_log(zone, ISC_LOG_ERROR,
6828					     "zone_nsec3chain:"
6829					     "dns_dbiterator_next -> %s",
6830					     dns_result_totext(result));
6831				goto failure;
6832			} else if (delegation) {
6833				dns_dbiterator_current(nsec3chain->dbiterator,
6834						       &node, nextname);
6835				dns_db_detachnode(db, &node);
6836				if (!dns_name_issubdomain(nextname, name))
6837					break;
6838			} else
6839				break;
6840		} while (1);
6841		continue;
6842
6843 same_addchain:
6844		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6845		first = ISC_TRUE;
6846		continue;
6847
6848 next_addchain:
6849		dns_dbiterator_pause(nsec3chain->dbiterator);
6850		nsec3chain = nextnsec3chain;
6851		first = ISC_TRUE;
6852		if (nsec3chain != NULL)
6853			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6854	}
6855
6856	/*
6857	 * Process removals.
6858	 */
6859	LOCK_ZONE(zone);
6860	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6861	UNLOCK_ZONE(zone);
6862	first = ISC_TRUE;
6863	buildnsecchain = ISC_FALSE;
6864	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6865		LOCK_ZONE(zone);
6866		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6867		UNLOCK_ZONE(zone);
6868
6869		if (nsec3chain->db != db)
6870			goto next_removechain;
6871
6872		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
6873			goto next_removechain;
6874
6875		/*
6876		 * Work out if we need to build a NSEC chain as a consequence
6877		 * of removing this NSEC3 chain.
6878		 */
6879		if (first && !updatensec &&
6880		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
6881		{
6882			result = need_nsec_chain(db, version,
6883						 &nsec3chain->nsec3param,
6884						 &buildnsecchain);
6885			if (result != ISC_R_SUCCESS) {
6886				dns_zone_log(zone, ISC_LOG_ERROR,
6887					     "zone_nsec3chain:"
6888					     "need_nsec_chain -> %s",
6889					     dns_result_totext(result));
6890				goto failure;
6891			}
6892		}
6893
6894		if (first)
6895			dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
6896				     "buildnsecchain = %u\n", buildnsecchain);
6897
6898		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6899		delegation = ISC_FALSE;
6900
6901		if (!buildnsecchain) {
6902			/*
6903			 * Delete the NSECPARAM record that matches this chain.
6904			 */
6905			if (first) {
6906				result = fixup_nsec3param(db, version,
6907							  nsec3chain,
6908							  ISC_TRUE, privatetype,
6909							  &param_diff);
6910				if (result != ISC_R_SUCCESS) {
6911					dns_zone_log(zone, ISC_LOG_ERROR,
6912						     "zone_nsec3chain:"
6913						     "fixup_nsec3param -> %s",
6914						     dns_result_totext(result));
6915					goto failure;
6916				}
6917			}
6918
6919			/*
6920			 *  Delete the NSEC3 records.
6921			 */
6922			result = deletematchingnsec3(db, version, node, name,
6923						     &nsec3chain->nsec3param,
6924						     &nsec3_diff);
6925			if (result != ISC_R_SUCCESS) {
6926				dns_zone_log(zone, ISC_LOG_ERROR,
6927					     "zone_nsec3chain:"
6928					     "deletematchingnsec3 -> %s",
6929					     dns_result_totext(result));
6930				goto failure;
6931			}
6932			goto next_removenode;
6933		}
6934
6935		if (first) {
6936			dns_fixedname_t ffound;
6937			dns_name_t *found;
6938			dns_fixedname_init(&ffound);
6939			found = dns_fixedname_name(&ffound);
6940			result = dns_db_find(db, name, version,
6941					     dns_rdatatype_soa,
6942					     DNS_DBFIND_NOWILD, 0, NULL, found,
6943					     NULL, NULL);
6944			if ((result == DNS_R_DELEGATION ||
6945			     result == DNS_R_DNAME) &&
6946			    !dns_name_equal(name, found)) {
6947				/*
6948				 * Remember the obscuring name so that
6949				 * we skip all obscured names.
6950				 */
6951				dns_name_copy(found, name, NULL);
6952				delegation = ISC_TRUE;
6953				goto next_removenode;
6954			}
6955		}
6956
6957		/*
6958		 * Check to see if this is a bottom of zone node.
6959		 */
6960		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6961		if (result == ISC_R_NOTFOUND)	/* Empty node? */
6962			goto next_removenode;
6963		if (result != ISC_R_SUCCESS)
6964			goto failure;
6965
6966		seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
6967			seen_rr = ISC_FALSE;
6968		for (result = dns_rdatasetiter_first(iterator);
6969		     result == ISC_R_SUCCESS;
6970		     result = dns_rdatasetiter_next(iterator)) {
6971			dns_rdatasetiter_current(iterator, &rdataset);
6972			if (rdataset.type == dns_rdatatype_soa)
6973				seen_soa = ISC_TRUE;
6974			else if (rdataset.type == dns_rdatatype_ns)
6975				seen_ns = ISC_TRUE;
6976			else if (rdataset.type == dns_rdatatype_dname)
6977				seen_dname = ISC_TRUE;
6978			else if (rdataset.type == dns_rdatatype_nsec)
6979				seen_nsec = ISC_TRUE;
6980			else if (rdataset.type == dns_rdatatype_nsec3)
6981				seen_nsec3 = ISC_TRUE;
6982			if (rdataset.type != dns_rdatatype_rrsig)
6983				seen_rr = ISC_TRUE;
6984			dns_rdataset_disassociate(&rdataset);
6985		}
6986		dns_rdatasetiter_destroy(&iterator);
6987
6988		if (!seen_rr || seen_nsec3 || seen_nsec)
6989			goto next_removenode;
6990		if ((seen_ns && !seen_soa) || seen_dname)
6991			delegation = ISC_TRUE;
6992
6993		/*
6994		 * Add a NSEC record except at the origin.
6995		 */
6996		if (!dns_name_equal(name, dns_db_origin(db))) {
6997			dns_dbiterator_pause(nsec3chain->dbiterator);
6998			CHECK(add_nsec(db, version, name, node, zone->minimum,
6999				       delegation, &nsec_diff));
7000		}
7001
7002 next_removenode:
7003		first = ISC_FALSE;
7004		dns_db_detachnode(db, &node);
7005		do {
7006			result = dns_dbiterator_next(nsec3chain->dbiterator);
7007			if (result == ISC_R_NOMORE && buildnsecchain) {
7008				/*
7009				 * The NSEC chain should now be built.
7010				 * We can now remove the NSEC3 chain.
7011				 */
7012				updatensec = ISC_TRUE;
7013				goto same_removechain;
7014			}
7015			if (result == ISC_R_NOMORE) {
7016				LOCK_ZONE(zone);
7017				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7018						link);
7019				UNLOCK_ZONE(zone);
7020				ISC_LIST_APPEND(cleanup, nsec3chain, link);
7021				dns_dbiterator_pause(nsec3chain->dbiterator);
7022				result = fixup_nsec3param(db, version,
7023							  nsec3chain, ISC_FALSE,
7024							  privatetype,
7025							  &param_diff);
7026				if (result != ISC_R_SUCCESS) {
7027					dns_zone_log(zone, ISC_LOG_ERROR,
7028						     "zone_nsec3chain:"
7029						     "fixup_nsec3param -> %s",
7030						     dns_result_totext(result));
7031					goto failure;
7032				}
7033				goto next_removechain;
7034			} else if (result != ISC_R_SUCCESS) {
7035				dns_zone_log(zone, ISC_LOG_ERROR,
7036					     "zone_nsec3chain:"
7037					     "dns_dbiterator_next -> %s",
7038					     dns_result_totext(result));
7039				goto failure;
7040			} else if (delegation) {
7041				dns_dbiterator_current(nsec3chain->dbiterator,
7042						       &node, nextname);
7043				dns_db_detachnode(db, &node);
7044				if (!dns_name_issubdomain(nextname, name))
7045					break;
7046			} else
7047				break;
7048		} while (1);
7049		continue;
7050
7051 same_removechain:
7052		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
7053		buildnsecchain = ISC_FALSE;
7054		first = ISC_TRUE;
7055		continue;
7056
7057 next_removechain:
7058		dns_dbiterator_pause(nsec3chain->dbiterator);
7059		nsec3chain = nextnsec3chain;
7060		first = ISC_TRUE;
7061	}
7062
7063	/*
7064	 * We may need to update the NSEC/NSEC3 records for the zone apex.
7065	 */
7066	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
7067		isc_boolean_t rebuild_nsec = ISC_FALSE,
7068			      rebuild_nsec3 = ISC_FALSE;
7069		result = dns_db_getoriginnode(db, &node);
7070		RUNTIME_CHECK(result == ISC_R_SUCCESS);
7071		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7072		if (result != ISC_R_SUCCESS) {
7073			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7074				     "dns_db_allrdatasets -> %s",
7075				     dns_result_totext(result));
7076			goto failure;
7077		}
7078		for (result = dns_rdatasetiter_first(iterator);
7079		     result == ISC_R_SUCCESS;
7080		     result = dns_rdatasetiter_next(iterator)) {
7081			dns_rdatasetiter_current(iterator, &rdataset);
7082			if (rdataset.type == dns_rdatatype_nsec)
7083				rebuild_nsec = ISC_TRUE;
7084			if (rdataset.type == dns_rdatatype_nsec3param)
7085				rebuild_nsec3 = ISC_TRUE;
7086			dns_rdataset_disassociate(&rdataset);
7087		}
7088		dns_rdatasetiter_destroy(&iterator);
7089		dns_db_detachnode(db, &node);
7090
7091		if (rebuild_nsec) {
7092			if (nsec3chain != NULL)
7093				dns_dbiterator_pause(nsec3chain->dbiterator);
7094
7095			result = updatesecure(db, version, &zone->origin,
7096					      zone->minimum, ISC_TRUE,
7097					      &nsec_diff);
7098			if (result != ISC_R_SUCCESS) {
7099				dns_zone_log(zone, ISC_LOG_ERROR,
7100					     "zone_nsec3chain:"
7101					     "updatesecure -> %s",
7102					     dns_result_totext(result));
7103				goto failure;
7104			}
7105		}
7106
7107		if (rebuild_nsec3) {
7108			if (nsec3chain != NULL)
7109				dns_dbiterator_pause(nsec3chain->dbiterator);
7110
7111			result = dns_nsec3_addnsec3s(db, version,
7112						     dns_db_origin(db),
7113						     zone->minimum, ISC_FALSE,
7114						     &nsec3_diff);
7115			if (result != ISC_R_SUCCESS) {
7116				dns_zone_log(zone, ISC_LOG_ERROR,
7117					     "zone_nsec3chain:"
7118					     "dns_nsec3_addnsec3s -> %s",
7119					     dns_result_totext(result));
7120				goto failure;
7121			}
7122		}
7123	}
7124
7125	if (nsec3chain != NULL)
7126		dns_dbiterator_pause(nsec3chain->dbiterator);
7127
7128	/*
7129	 * Add / update signatures for the NSEC3 records.
7130	 */
7131	if (nsec3chain != NULL)
7132		dns_dbiterator_pause(nsec3chain->dbiterator);
7133	result = update_sigs(&nsec3_diff, db, version, zone_keys,
7134			     nkeys, zone, inception, expire, now,
7135			     check_ksk, keyset_kskonly, &zonediff);
7136	if (result != ISC_R_SUCCESS) {
7137		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7138			     "update_sigs -> %s", dns_result_totext(result));
7139		goto failure;
7140	}
7141
7142	/*
7143	 * We have changed the NSEC3PARAM or private RRsets
7144	 * above so we need to update the signatures.
7145	 */
7146	result = update_sigs(&param_diff, db, version, zone_keys,
7147			     nkeys, zone, inception, expire, now,
7148			     check_ksk, keyset_kskonly, &zonediff);
7149	if (result != ISC_R_SUCCESS) {
7150		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7151			     "update_sigs -> %s", dns_result_totext(result));
7152		goto failure;
7153	}
7154
7155	if (updatensec) {
7156		result = updatesecure(db, version, &zone->origin,
7157				      zone->minimum, ISC_FALSE, &nsec_diff);
7158		if (result != ISC_R_SUCCESS) {
7159			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7160				     "updatesecure -> %s",
7161				     dns_result_totext(result));
7162			goto failure;
7163		}
7164	}
7165
7166	result = update_sigs(&nsec_diff, db, version, zone_keys,
7167			     nkeys, zone, inception, expire, now,
7168			     check_ksk, keyset_kskonly, &zonediff);
7169	if (result != ISC_R_SUCCESS) {
7170		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7171			     "update_sigs -> %s", dns_result_totext(result));
7172		goto failure;
7173	}
7174
7175	/*
7176	 * If we made no effective changes to the zone then we can just
7177	 * cleanup otherwise we need to increment the serial.
7178	 */
7179	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7180		/*
7181		 * No need to call dns_db_closeversion() here as it is
7182		 * called with commit = ISC_TRUE below.
7183		 */
7184		goto done;
7185	}
7186
7187	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7188			  &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7189	if (result != ISC_R_SUCCESS) {
7190		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7191			     "del_sigs -> %s", dns_result_totext(result));
7192		goto failure;
7193	}
7194
7195	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7196				   zone->updatemethod);
7197	if (result != ISC_R_SUCCESS) {
7198		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7199			     "update_soa_serial -> %s",
7200			     dns_result_totext(result));
7201		goto failure;
7202	}
7203
7204	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7205			  zonediff.diff, zone_keys, nkeys, zone->mctx,
7206			  inception, soaexpire, check_ksk, keyset_kskonly);
7207	if (result != ISC_R_SUCCESS) {
7208		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7209			     "add_sigs -> %s", dns_result_totext(result));
7210		goto failure;
7211	}
7212
7213	/* Write changes to journal file. */
7214	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
7215
7216	LOCK_ZONE(zone);
7217	zone_needdump(zone, DNS_DUMP_DELAY);
7218	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7219	UNLOCK_ZONE(zone);
7220
7221 done:
7222	/*
7223	 * Pause all iterators so that dns_db_closeversion() can succeed.
7224	 */
7225	LOCK_ZONE(zone);
7226	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7227	     nsec3chain != NULL;
7228	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7229		dns_dbiterator_pause(nsec3chain->dbiterator);
7230	UNLOCK_ZONE(zone);
7231
7232	/*
7233	 * Everything has succeeded. Commit the changes.
7234	 * Unconditionally commit as zonediff.offline not checked above.
7235	 */
7236	dns_db_closeversion(db, &version, ISC_TRUE);
7237
7238	/*
7239	 * Everything succeeded so we can clean these up now.
7240	 */
7241	nsec3chain = ISC_LIST_HEAD(cleanup);
7242	while (nsec3chain != NULL) {
7243		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7244		dns_db_detach(&nsec3chain->db);
7245		dns_dbiterator_destroy(&nsec3chain->dbiterator);
7246		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7247		nsec3chain = ISC_LIST_HEAD(cleanup);
7248	}
7249
7250	set_resigntime(zone);
7251
7252 failure:
7253	if (result != ISC_R_SUCCESS)
7254		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
7255			     dns_result_totext(result));
7256	/*
7257	 * On error roll back the current nsec3chain.
7258	 */
7259	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
7260		if (nsec3chain->done) {
7261			dns_db_detach(&nsec3chain->db);
7262			dns_dbiterator_destroy(&nsec3chain->dbiterator);
7263			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7264		} else {
7265			result = dns_dbiterator_first(nsec3chain->dbiterator);
7266			RUNTIME_CHECK(result == ISC_R_SUCCESS);
7267			dns_dbiterator_pause(nsec3chain->dbiterator);
7268			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7269		}
7270	}
7271
7272	/*
7273	 * Rollback the cleanup list.
7274	 */
7275	nsec3chain = ISC_LIST_TAIL(cleanup);
7276	while (nsec3chain != NULL) {
7277		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7278		if (nsec3chain->done) {
7279			dns_db_detach(&nsec3chain->db);
7280			dns_dbiterator_destroy(&nsec3chain->dbiterator);
7281			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7282		} else {
7283			LOCK_ZONE(zone);
7284			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
7285			UNLOCK_ZONE(zone);
7286			result = dns_dbiterator_first(nsec3chain->dbiterator);
7287			RUNTIME_CHECK(result == ISC_R_SUCCESS);
7288			dns_dbiterator_pause(nsec3chain->dbiterator);
7289			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7290		}
7291		nsec3chain = ISC_LIST_TAIL(cleanup);
7292	}
7293
7294	LOCK_ZONE(zone);
7295	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7296	     nsec3chain != NULL;
7297	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7298		dns_dbiterator_pause(nsec3chain->dbiterator);
7299	UNLOCK_ZONE(zone);
7300
7301	dns_diff_clear(&param_diff);
7302	dns_diff_clear(&nsec3_diff);
7303	dns_diff_clear(&nsec_diff);
7304	dns_diff_clear(&_sig_diff);
7305
7306	if (iterator != NULL)
7307		dns_rdatasetiter_destroy(&iterator);
7308
7309	for (i = 0; i < nkeys; i++)
7310		dst_key_free(&zone_keys[i]);
7311
7312	if (node != NULL)
7313		dns_db_detachnode(db, &node);
7314	if (version != NULL) {
7315		dns_db_closeversion(db, &version, ISC_FALSE);
7316		dns_db_detach(&db);
7317	} else if (db != NULL)
7318		dns_db_detach(&db);
7319
7320	LOCK_ZONE(zone);
7321	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
7322		isc_interval_t i;
7323		if (zone->update_disabled || result != ISC_R_SUCCESS)
7324			isc_interval_set(&i, 60, 0);		/* 1 minute */
7325		else
7326			isc_interval_set(&i, 0, 10000000);	/* 10 ms */
7327		isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
7328	} else
7329		isc_time_settoepoch(&zone->nsec3chaintime);
7330	UNLOCK_ZONE(zone);
7331}
7332
7333static isc_result_t
7334del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7335	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
7336	isc_uint16_t keyid, dns_diff_t *diff)
7337{
7338	dns_rdata_rrsig_t rrsig;
7339	dns_rdataset_t rdataset;
7340	dns_rdatasetiter_t *iterator = NULL;
7341	isc_result_t result;
7342
7343	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7344	if (result != ISC_R_SUCCESS) {
7345		if (result == ISC_R_NOTFOUND)
7346			result = ISC_R_SUCCESS;
7347		return (result);
7348	}
7349
7350	dns_rdataset_init(&rdataset);
7351	for (result = dns_rdatasetiter_first(iterator);
7352	     result == ISC_R_SUCCESS;
7353	     result = dns_rdatasetiter_next(iterator)) {
7354		dns_rdatasetiter_current(iterator, &rdataset);
7355		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
7356			for (result = dns_rdataset_first(&rdataset);
7357			     result == ISC_R_SUCCESS;
7358			     result = dns_rdataset_next(&rdataset)) {
7359				dns_rdata_t rdata = DNS_RDATA_INIT;
7360				dns_rdataset_current(&rdataset, &rdata);
7361				CHECK(update_one_rr(db, version, diff,
7362						    DNS_DIFFOP_DEL, name,
7363						    rdataset.ttl, &rdata));
7364			}
7365			if (result != ISC_R_NOMORE)
7366				goto failure;
7367			dns_rdataset_disassociate(&rdataset);
7368			continue;
7369		}
7370		if (rdataset.type != dns_rdatatype_rrsig) {
7371			dns_rdataset_disassociate(&rdataset);
7372			continue;
7373		}
7374		for (result = dns_rdataset_first(&rdataset);
7375		     result == ISC_R_SUCCESS;
7376		     result = dns_rdataset_next(&rdataset)) {
7377			dns_rdata_t rdata = DNS_RDATA_INIT;
7378			dns_rdataset_current(&rdataset, &rdata);
7379			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
7380			if (rrsig.algorithm != algorithm ||
7381			    rrsig.keyid != keyid)
7382				continue;
7383			CHECK(update_one_rr(db, version, diff,
7384					    DNS_DIFFOP_DELRESIGN, name,
7385					    rdataset.ttl, &rdata));
7386		}
7387		dns_rdataset_disassociate(&rdataset);
7388		if (result != ISC_R_NOMORE)
7389			break;
7390	}
7391	if (result == ISC_R_NOMORE)
7392		result = ISC_R_SUCCESS;
7393 failure:
7394	if (dns_rdataset_isassociated(&rdataset))
7395		dns_rdataset_disassociate(&rdataset);
7396	dns_rdatasetiter_destroy(&iterator);
7397	return (result);
7398}
7399
7400/*
7401 * Incrementally sign the zone using the keys requested.
7402 * Builds the NSEC chain if required.
7403 */
7404static void
7405zone_sign(dns_zone_t *zone) {
7406	const char *me = "zone_sign";
7407	dns_db_t *db = NULL;
7408	dns_dbnode_t *node = NULL;
7409	dns_dbversion_t *version = NULL;
7410	dns_diff_t _sig_diff;
7411	dns_diff_t post_diff;
7412	zonediff_t zonediff;
7413	dns_fixedname_t fixed;
7414	dns_fixedname_t nextfixed;
7415	dns_name_t *name, *nextname;
7416	dns_rdataset_t rdataset;
7417	dns_signing_t *signing, *nextsigning;
7418	dns_signinglist_t cleanup;
7419	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7420	isc_int32_t signatures;
7421	isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
7422	isc_boolean_t commit = ISC_FALSE;
7423	isc_boolean_t delegation;
7424	isc_boolean_t build_nsec = ISC_FALSE;
7425	isc_boolean_t build_nsec3 = ISC_FALSE;
7426	isc_boolean_t first;
7427	isc_result_t result;
7428	isc_stdtime_t now, inception, soaexpire, expire;
7429	isc_uint32_t jitter;
7430	unsigned int i, j;
7431	unsigned int nkeys = 0;
7432	isc_uint32_t nodes;
7433
7434	ENTER;
7435
7436	dns_rdataset_init(&rdataset);
7437	dns_fixedname_init(&fixed);
7438	name = dns_fixedname_name(&fixed);
7439	dns_fixedname_init(&nextfixed);
7440	nextname = dns_fixedname_name(&nextfixed);
7441	dns_diff_init(zone->mctx, &_sig_diff);
7442	dns_diff_init(zone->mctx, &post_diff);
7443	zonediff_init(&zonediff, &_sig_diff);
7444	ISC_LIST_INIT(cleanup);
7445
7446	/*
7447	 * Updates are disabled.  Pause for 5 minutes.
7448	 */
7449	if (zone->update_disabled) {
7450		result = ISC_R_FAILURE;
7451		goto failure;
7452	}
7453
7454	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7455	if (zone->db != NULL)
7456		dns_db_attach(zone->db, &db);
7457	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7458	if (db == NULL) {
7459		result = ISC_R_FAILURE;
7460		goto failure;
7461	}
7462
7463	result = dns_db_newversion(db, &version);
7464	if (result != ISC_R_SUCCESS) {
7465		dns_zone_log(zone, ISC_LOG_ERROR,
7466			     "zone_sign:dns_db_newversion -> %s",
7467			     dns_result_totext(result));
7468		goto failure;
7469	}
7470
7471	result = find_zone_keys(zone, db, version, zone->mctx,
7472				DNS_MAXZONEKEYS, zone_keys, &nkeys);
7473	if (result != ISC_R_SUCCESS) {
7474		dns_zone_log(zone, ISC_LOG_ERROR,
7475			     "zone_sign:find_zone_keys -> %s",
7476			     dns_result_totext(result));
7477		goto failure;
7478	}
7479
7480	isc_stdtime_get(&now);
7481	inception = now - 3600;	/* Allow for clock skew. */
7482	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
7483
7484	/*
7485	 * Spread out signatures over time if they happen to be
7486	 * clumped.  We don't do this for each add_sigs() call as
7487	 * we still want some clustering to occur.
7488	 */
7489	isc_random_get(&jitter);
7490	expire = soaexpire - jitter % 3600;
7491
7492	/*
7493	 * We keep pulling nodes off each iterator in turn until
7494	 * we have no more nodes to pull off or we reach the limits
7495	 * for this quantum.
7496	 */
7497	nodes = zone->nodes;
7498	signatures = zone->signatures;
7499	signing = ISC_LIST_HEAD(zone->signing);
7500	first = ISC_TRUE;
7501
7502	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7503	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7504
7505	/* Determine which type of chain to build */
7506	CHECK(dns_private_chains(db, version, zone->privatetype,
7507				 &build_nsec, &build_nsec3));
7508
7509	/* If neither chain is found, default to NSEC */
7510	if (!build_nsec && !build_nsec3)
7511		build_nsec = ISC_TRUE;
7512
7513	while (signing != NULL && nodes-- > 0 && signatures > 0) {
7514		nextsigning = ISC_LIST_NEXT(signing, link);
7515
7516		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7517		if (signing->done || signing->db != zone->db) {
7518			/*
7519			 * The zone has been reloaded.	We will have
7520			 * created new signings as part of the reload
7521			 * process so we can destroy this one.
7522			 */
7523			ISC_LIST_UNLINK(zone->signing, signing, link);
7524			ISC_LIST_APPEND(cleanup, signing, link);
7525			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7526			goto next_signing;
7527		}
7528		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7529
7530		if (signing->db != db)
7531			goto next_signing;
7532
7533		delegation = ISC_FALSE;
7534
7535		if (first && signing->delete) {
7536			/*
7537			 * Remove the key we are deleting from consideration.
7538			 */
7539			for (i = 0, j = 0; i < nkeys; i++) {
7540				/*
7541				 * Find the key we want to remove.
7542				 */
7543				if (ALG(zone_keys[i]) == signing->algorithm &&
7544				    dst_key_id(zone_keys[i]) == signing->keyid)
7545				{
7546					if (KSK(zone_keys[i]))
7547						dst_key_free(&zone_keys[i]);
7548					continue;
7549				}
7550				zone_keys[j] = zone_keys[i];
7551				j++;
7552			}
7553			nkeys = j;
7554		}
7555
7556		dns_dbiterator_current(signing->dbiterator, &node, name);
7557
7558		if (signing->delete) {
7559			dns_dbiterator_pause(signing->dbiterator);
7560			CHECK(del_sig(db, version, name, node, nkeys,
7561				      signing->algorithm, signing->keyid,
7562				      zonediff.diff));
7563		}
7564
7565		/*
7566		 * On the first pass we need to check if the current node
7567		 * has not been obscured.
7568		 */
7569		if (first) {
7570			dns_fixedname_t ffound;
7571			dns_name_t *found;
7572			dns_fixedname_init(&ffound);
7573			found = dns_fixedname_name(&ffound);
7574			result = dns_db_find(db, name, version,
7575					     dns_rdatatype_soa,
7576					     DNS_DBFIND_NOWILD, 0, NULL, found,
7577					     NULL, NULL);
7578			if ((result == DNS_R_DELEGATION ||
7579			    result == DNS_R_DNAME) &&
7580			    !dns_name_equal(name, found)) {
7581				/*
7582				 * Remember the obscuring name so that
7583				 * we skip all obscured names.
7584				 */
7585				dns_name_copy(found, name, NULL);
7586				delegation = ISC_TRUE;
7587				goto next_node;
7588			}
7589		}
7590
7591		/*
7592		 * Process one node.
7593		 */
7594		dns_dbiterator_pause(signing->dbiterator);
7595		for (i = 0; i < nkeys; i++) {
7596			isc_boolean_t both = ISC_FALSE;
7597
7598			/*
7599			 * Find the keys we want to sign with.
7600			 */
7601			if (!dst_key_isprivate(zone_keys[i]))
7602				continue;
7603
7604			/*
7605			 * When adding look for the specific key.
7606			 */
7607			if (!signing->delete &&
7608			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
7609			     dst_key_id(zone_keys[i]) != signing->keyid))
7610				continue;
7611
7612			/*
7613			 * When deleting make sure we are properly signed
7614			 * with the algorithm that was being removed.
7615			 */
7616			if (signing->delete &&
7617			    ALG(zone_keys[i]) != signing->algorithm)
7618				continue;
7619
7620			/*
7621			 * Do we do KSK processing?
7622			 */
7623			if (check_ksk && !REVOKE(zone_keys[i])) {
7624				isc_boolean_t have_ksk, have_nonksk;
7625				if (KSK(zone_keys[i])) {
7626					have_ksk = ISC_TRUE;
7627					have_nonksk = ISC_FALSE;
7628				} else {
7629					have_ksk = ISC_FALSE;
7630					have_nonksk = ISC_TRUE;
7631				}
7632				for (j = 0; j < nkeys; j++) {
7633					if (j == i ||
7634					    ALG(zone_keys[i]) !=
7635					    ALG(zone_keys[j]))
7636						continue;
7637					if (REVOKE(zone_keys[j]))
7638						continue;
7639					if (KSK(zone_keys[j]))
7640						have_ksk = ISC_TRUE;
7641					else
7642						have_nonksk = ISC_TRUE;
7643					both = have_ksk && have_nonksk;
7644					if (both)
7645						break;
7646				}
7647			}
7648			if (both || REVOKE(zone_keys[i]))
7649				is_ksk = KSK(zone_keys[i]);
7650			else
7651				is_ksk = ISC_FALSE;
7652
7653			CHECK(sign_a_node(db, name, node, version, build_nsec3,
7654					  build_nsec, zone_keys[i], inception,
7655					  expire, zone->minimum, is_ksk,
7656					  ISC_TF(both && keyset_kskonly),
7657					  &delegation, zonediff.diff,
7658					  &signatures, zone->mctx));
7659			/*
7660			 * If we are adding we are done.  Look for other keys
7661			 * of the same algorithm if deleting.
7662			 */
7663			if (!signing->delete)
7664				break;
7665		}
7666
7667		/*
7668		 * Go onto next node.
7669		 */
7670 next_node:
7671		first = ISC_FALSE;
7672		dns_db_detachnode(db, &node);
7673		do {
7674			result = dns_dbiterator_next(signing->dbiterator);
7675			if (result == ISC_R_NOMORE) {
7676				ISC_LIST_UNLINK(zone->signing, signing, link);
7677				ISC_LIST_APPEND(cleanup, signing, link);
7678				dns_dbiterator_pause(signing->dbiterator);
7679				if (nkeys != 0 && build_nsec) {
7680					/*
7681					 * We have finished regenerating the
7682					 * zone with a zone signing key.
7683					 * The NSEC chain is now complete and
7684					 * there is a full set of signatures
7685					 * for the zone.  We can now clear the
7686					 * OPT bit from the NSEC record.
7687					 */
7688					result = updatesecure(db, version,
7689							      &zone->origin,
7690							      zone->minimum,
7691							      ISC_FALSE,
7692							      &post_diff);
7693					if (result != ISC_R_SUCCESS) {
7694						dns_zone_log(zone,
7695							     ISC_LOG_ERROR,
7696						    "updatesecure -> %s",
7697						    dns_result_totext(result));
7698						goto failure;
7699					}
7700				}
7701				result = updatesignwithkey(zone, signing,
7702							   version,
7703							   build_nsec3,
7704							   zone->minimum,
7705							   &post_diff);
7706				if (result != ISC_R_SUCCESS) {
7707					dns_zone_log(zone, ISC_LOG_ERROR,
7708						     "updatesignwithkey -> %s",
7709						     dns_result_totext(result));
7710					goto failure;
7711				}
7712				build_nsec = ISC_FALSE;
7713				goto next_signing;
7714			} else if (result != ISC_R_SUCCESS) {
7715				dns_zone_log(zone, ISC_LOG_ERROR,
7716					"zone_sign:dns_dbiterator_next -> %s",
7717					     dns_result_totext(result));
7718				goto failure;
7719			} else if (delegation) {
7720				dns_dbiterator_current(signing->dbiterator,
7721						       &node, nextname);
7722				dns_db_detachnode(db, &node);
7723				if (!dns_name_issubdomain(nextname, name))
7724					break;
7725			} else
7726				break;
7727		} while (1);
7728		continue;
7729
7730 next_signing:
7731		dns_dbiterator_pause(signing->dbiterator);
7732		signing = nextsigning;
7733		first = ISC_TRUE;
7734	}
7735
7736	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
7737		result = update_sigs(&post_diff, db, version, zone_keys,
7738				     nkeys, zone, inception, expire, now,
7739				     check_ksk, keyset_kskonly, &zonediff);
7740		if (result != ISC_R_SUCCESS) {
7741			dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
7742				     "update_sigs -> %s",
7743				     dns_result_totext(result));
7744			goto failure;
7745		}
7746	}
7747
7748	/*
7749	 * Have we changed anything?
7750	 */
7751	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7752		if (zonediff.offline)
7753			commit = ISC_TRUE;
7754		result = ISC_R_SUCCESS;
7755		goto pauseall;
7756	}
7757
7758	commit = ISC_TRUE;
7759
7760	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7761			  &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7762	if (result != ISC_R_SUCCESS) {
7763		dns_zone_log(zone, ISC_LOG_ERROR,
7764			     "zone_sign:del_sigs -> %s",
7765			     dns_result_totext(result));
7766		goto failure;
7767	}
7768
7769	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7770				   zone->updatemethod);
7771	if (result != ISC_R_SUCCESS) {
7772		dns_zone_log(zone, ISC_LOG_ERROR,
7773			     "zone_sign:update_soa_serial -> %s",
7774			     dns_result_totext(result));
7775		goto failure;
7776	}
7777
7778	/*
7779	 * Generate maximum life time signatures so that the above loop
7780	 * termination is sensible.
7781	 */
7782	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7783			  zonediff.diff, zone_keys, nkeys, zone->mctx,
7784			  inception, soaexpire, check_ksk, keyset_kskonly);
7785	if (result != ISC_R_SUCCESS) {
7786		dns_zone_log(zone, ISC_LOG_ERROR,
7787			     "zone_sign:add_sigs -> %s",
7788			     dns_result_totext(result));
7789		goto failure;
7790	}
7791
7792	/*
7793	 * Write changes to journal file.
7794	 */
7795	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
7796
7797 pauseall:
7798	/*
7799	 * Pause all iterators so that dns_db_closeversion() can succeed.
7800	 */
7801	for (signing = ISC_LIST_HEAD(zone->signing);
7802	     signing != NULL;
7803	     signing = ISC_LIST_NEXT(signing, link))
7804		dns_dbiterator_pause(signing->dbiterator);
7805
7806	for (signing = ISC_LIST_HEAD(cleanup);
7807	     signing != NULL;
7808	     signing = ISC_LIST_NEXT(signing, link))
7809		dns_dbiterator_pause(signing->dbiterator);
7810
7811	/*
7812	 * Everything has succeeded. Commit the changes.
7813	 */
7814	dns_db_closeversion(db, &version, commit);
7815
7816	/*
7817	 * Everything succeeded so we can clean these up now.
7818	 */
7819	signing = ISC_LIST_HEAD(cleanup);
7820	while (signing != NULL) {
7821		ISC_LIST_UNLINK(cleanup, signing, link);
7822		dns_db_detach(&signing->db);
7823		dns_dbiterator_destroy(&signing->dbiterator);
7824		isc_mem_put(zone->mctx, signing, sizeof *signing);
7825		signing = ISC_LIST_HEAD(cleanup);
7826	}
7827
7828	set_resigntime(zone);
7829
7830	if (commit) {
7831		LOCK_ZONE(zone);
7832		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7833		zone_needdump(zone, DNS_DUMP_DELAY);
7834		UNLOCK_ZONE(zone);
7835	}
7836
7837 failure:
7838	/*
7839	 * Rollback the cleanup list.
7840	 */
7841	signing = ISC_LIST_HEAD(cleanup);
7842	while (signing != NULL) {
7843		ISC_LIST_UNLINK(cleanup, signing, link);
7844		ISC_LIST_PREPEND(zone->signing, signing, link);
7845		dns_dbiterator_first(signing->dbiterator);
7846		dns_dbiterator_pause(signing->dbiterator);
7847		signing = ISC_LIST_HEAD(cleanup);
7848	}
7849
7850	for (signing = ISC_LIST_HEAD(zone->signing);
7851	     signing != NULL;
7852	     signing = ISC_LIST_NEXT(signing, link))
7853		dns_dbiterator_pause(signing->dbiterator);
7854
7855	dns_diff_clear(&_sig_diff);
7856
7857	for (i = 0; i < nkeys; i++)
7858		dst_key_free(&zone_keys[i]);
7859
7860	if (node != NULL)
7861		dns_db_detachnode(db, &node);
7862
7863	if (version != NULL) {
7864		dns_db_closeversion(db, &version, ISC_FALSE);
7865		dns_db_detach(&db);
7866	} else if (db != NULL)
7867		dns_db_detach(&db);
7868
7869	if (ISC_LIST_HEAD(zone->signing) != NULL) {
7870		isc_interval_t i;
7871		if (zone->update_disabled || result != ISC_R_SUCCESS)
7872			isc_interval_set(&i, 60, 0);		/* 1 minute */
7873		else
7874			isc_interval_set(&i, 0, 10000000);	/* 10 ms */
7875		isc_time_nowplusinterval(&zone->signingtime, &i);
7876	} else
7877		isc_time_settoepoch(&zone->signingtime);
7878}
7879
7880static isc_result_t
7881normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
7882	      unsigned char *data, int size) {
7883	dns_rdata_dnskey_t dnskey;
7884	dns_rdata_keydata_t keydata;
7885	isc_buffer_t buf;
7886	isc_result_t result;
7887
7888	dns_rdata_reset(target);
7889	isc_buffer_init(&buf, data, size);
7890
7891	switch (rr->type) {
7892	    case dns_rdatatype_dnskey:
7893		result = dns_rdata_tostruct(rr, &dnskey, NULL);
7894		RUNTIME_CHECK(result == ISC_R_SUCCESS);
7895		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
7896		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7897				     &dnskey, &buf);
7898		break;
7899	    case dns_rdatatype_keydata:
7900		result = dns_rdata_tostruct(rr, &keydata, NULL);
7901		if (result == ISC_R_UNEXPECTEDEND)
7902			return (result);
7903		RUNTIME_CHECK(result == ISC_R_SUCCESS);
7904		dns_keydata_todnskey(&keydata, &dnskey, NULL);
7905		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7906				     &dnskey, &buf);
7907		break;
7908	    default:
7909		INSIST(0);
7910	}
7911	return (ISC_R_SUCCESS);
7912}
7913
7914/*
7915 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
7916 * a KEYDATA rdataset from the key zone.
7917 *
7918 * 'rr' contains either a DNSKEY record, or a KEYDATA record
7919 *
7920 * After normalizing keys to the same format (DNSKEY, with revoke bit
7921 * cleared), return ISC_TRUE if a key that matches 'rr' is found in
7922 * 'rdset', or ISC_FALSE if not.
7923 */
7924
7925static isc_boolean_t
7926matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
7927	unsigned char data1[4096], data2[4096];
7928	dns_rdata_t rdata, rdata1, rdata2;
7929	isc_result_t result;
7930
7931	dns_rdata_init(&rdata);
7932	dns_rdata_init(&rdata1);
7933	dns_rdata_init(&rdata2);
7934
7935	result = normalize_key(rr, &rdata1, data1, sizeof(data1));
7936	if (result != ISC_R_SUCCESS)
7937		return (ISC_FALSE);
7938
7939	for (result = dns_rdataset_first(rdset);
7940	     result == ISC_R_SUCCESS;
7941	     result = dns_rdataset_next(rdset)) {
7942		dns_rdata_reset(&rdata);
7943		dns_rdataset_current(rdset, &rdata);
7944		result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
7945		if (result != ISC_R_SUCCESS)
7946			continue;
7947		if (dns_rdata_compare(&rdata1, &rdata2) == 0)
7948			return (ISC_TRUE);
7949	}
7950
7951	return (ISC_FALSE);
7952}
7953
7954/*
7955 * Calculate the refresh interval for a keydata zone, per
7956 * RFC5011: MAX(1 hr,
7957 *		MIN(15 days,
7958 *		    1/2 * OrigTTL,
7959 *		    1/2 * RRSigExpirationInterval))
7960 * or for retries: MAX(1 hr,
7961 *		       MIN(1 day,
7962 *			   1/10 * OrigTTL,
7963 *			   1/10 * RRSigExpirationInterval))
7964 */
7965static inline isc_stdtime_t
7966refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
7967	isc_result_t result;
7968	isc_uint32_t t;
7969	dns_rdataset_t *rdset;
7970	dns_rdata_t sigrr = DNS_RDATA_INIT;
7971	dns_rdata_sig_t sig;
7972	isc_stdtime_t now;
7973
7974	isc_stdtime_get(&now);
7975
7976	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7977		rdset = &kfetch->dnskeysigset;
7978	else
7979		return (now + HOUR);
7980
7981	result = dns_rdataset_first(rdset);
7982	if (result != ISC_R_SUCCESS)
7983		return (now + HOUR);
7984
7985	dns_rdataset_current(rdset, &sigrr);
7986	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7987	RUNTIME_CHECK(result == ISC_R_SUCCESS);
7988
7989	if (!retry) {
7990		t = sig.originalttl / 2;
7991
7992		if (isc_serial_gt(sig.timeexpire, now)) {
7993			isc_uint32_t exp = (sig.timeexpire - now) / 2;
7994			if (t > exp)
7995				t = exp;
7996		}
7997
7998		if (t > (15*DAY))
7999			t = (15*DAY);
8000
8001		if (t < HOUR)
8002			t = HOUR;
8003	} else {
8004		t = sig.originalttl / 10;
8005
8006		if (isc_serial_gt(sig.timeexpire, now)) {
8007			isc_uint32_t exp = (sig.timeexpire - now) / 10;
8008			if (t > exp)
8009				t = exp;
8010		}
8011
8012		if (t > DAY)
8013			t = DAY;
8014
8015		if (t < HOUR)
8016			t = HOUR;
8017	}
8018
8019	return (now + t);
8020}
8021
8022/*
8023 * This routine is called when no changes are needed in a KEYDATA
8024 * record except to simply update the refresh timer.  Caller should
8025 * hold zone lock.
8026 */
8027static isc_result_t
8028minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
8029{
8030	isc_result_t result;
8031	isc_buffer_t keyb;
8032	unsigned char key_buf[4096];
8033	dns_rdata_t rdata = DNS_RDATA_INIT;
8034	dns_rdata_keydata_t keydata;
8035	dns_name_t *name;
8036	dns_zone_t *zone = kfetch->zone;
8037	isc_stdtime_t now;
8038
8039	name = dns_fixedname_name(&kfetch->name);
8040	isc_stdtime_get(&now);
8041
8042	for (result = dns_rdataset_first(&kfetch->keydataset);
8043	     result == ISC_R_SUCCESS;
8044	     result = dns_rdataset_next(&kfetch->keydataset)) {
8045		dns_rdata_reset(&rdata);
8046		dns_rdataset_current(&kfetch->keydataset, &rdata);
8047
8048		/* Delete old version */
8049		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
8050				    name, 0, &rdata));
8051
8052		/* Update refresh timer */
8053		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
8054		if (result == ISC_R_UNEXPECTEDEND)
8055			continue;
8056		if (result != ISC_R_SUCCESS)
8057			goto failure;
8058		keydata.refresh = refresh_time(kfetch, ISC_TRUE);
8059		set_refreshkeytimer(zone, &keydata, now);
8060
8061		dns_rdata_reset(&rdata);
8062		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8063		CHECK(dns_rdata_fromstruct(&rdata,
8064					   zone->rdclass, dns_rdatatype_keydata,
8065					   &keydata, &keyb));
8066
8067		/* Insert updated version */
8068		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
8069				    name, 0, &rdata));
8070	}
8071	result = ISC_R_SUCCESS;
8072  failure:
8073	return (result);
8074}
8075
8076/*
8077 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
8078 */
8079static isc_boolean_t
8080revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
8081	isc_result_t result;
8082	dns_name_t *keyname;
8083	isc_mem_t *mctx;
8084	dns_rdata_t sigrr = DNS_RDATA_INIT;
8085	dns_rdata_t rr = DNS_RDATA_INIT;
8086	dns_rdata_rrsig_t sig;
8087	dns_rdata_dnskey_t dnskey;
8088	dst_key_t *dstkey = NULL;
8089	unsigned char key_buf[4096];
8090	isc_buffer_t keyb;
8091	isc_boolean_t answer = ISC_FALSE;
8092
8093	REQUIRE(kfetch != NULL && keydata != NULL);
8094	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
8095
8096	keyname = dns_fixedname_name(&kfetch->name);
8097	mctx = kfetch->zone->view->mctx;
8098
8099	/* Generate a key from keydata */
8100	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8101	dns_keydata_todnskey(keydata, &dnskey, NULL);
8102	dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
8103				     &dnskey, &keyb);
8104	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
8105	if (result != ISC_R_SUCCESS)
8106		return (ISC_FALSE);
8107
8108	/* See if that key generated any of the signatures */
8109	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8110	     result == ISC_R_SUCCESS;
8111	     result = dns_rdataset_next(&kfetch->dnskeysigset)) {
8112		dns_fixedname_t fixed;
8113		dns_fixedname_init(&fixed);
8114
8115		dns_rdata_reset(&sigrr);
8116		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8117		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8118		RUNTIME_CHECK(result == ISC_R_SUCCESS);
8119
8120		if (dst_key_alg(dstkey) == sig.algorithm &&
8121		    (dst_key_id(dstkey) == sig.keyid ||
8122		     dst_key_rid(dstkey) == sig.keyid)) {
8123			result = dns_dnssec_verify2(keyname,
8124					    &kfetch->dnskeyset,
8125					    dstkey, ISC_FALSE, mctx, &sigrr,
8126					    dns_fixedname_name(&fixed));
8127
8128			dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
8129				     "Confirm revoked DNSKEY is self-signed: "
8130				     "%s", dns_result_totext(result));
8131
8132			if (result == ISC_R_SUCCESS) {
8133				answer = ISC_TRUE;
8134				break;
8135			}
8136		}
8137	}
8138
8139	dst_key_free(&dstkey);
8140	return (answer);
8141}
8142
8143/*
8144 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
8145 * anchors are being managed; scan the keyset, and update the key zone and the
8146 * local trust anchors according to RFC5011.
8147 */
8148static void
8149keyfetch_done(isc_task_t *task, isc_event_t *event) {
8150	isc_result_t result, eresult;
8151	dns_fetchevent_t *devent;
8152	dns_keyfetch_t *kfetch;
8153	dns_zone_t *zone;
8154	isc_mem_t *mctx = NULL;
8155	dns_keytable_t *secroots = NULL;
8156	dns_dbversion_t *ver = NULL;
8157	dns_diff_t diff;
8158	isc_boolean_t alldone = ISC_FALSE;
8159	isc_boolean_t commit = ISC_FALSE;
8160	dns_name_t *keyname;
8161	dns_rdata_t sigrr = DNS_RDATA_INIT;
8162	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
8163	dns_rdata_t keydatarr = DNS_RDATA_INIT;
8164	dns_rdata_rrsig_t sig;
8165	dns_rdata_dnskey_t dnskey;
8166	dns_rdata_keydata_t keydata;
8167	isc_boolean_t initializing;
8168	char namebuf[DNS_NAME_FORMATSIZE];
8169	unsigned char key_buf[4096];
8170	isc_buffer_t keyb;
8171	dst_key_t *dstkey;
8172	isc_stdtime_t now;
8173	int pending = 0;
8174	isc_boolean_t secure;
8175	isc_boolean_t free_needed;
8176
8177	UNUSED(task);
8178	INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
8179	INSIST(event->ev_arg != NULL);
8180
8181	kfetch = event->ev_arg;
8182	zone = kfetch->zone;
8183	isc_mem_attach(zone->mctx, &mctx);
8184	keyname = dns_fixedname_name(&kfetch->name);
8185
8186	devent = (dns_fetchevent_t *) event;
8187	eresult = devent->result;
8188
8189	/* Free resources which are not of interest */
8190	if (devent->node != NULL)
8191		dns_db_detachnode(devent->db, &devent->node);
8192	if (devent->db != NULL)
8193		dns_db_detach(&devent->db);
8194	isc_event_free(&event);
8195	dns_resolver_destroyfetch(&kfetch->fetch);
8196
8197	LOCK_ZONE(zone);
8198	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
8199		goto cleanup;
8200
8201	isc_stdtime_get(&now);
8202	dns_name_format(keyname, namebuf, sizeof(namebuf));
8203
8204	result = dns_view_getsecroots(zone->view, &secroots);
8205	INSIST(result == ISC_R_SUCCESS);
8206
8207	dns_diff_init(mctx, &diff);
8208
8209	CHECK(dns_db_newversion(kfetch->db, &ver));
8210
8211	zone->refreshkeycount--;
8212	alldone = ISC_TF(zone->refreshkeycount == 0);
8213
8214	if (alldone)
8215		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8216
8217	/* Fetch failed */
8218	if (eresult != ISC_R_SUCCESS ||
8219	    !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
8220		dns_zone_log(zone, ISC_LOG_WARNING,
8221			     "Unable to fetch DNSKEY set "
8222			     "'%s': %s", namebuf, dns_result_totext(eresult));
8223		CHECK(minimal_update(kfetch, ver, &diff));
8224		goto done;
8225	}
8226
8227	/* No RRSIGs found */
8228	if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
8229		dns_zone_log(zone, ISC_LOG_WARNING,
8230			     "No DNSKEY RRSIGs found for "
8231			     "'%s': %s", namebuf, dns_result_totext(eresult));
8232		CHECK(minimal_update(kfetch, ver, &diff));
8233		goto done;
8234	}
8235
8236	/*
8237	 * Validate the dnskeyset against the current trusted keys.
8238	 */
8239	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8240	     result == ISC_R_SUCCESS;
8241	     result = dns_rdataset_next(&kfetch->dnskeysigset)) {
8242		dns_keynode_t *keynode = NULL;
8243
8244		dns_rdata_reset(&sigrr);
8245		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8246		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8247		RUNTIME_CHECK(result == ISC_R_SUCCESS);
8248
8249		result = dns_keytable_find(secroots, keyname, &keynode);
8250		while (result == ISC_R_SUCCESS) {
8251			dns_keynode_t *nextnode = NULL;
8252			dns_fixedname_t fixed;
8253			dns_fixedname_init(&fixed);
8254
8255			dstkey = dns_keynode_key(keynode);
8256			if (dstkey == NULL) /* fail_secure() was called */
8257				break;
8258
8259			if (dst_key_alg(dstkey) == sig.algorithm &&
8260			    dst_key_id(dstkey) == sig.keyid) {
8261				result = dns_dnssec_verify2(keyname,
8262						    &kfetch->dnskeyset,
8263						    dstkey, ISC_FALSE,
8264						    zone->view->mctx, &sigrr,
8265						    dns_fixedname_name(&fixed));
8266
8267				dns_zone_log(zone, ISC_LOG_DEBUG(3),
8268					     "Verifying DNSKEY set for zone "
8269					     "'%s': %s", namebuf,
8270					     dns_result_totext(result));
8271
8272				if (result == ISC_R_SUCCESS) {
8273					kfetch->dnskeyset.trust =
8274						dns_trust_secure;
8275					kfetch->dnskeysigset.trust =
8276						dns_trust_secure;
8277					dns_keytable_detachkeynode(secroots,
8278								   &keynode);
8279					break;
8280				}
8281			}
8282
8283			result = dns_keytable_nextkeynode(secroots,
8284							  keynode, &nextnode);
8285			dns_keytable_detachkeynode(secroots, &keynode);
8286			keynode = nextnode;
8287		}
8288
8289		if (kfetch->dnskeyset.trust == dns_trust_secure)
8290			break;
8291	}
8292
8293	/*
8294	 * If we were not able to verify the answer using the current
8295	 * trusted keys then all we can do is look at any revoked keys.
8296	 */
8297	secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
8298
8299	/*
8300	 * First scan keydataset to find keys that are not in dnskeyset
8301	 *   - Missing keys which are not scheduled for removal,
8302	 *     log a warning
8303	 *   - Missing keys which are scheduled for removal and
8304	 *     the remove hold-down timer has completed should
8305	 *     be removed from the key zone
8306	 *   - Missing keys whose acceptance timers have not yet
8307	 *     completed, log a warning and reset the acceptance
8308	 *     timer to 30 days in the future
8309	 *   - All keys not being removed have their refresh timers
8310	 *     updated
8311	 */
8312	initializing = ISC_TRUE;
8313	for (result = dns_rdataset_first(&kfetch->keydataset);
8314	     result == ISC_R_SUCCESS;
8315	     result = dns_rdataset_next(&kfetch->keydataset)) {
8316		dns_rdata_reset(&keydatarr);
8317		dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8318		result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8319		RUNTIME_CHECK(result == ISC_R_SUCCESS);
8320
8321		/*
8322		 * If any keydata record has a nonzero add holddown, then
8323		 * there was a pre-existing trust anchor for this domain;
8324		 * that means we are *not* initializing it and shouldn't
8325		 * automatically trust all the keys we find at the zone apex.
8326		 */
8327		initializing = initializing && ISC_TF(keydata.addhd == 0);
8328
8329		if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
8330			isc_boolean_t deletekey = ISC_FALSE;
8331
8332			if (!secure) {
8333				if (now > keydata.removehd)
8334					deletekey = ISC_TRUE;
8335			} else if (now < keydata.addhd) {
8336				dns_zone_log(zone, ISC_LOG_WARNING,
8337					     "Pending key unexpectedly missing "
8338					     "from %s; restarting acceptance "
8339					     "timer", namebuf);
8340				keydata.addhd = now + MONTH;
8341				keydata.refresh = refresh_time(kfetch,
8342							       ISC_FALSE);
8343			} else if (keydata.addhd == 0) {
8344				keydata.addhd = now;
8345			} else if (keydata.removehd == 0) {
8346				dns_zone_log(zone, ISC_LOG_WARNING,
8347					     "Active key unexpectedly missing "
8348					     "from %s", namebuf);
8349				keydata.refresh = now + HOUR;
8350			} else if (now > keydata.removehd) {
8351				deletekey = ISC_TRUE;
8352			} else {
8353				keydata.refresh = refresh_time(kfetch,
8354							       ISC_FALSE);
8355			}
8356
8357			if  (secure || deletekey) {
8358				/* Delete old version */
8359				CHECK(update_one_rr(kfetch->db, ver, &diff,
8360						    DNS_DIFFOP_DEL, keyname, 0,
8361						    &keydatarr));
8362			}
8363
8364			if (!secure || deletekey)
8365				continue;
8366
8367			dns_rdata_reset(&keydatarr);
8368			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8369			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8370					     dns_rdatatype_keydata,
8371					     &keydata, &keyb);
8372
8373			/* Insert updated version */
8374			CHECK(update_one_rr(kfetch->db, ver, &diff,
8375					    DNS_DIFFOP_ADD, keyname, 0,
8376					    &keydatarr));
8377
8378			set_refreshkeytimer(zone, &keydata, now);
8379		}
8380	}
8381
8382	/*
8383	 * Next scan dnskeyset:
8384	 *   - If new keys are found (i.e., lacking a match in keydataset)
8385	 *     add them to the key zone and set the acceptance timer
8386	 *     to 30 days in the future (or to immediately if we've
8387	 *     determined that we're initializing the zone for the
8388	 *     first time)
8389	 *   - Previously-known keys that have been revoked
8390	 *     must be scheduled for removal from the key zone (or,
8391	 *     if they hadn't been accepted as trust anchors yet
8392	 *     anyway, removed at once)
8393	 *   - Previously-known unrevoked keys whose acceptance timers
8394	 *     have completed are promoted to trust anchors
8395	 *   - All keys not being removed have their refresh
8396	 *     timers updated
8397	 */
8398	for (result = dns_rdataset_first(&kfetch->dnskeyset);
8399	     result == ISC_R_SUCCESS;
8400	     result = dns_rdataset_next(&kfetch->dnskeyset)) {
8401		isc_boolean_t revoked = ISC_FALSE;
8402		isc_boolean_t newkey = ISC_FALSE;
8403		isc_boolean_t updatekey = ISC_FALSE;
8404		isc_boolean_t deletekey = ISC_FALSE;
8405		isc_boolean_t trustkey = ISC_FALSE;
8406
8407		dns_rdata_reset(&dnskeyrr);
8408		dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
8409		result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8410		RUNTIME_CHECK(result == ISC_R_SUCCESS);
8411
8412		/* Skip ZSK's */
8413		if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
8414			continue;
8415
8416		revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
8417
8418		if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
8419			dns_rdata_reset(&keydatarr);
8420			dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8421			result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8422			RUNTIME_CHECK(result == ISC_R_SUCCESS);
8423
8424			if (revoked && revocable(kfetch, &keydata)) {
8425				if (keydata.addhd > now) {
8426					/*
8427					 * Key wasn't trusted yet, and now
8428					 * it's been revoked?  Just remove it
8429					 */
8430					deletekey = ISC_TRUE;
8431				} else if (keydata.removehd == 0) {
8432					/* Remove from secroots */
8433					dns_view_untrust(zone->view, keyname,
8434							 &dnskey, mctx);
8435
8436					/* If initializing, delete now */
8437					if (keydata.addhd == 0)
8438						deletekey = ISC_TRUE;
8439					else
8440						keydata.removehd = now + MONTH;
8441				} else if (keydata.removehd < now) {
8442					/* Scheduled for removal */
8443					deletekey = ISC_TRUE;
8444				}
8445			} else if (revoked) {
8446				if (secure && keydata.removehd == 0) {
8447					dns_zone_log(zone, ISC_LOG_WARNING,
8448						     "Active key for zone "
8449						     "'%s' is revoked but "
8450						     "did not self-sign; "
8451							 "ignoring.", namebuf);
8452						continue;
8453				}
8454			} else if (secure) {
8455				if (keydata.removehd != 0) {
8456					/*
8457					 * Key isn't revoked--but it
8458					 * seems it used to be.
8459					 * Remove it now and add it
8460					 * back as if it were a fresh key.
8461					 */
8462					deletekey = ISC_TRUE;
8463					newkey = ISC_TRUE;
8464				} else if (keydata.addhd > now)
8465					pending++;
8466				else if (keydata.addhd == 0)
8467					keydata.addhd = now;
8468
8469				if (keydata.addhd <= now)
8470					trustkey = ISC_TRUE;
8471			}
8472
8473			if (!deletekey && !newkey)
8474				updatekey = ISC_TRUE;
8475		} else if (secure) {
8476			/*
8477			 * Key wasn't in the key zone but it's
8478			 * revoked now anyway, so just skip it
8479			 */
8480			if (revoked)
8481				continue;
8482
8483			/* Key wasn't in the key zone: add it */
8484			newkey = ISC_TRUE;
8485
8486			if (initializing) {
8487				dns_keytag_t tag = 0;
8488				CHECK(compute_tag(keyname, &dnskey,
8489						  mctx, &tag));
8490				dns_zone_log(zone, ISC_LOG_WARNING,
8491					     "Initializing automatic trust "
8492					     "anchor management for zone '%s'; "
8493					     "DNSKEY ID %d is now trusted, "
8494					     "waiving the normal 30-day "
8495					     "waiting period.",
8496					     namebuf, tag);
8497				trustkey = ISC_TRUE;
8498			}
8499		} else {
8500			/*
8501			 * No previously known key, and the key is not
8502			 * secure, so skip it.
8503			 */
8504			continue;
8505		}
8506
8507		/* Delete old version */
8508		if (deletekey || !newkey)
8509			CHECK(update_one_rr(kfetch->db, ver, &diff,
8510					    DNS_DIFFOP_DEL, keyname, 0,
8511					    &keydatarr));
8512
8513		if (updatekey) {
8514			/* Set refresh timer */
8515			keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8516			dns_rdata_reset(&keydatarr);
8517			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8518			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8519					     dns_rdatatype_keydata,
8520					     &keydata, &keyb);
8521
8522			/* Insert updated version */
8523			CHECK(update_one_rr(kfetch->db, ver, &diff,
8524					    DNS_DIFFOP_ADD, keyname, 0,
8525					    &keydatarr));
8526		} else if (newkey) {
8527			/* Convert DNSKEY to KEYDATA */
8528			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8529			RUNTIME_CHECK(result == ISC_R_SUCCESS);
8530			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
8531					       NULL);
8532			keydata.addhd = initializing ? now : now + MONTH;
8533			keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8534			dns_rdata_reset(&keydatarr);
8535			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8536			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8537					     dns_rdatatype_keydata,
8538					     &keydata, &keyb);
8539
8540			/* Insert into key zone */
8541			CHECK(update_one_rr(kfetch->db, ver, &diff,
8542					    DNS_DIFFOP_ADD, keyname, 0,
8543					    &keydatarr));
8544		}
8545
8546		if (trustkey) {
8547			/* Trust this key. */
8548			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8549			RUNTIME_CHECK(result == ISC_R_SUCCESS);
8550			trust_key(zone, keyname, &dnskey, mctx);
8551		}
8552
8553		if (secure && !deletekey)
8554			set_refreshkeytimer(zone, &keydata, now);
8555	}
8556
8557	/*
8558	 * RFC5011 says, "A trust point that has all of its trust anchors
8559	 * revoked is considered deleted and is treated as if the trust
8560	 * point was never configured."  But if someone revoked their
8561	 * active key before the standby was trusted, that would mean the
8562	 * zone would suddenly be nonsecured.  We avoid this by checking to
8563	 * see if there's pending keydata.  If so, we put a null key in
8564	 * the security roots; then all queries to the zone will fail.
8565	 */
8566	if (pending != 0)
8567		fail_secure(zone, keyname);
8568
8569 done:
8570
8571	if (!ISC_LIST_EMPTY(diff.tuples)) {
8572		/* Write changes to journal file. */
8573		CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
8574					zone->updatemethod));
8575		CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
8576		commit = ISC_TRUE;
8577
8578		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8579		zone_needdump(zone, 30);
8580	}
8581
8582  failure:
8583
8584	dns_diff_clear(&diff);
8585	if (ver != NULL)
8586		dns_db_closeversion(kfetch->db, &ver, commit);
8587
8588 cleanup:
8589	dns_db_detach(&kfetch->db);
8590
8591	INSIST(zone->irefs > 0);
8592	zone->irefs--;
8593	kfetch->zone = NULL;
8594
8595	if (dns_rdataset_isassociated(&kfetch->keydataset))
8596		dns_rdataset_disassociate(&kfetch->keydataset);
8597	if (dns_rdataset_isassociated(&kfetch->dnskeyset))
8598		dns_rdataset_disassociate(&kfetch->dnskeyset);
8599	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8600		dns_rdataset_disassociate(&kfetch->dnskeysigset);
8601
8602	dns_name_free(keyname, mctx);
8603	isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
8604	isc_mem_detach(&mctx);
8605
8606	if (secroots != NULL)
8607		dns_keytable_detach(&secroots);
8608
8609	free_needed = exit_check(zone);
8610	UNLOCK_ZONE(zone);
8611	if (free_needed)
8612		zone_free(zone);
8613}
8614
8615/*
8616 * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
8617 * records from the zone apex.
8618 */
8619static void
8620zone_refreshkeys(dns_zone_t *zone) {
8621	const char me[] = "zone_refreshkeys";
8622	isc_result_t result;
8623	dns_rriterator_t rrit;
8624	dns_db_t *db = NULL;
8625	dns_dbversion_t *ver = NULL;
8626	dns_diff_t diff;
8627	dns_rdata_t rdata = DNS_RDATA_INIT;
8628	dns_rdata_keydata_t kd;
8629	isc_stdtime_t now;
8630	isc_boolean_t commit = ISC_FALSE;
8631	isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
8632
8633	ENTER;
8634	REQUIRE(zone->db != NULL);
8635
8636	isc_stdtime_get(&now);
8637
8638	LOCK_ZONE(zone);
8639	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
8640		isc_time_settoepoch(&zone->refreshkeytime);
8641		UNLOCK_ZONE(zone);
8642		return;
8643	}
8644
8645	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8646	dns_db_attach(zone->db, &db);
8647	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8648
8649	dns_diff_init(zone->mctx, &diff);
8650
8651	CHECK(dns_db_newversion(db, &ver));
8652
8653	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
8654
8655	dns_rriterator_init(&rrit, db, ver, 0);
8656	for (result = dns_rriterator_first(&rrit);
8657	     result == ISC_R_SUCCESS;
8658	     result = dns_rriterator_nextrrset(&rrit)) {
8659		isc_stdtime_t timer = 0xffffffff;
8660		dns_name_t *name = NULL, *kname = NULL;
8661		dns_rdataset_t *kdset = NULL;
8662		dns_keyfetch_t *kfetch;
8663		isc_uint32_t ttl;
8664
8665		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
8666		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
8667		    !dns_rdataset_isassociated(kdset))
8668			continue;
8669
8670		/*
8671		 * Scan the stored keys looking for ones that need
8672		 * removal or refreshing
8673		 */
8674		for (result = dns_rdataset_first(kdset);
8675		     result == ISC_R_SUCCESS;
8676		     result = dns_rdataset_next(kdset)) {
8677			dns_rdata_reset(&rdata);
8678			dns_rdataset_current(kdset, &rdata);
8679			result = dns_rdata_tostruct(&rdata, &kd, NULL);
8680			RUNTIME_CHECK(result == ISC_R_SUCCESS);
8681
8682			/* Removal timer expired? */
8683			if (kd.removehd != 0 && kd.removehd < now) {
8684				CHECK(update_one_rr(db, ver, &diff,
8685						    DNS_DIFFOP_DEL, name, ttl,
8686						    &rdata));
8687				continue;
8688			}
8689
8690			/* Acceptance timer expired? */
8691			if (kd.addhd != 0 && kd.addhd < now)
8692				timer = kd.addhd;
8693
8694			/* Or do we just need to refresh the keyset? */
8695			if (timer > kd.refresh)
8696				timer = kd.refresh;
8697		}
8698
8699		if (timer > now)
8700			continue;
8701
8702		kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
8703		if (kfetch == NULL) {
8704			fetch_err = ISC_TRUE;
8705			goto failure;
8706		}
8707
8708		zone->refreshkeycount++;
8709		kfetch->zone = zone;
8710		zone->irefs++;
8711		INSIST(zone->irefs != 0);
8712		dns_fixedname_init(&kfetch->name);
8713		kname = dns_fixedname_name(&kfetch->name);
8714		dns_name_dup(name, zone->mctx, kname);
8715		dns_rdataset_init(&kfetch->dnskeyset);
8716		dns_rdataset_init(&kfetch->dnskeysigset);
8717		dns_rdataset_init(&kfetch->keydataset);
8718		dns_rdataset_clone(kdset, &kfetch->keydataset);
8719		kfetch->db = NULL;
8720		dns_db_attach(db, &kfetch->db);
8721		kfetch->fetch = NULL;
8722
8723		result = dns_resolver_createfetch(zone->view->resolver,
8724						  kname, dns_rdatatype_dnskey,
8725						  NULL, NULL, NULL,
8726						  DNS_FETCHOPT_NOVALIDATE,
8727						  zone->task,
8728						  keyfetch_done, kfetch,
8729						  &kfetch->dnskeyset,
8730						  &kfetch->dnskeysigset,
8731						  &kfetch->fetch);
8732		if (result == ISC_R_SUCCESS)
8733			fetching = ISC_TRUE;
8734		else {
8735			zone->refreshkeycount--;
8736			zone->irefs--;
8737			dns_db_detach(&kfetch->db);
8738			dns_rdataset_disassociate(&kfetch->keydataset);
8739			dns_name_free(kname, zone->mctx);
8740			isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
8741			dns_zone_log(zone, ISC_LOG_WARNING,
8742				     "Failed to create fetch for "
8743				     "DNSKEY update");
8744			fetch_err = ISC_TRUE;
8745		}
8746	}
8747	if (!ISC_LIST_EMPTY(diff.tuples)) {
8748		CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
8749					zone->updatemethod));
8750		CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
8751		commit = ISC_TRUE;
8752		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8753		zone_needdump(zone, 30);
8754	}
8755
8756  failure:
8757	if (fetch_err) {
8758		/*
8759		 * Error during a key fetch; retry in an hour.
8760		 */
8761		isc_time_t timenow, timethen;
8762		char timebuf[80];
8763
8764		TIME_NOW(&timenow);
8765		DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
8766		zone->refreshkeytime = timethen;
8767		zone_settimer(zone, &timenow);
8768
8769		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
8770		dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
8771			     timebuf);
8772
8773		if (!fetching)
8774			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8775	}
8776
8777	UNLOCK_ZONE(zone);
8778
8779	dns_diff_clear(&diff);
8780	if (ver != NULL) {
8781		dns_rriterator_destroy(&rrit);
8782		dns_db_closeversion(db, &ver, commit);
8783	}
8784	dns_db_detach(&db);
8785}
8786
8787static void
8788zone_maintenance(dns_zone_t *zone) {
8789	const char me[] = "zone_maintenance";
8790	isc_time_t now;
8791	isc_result_t result;
8792	isc_boolean_t dumping;
8793
8794	REQUIRE(DNS_ZONE_VALID(zone));
8795	ENTER;
8796
8797	/*
8798	 * Are we pending load/reload?
8799	 */
8800	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
8801		return;
8802
8803	/*
8804	 * Configuring the view of this zone may have
8805	 * failed, for example because the config file
8806	 * had a syntax error.	In that case, the view
8807	 * adb or resolver will be NULL, and we had better not try
8808	 * to do further maintenance on it.
8809	 */
8810	if (zone->view == NULL || zone->view->adb == NULL)
8811		return;
8812
8813	TIME_NOW(&now);
8814
8815	/*
8816	 * Expire check.
8817	 */
8818	switch (zone->type) {
8819	case dns_zone_redirect:
8820		if (zone->masters == NULL)
8821			break;
8822	case dns_zone_slave:
8823	case dns_zone_stub:
8824		LOCK_ZONE(zone);
8825		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
8826		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8827			zone_expire(zone);
8828			zone->refreshtime = now;
8829		}
8830		UNLOCK_ZONE(zone);
8831		break;
8832	default:
8833		break;
8834	}
8835
8836	/*
8837	 * Up to date check.
8838	 */
8839	switch (zone->type) {
8840	case dns_zone_redirect:
8841		if (zone->masters == NULL)
8842			break;
8843	case dns_zone_slave:
8844	case dns_zone_stub:
8845		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8846		    isc_time_compare(&now, &zone->refreshtime) >= 0)
8847			dns_zone_refresh(zone);
8848		break;
8849	default:
8850		break;
8851	}
8852
8853	/*
8854	 * Slaves send notifies before backing up to disk, masters after.
8855	 */
8856	if (zone->type == dns_zone_slave &&
8857	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8858	    isc_time_compare(&now, &zone->notifytime) >= 0)
8859		zone_notify(zone, &now);
8860
8861	/*
8862	 * Do we need to consolidate the backing store?
8863	 */
8864	switch (zone->type) {
8865	case dns_zone_master:
8866	case dns_zone_slave:
8867	case dns_zone_key:
8868	case dns_zone_redirect:
8869	case dns_zone_stub:
8870		LOCK_ZONE(zone);
8871		if (zone->masterfile != NULL &&
8872		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
8873		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8874		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
8875			dumping = was_dumping(zone);
8876		} else
8877			dumping = ISC_TRUE;
8878		UNLOCK_ZONE(zone);
8879		if (!dumping) {
8880			result = zone_dump(zone, ISC_TRUE); /* task locked */
8881			if (result != ISC_R_SUCCESS)
8882				dns_zone_log(zone, ISC_LOG_WARNING,
8883					     "dump failed: %s",
8884					     dns_result_totext(result));
8885		}
8886		break;
8887	default:
8888		break;
8889	}
8890
8891	/*
8892	 * Master/redirect zones send notifies now, if needed
8893	 */
8894	switch (zone->type) {
8895	case dns_zone_master:
8896	case dns_zone_redirect:
8897		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8898		    isc_time_compare(&now, &zone->notifytime) >= 0)
8899			zone_notify(zone, &now);
8900	default:
8901		break;
8902	}
8903
8904	/*
8905	 * Do we need to refresh keys?
8906	 */
8907	switch (zone->type) {
8908	case dns_zone_key:
8909		if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
8910			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8911			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
8912				zone_refreshkeys(zone);
8913			}
8914		}
8915		break;
8916	case dns_zone_master:
8917		if (!isc_time_isepoch(&zone->refreshkeytime) &&
8918		    isc_time_compare(&now, &zone->refreshkeytime) >= 0)
8919			zone_rekey(zone);
8920	default:
8921		break;
8922	}
8923
8924	switch (zone->type) {
8925	case dns_zone_master:
8926	case dns_zone_redirect:
8927	case dns_zone_slave:
8928		/*
8929		 * Do we need to sign/resign some RRsets?
8930		 */
8931		if (!isc_time_isepoch(&zone->signingtime) &&
8932		    isc_time_compare(&now, &zone->signingtime) >= 0)
8933			zone_sign(zone);
8934		else if (!isc_time_isepoch(&zone->resigntime) &&
8935		    isc_time_compare(&now, &zone->resigntime) >= 0)
8936			zone_resigninc(zone);
8937		else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
8938			isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
8939			zone_nsec3chain(zone);
8940		/*
8941		 * Do we need to issue a key expiry warning?
8942		 */
8943		if (!isc_time_isepoch(&zone->keywarntime) &&
8944		    isc_time_compare(&now, &zone->keywarntime) >= 0)
8945			set_key_expiry_warning(zone, zone->key_expiry,
8946					       isc_time_seconds(&now));
8947		break;
8948
8949	default:
8950		break;
8951	}
8952	zone_settimer(zone, &now);
8953}
8954
8955void
8956dns_zone_markdirty(dns_zone_t *zone) {
8957	isc_uint32_t serial;
8958	isc_result_t result = ISC_R_SUCCESS;
8959	dns_zone_t *secure = NULL;
8960
8961	/*
8962	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
8963	 * could result in a deadlock due to a LOR so we will spin if we
8964	 * can't obtain the both locks.
8965	 */
8966 again:
8967	LOCK_ZONE(zone);
8968	if (zone->type == dns_zone_master) {
8969		if (inline_raw(zone)) {
8970			unsigned int soacount;
8971			secure = zone->secure;
8972			INSIST(secure != zone);
8973			TRYLOCK_ZONE(result, secure);
8974			if (result != ISC_R_SUCCESS) {
8975				UNLOCK_ZONE(zone);
8976				secure = NULL;
8977#ifdef ISC_PLATFORM_USETHREADS
8978				isc_thread_yield();
8979#endif
8980				goto again;
8981			}
8982
8983			ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8984			if (zone->db != NULL) {
8985				result = zone_get_from_db(zone, zone->db, NULL,
8986							  &soacount, &serial,
8987							  NULL, NULL, NULL,
8988							  NULL, NULL);
8989			} else
8990				result = DNS_R_NOTLOADED;
8991			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8992			if (result == ISC_R_SUCCESS && soacount > 0U)
8993				zone_send_secureserial(zone, serial);
8994		}
8995
8996		/* XXXMPA make separate call back */
8997		if (result == ISC_R_SUCCESS)
8998			set_resigntime(zone);
8999	}
9000	if (secure != NULL)
9001		UNLOCK_ZONE(secure);
9002	zone_needdump(zone, DNS_DUMP_DELAY);
9003	UNLOCK_ZONE(zone);
9004}
9005
9006void
9007dns_zone_expire(dns_zone_t *zone) {
9008	REQUIRE(DNS_ZONE_VALID(zone));
9009
9010	LOCK_ZONE(zone);
9011	zone_expire(zone);
9012	UNLOCK_ZONE(zone);
9013}
9014
9015static void
9016zone_expire(dns_zone_t *zone) {
9017	/*
9018	 * 'zone' locked by caller.
9019	 */
9020
9021	REQUIRE(LOCKED_ZONE(zone));
9022
9023	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
9024
9025	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
9026	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
9027	zone->retry = DNS_ZONE_DEFAULTRETRY;
9028	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9029	zone_unload(zone);
9030}
9031
9032void
9033dns_zone_refresh(dns_zone_t *zone) {
9034	isc_interval_t i;
9035	isc_uint32_t oldflags;
9036	unsigned int j;
9037	isc_result_t result;
9038
9039	REQUIRE(DNS_ZONE_VALID(zone));
9040
9041	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
9042		return;
9043
9044	/*
9045	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
9046	 * in progress at a time.
9047	 */
9048
9049	LOCK_ZONE(zone);
9050	oldflags = zone->flags;
9051	if (zone->masterscnt == 0) {
9052		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
9053		if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
9054			dns_zone_log(zone, ISC_LOG_ERROR,
9055				     "cannot refresh: no masters");
9056		goto unlock;
9057	}
9058	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
9059	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9060	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9061	if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
9062		goto unlock;
9063
9064	/*
9065	 * Set the next refresh time as if refresh check has failed.
9066	 * Setting this to the retry time will do that.  XXXMLG
9067	 * If we are successful it will be reset using zone->refresh.
9068	 */
9069	isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
9070			 0);
9071	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
9072	if (result != ISC_R_SUCCESS)
9073		dns_zone_log(zone, ISC_LOG_WARNING,
9074			     "isc_time_nowplusinterval() failed: %s",
9075			     dns_result_totext(result));
9076
9077	/*
9078	 * When lacking user-specified timer values from the SOA,
9079	 * do exponential backoff of the retry time up to a
9080	 * maximum of six hours.
9081	 */
9082	if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
9083		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
9084
9085	zone->curmaster = 0;
9086	for (j = 0; j < zone->masterscnt; j++)
9087		zone->mastersok[j] = ISC_FALSE;
9088	/* initiate soa query */
9089	queue_soa_query(zone);
9090 unlock:
9091	UNLOCK_ZONE(zone);
9092}
9093
9094isc_result_t
9095dns_zone_flush(dns_zone_t *zone) {
9096	isc_result_t result = ISC_R_SUCCESS;
9097	isc_boolean_t dumping;
9098
9099	REQUIRE(DNS_ZONE_VALID(zone));
9100
9101	LOCK_ZONE(zone);
9102	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
9103	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9104	    zone->masterfile != NULL) {
9105		result = ISC_R_ALREADYRUNNING;
9106		dumping = was_dumping(zone);
9107	} else
9108		dumping = ISC_TRUE;
9109	UNLOCK_ZONE(zone);
9110	if (!dumping)
9111		result = zone_dump(zone, ISC_FALSE);	/* Unknown task. */
9112	return (result);
9113}
9114
9115isc_result_t
9116dns_zone_dump(dns_zone_t *zone) {
9117	isc_result_t result = ISC_R_ALREADYRUNNING;
9118	isc_boolean_t dumping;
9119
9120	REQUIRE(DNS_ZONE_VALID(zone));
9121
9122	LOCK_ZONE(zone);
9123	dumping = was_dumping(zone);
9124	UNLOCK_ZONE(zone);
9125	if (!dumping)
9126		result = zone_dump(zone, ISC_FALSE);	/* Unknown task. */
9127	return (result);
9128}
9129
9130static void
9131zone_needdump(dns_zone_t *zone, unsigned int delay) {
9132	const char me[] = "zone_needdump";
9133	isc_time_t dumptime;
9134	isc_time_t now;
9135
9136	/*
9137	 * 'zone' locked by caller
9138	 */
9139
9140	REQUIRE(DNS_ZONE_VALID(zone));
9141	REQUIRE(LOCKED_ZONE(zone));
9142	ENTER;
9143
9144	/*
9145	 * Do we have a place to dump to and are we loaded?
9146	 */
9147	if (zone->masterfile == NULL ||
9148	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
9149		return;
9150
9151	TIME_NOW(&now);
9152	/* add some noise */
9153	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
9154
9155	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9156	if (isc_time_isepoch(&zone->dumptime) ||
9157	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
9158		zone->dumptime = dumptime;
9159	if (zone->task != NULL)
9160		zone_settimer(zone, &now);
9161}
9162
9163static void
9164dump_done(void *arg, isc_result_t result) {
9165	const char me[] = "dump_done";
9166	dns_zone_t *zone = arg;
9167	dns_db_t *db;
9168	dns_dbversion_t *version;
9169	isc_boolean_t again = ISC_FALSE;
9170	isc_boolean_t compact = ISC_FALSE;
9171	isc_uint32_t serial;
9172	isc_result_t tresult;
9173
9174	REQUIRE(DNS_ZONE_VALID(zone));
9175
9176	ENTER;
9177
9178	if (result == ISC_R_SUCCESS && zone->journal != NULL &&
9179	    zone->journalsize != -1) {
9180
9181		/*
9182		 * We don't own these, zone->dctx must stay valid.
9183		 */
9184		db = dns_dumpctx_db(zone->dctx);
9185		version = dns_dumpctx_version(zone->dctx);
9186
9187		tresult = dns_db_getsoaserial(db, version, &serial);
9188		/*
9189		 * If there is a secure version of this zone
9190		 * use its serial if it is less than ours.
9191		 */
9192		if (tresult == ISC_R_SUCCESS && inline_raw(zone) &&
9193		    zone->secure->db != NULL)
9194		{
9195			isc_uint32_t sserial;
9196			isc_result_t mresult;
9197
9198			mresult = dns_db_getsoaserial(zone->secure->db,
9199						      NULL, &sserial);
9200			if (mresult == ISC_R_SUCCESS &&
9201			    isc_serial_lt(sserial, serial))
9202				serial = sserial;
9203		}
9204		/*
9205		 * Note: we are task locked here so we can test
9206		 * zone->xfr safely.
9207		 */
9208		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
9209			tresult = dns_journal_compact(zone->mctx,
9210						      zone->journal,
9211						      serial,
9212						      zone->journalsize);
9213			switch (tresult) {
9214			case ISC_R_SUCCESS:
9215			case ISC_R_NOSPACE:
9216			case ISC_R_NOTFOUND:
9217				dns_zone_log(zone, ISC_LOG_DEBUG(3),
9218					     "dns_journal_compact: %s",
9219					     dns_result_totext(tresult));
9220				break;
9221			default:
9222				dns_zone_log(zone, ISC_LOG_ERROR,
9223					     "dns_journal_compact failed: %s",
9224					     dns_result_totext(tresult));
9225				break;
9226			}
9227		} else if (tresult == ISC_R_SUCCESS) {
9228			compact = ISC_TRUE;
9229			zone->compact_serial = serial;
9230		}
9231	}
9232
9233	LOCK_ZONE(zone);
9234	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9235	if (compact)
9236		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
9237	if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
9238		/*
9239		 * Try again in a short while.
9240		 */
9241		zone_needdump(zone, DNS_DUMP_DELAY);
9242	} else if (result == ISC_R_SUCCESS &&
9243		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9244		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9245		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9246		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9247		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9248		isc_time_settoepoch(&zone->dumptime);
9249		again = ISC_TRUE;
9250	} else if (result == ISC_R_SUCCESS)
9251		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9252
9253	if (zone->dctx != NULL)
9254		dns_dumpctx_detach(&zone->dctx);
9255	zonemgr_putio(&zone->writeio);
9256	UNLOCK_ZONE(zone);
9257	if (again)
9258		(void)zone_dump(zone, ISC_FALSE);
9259	dns_zone_idetach(&zone);
9260}
9261
9262static isc_result_t
9263zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
9264	const char me[] = "zone_dump";
9265	isc_result_t result;
9266	dns_dbversion_t *version = NULL;
9267	isc_boolean_t again;
9268	dns_db_t *db = NULL;
9269	char *masterfile = NULL;
9270	dns_masterformat_t masterformat = dns_masterformat_none;
9271
9272/*
9273 * 'compact' MUST only be set if we are task locked.
9274 */
9275
9276	REQUIRE(DNS_ZONE_VALID(zone));
9277	ENTER;
9278
9279 redo:
9280	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9281	if (zone->db != NULL)
9282		dns_db_attach(zone->db, &db);
9283	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9284	LOCK_ZONE(zone);
9285	if (zone->masterfile != NULL) {
9286		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
9287		masterformat = zone->masterformat;
9288	}
9289	UNLOCK_ZONE(zone);
9290	if (db == NULL) {
9291		result = DNS_R_NOTLOADED;
9292		goto fail;
9293	}
9294	if (masterfile == NULL) {
9295		result = DNS_R_NOMASTERFILE;
9296		goto fail;
9297	}
9298
9299	if (compact && zone->type != dns_zone_stub) {
9300		dns_zone_t *dummy = NULL;
9301		LOCK_ZONE(zone);
9302		zone_iattach(zone, &dummy);
9303		result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
9304				       zone_gotwritehandle, zone,
9305				       &zone->writeio);
9306		if (result != ISC_R_SUCCESS)
9307			zone_idetach(&dummy);
9308		else
9309			result = DNS_R_CONTINUE;
9310		UNLOCK_ZONE(zone);
9311	} else {
9312		const dns_master_style_t *output_style;
9313
9314		dns_masterrawheader_t rawdata;
9315		dns_db_currentversion(db, &version);
9316		dns_master_initrawheader(&rawdata);
9317		if (inline_secure(zone))
9318			get_raw_serial(zone->raw, &rawdata);
9319		if (zone->type == dns_zone_key)
9320			output_style = &dns_master_style_keyzone;
9321		else
9322			output_style = &dns_master_style_default;
9323		result = dns_master_dump3(zone->mctx, db, version,
9324					  output_style, masterfile,
9325					  masterformat, &rawdata);
9326		dns_db_closeversion(db, &version, ISC_FALSE);
9327	}
9328 fail:
9329	if (db != NULL)
9330		dns_db_detach(&db);
9331	if (masterfile != NULL)
9332		isc_mem_free(zone->mctx, masterfile);
9333	masterfile = NULL;
9334
9335	if (result == DNS_R_CONTINUE)
9336		return (ISC_R_SUCCESS); /* XXXMPA */
9337
9338	again = ISC_FALSE;
9339	LOCK_ZONE(zone);
9340	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9341	if (result != ISC_R_SUCCESS) {
9342		/*
9343		 * Try again in a short while.
9344		 */
9345		zone_needdump(zone, DNS_DUMP_DELAY);
9346	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9347		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9348		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9349		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9350		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9351		isc_time_settoepoch(&zone->dumptime);
9352		again = ISC_TRUE;
9353	} else
9354		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9355	UNLOCK_ZONE(zone);
9356	if (again)
9357		goto redo;
9358
9359	return (result);
9360}
9361
9362static isc_result_t
9363dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
9364	     dns_masterformat_t format, const isc_uint32_t rawversion)
9365{
9366	isc_result_t result;
9367	dns_dbversion_t *version = NULL;
9368	dns_db_t *db = NULL;
9369	dns_masterrawheader_t rawdata;
9370
9371	REQUIRE(DNS_ZONE_VALID(zone));
9372
9373	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9374	if (zone->db != NULL)
9375		dns_db_attach(zone->db, &db);
9376	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9377	if (db == NULL)
9378		return (DNS_R_NOTLOADED);
9379
9380	dns_db_currentversion(db, &version);
9381	dns_master_initrawheader(&rawdata);
9382	if (rawversion == 0)
9383		rawdata.flags |= DNS_MASTERRAW_COMPAT;
9384	else if (inline_secure(zone))
9385		get_raw_serial(zone->raw, &rawdata);
9386	else if (zone->sourceserialset) {
9387		rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
9388		rawdata.sourceserial = zone->sourceserial;
9389	}
9390	result = dns_master_dumptostream3(zone->mctx, db, version, style,
9391					  format, &rawdata, fd);
9392	dns_db_closeversion(db, &version, ISC_FALSE);
9393	dns_db_detach(&db);
9394	return (result);
9395}
9396
9397isc_result_t
9398dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9399		       const dns_master_style_t *style,
9400		       const isc_uint32_t rawversion)
9401{
9402	return (dumptostream(zone, fd, style, format, rawversion));
9403}
9404
9405isc_result_t
9406dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9407		       const dns_master_style_t *style) {
9408	return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
9409}
9410
9411isc_result_t
9412dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
9413	return (dumptostream(zone, fd, &dns_master_style_default,
9414			     dns_masterformat_text, 0));
9415}
9416
9417isc_result_t
9418dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
9419	return (dumptostream(zone, fd, &dns_master_style_full,
9420			     dns_masterformat_text, 0));
9421}
9422
9423void
9424dns_zone_unload(dns_zone_t *zone) {
9425	REQUIRE(DNS_ZONE_VALID(zone));
9426
9427	LOCK_ZONE(zone);
9428	zone_unload(zone);
9429	UNLOCK_ZONE(zone);
9430}
9431
9432static void
9433notify_cancel(dns_zone_t *zone) {
9434	dns_notify_t *notify;
9435
9436	/*
9437	 * 'zone' locked by caller.
9438	 */
9439
9440	REQUIRE(LOCKED_ZONE(zone));
9441
9442	for (notify = ISC_LIST_HEAD(zone->notifies);
9443	     notify != NULL;
9444	     notify = ISC_LIST_NEXT(notify, link)) {
9445		if (notify->find != NULL)
9446			dns_adb_cancelfind(notify->find);
9447		if (notify->request != NULL)
9448			dns_request_cancel(notify->request);
9449	}
9450}
9451
9452static void
9453forward_cancel(dns_zone_t *zone) {
9454	dns_forward_t *forward;
9455
9456	/*
9457	 * 'zone' locked by caller.
9458	 */
9459
9460	REQUIRE(LOCKED_ZONE(zone));
9461
9462	for (forward = ISC_LIST_HEAD(zone->forwards);
9463	     forward != NULL;
9464	     forward = ISC_LIST_NEXT(forward, link)) {
9465		if (forward->request != NULL)
9466			dns_request_cancel(forward->request);
9467	}
9468}
9469
9470static void
9471zone_unload(dns_zone_t *zone) {
9472	/*
9473	 * 'zone' locked by caller.
9474	 */
9475
9476	REQUIRE(LOCKED_ZONE(zone));
9477
9478	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
9479	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9480		if (zone->writeio != NULL)
9481			zonemgr_cancelio(zone->writeio);
9482
9483		if (zone->dctx != NULL)
9484			dns_dumpctx_cancel(zone->dctx);
9485	}
9486	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9487	zone_detachdb(zone);
9488	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9489	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
9490	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9491}
9492
9493void
9494dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9495	REQUIRE(DNS_ZONE_VALID(zone));
9496	REQUIRE(val > 0);
9497
9498	zone->minrefresh = val;
9499}
9500
9501void
9502dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9503	REQUIRE(DNS_ZONE_VALID(zone));
9504	REQUIRE(val > 0);
9505
9506	zone->maxrefresh = val;
9507}
9508
9509void
9510dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
9511	REQUIRE(DNS_ZONE_VALID(zone));
9512	REQUIRE(val > 0);
9513
9514	zone->minretry = val;
9515}
9516
9517void
9518dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
9519	REQUIRE(DNS_ZONE_VALID(zone));
9520	REQUIRE(val > 0);
9521
9522	zone->maxretry = val;
9523}
9524
9525static isc_boolean_t
9526notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
9527	dns_notify_t *notify;
9528
9529	for (notify = ISC_LIST_HEAD(zone->notifies);
9530	     notify != NULL;
9531	     notify = ISC_LIST_NEXT(notify, link)) {
9532		if (notify->request != NULL)
9533			continue;
9534		if (name != NULL && dns_name_dynamic(&notify->ns) &&
9535		    dns_name_equal(name, &notify->ns))
9536			return (ISC_TRUE);
9537		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
9538			return (ISC_TRUE);
9539	}
9540	return (ISC_FALSE);
9541}
9542
9543static isc_boolean_t
9544notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
9545	dns_tsigkey_t *key = NULL;
9546	isc_sockaddr_t src;
9547	isc_sockaddr_t any;
9548	isc_boolean_t isself;
9549	isc_netaddr_t dstaddr;
9550	isc_result_t result;
9551
9552	if (zone->view == NULL || zone->isself == NULL)
9553		return (ISC_FALSE);
9554
9555	switch (isc_sockaddr_pf(dst)) {
9556	case PF_INET:
9557		src = zone->notifysrc4;
9558		isc_sockaddr_any(&any);
9559		break;
9560	case PF_INET6:
9561		src = zone->notifysrc6;
9562		isc_sockaddr_any6(&any);
9563		break;
9564	default:
9565		return (ISC_FALSE);
9566	}
9567
9568	/*
9569	 * When sending from any the kernel will assign a source address
9570	 * that matches the destination address.
9571	 */
9572	if (isc_sockaddr_eqaddr(&any, &src))
9573		src = *dst;
9574
9575	isc_netaddr_fromsockaddr(&dstaddr, dst);
9576	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
9577	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
9578		return (ISC_FALSE);
9579	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
9580				zone->isselfarg);
9581	if (key != NULL)
9582		dns_tsigkey_detach(&key);
9583	return (isself);
9584}
9585
9586static void
9587notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
9588	isc_mem_t *mctx;
9589
9590	/*
9591	 * Caller holds zone lock.
9592	 */
9593	REQUIRE(DNS_NOTIFY_VALID(notify));
9594
9595	if (notify->zone != NULL) {
9596		if (!locked)
9597			LOCK_ZONE(notify->zone);
9598		REQUIRE(LOCKED_ZONE(notify->zone));
9599		if (ISC_LINK_LINKED(notify, link))
9600			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
9601		if (!locked)
9602			UNLOCK_ZONE(notify->zone);
9603		if (locked)
9604			zone_idetach(&notify->zone);
9605		else
9606			dns_zone_idetach(&notify->zone);
9607	}
9608	if (notify->find != NULL)
9609		dns_adb_destroyfind(&notify->find);
9610	if (notify->request != NULL)
9611		dns_request_destroy(&notify->request);
9612	if (dns_name_dynamic(&notify->ns))
9613		dns_name_free(&notify->ns, notify->mctx);
9614	if (notify->key != NULL)
9615		dns_tsigkey_detach(&notify->key);
9616	mctx = notify->mctx;
9617	isc_mem_put(notify->mctx, notify, sizeof(*notify));
9618	isc_mem_detach(&mctx);
9619}
9620
9621static isc_result_t
9622notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
9623	dns_notify_t *notify;
9624
9625	REQUIRE(notifyp != NULL && *notifyp == NULL);
9626
9627	notify = isc_mem_get(mctx, sizeof(*notify));
9628	if (notify == NULL)
9629		return (ISC_R_NOMEMORY);
9630
9631	notify->mctx = NULL;
9632	isc_mem_attach(mctx, &notify->mctx);
9633	notify->flags = flags;
9634	notify->zone = NULL;
9635	notify->find = NULL;
9636	notify->request = NULL;
9637	notify->key = NULL;
9638	isc_sockaddr_any(&notify->dst);
9639	dns_name_init(&notify->ns, NULL);
9640	ISC_LINK_INIT(notify, link);
9641	notify->magic = NOTIFY_MAGIC;
9642	*notifyp = notify;
9643	return (ISC_R_SUCCESS);
9644}
9645
9646/*
9647 * XXXAG should check for DNS_ZONEFLG_EXITING
9648 */
9649static void
9650process_adb_event(isc_task_t *task, isc_event_t *ev) {
9651	dns_notify_t *notify;
9652	isc_eventtype_t result;
9653
9654	UNUSED(task);
9655
9656	notify = ev->ev_arg;
9657	REQUIRE(DNS_NOTIFY_VALID(notify));
9658	INSIST(task == notify->zone->task);
9659	result = ev->ev_type;
9660	isc_event_free(&ev);
9661	if (result == DNS_EVENT_ADBMOREADDRESSES) {
9662		dns_adb_destroyfind(&notify->find);
9663		notify_find_address(notify);
9664		return;
9665	}
9666	if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
9667		LOCK_ZONE(notify->zone);
9668		notify_send(notify);
9669		UNLOCK_ZONE(notify->zone);
9670	}
9671	notify_destroy(notify, ISC_FALSE);
9672}
9673
9674static void
9675notify_find_address(dns_notify_t *notify) {
9676	isc_result_t result;
9677	unsigned int options;
9678
9679	REQUIRE(DNS_NOTIFY_VALID(notify));
9680	options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
9681		  DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
9682
9683	if (notify->zone->view->adb == NULL)
9684		goto destroy;
9685
9686	result = dns_adb_createfind(notify->zone->view->adb,
9687				    notify->zone->task,
9688				    process_adb_event, notify,
9689				    &notify->ns, dns_rootname, 0,
9690				    options, 0, NULL,
9691				    notify->zone->view->dstport,
9692				    &notify->find);
9693
9694	/* Something failed? */
9695	if (result != ISC_R_SUCCESS)
9696		goto destroy;
9697
9698	/* More addresses pending? */
9699	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
9700		return;
9701
9702	/* We have as many addresses as we can get. */
9703	LOCK_ZONE(notify->zone);
9704	notify_send(notify);
9705	UNLOCK_ZONE(notify->zone);
9706
9707 destroy:
9708	notify_destroy(notify, ISC_FALSE);
9709}
9710
9711
9712static isc_result_t
9713notify_send_queue(dns_notify_t *notify) {
9714	isc_event_t *e;
9715	isc_result_t result;
9716
9717	e = isc_event_allocate(notify->mctx, NULL,
9718			       DNS_EVENT_NOTIFYSENDTOADDR,
9719			       notify_send_toaddr,
9720			       notify, sizeof(isc_event_t));
9721	if (e == NULL)
9722		return (ISC_R_NOMEMORY);
9723	e->ev_arg = notify;
9724	e->ev_sender = NULL;
9725	result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
9726					 notify->zone->task, &e);
9727	if (result != ISC_R_SUCCESS)
9728		isc_event_free(&e);
9729	return (result);
9730}
9731
9732static void
9733notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
9734	dns_notify_t *notify;
9735	isc_result_t result;
9736	dns_message_t *message = NULL;
9737	isc_netaddr_t dstip;
9738	dns_tsigkey_t *key = NULL;
9739	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9740	isc_sockaddr_t src;
9741	int timeout;
9742	isc_boolean_t have_notifysource = ISC_FALSE;
9743
9744	notify = event->ev_arg;
9745	REQUIRE(DNS_NOTIFY_VALID(notify));
9746
9747	UNUSED(task);
9748
9749	LOCK_ZONE(notify->zone);
9750
9751	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
9752		result = ISC_R_CANCELED;
9753		goto cleanup;
9754	}
9755
9756	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
9757	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
9758	    notify->zone->view->requestmgr == NULL ||
9759	    notify->zone->db == NULL) {
9760		result = ISC_R_CANCELED;
9761		goto cleanup;
9762	}
9763
9764	/*
9765	 * The raw IPv4 address should also exist.  Don't send to the
9766	 * mapped form.
9767	 */
9768	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
9769	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
9770		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9771		notify_log(notify->zone, ISC_LOG_DEBUG(3),
9772			   "notify: ignoring IPv6 mapped IPV4 address: %s",
9773			   addrbuf);
9774		result = ISC_R_CANCELED;
9775		goto cleanup;
9776	}
9777
9778	result = notify_createmessage(notify->zone, notify->flags, &message);
9779	if (result != ISC_R_SUCCESS)
9780		goto cleanup;
9781
9782	if (notify->key != NULL) {
9783		/* Transfer ownership of key */
9784		key = notify->key;
9785		notify->key = NULL;
9786	} else {
9787		isc_netaddr_fromsockaddr(&dstip, &notify->dst);
9788		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9789		result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
9790		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9791			notify_log(notify->zone, ISC_LOG_ERROR,
9792				   "NOTIFY to %s not sent. "
9793				   "Peer TSIG key lookup failure.", addrbuf);
9794			goto cleanup_message;
9795		}
9796	}
9797
9798	/* XXX: should we log the tsig key too? */
9799	notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
9800		   addrbuf);
9801	if (notify->zone->view->peers != NULL) {
9802		dns_peer_t *peer = NULL;
9803		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
9804						 &dstip, &peer);
9805		if (result == ISC_R_SUCCESS) {
9806			result = dns_peer_getnotifysource(peer, &src);
9807			if (result == ISC_R_SUCCESS)
9808				have_notifysource = ISC_TRUE;
9809		}
9810	}
9811	switch (isc_sockaddr_pf(&notify->dst)) {
9812	case PF_INET:
9813		if (!have_notifysource)
9814			src = notify->zone->notifysrc4;
9815		break;
9816	case PF_INET6:
9817		if (!have_notifysource)
9818			src = notify->zone->notifysrc6;
9819		break;
9820	default:
9821		result = ISC_R_NOTIMPLEMENTED;
9822		goto cleanup_key;
9823	}
9824	timeout = 15;
9825	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
9826		timeout = 30;
9827	result = dns_request_createvia2(notify->zone->view->requestmgr,
9828					message, &src, &notify->dst, 0, key,
9829					timeout * 3, timeout,
9830					notify->zone->task, notify_done,
9831					notify, &notify->request);
9832	if (result == ISC_R_SUCCESS) {
9833		if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
9834			inc_stats(notify->zone,
9835				  dns_zonestatscounter_notifyoutv4);
9836		} else {
9837			inc_stats(notify->zone,
9838				  dns_zonestatscounter_notifyoutv6);
9839		}
9840	}
9841
9842 cleanup_key:
9843	if (key != NULL)
9844		dns_tsigkey_detach(&key);
9845 cleanup_message:
9846	dns_message_destroy(&message);
9847 cleanup:
9848	UNLOCK_ZONE(notify->zone);
9849	isc_event_free(&event);
9850	if (result != ISC_R_SUCCESS)
9851		notify_destroy(notify, ISC_FALSE);
9852}
9853
9854static void
9855notify_send(dns_notify_t *notify) {
9856	dns_adbaddrinfo_t *ai;
9857	isc_sockaddr_t dst;
9858	isc_result_t result;
9859	dns_notify_t *new = NULL;
9860
9861	/*
9862	 * Zone lock held by caller.
9863	 */
9864	REQUIRE(DNS_NOTIFY_VALID(notify));
9865	REQUIRE(LOCKED_ZONE(notify->zone));
9866
9867	for (ai = ISC_LIST_HEAD(notify->find->list);
9868	     ai != NULL;
9869	     ai = ISC_LIST_NEXT(ai, publink)) {
9870		dst = ai->sockaddr;
9871		if (notify_isqueued(notify->zone, NULL, &dst))
9872			continue;
9873		if (notify_isself(notify->zone, &dst))
9874			continue;
9875		new = NULL;
9876		result = notify_create(notify->mctx,
9877				       (notify->flags & DNS_NOTIFY_NOSOA),
9878				       &new);
9879		if (result != ISC_R_SUCCESS)
9880			goto cleanup;
9881		zone_iattach(notify->zone, &new->zone);
9882		ISC_LIST_APPEND(new->zone->notifies, new, link);
9883		new->dst = dst;
9884		result = notify_send_queue(new);
9885		if (result != ISC_R_SUCCESS)
9886			goto cleanup;
9887		new = NULL;
9888	}
9889
9890 cleanup:
9891	if (new != NULL)
9892		notify_destroy(new, ISC_TRUE);
9893}
9894
9895void
9896dns_zone_notify(dns_zone_t *zone) {
9897	isc_time_t now;
9898
9899	REQUIRE(DNS_ZONE_VALID(zone));
9900
9901	LOCK_ZONE(zone);
9902	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9903
9904	TIME_NOW(&now);
9905	zone_settimer(zone, &now);
9906	UNLOCK_ZONE(zone);
9907}
9908
9909static void
9910zone_notify(dns_zone_t *zone, isc_time_t *now) {
9911	dns_dbnode_t *node = NULL;
9912	dns_db_t *zonedb = NULL;
9913	dns_dbversion_t *version = NULL;
9914	dns_name_t *origin = NULL;
9915	dns_name_t master;
9916	dns_rdata_ns_t ns;
9917	dns_rdata_soa_t soa;
9918	isc_uint32_t serial;
9919	dns_rdata_t rdata = DNS_RDATA_INIT;
9920	dns_rdataset_t nsrdset;
9921	dns_rdataset_t soardset;
9922	isc_result_t result;
9923	dns_notify_t *notify = NULL;
9924	unsigned int i;
9925	isc_sockaddr_t dst;
9926	isc_boolean_t isqueued;
9927	dns_notifytype_t notifytype;
9928	unsigned int flags = 0;
9929	isc_boolean_t loggednotify = ISC_FALSE;
9930
9931	REQUIRE(DNS_ZONE_VALID(zone));
9932
9933	LOCK_ZONE(zone);
9934	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9935	notifytype = zone->notifytype;
9936	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
9937	UNLOCK_ZONE(zone);
9938
9939	if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
9940		return;
9941
9942	if (notifytype == dns_notifytype_no)
9943		return;
9944
9945	if (notifytype == dns_notifytype_masteronly &&
9946	    zone->type != dns_zone_master)
9947		return;
9948
9949	origin = &zone->origin;
9950
9951	/*
9952	 * If the zone is dialup we are done as we don't want to send
9953	 * the current soa so as to force a refresh query.
9954	 */
9955	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
9956		flags |= DNS_NOTIFY_NOSOA;
9957
9958	/*
9959	 * Get SOA RRset.
9960	 */
9961	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9962	if (zone->db != NULL)
9963		dns_db_attach(zone->db, &zonedb);
9964	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9965	if (zonedb == NULL)
9966		return;
9967	dns_db_currentversion(zonedb, &version);
9968	result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
9969	if (result != ISC_R_SUCCESS)
9970		goto cleanup1;
9971
9972	dns_rdataset_init(&soardset);
9973	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
9974				     dns_rdatatype_none, 0, &soardset, NULL);
9975	if (result != ISC_R_SUCCESS)
9976		goto cleanup2;
9977
9978	/*
9979	 * Find serial and master server's name.
9980	 */
9981	dns_name_init(&master, NULL);
9982	result = dns_rdataset_first(&soardset);
9983	if (result != ISC_R_SUCCESS)
9984		goto cleanup3;
9985	dns_rdataset_current(&soardset, &rdata);
9986	result = dns_rdata_tostruct(&rdata, &soa, NULL);
9987	RUNTIME_CHECK(result == ISC_R_SUCCESS);
9988	dns_rdata_reset(&rdata);
9989	result = dns_name_dup(&soa.origin, zone->mctx, &master);
9990	serial = soa.serial;
9991	dns_rdataset_disassociate(&soardset);
9992	if (result != ISC_R_SUCCESS)
9993		goto cleanup3;
9994
9995	/*
9996	 * Enqueue notify requests for 'also-notify' servers.
9997	 */
9998	LOCK_ZONE(zone);
9999	for (i = 0; i < zone->notifycnt; i++) {
10000		dns_tsigkey_t *key = NULL;
10001
10002		dst = zone->notify[i];
10003		if (notify_isqueued(zone, NULL, &dst))
10004			continue;
10005
10006		result = notify_create(zone->mctx, flags, &notify);
10007		if (result != ISC_R_SUCCESS)
10008			continue;
10009
10010		zone_iattach(zone, &notify->zone);
10011		notify->dst = dst;
10012
10013		if ((zone->notifykeynames != NULL) &&
10014		    (zone->notifykeynames[i] != NULL)) {
10015			dns_view_t *view = dns_zone_getview(zone);
10016			dns_name_t *keyname = zone->notifykeynames[i];
10017			result = dns_view_gettsig(view, keyname, &key);
10018			if (result == ISC_R_SUCCESS) {
10019				notify->key = key;
10020				key = NULL;
10021			}
10022		}
10023
10024		ISC_LIST_APPEND(zone->notifies, notify, link);
10025		result = notify_send_queue(notify);
10026		if (result != ISC_R_SUCCESS)
10027			notify_destroy(notify, ISC_TRUE);
10028		if (!loggednotify) {
10029			notify_log(zone, ISC_LOG_INFO,
10030				   "sending notifies (serial %u)",
10031				   serial);
10032			loggednotify = ISC_TRUE;
10033		}
10034		notify = NULL;
10035	}
10036	UNLOCK_ZONE(zone);
10037
10038	if (notifytype == dns_notifytype_explicit)
10039		goto cleanup3;
10040
10041	/*
10042	 * Process NS RRset to generate notifies.
10043	 */
10044
10045	dns_rdataset_init(&nsrdset);
10046	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
10047				     dns_rdatatype_none, 0, &nsrdset, NULL);
10048	if (result != ISC_R_SUCCESS)
10049		goto cleanup3;
10050
10051	result = dns_rdataset_first(&nsrdset);
10052	while (result == ISC_R_SUCCESS) {
10053		dns_rdataset_current(&nsrdset, &rdata);
10054		result = dns_rdata_tostruct(&rdata, &ns, NULL);
10055		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10056		dns_rdata_reset(&rdata);
10057		/*
10058		 * Don't notify the master server unless explicitly
10059		 * configured to do so.
10060		 */
10061		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
10062		    dns_name_compare(&master, &ns.name) == 0) {
10063			result = dns_rdataset_next(&nsrdset);
10064			continue;
10065		}
10066
10067		if (!loggednotify) {
10068			notify_log(zone, ISC_LOG_INFO,
10069				   "sending notifies (serial %u)",
10070				   serial);
10071			loggednotify = ISC_TRUE;
10072		}
10073
10074		LOCK_ZONE(zone);
10075		isqueued = notify_isqueued(zone, &ns.name, NULL);
10076		UNLOCK_ZONE(zone);
10077		if (isqueued) {
10078			result = dns_rdataset_next(&nsrdset);
10079			continue;
10080		}
10081		result = notify_create(zone->mctx, flags, &notify);
10082		if (result != ISC_R_SUCCESS)
10083			continue;
10084		dns_zone_iattach(zone, &notify->zone);
10085		result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
10086		if (result != ISC_R_SUCCESS) {
10087			LOCK_ZONE(zone);
10088			notify_destroy(notify, ISC_TRUE);
10089			UNLOCK_ZONE(zone);
10090			continue;
10091		}
10092		LOCK_ZONE(zone);
10093		ISC_LIST_APPEND(zone->notifies, notify, link);
10094		UNLOCK_ZONE(zone);
10095		notify_find_address(notify);
10096		notify = NULL;
10097		result = dns_rdataset_next(&nsrdset);
10098	}
10099	dns_rdataset_disassociate(&nsrdset);
10100
10101 cleanup3:
10102	if (dns_name_dynamic(&master))
10103		dns_name_free(&master, zone->mctx);
10104 cleanup2:
10105	dns_db_detachnode(zonedb, &node);
10106 cleanup1:
10107	dns_db_closeversion(zonedb, &version, ISC_FALSE);
10108	dns_db_detach(&zonedb);
10109}
10110
10111/***
10112 *** Private
10113 ***/
10114
10115static inline isc_result_t
10116save_nsrrset(dns_message_t *message, dns_name_t *name,
10117	     dns_db_t *db, dns_dbversion_t *version)
10118{
10119	dns_rdataset_t *nsrdataset = NULL;
10120	dns_rdataset_t *rdataset = NULL;
10121	dns_dbnode_t *node = NULL;
10122	dns_rdata_ns_t ns;
10123	isc_result_t result;
10124	dns_rdata_t rdata = DNS_RDATA_INIT;
10125
10126	/*
10127	 * Extract NS RRset from message.
10128	 */
10129	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
10130				      dns_rdatatype_ns, dns_rdatatype_none,
10131				      NULL, &nsrdataset);
10132	if (result != ISC_R_SUCCESS)
10133		goto fail;
10134
10135	/*
10136	 * Add NS rdataset.
10137	 */
10138	result = dns_db_findnode(db, name, ISC_TRUE, &node);
10139	if (result != ISC_R_SUCCESS)
10140		goto fail;
10141	result = dns_db_addrdataset(db, node, version, 0,
10142				    nsrdataset, 0, NULL);
10143	dns_db_detachnode(db, &node);
10144	if (result != ISC_R_SUCCESS)
10145		goto fail;
10146	/*
10147	 * Add glue rdatasets.
10148	 */
10149	for (result = dns_rdataset_first(nsrdataset);
10150	     result == ISC_R_SUCCESS;
10151	     result = dns_rdataset_next(nsrdataset)) {
10152		dns_rdataset_current(nsrdataset, &rdata);
10153		result = dns_rdata_tostruct(&rdata, &ns, NULL);
10154		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10155		dns_rdata_reset(&rdata);
10156		if (!dns_name_issubdomain(&ns.name, name))
10157			continue;
10158		rdataset = NULL;
10159		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10160					      &ns.name, dns_rdatatype_aaaa,
10161					      dns_rdatatype_none, NULL,
10162					      &rdataset);
10163		if (result == ISC_R_SUCCESS) {
10164			result = dns_db_findnode(db, &ns.name,
10165						 ISC_TRUE, &node);
10166			if (result != ISC_R_SUCCESS)
10167				goto fail;
10168			result = dns_db_addrdataset(db, node, version, 0,
10169						    rdataset, 0, NULL);
10170			dns_db_detachnode(db, &node);
10171			if (result != ISC_R_SUCCESS)
10172				goto fail;
10173		}
10174		rdataset = NULL;
10175		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10176					      &ns.name, dns_rdatatype_a,
10177					      dns_rdatatype_none, NULL,
10178					      &rdataset);
10179		if (result == ISC_R_SUCCESS) {
10180			result = dns_db_findnode(db, &ns.name,
10181						 ISC_TRUE, &node);
10182			if (result != ISC_R_SUCCESS)
10183				goto fail;
10184			result = dns_db_addrdataset(db, node, version, 0,
10185						    rdataset, 0, NULL);
10186			dns_db_detachnode(db, &node);
10187			if (result != ISC_R_SUCCESS)
10188				goto fail;
10189		}
10190	}
10191	if (result != ISC_R_NOMORE)
10192		goto fail;
10193
10194	return (ISC_R_SUCCESS);
10195
10196fail:
10197	return (result);
10198}
10199
10200static void
10201stub_callback(isc_task_t *task, isc_event_t *event) {
10202	const char me[] = "stub_callback";
10203	dns_requestevent_t *revent = (dns_requestevent_t *)event;
10204	dns_stub_t *stub = NULL;
10205	dns_message_t *msg = NULL;
10206	dns_zone_t *zone = NULL;
10207	char master[ISC_SOCKADDR_FORMATSIZE];
10208	char source[ISC_SOCKADDR_FORMATSIZE];
10209	isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
10210	isc_result_t result;
10211	isc_time_t now;
10212	isc_boolean_t exiting = ISC_FALSE;
10213	isc_interval_t i;
10214	unsigned int j, soacount;
10215
10216	stub = revent->ev_arg;
10217	INSIST(DNS_STUB_VALID(stub));
10218
10219	UNUSED(task);
10220
10221	zone = stub->zone;
10222
10223	ENTER;
10224
10225	TIME_NOW(&now);
10226
10227	LOCK_ZONE(zone);
10228
10229	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10230		zone_debuglog(zone, me, 1, "exiting");
10231		exiting = ISC_TRUE;
10232		goto next_master;
10233	}
10234
10235	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10236	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10237
10238	if (revent->result != ISC_R_SUCCESS) {
10239		if (revent->result == ISC_R_TIMEDOUT &&
10240		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10241			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10242			dns_zone_log(zone, ISC_LOG_DEBUG(1),
10243				     "refreshing stub: timeout retrying "
10244				     " without EDNS master %s (source %s)",
10245				     master, source);
10246			goto same_master;
10247		}
10248		dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
10249					   &zone->sourceaddr, &now);
10250		dns_zone_log(zone, ISC_LOG_INFO,
10251			     "could not refresh stub from master %s"
10252			     " (source %s): %s", master, source,
10253			     dns_result_totext(revent->result));
10254		goto next_master;
10255	}
10256
10257	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10258	if (result != ISC_R_SUCCESS)
10259		goto next_master;
10260
10261	result = dns_request_getresponse(revent->request, msg, 0);
10262	if (result != ISC_R_SUCCESS)
10263		goto next_master;
10264
10265	/*
10266	 * Unexpected rcode.
10267	 */
10268	if (msg->rcode != dns_rcode_noerror) {
10269		char rcode[128];
10270		isc_buffer_t rb;
10271
10272		isc_buffer_init(&rb, rcode, sizeof(rcode));
10273		(void)dns_rcode_totext(msg->rcode, &rb);
10274
10275		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10276		    (msg->rcode == dns_rcode_servfail ||
10277		     msg->rcode == dns_rcode_notimp ||
10278		     msg->rcode == dns_rcode_formerr)) {
10279			dns_zone_log(zone, ISC_LOG_DEBUG(1),
10280				     "refreshing stub: rcode (%.*s) retrying "
10281				     "without EDNS master %s (source %s)",
10282				     (int)rb.used, rcode, master, source);
10283			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10284			goto same_master;
10285		}
10286
10287		dns_zone_log(zone, ISC_LOG_INFO,
10288			     "refreshing stub: "
10289			     "unexpected rcode (%.*s) from %s (source %s)",
10290			     (int)rb.used, rcode, master, source);
10291		goto next_master;
10292	}
10293
10294	/*
10295	 * We need complete messages.
10296	 */
10297	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10298		if (dns_request_usedtcp(revent->request)) {
10299			dns_zone_log(zone, ISC_LOG_INFO,
10300				     "refreshing stub: truncated TCP "
10301				     "response from master %s (source %s)",
10302				     master, source);
10303			goto next_master;
10304		}
10305		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10306		goto same_master;
10307	}
10308
10309	/*
10310	 * If non-auth log and next master.
10311	 */
10312	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10313		dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10314			     "non-authoritative answer from "
10315			     "master %s (source %s)", master, source);
10316		goto next_master;
10317	}
10318
10319	/*
10320	 * Sanity checks.
10321	 */
10322	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10323	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
10324
10325	if (cnamecnt != 0) {
10326		dns_zone_log(zone, ISC_LOG_INFO,
10327			     "refreshing stub: unexpected CNAME response "
10328			     "from master %s (source %s)", master, source);
10329		goto next_master;
10330	}
10331
10332	if (nscnt == 0) {
10333		dns_zone_log(zone, ISC_LOG_INFO,
10334			     "refreshing stub: no NS records in response "
10335			     "from master %s (source %s)", master, source);
10336		goto next_master;
10337	}
10338
10339	/*
10340	 * Save answer.
10341	 */
10342	result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
10343	if (result != ISC_R_SUCCESS) {
10344		dns_zone_log(zone, ISC_LOG_INFO,
10345			     "refreshing stub: unable to save NS records "
10346			     "from master %s (source %s)", master, source);
10347		goto next_master;
10348	}
10349
10350	/*
10351	 * Tidy up.
10352	 */
10353	dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
10354	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
10355	if (zone->db == NULL)
10356		zone_attachdb(zone, stub->db);
10357	result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
10358				  &refresh, &retry, &expire, NULL, NULL);
10359	if (result == ISC_R_SUCCESS && soacount > 0U) {
10360		zone->refresh = RANGE(refresh, zone->minrefresh,
10361				      zone->maxrefresh);
10362		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
10363		zone->expire = RANGE(expire, zone->refresh + zone->retry,
10364				     DNS_MAX_EXPIRE);
10365		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10366	}
10367	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
10368	dns_db_detach(&stub->db);
10369
10370	dns_message_destroy(&msg);
10371	isc_event_free(&event);
10372	dns_request_destroy(&zone->request);
10373
10374	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10375	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10376	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10377	isc_interval_set(&i, zone->expire, 0);
10378	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10379
10380	if (zone->masterfile != NULL)
10381		zone_needdump(zone, 0);
10382
10383	zone_settimer(zone, &now);
10384	goto free_stub;
10385
10386 next_master:
10387	if (stub->version != NULL)
10388		dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
10389	if (stub->db != NULL)
10390		dns_db_detach(&stub->db);
10391	if (msg != NULL)
10392		dns_message_destroy(&msg);
10393	isc_event_free(&event);
10394	dns_request_destroy(&zone->request);
10395	/*
10396	 * Skip to next failed / untried master.
10397	 */
10398	do {
10399		zone->curmaster++;
10400	} while (zone->curmaster < zone->masterscnt &&
10401		 zone->mastersok[zone->curmaster]);
10402	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10403	if (exiting || zone->curmaster >= zone->masterscnt) {
10404		isc_boolean_t done = ISC_TRUE;
10405		if (!exiting &&
10406		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10407		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10408			/*
10409			 * Did we get a good answer from all the masters?
10410			 */
10411			for (j = 0; j < zone->masterscnt; j++)
10412				if (zone->mastersok[j] == ISC_FALSE) {
10413					done = ISC_FALSE;
10414					break;
10415				}
10416		} else
10417			done = ISC_TRUE;
10418		if (!done) {
10419			zone->curmaster = 0;
10420			/*
10421			 * Find the next failed master.
10422			 */
10423			while (zone->curmaster < zone->masterscnt &&
10424			       zone->mastersok[zone->curmaster])
10425				zone->curmaster++;
10426			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10427		} else {
10428			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10429
10430			zone_settimer(zone, &now);
10431			goto free_stub;
10432		}
10433	}
10434	queue_soa_query(zone);
10435	goto free_stub;
10436
10437 same_master:
10438	if (msg != NULL)
10439		dns_message_destroy(&msg);
10440	isc_event_free(&event);
10441	dns_request_destroy(&zone->request);
10442	ns_query(zone, NULL, stub);
10443	UNLOCK_ZONE(zone);
10444	goto done;
10445
10446 free_stub:
10447	UNLOCK_ZONE(zone);
10448	stub->magic = 0;
10449	dns_zone_idetach(&stub->zone);
10450	INSIST(stub->db == NULL);
10451	INSIST(stub->version == NULL);
10452	isc_mem_put(stub->mctx, stub, sizeof(*stub));
10453
10454 done:
10455	INSIST(event == NULL);
10456	return;
10457}
10458
10459/*
10460 * An SOA query has finished (successfully or not).
10461 */
10462static void
10463refresh_callback(isc_task_t *task, isc_event_t *event) {
10464	const char me[] = "refresh_callback";
10465	dns_requestevent_t *revent = (dns_requestevent_t *)event;
10466	dns_zone_t *zone;
10467	dns_message_t *msg = NULL;
10468	isc_uint32_t soacnt, cnamecnt, soacount, nscount;
10469	isc_time_t now;
10470	char master[ISC_SOCKADDR_FORMATSIZE];
10471	char source[ISC_SOCKADDR_FORMATSIZE];
10472	dns_rdataset_t *rdataset = NULL;
10473	dns_rdata_t rdata = DNS_RDATA_INIT;
10474	dns_rdata_soa_t soa;
10475	isc_result_t result;
10476	isc_uint32_t serial, oldserial = 0;
10477	unsigned int j;
10478	isc_boolean_t do_queue_xfrin = ISC_FALSE;
10479
10480	zone = revent->ev_arg;
10481	INSIST(DNS_ZONE_VALID(zone));
10482
10483	UNUSED(task);
10484
10485	ENTER;
10486
10487	TIME_NOW(&now);
10488
10489	LOCK_ZONE(zone);
10490
10491	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10492		isc_event_free(&event);
10493		dns_request_destroy(&zone->request);
10494		goto detach;
10495	}
10496
10497	/*
10498	 * if timeout log and next master;
10499	 */
10500
10501	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10502	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10503
10504	if (revent->result != ISC_R_SUCCESS) {
10505		if (revent->result == ISC_R_TIMEDOUT &&
10506		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10507			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10508			dns_zone_log(zone, ISC_LOG_DEBUG(1),
10509				     "refresh: timeout retrying without EDNS "
10510				     "master %s (source %s)", master, source);
10511			goto same_master;
10512		}
10513		if (revent->result == ISC_R_TIMEDOUT &&
10514		    !dns_request_usedtcp(revent->request)) {
10515			dns_zone_log(zone, ISC_LOG_INFO,
10516				     "refresh: retry limit for "
10517				     "master %s exceeded (source %s)",
10518				     master, source);
10519			/* Try with slave with TCP. */
10520			if ((zone->type == dns_zone_slave ||
10521			     zone->type == dns_zone_redirect) &&
10522			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
10523				if (!dns_zonemgr_unreachable(zone->zmgr,
10524							     &zone->masteraddr,
10525							     &zone->sourceaddr,
10526							     &now))
10527				{
10528					DNS_ZONE_SETFLAG(zone,
10529						     DNS_ZONEFLG_SOABEFOREAXFR);
10530					goto tcp_transfer;
10531				}
10532				dns_zone_log(zone, ISC_LOG_DEBUG(1),
10533					     "refresh: skipped tcp fallback "
10534					     "as master %s (source %s) is "
10535					     "unreachable (cached)",
10536					      master, source);
10537			}
10538		} else
10539			dns_zone_log(zone, ISC_LOG_INFO,
10540				     "refresh: failure trying master "
10541				     "%s (source %s): %s", master, source,
10542				     dns_result_totext(revent->result));
10543		goto next_master;
10544	}
10545
10546	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10547	if (result != ISC_R_SUCCESS)
10548		goto next_master;
10549	result = dns_request_getresponse(revent->request, msg, 0);
10550	if (result != ISC_R_SUCCESS) {
10551		dns_zone_log(zone, ISC_LOG_INFO,
10552			     "refresh: failure trying master "
10553			     "%s (source %s): %s", master, source,
10554			     dns_result_totext(result));
10555		goto next_master;
10556	}
10557
10558	/*
10559	 * Unexpected rcode.
10560	 */
10561	if (msg->rcode != dns_rcode_noerror) {
10562		char rcode[128];
10563		isc_buffer_t rb;
10564
10565		isc_buffer_init(&rb, rcode, sizeof(rcode));
10566		(void)dns_rcode_totext(msg->rcode, &rb);
10567
10568		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10569		    (msg->rcode == dns_rcode_servfail ||
10570		     msg->rcode == dns_rcode_notimp ||
10571		     msg->rcode == dns_rcode_formerr)) {
10572			dns_zone_log(zone, ISC_LOG_DEBUG(1),
10573				     "refresh: rcode (%.*s) retrying without "
10574				     "EDNS master %s (source %s)",
10575				     (int)rb.used, rcode, master, source);
10576			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10577			goto same_master;
10578		}
10579		dns_zone_log(zone, ISC_LOG_INFO,
10580			     "refresh: unexpected rcode (%.*s) from "
10581			     "master %s (source %s)", (int)rb.used, rcode,
10582			     master, source);
10583		/*
10584		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
10585		 */
10586		if (msg->rcode == dns_rcode_refused &&
10587		    (zone->type == dns_zone_slave ||
10588		     zone->type == dns_zone_redirect))
10589			goto tcp_transfer;
10590		goto next_master;
10591	}
10592
10593	/*
10594	 * If truncated punt to zone transfer which will query again.
10595	 */
10596	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10597		if (zone->type == dns_zone_slave ||
10598		    zone->type == dns_zone_redirect) {
10599			dns_zone_log(zone, ISC_LOG_INFO,
10600				     "refresh: truncated UDP answer, "
10601				     "initiating TCP zone xfer "
10602				     "for master %s (source %s)",
10603				     master, source);
10604			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
10605			goto tcp_transfer;
10606		} else {
10607			INSIST(zone->type == dns_zone_stub);
10608			if (dns_request_usedtcp(revent->request)) {
10609				dns_zone_log(zone, ISC_LOG_INFO,
10610					     "refresh: truncated TCP response "
10611					     "from master %s (source %s)",
10612					     master, source);
10613				goto next_master;
10614			}
10615			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10616			goto same_master;
10617		}
10618	}
10619
10620	/*
10621	 * if non-auth log and next master;
10622	 */
10623	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10624		dns_zone_log(zone, ISC_LOG_INFO,
10625			     "refresh: non-authoritative answer from "
10626			     "master %s (source %s)", master, source);
10627		goto next_master;
10628	}
10629
10630	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10631	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
10632	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
10633	soacount = message_count(msg, DNS_SECTION_AUTHORITY,
10634				 dns_rdatatype_soa);
10635
10636	/*
10637	 * There should not be a CNAME record at top of zone.
10638	 */
10639	if (cnamecnt != 0) {
10640		dns_zone_log(zone, ISC_LOG_INFO,
10641			     "refresh: CNAME at top of zone "
10642			     "in master %s (source %s)", master, source);
10643		goto next_master;
10644	}
10645
10646	/*
10647	 * if referral log and next master;
10648	 */
10649	if (soacnt == 0 && soacount == 0 && nscount != 0) {
10650		dns_zone_log(zone, ISC_LOG_INFO,
10651			     "refresh: referral response "
10652			     "from master %s (source %s)", master, source);
10653		goto next_master;
10654	}
10655
10656	/*
10657	 * if nodata log and next master;
10658	 */
10659	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
10660		dns_zone_log(zone, ISC_LOG_INFO,
10661			     "refresh: NODATA response "
10662			     "from master %s (source %s)", master, source);
10663		goto next_master;
10664	}
10665
10666	/*
10667	 * Only one soa at top of zone.
10668	 */
10669	if (soacnt != 1) {
10670		dns_zone_log(zone, ISC_LOG_INFO,
10671			     "refresh: answer SOA count (%d) != 1 "
10672			     "from master %s (source %s)",
10673			     soacnt, master, source);
10674		goto next_master;
10675	}
10676
10677	/*
10678	 * Extract serial
10679	 */
10680	rdataset = NULL;
10681	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
10682				      dns_rdatatype_soa, dns_rdatatype_none,
10683				      NULL, &rdataset);
10684	if (result != ISC_R_SUCCESS) {
10685		dns_zone_log(zone, ISC_LOG_INFO,
10686			     "refresh: unable to get SOA record "
10687			     "from master %s (source %s)", master, source);
10688		goto next_master;
10689	}
10690
10691	result = dns_rdataset_first(rdataset);
10692	if (result != ISC_R_SUCCESS) {
10693		dns_zone_log(zone, ISC_LOG_INFO,
10694			     "refresh: dns_rdataset_first() failed");
10695		goto next_master;
10696	}
10697
10698	dns_rdataset_current(rdataset, &rdata);
10699	result = dns_rdata_tostruct(&rdata, &soa, NULL);
10700	RUNTIME_CHECK(result == ISC_R_SUCCESS);
10701
10702	serial = soa.serial;
10703	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10704		unsigned int soacount;
10705		result = zone_get_from_db(zone, zone->db, NULL, &soacount,
10706					  &oldserial, NULL, NULL, NULL, NULL,
10707					  NULL);
10708		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10709		RUNTIME_CHECK(soacount > 0U);
10710		zone_debuglog(zone, me, 1, "serial: new %u, old %u",
10711			      serial, oldserial);
10712	} else
10713		zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
10714			      serial);
10715
10716	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
10717	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
10718	    isc_serial_gt(serial, oldserial)) {
10719		if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
10720					    &zone->sourceaddr, &now))
10721		{
10722			dns_zone_log(zone, ISC_LOG_INFO,
10723				     "refresh: skipping %s as master %s "
10724				     "(source %s) is unreachable (cached)",
10725				     (zone->type == dns_zone_slave ||
10726				      zone->type == dns_zone_redirect) ?
10727				     "zone transfer" : "NS query",
10728				     master, source);
10729			goto next_master;
10730		}
10731 tcp_transfer:
10732		isc_event_free(&event);
10733		dns_request_destroy(&zone->request);
10734		if (zone->type == dns_zone_slave ||
10735		    zone->type == dns_zone_redirect) {
10736			do_queue_xfrin = ISC_TRUE;
10737		} else {
10738			INSIST(zone->type == dns_zone_stub);
10739			ns_query(zone, rdataset, NULL);
10740		}
10741		if (msg != NULL)
10742			dns_message_destroy(&msg);
10743	} else if (isc_serial_eq(soa.serial, oldserial)) {
10744		if (zone->masterfile != NULL) {
10745			result = ISC_R_FAILURE;
10746			if (zone->journal != NULL)
10747				result = isc_file_settime(zone->journal, &now);
10748			if (result == ISC_R_SUCCESS &&
10749			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10750			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10751				result = isc_file_settime(zone->masterfile,
10752							  &now);
10753			} else if (result != ISC_R_SUCCESS)
10754				result = isc_file_settime(zone->masterfile,
10755							  &now);
10756			/* Someone removed the file from underneath us! */
10757			if (result == ISC_R_FILENOTFOUND) {
10758				zone_needdump(zone, DNS_DUMP_DELAY);
10759			} else if (result != ISC_R_SUCCESS)
10760				dns_zone_log(zone, ISC_LOG_ERROR,
10761					     "refresh: could not set file "
10762					     "modification time of '%s': %s",
10763					     zone->masterfile,
10764					     dns_result_totext(result));
10765		}
10766		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10767		DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10768		zone->mastersok[zone->curmaster] = ISC_TRUE;
10769		goto next_master;
10770	} else {
10771		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
10772			dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
10773				     "received from master %s < ours (%u)",
10774				     soa.serial, master, oldserial);
10775		else
10776			zone_debuglog(zone, me, 1, "ahead");
10777		zone->mastersok[zone->curmaster] = ISC_TRUE;
10778		goto next_master;
10779	}
10780	if (msg != NULL)
10781		dns_message_destroy(&msg);
10782	goto detach;
10783
10784 next_master:
10785	if (msg != NULL)
10786		dns_message_destroy(&msg);
10787	isc_event_free(&event);
10788	dns_request_destroy(&zone->request);
10789	/*
10790	 * Skip to next failed / untried master.
10791	 */
10792	do {
10793		zone->curmaster++;
10794	} while (zone->curmaster < zone->masterscnt &&
10795		 zone->mastersok[zone->curmaster]);
10796	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10797	if (zone->curmaster >= zone->masterscnt) {
10798		isc_boolean_t done = ISC_TRUE;
10799		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10800		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10801			/*
10802			 * Did we get a good answer from all the masters?
10803			 */
10804			for (j = 0; j < zone->masterscnt; j++)
10805				if (zone->mastersok[j] == ISC_FALSE) {
10806					done = ISC_FALSE;
10807					break;
10808				}
10809		} else
10810			done = ISC_TRUE;
10811		if (!done) {
10812			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10813			zone->curmaster = 0;
10814			/*
10815			 * Find the next failed master.
10816			 */
10817			while (zone->curmaster < zone->masterscnt &&
10818			       zone->mastersok[zone->curmaster])
10819				zone->curmaster++;
10820			goto requeue;
10821		}
10822		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10823		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
10824			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10825			zone->refreshtime = now;
10826		}
10827		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10828		zone_settimer(zone, &now);
10829		goto detach;
10830	}
10831
10832 requeue:
10833	queue_soa_query(zone);
10834	goto detach;
10835
10836 same_master:
10837	if (msg != NULL)
10838		dns_message_destroy(&msg);
10839	isc_event_free(&event);
10840	dns_request_destroy(&zone->request);
10841	queue_soa_query(zone);
10842
10843 detach:
10844	UNLOCK_ZONE(zone);
10845	if (do_queue_xfrin)
10846		queue_xfrin(zone);
10847	dns_zone_idetach(&zone);
10848	return;
10849}
10850
10851static void
10852queue_soa_query(dns_zone_t *zone) {
10853	const char me[] = "queue_soa_query";
10854	isc_event_t *e;
10855	dns_zone_t *dummy = NULL;
10856	isc_result_t result;
10857
10858	ENTER;
10859	/*
10860	 * Locked by caller
10861	 */
10862	REQUIRE(LOCKED_ZONE(zone));
10863
10864	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10865		cancel_refresh(zone);
10866		return;
10867	}
10868
10869	e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
10870			       soa_query, zone, sizeof(isc_event_t));
10871	if (e == NULL) {
10872		cancel_refresh(zone);
10873		return;
10874	}
10875
10876	/*
10877	 * Attach so that we won't clean up
10878	 * until the event is delivered.
10879	 */
10880	zone_iattach(zone, &dummy);
10881
10882	e->ev_arg = zone;
10883	e->ev_sender = NULL;
10884	result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
10885	if (result != ISC_R_SUCCESS) {
10886		zone_idetach(&dummy);
10887		isc_event_free(&e);
10888		cancel_refresh(zone);
10889	}
10890}
10891
10892static inline isc_result_t
10893create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
10894	     dns_message_t **messagep)
10895{
10896	dns_message_t *message = NULL;
10897	dns_name_t *qname = NULL;
10898	dns_rdataset_t *qrdataset = NULL;
10899	isc_result_t result;
10900
10901	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10902				    &message);
10903	if (result != ISC_R_SUCCESS)
10904		goto cleanup;
10905
10906	message->opcode = dns_opcode_query;
10907	message->rdclass = zone->rdclass;
10908
10909	result = dns_message_gettempname(message, &qname);
10910	if (result != ISC_R_SUCCESS)
10911		goto cleanup;
10912
10913	result = dns_message_gettemprdataset(message, &qrdataset);
10914	if (result != ISC_R_SUCCESS)
10915		goto cleanup;
10916
10917	/*
10918	 * Make question.
10919	 */
10920	dns_name_init(qname, NULL);
10921	dns_name_clone(&zone->origin, qname);
10922	dns_rdataset_init(qrdataset);
10923	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
10924	ISC_LIST_APPEND(qname->list, qrdataset, link);
10925	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
10926
10927	*messagep = message;
10928	return (ISC_R_SUCCESS);
10929
10930 cleanup:
10931	if (qname != NULL)
10932		dns_message_puttempname(message, &qname);
10933	if (qrdataset != NULL)
10934		dns_message_puttemprdataset(message, &qrdataset);
10935	if (message != NULL)
10936		dns_message_destroy(&message);
10937	return (result);
10938}
10939
10940static isc_result_t
10941add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
10942	dns_rdataset_t *rdataset = NULL;
10943	dns_rdatalist_t *rdatalist = NULL;
10944	dns_rdata_t *rdata = NULL;
10945	isc_result_t result;
10946
10947	result = dns_message_gettemprdatalist(message, &rdatalist);
10948	if (result != ISC_R_SUCCESS)
10949		goto cleanup;
10950	result = dns_message_gettemprdata(message, &rdata);
10951	if (result != ISC_R_SUCCESS)
10952		goto cleanup;
10953	result = dns_message_gettemprdataset(message, &rdataset);
10954	if (result != ISC_R_SUCCESS)
10955		goto cleanup;
10956	dns_rdataset_init(rdataset);
10957
10958	rdatalist->type = dns_rdatatype_opt;
10959	rdatalist->covers = 0;
10960
10961	/*
10962	 * Set Maximum UDP buffer size.
10963	 */
10964	rdatalist->rdclass = udpsize;
10965
10966	/*
10967	 * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
10968	 */
10969	rdatalist->ttl = 0;
10970
10971	/* Set EDNS options if applicable */
10972	if (reqnsid) {
10973		unsigned char data[4];
10974		isc_buffer_t buf;
10975
10976		isc_buffer_init(&buf, data, sizeof(data));
10977		isc_buffer_putuint16(&buf, DNS_OPT_NSID);
10978		isc_buffer_putuint16(&buf, 0);
10979		rdata->data = data;
10980		rdata->length = sizeof(data);
10981	} else {
10982		rdata->data = NULL;
10983		rdata->length = 0;
10984	}
10985
10986	rdata->rdclass = rdatalist->rdclass;
10987	rdata->type = rdatalist->type;
10988	rdata->flags = 0;
10989
10990	ISC_LIST_INIT(rdatalist->rdata);
10991	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
10992	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
10993		      == ISC_R_SUCCESS);
10994
10995	return (dns_message_setopt(message, rdataset));
10996
10997 cleanup:
10998	if (rdatalist != NULL)
10999		dns_message_puttemprdatalist(message, &rdatalist);
11000	if (rdataset != NULL)
11001		dns_message_puttemprdataset(message, &rdataset);
11002	if (rdata != NULL)
11003		dns_message_puttemprdata(message, &rdata);
11004
11005	return (result);
11006}
11007
11008static void
11009soa_query(isc_task_t *task, isc_event_t *event) {
11010	const char me[] = "soa_query";
11011	isc_result_t result = ISC_R_FAILURE;
11012	dns_message_t *message = NULL;
11013	dns_zone_t *zone = event->ev_arg;
11014	dns_zone_t *dummy = NULL;
11015	isc_netaddr_t masterip;
11016	dns_tsigkey_t *key = NULL;
11017	isc_uint32_t options;
11018	isc_boolean_t cancel = ISC_TRUE;
11019	int timeout;
11020	isc_boolean_t have_xfrsource, reqnsid;
11021	isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11022
11023	REQUIRE(DNS_ZONE_VALID(zone));
11024
11025	UNUSED(task);
11026
11027	ENTER;
11028
11029	LOCK_ZONE(zone);
11030	if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
11031	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11032	    zone->view->requestmgr == NULL) {
11033		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11034			cancel = ISC_FALSE;
11035		goto cleanup;
11036	}
11037
11038	/*
11039	 * XXX Optimisation: Create message when zone is setup and reuse.
11040	 */
11041	result = create_query(zone, dns_rdatatype_soa, &message);
11042	if (result != ISC_R_SUCCESS)
11043		goto cleanup;
11044
11045 again:
11046	INSIST(zone->masterscnt > 0);
11047	INSIST(zone->curmaster < zone->masterscnt);
11048
11049	zone->masteraddr = zone->masters[zone->curmaster];
11050
11051	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11052	/*
11053	 * First, look for a tsig key in the master statement, then
11054	 * try for a server key.
11055	 */
11056	if ((zone->masterkeynames != NULL) &&
11057	    (zone->masterkeynames[zone->curmaster] != NULL)) {
11058		dns_view_t *view = dns_zone_getview(zone);
11059		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11060		result = dns_view_gettsig(view, keyname, &key);
11061		if (result != ISC_R_SUCCESS) {
11062			char namebuf[DNS_NAME_FORMATSIZE];
11063			dns_name_format(keyname, namebuf, sizeof(namebuf));
11064			dns_zone_log(zone, ISC_LOG_ERROR,
11065				     "unable to find key: %s", namebuf);
11066			goto skip_master;
11067		}
11068	}
11069	if (key == NULL) {
11070		result = dns_view_getpeertsig(zone->view, &masterip, &key);
11071		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11072			char addrbuf[ISC_NETADDR_FORMATSIZE];
11073			isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
11074			dns_zone_log(zone, ISC_LOG_ERROR,
11075				     "unable to find TSIG key for %s", addrbuf);
11076			goto skip_master;
11077		}
11078	}
11079
11080	have_xfrsource = ISC_FALSE;
11081	reqnsid = zone->view->requestnsid;
11082	if (zone->view->peers != NULL) {
11083		dns_peer_t *peer = NULL;
11084		isc_boolean_t edns;
11085		result = dns_peerlist_peerbyaddr(zone->view->peers,
11086						 &masterip, &peer);
11087		if (result == ISC_R_SUCCESS) {
11088			result = dns_peer_getsupportedns(peer, &edns);
11089			if (result == ISC_R_SUCCESS && !edns)
11090				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11091			result = dns_peer_gettransfersource(peer,
11092							    &zone->sourceaddr);
11093			if (result == ISC_R_SUCCESS)
11094				have_xfrsource = ISC_TRUE;
11095			if (zone->view->resolver != NULL)
11096				udpsize =
11097				  dns_resolver_getudpsize(zone->view->resolver);
11098			(void)dns_peer_getudpsize(peer, &udpsize);
11099			(void)dns_peer_getrequestnsid(peer, &reqnsid);
11100		}
11101	}
11102
11103	switch (isc_sockaddr_pf(&zone->masteraddr)) {
11104	case PF_INET:
11105		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11106			if (isc_sockaddr_equal(&zone->altxfrsource4,
11107					       &zone->xfrsource4))
11108				goto skip_master;
11109			zone->sourceaddr = zone->altxfrsource4;
11110		} else if (!have_xfrsource)
11111			zone->sourceaddr = zone->xfrsource4;
11112		break;
11113	case PF_INET6:
11114		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11115			if (isc_sockaddr_equal(&zone->altxfrsource6,
11116					       &zone->xfrsource6))
11117				goto skip_master;
11118			zone->sourceaddr = zone->altxfrsource6;
11119		} else if (!have_xfrsource)
11120			zone->sourceaddr = zone->xfrsource6;
11121		break;
11122	default:
11123		result = ISC_R_NOTIMPLEMENTED;
11124		goto cleanup;
11125	}
11126
11127	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
11128		  DNS_REQUESTOPT_TCP : 0;
11129
11130	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11131		result = add_opt(message, udpsize, reqnsid);
11132		if (result != ISC_R_SUCCESS)
11133			zone_debuglog(zone, me, 1,
11134				      "unable to add opt record: %s",
11135				      dns_result_totext(result));
11136	}
11137
11138	zone_iattach(zone, &dummy);
11139	timeout = 15;
11140	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11141		timeout = 30;
11142	result = dns_request_createvia2(zone->view->requestmgr, message,
11143					&zone->sourceaddr, &zone->masteraddr,
11144					options, key, timeout * 3, timeout,
11145					zone->task, refresh_callback, zone,
11146					&zone->request);
11147	if (result != ISC_R_SUCCESS) {
11148		zone_idetach(&dummy);
11149		zone_debuglog(zone, me, 1,
11150			      "dns_request_createvia2() failed: %s",
11151			      dns_result_totext(result));
11152		goto cleanup;
11153	} else {
11154		if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
11155			inc_stats(zone, dns_zonestatscounter_soaoutv4);
11156		else
11157			inc_stats(zone, dns_zonestatscounter_soaoutv6);
11158	}
11159	cancel = ISC_FALSE;
11160
11161 cleanup:
11162	if (key != NULL)
11163		dns_tsigkey_detach(&key);
11164	if (result != ISC_R_SUCCESS)
11165		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11166	if (message != NULL)
11167		dns_message_destroy(&message);
11168	if (cancel)
11169		cancel_refresh(zone);
11170	isc_event_free(&event);
11171	UNLOCK_ZONE(zone);
11172	dns_zone_idetach(&zone);
11173	return;
11174
11175 skip_master:
11176	if (key != NULL)
11177		dns_tsigkey_detach(&key);
11178	/*
11179	 * Skip to next failed / untried master.
11180	 */
11181	do {
11182		zone->curmaster++;
11183	} while (zone->curmaster < zone->masterscnt &&
11184		 zone->mastersok[zone->curmaster]);
11185	if (zone->curmaster < zone->masterscnt)
11186		goto again;
11187	zone->curmaster = 0;
11188	goto cleanup;
11189}
11190
11191static void
11192ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
11193	const char me[] = "ns_query";
11194	isc_result_t result;
11195	dns_message_t *message = NULL;
11196	isc_netaddr_t masterip;
11197	dns_tsigkey_t *key = NULL;
11198	dns_dbnode_t *node = NULL;
11199	int timeout;
11200	isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
11201	isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11202
11203	REQUIRE(DNS_ZONE_VALID(zone));
11204	REQUIRE(LOCKED_ZONE(zone));
11205	REQUIRE((soardataset != NULL && stub == NULL) ||
11206		(soardataset == NULL && stub != NULL));
11207	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
11208
11209	ENTER;
11210
11211	if (stub == NULL) {
11212		stub = isc_mem_get(zone->mctx, sizeof(*stub));
11213		if (stub == NULL)
11214			goto cleanup;
11215		stub->magic = STUB_MAGIC;
11216		stub->mctx = zone->mctx;
11217		stub->zone = NULL;
11218		stub->db = NULL;
11219		stub->version = NULL;
11220
11221		/*
11222		 * Attach so that the zone won't disappear from under us.
11223		 */
11224		zone_iattach(zone, &stub->zone);
11225
11226		/*
11227		 * If a db exists we will update it, otherwise we create a
11228		 * new one and attach it to the zone once we have the NS
11229		 * RRset and glue.
11230		 */
11231		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11232		if (zone->db != NULL) {
11233			dns_db_attach(zone->db, &stub->db);
11234			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11235		} else {
11236			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11237
11238			INSIST(zone->db_argc >= 1);
11239			result = dns_db_create(zone->mctx, zone->db_argv[0],
11240					       &zone->origin, dns_dbtype_stub,
11241					       zone->rdclass,
11242					       zone->db_argc - 1,
11243					       zone->db_argv + 1,
11244					       &stub->db);
11245			if (result != ISC_R_SUCCESS) {
11246				dns_zone_log(zone, ISC_LOG_ERROR,
11247					     "refreshing stub: "
11248					     "could not create "
11249					     "database: %s",
11250					     dns_result_totext(result));
11251				goto cleanup;
11252			}
11253			dns_db_settask(stub->db, zone->task);
11254		}
11255
11256		result = dns_db_newversion(stub->db, &stub->version);
11257		if (result != ISC_R_SUCCESS) {
11258			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11259				     "dns_db_newversion() failed: %s",
11260				     dns_result_totext(result));
11261			goto cleanup;
11262		}
11263
11264		/*
11265		 * Update SOA record.
11266		 */
11267		result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
11268					 &node);
11269		if (result != ISC_R_SUCCESS) {
11270			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11271				     "dns_db_findnode() failed: %s",
11272				     dns_result_totext(result));
11273			goto cleanup;
11274		}
11275
11276		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
11277					    soardataset, 0, NULL);
11278		dns_db_detachnode(stub->db, &node);
11279		if (result != ISC_R_SUCCESS) {
11280			dns_zone_log(zone, ISC_LOG_INFO,
11281				     "refreshing stub: "
11282				     "dns_db_addrdataset() failed: %s",
11283				     dns_result_totext(result));
11284			goto cleanup;
11285		}
11286	}
11287
11288	/*
11289	 * XXX Optimisation: Create message when zone is setup and reuse.
11290	 */
11291	result = create_query(zone, dns_rdatatype_ns, &message);
11292	INSIST(result == ISC_R_SUCCESS);
11293
11294	INSIST(zone->masterscnt > 0);
11295	INSIST(zone->curmaster < zone->masterscnt);
11296	zone->masteraddr = zone->masters[zone->curmaster];
11297
11298	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11299	/*
11300	 * First, look for a tsig key in the master statement, then
11301	 * try for a server key.
11302	 */
11303	if ((zone->masterkeynames != NULL) &&
11304	    (zone->masterkeynames[zone->curmaster] != NULL)) {
11305		dns_view_t *view = dns_zone_getview(zone);
11306		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11307		result = dns_view_gettsig(view, keyname, &key);
11308		if (result != ISC_R_SUCCESS) {
11309			char namebuf[DNS_NAME_FORMATSIZE];
11310			dns_name_format(keyname, namebuf, sizeof(namebuf));
11311			dns_zone_log(zone, ISC_LOG_ERROR,
11312				     "unable to find key: %s", namebuf);
11313		}
11314	}
11315	if (key == NULL)
11316		(void)dns_view_getpeertsig(zone->view, &masterip, &key);
11317
11318	reqnsid = zone->view->requestnsid;
11319	if (zone->view->peers != NULL) {
11320		dns_peer_t *peer = NULL;
11321		isc_boolean_t edns;
11322		result = dns_peerlist_peerbyaddr(zone->view->peers,
11323						 &masterip, &peer);
11324		if (result == ISC_R_SUCCESS) {
11325			result = dns_peer_getsupportedns(peer, &edns);
11326			if (result == ISC_R_SUCCESS && !edns)
11327				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11328			result = dns_peer_gettransfersource(peer,
11329							    &zone->sourceaddr);
11330			if (result == ISC_R_SUCCESS)
11331				have_xfrsource = ISC_TRUE;
11332			if (zone->view->resolver != NULL)
11333				udpsize =
11334				  dns_resolver_getudpsize(zone->view->resolver);
11335			(void)dns_peer_getudpsize(peer, &udpsize);
11336			(void)dns_peer_getrequestnsid(peer, &reqnsid);
11337		}
11338
11339	}
11340	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11341		result = add_opt(message, udpsize, reqnsid);
11342		if (result != ISC_R_SUCCESS)
11343			zone_debuglog(zone, me, 1,
11344				      "unable to add opt record: %s",
11345				      dns_result_totext(result));
11346	}
11347
11348	/*
11349	 * Always use TCP so that we shouldn't truncate in additional section.
11350	 */
11351	switch (isc_sockaddr_pf(&zone->masteraddr)) {
11352	case PF_INET:
11353		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11354			zone->sourceaddr = zone->altxfrsource4;
11355		else if (!have_xfrsource)
11356			zone->sourceaddr = zone->xfrsource4;
11357		break;
11358	case PF_INET6:
11359		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11360			zone->sourceaddr = zone->altxfrsource6;
11361		else if (!have_xfrsource)
11362			zone->sourceaddr = zone->xfrsource6;
11363		break;
11364	default:
11365		result = ISC_R_NOTIMPLEMENTED;
11366		POST(result);
11367		goto cleanup;
11368	}
11369	timeout = 15;
11370	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11371		timeout = 30;
11372	result = dns_request_createvia2(zone->view->requestmgr, message,
11373					&zone->sourceaddr, &zone->masteraddr,
11374					DNS_REQUESTOPT_TCP, key, timeout * 3,
11375					timeout, zone->task, stub_callback,
11376					stub, &zone->request);
11377	if (result != ISC_R_SUCCESS) {
11378		zone_debuglog(zone, me, 1,
11379			      "dns_request_createvia() failed: %s",
11380			      dns_result_totext(result));
11381		goto cleanup;
11382	}
11383	dns_message_destroy(&message);
11384	goto unlock;
11385
11386 cleanup:
11387	cancel_refresh(zone);
11388	if (stub != NULL) {
11389		stub->magic = 0;
11390		if (stub->version != NULL)
11391			dns_db_closeversion(stub->db, &stub->version,
11392					    ISC_FALSE);
11393		if (stub->db != NULL)
11394			dns_db_detach(&stub->db);
11395		if (stub->zone != NULL)
11396			zone_idetach(&stub->zone);
11397		isc_mem_put(stub->mctx, stub, sizeof(*stub));
11398	}
11399	if (message != NULL)
11400		dns_message_destroy(&message);
11401 unlock:
11402	if (key != NULL)
11403		dns_tsigkey_detach(&key);
11404	return;
11405}
11406
11407/*
11408 * Handle the control event.  Note that although this event causes the zone
11409 * to shut down, it is not a shutdown event in the sense of the task library.
11410 */
11411static void
11412zone_shutdown(isc_task_t *task, isc_event_t *event) {
11413	dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
11414	isc_boolean_t free_needed, linked = ISC_FALSE;
11415	dns_zone_t *raw = NULL, *secure = NULL;
11416
11417	UNUSED(task);
11418	REQUIRE(DNS_ZONE_VALID(zone));
11419	INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
11420	INSIST(isc_refcount_current(&zone->erefs) == 0);
11421
11422	zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
11423
11424	/*
11425	 * Stop things being restarted after we cancel them below.
11426	 */
11427	LOCK_ZONE(zone);
11428	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
11429	UNLOCK_ZONE(zone);
11430
11431	/*
11432	 * If we were waiting for xfrin quota, step out of
11433	 * the queue.
11434	 * If there's no zone manager, we can't be waiting for the
11435	 * xfrin quota
11436	 */
11437	if (zone->zmgr != NULL) {
11438		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11439		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
11440			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
11441					statelink);
11442			linked = ISC_TRUE;
11443			zone->statelist = NULL;
11444		}
11445		if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
11446			ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
11447					statelink);
11448			zone->statelist = NULL;
11449			zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
11450		}
11451		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11452	}
11453
11454	/*
11455	 * In task context, no locking required.  See zone_xfrdone().
11456	 */
11457	if (zone->xfr != NULL)
11458		dns_xfrin_shutdown(zone->xfr);
11459
11460	/* Safe to release the zone now */
11461	if (zone->zmgr != NULL)
11462		dns_zonemgr_releasezone(zone->zmgr, zone);
11463
11464	LOCK_ZONE(zone);
11465	if (linked) {
11466		INSIST(zone->irefs > 0);
11467		zone->irefs--;
11468	}
11469	if (zone->request != NULL) {
11470		dns_request_cancel(zone->request);
11471	}
11472
11473	if (zone->readio != NULL)
11474		zonemgr_cancelio(zone->readio);
11475
11476	if (zone->lctx != NULL)
11477		dns_loadctx_cancel(zone->lctx);
11478
11479	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11480	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11481		if (zone->writeio != NULL)
11482			zonemgr_cancelio(zone->writeio);
11483
11484		if (zone->dctx != NULL)
11485			dns_dumpctx_cancel(zone->dctx);
11486	}
11487
11488	notify_cancel(zone);
11489
11490	forward_cancel(zone);
11491
11492	if (zone->timer != NULL) {
11493		isc_timer_detach(&zone->timer);
11494		INSIST(zone->irefs > 0);
11495		zone->irefs--;
11496	}
11497
11498	if (zone->view != NULL)
11499		dns_view_weakdetach(&zone->view);
11500
11501	/*
11502	 * We have now canceled everything set the flag to allow exit_check()
11503	 * to succeed.	We must not unlock between setting this flag and
11504	 * calling exit_check().
11505	 */
11506	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
11507	free_needed = exit_check(zone);
11508	if (inline_secure(zone)) {
11509		raw = zone->raw;
11510		zone->raw = NULL;
11511	}
11512	if (inline_raw(zone)) {
11513		secure = zone->secure;
11514		zone->secure = NULL;
11515	}
11516	UNLOCK_ZONE(zone);
11517	if (raw != NULL)
11518		dns_zone_detach(&raw);
11519	if (secure != NULL)
11520		dns_zone_idetach(&secure);
11521	if (free_needed)
11522		zone_free(zone);
11523}
11524
11525static void
11526zone_timer(isc_task_t *task, isc_event_t *event) {
11527	const char me[] = "zone_timer";
11528	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
11529
11530	UNUSED(task);
11531	REQUIRE(DNS_ZONE_VALID(zone));
11532
11533	ENTER;
11534
11535	zone_maintenance(zone);
11536
11537	isc_event_free(&event);
11538}
11539
11540static void
11541zone_settimer(dns_zone_t *zone, isc_time_t *now) {
11542	const char me[] = "zone_settimer";
11543	isc_time_t next;
11544	isc_result_t result;
11545
11546	ENTER;
11547	REQUIRE(DNS_ZONE_VALID(zone));
11548	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11549		return;
11550
11551	isc_time_settoepoch(&next);
11552
11553	switch (zone->type) {
11554	case dns_zone_redirect:
11555		if (zone->masters != NULL)
11556			goto treat_as_slave;
11557		/* FALLTHROUGH */
11558
11559	case dns_zone_master:
11560		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
11561			next = zone->notifytime;
11562		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11563		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11564			INSIST(!isc_time_isepoch(&zone->dumptime));
11565			if (isc_time_isepoch(&next) ||
11566			    isc_time_compare(&zone->dumptime, &next) < 0)
11567				next = zone->dumptime;
11568		}
11569		if (zone->type == dns_zone_redirect)
11570			break;
11571		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
11572		    !isc_time_isepoch(&zone->refreshkeytime)) {
11573			if (isc_time_isepoch(&next) ||
11574			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
11575				next = zone->refreshkeytime;
11576		}
11577		if (!isc_time_isepoch(&zone->resigntime)) {
11578			if (isc_time_isepoch(&next) ||
11579			    isc_time_compare(&zone->resigntime, &next) < 0)
11580				next = zone->resigntime;
11581		}
11582		if (!isc_time_isepoch(&zone->keywarntime)) {
11583			if (isc_time_isepoch(&next) ||
11584			    isc_time_compare(&zone->keywarntime, &next) < 0)
11585				next = zone->keywarntime;
11586		}
11587		if (!isc_time_isepoch(&zone->signingtime)) {
11588			if (isc_time_isepoch(&next) ||
11589			    isc_time_compare(&zone->signingtime, &next) < 0)
11590				next = zone->signingtime;
11591		}
11592		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
11593			if (isc_time_isepoch(&next) ||
11594			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
11595				next = zone->nsec3chaintime;
11596		}
11597		break;
11598
11599	case dns_zone_slave:
11600	treat_as_slave:
11601		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
11602			next = zone->notifytime;
11603		/* FALLTHROUGH */
11604
11605	case dns_zone_stub:
11606		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
11607		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
11608		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
11609		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
11610			INSIST(!isc_time_isepoch(&zone->refreshtime));
11611			if (isc_time_isepoch(&next) ||
11612			    isc_time_compare(&zone->refreshtime, &next) < 0)
11613				next = zone->refreshtime;
11614		}
11615		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11616		    !isc_time_isepoch(&zone->expiretime)) {
11617			if (isc_time_isepoch(&next) ||
11618			     isc_time_compare(&zone->expiretime, &next) < 0)
11619				next = zone->expiretime;
11620		}
11621		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11622		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11623			INSIST(!isc_time_isepoch(&zone->dumptime));
11624			if (isc_time_isepoch(&next) ||
11625			    isc_time_compare(&zone->dumptime, &next) < 0)
11626				next = zone->dumptime;
11627		}
11628		break;
11629
11630	case dns_zone_key:
11631		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11632		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11633			INSIST(!isc_time_isepoch(&zone->dumptime));
11634			if (isc_time_isepoch(&next) ||
11635			    isc_time_compare(&zone->dumptime, &next) < 0)
11636				next = zone->dumptime;
11637		}
11638		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
11639			if (isc_time_isepoch(&next) ||
11640			    (!isc_time_isepoch(&zone->refreshkeytime) &&
11641			    isc_time_compare(&zone->refreshkeytime, &next) < 0))
11642				next = zone->refreshkeytime;
11643		}
11644		break;
11645
11646	default:
11647		break;
11648	}
11649
11650	if (isc_time_isepoch(&next)) {
11651		zone_debuglog(zone, me, 10, "settimer inactive");
11652		result = isc_timer_reset(zone->timer, isc_timertype_inactive,
11653					  NULL, NULL, ISC_TRUE);
11654		if (result != ISC_R_SUCCESS)
11655			dns_zone_log(zone, ISC_LOG_ERROR,
11656				     "could not deactivate zone timer: %s",
11657				     isc_result_totext(result));
11658	} else {
11659		if (isc_time_compare(&next, now) <= 0)
11660			next = *now;
11661		result = isc_timer_reset(zone->timer, isc_timertype_once,
11662					 &next, NULL, ISC_TRUE);
11663		if (result != ISC_R_SUCCESS)
11664			dns_zone_log(zone, ISC_LOG_ERROR,
11665				     "could not reset zone timer: %s",
11666				     isc_result_totext(result));
11667	}
11668}
11669
11670static void
11671cancel_refresh(dns_zone_t *zone) {
11672	const char me[] = "cancel_refresh";
11673	isc_time_t now;
11674
11675	/*
11676	 * 'zone' locked by caller.
11677	 */
11678
11679	REQUIRE(DNS_ZONE_VALID(zone));
11680	REQUIRE(LOCKED_ZONE(zone));
11681
11682	ENTER;
11683
11684	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11685	TIME_NOW(&now);
11686	zone_settimer(zone, &now);
11687}
11688
11689static isc_result_t
11690notify_createmessage(dns_zone_t *zone, unsigned int flags,
11691		     dns_message_t **messagep)
11692{
11693	dns_db_t *zonedb = NULL;
11694	dns_dbnode_t *node = NULL;
11695	dns_dbversion_t *version = NULL;
11696	dns_message_t *message = NULL;
11697	dns_rdataset_t rdataset;
11698	dns_rdata_t rdata = DNS_RDATA_INIT;
11699
11700	dns_name_t *tempname = NULL;
11701	dns_rdata_t *temprdata = NULL;
11702	dns_rdatalist_t *temprdatalist = NULL;
11703	dns_rdataset_t *temprdataset = NULL;
11704
11705	isc_result_t result;
11706	isc_region_t r;
11707	isc_buffer_t *b = NULL;
11708
11709	REQUIRE(DNS_ZONE_VALID(zone));
11710	REQUIRE(messagep != NULL && *messagep == NULL);
11711
11712	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11713				    &message);
11714	if (result != ISC_R_SUCCESS)
11715		return (result);
11716
11717	message->opcode = dns_opcode_notify;
11718	message->flags |= DNS_MESSAGEFLAG_AA;
11719	message->rdclass = zone->rdclass;
11720
11721	result = dns_message_gettempname(message, &tempname);
11722	if (result != ISC_R_SUCCESS)
11723		goto cleanup;
11724
11725	result = dns_message_gettemprdataset(message, &temprdataset);
11726	if (result != ISC_R_SUCCESS)
11727		goto cleanup;
11728
11729	/*
11730	 * Make question.
11731	 */
11732	dns_name_init(tempname, NULL);
11733	dns_name_clone(&zone->origin, tempname);
11734	dns_rdataset_init(temprdataset);
11735	dns_rdataset_makequestion(temprdataset, zone->rdclass,
11736				  dns_rdatatype_soa);
11737	ISC_LIST_APPEND(tempname->list, temprdataset, link);
11738	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
11739	tempname = NULL;
11740	temprdataset = NULL;
11741
11742	if ((flags & DNS_NOTIFY_NOSOA) != 0)
11743		goto done;
11744
11745	result = dns_message_gettempname(message, &tempname);
11746	if (result != ISC_R_SUCCESS)
11747		goto soa_cleanup;
11748	result = dns_message_gettemprdata(message, &temprdata);
11749	if (result != ISC_R_SUCCESS)
11750		goto soa_cleanup;
11751	result = dns_message_gettemprdataset(message, &temprdataset);
11752	if (result != ISC_R_SUCCESS)
11753		goto soa_cleanup;
11754	result = dns_message_gettemprdatalist(message, &temprdatalist);
11755	if (result != ISC_R_SUCCESS)
11756		goto soa_cleanup;
11757
11758	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11759	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
11760	dns_db_attach(zone->db, &zonedb);
11761	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11762
11763	dns_name_init(tempname, NULL);
11764	dns_name_clone(&zone->origin, tempname);
11765	dns_db_currentversion(zonedb, &version);
11766	result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
11767	if (result != ISC_R_SUCCESS)
11768		goto soa_cleanup;
11769
11770	dns_rdataset_init(&rdataset);
11771	result = dns_db_findrdataset(zonedb, node, version,
11772				     dns_rdatatype_soa,
11773				     dns_rdatatype_none, 0, &rdataset,
11774				     NULL);
11775	if (result != ISC_R_SUCCESS)
11776		goto soa_cleanup;
11777	result = dns_rdataset_first(&rdataset);
11778	if (result != ISC_R_SUCCESS)
11779		goto soa_cleanup;
11780	dns_rdataset_current(&rdataset, &rdata);
11781	dns_rdata_toregion(&rdata, &r);
11782	result = isc_buffer_allocate(zone->mctx, &b, r.length);
11783	if (result != ISC_R_SUCCESS)
11784		goto soa_cleanup;
11785	isc_buffer_putmem(b, r.base, r.length);
11786	isc_buffer_usedregion(b, &r);
11787	dns_rdata_init(temprdata);
11788	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
11789	dns_message_takebuffer(message, &b);
11790	result = dns_rdataset_next(&rdataset);
11791	dns_rdataset_disassociate(&rdataset);
11792	if (result != ISC_R_NOMORE)
11793		goto soa_cleanup;
11794	temprdatalist->rdclass = rdata.rdclass;
11795	temprdatalist->type = rdata.type;
11796	temprdatalist->covers = 0;
11797	temprdatalist->ttl = rdataset.ttl;
11798	ISC_LIST_INIT(temprdatalist->rdata);
11799	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
11800
11801	dns_rdataset_init(temprdataset);
11802	result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
11803	if (result != ISC_R_SUCCESS)
11804		goto soa_cleanup;
11805
11806	ISC_LIST_APPEND(tempname->list, temprdataset, link);
11807	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
11808	temprdatalist = NULL;
11809	temprdataset = NULL;
11810	temprdata = NULL;
11811	tempname = NULL;
11812
11813 soa_cleanup:
11814	if (node != NULL)
11815		dns_db_detachnode(zonedb, &node);
11816	if (version != NULL)
11817		dns_db_closeversion(zonedb, &version, ISC_FALSE);
11818	if (zonedb != NULL)
11819		dns_db_detach(&zonedb);
11820	if (tempname != NULL)
11821		dns_message_puttempname(message, &tempname);
11822	if (temprdata != NULL)
11823		dns_message_puttemprdata(message, &temprdata);
11824	if (temprdataset != NULL)
11825		dns_message_puttemprdataset(message, &temprdataset);
11826	if (temprdatalist != NULL)
11827		dns_message_puttemprdatalist(message, &temprdatalist);
11828
11829 done:
11830	*messagep = message;
11831	return (ISC_R_SUCCESS);
11832
11833 cleanup:
11834	if (tempname != NULL)
11835		dns_message_puttempname(message, &tempname);
11836	if (temprdataset != NULL)
11837		dns_message_puttemprdataset(message, &temprdataset);
11838	dns_message_destroy(&message);
11839	return (result);
11840}
11841
11842isc_result_t
11843dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
11844		       dns_message_t *msg)
11845{
11846	unsigned int i;
11847	dns_rdata_soa_t soa;
11848	dns_rdataset_t *rdataset = NULL;
11849	dns_rdata_t rdata = DNS_RDATA_INIT;
11850	isc_result_t result;
11851	char fromtext[ISC_SOCKADDR_FORMATSIZE];
11852	int match = 0;
11853	isc_netaddr_t netaddr;
11854	isc_sockaddr_t local, remote;
11855
11856	REQUIRE(DNS_ZONE_VALID(zone));
11857
11858	/*
11859	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
11860	 * ROLLOVER.
11861	 *
11862	 * SOA:	RFC1996
11863	 * Check that 'from' is a valid notify source, (zone->masters).
11864	 *	Return DNS_R_REFUSED if not.
11865	 *
11866	 * If the notify message contains a serial number check it
11867	 * against the zones serial and return if <= current serial
11868	 *
11869	 * If a refresh check is progress, if so just record the
11870	 * fact we received a NOTIFY and from where and return.
11871	 * We will perform a new refresh check when the current one
11872	 * completes. Return ISC_R_SUCCESS.
11873	 *
11874	 * Otherwise initiate a refresh check using 'from' as the
11875	 * first address to check.  Return ISC_R_SUCCESS.
11876	 */
11877
11878	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
11879
11880	/*
11881	 * Notify messages are processed by the raw zone.
11882	 */
11883	LOCK_ZONE(zone);
11884	if (inline_secure(zone)) {
11885		result = dns_zone_notifyreceive(zone->raw, from, msg);
11886		UNLOCK_ZONE(zone);
11887		return (result);
11888	}
11889	/*
11890	 *  We only handle NOTIFY (SOA) at the present.
11891	 */
11892	if (isc_sockaddr_pf(from) == PF_INET)
11893		inc_stats(zone, dns_zonestatscounter_notifyinv4);
11894	else
11895		inc_stats(zone, dns_zonestatscounter_notifyinv6);
11896	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
11897	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
11898				 dns_rdatatype_soa, dns_rdatatype_none,
11899				 NULL, NULL) != ISC_R_SUCCESS) {
11900		UNLOCK_ZONE(zone);
11901		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
11902			dns_zone_log(zone, ISC_LOG_NOTICE,
11903				     "NOTIFY with no "
11904				     "question section from: %s", fromtext);
11905			return (DNS_R_FORMERR);
11906		}
11907		dns_zone_log(zone, ISC_LOG_NOTICE,
11908			     "NOTIFY zone does not match");
11909		return (DNS_R_NOTIMP);
11910	}
11911
11912	/*
11913	 * If we are a master zone just succeed.
11914	 */
11915	if (zone->type == dns_zone_master) {
11916		UNLOCK_ZONE(zone);
11917		return (ISC_R_SUCCESS);
11918	}
11919
11920	isc_netaddr_fromsockaddr(&netaddr, from);
11921	for (i = 0; i < zone->masterscnt; i++) {
11922		if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
11923			break;
11924		if (zone->view->aclenv.match_mapped &&
11925		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
11926		    isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
11927			isc_netaddr_t na1, na2;
11928			isc_netaddr_fromv4mapped(&na1, &netaddr);
11929			isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
11930			if (isc_netaddr_equal(&na1, &na2))
11931				break;
11932		}
11933	}
11934
11935	/*
11936	 * Accept notify requests from non masters if they are on
11937	 * 'zone->notify_acl'.
11938	 */
11939	if (i >= zone->masterscnt && zone->notify_acl != NULL &&
11940	    dns_acl_match(&netaddr, NULL, zone->notify_acl,
11941			  &zone->view->aclenv,
11942			  &match, NULL) == ISC_R_SUCCESS &&
11943	    match > 0)
11944	{
11945		/* Accept notify. */
11946	} else if (i >= zone->masterscnt) {
11947		UNLOCK_ZONE(zone);
11948		dns_zone_log(zone, ISC_LOG_INFO,
11949			     "refused notify from non-master: %s", fromtext);
11950		inc_stats(zone, dns_zonestatscounter_notifyrej);
11951		return (DNS_R_REFUSED);
11952	}
11953
11954	/*
11955	 * If the zone is loaded and there are answers check the serial
11956	 * to see if we need to do a refresh.  Do not worry about this
11957	 * check if we are a dialup zone as we use the notify request
11958	 * to trigger a refresh check.
11959	 */
11960	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
11961	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11962	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
11963		result = dns_message_findname(msg, DNS_SECTION_ANSWER,
11964					      &zone->origin,
11965					      dns_rdatatype_soa,
11966					      dns_rdatatype_none, NULL,
11967					      &rdataset);
11968		if (result == ISC_R_SUCCESS)
11969			result = dns_rdataset_first(rdataset);
11970		if (result == ISC_R_SUCCESS) {
11971			isc_uint32_t serial = 0, oldserial;
11972			unsigned int soacount;
11973
11974			dns_rdataset_current(rdataset, &rdata);
11975			result = dns_rdata_tostruct(&rdata, &soa, NULL);
11976			RUNTIME_CHECK(result == ISC_R_SUCCESS);
11977			serial = soa.serial;
11978			/*
11979			 * The following should safely be performed without DB
11980			 * lock and succeed in this context.
11981			 */
11982			result = zone_get_from_db(zone, zone->db, NULL,
11983						  &soacount, &oldserial, NULL,
11984						  NULL, NULL, NULL, NULL);
11985			RUNTIME_CHECK(result == ISC_R_SUCCESS);
11986			RUNTIME_CHECK(soacount > 0U);
11987			if (isc_serial_le(serial, oldserial)) {
11988				dns_zone_log(zone,
11989					     ISC_LOG_INFO,
11990					     "notify from %s: "
11991					     "zone is up to date",
11992					     fromtext);
11993				UNLOCK_ZONE(zone);
11994				return (ISC_R_SUCCESS);
11995			}
11996		}
11997	}
11998
11999	/*
12000	 * If we got this far and there was a refresh in progress just
12001	 * let it complete.  Record where we got the notify from so we
12002	 * can perform a refresh check when the current one completes
12003	 */
12004	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
12005		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12006		zone->notifyfrom = *from;
12007		UNLOCK_ZONE(zone);
12008		dns_zone_log(zone, ISC_LOG_INFO,
12009			     "notify from %s: refresh in progress, "
12010			     "refresh check queued",
12011			     fromtext);
12012		return (ISC_R_SUCCESS);
12013	}
12014	zone->notifyfrom = *from;
12015	local = zone->masteraddr;
12016	remote = zone->sourceaddr;
12017	UNLOCK_ZONE(zone);
12018	dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
12019	dns_zone_refresh(zone);
12020	return (ISC_R_SUCCESS);
12021}
12022
12023void
12024dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
12025
12026	REQUIRE(DNS_ZONE_VALID(zone));
12027
12028	LOCK_ZONE(zone);
12029	if (zone->notify_acl != NULL)
12030		dns_acl_detach(&zone->notify_acl);
12031	dns_acl_attach(acl, &zone->notify_acl);
12032	UNLOCK_ZONE(zone);
12033}
12034
12035void
12036dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
12037
12038	REQUIRE(DNS_ZONE_VALID(zone));
12039
12040	LOCK_ZONE(zone);
12041	if (zone->query_acl != NULL)
12042		dns_acl_detach(&zone->query_acl);
12043	dns_acl_attach(acl, &zone->query_acl);
12044	UNLOCK_ZONE(zone);
12045}
12046
12047void
12048dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
12049
12050	REQUIRE(DNS_ZONE_VALID(zone));
12051
12052	LOCK_ZONE(zone);
12053	if (zone->queryon_acl != NULL)
12054		dns_acl_detach(&zone->queryon_acl);
12055	dns_acl_attach(acl, &zone->queryon_acl);
12056	UNLOCK_ZONE(zone);
12057}
12058
12059void
12060dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
12061
12062	REQUIRE(DNS_ZONE_VALID(zone));
12063
12064	LOCK_ZONE(zone);
12065	if (zone->update_acl != NULL)
12066		dns_acl_detach(&zone->update_acl);
12067	dns_acl_attach(acl, &zone->update_acl);
12068	UNLOCK_ZONE(zone);
12069}
12070
12071void
12072dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
12073
12074	REQUIRE(DNS_ZONE_VALID(zone));
12075
12076	LOCK_ZONE(zone);
12077	if (zone->forward_acl != NULL)
12078		dns_acl_detach(&zone->forward_acl);
12079	dns_acl_attach(acl, &zone->forward_acl);
12080	UNLOCK_ZONE(zone);
12081}
12082
12083void
12084dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
12085
12086	REQUIRE(DNS_ZONE_VALID(zone));
12087
12088	LOCK_ZONE(zone);
12089	if (zone->xfr_acl != NULL)
12090		dns_acl_detach(&zone->xfr_acl);
12091	dns_acl_attach(acl, &zone->xfr_acl);
12092	UNLOCK_ZONE(zone);
12093}
12094
12095dns_acl_t *
12096dns_zone_getnotifyacl(dns_zone_t *zone) {
12097
12098	REQUIRE(DNS_ZONE_VALID(zone));
12099
12100	return (zone->notify_acl);
12101}
12102
12103dns_acl_t *
12104dns_zone_getqueryacl(dns_zone_t *zone) {
12105
12106	REQUIRE(DNS_ZONE_VALID(zone));
12107
12108	return (zone->query_acl);
12109}
12110
12111dns_acl_t *
12112dns_zone_getqueryonacl(dns_zone_t *zone) {
12113
12114	REQUIRE(DNS_ZONE_VALID(zone));
12115
12116	return (zone->queryon_acl);
12117}
12118
12119dns_acl_t *
12120dns_zone_getupdateacl(dns_zone_t *zone) {
12121
12122	REQUIRE(DNS_ZONE_VALID(zone));
12123
12124	return (zone->update_acl);
12125}
12126
12127dns_acl_t *
12128dns_zone_getforwardacl(dns_zone_t *zone) {
12129
12130	REQUIRE(DNS_ZONE_VALID(zone));
12131
12132	return (zone->forward_acl);
12133}
12134
12135dns_acl_t *
12136dns_zone_getxfracl(dns_zone_t *zone) {
12137
12138	REQUIRE(DNS_ZONE_VALID(zone));
12139
12140	return (zone->xfr_acl);
12141}
12142
12143void
12144dns_zone_clearupdateacl(dns_zone_t *zone) {
12145
12146	REQUIRE(DNS_ZONE_VALID(zone));
12147
12148	LOCK_ZONE(zone);
12149	if (zone->update_acl != NULL)
12150		dns_acl_detach(&zone->update_acl);
12151	UNLOCK_ZONE(zone);
12152}
12153
12154void
12155dns_zone_clearforwardacl(dns_zone_t *zone) {
12156
12157	REQUIRE(DNS_ZONE_VALID(zone));
12158
12159	LOCK_ZONE(zone);
12160	if (zone->forward_acl != NULL)
12161		dns_acl_detach(&zone->forward_acl);
12162	UNLOCK_ZONE(zone);
12163}
12164
12165void
12166dns_zone_clearnotifyacl(dns_zone_t *zone) {
12167
12168	REQUIRE(DNS_ZONE_VALID(zone));
12169
12170	LOCK_ZONE(zone);
12171	if (zone->notify_acl != NULL)
12172		dns_acl_detach(&zone->notify_acl);
12173	UNLOCK_ZONE(zone);
12174}
12175
12176void
12177dns_zone_clearqueryacl(dns_zone_t *zone) {
12178
12179	REQUIRE(DNS_ZONE_VALID(zone));
12180
12181	LOCK_ZONE(zone);
12182	if (zone->query_acl != NULL)
12183		dns_acl_detach(&zone->query_acl);
12184	UNLOCK_ZONE(zone);
12185}
12186
12187void
12188dns_zone_clearqueryonacl(dns_zone_t *zone) {
12189
12190	REQUIRE(DNS_ZONE_VALID(zone));
12191
12192	LOCK_ZONE(zone);
12193	if (zone->queryon_acl != NULL)
12194		dns_acl_detach(&zone->queryon_acl);
12195	UNLOCK_ZONE(zone);
12196}
12197
12198void
12199dns_zone_clearxfracl(dns_zone_t *zone) {
12200
12201	REQUIRE(DNS_ZONE_VALID(zone));
12202
12203	LOCK_ZONE(zone);
12204	if (zone->xfr_acl != NULL)
12205		dns_acl_detach(&zone->xfr_acl);
12206	UNLOCK_ZONE(zone);
12207}
12208
12209isc_boolean_t
12210dns_zone_getupdatedisabled(dns_zone_t *zone) {
12211	REQUIRE(DNS_ZONE_VALID(zone));
12212	return (zone->update_disabled);
12213
12214}
12215
12216void
12217dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
12218	REQUIRE(DNS_ZONE_VALID(zone));
12219	zone->update_disabled = state;
12220}
12221
12222isc_boolean_t
12223dns_zone_getzeronosoattl(dns_zone_t *zone) {
12224	REQUIRE(DNS_ZONE_VALID(zone));
12225	return (zone->zero_no_soa_ttl);
12226
12227}
12228
12229void
12230dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
12231	REQUIRE(DNS_ZONE_VALID(zone));
12232	zone->zero_no_soa_ttl = state;
12233}
12234
12235void
12236dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
12237
12238	REQUIRE(DNS_ZONE_VALID(zone));
12239
12240	zone->check_names = severity;
12241}
12242
12243dns_severity_t
12244dns_zone_getchecknames(dns_zone_t *zone) {
12245
12246	REQUIRE(DNS_ZONE_VALID(zone));
12247
12248	return (zone->check_names);
12249}
12250
12251void
12252dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
12253
12254	REQUIRE(DNS_ZONE_VALID(zone));
12255
12256	zone->journalsize = size;
12257}
12258
12259isc_int32_t
12260dns_zone_getjournalsize(dns_zone_t *zone) {
12261
12262	REQUIRE(DNS_ZONE_VALID(zone));
12263
12264	return (zone->journalsize);
12265}
12266
12267static void
12268zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
12269	isc_result_t result = ISC_R_FAILURE;
12270	isc_buffer_t buffer;
12271
12272	REQUIRE(buf != NULL);
12273	REQUIRE(length > 1U);
12274
12275	/*
12276	 * Leave space for terminating '\0'.
12277	 */
12278	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12279	if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
12280		if (dns_name_dynamic(&zone->origin))
12281			result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12282		if (result != ISC_R_SUCCESS &&
12283		    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12284			isc_buffer_putstr(&buffer, "<UNKNOWN>");
12285
12286		if (isc_buffer_availablelength(&buffer) > 0)
12287			isc_buffer_putstr(&buffer, "/");
12288		(void)dns_rdataclass_totext(zone->rdclass, &buffer);
12289	}
12290
12291	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
12292	    strcmp(zone->view->name, "_default") != 0 &&
12293	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
12294		isc_buffer_putstr(&buffer, "/");
12295		isc_buffer_putstr(&buffer, zone->view->name);
12296	}
12297	if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
12298		isc_buffer_putstr(&buffer, " (signed)");
12299	if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
12300		isc_buffer_putstr(&buffer, " (unsigned)");
12301
12302	buf[isc_buffer_usedlength(&buffer)] = '\0';
12303}
12304
12305static void
12306zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
12307	isc_result_t result = ISC_R_FAILURE;
12308	isc_buffer_t buffer;
12309
12310	REQUIRE(buf != NULL);
12311	REQUIRE(length > 1U);
12312
12313	/*
12314	 * Leave space for terminating '\0'.
12315	 */
12316	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12317	if (dns_name_dynamic(&zone->origin))
12318		result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12319	if (result != ISC_R_SUCCESS &&
12320	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12321		isc_buffer_putstr(&buffer, "<UNKNOWN>");
12322
12323	buf[isc_buffer_usedlength(&buffer)] = '\0';
12324}
12325
12326static void
12327zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
12328	isc_buffer_t buffer;
12329
12330	REQUIRE(buf != NULL);
12331	REQUIRE(length > 1U);
12332
12333	/*
12334	 * Leave space for terminating '\0'.
12335	 */
12336	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12337	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
12338
12339	buf[isc_buffer_usedlength(&buffer)] = '\0';
12340}
12341
12342static void
12343zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
12344	isc_buffer_t buffer;
12345
12346	REQUIRE(buf != NULL);
12347	REQUIRE(length > 1U);
12348
12349
12350	/*
12351	 * Leave space for terminating '\0'.
12352	 */
12353	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12354
12355	if (zone->view == NULL) {
12356		isc_buffer_putstr(&buffer, "_none");
12357	} else if (strlen(zone->view->name)
12358		   < isc_buffer_availablelength(&buffer)) {
12359		isc_buffer_putstr(&buffer, zone->view->name);
12360	} else {
12361		isc_buffer_putstr(&buffer, "_toolong");
12362	}
12363
12364	buf[isc_buffer_usedlength(&buffer)] = '\0';
12365}
12366
12367void
12368dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
12369	REQUIRE(DNS_ZONE_VALID(zone));
12370	REQUIRE(buf != NULL);
12371	zone_namerd_tostr(zone, buf, length);
12372}
12373
12374static void
12375notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12376	va_list ap;
12377	char message[4096];
12378
12379	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12380		return;
12381
12382	va_start(ap, fmt);
12383	vsnprintf(message, sizeof(message), fmt, ap);
12384	va_end(ap);
12385	isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
12386		      level, "zone %s: %s", zone->strnamerd, message);
12387}
12388
12389void
12390dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
12391	      int level, const char *fmt, ...) {
12392	va_list ap;
12393	char message[4096];
12394
12395	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12396		return;
12397
12398	va_start(ap, fmt);
12399	vsnprintf(message, sizeof(message), fmt, ap);
12400	va_end(ap);
12401	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
12402		      level, "%s%s: %s", (zone->type == dns_zone_key) ?
12403		      "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12404		      "redirect-zone" : "zone ", zone->strnamerd, message);
12405}
12406
12407void
12408dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12409	va_list ap;
12410	char message[4096];
12411
12412	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12413		return;
12414
12415	va_start(ap, fmt);
12416	vsnprintf(message, sizeof(message), fmt, ap);
12417	va_end(ap);
12418	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12419		      level, "%s%s: %s", (zone->type == dns_zone_key) ?
12420		      "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12421		      "redirect-zone" : "zone ", zone->strnamerd, message);
12422}
12423
12424static void
12425zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
12426	      const char *fmt, ...)
12427{
12428	va_list ap;
12429	char message[4096];
12430	int level = ISC_LOG_DEBUG(debuglevel);
12431	const char *zstr;
12432
12433	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12434		return;
12435
12436	va_start(ap, fmt);
12437	vsnprintf(message, sizeof(message), fmt, ap);
12438	va_end(ap);
12439
12440	switch (zone->type) {
12441	case dns_zone_key:
12442		zstr = "managed-keys-zone";
12443		break;
12444	case dns_zone_redirect:
12445		zstr = "redirect-zone";
12446		break;
12447	default:
12448		zstr = "zone";
12449	}
12450
12451	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12452		      level, "%s: %s %s: %s", me, zstr, zone->strnamerd,
12453		      message);
12454}
12455
12456static int
12457message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
12458{
12459	isc_result_t result;
12460	dns_name_t *name;
12461	dns_rdataset_t *curr;
12462	int count = 0;
12463
12464	result = dns_message_firstname(msg, section);
12465	while (result == ISC_R_SUCCESS) {
12466		name = NULL;
12467		dns_message_currentname(msg, section, &name);
12468
12469		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
12470		     curr = ISC_LIST_PREV(curr, link)) {
12471			if (curr->type == type)
12472				count++;
12473		}
12474		result = dns_message_nextname(msg, section);
12475	}
12476
12477	return (count);
12478}
12479
12480void
12481dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
12482	REQUIRE(DNS_ZONE_VALID(zone));
12483
12484	zone->maxxfrin = maxxfrin;
12485}
12486
12487isc_uint32_t
12488dns_zone_getmaxxfrin(dns_zone_t *zone) {
12489	REQUIRE(DNS_ZONE_VALID(zone));
12490
12491	return (zone->maxxfrin);
12492}
12493
12494void
12495dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
12496	REQUIRE(DNS_ZONE_VALID(zone));
12497	zone->maxxfrout = maxxfrout;
12498}
12499
12500isc_uint32_t
12501dns_zone_getmaxxfrout(dns_zone_t *zone) {
12502	REQUIRE(DNS_ZONE_VALID(zone));
12503
12504	return (zone->maxxfrout);
12505}
12506
12507dns_zonetype_t
12508dns_zone_gettype(dns_zone_t *zone) {
12509	REQUIRE(DNS_ZONE_VALID(zone));
12510
12511	return (zone->type);
12512}
12513
12514dns_name_t *
12515dns_zone_getorigin(dns_zone_t *zone) {
12516	REQUIRE(DNS_ZONE_VALID(zone));
12517
12518	return (&zone->origin);
12519}
12520
12521void
12522dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
12523	REQUIRE(DNS_ZONE_VALID(zone));
12524
12525	LOCK_ZONE(zone);
12526	if (zone->task != NULL)
12527		isc_task_detach(&zone->task);
12528	isc_task_attach(task, &zone->task);
12529	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12530	if (zone->db != NULL)
12531		dns_db_settask(zone->db, zone->task);
12532	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12533	UNLOCK_ZONE(zone);
12534}
12535
12536void
12537dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
12538	REQUIRE(DNS_ZONE_VALID(zone));
12539	isc_task_attach(zone->task, target);
12540}
12541
12542void
12543dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
12544	REQUIRE(DNS_ZONE_VALID(zone));
12545
12546	if (idlein == 0)
12547		idlein = DNS_DEFAULT_IDLEIN;
12548	zone->idlein = idlein;
12549}
12550
12551isc_uint32_t
12552dns_zone_getidlein(dns_zone_t *zone) {
12553	REQUIRE(DNS_ZONE_VALID(zone));
12554
12555	return (zone->idlein);
12556}
12557
12558void
12559dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
12560	REQUIRE(DNS_ZONE_VALID(zone));
12561
12562	zone->idleout = idleout;
12563}
12564
12565isc_uint32_t
12566dns_zone_getidleout(dns_zone_t *zone) {
12567	REQUIRE(DNS_ZONE_VALID(zone));
12568
12569	return (zone->idleout);
12570}
12571
12572static void
12573notify_done(isc_task_t *task, isc_event_t *event) {
12574	dns_requestevent_t *revent = (dns_requestevent_t *)event;
12575	dns_notify_t *notify;
12576	isc_result_t result;
12577	dns_message_t *message = NULL;
12578	isc_buffer_t buf;
12579	char rcode[128];
12580	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12581
12582	UNUSED(task);
12583
12584	notify = event->ev_arg;
12585	REQUIRE(DNS_NOTIFY_VALID(notify));
12586	INSIST(task == notify->zone->task);
12587
12588	isc_buffer_init(&buf, rcode, sizeof(rcode));
12589	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12590
12591	result = revent->result;
12592	if (result == ISC_R_SUCCESS)
12593		result = dns_message_create(notify->zone->mctx,
12594					    DNS_MESSAGE_INTENTPARSE, &message);
12595	if (result == ISC_R_SUCCESS)
12596		result = dns_request_getresponse(revent->request, message,
12597					DNS_MESSAGEPARSE_PRESERVEORDER);
12598	if (result == ISC_R_SUCCESS)
12599		result = dns_rcode_totext(message->rcode, &buf);
12600	if (result == ISC_R_SUCCESS)
12601		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12602			   "notify response from %s: %.*s",
12603			   addrbuf, (int)buf.used, rcode);
12604	else
12605		notify_log(notify->zone, ISC_LOG_DEBUG(2),
12606			   "notify to %s failed: %s", addrbuf,
12607			   dns_result_totext(result));
12608
12609	/*
12610	 * Old bind's return formerr if they see a soa record.	Retry w/o
12611	 * the soa if we see a formerr and had sent a SOA.
12612	 */
12613	isc_event_free(&event);
12614	if (message != NULL && message->rcode == dns_rcode_formerr &&
12615	    (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
12616		notify->flags |= DNS_NOTIFY_NOSOA;
12617		dns_request_destroy(&notify->request);
12618		result = notify_send_queue(notify);
12619		if (result != ISC_R_SUCCESS)
12620			notify_destroy(notify, ISC_FALSE);
12621	} else {
12622		if (result == ISC_R_TIMEDOUT)
12623			notify_log(notify->zone, ISC_LOG_DEBUG(1),
12624				   "notify to %s: retries exceeded", addrbuf);
12625		notify_destroy(notify, ISC_FALSE);
12626	}
12627	if (message != NULL)
12628		dns_message_destroy(&message);
12629}
12630
12631struct secure_event {
12632	isc_event_t e;
12633	dns_db_t *db;
12634	isc_uint32_t serial;
12635};
12636
12637static void
12638update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
12639	UNUSED(arg);
12640	dns_zone_log(zone, level, "%s", message);
12641}
12642
12643static isc_result_t
12644sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal,
12645		    isc_uint32_t start, isc_uint32_t end,
12646		    dns_difftuple_t **soatuplep, dns_diff_t *diff)
12647{
12648	isc_result_t result;
12649	dns_difftuple_t *tuple = NULL;
12650	dns_diffop_t op = DNS_DIFFOP_ADD;
12651	int n_soa = 0;
12652
12653	REQUIRE(soatuplep != NULL);
12654
12655	if (start == end)
12656		return (DNS_R_UNCHANGED);
12657
12658	CHECK(dns_journal_iter_init(journal, start, end));
12659	for (result = dns_journal_first_rr(journal);
12660	     result == ISC_R_SUCCESS;
12661	     result = dns_journal_next_rr(journal))
12662	{
12663		dns_name_t *name = NULL;
12664		isc_uint32_t ttl;
12665		dns_rdata_t *rdata = NULL;
12666		dns_journal_current_rr(journal, &name, &ttl, &rdata);
12667
12668		if (rdata->type == dns_rdatatype_soa) {
12669			n_soa++;
12670			if (n_soa == 2) {
12671				/*
12672				 * Save the latest raw SOA record.
12673				 */
12674				if (*soatuplep != NULL)
12675					dns_difftuple_free(soatuplep);
12676				CHECK(dns_difftuple_create(diff->mctx,
12677							   DNS_DIFFOP_ADD,
12678							   name, ttl, rdata,
12679							   soatuplep));
12680			}
12681			if (n_soa == 3)
12682				n_soa = 1;
12683			continue;
12684		}
12685
12686		/* Sanity. */
12687		if (n_soa == 0) {
12688			dns_zone_log(zone->raw, ISC_LOG_ERROR,
12689				     "corrupt journal file: '%s'\n",
12690				     zone->raw->journal);
12691			return (ISC_R_FAILURE);
12692		}
12693
12694		if (zone->privatetype != 0 &&
12695		    rdata->type == zone->privatetype)
12696			continue;
12697
12698		if (rdata->type == dns_rdatatype_nsec ||
12699		    rdata->type == dns_rdatatype_rrsig ||
12700		    rdata->type == dns_rdatatype_nsec3 ||
12701		    rdata->type == dns_rdatatype_dnskey ||
12702		    rdata->type == dns_rdatatype_nsec3param)
12703			continue;
12704
12705		op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
12706
12707		CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
12708					   &tuple));
12709		dns_diff_appendminimal(diff, &tuple);
12710	}
12711	if (result == ISC_R_NOMORE)
12712		result = ISC_R_SUCCESS;
12713
12714 failure:
12715	return(result);
12716}
12717
12718static isc_result_t
12719sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb,
12720	       dns_dbversion_t *secver, dns_difftuple_t **soatuple,
12721	       dns_diff_t *diff)
12722{
12723	isc_result_t result;
12724	dns_db_t *rawdb = NULL;
12725	dns_dbversion_t *rawver = NULL;
12726	dns_difftuple_t *tuple = NULL, *next;
12727	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
12728	dns_rdata_soa_t oldsoa, newsoa;
12729
12730	REQUIRE(DNS_ZONE_VALID(seczone));
12731	REQUIRE(inline_secure(seczone));
12732	REQUIRE(soatuple != NULL && *soatuple == NULL);
12733
12734	if (!seczone->sourceserialset)
12735		return (DNS_R_UNCHANGED);
12736
12737	dns_db_attach(seczone->raw->db, &rawdb);
12738	dns_db_currentversion(rawdb, &rawver);
12739	result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
12740	dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
12741	dns_db_detach(&rawdb);
12742
12743	if (result != ISC_R_SUCCESS)
12744		return (result);
12745
12746	for (tuple = ISC_LIST_HEAD(diff->tuples);
12747	     tuple != NULL;
12748	     tuple = next)
12749	{
12750		next = ISC_LIST_NEXT(tuple, link);
12751		if (tuple->rdata.type == dns_rdatatype_nsec ||
12752		    tuple->rdata.type == dns_rdatatype_rrsig ||
12753		    tuple->rdata.type == dns_rdatatype_dnskey ||
12754		    tuple->rdata.type == dns_rdatatype_nsec3 ||
12755		    tuple->rdata.type == dns_rdatatype_nsec3param)
12756		{
12757			ISC_LIST_UNLINK(diff->tuples, tuple, link);
12758			dns_difftuple_free(&tuple);
12759			continue;
12760		}
12761		if (tuple->rdata.type == dns_rdatatype_soa) {
12762			if (tuple->op == DNS_DIFFOP_DEL) {
12763				INSIST(oldtuple == NULL);
12764				oldtuple = tuple;
12765			}
12766			if (tuple->op == DNS_DIFFOP_ADD) {
12767				INSIST(newtuple == NULL);
12768				newtuple = tuple;
12769			}
12770		}
12771	}
12772
12773	if (oldtuple != NULL && newtuple != NULL) {
12774
12775		result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
12776		RUNTIME_CHECK(result == ISC_R_SUCCESS);
12777
12778		result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
12779		RUNTIME_CHECK(result == ISC_R_SUCCESS);
12780
12781		/*
12782		 * If the SOA records are the same except for the serial
12783		 * remove them from the diff.
12784		 */
12785		if (oldsoa.refresh == newsoa.refresh &&
12786		    oldsoa.retry == newsoa.retry &&
12787		    oldsoa.minimum == newsoa.minimum &&
12788		    oldsoa.expire == newsoa.expire &&
12789		    dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
12790		    dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
12791			ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12792			dns_difftuple_free(&oldtuple);
12793			ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12794			dns_difftuple_free(&newtuple);
12795		}
12796	}
12797
12798	if (ISC_LIST_EMPTY(diff->tuples))
12799		return (DNS_R_UNCHANGED);
12800
12801	/*
12802	 * If there are still SOA records in the diff they can now be removed
12803	 * saving the new SOA record.
12804	 */
12805	if (oldtuple != NULL) {
12806		ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12807		dns_difftuple_free(&oldtuple);
12808	}
12809
12810	if (newtuple != NULL) {
12811		ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12812		*soatuple = newtuple;
12813	}
12814
12815	return (ISC_R_SUCCESS);
12816}
12817
12818static void
12819receive_secure_serial(isc_task_t *task, isc_event_t *event) {
12820	static char me[] = "receive_secure_serial";
12821	isc_result_t result;
12822	dns_journal_t *rjournal = NULL;
12823	isc_uint32_t start, end;
12824	dns_zone_t *zone;
12825	dns_db_t *db = NULL;
12826	dns_dbversion_t *newver = NULL, *oldver = NULL;
12827	dns_diff_t diff;
12828	dns_difftuple_t *tuple = NULL, *soatuple = NULL;
12829	dns_update_log_t log = { update_log_cb, NULL };
12830	isc_time_t timenow;
12831
12832	zone = event->ev_arg;
12833	end = ((struct secure_event *)event)->serial;
12834	isc_event_free(&event);
12835
12836	ENTER;
12837
12838	LOCK_ZONE(zone);
12839
12840	dns_diff_init(zone->mctx, &diff);
12841
12842	UNUSED(task);
12843
12844	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12845	if (zone->db != NULL)
12846		dns_db_attach(zone->db, &db);
12847	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12848
12849	/*
12850	 * zone->db may be NULL if the load from disk failed.
12851	 */
12852	if (db == NULL || !inline_secure(zone)) {
12853		result = ISC_R_FAILURE;
12854		goto failure;
12855	}
12856
12857	/*
12858	 * We first attempt to sync the raw zone to the secure zone
12859	 * by using the raw zone's journal, applying all the deltas
12860	 * from the latest source-serial of the secure zone up to
12861	 * the current serial number of the raw zone.
12862	 *
12863	 * If that fails, then we'll fall back to a direct comparison
12864	 * between raw and secure zones.
12865	 */
12866	result = dns_journal_open(zone->raw->mctx, zone->raw->journal,
12867				  DNS_JOURNAL_WRITE, &rjournal);
12868	if (result != ISC_R_SUCCESS)
12869		goto failure;
12870	else {
12871		dns_journal_t *sjournal = NULL;
12872
12873		result = dns_journal_open(zone->mctx, zone->journal,
12874					  DNS_JOURNAL_READ, &sjournal);
12875		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
12876			goto failure;
12877
12878		if (!dns_journal_get_sourceserial(rjournal, &start)) {
12879			start = dns_journal_first_serial(rjournal);
12880			dns_journal_set_sourceserial(rjournal, start);
12881		}
12882		if (sjournal != NULL) {
12883			isc_uint32_t serial;
12884			/*
12885			 * We read the secure journal first, if that exists
12886			 * use its value provided it is greater that from the
12887			 * raw journal.
12888			 */
12889			if (dns_journal_get_sourceserial(sjournal, &serial)) {
12890				if (isc_serial_gt(serial, start))
12891					start = serial;
12892			}
12893			dns_journal_destroy(&sjournal);
12894		}
12895	}
12896
12897	dns_db_currentversion(db, &oldver);
12898	CHECK(dns_db_newversion(db, &newver));
12899
12900	/*
12901	 * Try to apply diffs from the raw zone's journal to the secure
12902	 * zone.  If that fails, we recover by syncing up the databases
12903	 * directly.
12904	 */
12905	result = sync_secure_journal(zone, rjournal, start, end,
12906				     &soatuple, &diff);
12907	if (result == DNS_R_UNCHANGED)
12908		goto failure;
12909	else if (result != ISC_R_SUCCESS)
12910		CHECK(sync_secure_db(zone, db, oldver, &soatuple, &diff));
12911
12912	CHECK(dns_diff_apply(&diff, db, newver));
12913
12914	if (soatuple != NULL) {
12915		isc_uint32_t oldserial, newserial, desired;
12916
12917		CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
12918					    DNS_DIFFOP_DEL, &tuple));
12919		oldserial = dns_soa_getserial(&tuple->rdata);
12920		newserial = desired = dns_soa_getserial(&soatuple->rdata);
12921		if (!isc_serial_gt(newserial, oldserial)) {
12922			newserial = oldserial + 1;
12923			if (newserial == 0)
12924				newserial++;
12925			dns_soa_setserial(newserial, &soatuple->rdata);
12926		}
12927		CHECK(do_one_tuple(&tuple, db, newver, &diff));
12928		CHECK(do_one_tuple(&soatuple, db, newver, &diff));
12929		dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
12930			     newserial, desired);
12931	} else
12932		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
12933					zone->updatemethod));
12934
12935	CHECK(dns_update_signatures(&log, zone, db, oldver, newver,
12936				    &diff, zone->sigvalidityinterval));
12937
12938	CHECK(zone_journal(zone, &diff, &end, "receive_secure_serial"));
12939
12940	dns_journal_set_sourceserial(rjournal, end);
12941	dns_journal_commit(rjournal);
12942
12943	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12944
12945	zone->sourceserial = end;
12946	zone->sourceserialset = ISC_TRUE;
12947	zone_needdump(zone, DNS_DUMP_DELAY);
12948
12949	TIME_NOW(&timenow);
12950	zone_settimer(zone, &timenow);
12951
12952	dns_db_closeversion(db, &oldver, ISC_FALSE);
12953	dns_db_closeversion(db, &newver, ISC_TRUE);
12954
12955 failure:
12956	UNLOCK_ZONE(zone);
12957	if (result != ISC_R_SUCCESS)
12958		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
12959			     dns_result_totext(result));
12960	if (tuple != NULL)
12961		dns_difftuple_free(&tuple);
12962	if (soatuple != NULL)
12963		dns_difftuple_free(&soatuple);
12964	if (db != NULL) {
12965		if (oldver != NULL)
12966			dns_db_closeversion(db, &oldver, ISC_FALSE);
12967		if (newver != NULL)
12968			dns_db_closeversion(db, &newver, ISC_FALSE);
12969		dns_db_detach(&db);
12970	}
12971	if (rjournal != NULL)
12972		dns_journal_destroy(&rjournal);
12973	dns_diff_clear(&diff);
12974	dns_zone_idetach(&zone);
12975}
12976
12977static isc_result_t
12978zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) {
12979	isc_event_t *e;
12980	dns_zone_t *dummy = NULL;
12981
12982	e = isc_event_allocate(zone->secure->mctx, zone,
12983			       DNS_EVENT_ZONESECURESERIAL,
12984			       receive_secure_serial, zone->secure,
12985			       sizeof(struct secure_event));
12986	if (e == NULL)
12987		return (ISC_R_NOMEMORY);
12988	((struct secure_event *)e)->serial = serial;
12989	INSIST(LOCKED_ZONE(zone->secure));
12990	zone_iattach(zone->secure, &dummy);
12991	isc_task_send(zone->secure->task, &e);
12992
12993	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
12994	return (ISC_R_SUCCESS);
12995}
12996
12997static isc_result_t
12998checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
12999	       dns_rdataset_t *rdataset, isc_uint32_t oldserial)
13000{
13001	dns_rdata_soa_t soa;
13002	dns_rdata_t rdata = DNS_RDATA_INIT;
13003	dns_rdatalist_t temprdatalist;
13004	dns_rdataset_t temprdataset;
13005	isc_buffer_t b;
13006	isc_result_t result;
13007	unsigned char buf[DNS_SOA_BUFFERSIZE];
13008
13009	result = dns_rdataset_first(rdataset);
13010	RUNTIME_CHECK(result == ISC_R_SUCCESS);
13011	dns_rdataset_current(rdataset, &rdata);
13012	result = dns_rdata_tostruct(&rdata, &soa, NULL);
13013	RUNTIME_CHECK(result == ISC_R_SUCCESS);
13014
13015	if (isc_serial_gt(soa.serial, oldserial))
13016		return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
13017					   NULL));
13018	/*
13019	 * Always bump the serial.
13020	 */
13021	oldserial++;
13022	if (oldserial == 0)
13023		oldserial++;
13024	soa.serial = oldserial;
13025
13026	/*
13027	 * Construct a replacement rdataset.
13028	 */
13029	dns_rdata_reset(&rdata);
13030	isc_buffer_init(&b, buf, sizeof(buf));
13031	result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
13032				      dns_rdatatype_soa, &soa, &b);
13033	RUNTIME_CHECK(result == ISC_R_SUCCESS);
13034	temprdatalist.rdclass = rdata.rdclass;
13035	temprdatalist.type = rdata.type;
13036	temprdatalist.covers = 0;
13037	temprdatalist.ttl = rdataset->ttl;
13038	ISC_LIST_INIT(temprdatalist.rdata);
13039	ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
13040
13041	dns_rdataset_init(&temprdataset);
13042	result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
13043	RUNTIME_CHECK(result == ISC_R_SUCCESS);
13044	return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
13045				   0, NULL));
13046}
13047
13048/*
13049 * This function should populate an nsec3paramlist_t with the
13050 * nsecparam_t data from a zone.
13051 */
13052static isc_result_t
13053save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
13054	isc_result_t result;
13055	dns_dbnode_t *node = NULL;
13056	dns_rdataset_t rdataset, prdataset;
13057	dns_rdata_t rdata_in, prdata_in, prdata_out;
13058	dns_dbversion_t *version = NULL;
13059	nsec3param_t *nsec3param = NULL;
13060	nsec3param_t *nsec3p = NULL;
13061	nsec3param_t *next;
13062	dns_db_t *db = NULL;
13063	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
13064
13065	REQUIRE(DNS_ZONE_VALID(zone));
13066	REQUIRE(nsec3list != NULL);
13067	REQUIRE(ISC_LIST_EMPTY(*nsec3list));
13068
13069	dns_db_attach(zone->db, &db);
13070	CHECK(dns_db_getoriginnode(db, &node));
13071
13072	dns_rdataset_init(&rdataset);
13073	dns_db_currentversion(db, &version);
13074	result = dns_db_findrdataset(db, node, version,
13075				     dns_rdatatype_nsec3param,
13076				     dns_rdatatype_none, 0, &rdataset, NULL);
13077
13078	if (result != ISC_R_SUCCESS)
13079		goto getprivate;
13080
13081	/*
13082	 * walk nsec3param rdataset making a list of parameters (note that
13083	 * multiple simultaneous nsec3 chains are annoyingly legal -- this
13084	 * is why we use an nsec3list, even tho we will usually only have
13085	 * one)
13086	 */
13087	for (result = dns_rdataset_first(&rdataset);
13088	     result == ISC_R_SUCCESS;
13089	     result = dns_rdataset_next(&rdataset))
13090	{
13091		dns_rdata_init(&rdata_in);
13092		dns_rdataset_current(&rdataset, &rdata_in);
13093		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13094			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13095			      "looping through nsec3param data");
13096		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13097		if (nsec3param == NULL)
13098			CHECK(ISC_R_NOMEMORY);
13099		ISC_LINK_INIT(nsec3param, link);
13100
13101		/*
13102		 * now transfer the data from the rdata to
13103		 * the nsec3param
13104		 */
13105		dns_rdata_init(&prdata_out);
13106		dns_nsec3param_toprivate(&rdata_in, &prdata_out,
13107					 zone->privatetype, nsec3param->data,
13108					 sizeof(nsec3param->data));
13109		nsec3param->length = prdata_out.length;
13110		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13111	}
13112
13113 getprivate:
13114	dns_rdataset_init(&prdataset);
13115	result = dns_db_findrdataset(db, node, version, zone->privatetype,
13116				     dns_rdatatype_none, 0, &prdataset, NULL);
13117	if (result != ISC_R_SUCCESS)
13118		goto done;
13119
13120	/*
13121	 * walk private type records, converting them to nsec3 parameters
13122	 * using dns_nsec3param_fromprivate(), do the right thing based on
13123	 * CREATE and REMOVE flags
13124	 */
13125	for (result = dns_rdataset_first(&prdataset);
13126	     result == ISC_R_SUCCESS;
13127	     result = dns_rdataset_next(&prdataset))
13128	{
13129		dns_rdata_init(&prdata_in);
13130		dns_rdataset_current(&prdataset, &prdata_in);
13131		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13132			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13133			      "looping through nsec3param private data");
13134
13135		if (!dns_nsec3param_fromprivate(&prdata_in, &prdata_out,
13136						buf, sizeof(buf)))
13137			continue;
13138
13139		if ((prdata_out.data[1] & DNS_NSEC3FLAG_REMOVE) !=0) {
13140			prdata_out.data[1] = 0;
13141
13142			for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13143			     nsec3p != NULL;
13144			     nsec3p = next)
13145			{
13146				next = ISC_LIST_NEXT(nsec3p, link);
13147				if (memcmp(prdata_out.data, nsec3p->data,
13148				    sizeof(nsec3p->data)) == 0) {
13149					ISC_LIST_UNLINK(*nsec3list,
13150							nsec3p, link);
13151					isc_mem_put(zone->mctx, nsec3p,
13152						    sizeof(nsec3param_t));
13153				}
13154			}
13155			continue;
13156		}
13157
13158		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13159		if (nsec3param == NULL)
13160			CHECK(ISC_R_NOMEMORY);
13161		ISC_LINK_INIT(nsec3param, link);
13162
13163		dns_rdata_init(&prdata_out);
13164		dns_nsec3param_toprivate(&prdata_in, &prdata_out,
13165			zone->privatetype, nsec3param->data,
13166			sizeof(nsec3param->data));
13167		nsec3param->length = prdata_out.length;
13168		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13169	}
13170
13171 done:
13172	if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
13173		result = ISC_R_SUCCESS;
13174
13175 failure:
13176	if (node != NULL)
13177		dns_db_detachnode(db, &node);
13178	if (version != NULL)
13179		dns_db_closeversion(db, &version, ISC_FALSE);
13180	if (db != NULL)
13181		dns_db_detach(&db);
13182	if (dns_rdataset_isassociated(&rdataset))
13183		dns_rdataset_disassociate(&rdataset);
13184	if (dns_rdataset_isassociated(&prdataset))
13185		dns_rdataset_disassociate(&prdataset);
13186	return (result);
13187}
13188
13189/*
13190 * Walk the list of the nsec3 chains desired for the zone, converting
13191 * parameters to private type records using dns_nsec3param_toprivate(),
13192 * and insert them into the new zone db.
13193 */
13194static isc_result_t
13195restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
13196		   nsec3paramlist_t *nsec3list)
13197{
13198	isc_result_t result;
13199	dns_diff_t diff;
13200	dns_rdata_t rdata;
13201	nsec3param_t *nsec3p = NULL;
13202	nsec3param_t *next;
13203
13204	REQUIRE(DNS_ZONE_VALID(zone));
13205	REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
13206
13207	dns_diff_init(zone->mctx, &diff);
13208
13209	/*
13210	 * Loop through the list of private-type records, set the INITIAL
13211	 * and CREATE flags, and the add the record to the apex of the tree
13212	 * in db.
13213	 */
13214	for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13215	     nsec3p != NULL;
13216	     nsec3p = next)
13217	{
13218		next = ISC_LIST_NEXT(nsec3p, link);
13219		dns_rdata_init(&rdata);
13220		nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
13221		rdata.length = nsec3p->length;
13222		rdata.data = nsec3p->data;
13223		rdata.type = zone->privatetype;
13224		rdata.rdclass = zone->rdclass;
13225		CHECK(update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
13226				    &zone->origin, 0, &rdata));
13227	}
13228
13229	result = ISC_R_SUCCESS;
13230
13231failure:
13232	for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13233	     nsec3p != NULL;
13234	     nsec3p = next)
13235	{
13236		next = ISC_LIST_NEXT(nsec3p, link);
13237		ISC_LIST_UNLINK(*nsec3list, nsec3p, link);
13238		isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
13239	}
13240
13241	dns_diff_clear(&diff);
13242	return (result);
13243}
13244
13245static void
13246receive_secure_db(isc_task_t *task, isc_event_t *event) {
13247	isc_result_t result;
13248	dns_zone_t *zone;
13249	dns_db_t *rawdb, *db = NULL;
13250	dns_dbnode_t *rawnode = NULL, *node = NULL;
13251	dns_fixedname_t fname;
13252	dns_name_t *name;
13253	dns_dbiterator_t *dbiterator = NULL;
13254	dns_rdatasetiter_t *rdsit = NULL;
13255	dns_rdataset_t rdataset;
13256	dns_dbversion_t *version = NULL;
13257	isc_time_t loadtime;
13258	unsigned int oldserial = 0;
13259	isc_boolean_t have_oldserial = ISC_FALSE;
13260	nsec3paramlist_t nsec3list;
13261
13262	UNUSED(task);
13263
13264	ISC_LIST_INIT(nsec3list);
13265
13266	zone = event->ev_arg;
13267	rawdb = ((struct secure_event *)event)->db;
13268	isc_event_free(&event);
13269
13270	dns_fixedname_init(&fname);
13271	name = dns_fixedname_name(&fname);
13272	dns_rdataset_init(&rdataset);
13273
13274	LOCK_ZONE(zone);
13275	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
13276		result = ISC_R_SHUTTINGDOWN;
13277		goto failure;
13278	}
13279
13280	TIME_NOW(&loadtime);
13281	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13282	if (zone->db != NULL) {
13283		result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
13284		if (result == ISC_R_SUCCESS)
13285			have_oldserial = ISC_TRUE;
13286
13287		/*
13288		 * assemble nsec3parameters from the old zone, and set a flag
13289		 * if any are found
13290		 */
13291		result = save_nsec3param(zone, &nsec3list);
13292		if (result != ISC_R_SUCCESS) {
13293			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13294			goto failure;
13295		}
13296	}
13297	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13298
13299	result = dns_db_create(zone->mctx, zone->db_argv[0],
13300			       &zone->origin, dns_dbtype_zone, zone->rdclass,
13301			       zone->db_argc - 1, zone->db_argv + 1, &db);
13302	if (result != ISC_R_SUCCESS)
13303		goto failure;
13304
13305	result = dns_db_newversion(db, &version);
13306	if (result != ISC_R_SUCCESS)
13307		goto failure;
13308
13309	result = dns_db_createiterator(rawdb, 0, &dbiterator);
13310	if (result != ISC_R_SUCCESS)
13311		goto failure;
13312
13313	for (result = dns_dbiterator_first(dbiterator);
13314	     result == ISC_R_SUCCESS;
13315	     result = dns_dbiterator_next(dbiterator)) {
13316		result = dns_dbiterator_current(dbiterator, &rawnode, name);
13317		if (result != ISC_R_SUCCESS)
13318			continue;
13319
13320		result = dns_db_findnode(db, name, ISC_TRUE, &node);
13321		if (result != ISC_R_SUCCESS)
13322			goto failure;
13323
13324		result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
13325		if (result != ISC_R_SUCCESS)
13326			goto failure;
13327
13328		for (result = dns_rdatasetiter_first(rdsit);
13329		     result == ISC_R_SUCCESS;
13330		     result = dns_rdatasetiter_next(rdsit)) {
13331			dns_rdatasetiter_current(rdsit, &rdataset);
13332			if (rdataset.type == dns_rdatatype_nsec ||
13333			    rdataset.type == dns_rdatatype_rrsig ||
13334			    rdataset.type == dns_rdatatype_nsec3 ||
13335			    rdataset.type == dns_rdatatype_dnskey ||
13336			    rdataset.type == dns_rdatatype_nsec3param) {
13337				dns_rdataset_disassociate(&rdataset);
13338				continue;
13339			}
13340			if (rdataset.type == dns_rdatatype_soa &&
13341			    have_oldserial) {
13342				result = checkandaddsoa(db, node, version,
13343							&rdataset, oldserial);
13344			} else
13345				result = dns_db_addrdataset(db, node, version,
13346							    0, &rdataset, 0,
13347							    NULL);
13348			if (result != ISC_R_SUCCESS)
13349				goto failure;
13350
13351			dns_rdataset_disassociate(&rdataset);
13352		}
13353		dns_rdatasetiter_destroy(&rdsit);
13354		dns_db_detachnode(rawdb, &rawnode);
13355		dns_db_detachnode(db, &node);
13356	}
13357
13358	/*
13359	 * Call restore_nsec3param() to create private-type records from
13360	 * the old nsec3 parameters and insert them into db
13361	 */
13362	if (!ISC_LIST_EMPTY(nsec3list))
13363		restore_nsec3param(zone, db, version, &nsec3list);
13364
13365	dns_db_closeversion(db, &version, ISC_TRUE);
13366
13367	/*
13368	 * Lock hierarchy: zmgr, zone, raw.
13369	 */
13370	INSIST(zone != zone->raw);
13371	LOCK_ZONE(zone->raw);
13372	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13373	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
13374	zone_needdump(zone, 0); /* XXXMPA */
13375	UNLOCK_ZONE(zone->raw);
13376
13377 failure:
13378	UNLOCK_ZONE(zone);
13379	if (result != ISC_R_SUCCESS)
13380		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
13381			     dns_result_totext(result));
13382
13383	if (dns_rdataset_isassociated(&rdataset))
13384		dns_rdataset_disassociate(&rdataset);
13385	if (db != NULL) {
13386		if (node != NULL)
13387			dns_db_detachnode(db, &node);
13388		dns_db_detach(&db);
13389	}
13390	if (rawnode != NULL)
13391		dns_db_detachnode(rawdb, &rawnode);
13392	dns_db_detach(&rawdb);
13393	if (dbiterator != NULL)
13394		dns_dbiterator_destroy(&dbiterator);
13395	dns_zone_idetach(&zone);
13396}
13397
13398static isc_result_t
13399zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
13400	isc_event_t *e;
13401	dns_db_t *dummy = NULL;
13402	dns_zone_t *secure = NULL;
13403
13404	e = isc_event_allocate(zone->secure->mctx, zone,
13405			       DNS_EVENT_ZONESECUREDB,
13406			       receive_secure_db, zone->secure,
13407			       sizeof(struct secure_event));
13408	if (e == NULL)
13409		return (ISC_R_NOMEMORY);
13410	dns_db_attach(db, &dummy);
13411	((struct secure_event *)e)->db = dummy;
13412	INSIST(LOCKED_ZONE(zone->secure));
13413	zone_iattach(zone->secure, &secure);
13414	isc_task_send(zone->secure->task, &e);
13415	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
13416	return (ISC_R_SUCCESS);
13417}
13418
13419isc_result_t
13420dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13421	isc_result_t result;
13422	dns_zone_t *secure = NULL;
13423
13424	REQUIRE(DNS_ZONE_VALID(zone));
13425 again:
13426	LOCK_ZONE(zone);
13427	if (inline_raw(zone)) {
13428		secure = zone->secure;
13429		INSIST(secure != zone);
13430		TRYLOCK_ZONE(result, secure);
13431		if (result != ISC_R_SUCCESS) {
13432			UNLOCK_ZONE(zone);
13433			secure = NULL;
13434#if ISC_PLATFORM_USETHREADS
13435			isc_thread_yield();
13436#endif
13437			goto again;
13438		}
13439	}
13440	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13441	result = zone_replacedb(zone, db, dump);
13442	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13443	if (secure != NULL)
13444		UNLOCK_ZONE(secure);
13445	UNLOCK_ZONE(zone);
13446	return (result);
13447}
13448
13449static isc_result_t
13450zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13451	dns_dbversion_t *ver;
13452	isc_result_t result;
13453	unsigned int soacount = 0;
13454	unsigned int nscount = 0;
13455
13456	/*
13457	 * 'zone' and 'zonedb' locked by caller.
13458	 */
13459	REQUIRE(DNS_ZONE_VALID(zone));
13460	REQUIRE(LOCKED_ZONE(zone));
13461	if (inline_raw(zone))
13462		REQUIRE(LOCKED_ZONE(zone->secure));
13463
13464	result = zone_get_from_db(zone, db, &nscount, &soacount,
13465				  NULL, NULL, NULL, NULL, NULL, NULL);
13466	if (result == ISC_R_SUCCESS) {
13467		if (soacount != 1) {
13468			dns_zone_log(zone, ISC_LOG_ERROR,
13469				     "has %d SOA records", soacount);
13470			result = DNS_R_BADZONE;
13471		}
13472		if (nscount == 0 && zone->type != dns_zone_key) {
13473			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
13474			result = DNS_R_BADZONE;
13475		}
13476		if (result != ISC_R_SUCCESS)
13477			return (result);
13478	} else {
13479		dns_zone_log(zone, ISC_LOG_ERROR,
13480			    "retrieving SOA and NS records failed: %s",
13481			    dns_result_totext(result));
13482		return (result);
13483	}
13484
13485	result = check_nsec3param(zone, db);
13486	if (result != ISC_R_SUCCESS)
13487		return (result);
13488
13489	ver = NULL;
13490	dns_db_currentversion(db, &ver);
13491
13492	/*
13493	 * The initial version of a slave zone is always dumped;
13494	 * subsequent versions may be journaled instead if this
13495	 * is enabled in the configuration.
13496	 */
13497	if (zone->db != NULL && zone->journal != NULL &&
13498	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
13499	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
13500	{
13501		isc_uint32_t serial, oldserial;
13502		unsigned int soacount;
13503
13504		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
13505
13506		result = dns_db_getsoaserial(db, ver, &serial);
13507		if (result != ISC_R_SUCCESS) {
13508			dns_zone_log(zone, ISC_LOG_ERROR,
13509				     "ixfr-from-differences: unable to get "
13510				     "new serial");
13511			goto fail;
13512		}
13513
13514		/*
13515		 * This is checked in zone_postload() for master zones.
13516		 */
13517		result = zone_get_from_db(zone, zone->db, NULL, &soacount,
13518					  &oldserial, NULL, NULL, NULL, NULL,
13519					  NULL);
13520		RUNTIME_CHECK(result == ISC_R_SUCCESS);
13521		RUNTIME_CHECK(soacount > 0U);
13522		if ((zone->type == dns_zone_slave ||
13523		     (zone->type == dns_zone_redirect &&
13524		      zone->masters != NULL))
13525		    && !isc_serial_gt(serial, oldserial)) {
13526			isc_uint32_t serialmin, serialmax;
13527			serialmin = (oldserial + 1) & 0xffffffffU;
13528			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
13529			dns_zone_log(zone, ISC_LOG_ERROR,
13530				     "ixfr-from-differences: failed: "
13531				     "new serial (%u) out of range [%u - %u]",
13532				     serial, serialmin, serialmax);
13533			result = ISC_R_RANGE;
13534			goto fail;
13535		}
13536
13537		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
13538				     zone->journal);
13539		if (result != ISC_R_SUCCESS)
13540			goto fail;
13541		if (dump)
13542			zone_needdump(zone, DNS_DUMP_DELAY);
13543		else if (zone->journalsize != -1) {
13544			result = dns_journal_compact(zone->mctx, zone->journal,
13545						     serial, zone->journalsize);
13546			switch (result) {
13547			case ISC_R_SUCCESS:
13548			case ISC_R_NOSPACE:
13549			case ISC_R_NOTFOUND:
13550				dns_zone_log(zone, ISC_LOG_DEBUG(3),
13551					     "dns_journal_compact: %s",
13552					     dns_result_totext(result));
13553				break;
13554			default:
13555				dns_zone_log(zone, ISC_LOG_ERROR,
13556					     "dns_journal_compact failed: %s",
13557					     dns_result_totext(result));
13558				break;
13559			}
13560		}
13561		if (zone->type == dns_zone_master && inline_raw(zone))
13562			zone_send_secureserial(zone, serial);
13563	} else {
13564		if (dump && zone->masterfile != NULL) {
13565			/*
13566			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
13567			 * to keep the old masterfile.
13568			 */
13569			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
13570			    remove(zone->masterfile) < 0 && errno != ENOENT) {
13571				char strbuf[ISC_STRERRORSIZE];
13572				isc__strerror(errno, strbuf, sizeof(strbuf));
13573				isc_log_write(dns_lctx,
13574					      DNS_LOGCATEGORY_GENERAL,
13575					      DNS_LOGMODULE_ZONE,
13576					      ISC_LOG_WARNING,
13577					      "unable to remove masterfile "
13578					      "'%s': '%s'",
13579					      zone->masterfile, strbuf);
13580			}
13581			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
13582				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
13583			else
13584				zone_needdump(zone, 0);
13585		}
13586		if (dump && zone->journal != NULL) {
13587			/*
13588			 * The in-memory database just changed, and
13589			 * because 'dump' is set, it didn't change by
13590			 * being loaded from disk.  Also, we have not
13591			 * journaled diffs for this change.
13592			 * Therefore, the on-disk journal is missing
13593			 * the deltas for this change.	Since it can
13594			 * no longer be used to bring the zone
13595			 * up-to-date, it is useless and should be
13596			 * removed.
13597			 */
13598			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13599				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13600				      "removing journal file");
13601			if (remove(zone->journal) < 0 && errno != ENOENT) {
13602				char strbuf[ISC_STRERRORSIZE];
13603				isc__strerror(errno, strbuf, sizeof(strbuf));
13604				isc_log_write(dns_lctx,
13605					      DNS_LOGCATEGORY_GENERAL,
13606					      DNS_LOGMODULE_ZONE,
13607					      ISC_LOG_WARNING,
13608					      "unable to remove journal "
13609					      "'%s': '%s'",
13610					      zone->journal, strbuf);
13611			}
13612		}
13613
13614		if (inline_raw(zone))
13615			zone_send_securedb(zone, db);
13616	}
13617
13618	dns_db_closeversion(db, &ver, ISC_FALSE);
13619
13620	dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
13621
13622	if (zone->db != NULL)
13623		zone_detachdb(zone);
13624	zone_attachdb(zone, db);
13625	dns_db_settask(zone->db, zone->task);
13626	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
13627	return (ISC_R_SUCCESS);
13628
13629 fail:
13630	dns_db_closeversion(db, &ver, ISC_FALSE);
13631	return (result);
13632}
13633
13634/* The caller must hold the dblock as a writer. */
13635static inline void
13636zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
13637	REQUIRE(zone->db == NULL && db != NULL);
13638
13639	dns_db_attach(db, &zone->db);
13640	if (zone->acache != NULL) {
13641		isc_result_t result;
13642		result = dns_acache_setdb(zone->acache, db);
13643		if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
13644			UNEXPECTED_ERROR(__FILE__, __LINE__,
13645					 "dns_acache_setdb() failed: %s",
13646					 isc_result_totext(result));
13647		}
13648	}
13649}
13650
13651/* The caller must hold the dblock as a writer. */
13652static inline void
13653zone_detachdb(dns_zone_t *zone) {
13654	REQUIRE(zone->db != NULL);
13655
13656	if (zone->acache != NULL)
13657		(void)dns_acache_putdb(zone->acache, zone->db);
13658	dns_db_detach(&zone->db);
13659}
13660
13661static void
13662zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
13663	isc_time_t now;
13664	isc_boolean_t again = ISC_FALSE;
13665	unsigned int soacount;
13666	unsigned int nscount;
13667	isc_uint32_t serial, refresh, retry, expire, minimum;
13668	isc_result_t xfrresult = result;
13669	isc_boolean_t free_needed;
13670	dns_zone_t *secure = NULL;
13671
13672	REQUIRE(DNS_ZONE_VALID(zone));
13673
13674	dns_zone_log(zone, ISC_LOG_DEBUG(1),
13675		     "zone transfer finished: %s", dns_result_totext(result));
13676
13677	/*
13678	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
13679	 * could result in a deadlock due to a LOR so we will spin if we
13680	 * can't obtain the both locks.
13681	 */
13682 again:
13683	LOCK_ZONE(zone);
13684	if (inline_raw(zone)) {
13685		secure = zone->secure;
13686		INSIST(secure != zone);
13687		TRYLOCK_ZONE(result, secure);
13688		if (result != ISC_R_SUCCESS) {
13689			UNLOCK_ZONE(zone);
13690			secure = NULL;
13691#if ISC_PLATFORM_USETHREADS
13692			isc_thread_yield();
13693#endif
13694			goto again;
13695		}
13696	}
13697
13698	INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
13699	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13700	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
13701
13702	TIME_NOW(&now);
13703	switch (result) {
13704	case ISC_R_SUCCESS:
13705		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13706		/*FALLTHROUGH*/
13707	case DNS_R_UPTODATE:
13708		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13709		/*
13710		 * Has the zone expired underneath us?
13711		 */
13712		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13713		if (zone->db == NULL) {
13714			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13715			goto same_master;
13716		}
13717
13718		/*
13719		 * Update the zone structure's data from the actual
13720		 * SOA received.
13721		 */
13722		nscount = 0;
13723		soacount = 0;
13724		INSIST(zone->db != NULL);
13725		result = zone_get_from_db(zone, zone->db, &nscount,
13726					  &soacount, &serial, &refresh,
13727					  &retry, &expire, &minimum, NULL);
13728		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13729		if (result == ISC_R_SUCCESS) {
13730			if (soacount != 1)
13731				dns_zone_log(zone, ISC_LOG_ERROR,
13732					     "transferred zone "
13733					     "has %d SOA record%s", soacount,
13734					     (soacount != 0) ? "s" : "");
13735			if (nscount == 0) {
13736				dns_zone_log(zone, ISC_LOG_ERROR,
13737					     "transferred zone "
13738					     "has no NS records");
13739				if (DNS_ZONE_FLAG(zone,
13740						  DNS_ZONEFLG_HAVETIMERS)) {
13741					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
13742					zone->retry = DNS_ZONE_DEFAULTRETRY;
13743				}
13744				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13745				zone_unload(zone);
13746				goto next_master;
13747			}
13748			zone->refresh = RANGE(refresh, zone->minrefresh,
13749					      zone->maxrefresh);
13750			zone->retry = RANGE(retry, zone->minretry,
13751					    zone->maxretry);
13752			zone->expire = RANGE(expire,
13753					     zone->refresh + zone->retry,
13754					     DNS_MAX_EXPIRE);
13755			zone->minimum = minimum;
13756			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13757		}
13758
13759		/*
13760		 * Set our next update/expire times.
13761		 */
13762		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
13763			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13764			zone->refreshtime = now;
13765			DNS_ZONE_TIME_ADD(&now, zone->expire,
13766					  &zone->expiretime);
13767		} else {
13768			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
13769					    &zone->refreshtime);
13770			DNS_ZONE_TIME_ADD(&now, zone->expire,
13771					  &zone->expiretime);
13772		}
13773		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
13774			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
13775			if (zone->tsigkey != NULL) {
13776				char namebuf[DNS_NAME_FORMATSIZE];
13777				dns_name_format(&zone->tsigkey->name, namebuf,
13778						sizeof(namebuf));
13779				snprintf(buf, sizeof(buf), ": TSIG '%s'",
13780					 namebuf);
13781			} else
13782				buf[0] = '\0';
13783			dns_zone_log(zone, ISC_LOG_INFO,
13784				     "transferred serial %u%s",
13785				     serial, buf);
13786			if (inline_raw(zone))
13787				zone_send_secureserial(zone, serial);
13788		}
13789
13790		/*
13791		 * This is not necessary if we just performed a AXFR
13792		 * however it is necessary for an IXFR / UPTODATE and
13793		 * won't hurt with an AXFR.
13794		 */
13795		if (zone->masterfile != NULL || zone->journal != NULL) {
13796			unsigned int delay = DNS_DUMP_DELAY;
13797
13798			result = ISC_R_FAILURE;
13799			if (zone->journal != NULL)
13800				result = isc_file_settime(zone->journal, &now);
13801			if (result != ISC_R_SUCCESS &&
13802			    zone->masterfile != NULL)
13803				result = isc_file_settime(zone->masterfile,
13804							  &now);
13805
13806			if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
13807			    result == ISC_R_FILENOTFOUND)
13808				delay = 0;
13809
13810			if ((result == ISC_R_SUCCESS ||
13811			    result == ISC_R_FILENOTFOUND) &&
13812			    zone->masterfile != NULL)
13813				zone_needdump(zone, delay);
13814			else if (result != ISC_R_SUCCESS)
13815				dns_zone_log(zone, ISC_LOG_ERROR,
13816					     "transfer: could not set file "
13817					     "modification time of '%s': %s",
13818					     zone->masterfile,
13819					     dns_result_totext(result));
13820		}
13821		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
13822		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
13823		break;
13824
13825	case DNS_R_BADIXFR:
13826		/* Force retry with AXFR. */
13827		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
13828		goto same_master;
13829
13830	default:
13831	next_master:
13832		/*
13833		 * Skip to next failed / untried master.
13834		 */
13835		do {
13836			zone->curmaster++;
13837		} while (zone->curmaster < zone->masterscnt &&
13838			 zone->mastersok[zone->curmaster]);
13839		/* FALLTHROUGH */
13840	same_master:
13841		if (zone->curmaster >= zone->masterscnt) {
13842			zone->curmaster = 0;
13843			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13844			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13845				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
13846				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13847				while (zone->curmaster < zone->masterscnt &&
13848				       zone->mastersok[zone->curmaster])
13849					zone->curmaster++;
13850				again = ISC_TRUE;
13851			} else
13852				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13853		} else {
13854			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
13855			again = ISC_TRUE;
13856		}
13857		inc_stats(zone, dns_zonestatscounter_xfrfail);
13858		break;
13859	}
13860	zone_settimer(zone, &now);
13861
13862	/*
13863	 * If creating the transfer object failed, zone->xfr is NULL.
13864	 * Otherwise, we are called as the done callback of a zone
13865	 * transfer object that just entered its shutting-down
13866	 * state.  Since we are no longer responsible for shutting
13867	 * it down, we can detach our reference.
13868	 */
13869	if (zone->xfr != NULL)
13870		dns_xfrin_detach(&zone->xfr);
13871
13872	if (zone->tsigkey != NULL)
13873		dns_tsigkey_detach(&zone->tsigkey);
13874
13875	/*
13876	 * Handle any deferred journal compaction.
13877	 */
13878	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
13879		result = dns_journal_compact(zone->mctx, zone->journal,
13880					     zone->compact_serial,
13881					     zone->journalsize);
13882		switch (result) {
13883		case ISC_R_SUCCESS:
13884		case ISC_R_NOSPACE:
13885		case ISC_R_NOTFOUND:
13886			dns_zone_log(zone, ISC_LOG_DEBUG(3),
13887				     "dns_journal_compact: %s",
13888				     dns_result_totext(result));
13889			break;
13890		default:
13891			dns_zone_log(zone, ISC_LOG_ERROR,
13892				     "dns_journal_compact failed: %s",
13893				     dns_result_totext(result));
13894			break;
13895		}
13896		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
13897	}
13898
13899	if (secure != NULL)
13900		UNLOCK_ZONE(secure);
13901	/*
13902	 * This transfer finishing freed up a transfer quota slot.
13903	 * Let any other zones waiting for quota have it.
13904	 */
13905	if (zone->zmgr != NULL &&
13906	    zone->statelist == &zone->zmgr->xfrin_in_progress) {
13907		UNLOCK_ZONE(zone);
13908		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13909		ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
13910		zone->statelist = NULL;
13911		zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
13912		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13913		LOCK_ZONE(zone);
13914	}
13915
13916	/*
13917	 * Retry with a different server if necessary.
13918	 */
13919	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
13920		queue_soa_query(zone);
13921
13922	INSIST(zone->irefs > 0);
13923	zone->irefs--;
13924	free_needed = exit_check(zone);
13925	UNLOCK_ZONE(zone);
13926	if (free_needed)
13927		zone_free(zone);
13928}
13929
13930static void
13931zone_loaddone(void *arg, isc_result_t result) {
13932	static char me[] = "zone_loaddone";
13933	dns_load_t *load = arg;
13934	dns_zone_t *zone;
13935	isc_result_t tresult;
13936	dns_zone_t *secure = NULL;
13937
13938	REQUIRE(DNS_LOAD_VALID(load));
13939	zone = load->zone;
13940
13941	ENTER;
13942
13943	tresult = dns_db_endload(load->db, &load->callbacks.add_private);
13944	if (tresult != ISC_R_SUCCESS &&
13945	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
13946		result = tresult;
13947
13948	/*
13949	 * Lock hierarchy: zmgr, zone, raw.
13950	 */
13951 again:
13952	LOCK_ZONE(zone);
13953	if (inline_secure(zone))
13954		LOCK_ZONE(zone->raw);
13955	else if (inline_raw(zone)) {
13956		secure = zone->secure;
13957		TRYLOCK_ZONE(result, secure);
13958		if (result != ISC_R_SUCCESS) {
13959			UNLOCK_ZONE(zone);
13960			secure = NULL;
13961#if ISC_PLATFORM_USETHREADS
13962			isc_thread_yield();
13963#endif
13964			goto again;
13965		}
13966	}
13967	(void)zone_postload(zone, load->db, load->loadtime, result);
13968	zonemgr_putio(&zone->readio);
13969	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
13970	zone_idetach(&load->callbacks.zone);
13971	/*
13972	 * Leave the zone frozen if the reload fails.
13973	 */
13974	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
13975	     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
13976		zone->update_disabled = ISC_FALSE;
13977	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
13978	if (inline_secure(zone))
13979		UNLOCK_ZONE(zone->raw);
13980	else if (secure != NULL)
13981		UNLOCK_ZONE(secure);
13982	UNLOCK_ZONE(zone);
13983
13984	load->magic = 0;
13985	dns_db_detach(&load->db);
13986	if (load->zone->lctx != NULL)
13987		dns_loadctx_detach(&load->zone->lctx);
13988	dns_zone_idetach(&load->zone);
13989	isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
13990}
13991
13992void
13993dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
13994	REQUIRE(DNS_ZONE_VALID(zone));
13995	REQUIRE(table != NULL);
13996	REQUIRE(*table == NULL);
13997
13998	LOCK_ZONE(zone);
13999	if (zone->ssutable != NULL)
14000		dns_ssutable_attach(zone->ssutable, table);
14001	UNLOCK_ZONE(zone);
14002}
14003
14004void
14005dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
14006	REQUIRE(DNS_ZONE_VALID(zone));
14007
14008	LOCK_ZONE(zone);
14009	if (zone->ssutable != NULL)
14010		dns_ssutable_detach(&zone->ssutable);
14011	if (table != NULL)
14012		dns_ssutable_attach(table, &zone->ssutable);
14013	UNLOCK_ZONE(zone);
14014}
14015
14016void
14017dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
14018	REQUIRE(DNS_ZONE_VALID(zone));
14019
14020	zone->sigvalidityinterval = interval;
14021}
14022
14023isc_uint32_t
14024dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
14025	REQUIRE(DNS_ZONE_VALID(zone));
14026
14027	return (zone->sigvalidityinterval);
14028}
14029
14030void
14031dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
14032	isc_time_t now;
14033
14034	REQUIRE(DNS_ZONE_VALID(zone));
14035
14036	LOCK_ZONE(zone);
14037	zone->sigresigninginterval = interval;
14038	set_resigntime(zone);
14039	if (zone->task != NULL) {
14040		TIME_NOW(&now);
14041		zone_settimer(zone, &now);
14042	}
14043	UNLOCK_ZONE(zone);
14044}
14045
14046isc_uint32_t
14047dns_zone_getsigresigninginterval(dns_zone_t *zone) {
14048	REQUIRE(DNS_ZONE_VALID(zone));
14049
14050	return (zone->sigresigninginterval);
14051}
14052
14053static void
14054queue_xfrin(dns_zone_t *zone) {
14055	const char me[] = "queue_xfrin";
14056	isc_result_t result;
14057	dns_zonemgr_t *zmgr = zone->zmgr;
14058
14059	ENTER;
14060
14061	INSIST(zone->statelist == NULL);
14062
14063	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14064	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
14065	LOCK_ZONE(zone);
14066	zone->irefs++;
14067	UNLOCK_ZONE(zone);
14068	zone->statelist = &zmgr->waiting_for_xfrin;
14069	result = zmgr_start_xfrin_ifquota(zmgr, zone);
14070	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14071
14072	if (result == ISC_R_QUOTA) {
14073		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14074			      "zone transfer deferred due to quota");
14075	} else if (result != ISC_R_SUCCESS) {
14076		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
14077			      "starting zone transfer: %s",
14078			      isc_result_totext(result));
14079	}
14080}
14081
14082/*
14083 * This event callback is called when a zone has received
14084 * any necessary zone transfer quota.  This is the time
14085 * to go ahead and start the transfer.
14086 */
14087static void
14088got_transfer_quota(isc_task_t *task, isc_event_t *event) {
14089	isc_result_t result = ISC_R_SUCCESS;
14090	dns_peer_t *peer = NULL;
14091	char master[ISC_SOCKADDR_FORMATSIZE];
14092	char source[ISC_SOCKADDR_FORMATSIZE];
14093	dns_rdatatype_t xfrtype;
14094	dns_zone_t *zone = event->ev_arg;
14095	isc_netaddr_t masterip;
14096	isc_sockaddr_t sourceaddr;
14097	isc_sockaddr_t masteraddr;
14098	isc_time_t now;
14099	const char *soa_before = "";
14100	isc_boolean_t loaded;
14101
14102	UNUSED(task);
14103
14104	INSIST(task == zone->task);
14105
14106	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14107		result = ISC_R_CANCELED;
14108		goto cleanup;
14109	}
14110
14111	TIME_NOW(&now);
14112
14113	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
14114	if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
14115				    &zone->sourceaddr, &now))
14116	{
14117		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14118		dns_zone_log(zone, ISC_LOG_INFO,
14119			     "got_transfer_quota: skipping zone transfer as "
14120			     "master %s (source %s) is unreachable (cached)",
14121			     master, source);
14122		result = ISC_R_CANCELED;
14123		goto cleanup;
14124	}
14125
14126	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14127	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
14128
14129	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14130		soa_before = "SOA before ";
14131	/*
14132	 * Decide whether we should request IXFR or AXFR.
14133	 */
14134	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14135	loaded = ISC_TF(zone->db != NULL);
14136	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14137
14138	if (!loaded) {
14139		dns_zone_log(zone, ISC_LOG_DEBUG(1),
14140			     "no database exists yet, requesting AXFR of "
14141			     "initial version from %s", master);
14142		xfrtype = dns_rdatatype_axfr;
14143	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
14144		dns_zone_log(zone, ISC_LOG_DEBUG(1),
14145			     "forced reload, requesting AXFR of "
14146			     "initial version from %s", master);
14147		xfrtype = dns_rdatatype_axfr;
14148	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
14149		dns_zone_log(zone, ISC_LOG_DEBUG(1),
14150			     "retrying with AXFR from %s due to "
14151			     "previous IXFR failure", master);
14152		xfrtype = dns_rdatatype_axfr;
14153		LOCK_ZONE(zone);
14154		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
14155		UNLOCK_ZONE(zone);
14156	} else {
14157		isc_boolean_t use_ixfr = ISC_TRUE;
14158		if (peer != NULL)
14159			result = dns_peer_getrequestixfr(peer, &use_ixfr);
14160		if (peer == NULL || result != ISC_R_SUCCESS)
14161			use_ixfr = zone->requestixfr;
14162		if (use_ixfr == ISC_FALSE) {
14163			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14164				     "IXFR disabled, requesting %sAXFR from %s",
14165				     soa_before, master);
14166			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14167				xfrtype = dns_rdatatype_soa;
14168			else
14169				xfrtype = dns_rdatatype_axfr;
14170		} else {
14171			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14172				     "requesting IXFR from %s", master);
14173			xfrtype = dns_rdatatype_ixfr;
14174		}
14175	}
14176
14177	/*
14178	 * Determine if we should attempt to sign the request with TSIG.
14179	 */
14180	result = ISC_R_NOTFOUND;
14181	/*
14182	 * First, look for a tsig key in the master statement, then
14183	 * try for a server key.
14184	 */
14185	if ((zone->masterkeynames != NULL) &&
14186	    (zone->masterkeynames[zone->curmaster] != NULL)) {
14187		dns_view_t *view = dns_zone_getview(zone);
14188		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14189		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
14190	}
14191	if (zone->tsigkey == NULL)
14192		result = dns_view_getpeertsig(zone->view, &masterip,
14193					      &zone->tsigkey);
14194
14195	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14196		dns_zone_log(zone, ISC_LOG_ERROR,
14197			     "could not get TSIG key for zone transfer: %s",
14198			     isc_result_totext(result));
14199	}
14200
14201	LOCK_ZONE(zone);
14202	masteraddr = zone->masteraddr;
14203	sourceaddr = zone->sourceaddr;
14204	UNLOCK_ZONE(zone);
14205	INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
14206	result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
14207				   zone->tsigkey, zone->mctx,
14208				   zone->zmgr->timermgr, zone->zmgr->socketmgr,
14209				   zone->task, zone_xfrdone, &zone->xfr);
14210	if (result == ISC_R_SUCCESS) {
14211		LOCK_ZONE(zone);
14212		if (xfrtype == dns_rdatatype_axfr) {
14213			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14214				inc_stats(zone, dns_zonestatscounter_axfrreqv4);
14215			else
14216				inc_stats(zone, dns_zonestatscounter_axfrreqv6);
14217		} else if (xfrtype == dns_rdatatype_ixfr) {
14218			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14219				inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
14220			else
14221				inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
14222		}
14223		UNLOCK_ZONE(zone);
14224	}
14225 cleanup:
14226	/*
14227	 * Any failure in this function is handled like a failed
14228	 * zone transfer.  This ensures that we get removed from
14229	 * zmgr->xfrin_in_progress.
14230	 */
14231	if (result != ISC_R_SUCCESS)
14232		zone_xfrdone(zone, result);
14233
14234	isc_event_free(&event);
14235}
14236
14237/*
14238 * Update forwarding support.
14239 */
14240
14241static void
14242forward_destroy(dns_forward_t *forward) {
14243
14244	forward->magic = 0;
14245	if (forward->request != NULL)
14246		dns_request_destroy(&forward->request);
14247	if (forward->msgbuf != NULL)
14248		isc_buffer_free(&forward->msgbuf);
14249	if (forward->zone != NULL) {
14250		LOCK(&forward->zone->lock);
14251		if (ISC_LINK_LINKED(forward, link))
14252			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
14253		UNLOCK(&forward->zone->lock);
14254		dns_zone_idetach(&forward->zone);
14255	}
14256	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
14257}
14258
14259static isc_result_t
14260sendtomaster(dns_forward_t *forward) {
14261	isc_result_t result;
14262	isc_sockaddr_t src;
14263
14264	LOCK_ZONE(forward->zone);
14265
14266	if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
14267		UNLOCK_ZONE(forward->zone);
14268		return (ISC_R_CANCELED);
14269	}
14270
14271	if (forward->which >= forward->zone->masterscnt) {
14272		UNLOCK_ZONE(forward->zone);
14273		return (ISC_R_NOMORE);
14274	}
14275
14276	forward->addr = forward->zone->masters[forward->which];
14277	/*
14278	 * Always use TCP regardless of whether the original update
14279	 * used TCP.
14280	 * XXX The timeout may but a bit small if we are far down a
14281	 * transfer graph and the master has to try several masters.
14282	 */
14283	switch (isc_sockaddr_pf(&forward->addr)) {
14284	case PF_INET:
14285		src = forward->zone->xfrsource4;
14286		break;
14287	case PF_INET6:
14288		src = forward->zone->xfrsource6;
14289		break;
14290	default:
14291		result = ISC_R_NOTIMPLEMENTED;
14292		goto unlock;
14293	}
14294	result = dns_request_createraw(forward->zone->view->requestmgr,
14295				       forward->msgbuf,
14296				       &src, &forward->addr,
14297				       DNS_REQUESTOPT_TCP, 15 /* XXX */,
14298				       forward->zone->task,
14299				       forward_callback, forward,
14300				       &forward->request);
14301	if (result == ISC_R_SUCCESS) {
14302		if (!ISC_LINK_LINKED(forward, link))
14303			ISC_LIST_APPEND(forward->zone->forwards, forward, link);
14304	}
14305
14306 unlock:
14307	UNLOCK_ZONE(forward->zone);
14308	return (result);
14309}
14310
14311static void
14312forward_callback(isc_task_t *task, isc_event_t *event) {
14313	const char me[] = "forward_callback";
14314	dns_requestevent_t *revent = (dns_requestevent_t *)event;
14315	dns_message_t *msg = NULL;
14316	char master[ISC_SOCKADDR_FORMATSIZE];
14317	isc_result_t result;
14318	dns_forward_t *forward;
14319	dns_zone_t *zone;
14320
14321	UNUSED(task);
14322
14323	forward = revent->ev_arg;
14324	INSIST(DNS_FORWARD_VALID(forward));
14325	zone = forward->zone;
14326	INSIST(DNS_ZONE_VALID(zone));
14327
14328	ENTER;
14329
14330	isc_sockaddr_format(&forward->addr, master, sizeof(master));
14331
14332	if (revent->result != ISC_R_SUCCESS) {
14333		dns_zone_log(zone, ISC_LOG_INFO,
14334			     "could not forward dynamic update to %s: %s",
14335			     master, dns_result_totext(revent->result));
14336		goto next_master;
14337	}
14338
14339	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
14340	if (result != ISC_R_SUCCESS)
14341		goto next_master;
14342
14343	result = dns_request_getresponse(revent->request, msg,
14344					 DNS_MESSAGEPARSE_PRESERVEORDER |
14345					 DNS_MESSAGEPARSE_CLONEBUFFER);
14346	if (result != ISC_R_SUCCESS)
14347		goto next_master;
14348
14349	switch (msg->rcode) {
14350	/*
14351	 * Pass these rcodes back to client.
14352	 */
14353	case dns_rcode_noerror:
14354	case dns_rcode_yxdomain:
14355	case dns_rcode_yxrrset:
14356	case dns_rcode_nxrrset:
14357	case dns_rcode_refused:
14358	case dns_rcode_nxdomain: {
14359		char rcode[128];
14360		isc_buffer_t rb;
14361
14362		isc_buffer_init(&rb, rcode, sizeof(rcode));
14363		(void)dns_rcode_totext(msg->rcode, &rb);
14364		dns_zone_log(zone, ISC_LOG_INFO,
14365			     "forwarded dynamic update: "
14366			     "master %s returned: %.*s",
14367			     master, (int)rb.used, rcode);
14368		break;
14369	}
14370
14371	/* These should not occur if the masters/zone are valid. */
14372	case dns_rcode_notzone:
14373	case dns_rcode_notauth: {
14374		char rcode[128];
14375		isc_buffer_t rb;
14376
14377		isc_buffer_init(&rb, rcode, sizeof(rcode));
14378		(void)dns_rcode_totext(msg->rcode, &rb);
14379		dns_zone_log(zone, ISC_LOG_WARNING,
14380			     "forwarding dynamic update: "
14381			     "unexpected response: master %s returned: %.*s",
14382			     master, (int)rb.used, rcode);
14383		goto next_master;
14384	}
14385
14386	/* Try another server for these rcodes. */
14387	case dns_rcode_formerr:
14388	case dns_rcode_servfail:
14389	case dns_rcode_notimp:
14390	case dns_rcode_badvers:
14391	default:
14392		goto next_master;
14393	}
14394
14395	/* call callback */
14396	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
14397	msg = NULL;
14398	dns_request_destroy(&forward->request);
14399	forward_destroy(forward);
14400	isc_event_free(&event);
14401	return;
14402
14403 next_master:
14404	if (msg != NULL)
14405		dns_message_destroy(&msg);
14406	isc_event_free(&event);
14407	forward->which++;
14408	dns_request_destroy(&forward->request);
14409	result = sendtomaster(forward);
14410	if (result != ISC_R_SUCCESS) {
14411		/* call callback */
14412		dns_zone_log(zone, ISC_LOG_DEBUG(3),
14413			     "exhausted dynamic update forwarder list");
14414		(forward->callback)(forward->callback_arg, result, NULL);
14415		forward_destroy(forward);
14416	}
14417}
14418
14419isc_result_t
14420dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
14421		       dns_updatecallback_t callback, void *callback_arg)
14422{
14423	dns_forward_t *forward;
14424	isc_result_t result;
14425	isc_region_t *mr;
14426
14427	REQUIRE(DNS_ZONE_VALID(zone));
14428	REQUIRE(msg != NULL);
14429	REQUIRE(callback != NULL);
14430
14431	forward = isc_mem_get(zone->mctx, sizeof(*forward));
14432	if (forward == NULL)
14433		return (ISC_R_NOMEMORY);
14434
14435	forward->request = NULL;
14436	forward->zone = NULL;
14437	forward->msgbuf = NULL;
14438	forward->which = 0;
14439	forward->mctx = 0;
14440	forward->callback = callback;
14441	forward->callback_arg = callback_arg;
14442	ISC_LINK_INIT(forward, link);
14443	forward->magic = FORWARD_MAGIC;
14444
14445	mr = dns_message_getrawmessage(msg);
14446	if (mr == NULL) {
14447		result = ISC_R_UNEXPECTEDEND;
14448		goto cleanup;
14449	}
14450
14451	result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
14452	if (result != ISC_R_SUCCESS)
14453		goto cleanup;
14454	result = isc_buffer_copyregion(forward->msgbuf, mr);
14455	if (result != ISC_R_SUCCESS)
14456		goto cleanup;
14457
14458	isc_mem_attach(zone->mctx, &forward->mctx);
14459	dns_zone_iattach(zone, &forward->zone);
14460	result = sendtomaster(forward);
14461
14462 cleanup:
14463	if (result != ISC_R_SUCCESS) {
14464		forward_destroy(forward);
14465	}
14466	return (result);
14467}
14468
14469isc_result_t
14470dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
14471	REQUIRE(DNS_ZONE_VALID(zone));
14472	REQUIRE(next != NULL && *next == NULL);
14473
14474	*next = ISC_LIST_NEXT(zone, link);
14475	if (*next == NULL)
14476		return (ISC_R_NOMORE);
14477	else
14478		return (ISC_R_SUCCESS);
14479}
14480
14481isc_result_t
14482dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
14483	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14484	REQUIRE(first != NULL && *first == NULL);
14485
14486	*first = ISC_LIST_HEAD(zmgr->zones);
14487	if (*first == NULL)
14488		return (ISC_R_NOMORE);
14489	else
14490		return (ISC_R_SUCCESS);
14491}
14492
14493/***
14494 ***	Zone manager.
14495 ***/
14496
14497isc_result_t
14498dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
14499		   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
14500		   dns_zonemgr_t **zmgrp)
14501{
14502	dns_zonemgr_t *zmgr;
14503	isc_result_t result;
14504	isc_interval_t interval;
14505
14506	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
14507	if (zmgr == NULL)
14508		return (ISC_R_NOMEMORY);
14509	zmgr->mctx = NULL;
14510	zmgr->refs = 1;
14511	isc_mem_attach(mctx, &zmgr->mctx);
14512	zmgr->taskmgr = taskmgr;
14513	zmgr->timermgr = timermgr;
14514	zmgr->socketmgr = socketmgr;
14515	zmgr->zonetasks = NULL;
14516	zmgr->loadtasks = NULL;
14517	zmgr->mctxpool = NULL;
14518	zmgr->task = NULL;
14519	zmgr->notifyrl = NULL;
14520	zmgr->refreshrl = NULL;
14521	ISC_LIST_INIT(zmgr->zones);
14522	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
14523	ISC_LIST_INIT(zmgr->xfrin_in_progress);
14524	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
14525	result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
14526	if (result != ISC_R_SUCCESS)
14527		goto free_mem;
14528
14529	zmgr->transfersin = 10;
14530	zmgr->transfersperns = 2;
14531
14532	/* Unreachable lock. */
14533	result = isc_rwlock_init(&zmgr->urlock, 0, 0);
14534	if (result != ISC_R_SUCCESS)
14535		goto free_rwlock;
14536
14537	/* Create a single task for queueing of SOA queries. */
14538	result = isc_task_create(taskmgr, 1, &zmgr->task);
14539	if (result != ISC_R_SUCCESS)
14540		goto free_urlock;
14541
14542	isc_task_setname(zmgr->task, "zmgr", zmgr);
14543	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14544					&zmgr->notifyrl);
14545	if (result != ISC_R_SUCCESS)
14546		goto free_task;
14547
14548	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14549					&zmgr->refreshrl);
14550	if (result != ISC_R_SUCCESS)
14551		goto free_notifyrl;
14552
14553	/* default to 20 refresh queries / notifies per second. */
14554	isc_interval_set(&interval, 0, 1000000000/2);
14555	result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
14556	RUNTIME_CHECK(result == ISC_R_SUCCESS);
14557	isc_ratelimiter_setpertic(zmgr->notifyrl, 10);
14558
14559	result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
14560	RUNTIME_CHECK(result == ISC_R_SUCCESS);
14561	isc_ratelimiter_setpertic(zmgr->refreshrl, 10);
14562
14563	zmgr->iolimit = 1;
14564	zmgr->ioactive = 0;
14565	ISC_LIST_INIT(zmgr->high);
14566	ISC_LIST_INIT(zmgr->low);
14567
14568	result = isc_mutex_init(&zmgr->iolock);
14569	if (result != ISC_R_SUCCESS)
14570		goto free_refreshrl;
14571
14572	zmgr->magic = ZONEMGR_MAGIC;
14573
14574	*zmgrp = zmgr;
14575	return (ISC_R_SUCCESS);
14576
14577#if 0
14578 free_iolock:
14579	DESTROYLOCK(&zmgr->iolock);
14580#endif
14581 free_refreshrl:
14582	isc_ratelimiter_detach(&zmgr->refreshrl);
14583 free_notifyrl:
14584	isc_ratelimiter_detach(&zmgr->notifyrl);
14585 free_task:
14586	isc_task_detach(&zmgr->task);
14587 free_urlock:
14588	isc_rwlock_destroy(&zmgr->urlock);
14589 free_rwlock:
14590	isc_rwlock_destroy(&zmgr->rwlock);
14591 free_mem:
14592	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14593	isc_mem_detach(&mctx);
14594	return (result);
14595}
14596
14597isc_result_t
14598dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
14599	isc_result_t result;
14600	isc_mem_t *mctx = NULL;
14601	dns_zone_t *zone = NULL;
14602	void *item;
14603
14604	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14605	REQUIRE(zonep != NULL && *zonep == NULL);
14606
14607	if (zmgr->mctxpool == NULL)
14608		return (ISC_R_FAILURE);
14609
14610	item = isc_pool_get(zmgr->mctxpool);
14611	if (item == NULL)
14612		return (ISC_R_FAILURE);
14613
14614	isc_mem_attach((isc_mem_t *) item, &mctx);
14615	result = dns_zone_create(&zone, mctx);
14616	isc_mem_detach(&mctx);
14617
14618	if (result == ISC_R_SUCCESS)
14619		*zonep = zone;
14620
14621	return (result);
14622}
14623
14624isc_result_t
14625dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14626	isc_result_t result;
14627
14628	REQUIRE(DNS_ZONE_VALID(zone));
14629	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14630
14631	if (zmgr->zonetasks == NULL)
14632		return (ISC_R_FAILURE);
14633
14634	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14635	LOCK_ZONE(zone);
14636	REQUIRE(zone->task == NULL);
14637	REQUIRE(zone->timer == NULL);
14638	REQUIRE(zone->zmgr == NULL);
14639
14640	isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
14641	isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
14642
14643	/*
14644	 * Set the task name.  The tag will arbitrarily point to one
14645	 * of the zones sharing the task (in practice, the one
14646	 * to be managed last).
14647	 */
14648	isc_task_setname(zone->task, "zone", zone);
14649	isc_task_setname(zone->loadtask, "loadzone", zone);
14650
14651	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
14652				  NULL, NULL,
14653				  zone->task, zone_timer, zone,
14654				  &zone->timer);
14655
14656	if (result != ISC_R_SUCCESS)
14657		goto cleanup_tasks;
14658
14659	/*
14660	 * The timer "holds" a iref.
14661	 */
14662	zone->irefs++;
14663	INSIST(zone->irefs != 0);
14664
14665	ISC_LIST_APPEND(zmgr->zones, zone, link);
14666	zone->zmgr = zmgr;
14667	zmgr->refs++;
14668
14669	goto unlock;
14670
14671 cleanup_tasks:
14672	isc_task_detach(&zone->loadtask);
14673	isc_task_detach(&zone->task);
14674
14675 unlock:
14676	UNLOCK_ZONE(zone);
14677	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14678	return (result);
14679}
14680
14681void
14682dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14683	isc_boolean_t free_now = ISC_FALSE;
14684
14685	REQUIRE(DNS_ZONE_VALID(zone));
14686	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14687	REQUIRE(zone->zmgr == zmgr);
14688
14689	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14690	LOCK_ZONE(zone);
14691
14692	ISC_LIST_UNLINK(zmgr->zones, zone, link);
14693	zone->zmgr = NULL;
14694	zmgr->refs--;
14695	if (zmgr->refs == 0)
14696		free_now = ISC_TRUE;
14697
14698	UNLOCK_ZONE(zone);
14699	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14700
14701	if (free_now)
14702		zonemgr_free(zmgr);
14703	ENSURE(zone->zmgr == NULL);
14704}
14705
14706void
14707dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
14708	REQUIRE(DNS_ZONEMGR_VALID(source));
14709	REQUIRE(target != NULL && *target == NULL);
14710
14711	RWLOCK(&source->rwlock, isc_rwlocktype_write);
14712	REQUIRE(source->refs > 0);
14713	source->refs++;
14714	INSIST(source->refs > 0);
14715	RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
14716	*target = source;
14717}
14718
14719void
14720dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
14721	dns_zonemgr_t *zmgr;
14722	isc_boolean_t free_now = ISC_FALSE;
14723
14724	REQUIRE(zmgrp != NULL);
14725	zmgr = *zmgrp;
14726	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14727
14728	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14729	zmgr->refs--;
14730	if (zmgr->refs == 0)
14731		free_now = ISC_TRUE;
14732	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14733
14734	if (free_now)
14735		zonemgr_free(zmgr);
14736	*zmgrp = NULL;
14737}
14738
14739isc_result_t
14740dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
14741	dns_zone_t *p;
14742
14743	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14744
14745	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14746	for (p = ISC_LIST_HEAD(zmgr->zones);
14747	     p != NULL;
14748	     p = ISC_LIST_NEXT(p, link))
14749	{
14750		dns_zone_maintenance(p);
14751	}
14752	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14753
14754	/*
14755	 * Recent configuration changes may have increased the
14756	 * amount of available transfers quota.  Make sure any
14757	 * transfers currently blocked on quota get started if
14758	 * possible.
14759	 */
14760	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14761	zmgr_resume_xfrs(zmgr, ISC_TRUE);
14762	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14763	return (ISC_R_SUCCESS);
14764}
14765
14766void
14767dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
14768
14769	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14770
14771	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14772	zmgr_resume_xfrs(zmgr, ISC_TRUE);
14773	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14774}
14775
14776void
14777dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
14778	dns_zone_t *zone;
14779
14780	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14781
14782	isc_ratelimiter_shutdown(zmgr->notifyrl);
14783	isc_ratelimiter_shutdown(zmgr->refreshrl);
14784
14785	if (zmgr->task != NULL)
14786		isc_task_destroy(&zmgr->task);
14787	if (zmgr->zonetasks != NULL)
14788		isc_taskpool_destroy(&zmgr->zonetasks);
14789	if (zmgr->loadtasks != NULL)
14790		isc_taskpool_destroy(&zmgr->loadtasks);
14791	if (zmgr->mctxpool != NULL)
14792		isc_pool_destroy(&zmgr->mctxpool);
14793
14794	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14795	for (zone = ISC_LIST_HEAD(zmgr->zones);
14796	     zone != NULL;
14797	     zone = ISC_LIST_NEXT(zone, link))
14798	{
14799		LOCK_ZONE(zone);
14800		forward_cancel(zone);
14801		UNLOCK_ZONE(zone);
14802	}
14803	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14804}
14805
14806static isc_result_t
14807mctxinit(void **target, void *arg) {
14808	isc_result_t result;
14809	isc_mem_t *mctx = NULL;
14810
14811	UNUSED(arg);
14812
14813	REQUIRE(target != NULL && *target == NULL);
14814
14815	result = isc_mem_create(0, 0, &mctx);
14816	if (result != ISC_R_SUCCESS)
14817		return (result);
14818	isc_mem_setname(mctx, "zonemgr-pool", NULL);
14819
14820	*target = mctx;
14821	return (ISC_R_SUCCESS);
14822}
14823
14824static void
14825mctxfree(void **target) {
14826	isc_mem_t *mctx = *(isc_mem_t **) target;
14827	isc_mem_detach(&mctx);
14828	*target = NULL;
14829}
14830
14831#define ZONES_PER_TASK 100
14832#define ZONES_PER_MCTX 1000
14833
14834isc_result_t
14835dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
14836	isc_result_t result;
14837	int ntasks = num_zones / ZONES_PER_TASK;
14838	int nmctx = num_zones / ZONES_PER_MCTX;
14839	isc_taskpool_t *pool = NULL;
14840	isc_pool_t *mctxpool = NULL;
14841
14842	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14843
14844	/*
14845	 * For anything fewer than 1000 zones we use 10 tasks in
14846	 * the task pools.  More than that, and we'll scale at one
14847	 * task per 100 zones.  Similarly, for anything smaller than
14848	 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
14849	 */
14850	if (ntasks < 10)
14851		ntasks = 10;
14852	if (nmctx < 2)
14853		nmctx = 2;
14854
14855	/* Create or resize the zone task pools. */
14856	if (zmgr->zonetasks == NULL)
14857		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
14858					     ntasks, 2, &pool);
14859	else
14860		result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
14861
14862	if (result == ISC_R_SUCCESS)
14863		zmgr->zonetasks = pool;
14864
14865	pool = NULL;
14866	if (zmgr->loadtasks == NULL)
14867		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
14868					     ntasks, 2, &pool);
14869	else
14870		result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
14871
14872	if (result == ISC_R_SUCCESS)
14873		zmgr->loadtasks = pool;
14874
14875#ifdef BIND9
14876	/*
14877	 * We always set all tasks in the zone-load task pool to
14878	 * privileged.  This prevents other tasks in the system from
14879	 * running while the server task manager is in privileged
14880	 * mode.
14881	 *
14882	 * NOTE: If we start using task privileges for any other
14883	 * part of the system than zone tasks, then this will need to be
14884	 * revisted.  In that case we'd want to turn on privileges for
14885	 * zone tasks only when we were loading, and turn them off the
14886	 * rest of the time.  For now, however, it's okay to just
14887	 * set it and forget it.
14888	 */
14889	isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
14890#endif
14891
14892	/* Create or resize the zone memory context pool. */
14893	if (zmgr->mctxpool == NULL)
14894		result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
14895					 mctxinit, NULL, &mctxpool);
14896	else
14897		result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
14898
14899	if (result == ISC_R_SUCCESS)
14900		zmgr->mctxpool = mctxpool;
14901
14902	return (result);
14903}
14904
14905static void
14906zonemgr_free(dns_zonemgr_t *zmgr) {
14907	isc_mem_t *mctx;
14908
14909	INSIST(zmgr->refs == 0);
14910	INSIST(ISC_LIST_EMPTY(zmgr->zones));
14911
14912	zmgr->magic = 0;
14913
14914	DESTROYLOCK(&zmgr->iolock);
14915	isc_ratelimiter_detach(&zmgr->notifyrl);
14916	isc_ratelimiter_detach(&zmgr->refreshrl);
14917
14918	isc_rwlock_destroy(&zmgr->urlock);
14919	isc_rwlock_destroy(&zmgr->rwlock);
14920	mctx = zmgr->mctx;
14921	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14922	isc_mem_detach(&mctx);
14923}
14924
14925void
14926dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
14927	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14928
14929	zmgr->transfersin = value;
14930}
14931
14932isc_uint32_t
14933dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
14934	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14935
14936	return (zmgr->transfersin);
14937}
14938
14939void
14940dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
14941	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14942
14943	zmgr->transfersperns = value;
14944}
14945
14946isc_uint32_t
14947dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
14948	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14949
14950	return (zmgr->transfersperns);
14951}
14952
14953/*
14954 * Try to start a new incoming zone transfer to fill a quota
14955 * slot that was just vacated.
14956 *
14957 * Requires:
14958 *	The zone manager is locked by the caller.
14959 */
14960static void
14961zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
14962	dns_zone_t *zone;
14963	dns_zone_t *next;
14964
14965	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
14966	     zone != NULL;
14967	     zone = next)
14968	{
14969		isc_result_t result;
14970		next = ISC_LIST_NEXT(zone, statelink);
14971		result = zmgr_start_xfrin_ifquota(zmgr, zone);
14972		if (result == ISC_R_SUCCESS) {
14973			if (multi)
14974				continue;
14975			/*
14976			 * We successfully filled the slot.  We're done.
14977			 */
14978			break;
14979		} else if (result == ISC_R_QUOTA) {
14980			/*
14981			 * Not enough quota.  This is probably the per-server
14982			 * quota, because we usually get called when a unit of
14983			 * global quota has just been freed.  Try the next
14984			 * zone, it may succeed if it uses another master.
14985			 */
14986			continue;
14987		} else {
14988			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14989				     "starting zone transfer: %s",
14990				     isc_result_totext(result));
14991			break;
14992		}
14993	}
14994}
14995
14996/*
14997 * Try to start an incoming zone transfer for 'zone', quota permitting.
14998 *
14999 * Requires:
15000 *	The zone manager is locked by the caller.
15001 *
15002 * Returns:
15003 *	ISC_R_SUCCESS	There was enough quota and we attempted to
15004 *			start a transfer.  zone_xfrdone() has been or will
15005 *			be called.
15006 *	ISC_R_QUOTA	Not enough quota.
15007 *	Others		Failure.
15008 */
15009static isc_result_t
15010zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15011	dns_peer_t *peer = NULL;
15012	isc_netaddr_t masterip;
15013	isc_uint32_t nxfrsin, nxfrsperns;
15014	dns_zone_t *x;
15015	isc_uint32_t maxtransfersin, maxtransfersperns;
15016	isc_event_t *e;
15017
15018	/*
15019	 * If we are exiting just pretend we got quota so the zone will
15020	 * be cleaned up in the zone's task context.
15021	 */
15022	LOCK_ZONE(zone);
15023	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15024		UNLOCK_ZONE(zone);
15025		goto gotquota;
15026	}
15027
15028	/*
15029	 * Find any configured information about the server we'd
15030	 * like to transfer this zone from.
15031	 */
15032	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
15033	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
15034	UNLOCK_ZONE(zone);
15035
15036	/*
15037	 * Determine the total maximum number of simultaneous
15038	 * transfers allowed, and the maximum for this specific
15039	 * master.
15040	 */
15041	maxtransfersin = zmgr->transfersin;
15042	maxtransfersperns = zmgr->transfersperns;
15043	if (peer != NULL)
15044		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
15045
15046	/*
15047	 * Count the total number of transfers that are in progress,
15048	 * and the number of transfers in progress from this master.
15049	 * We linearly scan a list of all transfers; if this turns
15050	 * out to be too slow, we could hash on the master address.
15051	 */
15052	nxfrsin = nxfrsperns = 0;
15053	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15054	     x != NULL;
15055	     x = ISC_LIST_NEXT(x, statelink))
15056	{
15057		isc_netaddr_t xip;
15058
15059		LOCK_ZONE(x);
15060		isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
15061		UNLOCK_ZONE(x);
15062
15063		nxfrsin++;
15064		if (isc_netaddr_equal(&xip, &masterip))
15065			nxfrsperns++;
15066	}
15067
15068	/* Enforce quota. */
15069	if (nxfrsin >= maxtransfersin)
15070		return (ISC_R_QUOTA);
15071
15072	if (nxfrsperns >= maxtransfersperns)
15073		return (ISC_R_QUOTA);
15074
15075 gotquota:
15076	/*
15077	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
15078	 * list and send it an event to let it start the actual transfer in the
15079	 * context of its own task.
15080	 */
15081	e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
15082			       got_transfer_quota, zone, sizeof(isc_event_t));
15083	if (e == NULL)
15084		return (ISC_R_NOMEMORY);
15085
15086	LOCK_ZONE(zone);
15087	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
15088	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
15089	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
15090	zone->statelist = &zmgr->xfrin_in_progress;
15091	isc_task_send(zone->task, &e);
15092	dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
15093	UNLOCK_ZONE(zone);
15094
15095	return (ISC_R_SUCCESS);
15096}
15097
15098void
15099dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
15100
15101	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15102	REQUIRE(iolimit > 0);
15103
15104	zmgr->iolimit = iolimit;
15105}
15106
15107isc_uint32_t
15108dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
15109
15110	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15111
15112	return (zmgr->iolimit);
15113}
15114
15115/*
15116 * Get permission to request a file handle from the OS.
15117 * An event will be sent to action when one is available.
15118 * There are two queues available (high and low), the high
15119 * queue will be serviced before the low one.
15120 *
15121 * zonemgr_putio() must be called after the event is delivered to
15122 * 'action'.
15123 */
15124
15125static isc_result_t
15126zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
15127	      isc_task_t *task, isc_taskaction_t action, void *arg,
15128	      dns_io_t **iop)
15129{
15130	dns_io_t *io;
15131	isc_boolean_t queue;
15132
15133	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15134	REQUIRE(iop != NULL && *iop == NULL);
15135
15136	io = isc_mem_get(zmgr->mctx, sizeof(*io));
15137	if (io == NULL)
15138		return (ISC_R_NOMEMORY);
15139
15140	io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
15141				       action, arg, sizeof(*io->event));
15142	if (io->event == NULL) {
15143		isc_mem_put(zmgr->mctx, io, sizeof(*io));
15144		return (ISC_R_NOMEMORY);
15145	}
15146
15147	io->zmgr = zmgr;
15148	io->high = high;
15149	io->task = NULL;
15150	isc_task_attach(task, &io->task);
15151	ISC_LINK_INIT(io, link);
15152	io->magic = IO_MAGIC;
15153
15154	LOCK(&zmgr->iolock);
15155	zmgr->ioactive++;
15156	queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
15157	if (queue) {
15158		if (io->high)
15159			ISC_LIST_APPEND(zmgr->high, io, link);
15160		else
15161			ISC_LIST_APPEND(zmgr->low, io, link);
15162	}
15163	UNLOCK(&zmgr->iolock);
15164	*iop = io;
15165
15166	if (!queue)
15167		isc_task_send(io->task, &io->event);
15168	return (ISC_R_SUCCESS);
15169}
15170
15171static void
15172zonemgr_putio(dns_io_t **iop) {
15173	dns_io_t *io;
15174	dns_io_t *next;
15175	dns_zonemgr_t *zmgr;
15176
15177	REQUIRE(iop != NULL);
15178	io = *iop;
15179	REQUIRE(DNS_IO_VALID(io));
15180
15181	*iop = NULL;
15182
15183	INSIST(!ISC_LINK_LINKED(io, link));
15184	INSIST(io->event == NULL);
15185
15186	zmgr = io->zmgr;
15187	isc_task_detach(&io->task);
15188	io->magic = 0;
15189	isc_mem_put(zmgr->mctx, io, sizeof(*io));
15190
15191	LOCK(&zmgr->iolock);
15192	INSIST(zmgr->ioactive > 0);
15193	zmgr->ioactive--;
15194	next = HEAD(zmgr->high);
15195	if (next == NULL)
15196		next = HEAD(zmgr->low);
15197	if (next != NULL) {
15198		if (next->high)
15199			ISC_LIST_UNLINK(zmgr->high, next, link);
15200		else
15201			ISC_LIST_UNLINK(zmgr->low, next, link);
15202		INSIST(next->event != NULL);
15203	}
15204	UNLOCK(&zmgr->iolock);
15205	if (next != NULL)
15206		isc_task_send(next->task, &next->event);
15207}
15208
15209static void
15210zonemgr_cancelio(dns_io_t *io) {
15211	isc_boolean_t send_event = ISC_FALSE;
15212
15213	REQUIRE(DNS_IO_VALID(io));
15214
15215	/*
15216	 * If we are queued to be run then dequeue.
15217	 */
15218	LOCK(&io->zmgr->iolock);
15219	if (ISC_LINK_LINKED(io, link)) {
15220		if (io->high)
15221			ISC_LIST_UNLINK(io->zmgr->high, io, link);
15222		else
15223			ISC_LIST_UNLINK(io->zmgr->low, io, link);
15224
15225		send_event = ISC_TRUE;
15226		INSIST(io->event != NULL);
15227	}
15228	UNLOCK(&io->zmgr->iolock);
15229	if (send_event) {
15230		io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
15231		isc_task_send(io->task, &io->event);
15232	}
15233}
15234
15235static void
15236zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
15237	char *buf;
15238	int buflen;
15239	isc_result_t result;
15240
15241	buflen = strlen(path) + strlen(templat) + 2;
15242
15243	buf = isc_mem_get(zone->mctx, buflen);
15244	if (buf == NULL)
15245		return;
15246
15247	result = isc_file_template(path, templat, buf, buflen);
15248	if (result != ISC_R_SUCCESS)
15249		goto cleanup;
15250
15251	result = isc_file_renameunique(path, buf);
15252	if (result != ISC_R_SUCCESS)
15253		goto cleanup;
15254
15255	dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
15256		     "renaming file to '%s' for failure analysis and "
15257		     "retransferring.", path, buf);
15258
15259 cleanup:
15260	isc_mem_put(zone->mctx, buf, buflen);
15261}
15262
15263#if 0
15264/* Hook for ondestroy notification from a database. */
15265
15266static void
15267dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
15268	dns_db_t *db = event->sender;
15269	UNUSED(task);
15270
15271	isc_event_free(&event);
15272
15273	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15274		      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15275		      "database (%p) destroyed", (void*) db);
15276}
15277#endif
15278
15279void
15280dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
15281	isc_interval_t interval;
15282	isc_uint32_t s, ns;
15283	isc_uint32_t pertic;
15284	isc_result_t result;
15285
15286	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15287
15288	if (value == 0)
15289		value = 1;
15290
15291	if (value == 1) {
15292		s = 1;
15293		ns = 0;
15294		pertic = 1;
15295	} else if (value <= 10) {
15296		s = 0;
15297		ns = 1000000000 / value;
15298		pertic = 1;
15299	} else {
15300		s = 0;
15301		ns = (1000000000 / value) * 10;
15302		pertic = 10;
15303	}
15304
15305	isc_interval_set(&interval, s, ns);
15306
15307	result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
15308	RUNTIME_CHECK(result == ISC_R_SUCCESS);
15309	isc_ratelimiter_setpertic(zmgr->notifyrl, pertic);
15310
15311	result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
15312	RUNTIME_CHECK(result == ISC_R_SUCCESS);
15313	isc_ratelimiter_setpertic(zmgr->refreshrl, pertic);
15314
15315	zmgr->serialqueryrate = value;
15316}
15317
15318unsigned int
15319dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
15320	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15321
15322	return (zmgr->serialqueryrate);
15323}
15324
15325isc_boolean_t
15326dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15327			isc_sockaddr_t *local, isc_time_t *now)
15328{
15329	unsigned int i;
15330	isc_rwlocktype_t locktype;
15331	isc_result_t result;
15332	isc_uint32_t seconds = isc_time_seconds(now);
15333	isc_uint32_t count = 0;
15334
15335	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15336
15337	locktype = isc_rwlocktype_read;
15338	RWLOCK(&zmgr->urlock, locktype);
15339	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15340		if (zmgr->unreachable[i].expire >= seconds &&
15341		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15342		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
15343			result = isc_rwlock_tryupgrade(&zmgr->urlock);
15344			if (result == ISC_R_SUCCESS) {
15345				locktype = isc_rwlocktype_write;
15346				zmgr->unreachable[i].last = seconds;
15347				count = zmgr->unreachable[i].count;
15348			}
15349			break;
15350		}
15351	}
15352	RWUNLOCK(&zmgr->urlock, locktype);
15353	return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
15354}
15355
15356void
15357dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15358			   isc_sockaddr_t *local)
15359{
15360	unsigned int i;
15361	isc_rwlocktype_t locktype;
15362	isc_result_t result;
15363
15364	char master[ISC_SOCKADDR_FORMATSIZE];
15365	char source[ISC_SOCKADDR_FORMATSIZE];
15366
15367	isc_sockaddr_format(remote, master, sizeof(master));
15368	isc_sockaddr_format(local, source, sizeof(source));
15369
15370	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15371
15372	locktype = isc_rwlocktype_read;
15373	RWLOCK(&zmgr->urlock, locktype);
15374	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15375		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15376		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
15377			if (zmgr->unreachable[i].expire == 0)
15378				break;
15379			result = isc_rwlock_tryupgrade(&zmgr->urlock);
15380			if (result == ISC_R_SUCCESS) {
15381				locktype = isc_rwlocktype_write;
15382				zmgr->unreachable[i].expire = 0;
15383				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15384					      DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
15385					      "master %s (source %s) deleted "
15386					      "from unreachable cache",
15387					      master, source);
15388			}
15389			break;
15390		}
15391	}
15392	RWUNLOCK(&zmgr->urlock, locktype);
15393}
15394
15395void
15396dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15397			   isc_sockaddr_t *local, isc_time_t *now)
15398{
15399	isc_uint32_t seconds = isc_time_seconds(now);
15400	isc_uint32_t last = seconds;
15401	unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
15402
15403	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15404
15405	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
15406	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15407		/* Existing entry? */
15408		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15409		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
15410			break;
15411		/* Empty slot? */
15412		if (zmgr->unreachable[i].expire < seconds)
15413			slot = i;
15414		/* Least recently used slot? */
15415		if (zmgr->unreachable[i].last < last) {
15416			last = zmgr->unreachable[i].last;
15417			oldest = i;
15418		}
15419	}
15420	if (i < UNREACH_CHACHE_SIZE) {
15421		/*
15422		 * Found a existing entry.  Update the expire timer and
15423		 * last usage timestamps.
15424		 */
15425		zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
15426		zmgr->unreachable[i].last = seconds;
15427		if (zmgr->unreachable[i].expire < seconds)
15428			zmgr->unreachable[i].count = 1;
15429		else
15430			zmgr->unreachable[i].count++;
15431	} else if (slot != UNREACH_CHACHE_SIZE) {
15432		/*
15433		 * Found a empty slot. Add a new entry to the cache.
15434		 */
15435		zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
15436		zmgr->unreachable[slot].last = seconds;
15437		zmgr->unreachable[slot].remote = *remote;
15438		zmgr->unreachable[slot].local = *local;
15439		zmgr->unreachable[slot].count = 1;
15440	} else {
15441		/*
15442		 * Replace the least recently used entry in the cache.
15443		 */
15444		zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
15445		zmgr->unreachable[oldest].last = seconds;
15446		zmgr->unreachable[oldest].remote = *remote;
15447		zmgr->unreachable[oldest].local = *local;
15448		zmgr->unreachable[oldest].count = 1;
15449	}
15450	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
15451}
15452
15453void
15454dns_zone_forcereload(dns_zone_t *zone) {
15455	REQUIRE(DNS_ZONE_VALID(zone));
15456
15457	if (zone->type == dns_zone_master ||
15458	    (zone->type == dns_zone_redirect && zone->masters == NULL))
15459		return;
15460
15461	LOCK_ZONE(zone);
15462	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
15463	UNLOCK_ZONE(zone);
15464	dns_zone_refresh(zone);
15465}
15466
15467isc_boolean_t
15468dns_zone_isforced(dns_zone_t *zone) {
15469	REQUIRE(DNS_ZONE_VALID(zone));
15470
15471	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
15472}
15473
15474isc_result_t
15475dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
15476	/*
15477	 * This function is obsoleted.
15478	 */
15479	UNUSED(zone);
15480	UNUSED(on);
15481	return (ISC_R_NOTIMPLEMENTED);
15482}
15483
15484isc_uint64_t *
15485dns_zone_getstatscounters(dns_zone_t *zone) {
15486	/*
15487	 * This function is obsoleted.
15488	 */
15489	UNUSED(zone);
15490	return (NULL);
15491}
15492
15493void
15494dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
15495	REQUIRE(DNS_ZONE_VALID(zone));
15496	REQUIRE(zone->stats == NULL);
15497
15498	LOCK_ZONE(zone);
15499	zone->stats = NULL;
15500	isc_stats_attach(stats, &zone->stats);
15501	UNLOCK_ZONE(zone);
15502}
15503
15504void
15505dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
15506
15507	REQUIRE(DNS_ZONE_VALID(zone));
15508
15509	LOCK_ZONE(zone);
15510	if (zone->requeststats_on && stats == NULL)
15511		zone->requeststats_on = ISC_FALSE;
15512	else if (!zone->requeststats_on && stats != NULL) {
15513		if (zone->requeststats == NULL) {
15514			isc_stats_attach(stats, &zone->requeststats);
15515			zone->requeststats_on = ISC_TRUE;
15516		}
15517	}
15518	UNLOCK_ZONE(zone);
15519}
15520
15521#ifdef NEWSTATS
15522void
15523dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
15524
15525	REQUIRE(DNS_ZONE_VALID(zone));
15526
15527	LOCK_ZONE(zone);
15528	if (zone->requeststats_on && stats != NULL) {
15529		if (zone->rcvquerystats == NULL) {
15530			dns_stats_attach(stats, &zone->rcvquerystats);
15531			zone->requeststats_on = ISC_TRUE;
15532		}
15533	}
15534	UNLOCK_ZONE(zone);
15535}
15536#endif
15537
15538isc_stats_t *
15539dns_zone_getrequeststats(dns_zone_t *zone) {
15540	/*
15541	 * We don't lock zone for efficiency reason.  This is not catastrophic
15542	 * because requeststats must always be valid when requeststats_on is
15543	 * true.
15544	 * Some counters may be incremented while requeststats_on is becoming
15545	 * false, or some cannot be incremented just after the statistics are
15546	 * installed, but it shouldn't matter much in practice.
15547	 */
15548	if (zone->requeststats_on)
15549		return (zone->requeststats);
15550	else
15551		return (NULL);
15552}
15553
15554#ifdef NEWSTATS
15555/*
15556 * Return the received query stats bucket
15557 * see note from dns_zone_getrequeststats()
15558 */
15559dns_stats_t *
15560dns_zone_getrcvquerystats(dns_zone_t *zone) {
15561	if (zone->requeststats_on)
15562		return (zone->rcvquerystats);
15563	else
15564		return (NULL);
15565}
15566#endif
15567
15568void
15569dns_zone_dialup(dns_zone_t *zone) {
15570
15571	REQUIRE(DNS_ZONE_VALID(zone));
15572
15573	zone_debuglog(zone, "dns_zone_dialup", 3,
15574		      "notify = %d, refresh = %d",
15575		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
15576		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
15577
15578	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
15579		dns_zone_notify(zone);
15580	if (zone->type != dns_zone_master && zone->masters != NULL &&
15581	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
15582		dns_zone_refresh(zone);
15583}
15584
15585void
15586dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
15587	REQUIRE(DNS_ZONE_VALID(zone));
15588
15589	LOCK_ZONE(zone);
15590	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
15591			 DNS_ZONEFLG_DIALREFRESH |
15592			 DNS_ZONEFLG_NOREFRESH);
15593	switch (dialup) {
15594	case dns_dialuptype_no:
15595		break;
15596	case dns_dialuptype_yes:
15597		DNS_ZONE_SETFLAG(zone,	(DNS_ZONEFLG_DIALNOTIFY |
15598				 DNS_ZONEFLG_DIALREFRESH |
15599				 DNS_ZONEFLG_NOREFRESH));
15600		break;
15601	case dns_dialuptype_notify:
15602		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15603		break;
15604	case dns_dialuptype_notifypassive:
15605		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15606		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15607		break;
15608	case dns_dialuptype_refresh:
15609		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
15610		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15611		break;
15612	case dns_dialuptype_passive:
15613		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15614		break;
15615	default:
15616		INSIST(0);
15617	}
15618	UNLOCK_ZONE(zone);
15619}
15620
15621isc_result_t
15622dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
15623	isc_result_t result = ISC_R_SUCCESS;
15624
15625	REQUIRE(DNS_ZONE_VALID(zone));
15626
15627	LOCK_ZONE(zone);
15628	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
15629	UNLOCK_ZONE(zone);
15630
15631	return (result);
15632}
15633
15634const char *
15635dns_zone_getkeydirectory(dns_zone_t *zone) {
15636	REQUIRE(DNS_ZONE_VALID(zone));
15637
15638	return (zone->keydirectory);
15639}
15640
15641unsigned int
15642dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
15643	dns_zone_t *zone;
15644	unsigned int count = 0;
15645
15646	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15647
15648	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15649	switch (state) {
15650	case DNS_ZONESTATE_XFERRUNNING:
15651		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15652		     zone != NULL;
15653		     zone = ISC_LIST_NEXT(zone, statelink))
15654			count++;
15655		break;
15656	case DNS_ZONESTATE_XFERDEFERRED:
15657		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
15658		     zone != NULL;
15659		     zone = ISC_LIST_NEXT(zone, statelink))
15660			count++;
15661		break;
15662	case DNS_ZONESTATE_SOAQUERY:
15663		for (zone = ISC_LIST_HEAD(zmgr->zones);
15664		     zone != NULL;
15665		     zone = ISC_LIST_NEXT(zone, link))
15666			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
15667				count++;
15668		break;
15669	case DNS_ZONESTATE_ANY:
15670		for (zone = ISC_LIST_HEAD(zmgr->zones);
15671		     zone != NULL;
15672		     zone = ISC_LIST_NEXT(zone, link)) {
15673			dns_view_t *view = zone->view;
15674			if (view != NULL && strcmp(view->name, "_bind") == 0)
15675				continue;
15676			count++;
15677		}
15678		break;
15679	default:
15680		INSIST(0);
15681	}
15682
15683	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15684
15685	return (count);
15686}
15687
15688isc_result_t
15689dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
15690	isc_boolean_t ok = ISC_TRUE;
15691	isc_boolean_t fail = ISC_FALSE;
15692	char namebuf[DNS_NAME_FORMATSIZE];
15693	char namebuf2[DNS_NAME_FORMATSIZE];
15694	char typebuf[DNS_RDATATYPE_FORMATSIZE];
15695	int level = ISC_LOG_WARNING;
15696	dns_name_t bad;
15697
15698	REQUIRE(DNS_ZONE_VALID(zone));
15699
15700	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
15701		return (ISC_R_SUCCESS);
15702
15703	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
15704		level = ISC_LOG_ERROR;
15705		fail = ISC_TRUE;
15706	}
15707
15708	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
15709	if (!ok) {
15710		dns_name_format(name, namebuf, sizeof(namebuf));
15711		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
15712		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
15713			     dns_result_totext(DNS_R_BADOWNERNAME));
15714		if (fail)
15715			return (DNS_R_BADOWNERNAME);
15716	}
15717
15718	dns_name_init(&bad, NULL);
15719	ok = dns_rdata_checknames(rdata, name, &bad);
15720	if (!ok) {
15721		dns_name_format(name, namebuf, sizeof(namebuf));
15722		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
15723		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
15724		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
15725			     namebuf2, dns_result_totext(DNS_R_BADNAME));
15726		if (fail)
15727			return (DNS_R_BADNAME);
15728	}
15729
15730	return (ISC_R_SUCCESS);
15731}
15732
15733void
15734dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
15735	REQUIRE(DNS_ZONE_VALID(zone));
15736	zone->checkmx = checkmx;
15737}
15738
15739void
15740dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
15741	REQUIRE(DNS_ZONE_VALID(zone));
15742	zone->checksrv = checksrv;
15743}
15744
15745void
15746dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
15747	REQUIRE(DNS_ZONE_VALID(zone));
15748	zone->checkns = checkns;
15749}
15750
15751void
15752dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
15753	REQUIRE(DNS_ZONE_VALID(zone));
15754
15755	LOCK_ZONE(zone);
15756	zone->isself = isself;
15757	zone->isselfarg = arg;
15758	UNLOCK_ZONE(zone);
15759}
15760
15761void
15762dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
15763	REQUIRE(DNS_ZONE_VALID(zone));
15764
15765	LOCK_ZONE(zone);
15766	zone->notifydelay = delay;
15767	UNLOCK_ZONE(zone);
15768}
15769
15770isc_uint32_t
15771dns_zone_getnotifydelay(dns_zone_t *zone) {
15772	REQUIRE(DNS_ZONE_VALID(zone));
15773
15774	return (zone->notifydelay);
15775}
15776
15777isc_result_t
15778dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
15779		     isc_uint16_t keyid, isc_boolean_t delete)
15780{
15781	isc_result_t result;
15782	REQUIRE(DNS_ZONE_VALID(zone));
15783
15784	dns_zone_log(zone, ISC_LOG_NOTICE,
15785		     "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
15786		     algorithm, keyid);
15787	LOCK_ZONE(zone);
15788	result = zone_signwithkey(zone, algorithm, keyid, delete);
15789	UNLOCK_ZONE(zone);
15790
15791	return (result);
15792}
15793
15794static const char *hex = "0123456789ABCDEF";
15795
15796isc_result_t
15797dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
15798	isc_result_t result;
15799	char salt[255*2+1];
15800	unsigned int i, j;
15801
15802	REQUIRE(DNS_ZONE_VALID(zone));
15803
15804	if (nsec3param->salt_length != 0) {
15805		INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
15806		for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
15807			salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
15808			salt[j++] = hex[nsec3param->salt[i] & 0xf];
15809		}
15810		salt[j] = '\0';
15811	} else
15812		strcpy(salt, "-");
15813	dns_zone_log(zone, ISC_LOG_NOTICE,
15814		     "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
15815		     nsec3param->hash, nsec3param->iterations,
15816		     salt);
15817	LOCK_ZONE(zone);
15818	result = zone_addnsec3chain(zone, nsec3param);
15819	UNLOCK_ZONE(zone);
15820
15821	return (result);
15822}
15823
15824void
15825dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
15826	REQUIRE(DNS_ZONE_VALID(zone));
15827
15828	if (nodes == 0)
15829		nodes = 1;
15830	zone->nodes = nodes;
15831}
15832
15833void
15834dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
15835	REQUIRE(DNS_ZONE_VALID(zone));
15836
15837	/*
15838	 * We treat signatures as a signed value so explicitly
15839	 * limit its range here.
15840	 */
15841	if (signatures > ISC_INT32_MAX)
15842		signatures = ISC_INT32_MAX;
15843	else if (signatures == 0)
15844		signatures = 1;
15845	zone->signatures = signatures;
15846}
15847
15848void
15849dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
15850	REQUIRE(DNS_ZONE_VALID(zone));
15851	zone->privatetype = type;
15852}
15853
15854dns_rdatatype_t
15855dns_zone_getprivatetype(dns_zone_t *zone) {
15856	REQUIRE(DNS_ZONE_VALID(zone));
15857	return (zone->privatetype);
15858}
15859
15860static isc_result_t
15861zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
15862		 isc_boolean_t delete)
15863{
15864	dns_signing_t *signing;
15865	dns_signing_t *current;
15866	isc_result_t result = ISC_R_SUCCESS;
15867	isc_time_t now;
15868	dns_db_t *db = NULL;
15869
15870	signing = isc_mem_get(zone->mctx, sizeof *signing);
15871	if (signing == NULL)
15872		return (ISC_R_NOMEMORY);
15873
15874	signing->magic = 0;
15875	signing->db  = NULL;
15876	signing->dbiterator = NULL;
15877	signing->algorithm = algorithm;
15878	signing->keyid = keyid;
15879	signing->delete = delete;
15880	signing->done = ISC_FALSE;
15881
15882	TIME_NOW(&now);
15883
15884	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15885	if (zone->db != NULL)
15886		dns_db_attach(zone->db, &db);
15887	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15888
15889	if (db == NULL) {
15890		result = ISC_R_NOTFOUND;
15891		goto cleanup;
15892	}
15893
15894	dns_db_attach(db, &signing->db);
15895
15896	for (current = ISC_LIST_HEAD(zone->signing);
15897	     current != NULL;
15898	     current = ISC_LIST_NEXT(current, link)) {
15899		if (current->db == signing->db &&
15900		    current->algorithm == signing->algorithm &&
15901		    current->keyid == signing->keyid) {
15902			if (current->delete != signing->delete)
15903				current->done = ISC_TRUE;
15904			else
15905				goto cleanup;
15906		}
15907	}
15908
15909	result = dns_db_createiterator(signing->db, 0,
15910				       &signing->dbiterator);
15911
15912	if (result == ISC_R_SUCCESS)
15913		result = dns_dbiterator_first(signing->dbiterator);
15914	if (result == ISC_R_SUCCESS) {
15915		dns_dbiterator_pause(signing->dbiterator);
15916		ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
15917		signing = NULL;
15918		if (isc_time_isepoch(&zone->signingtime)) {
15919			zone->signingtime = now;
15920			if (zone->task != NULL)
15921				zone_settimer(zone, &now);
15922		}
15923	}
15924
15925 cleanup:
15926	if (signing != NULL) {
15927		if (signing->db != NULL)
15928			dns_db_detach(&signing->db);
15929		if (signing->dbiterator != NULL)
15930			dns_dbiterator_destroy(&signing->dbiterator);
15931		isc_mem_put(zone->mctx, signing, sizeof *signing);
15932	}
15933	if (db != NULL)
15934		dns_db_detach(&db);
15935	return (result);
15936}
15937
15938static void
15939logmsg(const char *format, ...) {
15940	va_list args;
15941	va_start(args, format);
15942	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
15943		       ISC_LOG_DEBUG(1), format, args);
15944	va_end(args);
15945}
15946
15947static void
15948clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
15949	dns_dnsseckey_t *key;
15950	while (!ISC_LIST_EMPTY(*list)) {
15951		key = ISC_LIST_HEAD(*list);
15952		ISC_LIST_UNLINK(*list, key, link);
15953		dns_dnsseckey_destroy(mctx, &key);
15954	}
15955}
15956
15957/* Called once; *timep should be set to the current time. */
15958static isc_result_t
15959next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
15960	isc_result_t result;
15961	isc_stdtime_t now, then = 0, event;
15962	int i;
15963
15964	now = *timep;
15965
15966	for (i = 0; i <= DST_MAX_TIMES; i++) {
15967		result = dst_key_gettime(key, i, &event);
15968		if (result == ISC_R_SUCCESS && event > now &&
15969		    (then == 0 || event < then))
15970			then = event;
15971	}
15972
15973	if (then != 0) {
15974		*timep = then;
15975		return (ISC_R_SUCCESS);
15976	}
15977
15978	return (ISC_R_NOTFOUND);
15979}
15980
15981static isc_result_t
15982rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
15983	  const dns_rdata_t *rdata, isc_boolean_t *flag)
15984{
15985	dns_rdataset_t rdataset;
15986	dns_dbnode_t *node = NULL;
15987	isc_result_t result;
15988
15989	dns_rdataset_init(&rdataset);
15990	if (rdata->type == dns_rdatatype_nsec3)
15991		CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
15992	else
15993		CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
15994	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
15995				     (isc_stdtime_t) 0, &rdataset, NULL);
15996	if (result == ISC_R_NOTFOUND) {
15997		*flag = ISC_FALSE;
15998		result = ISC_R_SUCCESS;
15999		goto failure;
16000	}
16001
16002	for (result = dns_rdataset_first(&rdataset);
16003	     result == ISC_R_SUCCESS;
16004	     result = dns_rdataset_next(&rdataset)) {
16005		dns_rdata_t myrdata = DNS_RDATA_INIT;
16006		dns_rdataset_current(&rdataset, &myrdata);
16007		if (!dns_rdata_compare(&myrdata, rdata))
16008			break;
16009	}
16010	dns_rdataset_disassociate(&rdataset);
16011	if (result == ISC_R_SUCCESS) {
16012		*flag = ISC_TRUE;
16013	} else if (result == ISC_R_NOMORE) {
16014		*flag = ISC_FALSE;
16015		result = ISC_R_SUCCESS;
16016	}
16017
16018 failure:
16019	if (node != NULL)
16020		dns_db_detachnode(db, &node);
16021	return (result);
16022}
16023
16024/*
16025 * Add records to signal the state of signing or of key removal.
16026 */
16027static isc_result_t
16028add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
16029		    dns_dbversion_t *ver, dns_diff_t *diff,
16030		    isc_boolean_t sign_all)
16031{
16032	dns_difftuple_t *tuple, *newtuple = NULL;
16033	dns_rdata_dnskey_t dnskey;
16034	dns_rdata_t rdata = DNS_RDATA_INIT;
16035	isc_boolean_t flag;
16036	isc_region_t r;
16037	isc_result_t result = ISC_R_SUCCESS;
16038	isc_uint16_t keyid;
16039	unsigned char buf[5];
16040	dns_name_t *name = dns_db_origin(db);
16041
16042	for (tuple = ISC_LIST_HEAD(diff->tuples);
16043	     tuple != NULL;
16044	     tuple = ISC_LIST_NEXT(tuple, link)) {
16045		if (tuple->rdata.type != dns_rdatatype_dnskey)
16046			continue;
16047
16048		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
16049		RUNTIME_CHECK(result == ISC_R_SUCCESS);
16050		if ((dnskey.flags &
16051		     (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
16052			 != DNS_KEYOWNER_ZONE)
16053			continue;
16054
16055		dns_rdata_toregion(&tuple->rdata, &r);
16056
16057		keyid = dst_region_computeid(&r, dnskey.algorithm);
16058
16059		buf[0] = dnskey.algorithm;
16060		buf[1] = (keyid & 0xff00) >> 8;
16061		buf[2] = (keyid & 0xff);
16062		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
16063		buf[4] = 0;
16064		rdata.data = buf;
16065		rdata.length = sizeof(buf);
16066		rdata.type = privatetype;
16067		rdata.rdclass = tuple->rdata.rdclass;
16068
16069		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
16070			CHECK(rr_exists(db, ver, name, &rdata, &flag));
16071			if (flag)
16072				continue;
16073			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
16074						   name, 0, &rdata, &newtuple));
16075			CHECK(do_one_tuple(&newtuple, db, ver, diff));
16076			INSIST(newtuple == NULL);
16077		}
16078
16079		/*
16080		 * Remove any record which says this operation has already
16081		 * completed.
16082		 */
16083		buf[4] = 1;
16084		CHECK(rr_exists(db, ver, name, &rdata, &flag));
16085		if (flag) {
16086			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
16087						   name, 0, &rdata, &newtuple));
16088			CHECK(do_one_tuple(&newtuple, db, ver, diff));
16089			INSIST(newtuple == NULL);
16090		}
16091	}
16092 failure:
16093	return (result);
16094}
16095
16096static isc_result_t
16097sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16098	  dns_diff_t *diff, zonediff_t *zonediff)
16099{
16100	isc_result_t result;
16101	isc_stdtime_t now, inception, soaexpire;
16102	isc_boolean_t check_ksk, keyset_kskonly;
16103	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
16104	unsigned int nkeys = 0, i;
16105	dns_difftuple_t *tuple;
16106
16107	result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
16108				zone_keys, &nkeys);
16109	if (result != ISC_R_SUCCESS) {
16110		dns_zone_log(zone, ISC_LOG_ERROR,
16111			     "sign_apex:find_zone_keys -> %s",
16112			     dns_result_totext(result));
16113		return (result);
16114	}
16115
16116	isc_stdtime_get(&now);
16117	inception = now - 3600;	/* Allow for clock skew. */
16118	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
16119
16120	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16121	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
16122
16123	/*
16124	 * See if update_sigs will update DNSKEY signature and if not
16125	 * cause them to sign so that so that newly activated keys
16126	 * are used.
16127	 */
16128	for (tuple = ISC_LIST_HEAD(diff->tuples);
16129	     tuple != NULL;
16130	     tuple = ISC_LIST_NEXT(tuple, link)) {
16131		if (tuple->rdata.type == dns_rdatatype_dnskey &&
16132		    dns_name_equal(&tuple->name, &zone->origin))
16133			break;
16134	}
16135
16136	if (tuple == NULL) {
16137		result = del_sigs(zone, db, ver, &zone->origin,
16138				  dns_rdatatype_dnskey, zonediff,
16139				  zone_keys, nkeys, now, ISC_FALSE);
16140		if (result != ISC_R_SUCCESS) {
16141			dns_zone_log(zone, ISC_LOG_ERROR,
16142				     "sign_apex:del_sigs -> %s",
16143				     dns_result_totext(result));
16144			goto failure;
16145		}
16146		result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
16147				  zonediff->diff, zone_keys, nkeys, zone->mctx,
16148				  inception, soaexpire, check_ksk,
16149				  keyset_kskonly);
16150		if (result != ISC_R_SUCCESS) {
16151			dns_zone_log(zone, ISC_LOG_ERROR,
16152				     "sign_apex:add_sigs -> %s",
16153				     dns_result_totext(result));
16154			goto failure;
16155		}
16156	}
16157
16158	result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
16159			     inception, soaexpire, now, check_ksk,
16160			     keyset_kskonly, zonediff);
16161
16162	if (result != ISC_R_SUCCESS) {
16163		dns_zone_log(zone, ISC_LOG_ERROR,
16164			     "sign_apex:update_sigs -> %s",
16165			     dns_result_totext(result));
16166		goto failure;
16167	}
16168
16169 failure:
16170	for (i = 0; i < nkeys; i++)
16171		dst_key_free(&zone_keys[i]);
16172	return (result);
16173}
16174
16175/*
16176 * Prevent the zone entering a inconsistent state where
16177 * NSEC only DNSKEYs are present with NSEC3 chains.
16178 * See update.c:check_dnssec()
16179 */
16180static isc_boolean_t
16181dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16182	    dns_diff_t *diff)
16183{
16184	isc_result_t result;
16185	dns_difftuple_t *tuple;
16186	isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
16187	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
16188
16189	/* Scan the tuples for an NSEC-only DNSKEY */
16190	for (tuple = ISC_LIST_HEAD(diff->tuples);
16191	     tuple != NULL;
16192	     tuple = ISC_LIST_NEXT(tuple, link)) {
16193		isc_uint8_t alg;
16194		if (tuple->rdata.type != dns_rdatatype_dnskey ||
16195		    tuple->op != DNS_DIFFOP_ADD)
16196			continue;
16197
16198		alg = tuple->rdata.data[3];
16199		if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
16200		    alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
16201			nseconly = ISC_TRUE;
16202			break;
16203		}
16204	}
16205
16206	/* Check existing DB for NSEC-only DNSKEY */
16207	if (!nseconly) {
16208		result = dns_nsec_nseconly(db, ver, &nseconly);
16209		if (result == ISC_R_NOTFOUND)
16210			result = ISC_R_SUCCESS;
16211		CHECK(result);
16212	}
16213
16214	/* Check existing DB for NSEC3 */
16215	if (!nsec3)
16216		CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
16217					privatetype, &nsec3));
16218
16219	/* Refuse to allow NSEC3 with NSEC-only keys */
16220	if (nseconly && nsec3) {
16221		dns_zone_log(zone, ISC_LOG_ERROR,
16222			   "NSEC only DNSKEYs and NSEC3 chains not allowed");
16223		goto failure;
16224	}
16225
16226	return (ISC_TRUE);
16227
16228 failure:
16229	return (ISC_FALSE);
16230}
16231
16232static isc_result_t
16233clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16234		 dns_diff_t *diff)
16235{
16236	isc_result_t result;
16237	dns_dbnode_t *node = NULL;
16238	dns_rdataset_t rdataset;
16239
16240	dns_rdataset_init(&rdataset);
16241	CHECK(dns_db_getoriginnode(db, &node));
16242
16243	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16244				     dns_rdatatype_none, 0, &rdataset, NULL);
16245	if (dns_rdataset_isassociated(&rdataset))
16246		dns_rdataset_disassociate(&rdataset);
16247	if (result != ISC_R_NOTFOUND)
16248		goto failure;
16249
16250	result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
16251
16252 failure:
16253	if (node != NULL)
16254		dns_db_detachnode(db, &node);
16255	return (result);
16256}
16257
16258/*
16259 * Given an RRSIG rdataset and an algorithm, determine whether there
16260 * are any signatures using that algorithm.
16261 */
16262static isc_boolean_t
16263signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
16264	dns_rdata_t rdata = DNS_RDATA_INIT;
16265	dns_rdata_rrsig_t rrsig;
16266	isc_result_t result;
16267
16268	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
16269	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
16270		return (ISC_FALSE);
16271	}
16272
16273	for (result = dns_rdataset_first(rdataset);
16274	     result == ISC_R_SUCCESS;
16275	     result = dns_rdataset_next(rdataset))
16276	{
16277		dns_rdataset_current(rdataset, &rdata);
16278		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
16279		RUNTIME_CHECK(result == ISC_R_SUCCESS);
16280		dns_rdata_reset(&rdata);
16281		if (rrsig.algorithm == alg)
16282			return (ISC_TRUE);
16283	}
16284
16285	return (ISC_FALSE);
16286}
16287
16288static isc_result_t
16289add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16290	   dns_diff_t *diff)
16291{
16292	dns_name_t *origin;
16293	isc_boolean_t build_nsec3;
16294	isc_result_t result;
16295
16296	origin = dns_db_origin(db);
16297	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
16298				 &build_nsec3));
16299	if (build_nsec3)
16300		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
16301					   ISC_FALSE, zone->privatetype, diff));
16302	CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
16303
16304 failure:
16305	return (result);
16306}
16307
16308static void
16309zone_rekey(dns_zone_t *zone) {
16310	isc_result_t result;
16311	dns_db_t *db = NULL;
16312	dns_dbnode_t *node = NULL;
16313	dns_dbversion_t *ver = NULL;
16314	dns_rdataset_t soaset, soasigs, keyset, keysigs;
16315	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
16316	dns_dnsseckey_t *key;
16317	dns_diff_t diff, _sig_diff;
16318	zonediff_t zonediff;
16319	isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
16320	isc_boolean_t newalg = ISC_FALSE;
16321	isc_boolean_t fullsign;
16322	dns_ttl_t ttl = 3600;
16323	const char *dir;
16324	isc_mem_t *mctx;
16325	isc_stdtime_t now;
16326	isc_time_t timenow;
16327	isc_interval_t ival;
16328	char timebuf[80];
16329
16330	REQUIRE(DNS_ZONE_VALID(zone));
16331
16332	ISC_LIST_INIT(dnskeys);
16333	ISC_LIST_INIT(keys);
16334	ISC_LIST_INIT(rmkeys);
16335	dns_rdataset_init(&soaset);
16336	dns_rdataset_init(&soasigs);
16337	dns_rdataset_init(&keyset);
16338	dns_rdataset_init(&keysigs);
16339	dir = dns_zone_getkeydirectory(zone);
16340	mctx = zone->mctx;
16341	dns_diff_init(mctx, &diff);
16342	dns_diff_init(mctx, &_sig_diff);
16343	zonediff_init(&zonediff, &_sig_diff);
16344
16345	CHECK(dns_zone_getdb(zone, &db));
16346	CHECK(dns_db_newversion(db, &ver));
16347	CHECK(dns_db_getoriginnode(db, &node));
16348
16349	TIME_NOW(&timenow);
16350	now = isc_time_seconds(&timenow);
16351
16352	dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
16353
16354	/* Get the SOA record's TTL */
16355	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
16356				  dns_rdatatype_none, 0, &soaset, &soasigs));
16357	ttl = soaset.ttl;
16358	dns_rdataset_disassociate(&soaset);
16359
16360	/* Get the DNSKEY rdataset */
16361	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16362				     dns_rdatatype_none, 0, &keyset, &keysigs);
16363	if (result == ISC_R_SUCCESS) {
16364		ttl = keyset.ttl;
16365		CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
16366						     mctx, &keyset,
16367						     &keysigs, &soasigs,
16368						     ISC_FALSE, ISC_FALSE,
16369						     &dnskeys));
16370	} else if (result != ISC_R_NOTFOUND)
16371		goto failure;
16372
16373	/*
16374	 * True when called from "rndc sign".  Indicates the zone should be
16375	 * fully signed now.
16376	 */
16377	fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
16378
16379	result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
16380	if (result == ISC_R_SUCCESS) {
16381		isc_boolean_t check_ksk;
16382		check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16383
16384		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
16385					       &zone->origin, ttl, &diff,
16386					       ISC_TF(!check_ksk),
16387					       mctx, logmsg);
16388
16389		/* Keys couldn't be updated for some reason;
16390		 * try again later. */
16391		if (result != ISC_R_SUCCESS) {
16392			dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
16393				     "couldn't update zone keys: %s",
16394				     isc_result_totext(result));
16395			goto failure;
16396		}
16397
16398		/*
16399		 * See if any pre-existing keys have newly become active;
16400		 * also, see if any new key is for a new algorithm, as in that
16401		 * event, we need to sign the zone fully.  (If there's a new
16402		 * key, but it's for an already-existing algorithm, then
16403		 * the zone signing can be handled incrementally.)
16404		 */
16405		for (key = ISC_LIST_HEAD(dnskeys);
16406		     key != NULL;
16407		     key = ISC_LIST_NEXT(key, link)) {
16408			if (!key->first_sign)
16409				continue;
16410
16411			newactive = ISC_TRUE;
16412
16413			if (!dns_rdataset_isassociated(&keysigs)) {
16414				newalg = ISC_TRUE;
16415				break;
16416			}
16417
16418			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
16419				/*
16420				 * This isn't a new algorithm; clear
16421				 * first_sign so we won't sign the
16422				 * whole zone with this key later
16423				 */
16424				key->first_sign = ISC_FALSE;
16425			} else {
16426				newalg = ISC_TRUE;
16427				break;
16428			}
16429		}
16430
16431		if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
16432		    dnskey_sane(zone, db, ver, &diff)) {
16433			CHECK(dns_diff_apply(&diff, db, ver));
16434			CHECK(clean_nsec3param(zone, db, ver, &diff));
16435			CHECK(add_signing_records(db, zone->privatetype,
16436						  ver, &diff,
16437						  ISC_TF(newalg || fullsign)));
16438			CHECK(update_soa_serial(db, ver, &diff, mctx,
16439						zone->updatemethod));
16440			CHECK(add_chains(zone, db, ver, &diff));
16441			CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
16442			CHECK(zone_journal(zone, zonediff.diff, NULL,
16443					   "zone_rekey"));
16444			commit = ISC_TRUE;
16445		}
16446	}
16447
16448	dns_db_closeversion(db, &ver, ISC_TRUE);
16449
16450	if (commit) {
16451		dns_difftuple_t *tuple;
16452
16453		LOCK_ZONE(zone);
16454		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16455
16456		zone_needdump(zone, DNS_DUMP_DELAY);
16457
16458		zone_settimer(zone, &timenow);
16459
16460		/* Remove any signatures from removed keys.  */
16461		if (!ISC_LIST_EMPTY(rmkeys)) {
16462			for (key = ISC_LIST_HEAD(rmkeys);
16463			     key != NULL;
16464			     key = ISC_LIST_NEXT(key, link)) {
16465				result = zone_signwithkey(zone,
16466							  dst_key_alg(key->key),
16467							  dst_key_id(key->key),
16468							  ISC_TRUE);
16469				if (result != ISC_R_SUCCESS) {
16470					dns_zone_log(zone, ISC_LOG_ERROR,
16471					     "zone_signwithkey failed: %s",
16472					     dns_result_totext(result));
16473				}
16474			}
16475		}
16476
16477		if (fullsign) {
16478			/*
16479			 * "rndc sign" was called, so we now sign the zone
16480			 * with all active keys, whether they're new or not.
16481			 */
16482			for (key = ISC_LIST_HEAD(dnskeys);
16483			     key != NULL;
16484			     key = ISC_LIST_NEXT(key, link)) {
16485				if (!key->force_sign && !key->hint_sign)
16486					continue;
16487
16488				result = zone_signwithkey(zone,
16489							  dst_key_alg(key->key),
16490							  dst_key_id(key->key),
16491							  ISC_FALSE);
16492				if (result != ISC_R_SUCCESS) {
16493					dns_zone_log(zone, ISC_LOG_ERROR,
16494					     "zone_signwithkey failed: %s",
16495					     dns_result_totext(result));
16496				}
16497			}
16498		} else if (newalg) {
16499			/*
16500			 * We haven't been told to sign fully, but a new
16501			 * algorithm was added to the DNSKEY.  We sign
16502			 * the full zone, but only with newly active
16503			 * keys.
16504			 */
16505			for (key = ISC_LIST_HEAD(dnskeys);
16506			     key != NULL;
16507			     key = ISC_LIST_NEXT(key, link)) {
16508				if (!key->first_sign)
16509					continue;
16510
16511				result = zone_signwithkey(zone,
16512							  dst_key_alg(key->key),
16513							  dst_key_id(key->key),
16514							  ISC_FALSE);
16515				if (result != ISC_R_SUCCESS) {
16516					dns_zone_log(zone, ISC_LOG_ERROR,
16517					     "zone_signwithkey failed: %s",
16518					     dns_result_totext(result));
16519				}
16520			}
16521		}
16522
16523		/*
16524		 * Clear fullsign flag, if it was set, so we don't do
16525		 * another full signing next time
16526		 */
16527		zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
16528
16529		/*
16530		 * Cause the zone to add/delete NSEC3 chains for the
16531		 * deferred NSEC3PARAM changes.
16532		 */
16533		for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
16534		     tuple != NULL;
16535		     tuple = ISC_LIST_NEXT(tuple, link)) {
16536			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16537			dns_rdata_t rdata = DNS_RDATA_INIT;
16538			dns_rdata_nsec3param_t nsec3param;
16539
16540			if (tuple->rdata.type != zone->privatetype ||
16541			    tuple->op != DNS_DIFFOP_ADD)
16542				continue;
16543
16544			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
16545							buf, sizeof(buf)))
16546				continue;
16547			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
16548			RUNTIME_CHECK(result == ISC_R_SUCCESS);
16549			if (nsec3param.flags == 0)
16550				continue;
16551
16552			result = zone_addnsec3chain(zone, &nsec3param);
16553			if (result != ISC_R_SUCCESS) {
16554				dns_zone_log(zone, ISC_LOG_ERROR,
16555					     "zone_addnsec3chain failed: %s",
16556					     dns_result_totext(result));
16557			}
16558		}
16559
16560		/*
16561		 * Activate any NSEC3 chain updates that may have
16562		 * been scheduled before this rekey.
16563		 */
16564		if (fullsign || newalg)
16565			resume_addnsec3chain(zone);
16566
16567		/*
16568		 * Schedule the next resigning event
16569		 */
16570		set_resigntime(zone);
16571		UNLOCK_ZONE(zone);
16572	}
16573
16574	isc_time_settoepoch(&zone->refreshkeytime);
16575
16576	/*
16577	 * If we're doing key maintenance, set the key refresh timer to
16578	 * the next scheduled key event or to 'dnssec-loadkeys-interval'
16579	 * seconds in the future, whichever is sooner.
16580	 */
16581	if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
16582		isc_time_t timethen;
16583		isc_stdtime_t then;
16584
16585		LOCK_ZONE(zone);
16586		DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
16587				  &timethen);
16588		zone->refreshkeytime = timethen;
16589		UNLOCK_ZONE(zone);
16590
16591		for (key = ISC_LIST_HEAD(dnskeys);
16592		     key != NULL;
16593		     key = ISC_LIST_NEXT(key, link)) {
16594			then = now;
16595			result = next_keyevent(key->key, &then);
16596			if (result != ISC_R_SUCCESS)
16597				continue;
16598
16599			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
16600			LOCK_ZONE(zone);
16601			if (isc_time_compare(&timethen,
16602					     &zone->refreshkeytime) < 0) {
16603				zone->refreshkeytime = timethen;
16604			}
16605			UNLOCK_ZONE(zone);
16606		}
16607
16608		zone_settimer(zone, &timenow);
16609
16610		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
16611		dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
16612	}
16613
16614 done:
16615	dns_diff_clear(&diff);
16616	dns_diff_clear(&_sig_diff);
16617
16618	clear_keylist(&dnskeys, mctx);
16619	clear_keylist(&keys, mctx);
16620	clear_keylist(&rmkeys, mctx);
16621
16622	if (ver != NULL)
16623		dns_db_closeversion(db, &ver, ISC_FALSE);
16624	if (dns_rdataset_isassociated(&keyset))
16625		dns_rdataset_disassociate(&keyset);
16626	if (dns_rdataset_isassociated(&keysigs))
16627		dns_rdataset_disassociate(&keysigs);
16628	if (dns_rdataset_isassociated(&soasigs))
16629		dns_rdataset_disassociate(&soasigs);
16630	if (node != NULL)
16631		dns_db_detachnode(db, &node);
16632	if (db != NULL)
16633		dns_db_detach(&db);
16634	return;
16635
16636 failure:
16637	/*
16638	 * Something went wrong; try again in ten minutes or
16639	 * after a key refresh interval, whichever is shorter.
16640	 */
16641	isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
16642	isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
16643	goto done;
16644}
16645
16646void
16647dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
16648	isc_time_t now;
16649
16650	if (zone->type == dns_zone_master && zone->task != NULL) {
16651		LOCK_ZONE(zone);
16652
16653		if (fullsign)
16654			zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
16655
16656		TIME_NOW(&now);
16657		zone->refreshkeytime = now;
16658		zone_settimer(zone, &now);
16659
16660		UNLOCK_ZONE(zone);
16661	}
16662}
16663
16664isc_result_t
16665dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
16666		 unsigned int *errors)
16667{
16668	isc_result_t result;
16669	dns_dbnode_t *node = NULL;
16670
16671	REQUIRE(DNS_ZONE_VALID(zone));
16672	REQUIRE(errors != NULL);
16673
16674	result = dns_db_getoriginnode(db, &node);
16675	if (result != ISC_R_SUCCESS)
16676		return (result);
16677	result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
16678				  ISC_FALSE);
16679	dns_db_detachnode(db, &node);
16680	return (result);
16681}
16682
16683void
16684dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
16685	REQUIRE(DNS_ZONE_VALID(zone));
16686	LOCK_ZONE(zone);
16687	zone->added = added;
16688	UNLOCK_ZONE(zone);
16689}
16690
16691isc_boolean_t
16692dns_zone_getadded(dns_zone_t *zone) {
16693	REQUIRE(DNS_ZONE_VALID(zone));
16694	return (zone->added);
16695}
16696
16697isc_result_t
16698dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
16699{
16700	isc_time_t loadtime;
16701	isc_result_t result;
16702	dns_zone_t *secure = NULL;
16703
16704	TIME_NOW(&loadtime);
16705
16706	/*
16707	 * Lock hierarchy: zmgr, zone, raw.
16708	 */
16709 again:
16710	LOCK_ZONE(zone);
16711	if (inline_secure(zone))
16712		LOCK_ZONE(zone->raw);
16713	else if (inline_raw(zone)) {
16714		secure = zone->secure;
16715		TRYLOCK_ZONE(result, secure);
16716		if (result != ISC_R_SUCCESS) {
16717			UNLOCK_ZONE(zone);
16718			secure = NULL;
16719#if ISC_PLATFORM_USETHREADS
16720			isc_thread_yield();
16721#endif
16722			goto again;
16723		}
16724	}
16725	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
16726	if (inline_secure(zone))
16727		UNLOCK_ZONE(zone->raw);
16728	else if (secure != NULL)
16729		UNLOCK_ZONE(secure);
16730	UNLOCK_ZONE(zone);
16731	return result;
16732}
16733
16734isc_result_t
16735dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
16736	REQUIRE(DNS_ZONE_VALID(zone));
16737	if (interval == 0)
16738		return (ISC_R_RANGE);
16739	/* Maximum value: 24 hours (3600 minutes) */
16740	if (interval > (24 * 60))
16741		interval = (24 * 60);
16742	/* Multiply by 60 for seconds */
16743	zone->refreshkeyinterval = interval * 60;
16744	return (ISC_R_SUCCESS);
16745}
16746
16747void
16748dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) {
16749	REQUIRE(DNS_ZONE_VALID(zone));
16750	zone->requestixfr = flag;
16751}
16752
16753isc_boolean_t
16754dns_zone_getrequestixfr(dns_zone_t *zone) {
16755	REQUIRE(DNS_ZONE_VALID(zone));
16756	return (zone->requestixfr);
16757}
16758
16759void
16760dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
16761	REQUIRE(DNS_ZONE_VALID(zone));
16762	zone->updatemethod = method;
16763}
16764
16765dns_updatemethod_t
16766dns_zone_getserialupdatemethod(dns_zone_t *zone) {
16767	REQUIRE(DNS_ZONE_VALID(zone));
16768	return(zone->updatemethod);
16769}
16770
16771/*
16772 * Lock hierarchy: zmgr, zone, raw.
16773 */
16774isc_result_t
16775dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
16776	isc_result_t result;
16777	dns_zonemgr_t *zmgr;
16778
16779	REQUIRE(DNS_ZONE_VALID(zone));
16780	REQUIRE(zone->zmgr != NULL);
16781	REQUIRE(zone->task != NULL);
16782	REQUIRE(zone->loadtask != NULL);
16783	REQUIRE(zone->raw == NULL);
16784
16785	REQUIRE(DNS_ZONE_VALID(raw));
16786	REQUIRE(raw->zmgr == NULL);
16787	REQUIRE(raw->task == NULL);
16788	REQUIRE(raw->loadtask == NULL);
16789	REQUIRE(raw->secure == NULL);
16790
16791	/*
16792	 * Lock hierarchy: zmgr, zone, raw.
16793	 */
16794	zmgr = zone->zmgr;
16795	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16796	LOCK_ZONE(zone);
16797	LOCK_ZONE(raw);
16798
16799	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
16800				  NULL, NULL, zone->task, zone_timer, raw,
16801				  &raw->timer);
16802	if (result != ISC_R_SUCCESS)
16803		goto unlock;
16804
16805	/*
16806	 * The timer "holds" a iref.
16807	 */
16808	raw->irefs++;
16809	INSIST(raw->irefs != 0);
16810
16811
16812	/* dns_zone_attach(raw, &zone->raw); */
16813	isc_refcount_increment(&raw->erefs, NULL);
16814	zone->raw = raw;
16815
16816	/* dns_zone_iattach(zone,  &raw->secure); */
16817	zone_iattach(zone, &raw->secure);
16818
16819	isc_task_attach(zone->task, &raw->task);
16820	isc_task_attach(zone->loadtask, &raw->loadtask);
16821
16822	ISC_LIST_APPEND(zmgr->zones, raw, link);
16823	raw->zmgr = zmgr;
16824	zmgr->refs++;
16825
16826 unlock:
16827	UNLOCK_ZONE(raw);
16828	UNLOCK_ZONE(zone);
16829	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16830	return (result);
16831}
16832
16833void
16834dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
16835	REQUIRE(DNS_ZONE_VALID(zone));
16836	REQUIRE(raw != NULL && *raw == NULL);
16837
16838	LOCK(&zone->lock);
16839	if (zone->raw != NULL)
16840		dns_zone_attach(zone->raw, raw);
16841	UNLOCK(&zone->lock);
16842}
16843
16844struct keydone {
16845	isc_event_t event;
16846	isc_boolean_t all;
16847	unsigned char data[5];
16848};
16849
16850#define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
16851
16852static void
16853keydone(isc_task_t *task, isc_event_t *event) {
16854	const char *me = "keydone";
16855	isc_boolean_t commit = ISC_FALSE;
16856	isc_result_t result;
16857	dns_rdata_t rdata = DNS_RDATA_INIT;
16858	dns_dbversion_t *oldver = NULL, *newver = NULL;
16859	dns_zone_t *zone;
16860	dns_db_t *db = NULL;
16861	dns_dbnode_t *node = NULL;
16862	dns_rdataset_t rdataset;
16863	dns_diff_t diff;
16864	struct keydone *keydone = (struct keydone *)event;
16865	dns_update_log_t log = { update_log_cb, NULL };
16866	isc_boolean_t clear_pending = ISC_FALSE;
16867
16868	UNUSED(task);
16869
16870	zone = event->ev_arg;
16871	INSIST(DNS_ZONE_VALID(zone));
16872
16873	ENTER;
16874
16875	dns_rdataset_init(&rdataset);
16876	dns_diff_init(zone->mctx, &diff);
16877
16878	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16879	if (zone->db != NULL) {
16880		dns_db_attach(zone->db, &db);
16881		dns_db_currentversion(db, &oldver);
16882		result = dns_db_newversion(db, &newver);
16883		if (result != ISC_R_SUCCESS) {
16884			dns_zone_log(zone, ISC_LOG_ERROR,
16885				     "keydone:dns_db_newversion -> %s",
16886				     dns_result_totext(result));
16887			goto failure;
16888		}
16889	}
16890	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16891	if (db == NULL)
16892		goto failure;
16893
16894	result = dns_db_getoriginnode(db, &node);
16895	if (result != ISC_R_SUCCESS)
16896		goto failure;
16897
16898	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
16899				     dns_rdatatype_none, 0, &rdataset, NULL);
16900	if (result == ISC_R_NOTFOUND) {
16901		INSIST(!dns_rdataset_isassociated(&rdataset));
16902		goto failure;
16903	}
16904	if (result != ISC_R_SUCCESS) {
16905		INSIST(!dns_rdataset_isassociated(&rdataset));
16906		goto failure;
16907	}
16908
16909	for (result = dns_rdataset_first(&rdataset);
16910	     result == ISC_R_SUCCESS;
16911	     result = dns_rdataset_next(&rdataset)) {
16912		isc_boolean_t found = ISC_FALSE;
16913
16914		dns_rdataset_current(&rdataset, &rdata);
16915
16916		if (keydone->all) {
16917			if (rdata.length == 5 && rdata.data[0] != 0 &&
16918			       rdata.data[3] == 0 && rdata.data[4] == 1)
16919				found = ISC_TRUE;
16920			else if (rdata.data[0] == 0 &&
16921				 (rdata.data[2] & PENDINGFLAGS) != 0) {
16922				found = ISC_TRUE;
16923				clear_pending = ISC_TRUE;
16924			}
16925		} else if (rdata.length == 5 &&
16926			   memcmp(rdata.data, keydone->data, 5) == 0)
16927			found = ISC_TRUE;
16928
16929		if (found)
16930			CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
16931					    &zone->origin, rdataset.ttl,
16932					    &rdata));
16933		dns_rdata_reset(&rdata);
16934	}
16935
16936	if (!ISC_LIST_EMPTY(diff.tuples)) {
16937		/* Write changes to journal file. */
16938		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
16939					zone->updatemethod));
16940
16941		result = dns_update_signatures(&log, zone, db,
16942					       oldver, newver, &diff,
16943					       zone->sigvalidityinterval);
16944		if (!clear_pending)
16945			CHECK(result);
16946
16947		CHECK(zone_journal(zone, &diff, NULL, "keydone"));
16948		commit = ISC_TRUE;
16949
16950		LOCK_ZONE(zone);
16951		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
16952		zone_needdump(zone, 30);
16953		UNLOCK_ZONE(zone);
16954	}
16955
16956 failure:
16957	if (dns_rdataset_isassociated(&rdataset))
16958		dns_rdataset_disassociate(&rdataset);
16959	if (db != NULL) {
16960		if (node != NULL)
16961			dns_db_detachnode(db, &node);
16962		if (oldver != NULL)
16963			dns_db_closeversion(db, &oldver, ISC_FALSE);
16964		if (newver != NULL)
16965			dns_db_closeversion(db, &newver, commit);
16966		dns_db_detach(&db);
16967	}
16968	dns_diff_clear(&diff);
16969	isc_event_free(&event);
16970	dns_zone_idetach(&zone);
16971}
16972
16973isc_result_t
16974dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
16975	isc_result_t result = ISC_R_SUCCESS;
16976	isc_event_t *e;
16977	isc_buffer_t b;
16978	dns_zone_t *dummy = NULL;
16979	struct keydone *kd;
16980
16981	REQUIRE(DNS_ZONE_VALID(zone));
16982
16983	LOCK_ZONE(zone);
16984
16985	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
16986			       zone, sizeof(struct keydone));
16987	if (e == NULL) {
16988		result = ISC_R_NOMEMORY;
16989		goto failure;
16990	}
16991
16992	kd = (struct keydone *) e;
16993	if (strcasecmp(keystr, "all") == 0)
16994		kd->all = ISC_TRUE;
16995	else {
16996		isc_textregion_t r;
16997		char *algstr;
16998		dns_keytag_t keyid;
16999		dns_secalg_t alg;
17000		size_t n;
17001
17002		kd->all = ISC_FALSE;
17003
17004		n = sscanf(keystr, "%hd/", &keyid);
17005		if (n == 0U)
17006			CHECK(ISC_R_FAILURE);
17007
17008		algstr = strchr(keystr, '/');
17009		if (algstr != NULL)
17010			algstr++;
17011		else
17012			CHECK(ISC_R_FAILURE);
17013
17014		n = sscanf(algstr, "%hhd", &alg);
17015		if (n == 0U) {
17016			DE_CONST(algstr, r.base);
17017			r.length = strlen(algstr);
17018			CHECK(dns_secalg_fromtext(&alg, &r));
17019		}
17020
17021		/* construct a private-type rdata */
17022		isc_buffer_init(&b, kd->data, sizeof(kd->data));
17023		isc_buffer_putuint8(&b, alg);
17024		isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
17025		isc_buffer_putuint8(&b, (keyid & 0xff));
17026		isc_buffer_putuint8(&b, 0);
17027		isc_buffer_putuint8(&b, 1);
17028	}
17029
17030	zone_iattach(zone, &dummy);
17031	isc_task_send(zone->task, &e);
17032
17033 failure:
17034	if (e != NULL)
17035		isc_event_free(&e);
17036	UNLOCK_ZONE(zone);
17037	return (result);
17038}
17039
17040static void
17041setnsec3param(isc_task_t *task, isc_event_t *event) {
17042	const char *me = "setnsec3param";
17043	isc_boolean_t commit = ISC_FALSE;
17044	isc_result_t result;
17045	dns_dbversion_t *oldver = NULL, *newver = NULL;
17046	dns_zone_t *zone;
17047	dns_db_t *db = NULL;
17048	dns_dbnode_t *node = NULL;
17049	dns_rdataset_t prdataset, nrdataset;
17050	dns_diff_t diff;
17051	struct np3event *npe = (struct np3event *)event;
17052	nsec3param_t *np;
17053	dns_update_log_t log = { update_log_cb, NULL };
17054	dns_rdata_t rdata;
17055	isc_boolean_t nseconly;
17056	isc_boolean_t exists = ISC_FALSE;
17057
17058	UNUSED(task);
17059
17060	zone = event->ev_arg;
17061	INSIST(DNS_ZONE_VALID(zone));
17062
17063	ENTER;
17064
17065	np = &npe->params;
17066
17067	dns_rdataset_init(&prdataset);
17068	dns_rdataset_init(&nrdataset);
17069	dns_diff_init(zone->mctx, &diff);
17070
17071	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17072	if (zone->db != NULL) {
17073		dns_db_attach(zone->db, &db);
17074		dns_db_currentversion(db, &oldver);
17075		result = dns_db_newversion(db, &newver);
17076		if (result != ISC_R_SUCCESS) {
17077			dns_zone_log(zone, ISC_LOG_ERROR,
17078				     "setnsec3param:dns_db_newversion -> %s",
17079				     dns_result_totext(result));
17080			goto failure;
17081		}
17082	}
17083	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17084	if (db == NULL)
17085		goto failure;
17086
17087	CHECK(dns_db_getoriginnode(db, &node));
17088
17089	/*
17090	 * Does a private-type record already exist for this chain?
17091	 */
17092	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
17093				     dns_rdatatype_none, 0, &prdataset, NULL);
17094	if (result == ISC_R_SUCCESS) {
17095		for (result = dns_rdataset_first(&prdataset);
17096		     result == ISC_R_SUCCESS;
17097		     result = dns_rdataset_next(&prdataset)) {
17098			dns_rdata_init(&rdata);
17099			dns_rdataset_current(&prdataset, &rdata);
17100
17101			if (np->length == rdata.length &&
17102			    memcmp(rdata.data, np->data, np->length) == 0) {
17103				exists = ISC_TRUE;
17104				break;
17105			}
17106		}
17107	} else if (result != ISC_R_NOTFOUND) {
17108		INSIST(!dns_rdataset_isassociated(&prdataset));
17109		goto failure;
17110	}
17111
17112	/*
17113	 * Does the chain already exist?
17114	 */
17115	result = dns_db_findrdataset(db, node, newver,
17116				     dns_rdatatype_nsec3param,
17117				     dns_rdatatype_none, 0, &nrdataset, NULL);
17118	if (result == ISC_R_SUCCESS) {
17119		for (result = dns_rdataset_first(&nrdataset);
17120		     result == ISC_R_SUCCESS;
17121		     result = dns_rdataset_next(&nrdataset)) {
17122			dns_rdata_init(&rdata);
17123			dns_rdataset_current(&nrdataset, &rdata);
17124
17125			if (np->length == (rdata.length + 1) &&
17126			    memcmp(rdata.data, np->data + 1,
17127				   np->length - 1) == 0)
17128			{
17129				exists = ISC_TRUE;
17130				break;
17131			}
17132		}
17133	} else if (result != ISC_R_NOTFOUND) {
17134		INSIST(!dns_rdataset_isassociated(&nrdataset));
17135		goto failure;
17136	}
17137
17138
17139	/*
17140	 * We need to remove any existing NSEC3 chains.
17141	 */
17142	if (!exists && np->replace && (np->length != 0 || np->nsec))
17143		CHECK(dns_nsec3param_deletechains(db, newver, zone,
17144						  !np->nsec, &diff));
17145
17146	if (!exists && np->length != 0) {
17147		/*
17148		 * We're creating an NSEC3 chain.
17149		 *
17150		 * If the zone is not currently capable of supporting
17151		 * an NSEC3 chain, add the INITIAL flag, so these
17152		 * parameters can be used later when NSEC3 becomes
17153		 * available.
17154		 */
17155		dns_rdata_init(&rdata);
17156
17157		np->data[2] |= DNS_NSEC3FLAG_CREATE;
17158		result = dns_nsec_nseconly(db, newver, &nseconly);
17159		if (result == ISC_R_NOTFOUND || nseconly)
17160			np->data[2] |= DNS_NSEC3FLAG_INITIAL;
17161
17162		rdata.length = np->length;
17163		rdata.data = np->data;
17164		rdata.type = zone->privatetype;
17165		rdata.rdclass = zone->rdclass;
17166		CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
17167				    &zone->origin, 0, &rdata));
17168	}
17169
17170	if (!ISC_LIST_EMPTY(diff.tuples)) {
17171		/* Write changes to journal file. */
17172		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
17173					zone->updatemethod));
17174		result = dns_update_signatures(&log, zone, db,
17175					       oldver, newver, &diff,
17176					       zone->sigvalidityinterval);
17177		if (result != ISC_R_NOTFOUND)
17178			CHECK(result);
17179		CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
17180		commit = ISC_TRUE;
17181
17182		LOCK_ZONE(zone);
17183		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
17184		zone_needdump(zone, 30);
17185		UNLOCK_ZONE(zone);
17186	}
17187
17188 failure:
17189	if (dns_rdataset_isassociated(&prdataset))
17190		dns_rdataset_disassociate(&prdataset);
17191	if (dns_rdataset_isassociated(&nrdataset))
17192		dns_rdataset_disassociate(&nrdataset);
17193	if (node != NULL)
17194		dns_db_detachnode(db, &node);
17195	if (oldver != NULL)
17196		dns_db_closeversion(db, &oldver, ISC_FALSE);
17197	if (newver != NULL)
17198		dns_db_closeversion(db, &newver, commit);
17199	if (db != NULL)
17200		dns_db_detach(&db);
17201	if (commit)
17202		resume_addnsec3chain(zone);
17203	dns_diff_clear(&diff);
17204	isc_event_free(&event);
17205	dns_zone_idetach(&zone);
17206}
17207
17208isc_result_t
17209dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
17210		       isc_uint16_t iter, isc_uint8_t saltlen,
17211		       unsigned char *salt, isc_boolean_t replace)
17212{
17213	isc_result_t result = ISC_R_SUCCESS;
17214	dns_rdata_nsec3param_t param;
17215	dns_rdata_t nrdata = DNS_RDATA_INIT;
17216	dns_rdata_t prdata = DNS_RDATA_INIT;
17217	unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
17218	struct np3event *npe;
17219	nsec3param_t *np;
17220	dns_zone_t *dummy = NULL;
17221	isc_buffer_t b;
17222	isc_event_t *e;
17223
17224	REQUIRE(DNS_ZONE_VALID(zone));
17225	REQUIRE(salt != NULL);
17226
17227	LOCK_ZONE(zone);
17228
17229	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
17230			       setnsec3param, zone, sizeof(struct np3event));
17231	if (e == NULL) {
17232		result = ISC_R_NOMEMORY;
17233		goto failure;
17234	}
17235
17236	npe = (struct np3event *) e;
17237	np = &npe->params;
17238
17239	np->replace = replace;
17240	if (hash == 0) {
17241		np->length = 0;
17242		np->nsec = ISC_TRUE;
17243	} else {
17244		param.common.rdclass = zone->rdclass;
17245		param.common.rdtype = dns_rdatatype_nsec3param;
17246		ISC_LINK_INIT(&param.common, link);
17247		param.mctx = NULL;
17248		param.hash = hash;
17249		param.flags = flags;
17250		param.iterations = iter;
17251		param.salt_length = saltlen;
17252		param.salt = salt;
17253		isc_buffer_init(&b, nbuf, sizeof(nbuf));
17254		CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
17255					   dns_rdatatype_nsec3param,
17256					   &param, &b));
17257		dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
17258					 np->data, sizeof(np->data));
17259		np->length = prdata.length;
17260	}
17261
17262	zone_iattach(zone, &dummy);
17263	isc_task_send(zone->task, &e);
17264
17265 failure:
17266	if (e != NULL)
17267		isc_event_free(&e);
17268	UNLOCK_ZONE(zone);
17269	return (result);
17270}
17271
17272void
17273dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
17274	REQUIRE(DNS_ZONE_VALID(zone));
17275
17276	zone->statlevel = level;
17277}
17278
17279dns_zonestat_level_t
17280dns_zone_getstatlevel(dns_zone_t *zone) {
17281	REQUIRE(DNS_ZONE_VALID(zone));
17282
17283	return (zone->statlevel);
17284}
17285