1/*
2 * Copyright (C) 2004-2012  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/mutex.h>
27#include <isc/print.h>
28#include <isc/random.h>
29#include <isc/ratelimiter.h>
30#include <isc/refcount.h>
31#include <isc/rwlock.h>
32#include <isc/serial.h>
33#include <isc/strerror.h>
34#include <isc/stats.h>
35#include <isc/stdtime.h>
36#include <isc/string.h>
37#include <isc/taskpool.h>
38#include <isc/timer.h>
39#include <isc/util.h>
40
41#include <dns/acache.h>
42#include <dns/acl.h>
43#include <dns/adb.h>
44#include <dns/callbacks.h>
45#include <dns/db.h>
46#include <dns/dbiterator.h>
47#include <dns/dnssec.h>
48#include <dns/events.h>
49#include <dns/journal.h>
50#include <dns/keydata.h>
51#include <dns/keytable.h>
52#include <dns/keyvalues.h>
53#include <dns/log.h>
54#include <dns/master.h>
55#include <dns/masterdump.h>
56#include <dns/message.h>
57#include <dns/name.h>
58#include <dns/nsec.h>
59#include <dns/nsec3.h>
60#include <dns/peer.h>
61#include <dns/private.h>
62#include <dns/rbt.h>
63#include <dns/rcode.h>
64#include <dns/rdataclass.h>
65#include <dns/rdatalist.h>
66#include <dns/rdataset.h>
67#include <dns/rdatasetiter.h>
68#include <dns/rdatastruct.h>
69#include <dns/rdatatype.h>
70#include <dns/request.h>
71#include <dns/resolver.h>
72#include <dns/result.h>
73#include <dns/rriterator.h>
74#include <dns/soa.h>
75#include <dns/ssu.h>
76#include <dns/stats.h>
77#include <dns/time.h>
78#include <dns/tsig.h>
79#include <dns/xfrin.h>
80#include <dns/zone.h>
81
82#include <dst/dst.h>
83
84#define ZONE_MAGIC			ISC_MAGIC('Z', 'O', 'N', 'E')
85#define DNS_ZONE_VALID(zone)		ISC_MAGIC_VALID(zone, ZONE_MAGIC)
86
87#define NOTIFY_MAGIC			ISC_MAGIC('N', 't', 'f', 'y')
88#define DNS_NOTIFY_VALID(notify)	ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
89
90#define STUB_MAGIC			ISC_MAGIC('S', 't', 'u', 'b')
91#define DNS_STUB_VALID(stub)		ISC_MAGIC_VALID(stub, STUB_MAGIC)
92
93#define ZONEMGR_MAGIC			ISC_MAGIC('Z', 'm', 'g', 'r')
94#define DNS_ZONEMGR_VALID(stub)		ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
95
96#define LOAD_MAGIC			ISC_MAGIC('L', 'o', 'a', 'd')
97#define DNS_LOAD_VALID(load)		ISC_MAGIC_VALID(load, LOAD_MAGIC)
98
99#define FORWARD_MAGIC			ISC_MAGIC('F', 'o', 'r', 'w')
100#define DNS_FORWARD_VALID(load)		ISC_MAGIC_VALID(load, FORWARD_MAGIC)
101
102#define IO_MAGIC			ISC_MAGIC('Z', 'm', 'I', 'O')
103#define DNS_IO_VALID(load)		ISC_MAGIC_VALID(load, IO_MAGIC)
104
105/*%
106 * Ensure 'a' is at least 'min' but not more than 'max'.
107 */
108#define RANGE(a, min, max) \
109		(((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
110
111#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
112
113/*%
114 * Key flags
115 */
116#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
117#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
118#define ALG(x) dst_key_alg(x)
119
120/*
121 * Default values.
122 */
123#define DNS_DEFAULT_IDLEIN 3600		/*%< 1 hour */
124#define DNS_DEFAULT_IDLEOUT 3600	/*%< 1 hour */
125#define MAX_XFER_TIME (2*3600)		/*%< Documented default is 2 hours */
126#define RESIGN_DELAY 3600		/*%< 1 hour */
127
128#ifndef DNS_MAX_EXPIRE
129#define DNS_MAX_EXPIRE	14515200	/*%< 24 weeks */
130#endif
131
132#ifndef DNS_DUMP_DELAY
133#define DNS_DUMP_DELAY 900		/*%< 15 minutes */
134#endif
135
136typedef struct dns_notify dns_notify_t;
137typedef struct dns_stub dns_stub_t;
138typedef struct dns_load dns_load_t;
139typedef struct dns_forward dns_forward_t;
140typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
141typedef struct dns_io dns_io_t;
142typedef ISC_LIST(dns_io_t) dns_iolist_t;
143typedef struct dns_signing dns_signing_t;
144typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
145typedef struct dns_nsec3chain dns_nsec3chain_t;
146typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
147typedef struct dns_keyfetch dns_keyfetch_t;
148
149#define DNS_ZONE_CHECKLOCK
150#ifdef DNS_ZONE_CHECKLOCK
151#define LOCK_ZONE(z) \
152	 do { LOCK(&(z)->lock); \
153	      INSIST((z)->locked == ISC_FALSE); \
154	     (z)->locked = ISC_TRUE; \
155		} while (0)
156#define UNLOCK_ZONE(z) \
157	do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
158#define LOCKED_ZONE(z) ((z)->locked)
159#else
160#define LOCK_ZONE(z) LOCK(&(z)->lock)
161#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
162#define LOCKED_ZONE(z) ISC_TRUE
163#endif
164
165#ifdef ISC_RWLOCK_USEATOMIC
166#define ZONEDB_INITLOCK(l)	isc_rwlock_init((l), 0, 0)
167#define ZONEDB_DESTROYLOCK(l)	isc_rwlock_destroy(l)
168#define ZONEDB_LOCK(l, t)	RWLOCK((l), (t))
169#define ZONEDB_UNLOCK(l, t)	RWUNLOCK((l), (t))
170#else
171#define ZONEDB_INITLOCK(l)	isc_mutex_init(l)
172#define ZONEDB_DESTROYLOCK(l)	DESTROYLOCK(l)
173#define ZONEDB_LOCK(l, t)	LOCK(l)
174#define ZONEDB_UNLOCK(l, t)	UNLOCK(l)
175#endif
176
177struct dns_zone {
178	/* Unlocked */
179	unsigned int		magic;
180	isc_mutex_t		lock;
181#ifdef DNS_ZONE_CHECKLOCK
182	isc_boolean_t		locked;
183#endif
184	isc_mem_t		*mctx;
185	isc_refcount_t		erefs;
186
187#ifdef ISC_RWLOCK_USEATOMIC
188	isc_rwlock_t		dblock;
189#else
190	isc_mutex_t		dblock;
191#endif
192	dns_db_t		*db;		/* Locked by dblock */
193
194	/* Locked */
195	dns_zonemgr_t		*zmgr;
196	ISC_LINK(dns_zone_t)	link;		/* Used by zmgr. */
197	isc_timer_t		*timer;
198	unsigned int		irefs;
199	dns_name_t		origin;
200	char			*masterfile;
201	dns_masterformat_t	masterformat;
202	char			*journal;
203	isc_int32_t		journalsize;
204	dns_rdataclass_t	rdclass;
205	dns_zonetype_t		type;
206	unsigned int		flags;
207	unsigned int		options;
208	unsigned int		db_argc;
209	char			**db_argv;
210	isc_time_t		expiretime;
211	isc_time_t		refreshtime;
212	isc_time_t		dumptime;
213	isc_time_t		loadtime;
214	isc_time_t		notifytime;
215	isc_time_t		resigntime;
216	isc_time_t		keywarntime;
217	isc_time_t		signingtime;
218	isc_time_t		nsec3chaintime;
219	isc_time_t		refreshkeytime;
220	isc_uint32_t		refreshkeycount;
221	isc_uint32_t		refresh;
222	isc_uint32_t		retry;
223	isc_uint32_t		expire;
224	isc_uint32_t		minimum;
225	isc_stdtime_t		key_expiry;
226	isc_stdtime_t		log_key_expired_timer;
227	char			*keydirectory;
228
229	isc_uint32_t		maxrefresh;
230	isc_uint32_t		minrefresh;
231	isc_uint32_t		maxretry;
232	isc_uint32_t		minretry;
233
234	isc_sockaddr_t		*masters;
235	dns_name_t		**masterkeynames;
236	isc_boolean_t		*mastersok;
237	unsigned int		masterscnt;
238	unsigned int		curmaster;
239	isc_sockaddr_t		masteraddr;
240	dns_notifytype_t	notifytype;
241	isc_sockaddr_t		*notify;
242	unsigned int		notifycnt;
243	isc_sockaddr_t		notifyfrom;
244	isc_task_t		*task;
245	isc_sockaddr_t		notifysrc4;
246	isc_sockaddr_t		notifysrc6;
247	isc_sockaddr_t		xfrsource4;
248	isc_sockaddr_t		xfrsource6;
249	isc_sockaddr_t		altxfrsource4;
250	isc_sockaddr_t		altxfrsource6;
251	isc_sockaddr_t		sourceaddr;
252	dns_xfrin_ctx_t		*xfr;		/* task locked */
253	dns_tsigkey_t		*tsigkey;	/* key used for xfr */
254	/* Access Control Lists */
255	dns_acl_t		*update_acl;
256	dns_acl_t		*forward_acl;
257	dns_acl_t		*notify_acl;
258	dns_acl_t		*query_acl;
259	dns_acl_t		*queryon_acl;
260	dns_acl_t		*xfr_acl;
261	isc_boolean_t		update_disabled;
262	isc_boolean_t		zero_no_soa_ttl;
263	dns_severity_t		check_names;
264	ISC_LIST(dns_notify_t)	notifies;
265	dns_request_t		*request;
266	dns_loadctx_t		*lctx;
267	dns_io_t		*readio;
268	dns_dumpctx_t		*dctx;
269	dns_io_t		*writeio;
270	isc_uint32_t		maxxfrin;
271	isc_uint32_t		maxxfrout;
272	isc_uint32_t		idlein;
273	isc_uint32_t		idleout;
274	isc_event_t		ctlevent;
275	dns_ssutable_t		*ssutable;
276	isc_uint32_t		sigvalidityinterval;
277	isc_uint32_t		sigresigninginterval;
278	dns_view_t		*view;
279	dns_acache_t		*acache;
280	dns_checkmxfunc_t	checkmx;
281	dns_checksrvfunc_t	checksrv;
282	dns_checknsfunc_t	checkns;
283	/*%
284	 * Zones in certain states such as "waiting for zone transfer"
285	 * or "zone transfer in progress" are kept on per-state linked lists
286	 * in the zone manager using the 'statelink' field.  The 'statelist'
287	 * field points at the list the zone is currently on.  It the zone
288	 * is not on any such list, statelist is NULL.
289	 */
290	ISC_LINK(dns_zone_t)	statelink;
291	dns_zonelist_t		*statelist;
292	/*%
293	 * Statistics counters about zone management.
294	 */
295	isc_stats_t		*stats;
296	/*%
297	 * Optional per-zone statistics counters.  Counted outside of this
298	 * module.
299	 */
300	isc_boolean_t		requeststats_on;
301	isc_stats_t		*requeststats;
302	isc_uint32_t		notifydelay;
303	dns_isselffunc_t	isself;
304	void			*isselfarg;
305
306	char *			strnamerd;
307	char *			strname;
308	char *			strrdclass;
309	char *			strviewname;
310
311	/*%
312	 * Serial number for deferred journal compaction.
313	 */
314	isc_uint32_t		compact_serial;
315	/*%
316	 * Keys that are signing the zone for the first time.
317	 */
318	dns_signinglist_t	signing;
319	dns_nsec3chainlist_t	nsec3chain;
320	/*%
321	 * Signing / re-signing quantum stopping parameters.
322	 */
323	isc_uint32_t		signatures;
324	isc_uint32_t		nodes;
325	dns_rdatatype_t		privatetype;
326
327	/*%
328	 * Autosigning/key-maintenance options
329	 */
330	isc_uint32_t		keyopts;
331
332	/*%
333	 * True if added by "rndc addzone"
334	 */
335	isc_boolean_t           added;
336
337	/*%
338	 * whether a rpz radix was needed when last loaded
339	 */
340	isc_boolean_t           rpz_zone;
341
342	/*%
343	 * Outstanding forwarded UPDATE requests.
344	 */
345	dns_forwardlist_t	forwards;
346};
347
348#define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
349#define DNS_ZONE_SETFLAG(z,f) do { \
350		INSIST(LOCKED_ZONE(z)); \
351		(z)->flags |= (f); \
352		} while (0)
353#define DNS_ZONE_CLRFLAG(z,f) do { \
354		INSIST(LOCKED_ZONE(z)); \
355		(z)->flags &= ~(f); \
356		} while (0)
357	/* XXX MPA these may need to go back into zone.h */
358#define DNS_ZONEFLG_REFRESH	0x00000001U	/*%< refresh check in progress */
359#define DNS_ZONEFLG_NEEDDUMP	0x00000002U	/*%< zone need consolidation */
360#define DNS_ZONEFLG_USEVC	0x00000004U	/*%< use tcp for refresh query */
361#define DNS_ZONEFLG_DUMPING	0x00000008U	/*%< a dump is in progress */
362#define DNS_ZONEFLG_HASINCLUDE	0x00000010U	/*%< $INCLUDE in zone file */
363#define DNS_ZONEFLG_LOADED	0x00000020U	/*%< database has loaded */
364#define DNS_ZONEFLG_EXITING	0x00000040U	/*%< zone is being destroyed */
365#define DNS_ZONEFLG_EXPIRED	0x00000080U	/*%< zone has expired */
366#define DNS_ZONEFLG_NEEDREFRESH	0x00000100U	/*%< refresh check needed */
367#define DNS_ZONEFLG_UPTODATE	0x00000200U	/*%< zone contents are
368						 * uptodate */
369#define DNS_ZONEFLG_NEEDNOTIFY	0x00000400U	/*%< need to send out notify
370						 * messages */
371#define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U	/*%< generate a journal diff on
372						 * reload */
373#define DNS_ZONEFLG_NOMASTERS	0x00001000U	/*%< an attempt to refresh a
374						 * zone with no masters
375						 * occurred */
376#define DNS_ZONEFLG_LOADING	0x00002000U	/*%< load from disk in progress*/
377#define DNS_ZONEFLG_HAVETIMERS	0x00004000U	/*%< timer values have been set
378						 * from SOA (if not set, we
379						 * are still using
380						 * default timer values) */
381#define DNS_ZONEFLG_FORCEXFER	0x00008000U	/*%< Force a zone xfer */
382#define DNS_ZONEFLG_NOREFRESH	0x00010000U
383#define DNS_ZONEFLG_DIALNOTIFY	0x00020000U
384#define DNS_ZONEFLG_DIALREFRESH	0x00040000U
385#define DNS_ZONEFLG_SHUTDOWN	0x00080000U
386#define DNS_ZONEFLAG_NOIXFR	0x00100000U	/*%< IXFR failed, force AXFR */
387#define DNS_ZONEFLG_FLUSH	0x00200000U
388#define DNS_ZONEFLG_NOEDNS	0x00400000U
389#define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
390#define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
391#define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
392#define DNS_ZONEFLG_REFRESHING	0x04000000U	/*%< Refreshing keydata */
393#define DNS_ZONEFLG_THAW	0x08000000U
394/* #define DNS_ZONEFLG_XXXXX	0x10000000U   XXXMPA unused. */
395#define DNS_ZONEFLG_NODELAY	0x20000000U
396
397#define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
398#define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
399
400/* Flags for zone_load() */
401#define DNS_ZONELOADFLAG_NOSTAT	0x00000001U	/* Do not stat() master files */
402#define DNS_ZONELOADFLAG_THAW	0x00000002U	/* Thaw the zone on successful
403						   load. */
404
405#define UNREACH_CHACHE_SIZE	10U
406#define UNREACH_HOLD_TIME	600	/* 10 minutes */
407
408#define CHECK(op) \
409	do { result = (op); \
410		if (result != ISC_R_SUCCESS) goto failure; \
411	} while (0)
412
413struct dns_unreachable {
414	isc_sockaddr_t	remote;
415	isc_sockaddr_t	local;
416	isc_uint32_t	expire;
417	isc_uint32_t	last;
418};
419
420struct dns_zonemgr {
421	unsigned int		magic;
422	isc_mem_t *		mctx;
423	int			refs;		/* Locked by rwlock */
424	isc_taskmgr_t *		taskmgr;
425	isc_timermgr_t *	timermgr;
426	isc_socketmgr_t *	socketmgr;
427	isc_taskpool_t *	zonetasks;
428	isc_task_t *		task;
429	isc_ratelimiter_t *	rl;
430	isc_rwlock_t		rwlock;
431	isc_mutex_t		iolock;
432	isc_rwlock_t		urlock;
433
434	/* Locked by rwlock. */
435	dns_zonelist_t		zones;
436	dns_zonelist_t		waiting_for_xfrin;
437	dns_zonelist_t		xfrin_in_progress;
438
439	/* Configuration data. */
440	isc_uint32_t		transfersin;
441	isc_uint32_t		transfersperns;
442	unsigned int		serialqueryrate;
443
444	/* Locked by iolock */
445	isc_uint32_t		iolimit;
446	isc_uint32_t		ioactive;
447	dns_iolist_t		high;
448	dns_iolist_t		low;
449
450	/* Locked by urlock. */
451	/* LRU cache */
452	struct dns_unreachable	unreachable[UNREACH_CHACHE_SIZE];
453};
454
455/*%
456 * Hold notify state.
457 */
458struct dns_notify {
459	unsigned int		magic;
460	unsigned int		flags;
461	isc_mem_t		*mctx;
462	dns_zone_t		*zone;
463	dns_adbfind_t		*find;
464	dns_request_t		*request;
465	dns_name_t		ns;
466	isc_sockaddr_t		dst;
467	ISC_LINK(dns_notify_t)	link;
468};
469
470#define DNS_NOTIFY_NOSOA	0x0001U
471
472/*%
473 *	dns_stub holds state while performing a 'stub' transfer.
474 *	'db' is the zone's 'db' or a new one if this is the initial
475 *	transfer.
476 */
477
478struct dns_stub {
479	unsigned int		magic;
480	isc_mem_t		*mctx;
481	dns_zone_t		*zone;
482	dns_db_t		*db;
483	dns_dbversion_t		*version;
484};
485
486/*%
487 *	Hold load state.
488 */
489struct dns_load {
490	unsigned int		magic;
491	isc_mem_t		*mctx;
492	dns_zone_t		*zone;
493	dns_db_t		*db;
494	isc_time_t		loadtime;
495	dns_rdatacallbacks_t	callbacks;
496};
497
498/*%
499 *	Hold forward state.
500 */
501struct dns_forward {
502	unsigned int		magic;
503	isc_mem_t		*mctx;
504	dns_zone_t		*zone;
505	isc_buffer_t		*msgbuf;
506	dns_request_t		*request;
507	isc_uint32_t		which;
508	isc_sockaddr_t		addr;
509	dns_updatecallback_t	callback;
510	void			*callback_arg;
511	ISC_LINK(dns_forward_t)	link;
512};
513
514/*%
515 *	Hold IO request state.
516 */
517struct dns_io {
518	unsigned int	magic;
519	dns_zonemgr_t	*zmgr;
520	isc_boolean_t	high;
521	isc_task_t	*task;
522	ISC_LINK(dns_io_t) link;
523	isc_event_t	*event;
524};
525
526/*%
527 *	Hold state for when we are signing a zone with a new
528 *	DNSKEY as result of an update.
529 */
530struct dns_signing {
531	unsigned int		magic;
532	dns_db_t		*db;
533	dns_dbiterator_t	*dbiterator;
534	dns_secalg_t		algorithm;
535	isc_uint16_t		keyid;
536	isc_boolean_t		delete;
537	isc_boolean_t		done;
538	ISC_LINK(dns_signing_t)	link;
539};
540
541struct dns_nsec3chain {
542	unsigned int			magic;
543	dns_db_t			*db;
544	dns_dbiterator_t		*dbiterator;
545	dns_rdata_nsec3param_t		nsec3param;
546	unsigned char			salt[255];
547	isc_boolean_t			done;
548	isc_boolean_t			seen_nsec;
549	isc_boolean_t			delete_nsec;
550	isc_boolean_t			save_delete_nsec;
551	ISC_LINK(dns_nsec3chain_t)	link;
552};
553/*%<
554 * 'dbiterator' contains a iterator for the database.  If we are creating
555 * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
556 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
557 * iterated.
558 *
559 * 'nsec3param' contains the parameters of the NSEC3 chain being created
560 * or removed.
561 *
562 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
563 *
564 * 'seen_nsec' will be set to true if, while iterating the zone to create a
565 * NSEC3 chain, a NSEC record is seen.
566 *
567 * 'delete_nsec' will be set to true if, at the completion of the creation
568 * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
569 * are in the process of deleting the NSEC chain.
570 *
571 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
572 * so it can be recovered in the event of a error.
573 */
574
575struct dns_keyfetch {
576	dns_fixedname_t name;
577	dns_rdataset_t keydataset;
578	dns_rdataset_t dnskeyset;
579	dns_rdataset_t dnskeysigset;
580	dns_zone_t *zone;
581	dns_db_t *db;
582	dns_fetch_t *fetch;
583};
584
585#define HOUR 3600
586#define DAY (24*HOUR)
587#define MONTH (30*DAY)
588
589#define SEND_BUFFER_SIZE 2048
590
591static void zone_settimer(dns_zone_t *, isc_time_t *);
592static void cancel_refresh(dns_zone_t *);
593static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
594			  const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
595static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
596     ISC_FORMAT_PRINTF(3, 4);
597static void queue_xfrin(dns_zone_t *zone);
598static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
599				  dns_diff_t *diff, dns_diffop_t op,
600				  dns_name_t *name, dns_ttl_t ttl,
601				  dns_rdata_t *rdata);
602static void zone_unload(dns_zone_t *zone);
603static void zone_expire(dns_zone_t *zone);
604static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
605static void zone_idetach(dns_zone_t **zonep);
606static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
607				   isc_boolean_t dump);
608static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
609static inline void zone_detachdb(dns_zone_t *zone);
610static isc_result_t default_journal(dns_zone_t *zone);
611static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
612static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
613				  isc_time_t loadtime, isc_result_t result);
614static void zone_needdump(dns_zone_t *zone, unsigned int delay);
615static void zone_shutdown(isc_task_t *, isc_event_t *);
616static void zone_loaddone(void *arg, isc_result_t result);
617static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
618				   isc_time_t loadtime);
619static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
620static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
621static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
622static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
623
624#if 0
625/* ondestroy example */
626static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
627#endif
628
629static void refresh_callback(isc_task_t *, isc_event_t *);
630static void stub_callback(isc_task_t *, isc_event_t *);
631static void queue_soa_query(dns_zone_t *zone);
632static void soa_query(isc_task_t *, isc_event_t *);
633static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
634		     dns_stub_t *stub);
635static int message_count(dns_message_t *msg, dns_section_t section,
636			 dns_rdatatype_t type);
637static void notify_cancel(dns_zone_t *zone);
638static void notify_find_address(dns_notify_t *notify);
639static void notify_send(dns_notify_t *notify);
640static isc_result_t notify_createmessage(dns_zone_t *zone,
641					 unsigned int flags,
642					 dns_message_t **messagep);
643static void notify_done(isc_task_t *task, isc_event_t *event);
644static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
645static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
646static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
647static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
648					     dns_zone_t *zone);
649static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
650static void zonemgr_free(dns_zonemgr_t *zmgr);
651static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
652				  isc_task_t *task, isc_taskaction_t action,
653				  void *arg, dns_io_t **iop);
654static void zonemgr_putio(dns_io_t **iop);
655static void zonemgr_cancelio(dns_io_t *io);
656
657static isc_result_t
658zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
659		 unsigned int *soacount, isc_uint32_t *serial,
660		 isc_uint32_t *refresh, isc_uint32_t *retry,
661		 isc_uint32_t *expire, isc_uint32_t *minimum,
662		 unsigned int *errors);
663
664static void zone_freedbargs(dns_zone_t *zone);
665static void forward_callback(isc_task_t *task, isc_event_t *event);
666static void zone_saveunique(dns_zone_t *zone, const char *path,
667			    const char *templat);
668static void zone_maintenance(dns_zone_t *zone);
669static void zone_notify(dns_zone_t *zone, isc_time_t *now);
670static void dump_done(void *arg, isc_result_t result);
671static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
672				     isc_uint16_t keyid, isc_boolean_t delete);
673static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
674				dns_dbnode_t *node, dns_name_t *name,
675				dns_diff_t *diff);
676static void zone_rekey(dns_zone_t *zone);
677static isc_boolean_t delsig_ok(dns_rdata_rrsig_t *rrsig_ptr,
678			       dst_key_t **keys, unsigned int nkeys);
679
680#define ENTER zone_debuglog(zone, me, 1, "enter")
681
682static const unsigned int dbargc_default = 1;
683static const char *dbargv_default[] = { "rbt" };
684
685#define DNS_ZONE_JITTER_ADD(a, b, c) \
686	do { \
687		isc_interval_t _i; \
688		isc_uint32_t _j; \
689		_j = isc_random_jitter((b), (b)/4); \
690		isc_interval_set(&_i, _j, 0); \
691		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
692			dns_zone_log(zone, ISC_LOG_WARNING, \
693				     "epoch approaching: upgrade required: " \
694				     "now + %s failed", #b); \
695			isc_interval_set(&_i, _j/2, 0); \
696			(void)isc_time_add((a), &_i, (c)); \
697		} \
698	} while (0)
699
700#define DNS_ZONE_TIME_ADD(a, b, c) \
701	do { \
702		isc_interval_t _i; \
703		isc_interval_set(&_i, (b), 0); \
704		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
705			dns_zone_log(zone, ISC_LOG_WARNING, \
706				     "epoch approaching: upgrade required: " \
707				     "now + %s failed", #b); \
708			isc_interval_set(&_i, (b)/2, 0); \
709			(void)isc_time_add((a), &_i, (c)); \
710		} \
711	} while (0)
712
713/*%
714 * Increment resolver-related statistics counters.  Zone must be locked.
715 */
716static inline void
717inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
718	if (zone->stats != NULL)
719		isc_stats_increment(zone->stats, counter);
720}
721
722/***
723 ***	Public functions.
724 ***/
725
726isc_result_t
727dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
728	isc_result_t result;
729	dns_zone_t *zone;
730	isc_time_t now;
731
732	REQUIRE(zonep != NULL && *zonep == NULL);
733	REQUIRE(mctx != NULL);
734
735	TIME_NOW(&now);
736	zone = isc_mem_get(mctx, sizeof(*zone));
737	if (zone == NULL)
738		return (ISC_R_NOMEMORY);
739
740	zone->mctx = NULL;
741	isc_mem_attach(mctx, &zone->mctx);
742
743	result = isc_mutex_init(&zone->lock);
744	if (result != ISC_R_SUCCESS)
745		goto free_zone;
746
747	result = ZONEDB_INITLOCK(&zone->dblock);
748	if (result != ISC_R_SUCCESS)
749		goto free_mutex;
750
751	/* XXX MPA check that all elements are initialised */
752#ifdef DNS_ZONE_CHECKLOCK
753	zone->locked = ISC_FALSE;
754#endif
755	zone->db = NULL;
756	zone->zmgr = NULL;
757	ISC_LINK_INIT(zone, link);
758	result = isc_refcount_init(&zone->erefs, 1);	/* Implicit attach. */
759	if (result != ISC_R_SUCCESS)
760		goto free_dblock;
761	zone->irefs = 0;
762	dns_name_init(&zone->origin, NULL);
763	zone->strnamerd = NULL;
764	zone->strname = NULL;
765	zone->strrdclass = NULL;
766	zone->strviewname = NULL;
767	zone->masterfile = NULL;
768	zone->masterformat = dns_masterformat_none;
769	zone->keydirectory = NULL;
770	zone->journalsize = -1;
771	zone->journal = NULL;
772	zone->rdclass = dns_rdataclass_none;
773	zone->type = dns_zone_none;
774	zone->flags = 0;
775	zone->options = 0;
776	zone->keyopts = 0;
777	zone->db_argc = 0;
778	zone->db_argv = NULL;
779	isc_time_settoepoch(&zone->expiretime);
780	isc_time_settoepoch(&zone->refreshtime);
781	isc_time_settoepoch(&zone->dumptime);
782	isc_time_settoepoch(&zone->loadtime);
783	zone->notifytime = now;
784	isc_time_settoepoch(&zone->resigntime);
785	isc_time_settoepoch(&zone->keywarntime);
786	isc_time_settoepoch(&zone->signingtime);
787	isc_time_settoepoch(&zone->nsec3chaintime);
788	isc_time_settoepoch(&zone->refreshkeytime);
789	zone->refreshkeycount = 0;
790	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
791	zone->retry = DNS_ZONE_DEFAULTRETRY;
792	zone->expire = 0;
793	zone->minimum = 0;
794	zone->maxrefresh = DNS_ZONE_MAXREFRESH;
795	zone->minrefresh = DNS_ZONE_MINREFRESH;
796	zone->maxretry = DNS_ZONE_MAXRETRY;
797	zone->minretry = DNS_ZONE_MINRETRY;
798	zone->masters = NULL;
799	zone->masterkeynames = NULL;
800	zone->mastersok = NULL;
801	zone->masterscnt = 0;
802	zone->curmaster = 0;
803	zone->notify = NULL;
804	zone->notifytype = dns_notifytype_yes;
805	zone->notifycnt = 0;
806	zone->task = NULL;
807	zone->update_acl = NULL;
808	zone->forward_acl = NULL;
809	zone->notify_acl = NULL;
810	zone->query_acl = NULL;
811	zone->queryon_acl = NULL;
812	zone->xfr_acl = NULL;
813	zone->update_disabled = ISC_FALSE;
814	zone->zero_no_soa_ttl = ISC_TRUE;
815	zone->check_names = dns_severity_ignore;
816	zone->request = NULL;
817	zone->lctx = NULL;
818	zone->readio = NULL;
819	zone->dctx = NULL;
820	zone->writeio = NULL;
821	zone->timer = NULL;
822	zone->idlein = DNS_DEFAULT_IDLEIN;
823	zone->idleout = DNS_DEFAULT_IDLEOUT;
824	zone->log_key_expired_timer = 0;
825	ISC_LIST_INIT(zone->notifies);
826	isc_sockaddr_any(&zone->notifysrc4);
827	isc_sockaddr_any6(&zone->notifysrc6);
828	isc_sockaddr_any(&zone->xfrsource4);
829	isc_sockaddr_any6(&zone->xfrsource6);
830	isc_sockaddr_any(&zone->altxfrsource4);
831	isc_sockaddr_any6(&zone->altxfrsource6);
832	zone->xfr = NULL;
833	zone->tsigkey = NULL;
834	zone->maxxfrin = MAX_XFER_TIME;
835	zone->maxxfrout = MAX_XFER_TIME;
836	zone->ssutable = NULL;
837	zone->sigvalidityinterval = 30 * 24 * 3600;
838	zone->sigresigninginterval = 7 * 24 * 3600;
839	zone->view = NULL;
840	zone->acache = NULL;
841	zone->checkmx = NULL;
842	zone->checksrv = NULL;
843	zone->checkns = NULL;
844	ISC_LINK_INIT(zone, statelink);
845	zone->statelist = NULL;
846	zone->stats = NULL;
847	zone->requeststats_on = ISC_FALSE;
848	zone->requeststats = NULL;
849	zone->notifydelay = 5;
850	zone->isself = NULL;
851	zone->isselfarg = NULL;
852	ISC_LIST_INIT(zone->signing);
853	ISC_LIST_INIT(zone->nsec3chain);
854	zone->signatures = 10;
855	zone->nodes = 100;
856	zone->privatetype = (dns_rdatatype_t)0xffffU;
857	zone->added = ISC_FALSE;
858	zone->rpz_zone = ISC_FALSE;
859	ISC_LIST_INIT(zone->forwards);
860
861	zone->magic = ZONE_MAGIC;
862
863	/* Must be after magic is set. */
864	result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
865	if (result != ISC_R_SUCCESS)
866		goto free_erefs;
867
868	ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
869		       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
870		       NULL, NULL);
871	*zonep = zone;
872	return (ISC_R_SUCCESS);
873
874 free_erefs:
875	isc_refcount_decrement(&zone->erefs, NULL);
876	isc_refcount_destroy(&zone->erefs);
877
878 free_dblock:
879	ZONEDB_DESTROYLOCK(&zone->dblock);
880
881 free_mutex:
882	DESTROYLOCK(&zone->lock);
883
884 free_zone:
885	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
886	return (result);
887}
888
889/*
890 * Free a zone.  Because we require that there be no more
891 * outstanding events or references, no locking is necessary.
892 */
893static void
894zone_free(dns_zone_t *zone) {
895	isc_mem_t *mctx = NULL;
896	dns_signing_t *signing;
897	dns_nsec3chain_t *nsec3chain;
898
899	REQUIRE(DNS_ZONE_VALID(zone));
900	REQUIRE(isc_refcount_current(&zone->erefs) == 0);
901	REQUIRE(zone->irefs == 0);
902	REQUIRE(!LOCKED_ZONE(zone));
903	REQUIRE(zone->timer == NULL);
904
905	/*
906	 * Managed objects.  Order is important.
907	 */
908	if (zone->request != NULL)
909		dns_request_destroy(&zone->request); /* XXXMPA */
910	INSIST(zone->readio == NULL);
911	INSIST(zone->statelist == NULL);
912	INSIST(zone->writeio == NULL);
913
914	if (zone->task != NULL)
915		isc_task_detach(&zone->task);
916	if (zone->zmgr != NULL)
917		dns_zonemgr_releasezone(zone->zmgr, zone);
918
919	/* Unmanaged objects */
920	for (signing = ISC_LIST_HEAD(zone->signing);
921	     signing != NULL;
922	     signing = ISC_LIST_HEAD(zone->signing)) {
923		ISC_LIST_UNLINK(zone->signing, signing, link);
924		dns_db_detach(&signing->db);
925		dns_dbiterator_destroy(&signing->dbiterator);
926		isc_mem_put(zone->mctx, signing, sizeof *signing);
927	}
928	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
929	     nsec3chain != NULL;
930	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
931		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
932		dns_db_detach(&nsec3chain->db);
933		dns_dbiterator_destroy(&nsec3chain->dbiterator);
934		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
935	}
936	if (zone->masterfile != NULL)
937		isc_mem_free(zone->mctx, zone->masterfile);
938	zone->masterfile = NULL;
939	if (zone->keydirectory != NULL)
940		isc_mem_free(zone->mctx, zone->keydirectory);
941	zone->keydirectory = NULL;
942	zone->journalsize = -1;
943	if (zone->journal != NULL)
944		isc_mem_free(zone->mctx, zone->journal);
945	zone->journal = NULL;
946	if (zone->stats != NULL)
947		isc_stats_detach(&zone->stats);
948	if (zone->requeststats != NULL)
949		isc_stats_detach(&zone->requeststats);
950	if (zone->db != NULL)
951		zone_detachdb(zone);
952	if (zone->acache != NULL)
953		dns_acache_detach(&zone->acache);
954	zone_freedbargs(zone);
955	RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
956		      == ISC_R_SUCCESS);
957	RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
958		      == ISC_R_SUCCESS);
959	zone->check_names = dns_severity_ignore;
960	if (zone->update_acl != NULL)
961		dns_acl_detach(&zone->update_acl);
962	if (zone->forward_acl != NULL)
963		dns_acl_detach(&zone->forward_acl);
964	if (zone->notify_acl != NULL)
965		dns_acl_detach(&zone->notify_acl);
966	if (zone->query_acl != NULL)
967		dns_acl_detach(&zone->query_acl);
968	if (zone->queryon_acl != NULL)
969		dns_acl_detach(&zone->queryon_acl);
970	if (zone->xfr_acl != NULL)
971		dns_acl_detach(&zone->xfr_acl);
972	if (dns_name_dynamic(&zone->origin))
973		dns_name_free(&zone->origin, zone->mctx);
974	if (zone->strnamerd != NULL)
975		isc_mem_free(zone->mctx, zone->strnamerd);
976	if (zone->strname != NULL)
977		isc_mem_free(zone->mctx, zone->strname);
978	if (zone->strrdclass != NULL)
979		isc_mem_free(zone->mctx, zone->strrdclass);
980	if (zone->strviewname != NULL)
981		isc_mem_free(zone->mctx, zone->strviewname);
982	if (zone->ssutable != NULL)
983		dns_ssutable_detach(&zone->ssutable);
984
985	/* last stuff */
986	ZONEDB_DESTROYLOCK(&zone->dblock);
987	DESTROYLOCK(&zone->lock);
988	isc_refcount_destroy(&zone->erefs);
989	zone->magic = 0;
990	mctx = zone->mctx;
991	isc_mem_put(mctx, zone, sizeof(*zone));
992	isc_mem_detach(&mctx);
993}
994
995/*
996 *	Single shot.
997 */
998void
999dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1000	char namebuf[1024];
1001
1002	REQUIRE(DNS_ZONE_VALID(zone));
1003	REQUIRE(rdclass != dns_rdataclass_none);
1004
1005	/*
1006	 * Test and set.
1007	 */
1008	LOCK_ZONE(zone);
1009	REQUIRE(zone->rdclass == dns_rdataclass_none ||
1010		zone->rdclass == rdclass);
1011	zone->rdclass = rdclass;
1012
1013	if (zone->strnamerd != NULL)
1014		isc_mem_free(zone->mctx, zone->strnamerd);
1015	if (zone->strrdclass != NULL)
1016		isc_mem_free(zone->mctx, zone->strrdclass);
1017
1018	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1019	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1020	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1021	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1022
1023	UNLOCK_ZONE(zone);
1024}
1025
1026dns_rdataclass_t
1027dns_zone_getclass(dns_zone_t *zone) {
1028	REQUIRE(DNS_ZONE_VALID(zone));
1029
1030	return (zone->rdclass);
1031}
1032
1033void
1034dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1035	REQUIRE(DNS_ZONE_VALID(zone));
1036
1037	LOCK_ZONE(zone);
1038	zone->notifytype = notifytype;
1039	UNLOCK_ZONE(zone);
1040}
1041
1042isc_result_t
1043dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1044	isc_result_t result;
1045
1046	REQUIRE(DNS_ZONE_VALID(zone));
1047	REQUIRE(serialp != NULL);
1048
1049	LOCK_ZONE(zone);
1050	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1051	if (zone->db != NULL) {
1052		result = zone_get_from_db(zone, zone->db, NULL, NULL, serialp,
1053					  NULL, NULL, NULL, NULL, NULL);
1054	} else
1055		result = DNS_R_NOTLOADED;
1056	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1057	UNLOCK_ZONE(zone);
1058
1059	return (result);
1060}
1061
1062isc_uint32_t
1063dns_zone_getserial(dns_zone_t *zone) {
1064	isc_result_t result;
1065	isc_uint32_t serial;
1066
1067	result = dns_zone_getserial2(zone, &serial);
1068	if (result != ISC_R_SUCCESS)
1069		serial = 0; /* XXX: not really correct, but no other choice */
1070
1071	return (serial);
1072}
1073
1074/*
1075 *	Single shot.
1076 */
1077void
1078dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1079
1080	REQUIRE(DNS_ZONE_VALID(zone));
1081	REQUIRE(type != dns_zone_none);
1082
1083	/*
1084	 * Test and set.
1085	 */
1086	LOCK_ZONE(zone);
1087	REQUIRE(zone->type == dns_zone_none || zone->type == type);
1088	zone->type = type;
1089	UNLOCK_ZONE(zone);
1090}
1091
1092static void
1093zone_freedbargs(dns_zone_t *zone) {
1094	unsigned int i;
1095
1096	/* Free the old database argument list. */
1097	if (zone->db_argv != NULL) {
1098		for (i = 0; i < zone->db_argc; i++)
1099			isc_mem_free(zone->mctx, zone->db_argv[i]);
1100		isc_mem_put(zone->mctx, zone->db_argv,
1101			    zone->db_argc * sizeof(*zone->db_argv));
1102	}
1103	zone->db_argc = 0;
1104	zone->db_argv = NULL;
1105}
1106
1107isc_result_t
1108dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1109	size_t size = 0;
1110	unsigned int i;
1111	isc_result_t result = ISC_R_SUCCESS;
1112	void *mem;
1113	char **tmp, *tmp2;
1114
1115	REQUIRE(DNS_ZONE_VALID(zone));
1116	REQUIRE(argv != NULL && *argv == NULL);
1117
1118	LOCK_ZONE(zone);
1119	size = (zone->db_argc + 1) * sizeof(char *);
1120	for (i = 0; i < zone->db_argc; i++)
1121		size += strlen(zone->db_argv[i]) + 1;
1122	mem = isc_mem_allocate(mctx, size);
1123	if (mem != NULL) {
1124		tmp = mem;
1125		tmp2 = mem;
1126		tmp2 += (zone->db_argc + 1) * sizeof(char *);
1127		for (i = 0; i < zone->db_argc; i++) {
1128			*tmp++ = tmp2;
1129			strcpy(tmp2, zone->db_argv[i]);
1130			tmp2 += strlen(tmp2) + 1;
1131		}
1132		*tmp = NULL;
1133	} else
1134		result = ISC_R_NOMEMORY;
1135	UNLOCK_ZONE(zone);
1136	*argv = mem;
1137	return (result);
1138}
1139
1140isc_result_t
1141dns_zone_setdbtype(dns_zone_t *zone,
1142		   unsigned int dbargc, const char * const *dbargv) {
1143	isc_result_t result = ISC_R_SUCCESS;
1144	char **new = NULL;
1145	unsigned int i;
1146
1147	REQUIRE(DNS_ZONE_VALID(zone));
1148	REQUIRE(dbargc >= 1);
1149	REQUIRE(dbargv != NULL);
1150
1151	LOCK_ZONE(zone);
1152
1153	/* Set up a new database argument list. */
1154	new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1155	if (new == NULL)
1156		goto nomem;
1157	for (i = 0; i < dbargc; i++)
1158		new[i] = NULL;
1159	for (i = 0; i < dbargc; i++) {
1160		new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1161		if (new[i] == NULL)
1162			goto nomem;
1163	}
1164
1165	/* Free the old list. */
1166	zone_freedbargs(zone);
1167
1168	zone->db_argc = dbargc;
1169	zone->db_argv = new;
1170	result = ISC_R_SUCCESS;
1171	goto unlock;
1172
1173 nomem:
1174	if (new != NULL) {
1175		for (i = 0; i < dbargc; i++)
1176			if (new[i] != NULL)
1177				isc_mem_free(zone->mctx, new[i]);
1178		isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1179	}
1180	result = ISC_R_NOMEMORY;
1181
1182 unlock:
1183	UNLOCK_ZONE(zone);
1184	return (result);
1185}
1186
1187void
1188dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1189	char namebuf[1024];
1190	REQUIRE(DNS_ZONE_VALID(zone));
1191
1192	LOCK_ZONE(zone);
1193	if (zone->view != NULL)
1194		dns_view_weakdetach(&zone->view);
1195	dns_view_weakattach(view, &zone->view);
1196
1197	if (zone->strviewname != NULL)
1198		isc_mem_free(zone->mctx, zone->strviewname);
1199	if (zone->strnamerd != NULL)
1200		isc_mem_free(zone->mctx, zone->strnamerd);
1201
1202	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1203	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1204	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1205	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1206
1207	UNLOCK_ZONE(zone);
1208}
1209
1210
1211dns_view_t *
1212dns_zone_getview(dns_zone_t *zone) {
1213	REQUIRE(DNS_ZONE_VALID(zone));
1214
1215	return (zone->view);
1216}
1217
1218
1219isc_result_t
1220dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1221	isc_result_t result;
1222	char namebuf[1024];
1223
1224	REQUIRE(DNS_ZONE_VALID(zone));
1225	REQUIRE(origin != NULL);
1226
1227	LOCK_ZONE(zone);
1228	if (dns_name_dynamic(&zone->origin)) {
1229		dns_name_free(&zone->origin, zone->mctx);
1230		dns_name_init(&zone->origin, NULL);
1231	}
1232	result = dns_name_dup(origin, zone->mctx, &zone->origin);
1233
1234	if (zone->strnamerd != NULL)
1235		isc_mem_free(zone->mctx, zone->strnamerd);
1236	if (zone->strname != NULL)
1237		isc_mem_free(zone->mctx, zone->strname);
1238
1239	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1240	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1241	zone_name_tostr(zone, namebuf, sizeof namebuf);
1242	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1243
1244	UNLOCK_ZONE(zone);
1245	return (result);
1246}
1247
1248void
1249dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1250	REQUIRE(DNS_ZONE_VALID(zone));
1251	REQUIRE(acache != NULL);
1252
1253	LOCK_ZONE(zone);
1254	if (zone->acache != NULL)
1255		dns_acache_detach(&zone->acache);
1256	dns_acache_attach(acache, &zone->acache);
1257	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1258	if (zone->db != NULL) {
1259		isc_result_t result;
1260
1261		/*
1262		 * If the zone reuses an existing DB, the DB needs to be
1263		 * set in the acache explicitly.  We can safely ignore the
1264		 * case where the DB is already set.  If other error happens,
1265		 * the acache will not work effectively.
1266		 */
1267		result = dns_acache_setdb(acache, zone->db);
1268		if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1269			UNEXPECTED_ERROR(__FILE__, __LINE__,
1270					 "dns_acache_setdb() failed: %s",
1271					 isc_result_totext(result));
1272		}
1273	}
1274	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1275	UNLOCK_ZONE(zone);
1276}
1277
1278static isc_result_t
1279dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1280	char *copy;
1281
1282	if (value != NULL) {
1283		copy = isc_mem_strdup(zone->mctx, value);
1284		if (copy == NULL)
1285			return (ISC_R_NOMEMORY);
1286	} else {
1287		copy = NULL;
1288	}
1289
1290	if (*field != NULL)
1291		isc_mem_free(zone->mctx, *field);
1292
1293	*field = copy;
1294	return (ISC_R_SUCCESS);
1295}
1296
1297isc_result_t
1298dns_zone_setfile(dns_zone_t *zone, const char *file) {
1299	return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1300}
1301
1302isc_result_t
1303dns_zone_setfile2(dns_zone_t *zone, const char *file,
1304		  dns_masterformat_t format) {
1305	isc_result_t result = ISC_R_SUCCESS;
1306
1307	REQUIRE(DNS_ZONE_VALID(zone));
1308
1309	LOCK_ZONE(zone);
1310	result = dns_zone_setstring(zone, &zone->masterfile, file);
1311	if (result == ISC_R_SUCCESS) {
1312		zone->masterformat = format;
1313		result = default_journal(zone);
1314	}
1315	UNLOCK_ZONE(zone);
1316
1317	return (result);
1318}
1319
1320const char *
1321dns_zone_getfile(dns_zone_t *zone) {
1322	REQUIRE(DNS_ZONE_VALID(zone));
1323
1324	return (zone->masterfile);
1325}
1326
1327static isc_result_t
1328default_journal(dns_zone_t *zone) {
1329	isc_result_t result;
1330	char *journal;
1331
1332	REQUIRE(DNS_ZONE_VALID(zone));
1333	REQUIRE(LOCKED_ZONE(zone));
1334
1335	if (zone->masterfile != NULL) {
1336		/* Calculate string length including '\0'. */
1337		int len = strlen(zone->masterfile) + sizeof(".jnl");
1338		journal = isc_mem_allocate(zone->mctx, len);
1339		if (journal == NULL)
1340			return (ISC_R_NOMEMORY);
1341		strcpy(journal, zone->masterfile);
1342		strcat(journal, ".jnl");
1343	} else {
1344		journal = NULL;
1345	}
1346	result = dns_zone_setstring(zone, &zone->journal, journal);
1347	if (journal != NULL)
1348		isc_mem_free(zone->mctx, journal);
1349	return (result);
1350}
1351
1352isc_result_t
1353dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1354	isc_result_t result = ISC_R_SUCCESS;
1355
1356	REQUIRE(DNS_ZONE_VALID(zone));
1357
1358	LOCK_ZONE(zone);
1359	result = dns_zone_setstring(zone, &zone->journal, journal);
1360	UNLOCK_ZONE(zone);
1361
1362	return (result);
1363}
1364
1365char *
1366dns_zone_getjournal(dns_zone_t *zone) {
1367	REQUIRE(DNS_ZONE_VALID(zone));
1368
1369	return (zone->journal);
1370}
1371
1372/*
1373 * Return true iff the zone is "dynamic", in the sense that the zone's
1374 * master file (if any) is written by the server, rather than being
1375 * updated manually and read by the server.
1376 *
1377 * This is true for slave zones, stub zones, key zones, and zones that
1378 * allow dynamic updates either by having an update policy ("ssutable")
1379 * or an "allow-update" ACL with a value other than exactly "{ none; }".
1380 */
1381static isc_boolean_t
1382zone_isdynamic(dns_zone_t *zone) {
1383	REQUIRE(DNS_ZONE_VALID(zone));
1384
1385	return (ISC_TF(zone->type == dns_zone_slave ||
1386		       zone->type == dns_zone_stub ||
1387		       zone->type == dns_zone_key ||
1388		       (!zone->update_disabled && zone->ssutable != NULL) ||
1389		       (!zone->update_disabled && zone->update_acl != NULL &&
1390			!dns_acl_isnone(zone->update_acl))));
1391}
1392
1393
1394static isc_result_t
1395zone_load(dns_zone_t *zone, unsigned int flags) {
1396	isc_result_t result;
1397	isc_time_t now;
1398	isc_time_t loadtime, filetime;
1399	dns_db_t *db = NULL;
1400	isc_boolean_t rbt;
1401
1402	REQUIRE(DNS_ZONE_VALID(zone));
1403
1404	LOCK_ZONE(zone);
1405	TIME_NOW(&now);
1406
1407	INSIST(zone->type != dns_zone_none);
1408
1409	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1410		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1411			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1412		result = DNS_R_CONTINUE;
1413		goto cleanup;
1414	}
1415
1416
1417	INSIST(zone->db_argc >= 1);
1418
1419	rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1420	      strcmp(zone->db_argv[0], "rbt64") == 0;
1421
1422	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1423		/*
1424		 * The zone has no master file configured.
1425		 */
1426		result = ISC_R_SUCCESS;
1427		goto cleanup;
1428	}
1429
1430	if (zone->db != NULL && zone_isdynamic(zone)) {
1431		/*
1432		 * This is a slave, stub, or dynamically updated
1433		 * zone being reloaded.  Do nothing - the database
1434		 * we already have is guaranteed to be up-to-date.
1435		 */
1436		if (zone->type == dns_zone_master)
1437			result = DNS_R_DYNAMIC;
1438		else
1439			result = ISC_R_SUCCESS;
1440		goto cleanup;
1441	}
1442
1443	/*
1444	 * Store the current time before the zone is loaded, so that if the
1445	 * file changes between the time of the load and the time that
1446	 * zone->loadtime is set, then the file will still be reloaded
1447	 * the next time dns_zone_load is called.
1448	 */
1449	TIME_NOW(&loadtime);
1450
1451	/*
1452	 * Don't do the load if the file that stores the zone is older
1453	 * than the last time the zone was loaded.  If the zone has not
1454	 * been loaded yet, zone->loadtime will be the epoch.
1455	 */
1456	if (zone->masterfile != NULL) {
1457		/*
1458		 * The file is already loaded.	If we are just doing a
1459		 * "rndc reconfig", we are done.
1460		 */
1461		if (!isc_time_isepoch(&zone->loadtime) &&
1462		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0 &&
1463		    zone->rpz_zone == dns_rpz_needed()) {
1464			result = ISC_R_SUCCESS;
1465			goto cleanup;
1466		}
1467
1468		result = isc_file_getmodtime(zone->masterfile, &filetime);
1469		if (result == ISC_R_SUCCESS) {
1470			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1471			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1472			    isc_time_compare(&filetime, &zone->loadtime) <= 0 &&
1473			    zone->rpz_zone == dns_rpz_needed()) {
1474				dns_zone_log(zone, ISC_LOG_DEBUG(1),
1475					     "skipping load: master file "
1476					     "older than last load");
1477				result = DNS_R_UPTODATE;
1478				goto cleanup;
1479			}
1480			loadtime = filetime;
1481			zone->rpz_zone = dns_rpz_needed();
1482		}
1483	}
1484
1485	/*
1486	 * Built in zones (with the exception of empty zones) don't need
1487	 * to be reloaded.
1488	 */
1489	if (zone->type == dns_zone_master &&
1490	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
1491	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1492	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1493		result = ISC_R_SUCCESS;
1494		goto cleanup;
1495	}
1496
1497	if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
1498	    rbt) {
1499		if (zone->masterfile == NULL ||
1500		    !isc_file_exists(zone->masterfile)) {
1501			if (zone->masterfile != NULL) {
1502				dns_zone_log(zone, ISC_LOG_DEBUG(1),
1503					     "no master file");
1504			}
1505			zone->refreshtime = now;
1506			if (zone->task != NULL)
1507				zone_settimer(zone, &now);
1508			result = ISC_R_SUCCESS;
1509			goto cleanup;
1510		}
1511	}
1512
1513	dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1514
1515	result = dns_db_create(zone->mctx, zone->db_argv[0],
1516			       &zone->origin, (zone->type == dns_zone_stub) ?
1517			       dns_dbtype_stub : dns_dbtype_zone,
1518			       zone->rdclass,
1519			       zone->db_argc - 1, zone->db_argv + 1,
1520			       &db);
1521
1522	if (result != ISC_R_SUCCESS) {
1523		dns_zone_log(zone, ISC_LOG_ERROR,
1524			     "loading zone: creating database: %s",
1525			     isc_result_totext(result));
1526		goto cleanup;
1527	}
1528	dns_db_settask(db, zone->task);
1529
1530	if (! dns_db_ispersistent(db)) {
1531		if (zone->masterfile != NULL) {
1532			result = zone_startload(db, zone, loadtime);
1533		} else {
1534			result = DNS_R_NOMASTERFILE;
1535			if (zone->type == dns_zone_master) {
1536				dns_zone_log(zone, ISC_LOG_ERROR,
1537					     "loading zone: "
1538					     "no master file configured");
1539				goto cleanup;
1540			}
1541			dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1542				     "no master file configured: continuing");
1543		}
1544	}
1545
1546	if (result == DNS_R_CONTINUE) {
1547		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1548		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1549			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1550		goto cleanup;
1551	}
1552
1553	result = zone_postload(zone, db, loadtime, result);
1554
1555 cleanup:
1556	UNLOCK_ZONE(zone);
1557	if (db != NULL)
1558		dns_db_detach(&db);
1559	return (result);
1560}
1561
1562isc_result_t
1563dns_zone_load(dns_zone_t *zone) {
1564	return (zone_load(zone, 0));
1565}
1566
1567isc_result_t
1568dns_zone_loadnew(dns_zone_t *zone) {
1569	return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1570}
1571
1572isc_result_t
1573dns_zone_loadandthaw(dns_zone_t *zone) {
1574	isc_result_t result;
1575
1576	result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1577	switch (result) {
1578	case DNS_R_CONTINUE:
1579		/* Deferred thaw. */
1580		break;
1581	case ISC_R_SUCCESS:
1582	case DNS_R_UPTODATE:
1583	case DNS_R_SEENINCLUDE:
1584		zone->update_disabled = ISC_FALSE;
1585		break;
1586	case DNS_R_NOMASTERFILE:
1587		zone->update_disabled = ISC_FALSE;
1588		break;
1589	default:
1590		/* Error, remain in disabled state. */
1591		break;
1592	}
1593	return (result);
1594}
1595
1596static unsigned int
1597get_master_options(dns_zone_t *zone) {
1598	unsigned int options;
1599
1600	options = DNS_MASTER_ZONE;
1601	if (zone->type == dns_zone_slave)
1602		options |= DNS_MASTER_SLAVE;
1603	if (zone->type == dns_zone_key)
1604		options |= DNS_MASTER_KEY;
1605	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1606		options |= DNS_MASTER_CHECKNS;
1607	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1608		options |= DNS_MASTER_FATALNS;
1609	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1610		options |= DNS_MASTER_CHECKNAMES;
1611	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1612		options |= DNS_MASTER_CHECKNAMESFAIL;
1613	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1614		options |= DNS_MASTER_CHECKMX;
1615	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1616		options |= DNS_MASTER_CHECKMXFAIL;
1617	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1618		options |= DNS_MASTER_CHECKWILDCARD;
1619	if (zone->type == dns_zone_master &&
1620	    ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1621	      zone->ssutable != NULL))
1622		options |= DNS_MASTER_RESIGN;
1623	return (options);
1624}
1625
1626static void
1627zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1628	dns_load_t *load = event->ev_arg;
1629	isc_result_t result = ISC_R_SUCCESS;
1630	unsigned int options;
1631
1632	REQUIRE(DNS_LOAD_VALID(load));
1633
1634	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1635		result = ISC_R_CANCELED;
1636	isc_event_free(&event);
1637	if (result == ISC_R_CANCELED)
1638		goto fail;
1639
1640	options = get_master_options(load->zone);
1641
1642	result = dns_master_loadfileinc3(load->zone->masterfile,
1643					 dns_db_origin(load->db),
1644					 dns_db_origin(load->db),
1645					 load->zone->rdclass,
1646					 options,
1647					 load->zone->sigresigninginterval,
1648					 &load->callbacks, task,
1649					 zone_loaddone, load,
1650					 &load->zone->lctx, load->zone->mctx,
1651					 load->zone->masterformat);
1652	if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1653	    result != DNS_R_SEENINCLUDE)
1654		goto fail;
1655	return;
1656
1657 fail:
1658	zone_loaddone(load, result);
1659}
1660
1661static void
1662zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1663	const char me[] = "zone_gotwritehandle";
1664	dns_zone_t *zone = event->ev_arg;
1665	isc_result_t result = ISC_R_SUCCESS;
1666	dns_dbversion_t *version = NULL;
1667
1668	REQUIRE(DNS_ZONE_VALID(zone));
1669	INSIST(task == zone->task);
1670	ENTER;
1671
1672	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1673		result = ISC_R_CANCELED;
1674	isc_event_free(&event);
1675	if (result == ISC_R_CANCELED)
1676		goto fail;
1677
1678	LOCK_ZONE(zone);
1679	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1680	if (zone->db != NULL) {
1681		dns_db_currentversion(zone->db, &version);
1682		result = dns_master_dumpinc2(zone->mctx, zone->db, version,
1683					     &dns_master_style_default,
1684					     zone->masterfile, zone->task,
1685					     dump_done, zone, &zone->dctx,
1686					     zone->masterformat);
1687		dns_db_closeversion(zone->db, &version, ISC_FALSE);
1688	} else
1689		result = ISC_R_CANCELED;
1690	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1691	UNLOCK_ZONE(zone);
1692	if (result != DNS_R_CONTINUE)
1693		goto fail;
1694	return;
1695
1696 fail:
1697	dump_done(zone, result);
1698}
1699
1700static isc_result_t
1701zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1702	dns_load_t *load;
1703	isc_result_t result;
1704	isc_result_t tresult;
1705	unsigned int options;
1706
1707	options = get_master_options(zone);
1708
1709	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1710		options |= DNS_MASTER_MANYERRORS;
1711
1712	if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1713		load = isc_mem_get(zone->mctx, sizeof(*load));
1714		if (load == NULL)
1715			return (ISC_R_NOMEMORY);
1716
1717		load->mctx = NULL;
1718		load->zone = NULL;
1719		load->db = NULL;
1720		load->loadtime = loadtime;
1721		load->magic = LOAD_MAGIC;
1722
1723		isc_mem_attach(zone->mctx, &load->mctx);
1724		zone_iattach(zone, &load->zone);
1725		dns_db_attach(db, &load->db);
1726		dns_rdatacallbacks_init(&load->callbacks);
1727		result = dns_db_beginload(db, &load->callbacks.add,
1728					  &load->callbacks.add_private);
1729		if (result != ISC_R_SUCCESS)
1730			goto cleanup;
1731		result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1732				       zone_gotreadhandle, load,
1733				       &zone->readio);
1734		if (result != ISC_R_SUCCESS) {
1735			/*
1736			 * We can't report multiple errors so ignore
1737			 * the result of dns_db_endload().
1738			 */
1739			(void)dns_db_endload(load->db,
1740					     &load->callbacks.add_private);
1741			goto cleanup;
1742		} else
1743			result = DNS_R_CONTINUE;
1744	} else {
1745		dns_rdatacallbacks_t callbacks;
1746
1747		dns_rdatacallbacks_init(&callbacks);
1748		result = dns_db_beginload(db, &callbacks.add,
1749					  &callbacks.add_private);
1750		if (result != ISC_R_SUCCESS)
1751			return (result);
1752		result = dns_master_loadfile3(zone->masterfile, &zone->origin,
1753					      &zone->origin, zone->rdclass,
1754					      options, zone->sigresigninginterval,
1755					      &callbacks, zone->mctx,
1756					      zone->masterformat);
1757		tresult = dns_db_endload(db, &callbacks.add_private);
1758		if (result == ISC_R_SUCCESS)
1759			result = tresult;
1760	}
1761
1762	return (result);
1763
1764 cleanup:
1765	load->magic = 0;
1766	dns_db_detach(&load->db);
1767	zone_idetach(&load->zone);
1768	isc_mem_detach(&load->mctx);
1769	isc_mem_put(zone->mctx, load, sizeof(*load));
1770	return (result);
1771}
1772
1773static isc_boolean_t
1774zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1775	      dns_name_t *owner)
1776{
1777	isc_result_t result;
1778	char ownerbuf[DNS_NAME_FORMATSIZE];
1779	char namebuf[DNS_NAME_FORMATSIZE];
1780	char altbuf[DNS_NAME_FORMATSIZE];
1781	dns_fixedname_t fixed;
1782	dns_name_t *foundname;
1783	int level;
1784
1785	/*
1786	 * "." means the services does not exist.
1787	 */
1788	if (dns_name_equal(name, dns_rootname))
1789		return (ISC_TRUE);
1790
1791	/*
1792	 * Outside of zone.
1793	 */
1794	if (!dns_name_issubdomain(name, &zone->origin)) {
1795		if (zone->checkmx != NULL)
1796			return ((zone->checkmx)(zone, name, owner));
1797		return (ISC_TRUE);
1798	}
1799
1800	if (zone->type == dns_zone_master)
1801		level = ISC_LOG_ERROR;
1802	else
1803		level = ISC_LOG_WARNING;
1804
1805	dns_fixedname_init(&fixed);
1806	foundname = dns_fixedname_name(&fixed);
1807
1808	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1809			     0, 0, NULL, foundname, NULL, NULL);
1810	if (result == ISC_R_SUCCESS)
1811		return (ISC_TRUE);
1812
1813	if (result == DNS_R_NXRRSET) {
1814		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1815				     0, 0, NULL, foundname, NULL, NULL);
1816		if (result == ISC_R_SUCCESS)
1817			return (ISC_TRUE);
1818	}
1819
1820	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1821	dns_name_format(name, namebuf, sizeof namebuf);
1822	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1823	    result == DNS_R_EMPTYNAME) {
1824		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1825			level = ISC_LOG_WARNING;
1826		dns_zone_log(zone, level,
1827			     "%s/MX '%s' has no address records (A or AAAA)",
1828			     ownerbuf, namebuf);
1829		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1830	}
1831
1832	if (result == DNS_R_CNAME) {
1833		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1834		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1835			level = ISC_LOG_WARNING;
1836		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1837			dns_zone_log(zone, level,
1838				     "%s/MX '%s' is a CNAME (illegal)",
1839				     ownerbuf, namebuf);
1840		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1841	}
1842
1843	if (result == DNS_R_DNAME) {
1844		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1845		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1846			level = ISC_LOG_WARNING;
1847		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
1848			dns_name_format(foundname, altbuf, sizeof altbuf);
1849			dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
1850				     " '%s' (illegal)", ownerbuf, namebuf,
1851				     altbuf);
1852		}
1853		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1854	}
1855
1856	if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
1857		return ((zone->checkmx)(zone, name, owner));
1858
1859	return (ISC_TRUE);
1860}
1861
1862static isc_boolean_t
1863zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1864	       dns_name_t *owner)
1865{
1866	isc_result_t result;
1867	char ownerbuf[DNS_NAME_FORMATSIZE];
1868	char namebuf[DNS_NAME_FORMATSIZE];
1869	char altbuf[DNS_NAME_FORMATSIZE];
1870	dns_fixedname_t fixed;
1871	dns_name_t *foundname;
1872	int level;
1873
1874	/*
1875	 * "." means the services does not exist.
1876	 */
1877	if (dns_name_equal(name, dns_rootname))
1878		return (ISC_TRUE);
1879
1880	/*
1881	 * Outside of zone.
1882	 */
1883	if (!dns_name_issubdomain(name, &zone->origin)) {
1884		if (zone->checksrv != NULL)
1885			return ((zone->checksrv)(zone, name, owner));
1886		return (ISC_TRUE);
1887	}
1888
1889	if (zone->type == dns_zone_master)
1890		level = ISC_LOG_ERROR;
1891	else
1892		level = ISC_LOG_WARNING;
1893
1894	dns_fixedname_init(&fixed);
1895	foundname = dns_fixedname_name(&fixed);
1896
1897	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1898			     0, 0, NULL, foundname, NULL, NULL);
1899	if (result == ISC_R_SUCCESS)
1900		return (ISC_TRUE);
1901
1902	if (result == DNS_R_NXRRSET) {
1903		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1904				     0, 0, NULL, foundname, NULL, NULL);
1905		if (result == ISC_R_SUCCESS)
1906			return (ISC_TRUE);
1907	}
1908
1909	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1910	dns_name_format(name, namebuf, sizeof namebuf);
1911	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1912	    result == DNS_R_EMPTYNAME) {
1913		dns_zone_log(zone, level,
1914			     "%s/SRV '%s' has no address records (A or AAAA)",
1915			     ownerbuf, namebuf);
1916		/* XXX950 make fatal for 9.5.0. */
1917		return (ISC_TRUE);
1918	}
1919
1920	if (result == DNS_R_CNAME) {
1921		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1922		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1923			level = ISC_LOG_WARNING;
1924		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1925			dns_zone_log(zone, level,
1926				     "%s/SRV '%s' is a CNAME (illegal)",
1927				     ownerbuf, namebuf);
1928		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1929	}
1930
1931	if (result == DNS_R_DNAME) {
1932		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1933		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1934			level = ISC_LOG_WARNING;
1935		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
1936			dns_name_format(foundname, altbuf, sizeof altbuf);
1937			dns_zone_log(zone, level, "%s/SRV '%s' is below a "
1938				     "DNAME '%s' (illegal)", ownerbuf, namebuf,
1939				     altbuf);
1940		}
1941		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1942	}
1943
1944	if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
1945		return ((zone->checksrv)(zone, name, owner));
1946
1947	return (ISC_TRUE);
1948}
1949
1950static isc_boolean_t
1951zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1952		dns_name_t *owner)
1953{
1954	isc_boolean_t answer = ISC_TRUE;
1955	isc_result_t result, tresult;
1956	char ownerbuf[DNS_NAME_FORMATSIZE];
1957	char namebuf[DNS_NAME_FORMATSIZE];
1958	char altbuf[DNS_NAME_FORMATSIZE];
1959	dns_fixedname_t fixed;
1960	dns_name_t *foundname;
1961	dns_rdataset_t a;
1962	dns_rdataset_t aaaa;
1963	int level;
1964
1965	/*
1966	 * Outside of zone.
1967	 */
1968	if (!dns_name_issubdomain(name, &zone->origin)) {
1969		if (zone->checkns != NULL)
1970			return ((zone->checkns)(zone, name, owner, NULL, NULL));
1971		return (ISC_TRUE);
1972	}
1973
1974	if (zone->type == dns_zone_master)
1975		level = ISC_LOG_ERROR;
1976	else
1977		level = ISC_LOG_WARNING;
1978
1979	dns_fixedname_init(&fixed);
1980	foundname = dns_fixedname_name(&fixed);
1981	dns_rdataset_init(&a);
1982	dns_rdataset_init(&aaaa);
1983
1984	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1985			     DNS_DBFIND_GLUEOK, 0, NULL,
1986			     foundname, &a, NULL);
1987
1988	if (result == ISC_R_SUCCESS) {
1989		dns_rdataset_disassociate(&a);
1990		return (ISC_TRUE);
1991	} else if (result == DNS_R_DELEGATION)
1992		dns_rdataset_disassociate(&a);
1993
1994	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
1995	    result == DNS_R_GLUE) {
1996		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1997				     DNS_DBFIND_GLUEOK, 0, NULL,
1998				     foundname, &aaaa, NULL);
1999		if (tresult == ISC_R_SUCCESS) {
2000			dns_rdataset_disassociate(&aaaa);
2001			return (ISC_TRUE);
2002		}
2003		if (tresult == DNS_R_DELEGATION)
2004			dns_rdataset_disassociate(&aaaa);
2005		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2006			/*
2007			 * Check glue against child zone.
2008			 */
2009			if (zone->checkns != NULL)
2010				answer = (zone->checkns)(zone, name, owner,
2011							 &a, &aaaa);
2012			if (dns_rdataset_isassociated(&a))
2013				dns_rdataset_disassociate(&a);
2014			if (dns_rdataset_isassociated(&aaaa))
2015				dns_rdataset_disassociate(&aaaa);
2016			return (answer);
2017		}
2018	}
2019
2020	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2021	dns_name_format(name, namebuf, sizeof namebuf);
2022	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2023	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2024		const char *what;
2025		isc_boolean_t required = ISC_FALSE;
2026		if (dns_name_issubdomain(name, owner)) {
2027			what = "REQUIRED GLUE ";
2028			required = ISC_TRUE;
2029		 } else if (result == DNS_R_DELEGATION)
2030			what = "SIBLING GLUE ";
2031		else
2032			what = "";
2033
2034		if (result != DNS_R_DELEGATION || required ||
2035		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2036			dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2037				     "address records (A or AAAA)",
2038				     ownerbuf, namebuf, what);
2039			/*
2040			 * Log missing address record.
2041			 */
2042			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2043				(void)(zone->checkns)(zone, name, owner,
2044						      &a, &aaaa);
2045			/* XXX950 make fatal for 9.5.0. */
2046			/* answer = ISC_FALSE; */
2047		}
2048	} else if (result == DNS_R_CNAME) {
2049		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2050			     ownerbuf, namebuf);
2051		/* XXX950 make fatal for 9.5.0. */
2052		/* answer = ISC_FALSE; */
2053	} else if (result == DNS_R_DNAME) {
2054		dns_name_format(foundname, altbuf, sizeof altbuf);
2055		dns_zone_log(zone, level,
2056			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
2057			     ownerbuf, namebuf, altbuf);
2058		/* XXX950 make fatal for 9.5.0. */
2059		/* answer = ISC_FALSE; */
2060	}
2061
2062	if (dns_rdataset_isassociated(&a))
2063		dns_rdataset_disassociate(&a);
2064	if (dns_rdataset_isassociated(&aaaa))
2065		dns_rdataset_disassociate(&aaaa);
2066	return (answer);
2067}
2068
2069static isc_boolean_t
2070zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2071		     dns_rdataset_t *rdataset)
2072{
2073	dns_rdataset_t tmprdataset;
2074	isc_result_t result;
2075	isc_boolean_t answer = ISC_TRUE;
2076	isc_boolean_t format = ISC_TRUE;
2077	int level = ISC_LOG_WARNING;
2078	char ownerbuf[DNS_NAME_FORMATSIZE];
2079	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2080	unsigned int count1 = 0;
2081
2082	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2083		level = ISC_LOG_ERROR;
2084
2085	dns_rdataset_init(&tmprdataset);
2086	for (result = dns_rdataset_first(rdataset);
2087	     result == ISC_R_SUCCESS;
2088	     result = dns_rdataset_next(rdataset)) {
2089		dns_rdata_t rdata1 = DNS_RDATA_INIT;
2090		unsigned int count2 = 0;
2091
2092		count1++;
2093		dns_rdataset_current(rdataset, &rdata1);
2094		dns_rdataset_clone(rdataset, &tmprdataset);
2095		for (result = dns_rdataset_first(&tmprdataset);
2096		     result == ISC_R_SUCCESS;
2097		     result = dns_rdataset_next(&tmprdataset)) {
2098			dns_rdata_t rdata2 = DNS_RDATA_INIT;
2099			count2++;
2100			if (count1 >= count2)
2101				continue;
2102			dns_rdataset_current(&tmprdataset, &rdata2);
2103			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2104				if (format) {
2105					dns_name_format(owner, ownerbuf,
2106							sizeof ownerbuf);
2107					dns_rdatatype_format(rdata1.type,
2108							     typebuf,
2109							     sizeof(typebuf));
2110					format = ISC_FALSE;
2111				}
2112				dns_zone_log(zone, level, "%s/%s has "
2113					     "semantically identical records",
2114					     ownerbuf, typebuf);
2115				if (level == ISC_LOG_ERROR)
2116					answer = ISC_FALSE;
2117				break;
2118			}
2119		}
2120		dns_rdataset_disassociate(&tmprdataset);
2121		if (!format)
2122			break;
2123	}
2124	return (answer);
2125}
2126
2127static isc_boolean_t
2128zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2129	dns_dbiterator_t *dbiterator = NULL;
2130	dns_dbnode_t *node = NULL;
2131	dns_fixedname_t fixed;
2132	dns_name_t *name;
2133	dns_rdataset_t rdataset;
2134	dns_rdatasetiter_t *rdsit = NULL;
2135	isc_boolean_t ok = ISC_TRUE;
2136	isc_result_t result;
2137
2138	dns_fixedname_init(&fixed);
2139	name = dns_fixedname_name(&fixed);
2140	dns_rdataset_init(&rdataset);
2141
2142	result = dns_db_createiterator(db, 0, &dbiterator);
2143	if (result != ISC_R_SUCCESS)
2144		return (ISC_TRUE);
2145
2146	for (result = dns_dbiterator_first(dbiterator);
2147	     result == ISC_R_SUCCESS;
2148	     result = dns_dbiterator_next(dbiterator)) {
2149		result = dns_dbiterator_current(dbiterator, &node, name);
2150		if (result != ISC_R_SUCCESS)
2151			continue;
2152
2153		result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2154		if (result != ISC_R_SUCCESS)
2155			continue;
2156
2157		for (result = dns_rdatasetiter_first(rdsit);
2158		     result == ISC_R_SUCCESS;
2159		     result = dns_rdatasetiter_next(rdsit)) {
2160			dns_rdatasetiter_current(rdsit, &rdataset);
2161			if (!zone_rrset_check_dup(zone, name, &rdataset))
2162				ok = ISC_FALSE;
2163			dns_rdataset_disassociate(&rdataset);
2164		}
2165		dns_rdatasetiter_destroy(&rdsit);
2166		dns_db_detachnode(db, &node);
2167	}
2168
2169	if (node != NULL)
2170		dns_db_detachnode(db, &node);
2171	dns_dbiterator_destroy(&dbiterator);
2172
2173	return (ok);
2174}
2175
2176static isc_boolean_t
2177integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2178	dns_dbiterator_t *dbiterator = NULL;
2179	dns_dbnode_t *node = NULL;
2180	dns_rdataset_t rdataset;
2181	dns_fixedname_t fixed;
2182	dns_fixedname_t fixedbottom;
2183	dns_rdata_mx_t mx;
2184	dns_rdata_ns_t ns;
2185	dns_rdata_in_srv_t srv;
2186	dns_rdata_t rdata;
2187	dns_name_t *name;
2188	dns_name_t *bottom;
2189	isc_result_t result;
2190	isc_boolean_t ok = ISC_TRUE;
2191
2192	dns_fixedname_init(&fixed);
2193	name = dns_fixedname_name(&fixed);
2194	dns_fixedname_init(&fixedbottom);
2195	bottom = dns_fixedname_name(&fixedbottom);
2196	dns_rdataset_init(&rdataset);
2197	dns_rdata_init(&rdata);
2198
2199	result = dns_db_createiterator(db, 0, &dbiterator);
2200	if (result != ISC_R_SUCCESS)
2201		return (ISC_TRUE);
2202
2203	result = dns_dbiterator_first(dbiterator);
2204	while (result == ISC_R_SUCCESS) {
2205		result = dns_dbiterator_current(dbiterator, &node, name);
2206		if (result != ISC_R_SUCCESS)
2207			goto cleanup;
2208
2209		/*
2210		 * Is this name visible in the zone?
2211		 */
2212		if (!dns_name_issubdomain(name, &zone->origin) ||
2213		    (dns_name_countlabels(bottom) > 0 &&
2214		     dns_name_issubdomain(name, bottom)))
2215			goto next;
2216
2217		/*
2218		 * Don't check the NS records at the origin.
2219		 */
2220		if (dns_name_equal(name, &zone->origin))
2221			goto checkmx;
2222
2223		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2224					     0, 0, &rdataset, NULL);
2225		if (result != ISC_R_SUCCESS)
2226			goto checkmx;
2227		/*
2228		 * Remember bottom of zone.
2229		 */
2230		dns_name_copy(name, bottom, NULL);
2231
2232		result = dns_rdataset_first(&rdataset);
2233		while (result == ISC_R_SUCCESS) {
2234			dns_rdataset_current(&rdataset, &rdata);
2235			result = dns_rdata_tostruct(&rdata, &ns, NULL);
2236			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2237			if (!zone_check_glue(zone, db, &ns.name, name))
2238				ok = ISC_FALSE;
2239			dns_rdata_reset(&rdata);
2240			result = dns_rdataset_next(&rdataset);
2241		}
2242		dns_rdataset_disassociate(&rdataset);
2243		goto next;
2244
2245 checkmx:
2246		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2247					     0, 0, &rdataset, NULL);
2248		if (result != ISC_R_SUCCESS)
2249			goto checksrv;
2250		result = dns_rdataset_first(&rdataset);
2251		while (result == ISC_R_SUCCESS) {
2252			dns_rdataset_current(&rdataset, &rdata);
2253			result = dns_rdata_tostruct(&rdata, &mx, NULL);
2254			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2255			if (!zone_check_mx(zone, db, &mx.mx, name))
2256				ok = ISC_FALSE;
2257			dns_rdata_reset(&rdata);
2258			result = dns_rdataset_next(&rdataset);
2259		}
2260		dns_rdataset_disassociate(&rdataset);
2261
2262 checksrv:
2263		if (zone->rdclass != dns_rdataclass_in)
2264			goto next;
2265		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2266					     0, 0, &rdataset, NULL);
2267		if (result != ISC_R_SUCCESS)
2268			goto next;
2269		result = dns_rdataset_first(&rdataset);
2270		while (result == ISC_R_SUCCESS) {
2271			dns_rdataset_current(&rdataset, &rdata);
2272			result = dns_rdata_tostruct(&rdata, &srv, NULL);
2273			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2274			if (!zone_check_srv(zone, db, &srv.target, name))
2275				ok = ISC_FALSE;
2276			dns_rdata_reset(&rdata);
2277			result = dns_rdataset_next(&rdataset);
2278		}
2279		dns_rdataset_disassociate(&rdataset);
2280
2281 next:
2282		dns_db_detachnode(db, &node);
2283		result = dns_dbiterator_next(dbiterator);
2284	}
2285
2286 cleanup:
2287	if (node != NULL)
2288		dns_db_detachnode(db, &node);
2289	dns_dbiterator_destroy(&dbiterator);
2290
2291	return (ok);
2292}
2293
2294/*
2295 * OpenSSL verification of RSA keys with exponent 3 is known to be
2296 * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
2297 * if they are in use.
2298 */
2299static void
2300zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2301	dns_dbnode_t *node = NULL;
2302	dns_dbversion_t *version = NULL;
2303	dns_rdata_dnskey_t dnskey;
2304	dns_rdata_t rdata = DNS_RDATA_INIT;
2305	dns_rdataset_t rdataset;
2306	isc_result_t result;
2307	isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2308	const char *algorithm;
2309
2310	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2311	if (result != ISC_R_SUCCESS)
2312		goto cleanup;
2313
2314	dns_db_currentversion(db, &version);
2315	dns_rdataset_init(&rdataset);
2316	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2317				     dns_rdatatype_none, 0, &rdataset, NULL);
2318	if (result != ISC_R_SUCCESS)
2319		goto cleanup;
2320
2321	for (result = dns_rdataset_first(&rdataset);
2322	     result == ISC_R_SUCCESS;
2323	     result = dns_rdataset_next(&rdataset))
2324	{
2325		dns_rdataset_current(&rdataset, &rdata);
2326		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2327		INSIST(result == ISC_R_SUCCESS);
2328
2329		if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2330		     dnskey.algorithm == DST_ALG_RSAMD5) &&
2331		     dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2332		     dnskey.data[1] == 3)
2333		{
2334			if (dnskey.algorithm == DST_ALG_RSASHA1) {
2335				logit = !foundrsa;
2336				foundrsa = ISC_TRUE;
2337				algorithm = "RSASHA1";
2338			} else {
2339				logit = !foundmd5;
2340				foundmd5 = ISC_TRUE;
2341				algorithm = "RSAMD5";
2342			}
2343			if (logit)
2344				dns_zone_log(zone, ISC_LOG_WARNING,
2345					     "weak %s (%u) key found "
2346					     "(exponent=3)", algorithm,
2347					     dnskey.algorithm);
2348			if (foundrsa && foundmd5)
2349				break;
2350		}
2351		dns_rdata_reset(&rdata);
2352	}
2353	dns_rdataset_disassociate(&rdataset);
2354
2355 cleanup:
2356	if (node != NULL)
2357		dns_db_detachnode(db, &node);
2358	if (version != NULL)
2359		dns_db_closeversion(db, &version, ISC_FALSE);
2360}
2361
2362static void
2363resume_signingwithkey(dns_zone_t *zone) {
2364	dns_dbnode_t *node = NULL;
2365	dns_dbversion_t *version = NULL;
2366	dns_rdata_t rdata = DNS_RDATA_INIT;
2367	dns_rdataset_t rdataset;
2368	isc_result_t result;
2369
2370	result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2371	if (result != ISC_R_SUCCESS)
2372		goto cleanup;
2373
2374	dns_db_currentversion(zone->db, &version);
2375	dns_rdataset_init(&rdataset);
2376	result = dns_db_findrdataset(zone->db, node, version,
2377				     zone->privatetype,
2378				     dns_rdatatype_none, 0,
2379				     &rdataset, NULL);
2380	if (result != ISC_R_SUCCESS) {
2381		INSIST(!dns_rdataset_isassociated(&rdataset));
2382		goto cleanup;
2383	}
2384
2385	for (result = dns_rdataset_first(&rdataset);
2386	     result == ISC_R_SUCCESS;
2387	     result = dns_rdataset_next(&rdataset))
2388	{
2389		dns_rdataset_current(&rdataset, &rdata);
2390		if (rdata.length != 5 ||
2391		    rdata.data[0] == 0 || rdata.data[4] != 0) {
2392			dns_rdata_reset(&rdata);
2393			continue;
2394		}
2395
2396		result = zone_signwithkey(zone, rdata.data[0],
2397					  (rdata.data[1] << 8) | rdata.data[2],
2398					  ISC_TF(rdata.data[3]));
2399		if (result != ISC_R_SUCCESS) {
2400			dns_zone_log(zone, ISC_LOG_ERROR,
2401				     "zone_signwithkey failed: %s",
2402				     dns_result_totext(result));
2403		}
2404		dns_rdata_reset(&rdata);
2405	}
2406	dns_rdataset_disassociate(&rdataset);
2407
2408 cleanup:
2409	if (node != NULL)
2410		dns_db_detachnode(zone->db, &node);
2411	if (version != NULL)
2412		dns_db_closeversion(zone->db, &version, ISC_FALSE);
2413}
2414
2415static isc_result_t
2416zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2417	dns_nsec3chain_t *nsec3chain, *current;
2418	isc_result_t result;
2419	isc_time_t now;
2420	unsigned int options = 0;
2421	char saltbuf[255*2+1];
2422	char flags[sizeof("REMOVE|CREATE|NONSEC|OPTOUT")];
2423	int i;
2424
2425	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2426	if (nsec3chain == NULL)
2427		return (ISC_R_NOMEMORY);
2428
2429	nsec3chain->magic = 0;
2430	nsec3chain->done = ISC_FALSE;
2431	nsec3chain->db = NULL;
2432	nsec3chain->dbiterator = NULL;
2433	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2434	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2435	nsec3chain->nsec3param.hash = nsec3param->hash;
2436	nsec3chain->nsec3param.iterations = nsec3param->iterations;
2437	nsec3chain->nsec3param.flags = nsec3param->flags;
2438	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2439	memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2440	nsec3chain->nsec3param.salt = nsec3chain->salt;
2441	nsec3chain->seen_nsec = ISC_FALSE;
2442	nsec3chain->delete_nsec = ISC_FALSE;
2443	nsec3chain->save_delete_nsec = ISC_FALSE;
2444
2445	if (nsec3param->flags == 0)
2446		strlcpy(flags, "NONE", sizeof(flags));
2447	else {
2448		flags[0] = '\0';
2449		if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2450			strlcat(flags, "REMOVE", sizeof(flags));
2451		if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2452			if (flags[0] == '\0')
2453				strlcpy(flags, "CREATE", sizeof(flags));
2454			else
2455				strlcat(flags, "|CREATE", sizeof(flags));
2456		}
2457		if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2458			if (flags[0] == '\0')
2459				strlcpy(flags, "NONSEC", sizeof(flags));
2460			else
2461				strlcat(flags, "|NONSEC", sizeof(flags));
2462		}
2463		if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2464			if (flags[0] == '\0')
2465				strlcpy(flags, "OPTOUT", sizeof(flags));
2466			else
2467				strlcat(flags, "|OPTOUT", sizeof(flags));
2468		}
2469	}
2470	if (nsec3param->salt_length == 0)
2471		strlcpy(saltbuf, "-", sizeof(saltbuf));
2472	else
2473		for (i = 0; i < nsec3param->salt_length; i++)
2474			sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2475	dns_zone_log(zone, ISC_LOG_INFO,
2476		     "zone_addnsec3chain(%u,%s,%u,%s)",
2477		      nsec3param->hash, flags, nsec3param->iterations,
2478		      saltbuf);
2479	for (current = ISC_LIST_HEAD(zone->nsec3chain);
2480	     current != NULL;
2481	     current = ISC_LIST_NEXT(current, link)) {
2482		if (current->db == zone->db &&
2483		    current->nsec3param.hash == nsec3param->hash &&
2484		    current->nsec3param.iterations == nsec3param->iterations &&
2485		    current->nsec3param.salt_length == nsec3param->salt_length
2486		    && !memcmp(current->nsec3param.salt, nsec3param->salt,
2487			       nsec3param->salt_length))
2488			current->done = ISC_TRUE;
2489	}
2490
2491	if (zone->db != NULL) {
2492		dns_db_attach(zone->db, &nsec3chain->db);
2493		if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2494			options = DNS_DB_NONSEC3;
2495		result = dns_db_createiterator(nsec3chain->db, options,
2496					       &nsec3chain->dbiterator);
2497		if (result == ISC_R_SUCCESS)
2498			dns_dbiterator_first(nsec3chain->dbiterator);
2499		if (result == ISC_R_SUCCESS) {
2500			dns_dbiterator_pause(nsec3chain->dbiterator);
2501			ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2502					       nsec3chain, link);
2503			nsec3chain = NULL;
2504			if (isc_time_isepoch(&zone->nsec3chaintime)) {
2505				TIME_NOW(&now);
2506				zone->nsec3chaintime = now;
2507				if (zone->task != NULL)
2508					zone_settimer(zone, &now);
2509			}
2510		}
2511	} else
2512		result = ISC_R_NOTFOUND;
2513
2514	if (nsec3chain != NULL) {
2515		if (nsec3chain->db != NULL)
2516			dns_db_detach(&nsec3chain->db);
2517		if (nsec3chain->dbiterator != NULL)
2518			dns_dbiterator_destroy(&nsec3chain->dbiterator);
2519		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2520	}
2521	return (result);
2522}
2523
2524static void
2525resume_addnsec3chain(dns_zone_t *zone) {
2526	dns_dbnode_t *node = NULL;
2527	dns_dbversion_t *version = NULL;
2528	dns_rdataset_t rdataset;
2529	isc_result_t result;
2530	dns_rdata_nsec3param_t nsec3param;
2531
2532	if (zone->privatetype == 0)
2533		return;
2534
2535	result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2536	if (result != ISC_R_SUCCESS)
2537		goto cleanup;
2538
2539	dns_db_currentversion(zone->db, &version);
2540	dns_rdataset_init(&rdataset);
2541	result = dns_db_findrdataset(zone->db, node, version,
2542				     zone->privatetype, dns_rdatatype_none,
2543				     0, &rdataset, NULL);
2544	if (result != ISC_R_SUCCESS) {
2545		INSIST(!dns_rdataset_isassociated(&rdataset));
2546		goto cleanup;
2547	}
2548
2549	for (result = dns_rdataset_first(&rdataset);
2550	     result == ISC_R_SUCCESS;
2551	     result = dns_rdataset_next(&rdataset))
2552	{
2553		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
2554		dns_rdata_t rdata = DNS_RDATA_INIT;
2555		dns_rdata_t private = DNS_RDATA_INIT;
2556
2557		dns_rdataset_current(&rdataset, &private);
2558		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
2559						sizeof(buf)))
2560			continue;
2561		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2562		RUNTIME_CHECK(result == ISC_R_SUCCESS);
2563		if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 ||
2564		    (nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
2565			result = zone_addnsec3chain(zone, &nsec3param);
2566			if (result != ISC_R_SUCCESS) {
2567				dns_zone_log(zone, ISC_LOG_ERROR,
2568					     "zone_addnsec3chain failed: %s",
2569					     dns_result_totext(result));
2570			}
2571		}
2572	}
2573	dns_rdataset_disassociate(&rdataset);
2574 cleanup:
2575	if (node != NULL)
2576		dns_db_detachnode(zone->db, &node);
2577	if (version != NULL)
2578		dns_db_closeversion(zone->db, &version, ISC_FALSE);
2579}
2580
2581static void
2582set_resigntime(dns_zone_t *zone) {
2583	dns_rdataset_t rdataset;
2584	dns_fixedname_t fixed;
2585	unsigned int resign;
2586	isc_result_t result;
2587	isc_uint32_t nanosecs;
2588
2589	dns_rdataset_init(&rdataset);
2590	dns_fixedname_init(&fixed);
2591	result = dns_db_getsigningtime(zone->db, &rdataset,
2592				       dns_fixedname_name(&fixed));
2593	if (result != ISC_R_SUCCESS) {
2594		isc_time_settoepoch(&zone->resigntime);
2595		return;
2596	}
2597	resign = rdataset.resign;
2598	dns_rdataset_disassociate(&rdataset);
2599	isc_random_get(&nanosecs);
2600	nanosecs %= 1000000000;
2601	isc_time_set(&zone->resigntime, resign, nanosecs);
2602}
2603
2604static isc_result_t
2605check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
2606	dns_dbnode_t *node = NULL;
2607	dns_rdataset_t rdataset;
2608	dns_dbversion_t *version = NULL;
2609	dns_rdata_nsec3param_t nsec3param;
2610	isc_boolean_t ok = ISC_FALSE;
2611	isc_result_t result;
2612	dns_rdata_t rdata = DNS_RDATA_INIT;
2613	isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
2614				zone_isdynamic(zone) : ISC_FALSE;
2615
2616	dns_rdataset_init(&rdataset);
2617	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2618	if (result != ISC_R_SUCCESS) {
2619		dns_zone_log(zone, ISC_LOG_ERROR,
2620			     "nsec3param lookup failure: %s",
2621			     dns_result_totext(result));
2622		return (result);
2623	}
2624	dns_db_currentversion(db, &version);
2625
2626	result = dns_db_findrdataset(db, node, version,
2627				     dns_rdatatype_nsec3param,
2628				     dns_rdatatype_none, 0, &rdataset, NULL);
2629	if (result == ISC_R_NOTFOUND) {
2630		INSIST(!dns_rdataset_isassociated(&rdataset));
2631		result = ISC_R_SUCCESS;
2632		goto cleanup;
2633	}
2634	if (result != ISC_R_SUCCESS) {
2635		INSIST(!dns_rdataset_isassociated(&rdataset));
2636		dns_zone_log(zone, ISC_LOG_ERROR,
2637			     "nsec3param lookup failure: %s",
2638			     dns_result_totext(result));
2639		goto cleanup;
2640	}
2641
2642	/*
2643	 * For dynamic zones we must support every algorithm so we can
2644	 * regenerate all the NSEC3 chains.
2645	 * For non-dynamic zones we only need to find a supported algorithm.
2646	 */
2647	for (result = dns_rdataset_first(&rdataset);
2648	     result == ISC_R_SUCCESS;
2649	     result = dns_rdataset_next(&rdataset))
2650	{
2651		dns_rdataset_current(&rdataset, &rdata);
2652		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2653		dns_rdata_reset(&rdata);
2654		INSIST(result == ISC_R_SUCCESS);
2655		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
2656		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
2657		{
2658			dns_zone_log(zone, ISC_LOG_WARNING,
2659			     "nsec3 test \"unknown\" hash algorithm found: %u",
2660				     nsec3param.hash);
2661			ok = ISC_TRUE;
2662		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
2663			if (dynamic) {
2664				dns_zone_log(zone, ISC_LOG_ERROR,
2665					     "unsupported nsec3 hash algorithm"
2666					     " in dynamic zone: %u",
2667					     nsec3param.hash);
2668				result = DNS_R_BADZONE;
2669				/* Stop second error message. */
2670				ok = ISC_TRUE;
2671				break;
2672			} else
2673				dns_zone_log(zone, ISC_LOG_WARNING,
2674				     "unsupported nsec3 hash algorithm: %u",
2675					     nsec3param.hash);
2676		} else
2677			ok = ISC_TRUE;
2678	}
2679	if (result == ISC_R_NOMORE)
2680		result = ISC_R_SUCCESS;
2681
2682	if (!ok) {
2683		result = DNS_R_BADZONE;
2684		dns_zone_log(zone, ISC_LOG_ERROR,
2685			     "no supported nsec3 hash algorithm");
2686	}
2687
2688 cleanup:
2689	if (dns_rdataset_isassociated(&rdataset))
2690		dns_rdataset_disassociate(&rdataset);
2691	dns_db_closeversion(db, &version, ISC_FALSE);
2692	dns_db_detachnode(db, &node);
2693	return (result);
2694}
2695
2696/*
2697 * Set the timer for refreshing the key zone to the soonest future time
2698 * of the set (current timer, keydata->refresh, keydata->addhd,
2699 * keydata->removehd).
2700 */
2701static void
2702set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
2703		    isc_stdtime_t now)
2704{
2705	const char me[] = "set_refreshkeytimer";
2706	isc_stdtime_t then;
2707	isc_time_t timenow, timethen;
2708	char timebuf[80];
2709
2710	ENTER;
2711	then = key->refresh;
2712	if (key->addhd > now && key->addhd < then)
2713		then = key->addhd;
2714	if (key->removehd > now && key->removehd < then)
2715		then = key->removehd;
2716
2717	TIME_NOW(&timenow);
2718	if (then > now)
2719		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
2720	else
2721		timethen = timenow;
2722	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
2723	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
2724		zone->refreshkeytime = timethen;
2725
2726	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
2727	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
2728	zone_settimer(zone, &timenow);
2729}
2730
2731/*
2732 * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
2733 * If the key zone is changed, set '*changed' to ISC_TRUE.
2734 */
2735static isc_result_t
2736create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
2737	       dns_diff_t *diff, dns_keytable_t *keytable,
2738	       dns_keynode_t **keynodep, isc_boolean_t *changed)
2739{
2740	const char me[] = "create_keydata";
2741	isc_result_t result = ISC_R_SUCCESS;
2742	isc_buffer_t keyb, dstb;
2743	unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
2744	dns_rdata_keydata_t keydata;
2745	dns_rdata_dnskey_t dnskey;
2746	dns_rdata_t rdata = DNS_RDATA_INIT;
2747	dns_keynode_t *keynode;
2748	isc_stdtime_t now;
2749	isc_region_t r;
2750	dst_key_t *key;
2751
2752	REQUIRE(keynodep != NULL);
2753	keynode = *keynodep;
2754
2755	ENTER;
2756	isc_stdtime_get(&now);
2757
2758	/* Loop in case there's more than one key. */
2759	while (result == ISC_R_SUCCESS) {
2760		dns_keynode_t *nextnode = NULL;
2761
2762		key = dns_keynode_key(keynode);
2763		if (key == NULL)
2764			goto skip;
2765
2766		isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
2767		CHECK(dst_key_todns(key, &dstb));
2768
2769		/* Convert DST key to DNSKEY. */
2770		dns_rdata_reset(&rdata);
2771		isc_buffer_usedregion(&dstb, &r);
2772		dns_rdata_fromregion(&rdata, dst_key_class(key),
2773				     dns_rdatatype_dnskey, &r);
2774
2775		/* DSTKEY to KEYDATA. */
2776		CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
2777		CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
2778					     NULL));
2779
2780		/* KEYDATA to rdata. */
2781		dns_rdata_reset(&rdata);
2782		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
2783		CHECK(dns_rdata_fromstruct(&rdata,
2784					   zone->rdclass, dns_rdatatype_keydata,
2785					   &keydata, &keyb));
2786
2787		/* Add rdata to zone. */
2788		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
2789				    dst_key_name(key), 0, &rdata));
2790		*changed = ISC_TRUE;
2791
2792 skip:
2793		result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
2794		if (result != ISC_R_NOTFOUND) {
2795			dns_keytable_detachkeynode(keytable, &keynode);
2796			keynode = nextnode;
2797		}
2798	}
2799
2800	/* Refresh new keys from the zone apex as soon as possible. */
2801	if (*changed)
2802		set_refreshkeytimer(zone, &keydata, now);
2803
2804	if (keynode != NULL)
2805		dns_keytable_detachkeynode(keytable, &keynode);
2806	*keynodep = NULL;
2807
2808	return (ISC_R_SUCCESS);
2809
2810  failure:
2811	return (result);
2812}
2813
2814/*
2815 * Remove from the key zone all the KEYDATA records found in rdataset.
2816 */
2817static isc_result_t
2818delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
2819	       dns_name_t *name, dns_rdataset_t *rdataset)
2820{
2821	dns_rdata_t rdata = DNS_RDATA_INIT;
2822	isc_result_t result, uresult;
2823
2824	for (result = dns_rdataset_first(rdataset);
2825	     result == ISC_R_SUCCESS;
2826	     result = dns_rdataset_next(rdataset)) {
2827		dns_rdata_reset(&rdata);
2828		dns_rdataset_current(rdataset, &rdata);
2829		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
2830					name, 0, &rdata);
2831		if (uresult != ISC_R_SUCCESS)
2832			return (uresult);
2833	}
2834	if (result == ISC_R_NOMORE)
2835		result = ISC_R_SUCCESS;
2836	return (result);
2837}
2838
2839/*
2840 * Compute the DNSSEC key ID for a DNSKEY record.
2841 */
2842static isc_result_t
2843compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
2844	    dns_keytag_t *tag)
2845{
2846	isc_result_t result;
2847	dns_rdata_t rdata = DNS_RDATA_INIT;
2848	unsigned char data[4096];
2849	isc_buffer_t buffer;
2850	dst_key_t *dstkey = NULL;
2851
2852	isc_buffer_init(&buffer, data, sizeof(data));
2853	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
2854			     dns_rdatatype_dnskey, dnskey, &buffer);
2855
2856	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
2857	if (result == ISC_R_SUCCESS)
2858		*tag = dst_key_id(dstkey);
2859	dst_key_free(&dstkey);
2860
2861	return (result);
2862}
2863
2864/*
2865 * Add key to the security roots.
2866 */
2867static void
2868trust_key(dns_zone_t *zone, dns_name_t *keyname,
2869	  dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
2870	isc_result_t result;
2871	dns_rdata_t rdata = DNS_RDATA_INIT;
2872	unsigned char data[4096];
2873	isc_buffer_t buffer;
2874	dns_keytable_t *sr = NULL;
2875	dst_key_t *dstkey = NULL;
2876
2877	/* Convert dnskey to DST key. */
2878	isc_buffer_init(&buffer, data, sizeof(data));
2879	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
2880			     dns_rdatatype_dnskey, dnskey, &buffer);
2881
2882	result = dns_view_getsecroots(zone->view, &sr);
2883	if (result != ISC_R_SUCCESS)
2884		goto failure;
2885
2886	CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
2887	CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
2888	dns_keytable_detach(&sr);
2889
2890  failure:
2891	if (dstkey != NULL)
2892		dst_key_free(&dstkey);
2893	if (sr != NULL)
2894		dns_keytable_detach(&sr);
2895	return;
2896}
2897
2898/*
2899 * Add a null key to the security roots for so that all queries
2900 * to the zone will fail.
2901 */
2902static void
2903fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
2904	isc_result_t result;
2905	dns_keytable_t *sr = NULL;
2906
2907	result = dns_view_getsecroots(zone->view, &sr);
2908	if (result == ISC_R_SUCCESS) {
2909		dns_keytable_marksecure(sr, keyname);
2910		dns_keytable_detach(&sr);
2911	}
2912}
2913
2914/*
2915 * Scan a set of KEYDATA records from the key zone.  The ones that are
2916 * valid (i.e., the add holddown timer has expired) become trusted keys.
2917 */
2918static void
2919load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
2920	isc_result_t result;
2921	dns_rdata_t rdata = DNS_RDATA_INIT;
2922	dns_rdata_keydata_t keydata;
2923	dns_rdata_dnskey_t dnskey;
2924	isc_mem_t *mctx = zone->mctx;
2925	int trusted = 0, revoked = 0, pending = 0;
2926	isc_stdtime_t now;
2927	dns_keytable_t *sr = NULL;
2928
2929	isc_stdtime_get(&now);
2930
2931	result = dns_view_getsecroots(zone->view, &sr);
2932	if (result == ISC_R_SUCCESS) {
2933		dns_keytable_delete(sr, name);
2934		dns_keytable_detach(&sr);
2935	}
2936
2937	/* Now insert all the accepted trust anchors from this keydata set. */
2938	for (result = dns_rdataset_first(rdataset);
2939	     result == ISC_R_SUCCESS;
2940	     result = dns_rdataset_next(rdataset)) {
2941		dns_rdata_reset(&rdata);
2942		dns_rdataset_current(rdataset, &rdata);
2943
2944		/* Convert rdata to keydata. */
2945		dns_rdata_tostruct(&rdata, &keydata, NULL);
2946
2947		/* Set the key refresh timer. */
2948		set_refreshkeytimer(zone, &keydata, now);
2949
2950		/* If the removal timer is nonzero, this key was revoked. */
2951		if (keydata.removehd != 0) {
2952			revoked++;
2953			continue;
2954		}
2955
2956		/*
2957		 * If the add timer is still pending, this key is not
2958		 * trusted yet.
2959		 */
2960		if (now < keydata.addhd) {
2961			pending++;
2962			continue;
2963		}
2964
2965		/* Convert keydata to dnskey. */
2966		dns_keydata_todnskey(&keydata, &dnskey, NULL);
2967
2968		/* Add to keytables. */
2969		trusted++;
2970		trust_key(zone, name, &dnskey, mctx);
2971	}
2972
2973	if (trusted == 0 && pending != 0) {
2974		char namebuf[DNS_NAME_FORMATSIZE];
2975		dns_name_format(name, namebuf, sizeof namebuf);
2976		dns_zone_log(zone, ISC_LOG_ERROR,
2977			     "No valid trust anchors for '%s'!", namebuf);
2978		dns_zone_log(zone, ISC_LOG_ERROR,
2979			     "%d key(s) revoked, %d still pending",
2980			     revoked, pending);
2981		dns_zone_log(zone, ISC_LOG_ERROR,
2982			     "All queries to '%s' will fail", namebuf);
2983		fail_secure(zone, name);
2984	}
2985}
2986
2987static isc_result_t
2988do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
2989	     dns_diff_t *diff)
2990{
2991	dns_diff_t temp_diff;
2992	isc_result_t result;
2993
2994	/*
2995	 * Create a singleton diff.
2996	 */
2997	dns_diff_init(diff->mctx, &temp_diff);
2998	temp_diff.resign = diff->resign;
2999	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3000
3001	/*
3002	 * Apply it to the database.
3003	 */
3004	result = dns_diff_apply(&temp_diff, db, ver);
3005	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3006	if (result != ISC_R_SUCCESS) {
3007		dns_difftuple_free(tuple);
3008		return (result);
3009	}
3010
3011	/*
3012	 * Merge it into the current pending journal entry.
3013	 */
3014	dns_diff_appendminimal(diff, tuple);
3015
3016	/*
3017	 * Do not clear temp_diff.
3018	 */
3019	return (ISC_R_SUCCESS);
3020}
3021
3022static isc_result_t
3023update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3024	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3025	      dns_rdata_t *rdata)
3026{
3027	dns_difftuple_t *tuple = NULL;
3028	isc_result_t result;
3029	result = dns_difftuple_create(diff->mctx, op,
3030				      name, ttl, rdata, &tuple);
3031	if (result != ISC_R_SUCCESS)
3032		return (result);
3033	return (do_one_tuple(&tuple, db, ver, diff));
3034}
3035
3036static isc_result_t
3037increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver,
3038		     dns_diff_t *diff, isc_mem_t *mctx) {
3039	dns_difftuple_t *deltuple = NULL;
3040	dns_difftuple_t *addtuple = NULL;
3041	isc_uint32_t serial;
3042	isc_result_t result;
3043
3044	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3045	CHECK(dns_difftuple_copy(deltuple, &addtuple));
3046	addtuple->op = DNS_DIFFOP_ADD;
3047
3048	serial = dns_soa_getserial(&addtuple->rdata);
3049
3050	/* RFC1982 */
3051	serial = (serial + 1) & 0xFFFFFFFF;
3052	if (serial == 0)
3053		serial = 1;
3054
3055	dns_soa_setserial(serial, &addtuple->rdata);
3056	CHECK(do_one_tuple(&deltuple, db, ver, diff));
3057	CHECK(do_one_tuple(&addtuple, db, ver, diff));
3058	result = ISC_R_SUCCESS;
3059
3060	failure:
3061	if (addtuple != NULL)
3062		dns_difftuple_free(&addtuple);
3063	if (deltuple != NULL)
3064		dns_difftuple_free(&deltuple);
3065	return (result);
3066}
3067
3068/*
3069 * Write all transactions in 'diff' to the zone journal file.
3070 */
3071static isc_result_t
3072zone_journal(dns_zone_t *zone, dns_diff_t *diff, const char *caller) {
3073	const char me[] = "zone_journal";
3074	const char *journalfile;
3075	isc_result_t result = ISC_R_SUCCESS;
3076	dns_journal_t *journal = NULL;
3077
3078	ENTER;
3079	journalfile = dns_zone_getjournal(zone);
3080	if (journalfile != NULL) {
3081		result = dns_journal_open(zone->mctx, journalfile,
3082					  ISC_TRUE, &journal);
3083		if (result != ISC_R_SUCCESS) {
3084			dns_zone_log(zone, ISC_LOG_ERROR,
3085				     "%s:dns_journal_open -> %s\n",
3086				     caller, dns_result_totext(result));
3087			return (result);
3088		}
3089
3090		result = dns_journal_write_transaction(journal, diff);
3091		dns_journal_destroy(&journal);
3092		if (result != ISC_R_SUCCESS) {
3093			dns_zone_log(zone, ISC_LOG_ERROR,
3094				     "%s:dns_journal_write_transaction -> %s\n",
3095				     caller, dns_result_totext(result));
3096			return (result);
3097		}
3098	}
3099	return (result);
3100}
3101
3102/*
3103 * Create an SOA record for a newly-created zone
3104 */
3105static isc_result_t
3106add_soa(dns_zone_t *zone, dns_db_t *db) {
3107	isc_result_t result;
3108	dns_rdata_t rdata = DNS_RDATA_INIT;
3109	unsigned char buf[DNS_SOA_BUFFERSIZE];
3110	dns_dbversion_t *ver = NULL;
3111	dns_diff_t diff;
3112
3113	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3114
3115	dns_diff_init(zone->mctx, &diff);
3116	result = dns_db_newversion(db, &ver);
3117	if (result != ISC_R_SUCCESS) {
3118		dns_zone_log(zone, ISC_LOG_ERROR,
3119			     "add_soa:dns_db_newversion -> %s\n",
3120			     dns_result_totext(result));
3121		goto failure;
3122	}
3123
3124	/* Build SOA record */
3125	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3126				    0, 0, 0, 0, 0, buf, &rdata);
3127	if (result != ISC_R_SUCCESS) {
3128		dns_zone_log(zone, ISC_LOG_ERROR,
3129			     "add_soa:dns_soa_buildrdata -> %s\n",
3130			     dns_result_totext(result));
3131		goto failure;
3132	}
3133
3134	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3135			       &zone->origin, 0, &rdata);
3136
3137failure:
3138	dns_diff_clear(&diff);
3139	if (ver != NULL)
3140		dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3141
3142	return (result);
3143}
3144
3145/*
3146 * Synchronize the set of initializing keys found in managed-keys {}
3147 * statements with the set of trust anchors found in the managed-keys.bind
3148 * zone.  If a domain is no longer named in managed-keys, delete all keys
3149 * from that domain from the key zone.	If a domain is mentioned in in
3150 * managed-keys but there are no references to it in the key zone, load
3151 * the key zone with the initializing key(s) for that domain.
3152 */
3153static isc_result_t
3154sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3155	isc_result_t result = ISC_R_SUCCESS;
3156	isc_boolean_t changed = ISC_FALSE;
3157	isc_boolean_t commit = ISC_FALSE;
3158	dns_rbtnodechain_t chain;
3159	dns_fixedname_t fn;
3160	dns_name_t foundname, *origin;
3161	dns_keynode_t *keynode = NULL;
3162	dns_view_t *view = zone->view;
3163	dns_keytable_t *sr = NULL;
3164	dns_dbversion_t *ver = NULL;
3165	dns_diff_t diff;
3166	dns_rriterator_t rrit;
3167
3168	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3169
3170	dns_name_init(&foundname, NULL);
3171	dns_fixedname_init(&fn);
3172	origin = dns_fixedname_name(&fn);
3173
3174	dns_diff_init(zone->mctx, &diff);
3175
3176	CHECK(dns_view_getsecroots(view, &sr));
3177
3178	result = dns_db_newversion(db, &ver);
3179	if (result != ISC_R_SUCCESS) {
3180		dns_zone_log(zone, ISC_LOG_ERROR,
3181			     "sync_keyzone:dns_db_newversion -> %s\n",
3182			     dns_result_totext(result));
3183		goto failure;
3184	}
3185
3186	/*
3187	 * Walk the zone DB.  If we find any keys whose names are no longer
3188	 * in managed-keys (or *are* in trusted-keys, meaning they are
3189	 * permanent and not RFC5011-maintained), delete them from the
3190	 * zone.  Otherwise call load_secroots(), which loads keys into
3191	 * secroots as appropriate.
3192	 */
3193	dns_rriterator_init(&rrit, db, ver, 0);
3194	for (result = dns_rriterator_first(&rrit);
3195	     result == ISC_R_SUCCESS;
3196	     result = dns_rriterator_nextrrset(&rrit)) {
3197		dns_rdataset_t *rdataset = NULL;
3198		dns_name_t *rrname = NULL;
3199		isc_uint32_t ttl;
3200
3201		dns_rriterator_current(&rrit, &rrname, &ttl,
3202				       &rdataset, NULL);
3203		if (!dns_rdataset_isassociated(rdataset)) {
3204			dns_rriterator_destroy(&rrit);
3205			goto failure;
3206		}
3207
3208		if (rdataset->type != dns_rdatatype_keydata)
3209			continue;
3210
3211		result = dns_keytable_find(sr, rrname, &keynode);
3212		if ((result != ISC_R_SUCCESS &&
3213		     result != DNS_R_PARTIALMATCH) ||
3214		    dns_keynode_managed(keynode) == ISC_FALSE) {
3215			CHECK(delete_keydata(db, ver, &diff,
3216					     rrname, rdataset));
3217			changed = ISC_TRUE;
3218		} else {
3219			load_secroots(zone, rrname, rdataset);
3220		}
3221
3222		if (keynode != NULL)
3223			dns_keytable_detachkeynode(sr, &keynode);
3224	}
3225	dns_rriterator_destroy(&rrit);
3226
3227	/*
3228	 * Now walk secroots to find any managed keys that aren't
3229	 * in the zone.  If we find any, we add them to the zone.
3230	 */
3231	RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3232	dns_rbtnodechain_init(&chain, zone->mctx);
3233	result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3234	if (result == ISC_R_NOTFOUND)
3235		result = ISC_R_NOMORE;
3236	while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3237		dns_rbtnode_t *rbtnode = NULL;
3238
3239		dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3240		if (rbtnode->data == NULL)
3241			goto skip;
3242
3243		dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3244		if (dns_keynode_managed(keynode)) {
3245			dns_fixedname_t fname;
3246			dns_name_t *keyname;
3247			dst_key_t *key;
3248
3249			key = dns_keynode_key(keynode);
3250			dns_fixedname_init(&fname);
3251
3252			if (key == NULL)   /* fail_secure() was called. */
3253				goto skip;
3254
3255			keyname = dst_key_name(key);
3256			result = dns_db_find(db, keyname, ver,
3257					     dns_rdatatype_keydata,
3258					     DNS_DBFIND_NOWILD, 0, NULL,
3259					     dns_fixedname_name(&fname),
3260					     NULL, NULL);
3261			if (result != ISC_R_SUCCESS)
3262				result = create_keydata(zone, db, ver, &diff,
3263							sr, &keynode, &changed);
3264			if (result != ISC_R_SUCCESS)
3265				break;
3266		}
3267  skip:
3268		result = dns_rbtnodechain_next(&chain, &foundname, origin);
3269		if (keynode != NULL)
3270			dns_keytable_detachkeynode(sr, &keynode);
3271	}
3272	RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3273
3274	if (result == ISC_R_NOMORE)
3275		result = ISC_R_SUCCESS;
3276
3277	if (changed) {
3278		/* Write changes to journal file. */
3279		CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
3280		CHECK(zone_journal(zone, &diff, "sync_keyzone"));
3281
3282		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3283		zone_needdump(zone, 30);
3284		commit = ISC_TRUE;
3285	}
3286
3287 failure:
3288	if (keynode != NULL)
3289		dns_keytable_detachkeynode(sr, &keynode);
3290	if (sr != NULL)
3291		dns_keytable_detach(&sr);
3292	if (ver != NULL)
3293		dns_db_closeversion(db, &ver, commit);
3294	dns_diff_clear(&diff);
3295
3296	return (result);
3297}
3298
3299static isc_result_t
3300zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3301	      isc_result_t result)
3302{
3303	unsigned int soacount = 0;
3304	unsigned int nscount = 0;
3305	unsigned int errors = 0;
3306	isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3307	isc_time_t now;
3308	isc_boolean_t needdump = ISC_FALSE;
3309	isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3310	isc_boolean_t nomaster = ISC_FALSE;
3311	unsigned int options;
3312
3313	TIME_NOW(&now);
3314
3315	/*
3316	 * Initiate zone transfer?  We may need a error code that
3317	 * indicates that the "permanent" form does not exist.
3318	 * XXX better error feedback to log.
3319	 */
3320	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3321		if (zone->type == dns_zone_slave ||
3322		    zone->type == dns_zone_stub) {
3323			if (result == ISC_R_FILENOTFOUND)
3324				dns_zone_log(zone, ISC_LOG_DEBUG(1),
3325					     "no master file");
3326			else if (result != DNS_R_NOMASTERFILE)
3327				dns_zone_log(zone, ISC_LOG_ERROR,
3328					     "loading from master file %s "
3329					     "failed: %s",
3330					     zone->masterfile,
3331					     dns_result_totext(result));
3332		} else {
3333			int level = ISC_LOG_ERROR;
3334			if (zone->type == dns_zone_key &&
3335			    result == ISC_R_FILENOTFOUND)
3336				level = ISC_LOG_DEBUG(1);
3337			dns_zone_log(zone, level,
3338				     "loading from master file %s failed: %s",
3339				     zone->masterfile,
3340				     dns_result_totext(result));
3341			nomaster = ISC_TRUE;
3342		}
3343
3344		if (zone->type != dns_zone_key)
3345			goto cleanup;
3346	}
3347
3348	dns_zone_log(zone, ISC_LOG_DEBUG(2),
3349		     "number of nodes in database: %u",
3350		     dns_db_nodecount(db));
3351
3352	if (result == DNS_R_SEENINCLUDE)
3353		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3354	else
3355		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3356
3357	/*
3358	 * If there's no master file for a key zone, then the zone is new:
3359	 * create an SOA record.  (We do this now, instead of later, so that
3360	 * if there happens to be a journal file, we can roll forward from
3361	 * a sane starting point.)
3362	 */
3363	if (nomaster && zone->type == dns_zone_key) {
3364		result = add_soa(zone, db);
3365		if (result != ISC_R_SUCCESS)
3366			goto cleanup;
3367	}
3368
3369	/*
3370	 * Apply update log, if any, on initial load.
3371	 */
3372	if (zone->journal != NULL &&
3373	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
3374	    ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3375	{
3376		if (zone->type == dns_zone_master &&
3377		    (zone->update_acl != NULL || zone->ssutable != NULL))
3378			options = DNS_JOURNALOPT_RESIGN;
3379		else
3380			options = 0;
3381		result = dns_journal_rollforward2(zone->mctx, db, options,
3382						  zone->sigresigninginterval,
3383						  zone->journal);
3384		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
3385		    result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
3386		    result != ISC_R_RANGE) {
3387			dns_zone_log(zone, ISC_LOG_ERROR,
3388				     "journal rollforward failed: %s",
3389				     dns_result_totext(result));
3390			goto cleanup;
3391		}
3392		if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
3393			dns_zone_log(zone, ISC_LOG_ERROR,
3394				     "journal rollforward failed: "
3395				     "journal out of sync with zone");
3396			goto cleanup;
3397		}
3398		dns_zone_log(zone, ISC_LOG_DEBUG(1),
3399			     "journal rollforward completed "
3400			     "successfully: %s",
3401			     dns_result_totext(result));
3402		if (result == ISC_R_SUCCESS)
3403			needdump = ISC_TRUE;
3404	}
3405
3406	dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
3407	/*
3408	 * Obtain ns, soa and cname counts for top of zone.
3409	 */
3410	INSIST(db != NULL);
3411	result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
3412				  &refresh, &retry, &expire, &minimum,
3413				  &errors);
3414	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
3415		dns_zone_log(zone, ISC_LOG_ERROR,
3416			     "could not find NS and/or SOA records");
3417	}
3418
3419	/*
3420	 * Master / Slave / Stub zones require both NS and SOA records at
3421	 * the top of the zone.
3422	 */
3423
3424	switch (zone->type) {
3425	case dns_zone_dlz:
3426	case dns_zone_master:
3427	case dns_zone_slave:
3428	case dns_zone_stub:
3429		if (soacount != 1) {
3430			dns_zone_log(zone, ISC_LOG_ERROR,
3431				     "has %d SOA records", soacount);
3432			result = DNS_R_BADZONE;
3433		}
3434		if (nscount == 0) {
3435			dns_zone_log(zone, ISC_LOG_ERROR,
3436				     "has no NS records");
3437			result = DNS_R_BADZONE;
3438		}
3439		if (result != ISC_R_SUCCESS)
3440			goto cleanup;
3441		if (zone->type == dns_zone_master && errors != 0) {
3442			result = DNS_R_BADZONE;
3443			goto cleanup;
3444		}
3445		if (zone->type != dns_zone_stub) {
3446			result = check_nsec3param(zone, db);
3447			if (result != ISC_R_SUCCESS)
3448				goto cleanup;
3449		}
3450		if (zone->type == dns_zone_master &&
3451		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
3452		    !integrity_checks(zone, db)) {
3453			result = DNS_R_BADZONE;
3454			goto cleanup;
3455		}
3456
3457		if (zone->type == dns_zone_master &&
3458		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
3459		    !zone_check_dup(zone, db)) {
3460			result = DNS_R_BADZONE;
3461			goto cleanup;
3462		}
3463
3464		if (zone->db != NULL) {
3465			/*
3466			 * This is checked in zone_replacedb() for slave zones
3467			 * as they don't reload from disk.
3468			 */
3469			result = zone_get_from_db(zone, zone->db, NULL, NULL,
3470						  &oldserial, NULL, NULL, NULL,
3471						  NULL, NULL);
3472			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3473			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
3474			    !isc_serial_gt(serial, oldserial)) {
3475				isc_uint32_t serialmin, serialmax;
3476
3477				INSIST(zone->type == dns_zone_master);
3478
3479				serialmin = (oldserial + 1) & 0xffffffffU;
3480				serialmax = (oldserial + 0x7fffffffU) &
3481					     0xffffffffU;
3482				dns_zone_log(zone, ISC_LOG_ERROR,
3483					     "ixfr-from-differences: "
3484					     "new serial (%u) out of range "
3485					     "[%u - %u]", serial, serialmin,
3486					     serialmax);
3487				result = DNS_R_BADZONE;
3488				goto cleanup;
3489			} else if (!isc_serial_ge(serial, oldserial))
3490				dns_zone_log(zone, ISC_LOG_ERROR,
3491					     "zone serial (%u/%u) has gone "
3492					     "backwards", serial, oldserial);
3493			else if (serial == oldserial && !hasinclude &&
3494				 strcmp(zone->db_argv[0], "_builtin") != 0)
3495				dns_zone_log(zone, ISC_LOG_ERROR,
3496					     "zone serial (%u) unchanged. "
3497					     "zone may fail to transfer "
3498					     "to slaves.", serial);
3499		}
3500
3501		if (zone->type == dns_zone_master &&
3502		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
3503		    zone->sigresigninginterval < (3 * refresh) &&
3504		    dns_db_issecure(db))
3505		{
3506			dns_zone_log(zone, ISC_LOG_WARNING,
3507				     "sig-re-signing-interval less than "
3508				     "3 * refresh.");
3509		}
3510
3511		zone->refresh = RANGE(refresh,
3512				      zone->minrefresh, zone->maxrefresh);
3513		zone->retry = RANGE(retry,
3514				    zone->minretry, zone->maxretry);
3515		zone->expire = RANGE(expire, zone->refresh + zone->retry,
3516				     DNS_MAX_EXPIRE);
3517		zone->minimum = minimum;
3518		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
3519
3520		if (zone->type == dns_zone_slave ||
3521		    zone->type == dns_zone_stub) {
3522			isc_time_t t;
3523			isc_uint32_t delay;
3524
3525			result = isc_file_getmodtime(zone->journal, &t);
3526			if (result != ISC_R_SUCCESS)
3527				result = isc_file_getmodtime(zone->masterfile,
3528							     &t);
3529			if (result == ISC_R_SUCCESS)
3530				DNS_ZONE_TIME_ADD(&t, zone->expire,
3531						  &zone->expiretime);
3532			else
3533				DNS_ZONE_TIME_ADD(&now, zone->retry,
3534						  &zone->expiretime);
3535
3536			delay = isc_random_jitter(zone->retry,
3537						  (zone->retry * 3) / 4);
3538			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
3539			if (isc_time_compare(&zone->refreshtime,
3540					     &zone->expiretime) >= 0)
3541				zone->refreshtime = now;
3542		}
3543		break;
3544
3545	case dns_zone_key:
3546		result = sync_keyzone(zone, db);
3547		if (result != ISC_R_SUCCESS)
3548			goto cleanup;
3549		break;
3550
3551	default:
3552		UNEXPECTED_ERROR(__FILE__, __LINE__,
3553				 "unexpected zone type %d", zone->type);
3554		result = ISC_R_UNEXPECTED;
3555		goto cleanup;
3556	}
3557
3558	/*
3559	 * Check for weak DNSKEY's.
3560	 */
3561	if (zone->type == dns_zone_master)
3562		zone_check_dnskeys(zone, db);
3563
3564	/*
3565	 * Schedule DNSSEC key refresh.
3566	 */
3567	if (zone->type == dns_zone_master &&
3568	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
3569		zone->refreshkeytime = now;
3570
3571#if 0
3572	/* destroy notification example. */
3573	{
3574		isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
3575						    DNS_EVENT_DBDESTROYED,
3576						    dns_zonemgr_dbdestroyed,
3577						    zone,
3578						    sizeof(isc_event_t));
3579		dns_db_ondestroy(db, zone->task, &e);
3580	}
3581#endif
3582
3583	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
3584	if (zone->db != NULL) {
3585		result = zone_replacedb(zone, db, ISC_FALSE);
3586		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3587		if (result != ISC_R_SUCCESS)
3588			goto cleanup;
3589	} else {
3590		zone_attachdb(zone, db);
3591		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3592		DNS_ZONE_SETFLAG(zone,
3593				 DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
3594	}
3595
3596	result = ISC_R_SUCCESS;
3597
3598	if (needdump) {
3599		if (zone->type == dns_zone_key)
3600			zone_needdump(zone, 30);
3601		else
3602			zone_needdump(zone, DNS_DUMP_DELAY);
3603	}
3604
3605	if (zone->task != NULL) {
3606		if (zone->type == dns_zone_master) {
3607			set_resigntime(zone);
3608			resume_signingwithkey(zone);
3609			resume_addnsec3chain(zone);
3610		}
3611
3612		if (zone->type == dns_zone_master &&
3613		    zone_isdynamic(zone) &&
3614		    dns_db_issecure(db)) {
3615			dns_name_t *name;
3616			dns_fixedname_t fixed;
3617			dns_rdataset_t next;
3618
3619			dns_rdataset_init(&next);
3620			dns_fixedname_init(&fixed);
3621			name = dns_fixedname_name(&fixed);
3622
3623			result = dns_db_getsigningtime(db, &next, name);
3624			if (result == ISC_R_SUCCESS) {
3625				isc_stdtime_t timenow;
3626				char namebuf[DNS_NAME_FORMATSIZE];
3627				char typebuf[DNS_RDATATYPE_FORMATSIZE];
3628
3629				isc_stdtime_get(&timenow);
3630				dns_name_format(name, namebuf, sizeof(namebuf));
3631				dns_rdatatype_format(next.covers,
3632						     typebuf, sizeof(typebuf));
3633				dns_zone_log(zone, ISC_LOG_DEBUG(3),
3634					     "next resign: %s/%s in %d seconds",
3635					     namebuf, typebuf,
3636					     next.resign - timenow);
3637				dns_rdataset_disassociate(&next);
3638			} else
3639				dns_zone_log(zone, ISC_LOG_WARNING,
3640					     "signed dynamic zone has no "
3641					     "resign event scheduled");
3642		}
3643
3644		zone_settimer(zone, &now);
3645	}
3646
3647	if (! dns_db_ispersistent(db))
3648		dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
3649			     dns_db_issecure(db) ? " (DNSSEC signed)" : "");
3650
3651	zone->loadtime = loadtime;
3652	return (result);
3653
3654 cleanup:
3655	if (zone->type == dns_zone_slave ||
3656	    zone->type == dns_zone_stub ||
3657	    zone->type == dns_zone_key) {
3658		if (zone->journal != NULL)
3659			zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
3660		if (zone->masterfile != NULL)
3661			zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
3662
3663		/* Mark the zone for immediate refresh. */
3664		zone->refreshtime = now;
3665		if (zone->task != NULL)
3666			zone_settimer(zone, &now);
3667		result = ISC_R_SUCCESS;
3668	} else if (zone->type == dns_zone_master)
3669		dns_zone_log(zone, ISC_LOG_ERROR, "not loaded due to errors.");
3670	return (result);
3671}
3672
3673static isc_boolean_t
3674exit_check(dns_zone_t *zone) {
3675
3676	REQUIRE(LOCKED_ZONE(zone));
3677
3678	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
3679	    zone->irefs == 0)
3680	{
3681		/*
3682		 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
3683		 */
3684		INSIST(isc_refcount_current(&zone->erefs) == 0);
3685		return (ISC_TRUE);
3686	}
3687	return (ISC_FALSE);
3688}
3689
3690static isc_boolean_t
3691zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
3692	      dns_name_t *name, isc_boolean_t logit)
3693{
3694	isc_result_t result;
3695	char namebuf[DNS_NAME_FORMATSIZE];
3696	char altbuf[DNS_NAME_FORMATSIZE];
3697	dns_fixedname_t fixed;
3698	dns_name_t *foundname;
3699	int level;
3700
3701	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
3702		return (ISC_TRUE);
3703
3704	if (zone->type == dns_zone_master)
3705		level = ISC_LOG_ERROR;
3706	else
3707		level = ISC_LOG_WARNING;
3708
3709	dns_fixedname_init(&fixed);
3710	foundname = dns_fixedname_name(&fixed);
3711
3712	result = dns_db_find(db, name, version, dns_rdatatype_a,
3713			     0, 0, NULL, foundname, NULL, NULL);
3714	if (result == ISC_R_SUCCESS)
3715		return (ISC_TRUE);
3716
3717	if (result == DNS_R_NXRRSET) {
3718		result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
3719				     0, 0, NULL, foundname, NULL, NULL);
3720		if (result == ISC_R_SUCCESS)
3721			return (ISC_TRUE);
3722	}
3723
3724	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3725	    result == DNS_R_EMPTYNAME) {
3726		if (logit) {
3727			dns_name_format(name, namebuf, sizeof namebuf);
3728			dns_zone_log(zone, level, "NS '%s' has no address "
3729				     "records (A or AAAA)", namebuf);
3730		}
3731		return (ISC_FALSE);
3732	}
3733
3734	if (result == DNS_R_CNAME) {
3735		if (logit) {
3736			dns_name_format(name, namebuf, sizeof namebuf);
3737			dns_zone_log(zone, level, "NS '%s' is a CNAME "
3738				     "(illegal)", namebuf);
3739		}
3740		return (ISC_FALSE);
3741	}
3742
3743	if (result == DNS_R_DNAME) {
3744		if (logit) {
3745			dns_name_format(name, namebuf, sizeof namebuf);
3746			dns_name_format(foundname, altbuf, sizeof altbuf);
3747			dns_zone_log(zone, level, "NS '%s' is below a DNAME "
3748				     "'%s' (illegal)", namebuf, altbuf);
3749		}
3750		return (ISC_FALSE);
3751	}
3752
3753	return (ISC_TRUE);
3754}
3755
3756static isc_result_t
3757zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
3758		 dns_dbversion_t *version, unsigned int *nscount,
3759		 unsigned int *errors, isc_boolean_t logit)
3760{
3761	isc_result_t result;
3762	unsigned int count = 0;
3763	unsigned int ecount = 0;
3764	dns_rdataset_t rdataset;
3765	dns_rdata_t rdata;
3766	dns_rdata_ns_t ns;
3767
3768	dns_rdataset_init(&rdataset);
3769	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
3770				     dns_rdatatype_none, 0, &rdataset, NULL);
3771	if (result == ISC_R_NOTFOUND) {
3772		INSIST(!dns_rdataset_isassociated(&rdataset));
3773		goto success;
3774	}
3775	if (result != ISC_R_SUCCESS) {
3776		INSIST(!dns_rdataset_isassociated(&rdataset));
3777		goto invalidate_rdataset;
3778	}
3779
3780	result = dns_rdataset_first(&rdataset);
3781	while (result == ISC_R_SUCCESS) {
3782		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
3783		    (zone->type == dns_zone_master ||
3784		     zone->type == dns_zone_slave)) {
3785			dns_rdata_init(&rdata);
3786			dns_rdataset_current(&rdataset, &rdata);
3787			result = dns_rdata_tostruct(&rdata, &ns, NULL);
3788			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3789			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
3790			    !zone_check_ns(zone, db, version, &ns.name, logit))
3791				ecount++;
3792		}
3793		count++;
3794		result = dns_rdataset_next(&rdataset);
3795	}
3796	dns_rdataset_disassociate(&rdataset);
3797
3798 success:
3799	if (nscount != NULL)
3800		*nscount = count;
3801	if (errors != NULL)
3802		*errors = ecount;
3803
3804	result = ISC_R_SUCCESS;
3805
3806 invalidate_rdataset:
3807	dns_rdataset_invalidate(&rdataset);
3808
3809	return (result);
3810}
3811
3812static isc_result_t
3813zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
3814		 unsigned int *soacount,
3815		 isc_uint32_t *serial, isc_uint32_t *refresh,
3816		 isc_uint32_t *retry, isc_uint32_t *expire,
3817		 isc_uint32_t *minimum)
3818{
3819	isc_result_t result;
3820	unsigned int count;
3821	dns_rdataset_t rdataset;
3822	dns_rdata_t rdata = DNS_RDATA_INIT;
3823	dns_rdata_soa_t soa;
3824
3825	dns_rdataset_init(&rdataset);
3826	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
3827				     dns_rdatatype_none, 0, &rdataset, NULL);
3828	if (result == ISC_R_NOTFOUND) {
3829		INSIST(!dns_rdataset_isassociated(&rdataset));
3830		if (soacount != NULL)
3831			*soacount = 0;
3832		if (serial != NULL)
3833			*serial = 0;
3834		if (refresh != NULL)
3835			*refresh = 0;
3836		if (retry != NULL)
3837			*retry = 0;
3838		if (expire != NULL)
3839			*expire = 0;
3840		if (minimum != NULL)
3841			*minimum = 0;
3842		result = ISC_R_SUCCESS;
3843		goto invalidate_rdataset;
3844	}
3845	if (result != ISC_R_SUCCESS) {
3846		INSIST(!dns_rdataset_isassociated(&rdataset));
3847		goto invalidate_rdataset;
3848	}
3849
3850	count = 0;
3851	result = dns_rdataset_first(&rdataset);
3852	while (result == ISC_R_SUCCESS) {
3853		dns_rdata_init(&rdata);
3854		dns_rdataset_current(&rdataset, &rdata);
3855		count++;
3856		if (count == 1) {
3857			result = dns_rdata_tostruct(&rdata, &soa, NULL);
3858			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3859		}
3860
3861		result = dns_rdataset_next(&rdataset);
3862		dns_rdata_reset(&rdata);
3863	}
3864	dns_rdataset_disassociate(&rdataset);
3865
3866	if (soacount != NULL)
3867		*soacount = count;
3868
3869	if (count > 0) {
3870		if (serial != NULL)
3871			*serial = soa.serial;
3872		if (refresh != NULL)
3873			*refresh = soa.refresh;
3874		if (retry != NULL)
3875			*retry = soa.retry;
3876		if (expire != NULL)
3877			*expire = soa.expire;
3878		if (minimum != NULL)
3879			*minimum = soa.minimum;
3880	}
3881
3882	result = ISC_R_SUCCESS;
3883
3884 invalidate_rdataset:
3885	dns_rdataset_invalidate(&rdataset);
3886
3887	return (result);
3888}
3889
3890/*
3891 * zone must be locked.
3892 */
3893static isc_result_t
3894zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
3895		 unsigned int *soacount, isc_uint32_t *serial,
3896		 isc_uint32_t *refresh, isc_uint32_t *retry,
3897		 isc_uint32_t *expire, isc_uint32_t *minimum,
3898		 unsigned int *errors)
3899{
3900	isc_result_t result;
3901	isc_result_t answer = ISC_R_SUCCESS;
3902	dns_dbversion_t *version = NULL;
3903	dns_dbnode_t *node;
3904
3905	REQUIRE(db != NULL);
3906	REQUIRE(zone != NULL);
3907
3908	dns_db_currentversion(db, &version);
3909
3910	node = NULL;
3911	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3912	if (result != ISC_R_SUCCESS) {
3913		answer = result;
3914		goto closeversion;
3915	}
3916
3917	if (nscount != NULL || errors != NULL) {
3918		result = zone_count_ns_rr(zone, db, node, version,
3919					  nscount, errors, ISC_TRUE);
3920		if (result != ISC_R_SUCCESS)
3921			answer = result;
3922	}
3923
3924	if (soacount != NULL || serial != NULL || refresh != NULL
3925	    || retry != NULL || expire != NULL || minimum != NULL) {
3926		result = zone_load_soa_rr(db, node, version, soacount,
3927					  serial, refresh, retry, expire,
3928					  minimum);
3929		if (result != ISC_R_SUCCESS)
3930			answer = result;
3931	}
3932
3933	dns_db_detachnode(db, &node);
3934 closeversion:
3935	dns_db_closeversion(db, &version, ISC_FALSE);
3936
3937	return (answer);
3938}
3939
3940void
3941dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
3942	REQUIRE(DNS_ZONE_VALID(source));
3943	REQUIRE(target != NULL && *target == NULL);
3944	isc_refcount_increment(&source->erefs, NULL);
3945	*target = source;
3946}
3947
3948void
3949dns_zone_detach(dns_zone_t **zonep) {
3950	dns_zone_t *zone;
3951	unsigned int refs;
3952	isc_boolean_t free_now = ISC_FALSE;
3953
3954	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
3955
3956	zone = *zonep;
3957
3958	isc_refcount_decrement(&zone->erefs, &refs);
3959
3960	if (refs == 0) {
3961		LOCK_ZONE(zone);
3962		/*
3963		 * We just detached the last external reference.
3964		 */
3965		if (zone->task != NULL) {
3966			/*
3967			 * This zone is being managed.	Post
3968			 * its control event and let it clean
3969			 * up synchronously in the context of
3970			 * its task.
3971			 */
3972			isc_event_t *ev = &zone->ctlevent;
3973			isc_task_send(zone->task, &ev);
3974		} else {
3975			/*
3976			 * This zone is not being managed; it has
3977			 * no task and can have no outstanding
3978			 * events.  Free it immediately.
3979			 */
3980			/*
3981			 * Unmanaged zones should not have non-null views;
3982			 * we have no way of detaching from the view here
3983			 * without causing deadlock because this code is called
3984			 * with the view already locked.
3985			 */
3986			INSIST(zone->view == NULL);
3987			free_now = ISC_TRUE;
3988		}
3989		UNLOCK_ZONE(zone);
3990	}
3991	*zonep = NULL;
3992	if (free_now)
3993		zone_free(zone);
3994}
3995
3996void
3997dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
3998	REQUIRE(DNS_ZONE_VALID(source));
3999	REQUIRE(target != NULL && *target == NULL);
4000	LOCK_ZONE(source);
4001	zone_iattach(source, target);
4002	UNLOCK_ZONE(source);
4003}
4004
4005isc_result_t
4006dns_zone_synckeyzone(dns_zone_t *zone) {
4007	isc_result_t result;
4008	dns_db_t *db = NULL;
4009
4010	if (zone->type != dns_zone_key)
4011		return (DNS_R_BADZONE);
4012
4013	CHECK(dns_zone_getdb(zone, &db));
4014
4015	LOCK_ZONE(zone);
4016	result = sync_keyzone(zone, db);
4017	UNLOCK_ZONE(zone);
4018
4019 failure:
4020	if (db != NULL)
4021		dns_db_detach(&db);
4022	return (result);
4023}
4024
4025static void
4026zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4027
4028	/*
4029	 * 'source' locked by caller.
4030	 */
4031	REQUIRE(LOCKED_ZONE(source));
4032	REQUIRE(DNS_ZONE_VALID(source));
4033	REQUIRE(target != NULL && *target == NULL);
4034	INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
4035	source->irefs++;
4036	INSIST(source->irefs != 0);
4037	*target = source;
4038}
4039
4040static void
4041zone_idetach(dns_zone_t **zonep) {
4042	dns_zone_t *zone;
4043
4044	/*
4045	 * 'zone' locked by caller.
4046	 */
4047	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4048	zone = *zonep;
4049	REQUIRE(LOCKED_ZONE(*zonep));
4050	*zonep = NULL;
4051
4052	INSIST(zone->irefs > 0);
4053	zone->irefs--;
4054	INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4055}
4056
4057void
4058dns_zone_idetach(dns_zone_t **zonep) {
4059	dns_zone_t *zone;
4060	isc_boolean_t free_needed;
4061
4062	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4063	zone = *zonep;
4064	*zonep = NULL;
4065
4066	LOCK_ZONE(zone);
4067	INSIST(zone->irefs > 0);
4068	zone->irefs--;
4069	free_needed = exit_check(zone);
4070	UNLOCK_ZONE(zone);
4071	if (free_needed)
4072		zone_free(zone);
4073}
4074
4075isc_mem_t *
4076dns_zone_getmctx(dns_zone_t *zone) {
4077	REQUIRE(DNS_ZONE_VALID(zone));
4078
4079	return (zone->mctx);
4080}
4081
4082dns_zonemgr_t *
4083dns_zone_getmgr(dns_zone_t *zone) {
4084	REQUIRE(DNS_ZONE_VALID(zone));
4085
4086	return (zone->zmgr);
4087}
4088
4089void
4090dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4091	REQUIRE(DNS_ZONE_VALID(zone));
4092
4093	LOCK_ZONE(zone);
4094	if (value)
4095		DNS_ZONE_SETFLAG(zone, flags);
4096	else
4097		DNS_ZONE_CLRFLAG(zone, flags);
4098	UNLOCK_ZONE(zone);
4099}
4100
4101void
4102dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4103{
4104	REQUIRE(DNS_ZONE_VALID(zone));
4105
4106	LOCK_ZONE(zone);
4107	if (value)
4108		zone->options |= option;
4109	else
4110		zone->options &= ~option;
4111	UNLOCK_ZONE(zone);
4112}
4113
4114unsigned int
4115dns_zone_getoptions(dns_zone_t *zone) {
4116
4117	REQUIRE(DNS_ZONE_VALID(zone));
4118
4119	return (zone->options);
4120}
4121
4122void
4123dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4124{
4125	REQUIRE(DNS_ZONE_VALID(zone));
4126
4127	LOCK_ZONE(zone);
4128	if (value)
4129		zone->keyopts |= keyopt;
4130	else
4131		zone->keyopts &= ~keyopt;
4132	UNLOCK_ZONE(zone);
4133}
4134
4135unsigned int
4136dns_zone_getkeyopts(dns_zone_t *zone) {
4137
4138	REQUIRE(DNS_ZONE_VALID(zone));
4139
4140	return (zone->keyopts);
4141}
4142
4143isc_result_t
4144dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4145	REQUIRE(DNS_ZONE_VALID(zone));
4146
4147	LOCK_ZONE(zone);
4148	zone->xfrsource4 = *xfrsource;
4149	UNLOCK_ZONE(zone);
4150
4151	return (ISC_R_SUCCESS);
4152}
4153
4154isc_sockaddr_t *
4155dns_zone_getxfrsource4(dns_zone_t *zone) {
4156	REQUIRE(DNS_ZONE_VALID(zone));
4157	return (&zone->xfrsource4);
4158}
4159
4160isc_result_t
4161dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4162	REQUIRE(DNS_ZONE_VALID(zone));
4163
4164	LOCK_ZONE(zone);
4165	zone->xfrsource6 = *xfrsource;
4166	UNLOCK_ZONE(zone);
4167
4168	return (ISC_R_SUCCESS);
4169}
4170
4171isc_sockaddr_t *
4172dns_zone_getxfrsource6(dns_zone_t *zone) {
4173	REQUIRE(DNS_ZONE_VALID(zone));
4174	return (&zone->xfrsource6);
4175}
4176
4177isc_result_t
4178dns_zone_setaltxfrsource4(dns_zone_t *zone,
4179			  const isc_sockaddr_t *altxfrsource)
4180{
4181	REQUIRE(DNS_ZONE_VALID(zone));
4182
4183	LOCK_ZONE(zone);
4184	zone->altxfrsource4 = *altxfrsource;
4185	UNLOCK_ZONE(zone);
4186
4187	return (ISC_R_SUCCESS);
4188}
4189
4190isc_sockaddr_t *
4191dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4192	REQUIRE(DNS_ZONE_VALID(zone));
4193	return (&zone->altxfrsource4);
4194}
4195
4196isc_result_t
4197dns_zone_setaltxfrsource6(dns_zone_t *zone,
4198			  const isc_sockaddr_t *altxfrsource)
4199{
4200	REQUIRE(DNS_ZONE_VALID(zone));
4201
4202	LOCK_ZONE(zone);
4203	zone->altxfrsource6 = *altxfrsource;
4204	UNLOCK_ZONE(zone);
4205
4206	return (ISC_R_SUCCESS);
4207}
4208
4209isc_sockaddr_t *
4210dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4211	REQUIRE(DNS_ZONE_VALID(zone));
4212	return (&zone->altxfrsource6);
4213}
4214
4215isc_result_t
4216dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4217	REQUIRE(DNS_ZONE_VALID(zone));
4218
4219	LOCK_ZONE(zone);
4220	zone->notifysrc4 = *notifysrc;
4221	UNLOCK_ZONE(zone);
4222
4223	return (ISC_R_SUCCESS);
4224}
4225
4226isc_sockaddr_t *
4227dns_zone_getnotifysrc4(dns_zone_t *zone) {
4228	REQUIRE(DNS_ZONE_VALID(zone));
4229	return (&zone->notifysrc4);
4230}
4231
4232isc_result_t
4233dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4234	REQUIRE(DNS_ZONE_VALID(zone));
4235
4236	LOCK_ZONE(zone);
4237	zone->notifysrc6 = *notifysrc;
4238	UNLOCK_ZONE(zone);
4239
4240	return (ISC_R_SUCCESS);
4241}
4242
4243isc_sockaddr_t *
4244dns_zone_getnotifysrc6(dns_zone_t *zone) {
4245	REQUIRE(DNS_ZONE_VALID(zone));
4246	return (&zone->notifysrc6);
4247}
4248
4249isc_result_t
4250dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
4251		       isc_uint32_t count)
4252{
4253	isc_sockaddr_t *new;
4254
4255	REQUIRE(DNS_ZONE_VALID(zone));
4256	REQUIRE(count == 0 || notify != NULL);
4257
4258	LOCK_ZONE(zone);
4259	if (zone->notify != NULL) {
4260		isc_mem_put(zone->mctx, zone->notify,
4261			    zone->notifycnt * sizeof(*new));
4262		zone->notify = NULL;
4263		zone->notifycnt = 0;
4264	}
4265	if (count != 0) {
4266		new = isc_mem_get(zone->mctx, count * sizeof(*new));
4267		if (new == NULL) {
4268			UNLOCK_ZONE(zone);
4269			return (ISC_R_NOMEMORY);
4270		}
4271		memcpy(new, notify, count * sizeof(*new));
4272		zone->notify = new;
4273		zone->notifycnt = count;
4274	}
4275	UNLOCK_ZONE(zone);
4276	return (ISC_R_SUCCESS);
4277}
4278
4279isc_result_t
4280dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
4281		    isc_uint32_t count)
4282{
4283	isc_result_t result;
4284
4285	result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
4286	return (result);
4287}
4288
4289static isc_boolean_t
4290same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4291	     isc_uint32_t count)
4292{
4293	unsigned int i;
4294
4295	for (i = 0; i < count; i++)
4296		if (!isc_sockaddr_equal(&old[i], &new[i]))
4297			return (ISC_FALSE);
4298	return (ISC_TRUE);
4299}
4300
4301static isc_boolean_t
4302same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
4303	unsigned int i;
4304
4305	if (old == NULL && new == NULL)
4306		return (ISC_TRUE);
4307	if (old == NULL || new == NULL)
4308		return (ISC_FALSE);
4309
4310	for (i = 0; i < count; i++) {
4311		if (old[i] == NULL && new[i] == NULL)
4312			continue;
4313		if (old[i] == NULL || new[i] == NULL ||
4314		     !dns_name_equal(old[i], new[i]))
4315			return (ISC_FALSE);
4316	}
4317	return (ISC_TRUE);
4318}
4319
4320isc_result_t
4321dns_zone_setmasterswithkeys(dns_zone_t *zone,
4322			    const isc_sockaddr_t *masters,
4323			    dns_name_t **keynames,
4324			    isc_uint32_t count)
4325{
4326	isc_sockaddr_t *new;
4327	isc_result_t result = ISC_R_SUCCESS;
4328	dns_name_t **newname;
4329	isc_boolean_t *newok;
4330	unsigned int i;
4331
4332	REQUIRE(DNS_ZONE_VALID(zone));
4333	REQUIRE(count == 0 || masters != NULL);
4334	if (keynames != NULL) {
4335		REQUIRE(count != 0);
4336	}
4337
4338	LOCK_ZONE(zone);
4339	/*
4340	 * The refresh code assumes that 'masters' wouldn't change under it.
4341	 * If it will change then kill off any current refresh in progress
4342	 * and update the masters info.  If it won't change then we can just
4343	 * unlock and exit.
4344	 */
4345	if (count != zone->masterscnt ||
4346	    !same_masters(zone->masters, masters, count) ||
4347	    !same_keynames(zone->masterkeynames, keynames, count)) {
4348		if (zone->request != NULL)
4349			dns_request_cancel(zone->request);
4350	} else
4351		goto unlock;
4352	if (zone->masters != NULL) {
4353		isc_mem_put(zone->mctx, zone->masters,
4354			    zone->masterscnt * sizeof(*new));
4355		zone->masters = NULL;
4356	}
4357	if (zone->masterkeynames != NULL) {
4358		for (i = 0; i < zone->masterscnt; i++) {
4359			if (zone->masterkeynames[i] != NULL) {
4360				dns_name_free(zone->masterkeynames[i],
4361					      zone->mctx);
4362				isc_mem_put(zone->mctx,
4363					    zone->masterkeynames[i],
4364					    sizeof(dns_name_t));
4365				zone->masterkeynames[i] = NULL;
4366			}
4367		}
4368		isc_mem_put(zone->mctx, zone->masterkeynames,
4369			    zone->masterscnt * sizeof(dns_name_t *));
4370		zone->masterkeynames = NULL;
4371	}
4372	if (zone->mastersok != NULL) {
4373		isc_mem_put(zone->mctx, zone->mastersok,
4374			    zone->masterscnt * sizeof(isc_boolean_t));
4375		zone->mastersok = NULL;
4376	}
4377	zone->masterscnt = 0;
4378	/*
4379	 * If count == 0, don't allocate any space for masters, mastersok or
4380	 * keynames so internally, those pointers are NULL if count == 0
4381	 */
4382	if (count == 0)
4383		goto unlock;
4384
4385	/*
4386	 * masters must contain count elements!
4387	 */
4388	new = isc_mem_get(zone->mctx, count * sizeof(*new));
4389	if (new == NULL) {
4390		result = ISC_R_NOMEMORY;
4391		goto unlock;
4392	}
4393	memcpy(new, masters, count * sizeof(*new));
4394
4395	/*
4396	 * Similarly for mastersok.
4397	 */
4398	newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
4399	if (newok == NULL) {
4400		result = ISC_R_NOMEMORY;
4401		isc_mem_put(zone->mctx, new, count * sizeof(*new));
4402		goto unlock;
4403	};
4404	for (i = 0; i < count; i++)
4405		newok[i] = ISC_FALSE;
4406
4407	/*
4408	 * if keynames is non-NULL, it must contain count elements!
4409	 */
4410	newname = NULL;
4411	if (keynames != NULL) {
4412		newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
4413		if (newname == NULL) {
4414			result = ISC_R_NOMEMORY;
4415			isc_mem_put(zone->mctx, new, count * sizeof(*new));
4416			isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
4417			goto unlock;
4418		}
4419		for (i = 0; i < count; i++)
4420			newname[i] = NULL;
4421		for (i = 0; i < count; i++) {
4422			if (keynames[i] != NULL) {
4423				newname[i] = isc_mem_get(zone->mctx,
4424							 sizeof(dns_name_t));
4425				if (newname[i] == NULL)
4426					goto allocfail;
4427				dns_name_init(newname[i], NULL);
4428				result = dns_name_dup(keynames[i], zone->mctx,
4429						      newname[i]);
4430				if (result != ISC_R_SUCCESS) {
4431				allocfail:
4432					for (i = 0; i < count; i++)
4433						if (newname[i] != NULL)
4434							dns_name_free(
4435							       newname[i],
4436							       zone->mctx);
4437					isc_mem_put(zone->mctx, new,
4438						    count * sizeof(*new));
4439					isc_mem_put(zone->mctx, newok,
4440						    count * sizeof(*newok));
4441					isc_mem_put(zone->mctx, newname,
4442						    count * sizeof(*newname));
4443					goto unlock;
4444				}
4445			}
4446		}
4447	}
4448
4449	/*
4450	 * Everything is ok so attach to the zone.
4451	 */
4452	zone->curmaster = 0;
4453	zone->masters = new;
4454	zone->mastersok = newok;
4455	zone->masterkeynames = newname;
4456	zone->masterscnt = count;
4457	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
4458
4459 unlock:
4460	UNLOCK_ZONE(zone);
4461	return (result);
4462}
4463
4464isc_result_t
4465dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
4466	isc_result_t result = ISC_R_SUCCESS;
4467
4468	REQUIRE(DNS_ZONE_VALID(zone));
4469
4470	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4471	if (zone->db == NULL)
4472		result = DNS_R_NOTLOADED;
4473	else
4474		dns_db_attach(zone->db, dpb);
4475	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4476
4477	return (result);
4478}
4479
4480void
4481dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
4482	REQUIRE(DNS_ZONE_VALID(zone));
4483	REQUIRE(zone->type == dns_zone_staticstub);
4484
4485	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4486	REQUIRE(zone->db == NULL);
4487	dns_db_attach(db, &zone->db);
4488	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4489}
4490
4491/*
4492 * Co-ordinates the starting of routine jobs.
4493 */
4494
4495void
4496dns_zone_maintenance(dns_zone_t *zone) {
4497	const char me[] = "dns_zone_maintenance";
4498	isc_time_t now;
4499
4500	REQUIRE(DNS_ZONE_VALID(zone));
4501	ENTER;
4502
4503	LOCK_ZONE(zone);
4504	TIME_NOW(&now);
4505	zone_settimer(zone, &now);
4506	UNLOCK_ZONE(zone);
4507}
4508
4509static inline isc_boolean_t
4510was_dumping(dns_zone_t *zone) {
4511	isc_boolean_t dumping;
4512
4513	REQUIRE(LOCKED_ZONE(zone));
4514
4515	dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
4516	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
4517	if (!dumping) {
4518		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
4519		isc_time_settoepoch(&zone->dumptime);
4520	}
4521	return (dumping);
4522}
4523
4524static isc_result_t
4525find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4526	       isc_mem_t *mctx, unsigned int maxkeys,
4527	       dst_key_t **keys, unsigned int *nkeys)
4528{
4529	isc_result_t result;
4530	dns_dbnode_t *node = NULL;
4531	const char *directory = dns_zone_getkeydirectory(zone);
4532
4533	CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
4534	result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
4535					  directory, mctx, maxkeys, keys,
4536					  nkeys);
4537	if (result == ISC_R_NOTFOUND)
4538		result = ISC_R_SUCCESS;
4539 failure:
4540	if (node != NULL)
4541		dns_db_detachnode(db, &node);
4542	return (result);
4543}
4544
4545static isc_result_t
4546offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name,
4547	dns_ttl_t ttl, dns_rdata_t *rdata)
4548{
4549	isc_result_t result;
4550
4551	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
4552		return (ISC_R_SUCCESS);
4553	result = update_one_rr(db, ver, diff, DNS_DIFFOP_DELRESIGN,
4554			       name, ttl, rdata);
4555	if (result != ISC_R_SUCCESS)
4556		return (result);
4557	rdata->flags |= DNS_RDATA_OFFLINE;
4558	result = update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
4559			       name, ttl, rdata);
4560	return (result);
4561}
4562
4563static void
4564set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
4565{
4566	unsigned int delta;
4567	char timebuf[80];
4568
4569	zone->key_expiry = when;
4570	if (when <= now) {
4571		dns_zone_log(zone, ISC_LOG_ERROR,
4572			     "DNSKEY RRSIG(s) have expired");
4573		isc_time_settoepoch(&zone->keywarntime);
4574	} else if (when < now + 7 * 24 * 3600) {
4575		isc_time_t t;
4576		isc_time_set(&t, when, 0);
4577		isc_time_formattimestamp(&t, timebuf, 80);
4578		dns_zone_log(zone, ISC_LOG_WARNING,
4579			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
4580			     timebuf);
4581		delta = when - now;
4582		delta--;		/* loop prevention */
4583		delta /= 24 * 3600;	/* to whole days */
4584		delta *= 24 * 3600;	/* to seconds */
4585		isc_time_set(&zone->keywarntime, when - delta, 0);
4586	}  else {
4587		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
4588		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4589		dns_zone_log(zone, ISC_LOG_NOTICE,
4590			     "setting keywarntime to %s", timebuf);
4591	}
4592}
4593
4594/*
4595 * Helper function to del_sigs(). We don't want to delete RRSIGs that
4596 * have no new key.
4597 */
4598static isc_boolean_t
4599delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys) {
4600	unsigned int i = 0;
4601
4602	/*
4603	 * It's okay to delete a signature if there is an active ZSK
4604	 * with the same algorithm
4605	 */
4606	for (i = 0; i < nkeys; i++) {
4607		if (rrsig_ptr->algorithm == dst_key_alg(keys[i]) &&
4608		    (dst_key_isprivate(keys[i])) && !KSK(keys[i]))
4609			return (ISC_TRUE);
4610	}
4611
4612	/*
4613	 * Failing that, it is *not* okay to delete a signature
4614	 * if the associated public key is still in the DNSKEY RRset
4615	 */
4616	for (i = 0; i < nkeys; i++) {
4617		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
4618		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
4619			return (ISC_FALSE);
4620	}
4621
4622	/*
4623	 * But if the key is gone, then go ahead.
4624	 */
4625	return (ISC_TRUE);
4626}
4627
4628/*
4629 * Delete expired RRsigs and any RRsigs we are about to re-sign.
4630 * See also update.c:del_keysigs().
4631 */
4632static isc_result_t
4633del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
4634	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
4635	 unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
4636{
4637	isc_result_t result;
4638	dns_dbnode_t *node = NULL;
4639	dns_rdataset_t rdataset;
4640	unsigned int i;
4641	dns_rdata_rrsig_t rrsig;
4642	isc_boolean_t found, changed;
4643	isc_int64_t warn = 0, maybe = 0;
4644
4645	dns_rdataset_init(&rdataset);
4646
4647	if (type == dns_rdatatype_nsec3)
4648		result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
4649	else
4650		result = dns_db_findnode(db, name, ISC_FALSE, &node);
4651	if (result == ISC_R_NOTFOUND)
4652		return (ISC_R_SUCCESS);
4653	if (result != ISC_R_SUCCESS)
4654		goto failure;
4655	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
4656				     (isc_stdtime_t) 0, &rdataset, NULL);
4657	dns_db_detachnode(db, &node);
4658
4659	if (result == ISC_R_NOTFOUND) {
4660		INSIST(!dns_rdataset_isassociated(&rdataset));
4661		return (ISC_R_SUCCESS);
4662	}
4663	if (result != ISC_R_SUCCESS) {
4664		INSIST(!dns_rdataset_isassociated(&rdataset));
4665		goto failure;
4666	}
4667
4668	changed = ISC_FALSE;
4669	for (result = dns_rdataset_first(&rdataset);
4670	     result == ISC_R_SUCCESS;
4671	     result = dns_rdataset_next(&rdataset)) {
4672		dns_rdata_t rdata = DNS_RDATA_INIT;
4673
4674		dns_rdataset_current(&rdataset, &rdata);
4675		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
4676		RUNTIME_CHECK(result == ISC_R_SUCCESS);
4677
4678		if (type != dns_rdatatype_dnskey) {
4679			if (delsig_ok(&rrsig, keys, nkeys)) {
4680				result = update_one_rr(db, ver, diff,
4681					       DNS_DIFFOP_DELRESIGN, name,
4682					       rdataset.ttl, &rdata);
4683				if (incremental)
4684					changed = ISC_TRUE;
4685				if (result != ISC_R_SUCCESS)
4686					break;
4687			} else {
4688				/*
4689				 * At this point, we've got an RRSIG,
4690				 * which is signed by an inactive key.
4691				 * An administrator needs to provide a new
4692				 * key/alg, but until that time, we want to
4693				 * keep the old RRSIG.  Marking the key as
4694				 * offline will prevent us spinning waiting
4695				 * for the private part.
4696				 */
4697				if (incremental) {
4698					result = offline(db, ver, diff, name,
4699							 rdataset.ttl, &rdata);
4700					changed = ISC_TRUE;
4701					if (result != ISC_R_SUCCESS)
4702						break;
4703				}
4704
4705				/*
4706				 * Log the key id and algorithm of
4707				 * the inactive key with no replacement
4708				 */
4709				if (zone->log_key_expired_timer <= now) {
4710					char origin[DNS_NAME_FORMATSIZE];
4711					char algbuf[DNS_NAME_FORMATSIZE];
4712					dns_name_format(&zone->origin, origin,
4713							sizeof(origin));
4714					dns_secalg_format(rrsig.algorithm,
4715							  algbuf,
4716							  sizeof(algbuf));
4717					dns_zone_log(zone, ISC_LOG_WARNING,
4718						     "Key %s/%s/%d "
4719						     "missing or inactive "
4720						     "and has no replacement: "
4721						     "retaining signatures.",
4722						     origin, algbuf,
4723						     rrsig.keyid);
4724					zone->log_key_expired_timer = now +
4725									3600;
4726				}
4727			}
4728			continue;
4729		}
4730
4731		/*
4732		 * RRSIG(DNSKEY) requires special processing.
4733		 */
4734		found = ISC_FALSE;
4735		for (i = 0; i < nkeys; i++) {
4736			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
4737			    rrsig.keyid == dst_key_id(keys[i])) {
4738				found = ISC_TRUE;
4739				/*
4740				 * Mark offline RRSIG(DNSKEY).
4741				 * We want the earliest offline expire time
4742				 * iff there is a new offline signature.
4743				 */
4744				if (!dst_key_isprivate(keys[i])) {
4745					isc_int64_t timeexpire =
4746					   dns_time64_from32(rrsig.timeexpire);
4747					if (warn != 0 && warn > timeexpire)
4748						warn = timeexpire;
4749					if (rdata.flags & DNS_RDATA_OFFLINE) {
4750						if (maybe == 0 ||
4751						    maybe > timeexpire)
4752							maybe = timeexpire;
4753						break;
4754					}
4755					if (warn == 0)
4756						warn = maybe;
4757					if (warn == 0 || warn > timeexpire)
4758						warn = timeexpire;
4759					result = offline(db, ver, diff, name,
4760							 rdataset.ttl, &rdata);
4761					break;
4762				}
4763				result = update_one_rr(db, ver, diff,
4764						       DNS_DIFFOP_DELRESIGN,
4765						       name, rdataset.ttl,
4766						       &rdata);
4767				break;
4768			}
4769		}
4770
4771		/*
4772		 * If there is not a matching DNSKEY then
4773		 * delete the RRSIG.
4774		 */
4775		if (!found)
4776			result = update_one_rr(db, ver, diff,
4777					       DNS_DIFFOP_DELRESIGN, name,
4778					       rdataset.ttl, &rdata);
4779		if (result != ISC_R_SUCCESS)
4780			break;
4781	}
4782
4783	if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0)
4784		dns_db_resigned(db, &rdataset, ver);
4785
4786	dns_rdataset_disassociate(&rdataset);
4787	if (result == ISC_R_NOMORE)
4788		result = ISC_R_SUCCESS;
4789	if (warn > 0) {
4790#if defined(STDTIME_ON_32BITS)
4791		isc_stdtime_t stdwarn = (isc_stdtime_t)warn;
4792		if (warn == stdwarn)
4793#endif
4794			set_key_expiry_warning(zone, (isc_stdtime_t)warn, now);
4795#if defined(STDTIME_ON_32BITS)
4796		else
4797			dns_zone_log(zone, ISC_LOG_ERROR,
4798				     "key expiry warning time out of range");
4799#endif
4800	}
4801 failure:
4802	if (node != NULL)
4803		dns_db_detachnode(db, &node);
4804	return (result);
4805}
4806
4807static isc_result_t
4808add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
4809	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
4810	 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
4811	 isc_stdtime_t expire, isc_boolean_t check_ksk,
4812	 isc_boolean_t keyset_kskonly)
4813{
4814	isc_result_t result;
4815	dns_dbnode_t *node = NULL;
4816	dns_rdataset_t rdataset;
4817	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
4818	unsigned char data[1024]; /* XXX */
4819	isc_buffer_t buffer;
4820	unsigned int i, j;
4821
4822	dns_rdataset_init(&rdataset);
4823	isc_buffer_init(&buffer, data, sizeof(data));
4824
4825	if (type == dns_rdatatype_nsec3)
4826		result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
4827	else
4828		result = dns_db_findnode(db, name, ISC_FALSE, &node);
4829	if (result == ISC_R_NOTFOUND)
4830		return (ISC_R_SUCCESS);
4831	if (result != ISC_R_SUCCESS)
4832		goto failure;
4833	result = dns_db_findrdataset(db, node, ver, type, 0,
4834				     (isc_stdtime_t) 0, &rdataset, NULL);
4835	dns_db_detachnode(db, &node);
4836	if (result == ISC_R_NOTFOUND) {
4837		INSIST(!dns_rdataset_isassociated(&rdataset));
4838		return (ISC_R_SUCCESS);
4839	}
4840	if (result != ISC_R_SUCCESS) {
4841		INSIST(!dns_rdataset_isassociated(&rdataset));
4842		goto failure;
4843	}
4844
4845	for (i = 0; i < nkeys; i++) {
4846		isc_boolean_t both = ISC_FALSE;
4847
4848		if (!dst_key_isprivate(keys[i]))
4849			continue;
4850
4851		if (check_ksk && !REVOKE(keys[i])) {
4852			isc_boolean_t have_ksk, have_nonksk;
4853			if (KSK(keys[i])) {
4854				have_ksk = ISC_TRUE;
4855				have_nonksk = ISC_FALSE;
4856			} else {
4857				have_ksk = ISC_FALSE;
4858				have_nonksk = ISC_TRUE;
4859			}
4860			for (j = 0; j < nkeys; j++) {
4861				if (j == i || ALG(keys[i]) != ALG(keys[j]))
4862					continue;
4863				if (REVOKE(keys[j]))
4864					continue;
4865				if (KSK(keys[j]))
4866					have_ksk = ISC_TRUE;
4867				else
4868					have_nonksk = ISC_TRUE;
4869				both = have_ksk && have_nonksk;
4870				if (both)
4871					break;
4872			}
4873		}
4874		if (both) {
4875			if (type == dns_rdatatype_dnskey) {
4876				if (!KSK(keys[i]) && keyset_kskonly)
4877					continue;
4878			} else if (KSK(keys[i]))
4879				continue;
4880		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
4881				continue;
4882
4883		/* Calculate the signature, creating a RRSIG RDATA. */
4884		isc_buffer_clear(&buffer);
4885		CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
4886				      &inception, &expire,
4887				      mctx, &buffer, &sig_rdata));
4888		/* Update the database and journal with the RRSIG. */
4889		/* XXX inefficient - will cause dataset merging */
4890		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
4891				    name, rdataset.ttl, &sig_rdata));
4892		dns_rdata_reset(&sig_rdata);
4893		isc_buffer_init(&buffer, data, sizeof(data));
4894	}
4895
4896 failure:
4897	if (dns_rdataset_isassociated(&rdataset))
4898		dns_rdataset_disassociate(&rdataset);
4899	if (node != NULL)
4900		dns_db_detachnode(db, &node);
4901	return (result);
4902}
4903
4904static void
4905zone_resigninc(dns_zone_t *zone) {
4906	dns_db_t *db = NULL;
4907	dns_dbversion_t *version = NULL;
4908	dns_diff_t sig_diff;
4909	dns_fixedname_t fixed;
4910	dns_name_t *name;
4911	dns_rdataset_t rdataset;
4912	dns_rdatatype_t covers;
4913	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
4914	isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
4915	isc_result_t result;
4916	isc_stdtime_t now, inception, soaexpire, expire, stop;
4917	isc_uint32_t jitter;
4918	unsigned int i;
4919	unsigned int nkeys = 0;
4920	unsigned int resign;
4921
4922	dns_rdataset_init(&rdataset);
4923	dns_fixedname_init(&fixed);
4924	dns_diff_init(zone->mctx, &sig_diff);
4925	sig_diff.resign = zone->sigresigninginterval;
4926
4927	/*
4928	 * Updates are disabled.  Pause for 5 minutes.
4929	 */
4930	if (zone->update_disabled) {
4931		result = ISC_R_FAILURE;
4932		goto failure;
4933	}
4934
4935	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4936	dns_db_attach(zone->db, &db);
4937	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4938
4939	result = dns_db_newversion(db, &version);
4940	if (result != ISC_R_SUCCESS) {
4941		dns_zone_log(zone, ISC_LOG_ERROR,
4942			     "zone_resigninc:dns_db_newversion -> %s\n",
4943			     dns_result_totext(result));
4944		goto failure;
4945	}
4946
4947	result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
4948				zone_keys, &nkeys);
4949	if (result != ISC_R_SUCCESS) {
4950		dns_zone_log(zone, ISC_LOG_ERROR,
4951			     "zone_resigninc:find_zone_keys -> %s\n",
4952			     dns_result_totext(result));
4953		goto failure;
4954	}
4955
4956	isc_stdtime_get(&now);
4957	inception = now - 3600;	/* Allow for clock skew. */
4958	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
4959	/*
4960	 * Spread out signatures over time if they happen to be
4961	 * clumped.  We don't do this for each add_sigs() call as
4962	 * we still want some clustering to occur.
4963	 */
4964	isc_random_get(&jitter);
4965	expire = soaexpire - jitter % 3600;
4966	stop = now + 5;
4967
4968	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
4969	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
4970
4971	name = dns_fixedname_name(&fixed);
4972	result = dns_db_getsigningtime(db, &rdataset, name);
4973	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
4974		dns_zone_log(zone, ISC_LOG_ERROR,
4975			     "zone_resigninc:dns_db_getsigningtime -> %s\n",
4976			     dns_result_totext(result));
4977	}
4978
4979	i = 0;
4980	while (result == ISC_R_SUCCESS) {
4981		resign = rdataset.resign;
4982		covers = rdataset.covers;
4983		dns_rdataset_disassociate(&rdataset);
4984
4985		/*
4986		 * Stop if we hit the SOA as that means we have walked the
4987		 * entire zone.  The SOA record should always be the most
4988		 * recent signature.
4989		 */
4990		/* XXXMPA increase number of RRsets signed pre call */
4991		if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
4992		    resign > stop)
4993			break;
4994
4995		result = del_sigs(zone, db, version, name, covers, &sig_diff,
4996				  zone_keys, nkeys, now, ISC_TRUE);
4997		if (result != ISC_R_SUCCESS) {
4998			dns_zone_log(zone, ISC_LOG_ERROR,
4999				     "zone_resigninc:del_sigs -> %s\n",
5000				     dns_result_totext(result));
5001			break;
5002		}
5003
5004		result = add_sigs(db, version, name, covers, &sig_diff,
5005				  zone_keys, nkeys, zone->mctx, inception,
5006				  expire, check_ksk, keyset_kskonly);
5007		if (result != ISC_R_SUCCESS) {
5008			dns_zone_log(zone, ISC_LOG_ERROR,
5009				     "zone_resigninc:add_sigs -> %s\n",
5010				     dns_result_totext(result));
5011			break;
5012		}
5013		result	= dns_db_getsigningtime(db, &rdataset,
5014						dns_fixedname_name(&fixed));
5015		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
5016			result = ISC_R_SUCCESS;
5017			break;
5018		}
5019		if (result != ISC_R_SUCCESS)
5020			dns_zone_log(zone, ISC_LOG_ERROR,
5021			     "zone_resigninc:dns_db_getsigningtime -> %s\n",
5022				     dns_result_totext(result));
5023	}
5024
5025	if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
5026		goto failure;
5027
5028	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5029			  &sig_diff, zone_keys, nkeys, now, ISC_TRUE);
5030	if (result != ISC_R_SUCCESS) {
5031		dns_zone_log(zone, ISC_LOG_ERROR,
5032			     "zone_resigninc:del_sigs -> %s\n",
5033			     dns_result_totext(result));
5034		goto failure;
5035	}
5036
5037	/*
5038	 * Did we change anything in the zone?
5039	 */
5040	if (ISC_LIST_EMPTY(sig_diff.tuples))
5041		goto failure;
5042
5043	/* Increment SOA serial if we have made changes */
5044	result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
5045	if (result != ISC_R_SUCCESS) {
5046		dns_zone_log(zone, ISC_LOG_ERROR,
5047			     "zone_resigninc:increment_soa_serial -> %s\n",
5048			     dns_result_totext(result));
5049		goto failure;
5050	}
5051
5052	/*
5053	 * Generate maximum life time signatures so that the above loop
5054	 * termination is sensible.
5055	 */
5056	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5057			  &sig_diff, zone_keys, nkeys, zone->mctx, inception,
5058			  soaexpire, check_ksk, keyset_kskonly);
5059	if (result != ISC_R_SUCCESS) {
5060		dns_zone_log(zone, ISC_LOG_ERROR,
5061			     "zone_resigninc:add_sigs -> %s\n",
5062			     dns_result_totext(result));
5063		goto failure;
5064	}
5065
5066	/* Write changes to journal file. */
5067	CHECK(zone_journal(zone, &sig_diff, "zone_resigninc"));
5068
5069	/* Everything has succeeded. Commit the changes. */
5070	dns_db_closeversion(db, &version, ISC_TRUE);
5071
5072 failure:
5073	dns_diff_clear(&sig_diff);
5074	for (i = 0; i < nkeys; i++)
5075		dst_key_free(&zone_keys[i]);
5076	if (version != NULL) {
5077		dns_db_closeversion(zone->db, &version, ISC_FALSE);
5078		dns_db_detach(&db);
5079	} else if (db != NULL)
5080		dns_db_detach(&db);
5081	if (result == ISC_R_SUCCESS) {
5082		set_resigntime(zone);
5083		LOCK_ZONE(zone);
5084		zone_needdump(zone, DNS_DUMP_DELAY);
5085		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5086		UNLOCK_ZONE(zone);
5087	} else {
5088		/*
5089		 * Something failed.  Retry in 5 minutes.
5090		 */
5091		isc_interval_t ival;
5092		isc_interval_set(&ival, 300, 0);
5093		isc_time_nowplusinterval(&zone->resigntime, &ival);
5094	}
5095}
5096
5097static isc_result_t
5098next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
5099	    dns_name_t *newname, isc_boolean_t bottom)
5100{
5101	isc_result_t result;
5102	dns_dbiterator_t *dbit = NULL;
5103	dns_rdatasetiter_t *rdsit = NULL;
5104	dns_dbnode_t *node = NULL;
5105
5106	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
5107	CHECK(dns_dbiterator_seek(dbit, oldname));
5108	do {
5109		result = dns_dbiterator_next(dbit);
5110		if (result == ISC_R_NOMORE)
5111			CHECK(dns_dbiterator_first(dbit));
5112		CHECK(dns_dbiterator_current(dbit, &node, newname));
5113		if (bottom && dns_name_issubdomain(newname, oldname) &&
5114		    !dns_name_equal(newname, oldname)) {
5115			dns_db_detachnode(db, &node);
5116			continue;
5117		}
5118		/*
5119		 * Is this node empty?
5120		 */
5121		CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
5122		result = dns_rdatasetiter_first(rdsit);
5123		dns_db_detachnode(db, &node);
5124		dns_rdatasetiter_destroy(&rdsit);
5125		if (result != ISC_R_NOMORE)
5126			break;
5127	} while (1);
5128 failure:
5129	if (node != NULL)
5130		dns_db_detachnode(db, &node);
5131	if (dbit != NULL)
5132		dns_dbiterator_destroy(&dbit);
5133	return (result);
5134}
5135
5136static isc_boolean_t
5137signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5138		dns_rdatatype_t type, dst_key_t *key)
5139{
5140	isc_result_t result;
5141	dns_rdataset_t rdataset;
5142	dns_rdata_t rdata = DNS_RDATA_INIT;
5143	dns_rdata_rrsig_t rrsig;
5144
5145	dns_rdataset_init(&rdataset);
5146	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
5147				     type, 0, &rdataset, NULL);
5148	if (result != ISC_R_SUCCESS) {
5149		INSIST(!dns_rdataset_isassociated(&rdataset));
5150		return (ISC_FALSE);
5151	}
5152	for (result = dns_rdataset_first(&rdataset);
5153	     result == ISC_R_SUCCESS;
5154	     result = dns_rdataset_next(&rdataset)) {
5155		dns_rdataset_current(&rdataset, &rdata);
5156		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5157		INSIST(result == ISC_R_SUCCESS);
5158		if (rrsig.algorithm == dst_key_alg(key) &&
5159		    rrsig.keyid == dst_key_id(key)) {
5160			dns_rdataset_disassociate(&rdataset);
5161			return (ISC_TRUE);
5162		}
5163		dns_rdata_reset(&rdata);
5164	}
5165	dns_rdataset_disassociate(&rdataset);
5166	return (ISC_FALSE);
5167}
5168
5169static isc_result_t
5170add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5171	 dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
5172	 dns_diff_t *diff)
5173{
5174	dns_fixedname_t fixed;
5175	dns_name_t *next;
5176	dns_rdata_t rdata = DNS_RDATA_INIT;
5177	isc_result_t result;
5178	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
5179
5180	dns_fixedname_init(&fixed);
5181	next = dns_fixedname_name(&fixed);
5182
5183	CHECK(next_active(db, version, name, next, bottom));
5184	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
5185				  &rdata));
5186	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
5187			    &rdata));
5188 failure:
5189	return (result);
5190}
5191
5192static isc_result_t
5193sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
5194	    dns_dbversion_t *version, isc_boolean_t build_nsec3,
5195	    isc_boolean_t build_nsec, dst_key_t *key,
5196	    isc_stdtime_t inception, isc_stdtime_t expire,
5197	    unsigned int minimum, isc_boolean_t is_ksk,
5198	    isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
5199	    dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
5200{
5201	isc_result_t result;
5202	dns_rdatasetiter_t *iterator = NULL;
5203	dns_rdataset_t rdataset;
5204	dns_rdata_t rdata = DNS_RDATA_INIT;
5205	isc_buffer_t buffer;
5206	unsigned char data[1024];
5207	isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
5208		      seen_nsec3, seen_ds;
5209	isc_boolean_t bottom;
5210
5211	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5212	if (result != ISC_R_SUCCESS) {
5213		if (result == ISC_R_NOTFOUND)
5214			result = ISC_R_SUCCESS;
5215		return (result);
5216	}
5217
5218	dns_rdataset_init(&rdataset);
5219	isc_buffer_init(&buffer, data, sizeof(data));
5220	seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
5221	seen_nsec3 = seen_ds = ISC_FALSE;
5222	for (result = dns_rdatasetiter_first(iterator);
5223	     result == ISC_R_SUCCESS;
5224	     result = dns_rdatasetiter_next(iterator)) {
5225		dns_rdatasetiter_current(iterator, &rdataset);
5226		if (rdataset.type == dns_rdatatype_soa)
5227			seen_soa = ISC_TRUE;
5228		else if (rdataset.type == dns_rdatatype_ns)
5229			seen_ns = ISC_TRUE;
5230		else if (rdataset.type == dns_rdatatype_ds)
5231			seen_ds = ISC_TRUE;
5232		else if (rdataset.type == dns_rdatatype_dname)
5233			seen_dname = ISC_TRUE;
5234		else if (rdataset.type == dns_rdatatype_nsec)
5235			seen_nsec = ISC_TRUE;
5236		else if (rdataset.type == dns_rdatatype_nsec3)
5237			seen_nsec3 = ISC_TRUE;
5238		if (rdataset.type != dns_rdatatype_rrsig)
5239			seen_rr = ISC_TRUE;
5240		dns_rdataset_disassociate(&rdataset);
5241	}
5242	if (result != ISC_R_NOMORE)
5243		goto failure;
5244	if (seen_ns && !seen_soa)
5245		*delegation = ISC_TRUE;
5246	/*
5247	 * Going from insecure to NSEC3.
5248	 * Don't generate NSEC3 records for NSEC3 records.
5249	 */
5250	if (build_nsec3 && !seen_nsec3 && seen_rr) {
5251		isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
5252		CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
5253					  unsecure, diff));
5254		(*signatures)--;
5255	}
5256	/*
5257	 * Going from insecure to NSEC.
5258	 * Don't generate NSEC records for NSEC3 records.
5259	 */
5260	if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
5261		/* Build and add NSEC. */
5262		bottom = (seen_ns && !seen_soa) || seen_dname;
5263		/*
5264		 * Build a NSEC record except at the origin.
5265		 */
5266		if (!dns_name_equal(name, dns_db_origin(db))) {
5267			CHECK(add_nsec(db, version, name, node, minimum,
5268				       bottom, diff));
5269			/* Count a NSEC generation as a signature generation. */
5270			(*signatures)--;
5271		}
5272	}
5273	result = dns_rdatasetiter_first(iterator);
5274	while (result == ISC_R_SUCCESS) {
5275		dns_rdatasetiter_current(iterator, &rdataset);
5276		if (rdataset.type == dns_rdatatype_soa ||
5277		    rdataset.type == dns_rdatatype_rrsig)
5278			goto next_rdataset;
5279		if (rdataset.type == dns_rdatatype_dnskey) {
5280			if (!is_ksk && keyset_kskonly)
5281				goto next_rdataset;
5282		} else if (is_ksk)
5283			goto next_rdataset;
5284		if (*delegation &&
5285		    rdataset.type != dns_rdatatype_ds &&
5286		    rdataset.type != dns_rdatatype_nsec)
5287			goto next_rdataset;
5288		if (signed_with_key(db, node, version, rdataset.type, key))
5289			goto next_rdataset;
5290		/* Calculate the signature, creating a RRSIG RDATA. */
5291		isc_buffer_clear(&buffer);
5292		CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
5293				      &expire, mctx, &buffer, &rdata));
5294		/* Update the database and journal with the RRSIG. */
5295		/* XXX inefficient - will cause dataset merging */
5296		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
5297				    name, rdataset.ttl, &rdata));
5298		dns_rdata_reset(&rdata);
5299		(*signatures)--;
5300 next_rdataset:
5301		dns_rdataset_disassociate(&rdataset);
5302		result = dns_rdatasetiter_next(iterator);
5303	}
5304	if (result == ISC_R_NOMORE)
5305		result = ISC_R_SUCCESS;
5306	if (seen_dname)
5307		*delegation = ISC_TRUE;
5308 failure:
5309	if (dns_rdataset_isassociated(&rdataset))
5310		dns_rdataset_disassociate(&rdataset);
5311	if (iterator != NULL)
5312		dns_rdatasetiter_destroy(&iterator);
5313	return (result);
5314}
5315
5316/*
5317 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
5318 */
5319static isc_result_t
5320updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5321	     dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
5322{
5323	isc_result_t result;
5324	dns_rdataset_t rdataset;
5325	dns_dbnode_t *node = NULL;
5326
5327	CHECK(dns_db_getoriginnode(db, &node));
5328	if (update_only) {
5329		dns_rdataset_init(&rdataset);
5330		result = dns_db_findrdataset(db, node, version,
5331					     dns_rdatatype_nsec,
5332					     dns_rdatatype_none,
5333					     0, &rdataset, NULL);
5334		if (dns_rdataset_isassociated(&rdataset))
5335			dns_rdataset_disassociate(&rdataset);
5336		if (result == ISC_R_NOTFOUND)
5337			goto success;
5338		if (result != ISC_R_SUCCESS)
5339			goto failure;
5340	}
5341	CHECK(delete_nsec(db, version, node, name, diff));
5342	CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
5343 success:
5344	result = ISC_R_SUCCESS;
5345 failure:
5346	if (node != NULL)
5347		dns_db_detachnode(db, &node);
5348	return (result);
5349}
5350
5351static isc_result_t
5352updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
5353		  dns_dbversion_t *version, isc_boolean_t build_nsec3,
5354		  dns_ttl_t minimum, dns_diff_t *diff)
5355{
5356	isc_result_t result;
5357	dns_dbnode_t *node = NULL;
5358	dns_rdataset_t rdataset;
5359	dns_rdata_t rdata = DNS_RDATA_INIT;
5360	unsigned char data[5];
5361	isc_boolean_t seen_done = ISC_FALSE;
5362	isc_boolean_t have_rr = ISC_FALSE;
5363
5364	dns_rdataset_init(&rdataset);
5365	result = dns_db_getoriginnode(signing->db, &node);
5366	if (result != ISC_R_SUCCESS)
5367		goto failure;
5368
5369	result = dns_db_findrdataset(signing->db, node, version,
5370				     zone->privatetype, dns_rdatatype_none,
5371				     0, &rdataset, NULL);
5372	if (result == ISC_R_NOTFOUND) {
5373		INSIST(!dns_rdataset_isassociated(&rdataset));
5374		result = ISC_R_SUCCESS;
5375		goto failure;
5376	}
5377	if (result != ISC_R_SUCCESS) {
5378		INSIST(!dns_rdataset_isassociated(&rdataset));
5379		goto failure;
5380	}
5381	for (result = dns_rdataset_first(&rdataset);
5382	     result == ISC_R_SUCCESS;
5383	     result = dns_rdataset_next(&rdataset)) {
5384		dns_rdataset_current(&rdataset, &rdata);
5385		/*
5386		 * If we don't match the algorithm or keyid skip the record.
5387		 */
5388		if (rdata.length != 5 ||
5389		    rdata.data[0] != signing->algorithm ||
5390		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
5391		    rdata.data[2] != (signing->keyid & 0xff)) {
5392			have_rr = ISC_TRUE;
5393			dns_rdata_reset(&rdata);
5394			continue;
5395		}
5396		/*
5397		 * We have a match.  If we were signing (!signing->delete)
5398		 * and we already have a record indicating that we have
5399		 * finished signing (rdata.data[4] != 0) then keep it.
5400		 * Otherwise it needs to be deleted as we have removed all
5401		 * the signatures (signing->delete), so any record indicating
5402		 * completion is now out of date, or we have finished signing
5403		 * with the new record so we no longer need to remember that
5404		 * we need to sign the zone with the matching key across a
5405		 * nameserver re-start.
5406		 */
5407		if (!signing->delete && rdata.data[4] != 0) {
5408			seen_done = ISC_TRUE;
5409			have_rr = ISC_TRUE;
5410		} else
5411			CHECK(update_one_rr(signing->db, version, diff,
5412					    DNS_DIFFOP_DEL, &zone->origin,
5413					    rdataset.ttl, &rdata));
5414		dns_rdata_reset(&rdata);
5415	}
5416	if (result == ISC_R_NOMORE)
5417		result = ISC_R_SUCCESS;
5418	if (!signing->delete && !seen_done) {
5419		/*
5420		 * If we were signing then we need to indicate that we have
5421		 * finished signing the zone with this key.  If it is already
5422		 * there we don't need to add it a second time.
5423		 */
5424		data[0] = signing->algorithm;
5425		data[1] = (signing->keyid >> 8) & 0xff;
5426		data[2] = signing->keyid & 0xff;
5427		data[3] = 0;
5428		data[4] = 1;
5429		rdata.length = sizeof(data);
5430		rdata.data = data;
5431		rdata.type = zone->privatetype;
5432		rdata.rdclass = dns_db_class(signing->db);
5433		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
5434				    &zone->origin, rdataset.ttl, &rdata));
5435	} else if (!have_rr) {
5436		dns_name_t *origin = dns_db_origin(signing->db);
5437		/*
5438		 * Rebuild the NSEC/NSEC3 record for the origin as we no
5439		 * longer have any private records.
5440		 */
5441		if (build_nsec3)
5442			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
5443						  minimum, ISC_FALSE, diff));
5444		CHECK(updatesecure(signing->db, version, origin, minimum,
5445				   ISC_TRUE, diff));
5446	}
5447
5448 failure:
5449	if (dns_rdataset_isassociated(&rdataset))
5450		dns_rdataset_disassociate(&rdataset);
5451	if (node != NULL)
5452		dns_db_detachnode(signing->db, &node);
5453	return (result);
5454}
5455
5456/*
5457 * If 'active' is set then we are not done with the chain yet so only
5458 * delete the nsec3param record which indicates a full chain exists
5459 * (flags == 0).
5460 */
5461static isc_result_t
5462fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
5463		 isc_boolean_t active, dns_rdatatype_t privatetype,
5464		 dns_diff_t *diff)
5465{
5466	dns_dbnode_t *node = NULL;
5467	dns_name_t *name = dns_db_origin(db);
5468	dns_rdata_t rdata = DNS_RDATA_INIT;
5469	dns_rdataset_t rdataset;
5470	dns_rdata_nsec3param_t nsec3param;
5471	isc_result_t result;
5472	isc_buffer_t buffer;
5473	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
5474	dns_ttl_t ttl = 0;
5475
5476	dns_rdataset_init(&rdataset);
5477
5478	result = dns_db_getoriginnode(db, &node);
5479	RUNTIME_CHECK(result == ISC_R_SUCCESS);
5480	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5481				     0, 0, &rdataset, NULL);
5482	if (result == ISC_R_NOTFOUND)
5483		goto try_private;
5484	if (result != ISC_R_SUCCESS)
5485		goto failure;
5486
5487	/*
5488	 * Preserve the existing ttl.
5489	 */
5490	ttl = rdataset.ttl;
5491
5492	/*
5493	 * Delete all NSEC3PARAM records which match that in nsec3chain.
5494	 */
5495	for (result = dns_rdataset_first(&rdataset);
5496	     result == ISC_R_SUCCESS;
5497	     result = dns_rdataset_next(&rdataset)) {
5498
5499		dns_rdataset_current(&rdataset, &rdata);
5500		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5501
5502		if (nsec3param.hash != chain->nsec3param.hash ||
5503		    (active && nsec3param.flags != 0) ||
5504		    nsec3param.iterations != chain->nsec3param.iterations ||
5505		    nsec3param.salt_length != chain->nsec3param.salt_length ||
5506		    memcmp(nsec3param.salt, chain->nsec3param.salt,
5507			   nsec3param.salt_length)) {
5508			dns_rdata_reset(&rdata);
5509			continue;
5510		}
5511
5512		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5513				    name, rdataset.ttl, &rdata));
5514		dns_rdata_reset(&rdata);
5515	}
5516	if (result != ISC_R_NOMORE)
5517		goto failure;
5518
5519	dns_rdataset_disassociate(&rdataset);
5520
5521 try_private:
5522
5523	if (active)
5524		goto add;
5525	/*
5526	 * Delete all private records which match that in nsec3chain.
5527	 */
5528	result = dns_db_findrdataset(db, node, ver, privatetype,
5529				     0, 0, &rdataset, NULL);
5530	if (result == ISC_R_NOTFOUND)
5531		goto add;
5532	if (result != ISC_R_SUCCESS)
5533		goto failure;
5534
5535	for (result = dns_rdataset_first(&rdataset);
5536	     result == ISC_R_SUCCESS;
5537	     result = dns_rdataset_next(&rdataset)) {
5538		dns_rdata_t private = DNS_RDATA_INIT;
5539		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
5540
5541		dns_rdataset_current(&rdataset, &private);
5542		if (!dns_nsec3param_fromprivate(&private, &rdata,
5543						buf, sizeof(buf)))
5544			continue;
5545		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5546
5547		if (nsec3param.hash != chain->nsec3param.hash ||
5548		    nsec3param.iterations != chain->nsec3param.iterations ||
5549		    nsec3param.salt_length != chain->nsec3param.salt_length ||
5550		    memcmp(nsec3param.salt, chain->nsec3param.salt,
5551			   nsec3param.salt_length)) {
5552			dns_rdata_reset(&rdata);
5553			continue;
5554		}
5555
5556		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5557				    name, rdataset.ttl, &private));
5558		dns_rdata_reset(&rdata);
5559	}
5560	if (result != ISC_R_NOMORE)
5561		goto failure;
5562
5563  add:
5564	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
5565		result = ISC_R_SUCCESS;
5566		goto failure;
5567	}
5568
5569	/*
5570	 * Add a NSEC3PARAM record which matches that in nsec3chain but
5571	 * with all flags bits cleared.
5572	 *
5573	 * Note: we do not clear chain->nsec3param.flags as this change
5574	 * may be reversed.
5575	 */
5576	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
5577	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
5578				   dns_rdatatype_nsec3param,
5579				   &chain->nsec3param, &buffer));
5580	rdata.data[1] = 0;	/* Clear flag bits. */
5581	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
5582
5583  failure:
5584	dns_db_detachnode(db, &node);
5585	if (dns_rdataset_isassociated(&rdataset))
5586		dns_rdataset_disassociate(&rdataset);
5587	return (result);
5588}
5589
5590static isc_result_t
5591delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
5592	    dns_name_t *name, dns_diff_t *diff)
5593{
5594	dns_rdataset_t rdataset;
5595	isc_result_t result;
5596
5597	dns_rdataset_init(&rdataset);
5598
5599	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
5600				     0, 0, &rdataset, NULL);
5601	if (result == ISC_R_NOTFOUND)
5602		return (ISC_R_SUCCESS);
5603	if (result != ISC_R_SUCCESS)
5604		return (result);
5605	for (result = dns_rdataset_first(&rdataset);
5606	     result == ISC_R_SUCCESS;
5607	     result = dns_rdataset_next(&rdataset)) {
5608		dns_rdata_t rdata = DNS_RDATA_INIT;
5609
5610		dns_rdataset_current(&rdataset, &rdata);
5611		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
5612				    rdataset.ttl, &rdata));
5613	}
5614	if (result == ISC_R_NOMORE)
5615		result = ISC_R_SUCCESS;
5616 failure:
5617	dns_rdataset_disassociate(&rdataset);
5618	return (result);
5619}
5620
5621static isc_result_t
5622deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
5623		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
5624		    dns_diff_t *diff)
5625{
5626	dns_rdataset_t rdataset;
5627	dns_rdata_nsec3_t nsec3;
5628	isc_result_t result;
5629
5630	dns_rdataset_init(&rdataset);
5631	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
5632				     0, 0, &rdataset, NULL);
5633	if (result == ISC_R_NOTFOUND)
5634		return (ISC_R_SUCCESS);
5635	if (result != ISC_R_SUCCESS)
5636		return (result);
5637
5638	for (result = dns_rdataset_first(&rdataset);
5639	     result == ISC_R_SUCCESS;
5640	     result = dns_rdataset_next(&rdataset)) {
5641		dns_rdata_t rdata = DNS_RDATA_INIT;
5642
5643		dns_rdataset_current(&rdataset, &rdata);
5644		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
5645		if (nsec3.hash != param->hash ||
5646		    nsec3.iterations != param->iterations ||
5647		    nsec3.salt_length != param->salt_length ||
5648		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
5649			continue;
5650		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
5651				    rdataset.ttl, &rdata));
5652	}
5653	if (result == ISC_R_NOMORE)
5654		result = ISC_R_SUCCESS;
5655 failure:
5656	dns_rdataset_disassociate(&rdataset);
5657	return (result);
5658}
5659
5660static isc_result_t
5661need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
5662		const dns_rdata_nsec3param_t *param,
5663		isc_boolean_t *answer)
5664{
5665	dns_dbnode_t *node = NULL;
5666	dns_rdata_t rdata = DNS_RDATA_INIT;
5667	dns_rdata_nsec3param_t myparam;
5668	dns_rdataset_t rdataset;
5669	isc_result_t result;
5670
5671	*answer = ISC_FALSE;
5672
5673	result = dns_db_getoriginnode(db, &node);
5674	RUNTIME_CHECK(result == ISC_R_SUCCESS);
5675
5676	dns_rdataset_init(&rdataset);
5677
5678	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
5679				     0, 0, &rdataset, NULL);
5680	if (result == ISC_R_SUCCESS) {
5681		dns_rdataset_disassociate(&rdataset);
5682		dns_db_detachnode(db, &node);
5683		return (result);
5684	}
5685	if (result != ISC_R_NOTFOUND) {
5686		dns_db_detachnode(db, &node);
5687		return (result);
5688	}
5689
5690	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5691				     0, 0, &rdataset, NULL);
5692	if (result == ISC_R_NOTFOUND) {
5693		*answer = ISC_TRUE;
5694		dns_db_detachnode(db, &node);
5695		return (ISC_R_SUCCESS);
5696	}
5697	if (result != ISC_R_SUCCESS) {
5698		dns_db_detachnode(db, &node);
5699		return (result);
5700	}
5701
5702	for (result = dns_rdataset_first(&rdataset);
5703	     result == ISC_R_SUCCESS;
5704	     result = dns_rdataset_next(&rdataset)) {
5705		dns_rdataset_current(&rdataset, &rdata);
5706		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
5707		dns_rdata_reset(&rdata);
5708		/*
5709		 * Ignore any NSEC3PARAM removals.
5710		 */
5711		if (NSEC3REMOVE(myparam.flags))
5712			continue;
5713		/*
5714		 * Ignore the chain that we are in the process of deleting.
5715		 */
5716		if (myparam.hash == param->hash &&
5717		    myparam.iterations == param->iterations &&
5718		    myparam.salt_length == param->salt_length &&
5719		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
5720			continue;
5721		/*
5722		 * Found an active NSEC3 chain.
5723		 */
5724		break;
5725	}
5726	if (result == ISC_R_NOMORE) {
5727		*answer = ISC_TRUE;
5728		result = ISC_R_SUCCESS;
5729	}
5730
5731 failure:
5732	if (dns_rdataset_isassociated(&rdataset))
5733		dns_rdataset_disassociate(&rdataset);
5734	dns_db_detachnode(db, &node);
5735	return (result);
5736}
5737
5738static isc_result_t
5739update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
5740	    dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
5741	    isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
5742	    isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
5743	    dns_diff_t *sig_diff)
5744{
5745	dns_difftuple_t *tuple;
5746	isc_result_t result;
5747
5748	for (tuple = ISC_LIST_HEAD(diff->tuples);
5749	     tuple != NULL;
5750	     tuple = ISC_LIST_HEAD(diff->tuples)) {
5751		result = del_sigs(zone, db, version, &tuple->name,
5752				  tuple->rdata.type, sig_diff,
5753				  zone_keys, nkeys, now, ISC_FALSE);
5754		if (result != ISC_R_SUCCESS) {
5755			dns_zone_log(zone, ISC_LOG_ERROR,
5756				     "update_sigs:del_sigs -> %s\n",
5757				     dns_result_totext(result));
5758			return (result);
5759		}
5760		result = add_sigs(db, version, &tuple->name,
5761				  tuple->rdata.type, sig_diff,
5762				  zone_keys, nkeys, zone->mctx, inception,
5763				  expire, check_ksk, keyset_kskonly);
5764		if (result != ISC_R_SUCCESS) {
5765			dns_zone_log(zone, ISC_LOG_ERROR,
5766				     "update_sigs:add_sigs -> %s\n",
5767				     dns_result_totext(result));
5768			return (result);
5769		}
5770
5771		do {
5772			dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
5773			while (next != NULL &&
5774			       (tuple->rdata.type != next->rdata.type ||
5775				!dns_name_equal(&tuple->name, &next->name)))
5776				next = ISC_LIST_NEXT(next, link);
5777			ISC_LIST_UNLINK(diff->tuples, tuple, link);
5778			dns_diff_appendminimal(sig_diff, &tuple);
5779			INSIST(tuple == NULL);
5780			tuple = next;
5781		} while (tuple != NULL);
5782	}
5783	return (ISC_R_SUCCESS);
5784}
5785
5786/*
5787 * Incrementally build and sign a new NSEC3 chain using the parameters
5788 * requested.
5789 */
5790static void
5791zone_nsec3chain(dns_zone_t *zone) {
5792	dns_db_t *db = NULL;
5793	dns_dbnode_t *node = NULL;
5794	dns_dbversion_t *version = NULL;
5795	dns_diff_t sig_diff;
5796	dns_diff_t nsec_diff;
5797	dns_diff_t nsec3_diff;
5798	dns_diff_t param_diff;
5799	dns_fixedname_t fixed;
5800	dns_fixedname_t nextfixed;
5801	dns_name_t *name, *nextname;
5802	dns_rdataset_t rdataset;
5803	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
5804	dns_nsec3chainlist_t cleanup;
5805	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
5806	isc_int32_t signatures;
5807	isc_boolean_t check_ksk, keyset_kskonly;
5808	isc_boolean_t delegation;
5809	isc_boolean_t first;
5810	isc_result_t result;
5811	isc_stdtime_t now, inception, soaexpire, expire;
5812	isc_uint32_t jitter;
5813	unsigned int i;
5814	unsigned int nkeys = 0;
5815	isc_uint32_t nodes;
5816	isc_boolean_t unsecure = ISC_FALSE;
5817	isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
5818	isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
5819	dns_rdatasetiter_t *iterator = NULL;
5820	isc_boolean_t buildnsecchain;
5821	isc_boolean_t updatensec = ISC_FALSE;
5822	dns_rdatatype_t privatetype = zone->privatetype;
5823
5824	dns_rdataset_init(&rdataset);
5825	dns_fixedname_init(&fixed);
5826	name = dns_fixedname_name(&fixed);
5827	dns_fixedname_init(&nextfixed);
5828	nextname = dns_fixedname_name(&nextfixed);
5829	dns_diff_init(zone->mctx, &param_diff);
5830	dns_diff_init(zone->mctx, &nsec3_diff);
5831	dns_diff_init(zone->mctx, &nsec_diff);
5832	dns_diff_init(zone->mctx, &sig_diff);
5833	sig_diff.resign = zone->sigresigninginterval;
5834	ISC_LIST_INIT(cleanup);
5835
5836	/*
5837	 * Updates are disabled.  Pause for 5 minutes.
5838	 */
5839	if (zone->update_disabled) {
5840		result = ISC_R_FAILURE;
5841		goto failure;
5842	}
5843
5844	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5845	dns_db_attach(zone->db, &db);
5846	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5847
5848	result = dns_db_newversion(db, &version);
5849	if (result != ISC_R_SUCCESS) {
5850		dns_zone_log(zone, ISC_LOG_ERROR,
5851			     "zone_nsec3chain:dns_db_newversion -> %s\n",
5852			     dns_result_totext(result));
5853		goto failure;
5854	}
5855
5856	result = find_zone_keys(zone, db, version, zone->mctx,
5857				DNS_MAXZONEKEYS, zone_keys, &nkeys);
5858	if (result != ISC_R_SUCCESS) {
5859		dns_zone_log(zone, ISC_LOG_ERROR,
5860			     "zone_nsec3chain:find_zone_keys -> %s\n",
5861			     dns_result_totext(result));
5862		goto failure;
5863	}
5864
5865	isc_stdtime_get(&now);
5866	inception = now - 3600;	/* Allow for clock skew. */
5867	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5868
5869	/*
5870	 * Spread out signatures over time if they happen to be
5871	 * clumped.  We don't do this for each add_sigs() call as
5872	 * we still want some clustering to occur.
5873	 */
5874	isc_random_get(&jitter);
5875	expire = soaexpire - jitter % 3600;
5876
5877	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5878	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5879
5880	/*
5881	 * We keep pulling nodes off each iterator in turn until
5882	 * we have no more nodes to pull off or we reach the limits
5883	 * for this quantum.
5884	 */
5885	nodes = zone->nodes;
5886	signatures = zone->signatures;
5887	LOCK_ZONE(zone);
5888	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
5889	UNLOCK_ZONE(zone);
5890	first = ISC_TRUE;
5891
5892	if (nsec3chain != NULL)
5893		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
5894	/*
5895	 * Generate new NSEC3 chains first.
5896	 */
5897	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
5898		LOCK_ZONE(zone);
5899		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
5900
5901		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5902		if (nsec3chain->done || nsec3chain->db != zone->db) {
5903			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
5904			ISC_LIST_APPEND(cleanup, nsec3chain, link);
5905		}
5906		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5907		UNLOCK_ZONE(zone);
5908		if (ISC_LIST_TAIL(cleanup) == nsec3chain)
5909			goto next_addchain;
5910
5911		/*
5912		 * Possible future db.
5913		 */
5914		if (nsec3chain->db != db) {
5915			goto next_addchain;
5916		}
5917
5918		if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
5919			goto next_addchain;
5920
5921		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
5922
5923		if (nsec3chain->delete_nsec) {
5924			delegation = ISC_FALSE;
5925			dns_dbiterator_pause(nsec3chain->dbiterator);
5926			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
5927			goto next_addnode;
5928		}
5929		/*
5930		 * On the first pass we need to check if the current node
5931		 * has not been obscured.
5932		 */
5933		delegation = ISC_FALSE;
5934		unsecure = ISC_FALSE;
5935		if (first) {
5936			dns_fixedname_t ffound;
5937			dns_name_t *found;
5938			dns_fixedname_init(&ffound);
5939			found = dns_fixedname_name(&ffound);
5940			result = dns_db_find(db, name, version,
5941					     dns_rdatatype_soa,
5942					     DNS_DBFIND_NOWILD, 0, NULL, found,
5943					     NULL, NULL);
5944			if ((result == DNS_R_DELEGATION ||
5945			    result == DNS_R_DNAME) &&
5946			    !dns_name_equal(name, found)) {
5947				/*
5948				 * Remember the obscuring name so that
5949				 * we skip all obscured names.
5950				 */
5951				dns_name_copy(found, name, NULL);
5952				delegation = ISC_TRUE;
5953				goto next_addnode;
5954			}
5955		}
5956
5957		/*
5958		 * Check to see if this is a bottom of zone node.
5959		 */
5960		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5961		if (result == ISC_R_NOTFOUND)	/* Empty node? */
5962			goto next_addnode;
5963		if (result != ISC_R_SUCCESS)
5964			goto failure;
5965
5966		seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
5967			ISC_FALSE;
5968		for (result = dns_rdatasetiter_first(iterator);
5969		     result == ISC_R_SUCCESS;
5970		     result = dns_rdatasetiter_next(iterator)) {
5971			dns_rdatasetiter_current(iterator, &rdataset);
5972			INSIST(rdataset.type != dns_rdatatype_nsec3);
5973			if (rdataset.type == dns_rdatatype_soa)
5974				seen_soa = ISC_TRUE;
5975			else if (rdataset.type == dns_rdatatype_ns)
5976				seen_ns = ISC_TRUE;
5977			else if (rdataset.type == dns_rdatatype_dname)
5978				seen_dname = ISC_TRUE;
5979			else if (rdataset.type == dns_rdatatype_ds)
5980				seen_ds = ISC_TRUE;
5981			else if (rdataset.type == dns_rdatatype_nsec)
5982				seen_nsec = ISC_TRUE;
5983			dns_rdataset_disassociate(&rdataset);
5984		}
5985		dns_rdatasetiter_destroy(&iterator);
5986		/*
5987		 * Is there a NSEC chain than needs to be cleaned up?
5988		 */
5989		if (seen_nsec)
5990			nsec3chain->seen_nsec = ISC_TRUE;
5991		if (seen_ns && !seen_soa && !seen_ds)
5992			unsecure = ISC_TRUE;
5993		if ((seen_ns && !seen_soa) || seen_dname)
5994			delegation = ISC_TRUE;
5995
5996		/*
5997		 * Process one node.
5998		 */
5999		dns_dbiterator_pause(nsec3chain->dbiterator);
6000		result = dns_nsec3_addnsec3(db, version, name,
6001					    &nsec3chain->nsec3param,
6002					    zone->minimum, unsecure,
6003					    &nsec3_diff);
6004		if (result != ISC_R_SUCCESS) {
6005			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6006				     "dns_nsec3_addnsec3 -> %s\n",
6007				     dns_result_totext(result));
6008			goto failure;
6009		}
6010
6011		/*
6012		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
6013		 * two signatures.  Additionally there will, in general, be
6014		 * two signature generated below.
6015		 *
6016		 * If we are only changing the optout flag the cost is half
6017		 * that of the cost of generating a completely new chain.
6018		 */
6019		signatures -= 4;
6020
6021		/*
6022		 * Go onto next node.
6023		 */
6024 next_addnode:
6025		first = ISC_FALSE;
6026		dns_db_detachnode(db, &node);
6027		do {
6028			result = dns_dbiterator_next(nsec3chain->dbiterator);
6029
6030			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
6031				CHECK(fixup_nsec3param(db, version, nsec3chain,
6032						       ISC_FALSE, privatetype,
6033						       &param_diff));
6034				LOCK_ZONE(zone);
6035				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6036						link);
6037				UNLOCK_ZONE(zone);
6038				ISC_LIST_APPEND(cleanup, nsec3chain, link);
6039				goto next_addchain;
6040			}
6041			if (result == ISC_R_NOMORE) {
6042				dns_dbiterator_pause(nsec3chain->dbiterator);
6043				if (nsec3chain->seen_nsec) {
6044					CHECK(fixup_nsec3param(db, version,
6045							       nsec3chain,
6046							       ISC_TRUE,
6047							       privatetype,
6048							       &param_diff));
6049					nsec3chain->delete_nsec = ISC_TRUE;
6050					goto same_addchain;
6051				}
6052				CHECK(fixup_nsec3param(db, version, nsec3chain,
6053						       ISC_FALSE, privatetype,
6054						       &param_diff));
6055				LOCK_ZONE(zone);
6056				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6057						link);
6058				UNLOCK_ZONE(zone);
6059				ISC_LIST_APPEND(cleanup, nsec3chain, link);
6060				goto next_addchain;
6061			} else if (result != ISC_R_SUCCESS) {
6062				dns_zone_log(zone, ISC_LOG_ERROR,
6063					     "zone_nsec3chain:"
6064					     "dns_dbiterator_next -> %s\n",
6065					     dns_result_totext(result));
6066				goto failure;
6067			} else if (delegation) {
6068				dns_dbiterator_current(nsec3chain->dbiterator,
6069						       &node, nextname);
6070				dns_db_detachnode(db, &node);
6071				if (!dns_name_issubdomain(nextname, name))
6072					break;
6073			} else
6074				break;
6075		} while (1);
6076		continue;
6077
6078 same_addchain:
6079		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6080		first = ISC_TRUE;
6081		continue;
6082
6083 next_addchain:
6084		dns_dbiterator_pause(nsec3chain->dbiterator);
6085		nsec3chain = nextnsec3chain;
6086		first = ISC_TRUE;
6087		if (nsec3chain != NULL)
6088			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6089	}
6090
6091	/*
6092	 * Process removals.
6093	 */
6094	LOCK_ZONE(zone);
6095	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6096	UNLOCK_ZONE(zone);
6097	first = ISC_TRUE;
6098	buildnsecchain = ISC_FALSE;
6099	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6100		LOCK_ZONE(zone);
6101		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6102		UNLOCK_ZONE(zone);
6103
6104		if (nsec3chain->db != db)
6105			goto next_removechain;
6106
6107		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
6108			goto next_removechain;
6109
6110		/*
6111		 * Work out if we need to build a NSEC chain as a consequence
6112		 * of removing this NSEC3 chain.
6113		 */
6114		if (first && !updatensec &&
6115		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0) {
6116			result = need_nsec_chain(db, version,
6117						 &nsec3chain->nsec3param,
6118						 &buildnsecchain);
6119			if (result != ISC_R_SUCCESS) {
6120				dns_zone_log(zone, ISC_LOG_ERROR,
6121					     "zone_nsec3chain:"
6122					     "need_nsec_chain -> %s\n",
6123					     dns_result_totext(result));
6124				goto failure;
6125			}
6126		}
6127
6128		if (first)
6129			dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
6130				     "buildnsecchain = %u\n", buildnsecchain);
6131
6132		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6133		delegation = ISC_FALSE;
6134
6135		if (!buildnsecchain) {
6136			/*
6137			 * Delete the NSECPARAM record that matches this chain.
6138			 */
6139			if (first) {
6140				result = fixup_nsec3param(db, version,
6141							  nsec3chain,
6142							  ISC_TRUE, privatetype,
6143							  &param_diff);
6144				if (result != ISC_R_SUCCESS) {
6145					dns_zone_log(zone, ISC_LOG_ERROR,
6146						     "zone_nsec3chain:"
6147						     "fixup_nsec3param -> %s\n",
6148						     dns_result_totext(result));
6149					goto failure;
6150				}
6151			}
6152
6153			/*
6154			 *  Delete the NSEC3 records.
6155			 */
6156			result = deletematchingnsec3(db, version, node, name,
6157						     &nsec3chain->nsec3param,
6158						     &nsec3_diff);
6159			if (result != ISC_R_SUCCESS) {
6160				dns_zone_log(zone, ISC_LOG_ERROR,
6161					     "zone_nsec3chain:"
6162					     "deletematchingnsec3 -> %s\n",
6163					     dns_result_totext(result));
6164				goto failure;
6165			}
6166			goto next_removenode;
6167		}
6168
6169		if (first) {
6170			dns_fixedname_t ffound;
6171			dns_name_t *found;
6172			dns_fixedname_init(&ffound);
6173			found = dns_fixedname_name(&ffound);
6174			result = dns_db_find(db, name, version,
6175					     dns_rdatatype_soa,
6176					     DNS_DBFIND_NOWILD, 0, NULL, found,
6177					     NULL, NULL);
6178			if ((result == DNS_R_DELEGATION ||
6179			     result == DNS_R_DNAME) &&
6180			    !dns_name_equal(name, found)) {
6181				/*
6182				 * Remember the obscuring name so that
6183				 * we skip all obscured names.
6184				 */
6185				dns_name_copy(found, name, NULL);
6186				delegation = ISC_TRUE;
6187				goto next_removenode;
6188			}
6189		}
6190
6191		/*
6192		 * Check to see if this is a bottom of zone node.
6193		 */
6194		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6195		if (result == ISC_R_NOTFOUND)	/* Empty node? */
6196			goto next_removenode;
6197		if (result != ISC_R_SUCCESS)
6198			goto failure;
6199
6200		seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
6201			seen_rr = ISC_FALSE;
6202		for (result = dns_rdatasetiter_first(iterator);
6203		     result == ISC_R_SUCCESS;
6204		     result = dns_rdatasetiter_next(iterator)) {
6205			dns_rdatasetiter_current(iterator, &rdataset);
6206			if (rdataset.type == dns_rdatatype_soa)
6207				seen_soa = ISC_TRUE;
6208			else if (rdataset.type == dns_rdatatype_ns)
6209				seen_ns = ISC_TRUE;
6210			else if (rdataset.type == dns_rdatatype_dname)
6211				seen_dname = ISC_TRUE;
6212			else if (rdataset.type == dns_rdatatype_nsec)
6213				seen_nsec = ISC_TRUE;
6214			else if (rdataset.type == dns_rdatatype_nsec3)
6215				seen_nsec3 = ISC_TRUE;
6216			if (rdataset.type != dns_rdatatype_rrsig)
6217				seen_rr = ISC_TRUE;
6218			dns_rdataset_disassociate(&rdataset);
6219		}
6220		dns_rdatasetiter_destroy(&iterator);
6221
6222		if (!seen_rr || seen_nsec3 || seen_nsec)
6223			goto next_removenode;
6224		if ((seen_ns && !seen_soa) || seen_dname)
6225			delegation = ISC_TRUE;
6226
6227		/*
6228		 * Add a NSEC record except at the origin.
6229		 */
6230		if (!dns_name_equal(name, dns_db_origin(db))) {
6231			dns_dbiterator_pause(nsec3chain->dbiterator);
6232			CHECK(add_nsec(db, version, name, node, zone->minimum,
6233				       delegation, &nsec_diff));
6234		}
6235
6236 next_removenode:
6237		first = ISC_FALSE;
6238		dns_db_detachnode(db, &node);
6239		do {
6240			result = dns_dbiterator_next(nsec3chain->dbiterator);
6241			if (result == ISC_R_NOMORE && buildnsecchain) {
6242				/*
6243				 * The NSEC chain should now be built.
6244				 * We can now remove the NSEC3 chain.
6245				 */
6246				updatensec = ISC_TRUE;
6247				goto same_removechain;
6248			}
6249			if (result == ISC_R_NOMORE) {
6250				LOCK_ZONE(zone);
6251				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6252						link);
6253				UNLOCK_ZONE(zone);
6254				ISC_LIST_APPEND(cleanup, nsec3chain, link);
6255				dns_dbiterator_pause(nsec3chain->dbiterator);
6256				result = fixup_nsec3param(db, version,
6257							  nsec3chain, ISC_FALSE,
6258							  privatetype,
6259							  &param_diff);
6260				if (result != ISC_R_SUCCESS) {
6261					dns_zone_log(zone, ISC_LOG_ERROR,
6262						     "zone_nsec3chain:"
6263						     "fixup_nsec3param -> %s\n",
6264						     dns_result_totext(result));
6265					goto failure;
6266				}
6267				goto next_removechain;
6268			} else if (result != ISC_R_SUCCESS) {
6269				dns_zone_log(zone, ISC_LOG_ERROR,
6270					     "zone_nsec3chain:"
6271					     "dns_dbiterator_next -> %s\n",
6272					     dns_result_totext(result));
6273				goto failure;
6274			} else if (delegation) {
6275				dns_dbiterator_current(nsec3chain->dbiterator,
6276						       &node, nextname);
6277				dns_db_detachnode(db, &node);
6278				if (!dns_name_issubdomain(nextname, name))
6279					break;
6280			} else
6281				break;
6282		} while (1);
6283		continue;
6284
6285 same_removechain:
6286		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6287		buildnsecchain = ISC_FALSE;
6288		first = ISC_TRUE;
6289		continue;
6290
6291 next_removechain:
6292		dns_dbiterator_pause(nsec3chain->dbiterator);
6293		nsec3chain = nextnsec3chain;
6294		first = ISC_TRUE;
6295	}
6296
6297	/*
6298	 * We may need to update the NSEC/NSEC3 records for the zone apex.
6299	 */
6300	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
6301		isc_boolean_t rebuild_nsec = ISC_FALSE,
6302			      rebuild_nsec3 = ISC_FALSE;
6303		result = dns_db_getoriginnode(db, &node);
6304		RUNTIME_CHECK(result == ISC_R_SUCCESS);
6305		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6306		if (result != ISC_R_SUCCESS) {
6307			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6308				     "dns_db_allrdatasets -> %s\n",
6309				     dns_result_totext(result));
6310			goto failure;
6311		}
6312		for (result = dns_rdatasetiter_first(iterator);
6313		     result == ISC_R_SUCCESS;
6314		     result = dns_rdatasetiter_next(iterator)) {
6315			dns_rdatasetiter_current(iterator, &rdataset);
6316			if (rdataset.type == dns_rdatatype_nsec)
6317				rebuild_nsec = ISC_TRUE;
6318			if (rdataset.type == dns_rdatatype_nsec3param)
6319				rebuild_nsec3 = ISC_TRUE;
6320			dns_rdataset_disassociate(&rdataset);
6321		}
6322		dns_rdatasetiter_destroy(&iterator);
6323		dns_db_detachnode(db, &node);
6324
6325		if (rebuild_nsec) {
6326			if (nsec3chain != NULL)
6327				dns_dbiterator_pause(nsec3chain->dbiterator);
6328			result = updatesecure(db, version, &zone->origin,
6329					      zone->minimum, ISC_TRUE,
6330					      &nsec_diff);
6331			if (result != ISC_R_SUCCESS) {
6332				dns_zone_log(zone, ISC_LOG_ERROR,
6333					     "zone_nsec3chain:"
6334					     "updatesecure -> %s\n",
6335					     dns_result_totext(result));
6336				goto failure;
6337			}
6338		}
6339		if (rebuild_nsec3) {
6340			result = dns_nsec3_addnsec3s(db, version,
6341						     dns_db_origin(db),
6342						     zone->minimum, ISC_FALSE,
6343						     &nsec3_diff);
6344			if (result != ISC_R_SUCCESS) {
6345				dns_zone_log(zone, ISC_LOG_ERROR,
6346					     "zone_nsec3chain:"
6347					     "dns_nsec3_addnsec3s -> %s\n",
6348					     dns_result_totext(result));
6349				goto failure;
6350			}
6351		}
6352	}
6353
6354	/*
6355	 * Add / update signatures for the NSEC3 records.
6356	 */
6357	result = update_sigs(&nsec3_diff, db, version, zone_keys,
6358			     nkeys, zone, inception, expire, now,
6359			     check_ksk, keyset_kskonly, &sig_diff);
6360	if (result != ISC_R_SUCCESS) {
6361		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6362			     "update_sigs -> %s\n", dns_result_totext(result));
6363		goto failure;
6364	}
6365
6366	/*
6367	 * We have changed the NSEC3PARAM or private RRsets
6368	 * above so we need to update the signatures.
6369	 */
6370	result = update_sigs(&param_diff, db, version, zone_keys,
6371			     nkeys, zone, inception, expire, now,
6372			     check_ksk, keyset_kskonly, &sig_diff);
6373	if (result != ISC_R_SUCCESS) {
6374		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6375			     "update_sigs -> %s\n", dns_result_totext(result));
6376		goto failure;
6377	}
6378
6379	if (updatensec) {
6380		if (nsec3chain != NULL)
6381			dns_dbiterator_pause(nsec3chain->dbiterator);
6382		result = updatesecure(db, version, &zone->origin,
6383				      zone->minimum, ISC_FALSE, &nsec_diff);
6384		if (result != ISC_R_SUCCESS) {
6385			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6386				     "updatesecure -> %s\n",
6387				     dns_result_totext(result));
6388			goto failure;
6389		}
6390	}
6391
6392	result = update_sigs(&nsec_diff, db, version, zone_keys,
6393			     nkeys, zone, inception, expire, now,
6394			     check_ksk, keyset_kskonly, &sig_diff);
6395	if (result != ISC_R_SUCCESS) {
6396		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6397			     "update_sigs -> %s\n", dns_result_totext(result));
6398		goto failure;
6399	}
6400
6401	/*
6402	 * If we made no effective changes to the zone then we can just
6403	 * cleanup otherwise we need to increment the serial.
6404	 */
6405	if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
6406		goto done;
6407
6408	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6409			  &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
6410	if (result != ISC_R_SUCCESS) {
6411		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6412			     "del_sigs -> %s\n", dns_result_totext(result));
6413		goto failure;
6414	}
6415
6416	result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
6417	if (result != ISC_R_SUCCESS) {
6418		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6419			     "increment_soa_serial -> %s\n",
6420			     dns_result_totext(result));
6421		goto failure;
6422	}
6423
6424	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6425			  &sig_diff, zone_keys, nkeys, zone->mctx, inception,
6426			  soaexpire, check_ksk, keyset_kskonly);
6427	if (result != ISC_R_SUCCESS) {
6428		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6429			     "add_sigs -> %s\n", dns_result_totext(result));
6430		goto failure;
6431	}
6432
6433	/* Write changes to journal file. */
6434	CHECK(zone_journal(zone, &sig_diff, "zone_nsec3chain"));
6435
6436	LOCK_ZONE(zone);
6437	zone_needdump(zone, DNS_DUMP_DELAY);
6438	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6439	UNLOCK_ZONE(zone);
6440
6441 done:
6442	/*
6443	 * Pause all iterators so that dns_db_closeversion() can succeed.
6444	 */
6445	LOCK_ZONE(zone);
6446	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6447	     nsec3chain != NULL;
6448	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6449		dns_dbiterator_pause(nsec3chain->dbiterator);
6450	UNLOCK_ZONE(zone);
6451
6452	/*
6453	 * Everything has succeeded. Commit the changes.
6454	 */
6455	dns_db_closeversion(db, &version, ISC_TRUE);
6456
6457	/*
6458	 * Everything succeeded so we can clean these up now.
6459	 */
6460	nsec3chain = ISC_LIST_HEAD(cleanup);
6461	while (nsec3chain != NULL) {
6462		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6463		dns_db_detach(&nsec3chain->db);
6464		dns_dbiterator_destroy(&nsec3chain->dbiterator);
6465		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6466		nsec3chain = ISC_LIST_HEAD(cleanup);
6467	}
6468
6469	set_resigntime(zone);
6470
6471 failure:
6472	if (result != ISC_R_SUCCESS)
6473		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s\n",
6474			     dns_result_totext(result));
6475	/*
6476	 * On error roll back the current nsec3chain.
6477	 */
6478	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
6479		if (nsec3chain->done) {
6480			dns_db_detach(&nsec3chain->db);
6481			dns_dbiterator_destroy(&nsec3chain->dbiterator);
6482			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6483		} else {
6484			result = dns_dbiterator_first(nsec3chain->dbiterator);
6485			RUNTIME_CHECK(result == ISC_R_SUCCESS);
6486			dns_dbiterator_pause(nsec3chain->dbiterator);
6487			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6488		}
6489	}
6490
6491	/*
6492	 * Rollback the cleanup list.
6493	 */
6494	nsec3chain = ISC_LIST_TAIL(cleanup);
6495	while (nsec3chain != NULL) {
6496		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6497		if (nsec3chain->done) {
6498			dns_db_detach(&nsec3chain->db);
6499			dns_dbiterator_destroy(&nsec3chain->dbiterator);
6500			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6501		} else {
6502			LOCK_ZONE(zone);
6503			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
6504			UNLOCK_ZONE(zone);
6505			result = dns_dbiterator_first(nsec3chain->dbiterator);
6506			RUNTIME_CHECK(result == ISC_R_SUCCESS);
6507			dns_dbiterator_pause(nsec3chain->dbiterator);
6508			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6509		}
6510		nsec3chain = ISC_LIST_TAIL(cleanup);
6511	}
6512
6513	LOCK_ZONE(zone);
6514	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6515	     nsec3chain != NULL;
6516	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6517		dns_dbiterator_pause(nsec3chain->dbiterator);
6518	UNLOCK_ZONE(zone);
6519
6520	dns_diff_clear(&param_diff);
6521	dns_diff_clear(&nsec3_diff);
6522	dns_diff_clear(&nsec_diff);
6523	dns_diff_clear(&sig_diff);
6524
6525	if (iterator != NULL)
6526		dns_rdatasetiter_destroy(&iterator);
6527
6528	for (i = 0; i < nkeys; i++)
6529		dst_key_free(&zone_keys[i]);
6530
6531	if (node != NULL)
6532		dns_db_detachnode(db, &node);
6533	if (version != NULL) {
6534		dns_db_closeversion(db, &version, ISC_FALSE);
6535		dns_db_detach(&db);
6536	} else if (db != NULL)
6537		dns_db_detach(&db);
6538
6539	LOCK_ZONE(zone);
6540	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
6541		isc_interval_t i;
6542		if (zone->update_disabled || result != ISC_R_SUCCESS)
6543			isc_interval_set(&i, 60, 0);		/* 1 minute */
6544		else
6545			isc_interval_set(&i, 0, 10000000);	/* 10 ms */
6546		isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
6547	} else
6548		isc_time_settoepoch(&zone->nsec3chaintime);
6549	UNLOCK_ZONE(zone);
6550}
6551
6552static isc_result_t
6553del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6554	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
6555	isc_uint16_t keyid, dns_diff_t *diff)
6556{
6557	dns_rdata_rrsig_t rrsig;
6558	dns_rdataset_t rdataset;
6559	dns_rdatasetiter_t *iterator = NULL;
6560	isc_result_t result;
6561
6562	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6563	if (result != ISC_R_SUCCESS) {
6564		if (result == ISC_R_NOTFOUND)
6565			result = ISC_R_SUCCESS;
6566		return (result);
6567	}
6568
6569	dns_rdataset_init(&rdataset);
6570	for (result = dns_rdatasetiter_first(iterator);
6571	     result == ISC_R_SUCCESS;
6572	     result = dns_rdatasetiter_next(iterator)) {
6573		dns_rdatasetiter_current(iterator, &rdataset);
6574		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
6575			for (result = dns_rdataset_first(&rdataset);
6576			     result == ISC_R_SUCCESS;
6577			     result = dns_rdataset_next(&rdataset)) {
6578				dns_rdata_t rdata = DNS_RDATA_INIT;
6579				dns_rdataset_current(&rdataset, &rdata);
6580				CHECK(update_one_rr(db, version, diff,
6581						    DNS_DIFFOP_DEL, name,
6582						    rdataset.ttl, &rdata));
6583			}
6584			if (result != ISC_R_NOMORE)
6585				goto failure;
6586			dns_rdataset_disassociate(&rdataset);
6587			continue;
6588		}
6589		if (rdataset.type != dns_rdatatype_rrsig) {
6590			dns_rdataset_disassociate(&rdataset);
6591			continue;
6592		}
6593		for (result = dns_rdataset_first(&rdataset);
6594		     result == ISC_R_SUCCESS;
6595		     result = dns_rdataset_next(&rdataset)) {
6596			dns_rdata_t rdata = DNS_RDATA_INIT;
6597			dns_rdataset_current(&rdataset, &rdata);
6598			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
6599			if (rrsig.algorithm != algorithm ||
6600			    rrsig.keyid != keyid)
6601				continue;
6602			CHECK(update_one_rr(db, version, diff,
6603					    DNS_DIFFOP_DELRESIGN, name,
6604					    rdataset.ttl, &rdata));
6605		}
6606		dns_rdataset_disassociate(&rdataset);
6607		if (result != ISC_R_NOMORE)
6608			break;
6609	}
6610	if (result == ISC_R_NOMORE)
6611		result = ISC_R_SUCCESS;
6612 failure:
6613	if (dns_rdataset_isassociated(&rdataset))
6614		dns_rdataset_disassociate(&rdataset);
6615	dns_rdatasetiter_destroy(&iterator);
6616	return (result);
6617}
6618
6619/*
6620 * Incrementally sign the zone using the keys requested.
6621 * Builds the NSEC chain if required.
6622 */
6623static void
6624zone_sign(dns_zone_t *zone) {
6625	dns_db_t *db = NULL;
6626	dns_dbnode_t *node = NULL;
6627	dns_dbversion_t *version = NULL;
6628	dns_diff_t sig_diff;
6629	dns_diff_t post_diff;
6630	dns_fixedname_t fixed;
6631	dns_fixedname_t nextfixed;
6632	dns_name_t *name, *nextname;
6633	dns_rdataset_t rdataset;
6634	dns_signing_t *signing, *nextsigning;
6635	dns_signinglist_t cleanup;
6636	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6637	isc_int32_t signatures;
6638	isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
6639	isc_boolean_t commit = ISC_FALSE;
6640	isc_boolean_t delegation;
6641	isc_boolean_t build_nsec = ISC_FALSE;
6642	isc_boolean_t build_nsec3 = ISC_FALSE;
6643	isc_boolean_t first;
6644	isc_result_t result;
6645	isc_stdtime_t now, inception, soaexpire, expire;
6646	isc_uint32_t jitter;
6647	unsigned int i, j;
6648	unsigned int nkeys = 0;
6649	isc_uint32_t nodes;
6650
6651	dns_rdataset_init(&rdataset);
6652	dns_fixedname_init(&fixed);
6653	name = dns_fixedname_name(&fixed);
6654	dns_fixedname_init(&nextfixed);
6655	nextname = dns_fixedname_name(&nextfixed);
6656	dns_diff_init(zone->mctx, &sig_diff);
6657	sig_diff.resign = zone->sigresigninginterval;
6658	dns_diff_init(zone->mctx, &post_diff);
6659	ISC_LIST_INIT(cleanup);
6660
6661	/*
6662	 * Updates are disabled.  Pause for 5 minutes.
6663	 */
6664	if (zone->update_disabled) {
6665		result = ISC_R_FAILURE;
6666		goto failure;
6667	}
6668
6669	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6670	dns_db_attach(zone->db, &db);
6671	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6672
6673	result = dns_db_newversion(db, &version);
6674	if (result != ISC_R_SUCCESS) {
6675		dns_zone_log(zone, ISC_LOG_ERROR,
6676			     "zone_sign:dns_db_newversion -> %s\n",
6677			     dns_result_totext(result));
6678		goto failure;
6679	}
6680
6681	result = find_zone_keys(zone, db, version, zone->mctx,
6682				DNS_MAXZONEKEYS, zone_keys, &nkeys);
6683	if (result != ISC_R_SUCCESS) {
6684		dns_zone_log(zone, ISC_LOG_ERROR,
6685			     "zone_sign:find_zone_keys -> %s\n",
6686			     dns_result_totext(result));
6687		goto failure;
6688	}
6689
6690	isc_stdtime_get(&now);
6691	inception = now - 3600;	/* Allow for clock skew. */
6692	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6693
6694	/*
6695	 * Spread out signatures over time if they happen to be
6696	 * clumped.  We don't do this for each add_sigs() call as
6697	 * we still want some clustering to occur.
6698	 */
6699	isc_random_get(&jitter);
6700	expire = soaexpire - jitter % 3600;
6701
6702	/*
6703	 * We keep pulling nodes off each iterator in turn until
6704	 * we have no more nodes to pull off or we reach the limits
6705	 * for this quantum.
6706	 */
6707	nodes = zone->nodes;
6708	signatures = zone->signatures;
6709	signing = ISC_LIST_HEAD(zone->signing);
6710	first = ISC_TRUE;
6711
6712	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6713	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6714
6715	/* Determine which type of chain to build */
6716	CHECK(dns_private_chains(db, version, zone->privatetype,
6717				 &build_nsec, &build_nsec3));
6718
6719	/* If neither chain is found, default to NSEC */
6720	if (!build_nsec && !build_nsec3)
6721		build_nsec = ISC_TRUE;
6722
6723	while (signing != NULL && nodes-- > 0 && signatures > 0) {
6724		nextsigning = ISC_LIST_NEXT(signing, link);
6725
6726		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6727		if (signing->done || signing->db != zone->db) {
6728			/*
6729			 * The zone has been reloaded.	We will have
6730			 * created new signings as part of the reload
6731			 * process so we can destroy this one.
6732			 */
6733			ISC_LIST_UNLINK(zone->signing, signing, link);
6734			ISC_LIST_APPEND(cleanup, signing, link);
6735			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6736			goto next_signing;
6737		}
6738		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6739
6740		if (signing->db != db)
6741			goto next_signing;
6742
6743		delegation = ISC_FALSE;
6744
6745		if (first && signing->delete) {
6746			/*
6747			 * Remove the key we are deleting from consideration.
6748			 */
6749			for (i = 0, j = 0; i < nkeys; i++) {
6750				/*
6751				 * Find the key we want to remove.
6752				 */
6753				if (ALG(zone_keys[i]) == signing->algorithm &&
6754				    dst_key_id(zone_keys[i]) == signing->keyid)
6755				{
6756					if (KSK(zone_keys[i]))
6757						dst_key_free(&zone_keys[i]);
6758					continue;
6759				}
6760				zone_keys[j] = zone_keys[i];
6761				j++;
6762			}
6763			nkeys = j;
6764		}
6765
6766		dns_dbiterator_current(signing->dbiterator, &node, name);
6767
6768		if (signing->delete) {
6769			dns_dbiterator_pause(signing->dbiterator);
6770			CHECK(del_sig(db, version, name, node, nkeys,
6771				      signing->algorithm, signing->keyid,
6772				      &sig_diff));
6773		}
6774
6775		/*
6776		 * On the first pass we need to check if the current node
6777		 * has not been obscured.
6778		 */
6779		if (first) {
6780			dns_fixedname_t ffound;
6781			dns_name_t *found;
6782			dns_fixedname_init(&ffound);
6783			found = dns_fixedname_name(&ffound);
6784			result = dns_db_find(db, name, version,
6785					     dns_rdatatype_soa,
6786					     DNS_DBFIND_NOWILD, 0, NULL, found,
6787					     NULL, NULL);
6788			if ((result == DNS_R_DELEGATION ||
6789			    result == DNS_R_DNAME) &&
6790			    !dns_name_equal(name, found)) {
6791				/*
6792				 * Remember the obscuring name so that
6793				 * we skip all obscured names.
6794				 */
6795				dns_name_copy(found, name, NULL);
6796				delegation = ISC_TRUE;
6797				goto next_node;
6798			}
6799		}
6800
6801		/*
6802		 * Process one node.
6803		 */
6804		dns_dbiterator_pause(signing->dbiterator);
6805		for (i = 0; i < nkeys; i++) {
6806			isc_boolean_t both = ISC_FALSE;
6807
6808			/*
6809			 * Find the keys we want to sign with.
6810			 */
6811			if (!dst_key_isprivate(zone_keys[i]))
6812				continue;
6813
6814			/*
6815			 * When adding look for the specific key.
6816			 */
6817			if (!signing->delete &&
6818			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
6819			     dst_key_id(zone_keys[i]) != signing->keyid))
6820				continue;
6821
6822			/*
6823			 * When deleting make sure we are properly signed
6824			 * with the algorithm that was being removed.
6825			 */
6826			if (signing->delete &&
6827			    ALG(zone_keys[i]) != signing->algorithm)
6828				continue;
6829
6830			/*
6831			 * Do we do KSK processing?
6832			 */
6833			if (check_ksk && !REVOKE(zone_keys[i])) {
6834				isc_boolean_t have_ksk, have_nonksk;
6835				if (KSK(zone_keys[i])) {
6836					have_ksk = ISC_TRUE;
6837					have_nonksk = ISC_FALSE;
6838				} else {
6839					have_ksk = ISC_FALSE;
6840					have_nonksk = ISC_TRUE;
6841				}
6842				for (j = 0; j < nkeys; j++) {
6843					if (j == i ||
6844					    ALG(zone_keys[i]) !=
6845					    ALG(zone_keys[j]))
6846						continue;
6847					if (REVOKE(zone_keys[j]))
6848						continue;
6849					if (KSK(zone_keys[j]))
6850						have_ksk = ISC_TRUE;
6851					else
6852						have_nonksk = ISC_TRUE;
6853					both = have_ksk && have_nonksk;
6854					if (both)
6855						break;
6856				}
6857			}
6858			if (both || REVOKE(zone_keys[i]))
6859				is_ksk = KSK(zone_keys[i]);
6860			else
6861				is_ksk = ISC_FALSE;
6862
6863			CHECK(sign_a_node(db, name, node, version, build_nsec3,
6864					  build_nsec, zone_keys[i], inception,
6865					  expire, zone->minimum, is_ksk,
6866					  ISC_TF(both && keyset_kskonly),
6867					  &delegation, &sig_diff,
6868					  &signatures, zone->mctx));
6869			/*
6870			 * If we are adding we are done.  Look for other keys
6871			 * of the same algorithm if deleting.
6872			 */
6873			if (!signing->delete)
6874				break;
6875		}
6876
6877		/*
6878		 * Go onto next node.
6879		 */
6880 next_node:
6881		first = ISC_FALSE;
6882		dns_db_detachnode(db, &node);
6883		do {
6884			result = dns_dbiterator_next(signing->dbiterator);
6885			if (result == ISC_R_NOMORE) {
6886				ISC_LIST_UNLINK(zone->signing, signing, link);
6887				ISC_LIST_APPEND(cleanup, signing, link);
6888				dns_dbiterator_pause(signing->dbiterator);
6889				if (nkeys != 0 && build_nsec) {
6890					/*
6891					 * We have finished regenerating the
6892					 * zone with a zone signing key.
6893					 * The NSEC chain is now complete and
6894					 * there is a full set of signatures
6895					 * for the zone.  We can now clear the
6896					 * OPT bit from the NSEC record.
6897					 */
6898					result = updatesecure(db, version,
6899							      &zone->origin,
6900							      zone->minimum,
6901							      ISC_FALSE,
6902							      &post_diff);
6903					if (result != ISC_R_SUCCESS) {
6904						dns_zone_log(zone,
6905							     ISC_LOG_ERROR,
6906						    "updatesecure -> %s\n",
6907						    dns_result_totext(result));
6908						goto failure;
6909					}
6910				}
6911				result = updatesignwithkey(zone, signing,
6912							   version,
6913							   build_nsec3,
6914							   zone->minimum,
6915							   &post_diff);
6916				if (result != ISC_R_SUCCESS) {
6917					dns_zone_log(zone, ISC_LOG_ERROR,
6918						     "updatesignwithkey "
6919						     "-> %s\n",
6920						     dns_result_totext(result));
6921					goto failure;
6922				}
6923				build_nsec = ISC_FALSE;
6924				goto next_signing;
6925			} else if (result != ISC_R_SUCCESS) {
6926				dns_zone_log(zone, ISC_LOG_ERROR,
6927					"zone_sign:dns_dbiterator_next -> %s\n",
6928					     dns_result_totext(result));
6929				goto failure;
6930			} else if (delegation) {
6931				dns_dbiterator_current(signing->dbiterator,
6932						       &node, nextname);
6933				dns_db_detachnode(db, &node);
6934				if (!dns_name_issubdomain(nextname, name))
6935					break;
6936			} else
6937				break;
6938		} while (1);
6939		continue;
6940
6941 next_signing:
6942		dns_dbiterator_pause(signing->dbiterator);
6943		signing = nextsigning;
6944		first = ISC_TRUE;
6945	}
6946
6947	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
6948		result = update_sigs(&post_diff, db, version, zone_keys,
6949				     nkeys, zone, inception, expire, now,
6950				     check_ksk, keyset_kskonly, &sig_diff);
6951		if (result != ISC_R_SUCCESS) {
6952			dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
6953				     "update_sigs -> %s\n",
6954				     dns_result_totext(result));
6955			goto failure;
6956		}
6957	}
6958
6959	/*
6960	 * Have we changed anything?
6961	 */
6962	if (ISC_LIST_HEAD(sig_diff.tuples) == NULL) {
6963		result = ISC_R_SUCCESS;
6964		goto pauseall;
6965	}
6966
6967	commit = ISC_TRUE;
6968
6969	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6970			  &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
6971	if (result != ISC_R_SUCCESS) {
6972		dns_zone_log(zone, ISC_LOG_ERROR,
6973			     "zone_sign:del_sigs -> %s\n",
6974			     dns_result_totext(result));
6975		goto failure;
6976	}
6977
6978	result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
6979	if (result != ISC_R_SUCCESS) {
6980		dns_zone_log(zone, ISC_LOG_ERROR,
6981			     "zone_sign:increment_soa_serial -> %s\n",
6982			     dns_result_totext(result));
6983		goto failure;
6984	}
6985
6986	/*
6987	 * Generate maximum life time signatures so that the above loop
6988	 * termination is sensible.
6989	 */
6990	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6991			  &sig_diff, zone_keys, nkeys, zone->mctx, inception,
6992			  soaexpire, check_ksk, keyset_kskonly);
6993	if (result != ISC_R_SUCCESS) {
6994		dns_zone_log(zone, ISC_LOG_ERROR,
6995			     "zone_sign:add_sigs -> %s\n",
6996			     dns_result_totext(result));
6997		goto failure;
6998	}
6999
7000	/*
7001	 * Write changes to journal file.
7002	 */
7003	CHECK(zone_journal(zone, &sig_diff, "zone_sign"));
7004
7005 pauseall:
7006	/*
7007	 * Pause all iterators so that dns_db_closeversion() can succeed.
7008	 */
7009	for (signing = ISC_LIST_HEAD(zone->signing);
7010	     signing != NULL;
7011	     signing = ISC_LIST_NEXT(signing, link))
7012		dns_dbiterator_pause(signing->dbiterator);
7013
7014	for (signing = ISC_LIST_HEAD(cleanup);
7015	     signing != NULL;
7016	     signing = ISC_LIST_NEXT(signing, link))
7017		dns_dbiterator_pause(signing->dbiterator);
7018
7019	/*
7020	 * Everything has succeeded. Commit the changes.
7021	 */
7022	dns_db_closeversion(db, &version, commit);
7023
7024	/*
7025	 * Everything succeeded so we can clean these up now.
7026	 */
7027	signing = ISC_LIST_HEAD(cleanup);
7028	while (signing != NULL) {
7029		ISC_LIST_UNLINK(cleanup, signing, link);
7030		dns_db_detach(&signing->db);
7031		dns_dbiterator_destroy(&signing->dbiterator);
7032		isc_mem_put(zone->mctx, signing, sizeof *signing);
7033		signing = ISC_LIST_HEAD(cleanup);
7034	}
7035
7036	set_resigntime(zone);
7037
7038	if (commit) {
7039		LOCK_ZONE(zone);
7040		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7041		zone_needdump(zone, DNS_DUMP_DELAY);
7042		UNLOCK_ZONE(zone);
7043	}
7044
7045 failure:
7046	/*
7047	 * Rollback the cleanup list.
7048	 */
7049	signing = ISC_LIST_HEAD(cleanup);
7050	while (signing != NULL) {
7051		ISC_LIST_UNLINK(cleanup, signing, link);
7052		ISC_LIST_PREPEND(zone->signing, signing, link);
7053		dns_dbiterator_first(signing->dbiterator);
7054		dns_dbiterator_pause(signing->dbiterator);
7055		signing = ISC_LIST_HEAD(cleanup);
7056	}
7057
7058	for (signing = ISC_LIST_HEAD(zone->signing);
7059	     signing != NULL;
7060	     signing = ISC_LIST_NEXT(signing, link))
7061		dns_dbiterator_pause(signing->dbiterator);
7062
7063	dns_diff_clear(&sig_diff);
7064
7065	for (i = 0; i < nkeys; i++)
7066		dst_key_free(&zone_keys[i]);
7067
7068	if (node != NULL)
7069		dns_db_detachnode(db, &node);
7070
7071	if (version != NULL) {
7072		dns_db_closeversion(db, &version, ISC_FALSE);
7073		dns_db_detach(&db);
7074	} else if (db != NULL)
7075		dns_db_detach(&db);
7076
7077	if (ISC_LIST_HEAD(zone->signing) != NULL) {
7078		isc_interval_t i;
7079		if (zone->update_disabled || result != ISC_R_SUCCESS)
7080			isc_interval_set(&i, 60, 0);		/* 1 minute */
7081		else
7082			isc_interval_set(&i, 0, 10000000);	/* 10 ms */
7083		isc_time_nowplusinterval(&zone->signingtime, &i);
7084	} else
7085		isc_time_settoepoch(&zone->signingtime);
7086}
7087
7088static void
7089normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
7090	      unsigned char *data, int size) {
7091	dns_rdata_dnskey_t dnskey;
7092	dns_rdata_keydata_t keydata;
7093	isc_buffer_t buf;
7094
7095	dns_rdata_reset(target);
7096	isc_buffer_init(&buf, data, size);
7097
7098	switch (rr->type) {
7099	    case dns_rdatatype_dnskey:
7100		dns_rdata_tostruct(rr, &dnskey, NULL);
7101		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
7102		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7103				     &dnskey, &buf);
7104		break;
7105	    case dns_rdatatype_keydata:
7106		dns_rdata_tostruct(rr, &keydata, NULL);
7107		dns_keydata_todnskey(&keydata, &dnskey, NULL);
7108		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7109				     &dnskey, &buf);
7110		break;
7111	    default:
7112		INSIST(0);
7113	}
7114}
7115
7116/*
7117 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
7118 * a KEYDATA rdataset from the key zone.
7119 *
7120 * 'rr' contains either a DNSKEY record, or a KEYDATA record
7121 *
7122 * After normalizing keys to the same format (DNSKEY, with revoke bit
7123 * cleared), return ISC_TRUE if a key that matches 'rr' is found in
7124 * 'rdset', or ISC_FALSE if not.
7125 */
7126
7127static isc_boolean_t
7128matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
7129	unsigned char data1[4096], data2[4096];
7130	dns_rdata_t rdata, rdata1, rdata2;
7131	isc_result_t result;
7132
7133	dns_rdata_init(&rdata);
7134	dns_rdata_init(&rdata1);
7135	dns_rdata_init(&rdata2);
7136
7137	normalize_key(rr, &rdata1, data1, sizeof(data1));
7138
7139	for (result = dns_rdataset_first(rdset);
7140	     result == ISC_R_SUCCESS;
7141	     result = dns_rdataset_next(rdset)) {
7142		dns_rdata_reset(&rdata);
7143		dns_rdataset_current(rdset, &rdata);
7144		normalize_key(&rdata, &rdata2, data2, sizeof(data2));
7145		if (dns_rdata_compare(&rdata1, &rdata2) == 0)
7146			return (ISC_TRUE);
7147	}
7148
7149	return (ISC_FALSE);
7150}
7151
7152/*
7153 * Calculate the refresh interval for a keydata zone, per
7154 * RFC5011: MAX(1 hr,
7155 *		MIN(15 days,
7156 *		    1/2 * OrigTTL,
7157 *		    1/2 * RRSigExpirationInterval))
7158 * or for retries: MAX(1 hr,
7159 *		       MIN(1 day,
7160 *			   1/10 * OrigTTL,
7161 *			   1/10 * RRSigExpirationInterval))
7162 */
7163static inline isc_stdtime_t
7164refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
7165	isc_result_t result;
7166	isc_uint32_t t;
7167	dns_rdataset_t *rdset;
7168	dns_rdata_t sigrr = DNS_RDATA_INIT;
7169	dns_rdata_sig_t sig;
7170	isc_stdtime_t now;
7171
7172	isc_stdtime_get(&now);
7173
7174	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7175		rdset = &kfetch->dnskeysigset;
7176	else
7177		return (now + HOUR);
7178
7179	result = dns_rdataset_first(rdset);
7180	if (result != ISC_R_SUCCESS)
7181		return (now + HOUR);
7182
7183	dns_rdataset_current(rdset, &sigrr);
7184	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7185	RUNTIME_CHECK(result == ISC_R_SUCCESS);
7186
7187	if (!retry) {
7188		t = sig.originalttl / 2;
7189
7190		if (isc_serial_gt(sig.timeexpire, now)) {
7191			isc_uint32_t exp = (sig.timeexpire - now) / 2;
7192			if (t > exp)
7193				t = exp;
7194		}
7195
7196		if (t > (15*DAY))
7197			t = (15*DAY);
7198
7199		if (t < HOUR)
7200			t = HOUR;
7201	} else {
7202		t = sig.originalttl / 10;
7203
7204		if (isc_serial_gt(sig.timeexpire, now)) {
7205			isc_uint32_t exp = (sig.timeexpire - now) / 10;
7206			if (t > exp)
7207				t = exp;
7208		}
7209
7210		if (t > DAY)
7211			t = DAY;
7212
7213		if (t < HOUR)
7214			t = HOUR;
7215	}
7216
7217	return (now + t);
7218}
7219
7220/*
7221 * This routine is called when no changes are needed in a KEYDATA
7222 * record except to simply update the refresh timer.  Caller should
7223 * hold zone lock.
7224 */
7225static isc_result_t
7226minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
7227{
7228	isc_result_t result;
7229	isc_buffer_t keyb;
7230	unsigned char key_buf[4096];
7231	dns_rdata_t rdata = DNS_RDATA_INIT;
7232	dns_rdata_keydata_t keydata;
7233	dns_name_t *name;
7234	dns_zone_t *zone = kfetch->zone;
7235	isc_stdtime_t now;
7236
7237	name = dns_fixedname_name(&kfetch->name);
7238	isc_stdtime_get(&now);
7239
7240	for (result = dns_rdataset_first(&kfetch->keydataset);
7241	     result == ISC_R_SUCCESS;
7242	     result = dns_rdataset_next(&kfetch->keydataset)) {
7243		dns_rdata_reset(&rdata);
7244		dns_rdataset_current(&kfetch->keydataset, &rdata);
7245
7246		/* Delete old version */
7247		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
7248				    name, 0, &rdata));
7249
7250		/* Update refresh timer */
7251		CHECK(dns_rdata_tostruct(&rdata, &keydata, NULL));
7252		keydata.refresh = refresh_time(kfetch, ISC_TRUE);
7253		set_refreshkeytimer(zone, &keydata, now);
7254
7255		dns_rdata_reset(&rdata);
7256		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7257		CHECK(dns_rdata_fromstruct(&rdata,
7258					   zone->rdclass, dns_rdatatype_keydata,
7259					   &keydata, &keyb));
7260
7261		/* Insert updated version */
7262		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
7263				    name, 0, &rdata));
7264	}
7265	result = ISC_R_SUCCESS;
7266  failure:
7267	return (result);
7268}
7269
7270/*
7271 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
7272 */
7273static isc_boolean_t
7274revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
7275	isc_result_t result;
7276	dns_name_t *keyname;
7277	isc_mem_t *mctx;
7278	dns_rdata_t sigrr = DNS_RDATA_INIT;
7279	dns_rdata_t rr = DNS_RDATA_INIT;
7280	dns_rdata_rrsig_t sig;
7281	dns_rdata_dnskey_t dnskey;
7282	dst_key_t *dstkey = NULL;
7283	unsigned char key_buf[4096];
7284	isc_buffer_t keyb;
7285	isc_boolean_t answer = ISC_FALSE;
7286
7287	REQUIRE(kfetch != NULL && keydata != NULL);
7288	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
7289
7290	keyname = dns_fixedname_name(&kfetch->name);
7291	mctx = kfetch->zone->view->mctx;
7292
7293	/* Generate a key from keydata */
7294	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7295	dns_keydata_todnskey(keydata, &dnskey, NULL);
7296	dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
7297				     &dnskey, &keyb);
7298	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
7299	if (result != ISC_R_SUCCESS)
7300		return (ISC_FALSE);
7301
7302	/* See if that key generated any of the signatures */
7303	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7304	     result == ISC_R_SUCCESS;
7305	     result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7306		dns_fixedname_t fixed;
7307		dns_fixedname_init(&fixed);
7308
7309		dns_rdata_reset(&sigrr);
7310		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7311		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7312		RUNTIME_CHECK(result == ISC_R_SUCCESS);
7313
7314		if (dst_key_alg(dstkey) == sig.algorithm &&
7315		    (dst_key_id(dstkey) == sig.keyid ||
7316		     dst_key_rid(dstkey) == sig.keyid)) {
7317			result = dns_dnssec_verify2(keyname,
7318					    &kfetch->dnskeyset,
7319					    dstkey, ISC_FALSE, mctx, &sigrr,
7320					    dns_fixedname_name(&fixed));
7321
7322			dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
7323				     "Confirm revoked DNSKEY is self-signed: "
7324				     "%s", dns_result_totext(result));
7325
7326			if (result == ISC_R_SUCCESS) {
7327				answer = ISC_TRUE;
7328				break;
7329			}
7330		}
7331	}
7332
7333	dst_key_free(&dstkey);
7334	return (answer);
7335}
7336
7337/*
7338 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
7339 * anchors are being managed; scan the keyset, and update the key zone and the
7340 * local trust anchors according to RFC5011.
7341 */
7342static void
7343keyfetch_done(isc_task_t *task, isc_event_t *event) {
7344	isc_result_t result, eresult;
7345	dns_fetchevent_t *devent;
7346	dns_keyfetch_t *kfetch;
7347	dns_zone_t *zone;
7348	isc_mem_t *mctx = NULL;
7349	dns_keytable_t *secroots = NULL;
7350	dns_dbversion_t *ver = NULL;
7351	dns_diff_t diff;
7352	isc_boolean_t alldone = ISC_FALSE;
7353	isc_boolean_t commit = ISC_FALSE;
7354	dns_name_t *keyname;
7355	dns_rdata_t sigrr = DNS_RDATA_INIT;
7356	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
7357	dns_rdata_t keydatarr = DNS_RDATA_INIT;
7358	dns_rdata_rrsig_t sig;
7359	dns_rdata_dnskey_t dnskey;
7360	dns_rdata_keydata_t keydata;
7361	isc_boolean_t initializing;
7362	char namebuf[DNS_NAME_FORMATSIZE];
7363	unsigned char key_buf[4096];
7364	isc_buffer_t keyb;
7365	dst_key_t *dstkey;
7366	isc_stdtime_t now;
7367	int pending = 0;
7368	isc_boolean_t secure;
7369	isc_boolean_t free_needed;
7370
7371	UNUSED(task);
7372	INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
7373	INSIST(event->ev_arg != NULL);
7374
7375	kfetch = event->ev_arg;
7376	zone = kfetch->zone;
7377	isc_mem_attach(zone->mctx, &mctx);
7378	keyname = dns_fixedname_name(&kfetch->name);
7379
7380	devent = (dns_fetchevent_t *) event;
7381	eresult = devent->result;
7382
7383	/* Free resources which are not of interest */
7384	if (devent->node != NULL)
7385		dns_db_detachnode(devent->db, &devent->node);
7386	if (devent->db != NULL)
7387		dns_db_detach(&devent->db);
7388	isc_event_free(&event);
7389	dns_resolver_destroyfetch(&kfetch->fetch);
7390
7391	LOCK_ZONE(zone);
7392	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
7393		goto cleanup;
7394
7395	isc_stdtime_get(&now);
7396	dns_name_format(keyname, namebuf, sizeof(namebuf));
7397
7398	result = dns_view_getsecroots(zone->view, &secroots);
7399	INSIST(result == ISC_R_SUCCESS);
7400
7401	dns_diff_init(mctx, &diff);
7402	diff.resign = zone->sigresigninginterval;
7403
7404	CHECK(dns_db_newversion(kfetch->db, &ver));
7405
7406	zone->refreshkeycount--;
7407	alldone = ISC_TF(zone->refreshkeycount == 0);
7408
7409	if (alldone)
7410		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
7411
7412	/* Fetch failed */
7413	if (eresult != ISC_R_SUCCESS ||
7414	    !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
7415		dns_zone_log(zone, ISC_LOG_WARNING,
7416			     "Unable to fetch DNSKEY set "
7417			     "'%s': %s", namebuf, dns_result_totext(eresult));
7418		CHECK(minimal_update(kfetch, ver, &diff));
7419		goto done;
7420	}
7421
7422	/* No RRSIGs found */
7423	if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
7424		dns_zone_log(zone, ISC_LOG_WARNING,
7425			     "No DNSKEY RRSIGs found for "
7426			     "'%s': %s", namebuf, dns_result_totext(eresult));
7427		CHECK(minimal_update(kfetch, ver, &diff));
7428		goto done;
7429	}
7430
7431	/*
7432	 * Validate the dnskeyset against the current trusted keys.
7433	 */
7434	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7435	     result == ISC_R_SUCCESS;
7436	     result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7437		dns_keynode_t *keynode = NULL;
7438
7439		dns_rdata_reset(&sigrr);
7440		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7441		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7442		RUNTIME_CHECK(result == ISC_R_SUCCESS);
7443
7444		result = dns_keytable_find(secroots, keyname, &keynode);
7445		while (result == ISC_R_SUCCESS) {
7446			dns_keynode_t *nextnode = NULL;
7447			dns_fixedname_t fixed;
7448			dns_fixedname_init(&fixed);
7449
7450			dstkey = dns_keynode_key(keynode);
7451			if (dstkey == NULL) /* fail_secure() was called */
7452				break;
7453
7454			if (dst_key_alg(dstkey) == sig.algorithm &&
7455			    dst_key_id(dstkey) == sig.keyid) {
7456				result = dns_dnssec_verify2(keyname,
7457						    &kfetch->dnskeyset,
7458						    dstkey, ISC_FALSE,
7459						    zone->view->mctx, &sigrr,
7460						    dns_fixedname_name(&fixed));
7461
7462				dns_zone_log(zone, ISC_LOG_DEBUG(3),
7463					     "Verifying DNSKEY set for zone "
7464					     "'%s': %s", namebuf,
7465					     dns_result_totext(result));
7466
7467				if (result == ISC_R_SUCCESS) {
7468					kfetch->dnskeyset.trust =
7469						dns_trust_secure;
7470					kfetch->dnskeysigset.trust =
7471						dns_trust_secure;
7472					dns_keytable_detachkeynode(secroots,
7473								   &keynode);
7474					break;
7475				}
7476			}
7477
7478			result = dns_keytable_nextkeynode(secroots,
7479							  keynode, &nextnode);
7480			dns_keytable_detachkeynode(secroots, &keynode);
7481			keynode = nextnode;
7482		}
7483
7484		if (kfetch->dnskeyset.trust == dns_trust_secure)
7485			break;
7486	}
7487
7488	/*
7489	 * If we were not able to verify the answer using the current
7490	 * trusted keys then all we can do is look at any revoked keys.
7491	 */
7492	secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
7493
7494	/*
7495	 * First scan keydataset to find keys that are not in dnskeyset
7496	 *   - Missing keys which are not scheduled for removal,
7497	 *     log a warning
7498	 *   - Missing keys which are scheduled for removal and
7499	 *     the remove hold-down timer has completed should
7500	 *     be removed from the key zone
7501	 *   - Missing keys whose acceptance timers have not yet
7502	 *     completed, log a warning and reset the acceptance
7503	 *     timer to 30 days in the future
7504	 *   - All keys not being removed have their refresh timers
7505	 *     updated
7506	 */
7507	initializing = ISC_TRUE;
7508	for (result = dns_rdataset_first(&kfetch->keydataset);
7509	     result == ISC_R_SUCCESS;
7510	     result = dns_rdataset_next(&kfetch->keydataset)) {
7511		dns_rdata_reset(&keydatarr);
7512		dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7513		dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7514
7515		/*
7516		 * If any keydata record has a nonzero add holddown, then
7517		 * there was a pre-existing trust anchor for this domain;
7518		 * that means we are *not* initializing it and shouldn't
7519		 * automatically trust all the keys we find at the zone apex.
7520		 */
7521		initializing = initializing && ISC_TF(keydata.addhd == 0);
7522
7523		if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
7524			isc_boolean_t deletekey = ISC_FALSE;
7525
7526			if (!secure) {
7527				if (now > keydata.removehd)
7528					deletekey = ISC_TRUE;
7529			} else if (now < keydata.addhd) {
7530				dns_zone_log(zone, ISC_LOG_WARNING,
7531					     "Pending key unexpectedly missing "
7532					     "from %s; restarting acceptance "
7533					     "timer", namebuf);
7534				keydata.addhd = now + MONTH;
7535				keydata.refresh = refresh_time(kfetch,
7536							       ISC_FALSE);
7537			} else if (keydata.addhd == 0) {
7538				keydata.addhd = now;
7539			} else if (keydata.removehd == 0) {
7540				dns_zone_log(zone, ISC_LOG_WARNING,
7541					     "Active key unexpectedly missing "
7542					     "from %s", namebuf);
7543				keydata.refresh = now + HOUR;
7544			} else if (now > keydata.removehd) {
7545				deletekey = ISC_TRUE;
7546			} else {
7547				keydata.refresh = refresh_time(kfetch,
7548							       ISC_FALSE);
7549			}
7550
7551			if  (secure || deletekey) {
7552				/* Delete old version */
7553				CHECK(update_one_rr(kfetch->db, ver, &diff,
7554						    DNS_DIFFOP_DEL, keyname, 0,
7555						    &keydatarr));
7556			}
7557
7558			if (!secure || deletekey)
7559				continue;
7560
7561			dns_rdata_reset(&keydatarr);
7562			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7563			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7564					     dns_rdatatype_keydata,
7565					     &keydata, &keyb);
7566
7567			/* Insert updated version */
7568			CHECK(update_one_rr(kfetch->db, ver, &diff,
7569					    DNS_DIFFOP_ADD, keyname, 0,
7570					    &keydatarr));
7571
7572			set_refreshkeytimer(zone, &keydata, now);
7573		}
7574	}
7575
7576	/*
7577	 * Next scan dnskeyset:
7578	 *   - If new keys are found (i.e., lacking a match in keydataset)
7579	 *     add them to the key zone and set the acceptance timer
7580	 *     to 30 days in the future (or to immediately if we've
7581	 *     determined that we're initializing the zone for the
7582	 *     first time)
7583	 *   - Previously-known keys that have been revoked
7584	 *     must be scheduled for removal from the key zone (or,
7585	 *     if they hadn't been accepted as trust anchors yet
7586	 *     anyway, removed at once)
7587	 *   - Previously-known unrevoked keys whose acceptance timers
7588	 *     have completed are promoted to trust anchors
7589	 *   - All keys not being removed have their refresh
7590	 *     timers updated
7591	 */
7592	for (result = dns_rdataset_first(&kfetch->dnskeyset);
7593	     result == ISC_R_SUCCESS;
7594	     result = dns_rdataset_next(&kfetch->dnskeyset)) {
7595		isc_boolean_t revoked = ISC_FALSE;
7596		isc_boolean_t newkey = ISC_FALSE;
7597		isc_boolean_t updatekey = ISC_FALSE;
7598		isc_boolean_t deletekey = ISC_FALSE;
7599		isc_boolean_t trustkey = ISC_FALSE;
7600
7601		dns_rdata_reset(&dnskeyrr);
7602		dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
7603		dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7604
7605		/* Skip ZSK's */
7606		if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
7607			continue;
7608
7609		revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
7610
7611		if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
7612			dns_rdata_reset(&keydatarr);
7613			dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7614			dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7615
7616			if (revoked && revocable(kfetch, &keydata)) {
7617				if (keydata.addhd > now) {
7618					/*
7619					 * Key wasn't trusted yet, and now
7620					 * it's been revoked?  Just remove it
7621					 */
7622					deletekey = ISC_TRUE;
7623				} else if (keydata.removehd == 0) {
7624					/* Remove from secroots */
7625					dns_view_untrust(zone->view, keyname,
7626							 &dnskey, mctx);
7627
7628					/* If initializing, delete now */
7629					if (keydata.addhd == 0)
7630						deletekey = ISC_TRUE;
7631					else
7632						keydata.removehd = now + MONTH;
7633				} else if (keydata.removehd < now) {
7634					/* Scheduled for removal */
7635					deletekey = ISC_TRUE;
7636				}
7637			} else if (revoked) {
7638				if (secure && keydata.removehd == 0) {
7639					dns_zone_log(zone, ISC_LOG_WARNING,
7640						     "Active key for zone "
7641						     "'%s' is revoked but "
7642						     "did not self-sign; "
7643							 "ignoring.", namebuf);
7644						continue;
7645				}
7646			} else if (secure) {
7647				if (keydata.removehd != 0) {
7648					/*
7649					 * Key isn't revoked--but it
7650					 * seems it used to be.
7651					 * Remove it now and add it
7652					 * back as if it were a fresh key.
7653					 */
7654					deletekey = ISC_TRUE;
7655					newkey = ISC_TRUE;
7656				} else if (keydata.addhd > now)
7657					pending++;
7658				else if (keydata.addhd == 0)
7659					keydata.addhd = now;
7660
7661				if (keydata.addhd <= now)
7662					trustkey = ISC_TRUE;
7663			}
7664
7665			if (!deletekey && !newkey)
7666				updatekey = ISC_TRUE;
7667		} else if (secure) {
7668			/*
7669			 * Key wasn't in the key zone but it's
7670			 * revoked now anyway, so just skip it
7671			 */
7672			if (revoked)
7673				continue;
7674
7675			/* Key wasn't in the key zone: add it */
7676			newkey = ISC_TRUE;
7677
7678			if (initializing) {
7679				dns_keytag_t tag = 0;
7680				CHECK(compute_tag(keyname, &dnskey,
7681						  mctx, &tag));
7682				dns_zone_log(zone, ISC_LOG_WARNING,
7683					     "Initializing automatic trust "
7684					     "anchor management for zone '%s'; "
7685					     "DNSKEY ID %d is now trusted, "
7686					     "waiving the normal 30-day "
7687					     "waiting period.",
7688					     namebuf, tag);
7689				trustkey = ISC_TRUE;
7690			}
7691		}
7692
7693		/* Delete old version */
7694		if (deletekey || !newkey)
7695			CHECK(update_one_rr(kfetch->db, ver, &diff,
7696					    DNS_DIFFOP_DEL, keyname, 0,
7697					    &keydatarr));
7698
7699		if (updatekey) {
7700			/* Set refresh timer */
7701			keydata.refresh = refresh_time(kfetch, ISC_FALSE);
7702			dns_rdata_reset(&keydatarr);
7703			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7704			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7705					     dns_rdatatype_keydata,
7706					     &keydata, &keyb);
7707
7708			/* Insert updated version */
7709			CHECK(update_one_rr(kfetch->db, ver, &diff,
7710					    DNS_DIFFOP_ADD, keyname, 0,
7711					    &keydatarr));
7712		} else if (newkey) {
7713			/* Convert DNSKEY to KEYDATA */
7714			dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7715			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
7716					       NULL);
7717			keydata.addhd = initializing ? now : now + MONTH;
7718			keydata.refresh = refresh_time(kfetch, ISC_FALSE);
7719			dns_rdata_reset(&keydatarr);
7720			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7721			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7722					     dns_rdatatype_keydata,
7723					     &keydata, &keyb);
7724
7725			/* Insert into key zone */
7726			CHECK(update_one_rr(kfetch->db, ver, &diff,
7727					    DNS_DIFFOP_ADD, keyname, 0,
7728					    &keydatarr));
7729		}
7730
7731		if (trustkey) {
7732			/* Trust this key. */
7733			dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7734			trust_key(zone, keyname, &dnskey, mctx);
7735		}
7736
7737		if (!deletekey)
7738			set_refreshkeytimer(zone, &keydata, now);
7739	}
7740
7741	/*
7742	 * RFC5011 says, "A trust point that has all of its trust anchors
7743	 * revoked is considered deleted and is treated as if the trust
7744	 * point was never configured."  But if someone revoked their
7745	 * active key before the standby was trusted, that would mean the
7746	 * zone would suddenly be nonsecured.  We avoid this by checking to
7747	 * see if there's pending keydata.  If so, we put a null key in
7748	 * the security roots; then all queries to the zone will fail.
7749	 */
7750	if (pending != 0)
7751		fail_secure(zone, keyname);
7752
7753 done:
7754
7755	if (!ISC_LIST_EMPTY(diff.tuples)) {
7756		/* Write changes to journal file. */
7757		CHECK(increment_soa_serial(kfetch->db, ver, &diff, mctx));
7758		CHECK(zone_journal(zone, &diff, "keyfetch_done"));
7759		commit = ISC_TRUE;
7760
7761		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
7762		zone_needdump(zone, 30);
7763	}
7764
7765  failure:
7766
7767	dns_diff_clear(&diff);
7768	if (ver != NULL)
7769		dns_db_closeversion(kfetch->db, &ver, commit);
7770
7771 cleanup:
7772	dns_db_detach(&kfetch->db);
7773
7774	INSIST(zone->irefs > 0);
7775	zone->irefs--;
7776	kfetch->zone = NULL;
7777
7778	if (dns_rdataset_isassociated(&kfetch->keydataset))
7779		dns_rdataset_disassociate(&kfetch->keydataset);
7780	if (dns_rdataset_isassociated(&kfetch->dnskeyset))
7781		dns_rdataset_disassociate(&kfetch->dnskeyset);
7782	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7783		dns_rdataset_disassociate(&kfetch->dnskeysigset);
7784
7785	dns_name_free(keyname, mctx);
7786	isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
7787	isc_mem_detach(&mctx);
7788
7789	if (secroots != NULL)
7790		dns_keytable_detach(&secroots);
7791
7792	free_needed = exit_check(zone);
7793	UNLOCK_ZONE(zone);
7794	if (free_needed)
7795		zone_free(zone);
7796}
7797
7798/*
7799 * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
7800 * records from the zone apex.
7801 */
7802static void
7803zone_refreshkeys(dns_zone_t *zone) {
7804	const char me[] = "zone_refreshkeys";
7805	isc_result_t result;
7806	dns_rriterator_t rrit;
7807	dns_db_t *db = NULL;
7808	dns_dbversion_t *ver = NULL;
7809	dns_diff_t diff;
7810	dns_rdata_t rdata = DNS_RDATA_INIT;
7811	dns_rdata_keydata_t kd;
7812	isc_stdtime_t now;
7813	isc_boolean_t commit = ISC_FALSE;
7814	isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
7815
7816	ENTER;
7817	REQUIRE(zone->db != NULL);
7818
7819	isc_stdtime_get(&now);
7820
7821	LOCK_ZONE(zone);
7822	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
7823		isc_time_settoepoch(&zone->refreshkeytime);
7824		UNLOCK_ZONE(zone);
7825		return;
7826	}
7827
7828	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7829	dns_db_attach(zone->db, &db);
7830	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7831
7832	dns_diff_init(zone->mctx, &diff);
7833
7834	CHECK(dns_db_newversion(db, &ver));
7835
7836	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
7837
7838	dns_rriterator_init(&rrit, db, ver, 0);
7839	for (result = dns_rriterator_first(&rrit);
7840	     result == ISC_R_SUCCESS;
7841	     result = dns_rriterator_nextrrset(&rrit)) {
7842		isc_stdtime_t timer = 0xffffffff;
7843		dns_name_t *name = NULL, *kname = NULL;
7844		dns_rdataset_t *kdset = NULL;
7845		dns_keyfetch_t *kfetch;
7846		isc_uint32_t ttl;
7847
7848		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
7849		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
7850		    !dns_rdataset_isassociated(kdset))
7851			continue;
7852
7853		/*
7854		 * Scan the stored keys looking for ones that need
7855		 * removal or refreshing
7856		 */
7857		for (result = dns_rdataset_first(kdset);
7858		     result == ISC_R_SUCCESS;
7859		     result = dns_rdataset_next(kdset)) {
7860			dns_rdata_reset(&rdata);
7861			dns_rdataset_current(kdset, &rdata);
7862			result = dns_rdata_tostruct(&rdata, &kd, NULL);
7863			RUNTIME_CHECK(result == ISC_R_SUCCESS);
7864
7865			/* Removal timer expired? */
7866			if (kd.removehd != 0 && kd.removehd < now) {
7867				CHECK(update_one_rr(db, ver, &diff,
7868						    DNS_DIFFOP_DEL, name, ttl,
7869						    &rdata));
7870				continue;
7871			}
7872
7873			/* Acceptance timer expired? */
7874			if (kd.addhd != 0 && kd.addhd < now)
7875				timer = kd.addhd;
7876
7877			/* Or do we just need to refresh the keyset? */
7878			if (timer > kd.refresh)
7879				timer = kd.refresh;
7880		}
7881
7882		if (timer > now)
7883			continue;
7884
7885		kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
7886		if (kfetch == NULL) {
7887			fetch_err = ISC_TRUE;
7888			goto failure;
7889		}
7890
7891		zone->refreshkeycount++;
7892		kfetch->zone = zone;
7893		zone->irefs++;
7894		INSIST(zone->irefs != 0);
7895		dns_fixedname_init(&kfetch->name);
7896		kname = dns_fixedname_name(&kfetch->name);
7897		dns_name_dup(name, zone->mctx, kname);
7898		dns_rdataset_init(&kfetch->dnskeyset);
7899		dns_rdataset_init(&kfetch->dnskeysigset);
7900		dns_rdataset_init(&kfetch->keydataset);
7901		dns_rdataset_clone(kdset, &kfetch->keydataset);
7902		kfetch->db = NULL;
7903		dns_db_attach(db, &kfetch->db);
7904		kfetch->fetch = NULL;
7905
7906		result = dns_resolver_createfetch(zone->view->resolver,
7907						  kname, dns_rdatatype_dnskey,
7908						  NULL, NULL, NULL,
7909						  DNS_FETCHOPT_NOVALIDATE,
7910						  zone->task,
7911						  keyfetch_done, kfetch,
7912						  &kfetch->dnskeyset,
7913						  &kfetch->dnskeysigset,
7914						  &kfetch->fetch);
7915		if (result == ISC_R_SUCCESS)
7916			fetching = ISC_TRUE;
7917		else {
7918			zone->refreshkeycount--;
7919			zone->irefs--;
7920			dns_db_detach(&kfetch->db);
7921			dns_rdataset_disassociate(&kfetch->keydataset);
7922			dns_name_free(kname, zone->mctx);
7923			isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
7924			dns_zone_log(zone, ISC_LOG_WARNING,
7925				     "Failed to create fetch for "
7926				     "DNSKEY update");
7927			fetch_err = ISC_TRUE;
7928		}
7929	}
7930	if (!ISC_LIST_EMPTY(diff.tuples)) {
7931		CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
7932		CHECK(zone_journal(zone, &diff, "zone_refreshkeys"));
7933		commit = ISC_TRUE;
7934		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
7935		zone_needdump(zone, 30);
7936	}
7937
7938  failure:
7939	if (fetch_err) {
7940		/*
7941		 * Error during a key fetch; retry in an hour.
7942		 */
7943		isc_time_t timenow, timethen;
7944		char timebuf[80];
7945
7946		TIME_NOW(&timenow);
7947		DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
7948		zone->refreshkeytime = timethen;
7949		zone_settimer(zone, &timenow);
7950
7951		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
7952		dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
7953			     timebuf);
7954
7955		if (!fetching)
7956			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
7957	}
7958
7959	UNLOCK_ZONE(zone);
7960
7961	dns_diff_clear(&diff);
7962	if (ver != NULL) {
7963		dns_rriterator_destroy(&rrit);
7964		dns_db_closeversion(db, &ver, commit);
7965	}
7966	dns_db_detach(&db);
7967}
7968
7969static void
7970zone_maintenance(dns_zone_t *zone) {
7971	const char me[] = "zone_maintenance";
7972	isc_time_t now;
7973	isc_result_t result;
7974	isc_boolean_t dumping;
7975
7976	REQUIRE(DNS_ZONE_VALID(zone));
7977	ENTER;
7978
7979	/*
7980	 * Configuring the view of this zone may have
7981	 * failed, for example because the config file
7982	 * had a syntax error.	In that case, the view
7983	 * db or resolver will be NULL, and we had better not try
7984	 * to do maintenance on it.
7985	 */
7986	if (zone->view == NULL || zone->view->adb == NULL)
7987		return;
7988
7989	TIME_NOW(&now);
7990
7991	/*
7992	 * Expire check.
7993	 */
7994	switch (zone->type) {
7995	case dns_zone_slave:
7996	case dns_zone_stub:
7997		LOCK_ZONE(zone);
7998		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
7999		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8000			zone_expire(zone);
8001			zone->refreshtime = now;
8002		}
8003		UNLOCK_ZONE(zone);
8004		break;
8005	default:
8006		break;
8007	}
8008
8009	/*
8010	 * Up to date check.
8011	 */
8012	switch (zone->type) {
8013	case dns_zone_slave:
8014	case dns_zone_stub:
8015		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8016		    isc_time_compare(&now, &zone->refreshtime) >= 0)
8017			dns_zone_refresh(zone);
8018		break;
8019	default:
8020		break;
8021	}
8022
8023	/*
8024	 * Do we need to consolidate the backing store?
8025	 */
8026	switch (zone->type) {
8027	case dns_zone_master:
8028	case dns_zone_slave:
8029	case dns_zone_key:
8030		LOCK_ZONE(zone);
8031		if (zone->masterfile != NULL &&
8032		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
8033		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8034		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
8035			dumping = was_dumping(zone);
8036		} else
8037			dumping = ISC_TRUE;
8038		UNLOCK_ZONE(zone);
8039		if (!dumping) {
8040			result = zone_dump(zone, ISC_TRUE); /* task locked */
8041			if (result != ISC_R_SUCCESS)
8042				dns_zone_log(zone, ISC_LOG_WARNING,
8043					     "dump failed: %s",
8044					     dns_result_totext(result));
8045		}
8046		break;
8047	default:
8048		break;
8049	}
8050
8051	/*
8052	 * Do we need to refresh keys?
8053	 */
8054	switch (zone->type) {
8055	case dns_zone_key:
8056		if (isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
8057		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8058		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
8059			zone_refreshkeys(zone);
8060		break;
8061	case dns_zone_master:
8062		if (!isc_time_isepoch(&zone->refreshkeytime) &&
8063		    isc_time_compare(&now, &zone->refreshkeytime) >= 0)
8064			zone_rekey(zone);
8065	default:
8066		break;
8067	}
8068
8069	switch (zone->type) {
8070	case dns_zone_master:
8071	case dns_zone_slave:
8072		/*
8073		 * Do we need to send out notify messages?
8074		 */
8075		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8076		    isc_time_compare(&now, &zone->notifytime) >= 0)
8077			zone_notify(zone, &now);
8078		/*
8079		 * Do we need to sign/resign some RRsets?
8080		 */
8081		if (!isc_time_isepoch(&zone->signingtime) &&
8082		    isc_time_compare(&now, &zone->signingtime) >= 0)
8083			zone_sign(zone);
8084		else if (!isc_time_isepoch(&zone->resigntime) &&
8085		    isc_time_compare(&now, &zone->resigntime) >= 0)
8086			zone_resigninc(zone);
8087		else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
8088			isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
8089			zone_nsec3chain(zone);
8090		/*
8091		 * Do we need to issue a key expiry warning.
8092		 */
8093		if (!isc_time_isepoch(&zone->keywarntime) &&
8094		    isc_time_compare(&now, &zone->keywarntime) >= 0)
8095			set_key_expiry_warning(zone, zone->key_expiry,
8096					       isc_time_seconds(&now));
8097		break;
8098	default:
8099		break;
8100	}
8101	zone_settimer(zone, &now);
8102}
8103
8104void
8105dns_zone_markdirty(dns_zone_t *zone) {
8106
8107	LOCK_ZONE(zone);
8108	if (zone->type == dns_zone_master)
8109		set_resigntime(zone);	/* XXXMPA make separate call back */
8110	zone_needdump(zone, DNS_DUMP_DELAY);
8111	UNLOCK_ZONE(zone);
8112}
8113
8114void
8115dns_zone_expire(dns_zone_t *zone) {
8116	REQUIRE(DNS_ZONE_VALID(zone));
8117
8118	LOCK_ZONE(zone);
8119	zone_expire(zone);
8120	UNLOCK_ZONE(zone);
8121}
8122
8123static void
8124zone_expire(dns_zone_t *zone) {
8125	/*
8126	 * 'zone' locked by caller.
8127	 */
8128
8129	REQUIRE(LOCKED_ZONE(zone));
8130
8131	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
8132
8133	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
8134	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
8135	zone->retry = DNS_ZONE_DEFAULTRETRY;
8136	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
8137	zone_unload(zone);
8138}
8139
8140void
8141dns_zone_refresh(dns_zone_t *zone) {
8142	isc_interval_t i;
8143	isc_uint32_t oldflags;
8144	unsigned int j;
8145	isc_result_t result;
8146
8147	REQUIRE(DNS_ZONE_VALID(zone));
8148
8149	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
8150		return;
8151
8152	/*
8153	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
8154	 * in progress at a time.
8155	 */
8156
8157	LOCK_ZONE(zone);
8158	oldflags = zone->flags;
8159	if (zone->masterscnt == 0) {
8160		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
8161		if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
8162			dns_zone_log(zone, ISC_LOG_ERROR,
8163				     "cannot refresh: no masters");
8164		goto unlock;
8165	}
8166	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
8167	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
8168	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
8169	if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
8170		goto unlock;
8171
8172	/*
8173	 * Set the next refresh time as if refresh check has failed.
8174	 * Setting this to the retry time will do that.  XXXMLG
8175	 * If we are successful it will be reset using zone->refresh.
8176	 */
8177	isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
8178			 0);
8179	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
8180	if (result != ISC_R_SUCCESS)
8181		dns_zone_log(zone, ISC_LOG_WARNING,
8182			     "isc_time_nowplusinterval() failed: %s",
8183			     dns_result_totext(result));
8184
8185	/*
8186	 * When lacking user-specified timer values from the SOA,
8187	 * do exponential backoff of the retry time up to a
8188	 * maximum of six hours.
8189	 */
8190	if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
8191		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
8192
8193	zone->curmaster = 0;
8194	for (j = 0; j < zone->masterscnt; j++)
8195		zone->mastersok[j] = ISC_FALSE;
8196	/* initiate soa query */
8197	queue_soa_query(zone);
8198 unlock:
8199	UNLOCK_ZONE(zone);
8200}
8201
8202isc_result_t
8203dns_zone_flush(dns_zone_t *zone) {
8204	isc_result_t result = ISC_R_SUCCESS;
8205	isc_boolean_t dumping;
8206
8207	REQUIRE(DNS_ZONE_VALID(zone));
8208
8209	LOCK_ZONE(zone);
8210	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
8211	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8212	    zone->masterfile != NULL) {
8213		result = ISC_R_ALREADYRUNNING;
8214		dumping = was_dumping(zone);
8215	} else
8216		dumping = ISC_TRUE;
8217	UNLOCK_ZONE(zone);
8218	if (!dumping)
8219		result = zone_dump(zone, ISC_FALSE);	/* Unknown task. */
8220	return (result);
8221}
8222
8223isc_result_t
8224dns_zone_dump(dns_zone_t *zone) {
8225	isc_result_t result = ISC_R_ALREADYRUNNING;
8226	isc_boolean_t dumping;
8227
8228	REQUIRE(DNS_ZONE_VALID(zone));
8229
8230	LOCK_ZONE(zone);
8231	dumping = was_dumping(zone);
8232	UNLOCK_ZONE(zone);
8233	if (!dumping)
8234		result = zone_dump(zone, ISC_FALSE);	/* Unknown task. */
8235	return (result);
8236}
8237
8238static void
8239zone_needdump(dns_zone_t *zone, unsigned int delay) {
8240	isc_time_t dumptime;
8241	isc_time_t now;
8242
8243	/*
8244	 * 'zone' locked by caller
8245	 */
8246
8247	REQUIRE(DNS_ZONE_VALID(zone));
8248	REQUIRE(LOCKED_ZONE(zone));
8249
8250	/*
8251	 * Do we have a place to dump to and are we loaded?
8252	 */
8253	if (zone->masterfile == NULL ||
8254	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
8255		return;
8256
8257	TIME_NOW(&now);
8258	/* add some noise */
8259	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
8260
8261	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8262	if (isc_time_isepoch(&zone->dumptime) ||
8263	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
8264		zone->dumptime = dumptime;
8265	if (zone->task != NULL)
8266		zone_settimer(zone, &now);
8267}
8268
8269static void
8270dump_done(void *arg, isc_result_t result) {
8271	const char me[] = "dump_done";
8272	dns_zone_t *zone = arg;
8273	dns_db_t *db;
8274	dns_dbversion_t *version;
8275	isc_boolean_t again = ISC_FALSE;
8276	isc_boolean_t compact = ISC_FALSE;
8277	isc_uint32_t serial;
8278	isc_result_t tresult;
8279
8280	REQUIRE(DNS_ZONE_VALID(zone));
8281
8282	ENTER;
8283
8284	if (result == ISC_R_SUCCESS && zone->journal != NULL &&
8285	    zone->journalsize != -1) {
8286
8287		/*
8288		 * We don't own these, zone->dctx must stay valid.
8289		 */
8290		db = dns_dumpctx_db(zone->dctx);
8291		version = dns_dumpctx_version(zone->dctx);
8292
8293		tresult = dns_db_getsoaserial(db, version, &serial);
8294		/*
8295		 * Note: we are task locked here so we can test
8296		 * zone->xfr safely.
8297		 */
8298		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
8299			tresult = dns_journal_compact(zone->mctx,
8300						      zone->journal,
8301						      serial,
8302						      zone->journalsize);
8303			switch (tresult) {
8304			case ISC_R_SUCCESS:
8305			case ISC_R_NOSPACE:
8306			case ISC_R_NOTFOUND:
8307				dns_zone_log(zone, ISC_LOG_DEBUG(3),
8308					     "dns_journal_compact: %s",
8309					     dns_result_totext(tresult));
8310				break;
8311			default:
8312				dns_zone_log(zone, ISC_LOG_ERROR,
8313					     "dns_journal_compact failed: %s",
8314					     dns_result_totext(tresult));
8315				break;
8316			}
8317		} else if (tresult == ISC_R_SUCCESS) {
8318			compact = ISC_TRUE;
8319			zone->compact_serial = serial;
8320		}
8321	}
8322
8323	LOCK_ZONE(zone);
8324	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8325	if (compact)
8326		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
8327	if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
8328		/*
8329		 * Try again in a short while.
8330		 */
8331		zone_needdump(zone, DNS_DUMP_DELAY);
8332	} else if (result == ISC_R_SUCCESS &&
8333		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8334		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8335		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8336		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8337		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8338		isc_time_settoepoch(&zone->dumptime);
8339		again = ISC_TRUE;
8340	} else if (result == ISC_R_SUCCESS)
8341		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8342
8343	if (zone->dctx != NULL)
8344		dns_dumpctx_detach(&zone->dctx);
8345	zonemgr_putio(&zone->writeio);
8346	UNLOCK_ZONE(zone);
8347	if (again)
8348		(void)zone_dump(zone, ISC_FALSE);
8349	dns_zone_idetach(&zone);
8350}
8351
8352static isc_result_t
8353zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
8354	const char me[] = "zone_dump";
8355	isc_result_t result;
8356	dns_dbversion_t *version = NULL;
8357	isc_boolean_t again;
8358	dns_db_t *db = NULL;
8359	char *masterfile = NULL;
8360	dns_masterformat_t masterformat = dns_masterformat_none;
8361
8362/*
8363 * 'compact' MUST only be set if we are task locked.
8364 */
8365
8366	REQUIRE(DNS_ZONE_VALID(zone));
8367	ENTER;
8368
8369 redo:
8370	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8371	if (zone->db != NULL)
8372		dns_db_attach(zone->db, &db);
8373	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8374	LOCK_ZONE(zone);
8375	if (zone->masterfile != NULL) {
8376		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
8377		masterformat = zone->masterformat;
8378	}
8379	UNLOCK_ZONE(zone);
8380	if (db == NULL) {
8381		result = DNS_R_NOTLOADED;
8382		goto fail;
8383	}
8384	if (masterfile == NULL) {
8385		result = DNS_R_NOMASTERFILE;
8386		goto fail;
8387	}
8388
8389	if (compact) {
8390		dns_zone_t *dummy = NULL;
8391		LOCK_ZONE(zone);
8392		zone_iattach(zone, &dummy);
8393		result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
8394				       zone_gotwritehandle, zone,
8395				       &zone->writeio);
8396		if (result != ISC_R_SUCCESS)
8397			zone_idetach(&dummy);
8398		else
8399			result = DNS_R_CONTINUE;
8400		UNLOCK_ZONE(zone);
8401	} else {
8402		dns_db_currentversion(db, &version);
8403		result = dns_master_dump2(zone->mctx, db, version,
8404					  &dns_master_style_default,
8405					  masterfile, masterformat);
8406		dns_db_closeversion(db, &version, ISC_FALSE);
8407	}
8408 fail:
8409	if (db != NULL)
8410		dns_db_detach(&db);
8411	if (masterfile != NULL)
8412		isc_mem_free(zone->mctx, masterfile);
8413	masterfile = NULL;
8414
8415	if (result == DNS_R_CONTINUE)
8416		return (ISC_R_SUCCESS); /* XXXMPA */
8417
8418	again = ISC_FALSE;
8419	LOCK_ZONE(zone);
8420	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8421	if (result != ISC_R_SUCCESS) {
8422		/*
8423		 * Try again in a short while.
8424		 */
8425		zone_needdump(zone, DNS_DUMP_DELAY);
8426	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8427		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8428		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8429		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8430		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8431		isc_time_settoepoch(&zone->dumptime);
8432		again = ISC_TRUE;
8433	} else
8434		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8435	UNLOCK_ZONE(zone);
8436	if (again)
8437		goto redo;
8438
8439	return (result);
8440}
8441
8442static isc_result_t
8443dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
8444	     dns_masterformat_t format)
8445{
8446	isc_result_t result;
8447	dns_dbversion_t *version = NULL;
8448	dns_db_t *db = NULL;
8449
8450	REQUIRE(DNS_ZONE_VALID(zone));
8451
8452	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8453	if (zone->db != NULL)
8454		dns_db_attach(zone->db, &db);
8455	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8456	if (db == NULL)
8457		return (DNS_R_NOTLOADED);
8458
8459	dns_db_currentversion(db, &version);
8460	result = dns_master_dumptostream2(zone->mctx, db, version, style,
8461					  format, fd);
8462	dns_db_closeversion(db, &version, ISC_FALSE);
8463	dns_db_detach(&db);
8464	return (result);
8465}
8466
8467isc_result_t
8468dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
8469		       const dns_master_style_t *style) {
8470	return dumptostream(zone, fd, style, format);
8471}
8472
8473isc_result_t
8474dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
8475	return dumptostream(zone, fd, &dns_master_style_default,
8476			    dns_masterformat_text);
8477}
8478
8479isc_result_t
8480dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
8481	return dumptostream(zone, fd, &dns_master_style_full,
8482			    dns_masterformat_text);
8483}
8484
8485void
8486dns_zone_unload(dns_zone_t *zone) {
8487	REQUIRE(DNS_ZONE_VALID(zone));
8488
8489	LOCK_ZONE(zone);
8490	zone_unload(zone);
8491	UNLOCK_ZONE(zone);
8492}
8493
8494static void
8495notify_cancel(dns_zone_t *zone) {
8496	dns_notify_t *notify;
8497
8498	/*
8499	 * 'zone' locked by caller.
8500	 */
8501
8502	REQUIRE(LOCKED_ZONE(zone));
8503
8504	for (notify = ISC_LIST_HEAD(zone->notifies);
8505	     notify != NULL;
8506	     notify = ISC_LIST_NEXT(notify, link)) {
8507		if (notify->find != NULL)
8508			dns_adb_cancelfind(notify->find);
8509		if (notify->request != NULL)
8510			dns_request_cancel(notify->request);
8511	}
8512}
8513
8514static void
8515forward_cancel(dns_zone_t *zone) {
8516	dns_forward_t *forward;
8517
8518	/*
8519	 * 'zone' locked by caller.
8520	 */
8521
8522	REQUIRE(LOCKED_ZONE(zone));
8523
8524	for (forward = ISC_LIST_HEAD(zone->forwards);
8525	     forward != NULL;
8526	     forward = ISC_LIST_NEXT(forward, link)) {
8527		if (forward->request != NULL)
8528			dns_request_cancel(forward->request);
8529	}
8530}
8531
8532static void
8533zone_unload(dns_zone_t *zone) {
8534
8535	/*
8536	 * 'zone' locked by caller.
8537	 */
8538
8539	REQUIRE(LOCKED_ZONE(zone));
8540
8541	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
8542	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
8543		if (zone->writeio != NULL)
8544			zonemgr_cancelio(zone->writeio);
8545
8546		if (zone->dctx != NULL)
8547			dns_dumpctx_cancel(zone->dctx);
8548	}
8549	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
8550	zone_detachdb(zone);
8551	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
8552	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
8553	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8554}
8555
8556void
8557dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8558	REQUIRE(DNS_ZONE_VALID(zone));
8559	REQUIRE(val > 0);
8560
8561	zone->minrefresh = val;
8562}
8563
8564void
8565dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8566	REQUIRE(DNS_ZONE_VALID(zone));
8567	REQUIRE(val > 0);
8568
8569	zone->maxrefresh = val;
8570}
8571
8572void
8573dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
8574	REQUIRE(DNS_ZONE_VALID(zone));
8575	REQUIRE(val > 0);
8576
8577	zone->minretry = val;
8578}
8579
8580void
8581dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
8582	REQUIRE(DNS_ZONE_VALID(zone));
8583	REQUIRE(val > 0);
8584
8585	zone->maxretry = val;
8586}
8587
8588static isc_boolean_t
8589notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
8590	dns_notify_t *notify;
8591
8592	for (notify = ISC_LIST_HEAD(zone->notifies);
8593	     notify != NULL;
8594	     notify = ISC_LIST_NEXT(notify, link)) {
8595		if (notify->request != NULL)
8596			continue;
8597		if (name != NULL && dns_name_dynamic(&notify->ns) &&
8598		    dns_name_equal(name, &notify->ns))
8599			return (ISC_TRUE);
8600		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
8601			return (ISC_TRUE);
8602	}
8603	return (ISC_FALSE);
8604}
8605
8606static isc_boolean_t
8607notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
8608	dns_tsigkey_t *key = NULL;
8609	isc_sockaddr_t src;
8610	isc_sockaddr_t any;
8611	isc_boolean_t isself;
8612	isc_netaddr_t dstaddr;
8613	isc_result_t result;
8614
8615	if (zone->view == NULL || zone->isself == NULL)
8616		return (ISC_FALSE);
8617
8618	switch (isc_sockaddr_pf(dst)) {
8619	case PF_INET:
8620		src = zone->notifysrc4;
8621		isc_sockaddr_any(&any);
8622		break;
8623	case PF_INET6:
8624		src = zone->notifysrc6;
8625		isc_sockaddr_any6(&any);
8626		break;
8627	default:
8628		return (ISC_FALSE);
8629	}
8630
8631	/*
8632	 * When sending from any the kernel will assign a source address
8633	 * that matches the destination address.
8634	 */
8635	if (isc_sockaddr_eqaddr(&any, &src))
8636		src = *dst;
8637
8638	isc_netaddr_fromsockaddr(&dstaddr, dst);
8639	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
8640	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
8641		return (ISC_FALSE);
8642	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
8643				zone->isselfarg);
8644	if (key != NULL)
8645		dns_tsigkey_detach(&key);
8646	return (isself);
8647}
8648
8649static void
8650notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
8651	isc_mem_t *mctx;
8652
8653	/*
8654	 * Caller holds zone lock.
8655	 */
8656	REQUIRE(DNS_NOTIFY_VALID(notify));
8657
8658	if (notify->zone != NULL) {
8659		if (!locked)
8660			LOCK_ZONE(notify->zone);
8661		REQUIRE(LOCKED_ZONE(notify->zone));
8662		if (ISC_LINK_LINKED(notify, link))
8663			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
8664		if (!locked)
8665			UNLOCK_ZONE(notify->zone);
8666		if (locked)
8667			zone_idetach(&notify->zone);
8668		else
8669			dns_zone_idetach(&notify->zone);
8670	}
8671	if (notify->find != NULL)
8672		dns_adb_destroyfind(&notify->find);
8673	if (notify->request != NULL)
8674		dns_request_destroy(&notify->request);
8675	if (dns_name_dynamic(&notify->ns))
8676		dns_name_free(&notify->ns, notify->mctx);
8677	mctx = notify->mctx;
8678	isc_mem_put(notify->mctx, notify, sizeof(*notify));
8679	isc_mem_detach(&mctx);
8680}
8681
8682static isc_result_t
8683notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
8684	dns_notify_t *notify;
8685
8686	REQUIRE(notifyp != NULL && *notifyp == NULL);
8687
8688	notify = isc_mem_get(mctx, sizeof(*notify));
8689	if (notify == NULL)
8690		return (ISC_R_NOMEMORY);
8691
8692	notify->mctx = NULL;
8693	isc_mem_attach(mctx, &notify->mctx);
8694	notify->flags = flags;
8695	notify->zone = NULL;
8696	notify->find = NULL;
8697	notify->request = NULL;
8698	isc_sockaddr_any(&notify->dst);
8699	dns_name_init(&notify->ns, NULL);
8700	ISC_LINK_INIT(notify, link);
8701	notify->magic = NOTIFY_MAGIC;
8702	*notifyp = notify;
8703	return (ISC_R_SUCCESS);
8704}
8705
8706/*
8707 * XXXAG should check for DNS_ZONEFLG_EXITING
8708 */
8709static void
8710process_adb_event(isc_task_t *task, isc_event_t *ev) {
8711	dns_notify_t *notify;
8712	isc_eventtype_t result;
8713
8714	UNUSED(task);
8715
8716	notify = ev->ev_arg;
8717	REQUIRE(DNS_NOTIFY_VALID(notify));
8718	INSIST(task == notify->zone->task);
8719	result = ev->ev_type;
8720	isc_event_free(&ev);
8721	if (result == DNS_EVENT_ADBMOREADDRESSES) {
8722		dns_adb_destroyfind(&notify->find);
8723		notify_find_address(notify);
8724		return;
8725	}
8726	if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
8727		LOCK_ZONE(notify->zone);
8728		notify_send(notify);
8729		UNLOCK_ZONE(notify->zone);
8730	}
8731	notify_destroy(notify, ISC_FALSE);
8732}
8733
8734static void
8735notify_find_address(dns_notify_t *notify) {
8736	isc_result_t result;
8737	unsigned int options;
8738
8739	REQUIRE(DNS_NOTIFY_VALID(notify));
8740	options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
8741		  DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
8742
8743	if (notify->zone->view->adb == NULL)
8744		goto destroy;
8745
8746	result = dns_adb_createfind(notify->zone->view->adb,
8747				    notify->zone->task,
8748				    process_adb_event, notify,
8749				    &notify->ns, dns_rootname, 0,
8750				    options, 0, NULL,
8751				    notify->zone->view->dstport,
8752				    &notify->find);
8753
8754	/* Something failed? */
8755	if (result != ISC_R_SUCCESS)
8756		goto destroy;
8757
8758	/* More addresses pending? */
8759	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
8760		return;
8761
8762	/* We have as many addresses as we can get. */
8763	LOCK_ZONE(notify->zone);
8764	notify_send(notify);
8765	UNLOCK_ZONE(notify->zone);
8766
8767 destroy:
8768	notify_destroy(notify, ISC_FALSE);
8769}
8770
8771
8772static isc_result_t
8773notify_send_queue(dns_notify_t *notify) {
8774	isc_event_t *e;
8775	isc_result_t result;
8776
8777	e = isc_event_allocate(notify->mctx, NULL,
8778			       DNS_EVENT_NOTIFYSENDTOADDR,
8779			       notify_send_toaddr,
8780			       notify, sizeof(isc_event_t));
8781	if (e == NULL)
8782		return (ISC_R_NOMEMORY);
8783	e->ev_arg = notify;
8784	e->ev_sender = NULL;
8785	result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
8786					 notify->zone->task, &e);
8787	if (result != ISC_R_SUCCESS)
8788		isc_event_free(&e);
8789	return (result);
8790}
8791
8792static void
8793notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
8794	dns_notify_t *notify;
8795	isc_result_t result;
8796	dns_message_t *message = NULL;
8797	isc_netaddr_t dstip;
8798	dns_tsigkey_t *key = NULL;
8799	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
8800	isc_sockaddr_t src;
8801	int timeout;
8802	isc_boolean_t have_notifysource = ISC_FALSE;
8803
8804	notify = event->ev_arg;
8805	REQUIRE(DNS_NOTIFY_VALID(notify));
8806
8807	UNUSED(task);
8808
8809	LOCK_ZONE(notify->zone);
8810
8811	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
8812		result = ISC_R_CANCELED;
8813		goto cleanup;
8814	}
8815
8816	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
8817	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
8818	    notify->zone->view->requestmgr == NULL ||
8819	    notify->zone->db == NULL) {
8820		result = ISC_R_CANCELED;
8821		goto cleanup;
8822	}
8823
8824	/*
8825	 * The raw IPv4 address should also exist.  Don't send to the
8826	 * mapped form.
8827	 */
8828	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
8829	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
8830		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
8831		notify_log(notify->zone, ISC_LOG_DEBUG(3),
8832			   "notify: ignoring IPv6 mapped IPV4 address: %s",
8833			   addrbuf);
8834		result = ISC_R_CANCELED;
8835		goto cleanup;
8836	}
8837
8838	result = notify_createmessage(notify->zone, notify->flags, &message);
8839	if (result != ISC_R_SUCCESS)
8840		goto cleanup;
8841
8842	isc_netaddr_fromsockaddr(&dstip, &notify->dst);
8843	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
8844	result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
8845	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
8846		notify_log(notify->zone, ISC_LOG_ERROR, "NOTIFY to %s not "
8847			   "sent. Peer TSIG key lookup failure.", addrbuf);
8848		goto cleanup_message;
8849	}
8850
8851	notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
8852		   addrbuf);
8853	if (notify->zone->view->peers != NULL) {
8854		dns_peer_t *peer = NULL;
8855		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
8856						 &dstip, &peer);
8857		if (result == ISC_R_SUCCESS) {
8858			result = dns_peer_getnotifysource(peer, &src);
8859			if (result == ISC_R_SUCCESS)
8860				have_notifysource = ISC_TRUE;
8861		}
8862	}
8863	switch (isc_sockaddr_pf(&notify->dst)) {
8864	case PF_INET:
8865		if (!have_notifysource)
8866			src = notify->zone->notifysrc4;
8867		break;
8868	case PF_INET6:
8869		if (!have_notifysource)
8870			src = notify->zone->notifysrc6;
8871		break;
8872	default:
8873		result = ISC_R_NOTIMPLEMENTED;
8874		goto cleanup_key;
8875	}
8876	timeout = 15;
8877	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
8878		timeout = 30;
8879	result = dns_request_createvia2(notify->zone->view->requestmgr,
8880					message, &src, &notify->dst, 0, key,
8881					timeout * 3, timeout,
8882					notify->zone->task, notify_done,
8883					notify, &notify->request);
8884	if (result == ISC_R_SUCCESS) {
8885		if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
8886			inc_stats(notify->zone,
8887				  dns_zonestatscounter_notifyoutv4);
8888		} else {
8889			inc_stats(notify->zone,
8890				  dns_zonestatscounter_notifyoutv6);
8891		}
8892	}
8893
8894 cleanup_key:
8895	if (key != NULL)
8896		dns_tsigkey_detach(&key);
8897 cleanup_message:
8898	dns_message_destroy(&message);
8899 cleanup:
8900	UNLOCK_ZONE(notify->zone);
8901	if (result != ISC_R_SUCCESS)
8902		notify_destroy(notify, ISC_FALSE);
8903	isc_event_free(&event);
8904}
8905
8906static void
8907notify_send(dns_notify_t *notify) {
8908	dns_adbaddrinfo_t *ai;
8909	isc_sockaddr_t dst;
8910	isc_result_t result;
8911	dns_notify_t *new = NULL;
8912
8913	/*
8914	 * Zone lock held by caller.
8915	 */
8916	REQUIRE(DNS_NOTIFY_VALID(notify));
8917	REQUIRE(LOCKED_ZONE(notify->zone));
8918
8919	for (ai = ISC_LIST_HEAD(notify->find->list);
8920	     ai != NULL;
8921	     ai = ISC_LIST_NEXT(ai, publink)) {
8922		dst = ai->sockaddr;
8923		if (notify_isqueued(notify->zone, NULL, &dst))
8924			continue;
8925		if (notify_isself(notify->zone, &dst))
8926			continue;
8927		new = NULL;
8928		result = notify_create(notify->mctx,
8929				       (notify->flags & DNS_NOTIFY_NOSOA),
8930				       &new);
8931		if (result != ISC_R_SUCCESS)
8932			goto cleanup;
8933		zone_iattach(notify->zone, &new->zone);
8934		ISC_LIST_APPEND(new->zone->notifies, new, link);
8935		new->dst = dst;
8936		result = notify_send_queue(new);
8937		if (result != ISC_R_SUCCESS)
8938			goto cleanup;
8939		new = NULL;
8940	}
8941
8942 cleanup:
8943	if (new != NULL)
8944		notify_destroy(new, ISC_TRUE);
8945}
8946
8947void
8948dns_zone_notify(dns_zone_t *zone) {
8949	isc_time_t now;
8950
8951	REQUIRE(DNS_ZONE_VALID(zone));
8952
8953	LOCK_ZONE(zone);
8954	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8955
8956	TIME_NOW(&now);
8957	zone_settimer(zone, &now);
8958	UNLOCK_ZONE(zone);
8959}
8960
8961static void
8962zone_notify(dns_zone_t *zone, isc_time_t *now) {
8963	dns_dbnode_t *node = NULL;
8964	dns_db_t *zonedb = NULL;
8965	dns_dbversion_t *version = NULL;
8966	dns_name_t *origin = NULL;
8967	dns_name_t master;
8968	dns_rdata_ns_t ns;
8969	dns_rdata_soa_t soa;
8970	isc_uint32_t serial;
8971	dns_rdata_t rdata = DNS_RDATA_INIT;
8972	dns_rdataset_t nsrdset;
8973	dns_rdataset_t soardset;
8974	isc_result_t result;
8975	dns_notify_t *notify = NULL;
8976	unsigned int i;
8977	isc_sockaddr_t dst;
8978	isc_boolean_t isqueued;
8979	dns_notifytype_t notifytype;
8980	unsigned int flags = 0;
8981	isc_boolean_t loggednotify = ISC_FALSE;
8982
8983	REQUIRE(DNS_ZONE_VALID(zone));
8984
8985	LOCK_ZONE(zone);
8986	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8987	notifytype = zone->notifytype;
8988	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
8989	UNLOCK_ZONE(zone);
8990
8991	if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
8992		return;
8993
8994	if (notifytype == dns_notifytype_no)
8995		return;
8996
8997	if (notifytype == dns_notifytype_masteronly &&
8998	    zone->type != dns_zone_master)
8999		return;
9000
9001	origin = &zone->origin;
9002
9003	/*
9004	 * If the zone is dialup we are done as we don't want to send
9005	 * the current soa so as to force a refresh query.
9006	 */
9007	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
9008		flags |= DNS_NOTIFY_NOSOA;
9009
9010	/*
9011	 * Get SOA RRset.
9012	 */
9013	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9014	if (zone->db != NULL)
9015		dns_db_attach(zone->db, &zonedb);
9016	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9017	if (zonedb == NULL)
9018		return;
9019	dns_db_currentversion(zonedb, &version);
9020	result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
9021	if (result != ISC_R_SUCCESS)
9022		goto cleanup1;
9023
9024	dns_rdataset_init(&soardset);
9025	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
9026				     dns_rdatatype_none, 0, &soardset, NULL);
9027	if (result != ISC_R_SUCCESS)
9028		goto cleanup2;
9029
9030	/*
9031	 * Find serial and master server's name.
9032	 */
9033	dns_name_init(&master, NULL);
9034	result = dns_rdataset_first(&soardset);
9035	if (result != ISC_R_SUCCESS)
9036		goto cleanup3;
9037	dns_rdataset_current(&soardset, &rdata);
9038	result = dns_rdata_tostruct(&rdata, &soa, NULL);
9039	RUNTIME_CHECK(result == ISC_R_SUCCESS);
9040	dns_rdata_reset(&rdata);
9041	result = dns_name_dup(&soa.origin, zone->mctx, &master);
9042	serial = soa.serial;
9043	dns_rdataset_disassociate(&soardset);
9044	if (result != ISC_R_SUCCESS)
9045		goto cleanup3;
9046
9047	/*
9048	 * Enqueue notify requests for 'also-notify' servers.
9049	 */
9050	LOCK_ZONE(zone);
9051	for (i = 0; i < zone->notifycnt; i++) {
9052		dst = zone->notify[i];
9053		if (notify_isqueued(zone, NULL, &dst))
9054			continue;
9055		result = notify_create(zone->mctx, flags, &notify);
9056		if (result != ISC_R_SUCCESS)
9057			continue;
9058		zone_iattach(zone, &notify->zone);
9059		notify->dst = dst;
9060		ISC_LIST_APPEND(zone->notifies, notify, link);
9061		result = notify_send_queue(notify);
9062		if (result != ISC_R_SUCCESS)
9063			notify_destroy(notify, ISC_TRUE);
9064		if (!loggednotify) {
9065			notify_log(zone, ISC_LOG_INFO,
9066				   "sending notifies (serial %u)",
9067				   serial);
9068			loggednotify = ISC_TRUE;
9069		}
9070		notify = NULL;
9071	}
9072	UNLOCK_ZONE(zone);
9073
9074	if (notifytype == dns_notifytype_explicit)
9075		goto cleanup3;
9076
9077	/*
9078	 * Process NS RRset to generate notifies.
9079	 */
9080
9081	dns_rdataset_init(&nsrdset);
9082	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
9083				     dns_rdatatype_none, 0, &nsrdset, NULL);
9084	if (result != ISC_R_SUCCESS)
9085		goto cleanup3;
9086
9087	result = dns_rdataset_first(&nsrdset);
9088	while (result == ISC_R_SUCCESS) {
9089		dns_rdataset_current(&nsrdset, &rdata);
9090		result = dns_rdata_tostruct(&rdata, &ns, NULL);
9091		RUNTIME_CHECK(result == ISC_R_SUCCESS);
9092		dns_rdata_reset(&rdata);
9093		/*
9094		 * Don't notify the master server unless explicitly
9095		 * configured to do so.
9096		 */
9097		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
9098		    dns_name_compare(&master, &ns.name) == 0) {
9099			result = dns_rdataset_next(&nsrdset);
9100			continue;
9101		}
9102
9103		if (!loggednotify) {
9104			notify_log(zone, ISC_LOG_INFO,
9105				   "sending notifies (serial %u)",
9106				   serial);
9107			loggednotify = ISC_TRUE;
9108		}
9109
9110		LOCK_ZONE(zone);
9111		isqueued = notify_isqueued(zone, &ns.name, NULL);
9112		UNLOCK_ZONE(zone);
9113		if (isqueued) {
9114			result = dns_rdataset_next(&nsrdset);
9115			continue;
9116		}
9117		result = notify_create(zone->mctx, flags, &notify);
9118		if (result != ISC_R_SUCCESS)
9119			continue;
9120		dns_zone_iattach(zone, &notify->zone);
9121		result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
9122		if (result != ISC_R_SUCCESS) {
9123			LOCK_ZONE(zone);
9124			notify_destroy(notify, ISC_TRUE);
9125			UNLOCK_ZONE(zone);
9126			continue;
9127		}
9128		LOCK_ZONE(zone);
9129		ISC_LIST_APPEND(zone->notifies, notify, link);
9130		UNLOCK_ZONE(zone);
9131		notify_find_address(notify);
9132		notify = NULL;
9133		result = dns_rdataset_next(&nsrdset);
9134	}
9135	dns_rdataset_disassociate(&nsrdset);
9136
9137 cleanup3:
9138	if (dns_name_dynamic(&master))
9139		dns_name_free(&master, zone->mctx);
9140 cleanup2:
9141	dns_db_detachnode(zonedb, &node);
9142 cleanup1:
9143	dns_db_closeversion(zonedb, &version, ISC_FALSE);
9144	dns_db_detach(&zonedb);
9145}
9146
9147/***
9148 *** Private
9149 ***/
9150
9151static inline isc_result_t
9152save_nsrrset(dns_message_t *message, dns_name_t *name,
9153	     dns_db_t *db, dns_dbversion_t *version)
9154{
9155	dns_rdataset_t *nsrdataset = NULL;
9156	dns_rdataset_t *rdataset = NULL;
9157	dns_dbnode_t *node = NULL;
9158	dns_rdata_ns_t ns;
9159	isc_result_t result;
9160	dns_rdata_t rdata = DNS_RDATA_INIT;
9161
9162	/*
9163	 * Extract NS RRset from message.
9164	 */
9165	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
9166				      dns_rdatatype_ns, dns_rdatatype_none,
9167				      NULL, &nsrdataset);
9168	if (result != ISC_R_SUCCESS)
9169		goto fail;
9170
9171	/*
9172	 * Add NS rdataset.
9173	 */
9174	result = dns_db_findnode(db, name, ISC_TRUE, &node);
9175	if (result != ISC_R_SUCCESS)
9176		goto fail;
9177	result = dns_db_addrdataset(db, node, version, 0,
9178				    nsrdataset, 0, NULL);
9179	dns_db_detachnode(db, &node);
9180	if (result != ISC_R_SUCCESS)
9181		goto fail;
9182	/*
9183	 * Add glue rdatasets.
9184	 */
9185	for (result = dns_rdataset_first(nsrdataset);
9186	     result == ISC_R_SUCCESS;
9187	     result = dns_rdataset_next(nsrdataset)) {
9188		dns_rdataset_current(nsrdataset, &rdata);
9189		result = dns_rdata_tostruct(&rdata, &ns, NULL);
9190		RUNTIME_CHECK(result == ISC_R_SUCCESS);
9191		dns_rdata_reset(&rdata);
9192		if (!dns_name_issubdomain(&ns.name, name))
9193			continue;
9194		rdataset = NULL;
9195		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9196					      &ns.name, dns_rdatatype_aaaa,
9197					      dns_rdatatype_none, NULL,
9198					      &rdataset);
9199		if (result == ISC_R_SUCCESS) {
9200			result = dns_db_findnode(db, &ns.name,
9201						 ISC_TRUE, &node);
9202			if (result != ISC_R_SUCCESS)
9203				goto fail;
9204			result = dns_db_addrdataset(db, node, version, 0,
9205						    rdataset, 0, NULL);
9206			dns_db_detachnode(db, &node);
9207			if (result != ISC_R_SUCCESS)
9208				goto fail;
9209		}
9210		rdataset = NULL;
9211		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9212					      &ns.name, dns_rdatatype_a,
9213					      dns_rdatatype_none, NULL,
9214					      &rdataset);
9215		if (result == ISC_R_SUCCESS) {
9216			result = dns_db_findnode(db, &ns.name,
9217						 ISC_TRUE, &node);
9218			if (result != ISC_R_SUCCESS)
9219				goto fail;
9220			result = dns_db_addrdataset(db, node, version, 0,
9221						    rdataset, 0, NULL);
9222			dns_db_detachnode(db, &node);
9223			if (result != ISC_R_SUCCESS)
9224				goto fail;
9225		}
9226	}
9227	if (result != ISC_R_NOMORE)
9228		goto fail;
9229
9230	return (ISC_R_SUCCESS);
9231
9232fail:
9233	return (result);
9234}
9235
9236static void
9237stub_callback(isc_task_t *task, isc_event_t *event) {
9238	const char me[] = "stub_callback";
9239	dns_requestevent_t *revent = (dns_requestevent_t *)event;
9240	dns_stub_t *stub = NULL;
9241	dns_message_t *msg = NULL;
9242	dns_zone_t *zone = NULL;
9243	char master[ISC_SOCKADDR_FORMATSIZE];
9244	char source[ISC_SOCKADDR_FORMATSIZE];
9245	isc_uint32_t nscnt, cnamecnt;
9246	isc_result_t result;
9247	isc_time_t now;
9248	isc_boolean_t exiting = ISC_FALSE;
9249	isc_interval_t i;
9250	unsigned int j;
9251
9252	stub = revent->ev_arg;
9253	INSIST(DNS_STUB_VALID(stub));
9254
9255	UNUSED(task);
9256
9257	zone = stub->zone;
9258
9259	ENTER;
9260
9261	TIME_NOW(&now);
9262
9263	LOCK_ZONE(zone);
9264
9265	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9266		zone_debuglog(zone, me, 1, "exiting");
9267		exiting = ISC_TRUE;
9268		goto next_master;
9269	}
9270
9271	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9272	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9273
9274	if (revent->result != ISC_R_SUCCESS) {
9275		if (revent->result == ISC_R_TIMEDOUT &&
9276		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9277			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9278			dns_zone_log(zone, ISC_LOG_DEBUG(1),
9279				     "refreshing stub: timeout retrying "
9280				     " without EDNS master %s (source %s)",
9281				     master, source);
9282			goto same_master;
9283		}
9284		dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
9285					   &zone->sourceaddr, &now);
9286		dns_zone_log(zone, ISC_LOG_INFO,
9287			     "could not refresh stub from master %s"
9288			     " (source %s): %s", master, source,
9289			     dns_result_totext(revent->result));
9290		goto next_master;
9291	}
9292
9293	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9294	if (result != ISC_R_SUCCESS)
9295		goto next_master;
9296
9297	result = dns_request_getresponse(revent->request, msg, 0);
9298	if (result != ISC_R_SUCCESS)
9299		goto next_master;
9300
9301	/*
9302	 * Unexpected rcode.
9303	 */
9304	if (msg->rcode != dns_rcode_noerror) {
9305		char rcode[128];
9306		isc_buffer_t rb;
9307
9308		isc_buffer_init(&rb, rcode, sizeof(rcode));
9309		(void)dns_rcode_totext(msg->rcode, &rb);
9310
9311		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9312		    (msg->rcode == dns_rcode_servfail ||
9313		     msg->rcode == dns_rcode_notimp ||
9314		     msg->rcode == dns_rcode_formerr)) {
9315			dns_zone_log(zone, ISC_LOG_DEBUG(1),
9316				     "refreshing stub: rcode (%.*s) retrying "
9317				     "without EDNS master %s (source %s)",
9318				     (int)rb.used, rcode, master, source);
9319			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9320			goto same_master;
9321		}
9322
9323		dns_zone_log(zone, ISC_LOG_INFO,
9324			     "refreshing stub: "
9325			     "unexpected rcode (%.*s) from %s (source %s)",
9326			     (int)rb.used, rcode, master, source);
9327		goto next_master;
9328	}
9329
9330	/*
9331	 * We need complete messages.
9332	 */
9333	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9334		if (dns_request_usedtcp(revent->request)) {
9335			dns_zone_log(zone, ISC_LOG_INFO,
9336				     "refreshing stub: truncated TCP "
9337				     "response from master %s (source %s)",
9338				     master, source);
9339			goto next_master;
9340		}
9341		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9342		goto same_master;
9343	}
9344
9345	/*
9346	 * If non-auth log and next master.
9347	 */
9348	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9349		dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
9350			     "non-authoritative answer from "
9351			     "master %s (source %s)", master, source);
9352		goto next_master;
9353	}
9354
9355	/*
9356	 * Sanity checks.
9357	 */
9358	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9359	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
9360
9361	if (cnamecnt != 0) {
9362		dns_zone_log(zone, ISC_LOG_INFO,
9363			     "refreshing stub: unexpected CNAME response "
9364			     "from master %s (source %s)", master, source);
9365		goto next_master;
9366	}
9367
9368	if (nscnt == 0) {
9369		dns_zone_log(zone, ISC_LOG_INFO,
9370			     "refreshing stub: no NS records in response "
9371			     "from master %s (source %s)", master, source);
9372		goto next_master;
9373	}
9374
9375	/*
9376	 * Save answer.
9377	 */
9378	result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
9379	if (result != ISC_R_SUCCESS) {
9380		dns_zone_log(zone, ISC_LOG_INFO,
9381			     "refreshing stub: unable to save NS records "
9382			     "from master %s (source %s)", master, source);
9383		goto next_master;
9384	}
9385
9386	/*
9387	 * Tidy up.
9388	 */
9389	dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
9390	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9391	if (zone->db == NULL)
9392		zone_attachdb(zone, stub->db);
9393	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9394	dns_db_detach(&stub->db);
9395
9396	if (zone->masterfile != NULL)
9397		zone_needdump(zone, 0);
9398
9399	dns_message_destroy(&msg);
9400	isc_event_free(&event);
9401	dns_request_destroy(&zone->request);
9402	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9403	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9404	isc_interval_set(&i, zone->expire, 0);
9405	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9406	zone_settimer(zone, &now);
9407	goto free_stub;
9408
9409 next_master:
9410	if (stub->version != NULL)
9411		dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
9412	if (stub->db != NULL)
9413		dns_db_detach(&stub->db);
9414	if (msg != NULL)
9415		dns_message_destroy(&msg);
9416	isc_event_free(&event);
9417	dns_request_destroy(&zone->request);
9418	/*
9419	 * Skip to next failed / untried master.
9420	 */
9421	do {
9422		zone->curmaster++;
9423	} while (zone->curmaster < zone->masterscnt &&
9424		 zone->mastersok[zone->curmaster]);
9425	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9426	if (exiting || zone->curmaster >= zone->masterscnt) {
9427		isc_boolean_t done = ISC_TRUE;
9428		if (!exiting &&
9429		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9430		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9431			/*
9432			 * Did we get a good answer from all the masters?
9433			 */
9434			for (j = 0; j < zone->masterscnt; j++)
9435				if (zone->mastersok[j] == ISC_FALSE) {
9436					done = ISC_FALSE;
9437					break;
9438				}
9439		} else
9440			done = ISC_TRUE;
9441		if (!done) {
9442			zone->curmaster = 0;
9443			/*
9444			 * Find the next failed master.
9445			 */
9446			while (zone->curmaster < zone->masterscnt &&
9447			       zone->mastersok[zone->curmaster])
9448				zone->curmaster++;
9449			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9450		} else {
9451			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9452
9453			zone_settimer(zone, &now);
9454			goto free_stub;
9455		}
9456	}
9457	queue_soa_query(zone);
9458	goto free_stub;
9459
9460 same_master:
9461	if (msg != NULL)
9462		dns_message_destroy(&msg);
9463	isc_event_free(&event);
9464	dns_request_destroy(&zone->request);
9465	ns_query(zone, NULL, stub);
9466	UNLOCK_ZONE(zone);
9467	goto done;
9468
9469 free_stub:
9470	UNLOCK_ZONE(zone);
9471	stub->magic = 0;
9472	dns_zone_idetach(&stub->zone);
9473	INSIST(stub->db == NULL);
9474	INSIST(stub->version == NULL);
9475	isc_mem_put(stub->mctx, stub, sizeof(*stub));
9476
9477 done:
9478	INSIST(event == NULL);
9479	return;
9480}
9481
9482/*
9483 * An SOA query has finished (successfully or not).
9484 */
9485static void
9486refresh_callback(isc_task_t *task, isc_event_t *event) {
9487	const char me[] = "refresh_callback";
9488	dns_requestevent_t *revent = (dns_requestevent_t *)event;
9489	dns_zone_t *zone;
9490	dns_message_t *msg = NULL;
9491	isc_uint32_t soacnt, cnamecnt, soacount, nscount;
9492	isc_time_t now;
9493	char master[ISC_SOCKADDR_FORMATSIZE];
9494	char source[ISC_SOCKADDR_FORMATSIZE];
9495	dns_rdataset_t *rdataset = NULL;
9496	dns_rdata_t rdata = DNS_RDATA_INIT;
9497	dns_rdata_soa_t soa;
9498	isc_result_t result;
9499	isc_uint32_t serial, oldserial = 0;
9500	unsigned int j;
9501	isc_boolean_t do_queue_xfrin = ISC_FALSE;
9502
9503	zone = revent->ev_arg;
9504	INSIST(DNS_ZONE_VALID(zone));
9505
9506	UNUSED(task);
9507
9508	ENTER;
9509
9510	TIME_NOW(&now);
9511
9512	LOCK_ZONE(zone);
9513
9514	/*
9515	 * if timeout log and next master;
9516	 */
9517
9518	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9519	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9520
9521	if (revent->result != ISC_R_SUCCESS) {
9522		if (revent->result == ISC_R_TIMEDOUT &&
9523		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9524			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9525			dns_zone_log(zone, ISC_LOG_DEBUG(1),
9526				     "refresh: timeout retrying without EDNS "
9527				     "master %s (source %s)", master, source);
9528			goto same_master;
9529		}
9530		if (revent->result == ISC_R_TIMEDOUT &&
9531		    !dns_request_usedtcp(revent->request)) {
9532			dns_zone_log(zone, ISC_LOG_INFO,
9533				     "refresh: retry limit for "
9534				     "master %s exceeded (source %s)",
9535				     master, source);
9536			/* Try with slave with TCP. */
9537			if (zone->type == dns_zone_slave &&
9538			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
9539				if (!dns_zonemgr_unreachable(zone->zmgr,
9540							     &zone->masteraddr,
9541							     &zone->sourceaddr,
9542							     &now))
9543				{
9544					DNS_ZONE_SETFLAG(zone,
9545						     DNS_ZONEFLG_SOABEFOREAXFR);
9546					goto tcp_transfer;
9547				}
9548				dns_zone_log(zone, ISC_LOG_DEBUG(1),
9549					     "refresh: skipped tcp fallback "
9550					     "as master %s (source %s) is "
9551					     "unreachable (cached)",
9552					      master, source);
9553			}
9554		} else
9555			dns_zone_log(zone, ISC_LOG_INFO,
9556				     "refresh: failure trying master "
9557				     "%s (source %s): %s", master, source,
9558				     dns_result_totext(revent->result));
9559		goto next_master;
9560	}
9561
9562	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9563	if (result != ISC_R_SUCCESS)
9564		goto next_master;
9565	result = dns_request_getresponse(revent->request, msg, 0);
9566	if (result != ISC_R_SUCCESS) {
9567		dns_zone_log(zone, ISC_LOG_INFO,
9568			     "refresh: failure trying master "
9569			     "%s (source %s): %s", master, source,
9570			     dns_result_totext(result));
9571		goto next_master;
9572	}
9573
9574	/*
9575	 * Unexpected rcode.
9576	 */
9577	if (msg->rcode != dns_rcode_noerror) {
9578		char rcode[128];
9579		isc_buffer_t rb;
9580
9581		isc_buffer_init(&rb, rcode, sizeof(rcode));
9582		(void)dns_rcode_totext(msg->rcode, &rb);
9583
9584		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9585		    (msg->rcode == dns_rcode_servfail ||
9586		     msg->rcode == dns_rcode_notimp ||
9587		     msg->rcode == dns_rcode_formerr)) {
9588			dns_zone_log(zone, ISC_LOG_DEBUG(1),
9589				     "refresh: rcode (%.*s) retrying without "
9590				     "EDNS master %s (source %s)",
9591				     (int)rb.used, rcode, master, source);
9592			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9593			goto same_master;
9594		}
9595		dns_zone_log(zone, ISC_LOG_INFO,
9596			     "refresh: unexpected rcode (%.*s) from "
9597			     "master %s (source %s)", (int)rb.used, rcode,
9598			     master, source);
9599		/*
9600		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
9601		 */
9602		if (msg->rcode == dns_rcode_refused &&
9603		    zone->type == dns_zone_slave)
9604			goto tcp_transfer;
9605		goto next_master;
9606	}
9607
9608	/*
9609	 * If truncated punt to zone transfer which will query again.
9610	 */
9611	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9612		if (zone->type == dns_zone_slave) {
9613			dns_zone_log(zone, ISC_LOG_INFO,
9614				     "refresh: truncated UDP answer, "
9615				     "initiating TCP zone xfer "
9616				     "for master %s (source %s)",
9617				     master, source);
9618			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
9619			goto tcp_transfer;
9620		} else {
9621			INSIST(zone->type == dns_zone_stub);
9622			if (dns_request_usedtcp(revent->request)) {
9623				dns_zone_log(zone, ISC_LOG_INFO,
9624					     "refresh: truncated TCP response "
9625					     "from master %s (source %s)",
9626					     master, source);
9627				goto next_master;
9628			}
9629			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9630			goto same_master;
9631		}
9632	}
9633
9634	/*
9635	 * if non-auth log and next master;
9636	 */
9637	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9638		dns_zone_log(zone, ISC_LOG_INFO,
9639			     "refresh: non-authoritative answer from "
9640			     "master %s (source %s)", master, source);
9641		goto next_master;
9642	}
9643
9644	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9645	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
9646	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
9647	soacount = message_count(msg, DNS_SECTION_AUTHORITY,
9648				 dns_rdatatype_soa);
9649
9650	/*
9651	 * There should not be a CNAME record at top of zone.
9652	 */
9653	if (cnamecnt != 0) {
9654		dns_zone_log(zone, ISC_LOG_INFO,
9655			     "refresh: CNAME at top of zone "
9656			     "in master %s (source %s)", master, source);
9657		goto next_master;
9658	}
9659
9660	/*
9661	 * if referral log and next master;
9662	 */
9663	if (soacnt == 0 && soacount == 0 && nscount != 0) {
9664		dns_zone_log(zone, ISC_LOG_INFO,
9665			     "refresh: referral response "
9666			     "from master %s (source %s)", master, source);
9667		goto next_master;
9668	}
9669
9670	/*
9671	 * if nodata log and next master;
9672	 */
9673	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
9674		dns_zone_log(zone, ISC_LOG_INFO,
9675			     "refresh: NODATA response "
9676			     "from master %s (source %s)", master, source);
9677		goto next_master;
9678	}
9679
9680	/*
9681	 * Only one soa at top of zone.
9682	 */
9683	if (soacnt != 1) {
9684		dns_zone_log(zone, ISC_LOG_INFO,
9685			     "refresh: answer SOA count (%d) != 1 "
9686			     "from master %s (source %s)",
9687			     soacnt, master, source);
9688		goto next_master;
9689	}
9690
9691	/*
9692	 * Extract serial
9693	 */
9694	rdataset = NULL;
9695	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
9696				      dns_rdatatype_soa, dns_rdatatype_none,
9697				      NULL, &rdataset);
9698	if (result != ISC_R_SUCCESS) {
9699		dns_zone_log(zone, ISC_LOG_INFO,
9700			     "refresh: unable to get SOA record "
9701			     "from master %s (source %s)", master, source);
9702		goto next_master;
9703	}
9704
9705	result = dns_rdataset_first(rdataset);
9706	if (result != ISC_R_SUCCESS) {
9707		dns_zone_log(zone, ISC_LOG_INFO,
9708			     "refresh: dns_rdataset_first() failed");
9709		goto next_master;
9710	}
9711
9712	dns_rdataset_current(rdataset, &rdata);
9713	result = dns_rdata_tostruct(&rdata, &soa, NULL);
9714	RUNTIME_CHECK(result == ISC_R_SUCCESS);
9715
9716	serial = soa.serial;
9717	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9718		result = zone_get_from_db(zone, zone->db, NULL, NULL,
9719					  &oldserial, NULL, NULL, NULL, NULL,
9720					  NULL);
9721		RUNTIME_CHECK(result == ISC_R_SUCCESS);
9722		zone_debuglog(zone, me, 1, "serial: new %u, old %u",
9723			      serial, oldserial);
9724	} else
9725		zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
9726			      serial);
9727
9728	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
9729	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
9730	    isc_serial_gt(serial, oldserial)) {
9731		if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
9732					    &zone->sourceaddr, &now))
9733		{
9734			dns_zone_log(zone, ISC_LOG_INFO,
9735				     "refresh: skipping %s as master %s "
9736				     "(source %s) is unreachable (cached)",
9737				     zone->type == dns_zone_slave ?
9738				     "zone transfer" : "NS query",
9739				     master, source);
9740			goto next_master;
9741		}
9742 tcp_transfer:
9743		isc_event_free(&event);
9744		dns_request_destroy(&zone->request);
9745		if (zone->type == dns_zone_slave) {
9746			do_queue_xfrin = ISC_TRUE;
9747		} else {
9748			INSIST(zone->type == dns_zone_stub);
9749			ns_query(zone, rdataset, NULL);
9750		}
9751		if (msg != NULL)
9752			dns_message_destroy(&msg);
9753	} else if (isc_serial_eq(soa.serial, oldserial)) {
9754		if (zone->masterfile != NULL) {
9755			result = ISC_R_FAILURE;
9756			if (zone->journal != NULL)
9757				result = isc_file_settime(zone->journal, &now);
9758			if (result == ISC_R_SUCCESS &&
9759			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9760			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9761				result = isc_file_settime(zone->masterfile,
9762							  &now);
9763			} else if (result != ISC_R_SUCCESS)
9764				result = isc_file_settime(zone->masterfile,
9765							  &now);
9766			/* Someone removed the file from underneath us! */
9767			if (result == ISC_R_FILENOTFOUND) {
9768				zone_needdump(zone, DNS_DUMP_DELAY);
9769			} else if (result != ISC_R_SUCCESS)
9770				dns_zone_log(zone, ISC_LOG_ERROR,
9771					     "refresh: could not set file "
9772					     "modification time of '%s': %s",
9773					     zone->masterfile,
9774					     dns_result_totext(result));
9775		}
9776		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9777		DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9778		zone->mastersok[zone->curmaster] = ISC_TRUE;
9779		goto next_master;
9780	} else {
9781		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
9782			dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
9783				     "received from master %s < ours (%u)",
9784				     soa.serial, master, oldserial);
9785		else
9786			zone_debuglog(zone, me, 1, "ahead");
9787		zone->mastersok[zone->curmaster] = ISC_TRUE;
9788		goto next_master;
9789	}
9790	if (msg != NULL)
9791		dns_message_destroy(&msg);
9792	goto detach;
9793
9794 next_master:
9795	if (msg != NULL)
9796		dns_message_destroy(&msg);
9797	isc_event_free(&event);
9798	dns_request_destroy(&zone->request);
9799	/*
9800	 * Skip to next failed / untried master.
9801	 */
9802	do {
9803		zone->curmaster++;
9804	} while (zone->curmaster < zone->masterscnt &&
9805		 zone->mastersok[zone->curmaster]);
9806	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9807	if (zone->curmaster >= zone->masterscnt) {
9808		isc_boolean_t done = ISC_TRUE;
9809		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9810		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9811			/*
9812			 * Did we get a good answer from all the masters?
9813			 */
9814			for (j = 0; j < zone->masterscnt; j++)
9815				if (zone->mastersok[j] == ISC_FALSE) {
9816					done = ISC_FALSE;
9817					break;
9818				}
9819		} else
9820			done = ISC_TRUE;
9821		if (!done) {
9822			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9823			zone->curmaster = 0;
9824			/*
9825			 * Find the next failed master.
9826			 */
9827			while (zone->curmaster < zone->masterscnt &&
9828			       zone->mastersok[zone->curmaster])
9829				zone->curmaster++;
9830			goto requeue;
9831		}
9832		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9833		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
9834			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
9835			zone->refreshtime = now;
9836		}
9837		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9838		zone_settimer(zone, &now);
9839		goto detach;
9840	}
9841
9842 requeue:
9843	queue_soa_query(zone);
9844	goto detach;
9845
9846 same_master:
9847	if (msg != NULL)
9848		dns_message_destroy(&msg);
9849	isc_event_free(&event);
9850	dns_request_destroy(&zone->request);
9851	queue_soa_query(zone);
9852
9853 detach:
9854	UNLOCK_ZONE(zone);
9855	if (do_queue_xfrin)
9856		queue_xfrin(zone);
9857	dns_zone_idetach(&zone);
9858	return;
9859}
9860
9861static void
9862queue_soa_query(dns_zone_t *zone) {
9863	const char me[] = "queue_soa_query";
9864	isc_event_t *e;
9865	dns_zone_t *dummy = NULL;
9866	isc_result_t result;
9867
9868	ENTER;
9869	/*
9870	 * Locked by caller
9871	 */
9872	REQUIRE(LOCKED_ZONE(zone));
9873
9874	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9875		cancel_refresh(zone);
9876		return;
9877	}
9878
9879	e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
9880			       soa_query, zone, sizeof(isc_event_t));
9881	if (e == NULL) {
9882		cancel_refresh(zone);
9883		return;
9884	}
9885
9886	/*
9887	 * Attach so that we won't clean up
9888	 * until the event is delivered.
9889	 */
9890	zone_iattach(zone, &dummy);
9891
9892	e->ev_arg = zone;
9893	e->ev_sender = NULL;
9894	result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
9895	if (result != ISC_R_SUCCESS) {
9896		zone_idetach(&dummy);
9897		isc_event_free(&e);
9898		cancel_refresh(zone);
9899	}
9900}
9901
9902static inline isc_result_t
9903create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
9904	     dns_message_t **messagep)
9905{
9906	dns_message_t *message = NULL;
9907	dns_name_t *qname = NULL;
9908	dns_rdataset_t *qrdataset = NULL;
9909	isc_result_t result;
9910
9911	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
9912				    &message);
9913	if (result != ISC_R_SUCCESS)
9914		goto cleanup;
9915
9916	message->opcode = dns_opcode_query;
9917	message->rdclass = zone->rdclass;
9918
9919	result = dns_message_gettempname(message, &qname);
9920	if (result != ISC_R_SUCCESS)
9921		goto cleanup;
9922
9923	result = dns_message_gettemprdataset(message, &qrdataset);
9924	if (result != ISC_R_SUCCESS)
9925		goto cleanup;
9926
9927	/*
9928	 * Make question.
9929	 */
9930	dns_name_init(qname, NULL);
9931	dns_name_clone(&zone->origin, qname);
9932	dns_rdataset_init(qrdataset);
9933	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
9934	ISC_LIST_APPEND(qname->list, qrdataset, link);
9935	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
9936
9937	*messagep = message;
9938	return (ISC_R_SUCCESS);
9939
9940 cleanup:
9941	if (qname != NULL)
9942		dns_message_puttempname(message, &qname);
9943	if (qrdataset != NULL)
9944		dns_message_puttemprdataset(message, &qrdataset);
9945	if (message != NULL)
9946		dns_message_destroy(&message);
9947	return (result);
9948}
9949
9950static isc_result_t
9951add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
9952	dns_rdataset_t *rdataset = NULL;
9953	dns_rdatalist_t *rdatalist = NULL;
9954	dns_rdata_t *rdata = NULL;
9955	isc_result_t result;
9956
9957	result = dns_message_gettemprdatalist(message, &rdatalist);
9958	if (result != ISC_R_SUCCESS)
9959		goto cleanup;
9960	result = dns_message_gettemprdata(message, &rdata);
9961	if (result != ISC_R_SUCCESS)
9962		goto cleanup;
9963	result = dns_message_gettemprdataset(message, &rdataset);
9964	if (result != ISC_R_SUCCESS)
9965		goto cleanup;
9966	dns_rdataset_init(rdataset);
9967
9968	rdatalist->type = dns_rdatatype_opt;
9969	rdatalist->covers = 0;
9970
9971	/*
9972	 * Set Maximum UDP buffer size.
9973	 */
9974	rdatalist->rdclass = udpsize;
9975
9976	/*
9977	 * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
9978	 */
9979	rdatalist->ttl = 0;
9980
9981	/* Set EDNS options if applicable */
9982	if (reqnsid) {
9983		unsigned char data[4];
9984		isc_buffer_t buf;
9985
9986		isc_buffer_init(&buf, data, sizeof(data));
9987		isc_buffer_putuint16(&buf, DNS_OPT_NSID);
9988		isc_buffer_putuint16(&buf, 0);
9989		rdata->data = data;
9990		rdata->length = sizeof(data);
9991	} else {
9992		rdata->data = NULL;
9993		rdata->length = 0;
9994	}
9995
9996	rdata->rdclass = rdatalist->rdclass;
9997	rdata->type = rdatalist->type;
9998	rdata->flags = 0;
9999
10000	ISC_LIST_INIT(rdatalist->rdata);
10001	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
10002	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
10003		      == ISC_R_SUCCESS);
10004
10005	return (dns_message_setopt(message, rdataset));
10006
10007 cleanup:
10008	if (rdatalist != NULL)
10009		dns_message_puttemprdatalist(message, &rdatalist);
10010	if (rdataset != NULL)
10011		dns_message_puttemprdataset(message, &rdataset);
10012	if (rdata != NULL)
10013		dns_message_puttemprdata(message, &rdata);
10014
10015	return (result);
10016}
10017
10018static void
10019soa_query(isc_task_t *task, isc_event_t *event) {
10020	const char me[] = "soa_query";
10021	isc_result_t result = ISC_R_FAILURE;
10022	dns_message_t *message = NULL;
10023	dns_zone_t *zone = event->ev_arg;
10024	dns_zone_t *dummy = NULL;
10025	isc_netaddr_t masterip;
10026	dns_tsigkey_t *key = NULL;
10027	isc_uint32_t options;
10028	isc_boolean_t cancel = ISC_TRUE;
10029	int timeout;
10030	isc_boolean_t have_xfrsource, reqnsid;
10031	isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10032
10033	REQUIRE(DNS_ZONE_VALID(zone));
10034
10035	UNUSED(task);
10036
10037	ENTER;
10038
10039	LOCK_ZONE(zone);
10040	if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
10041	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
10042	    zone->view->requestmgr == NULL) {
10043		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10044			cancel = ISC_FALSE;
10045		goto cleanup;
10046	}
10047
10048	/*
10049	 * XXX Optimisation: Create message when zone is setup and reuse.
10050	 */
10051	result = create_query(zone, dns_rdatatype_soa, &message);
10052	if (result != ISC_R_SUCCESS)
10053		goto cleanup;
10054
10055 again:
10056	INSIST(zone->masterscnt > 0);
10057	INSIST(zone->curmaster < zone->masterscnt);
10058
10059	zone->masteraddr = zone->masters[zone->curmaster];
10060
10061	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10062	/*
10063	 * First, look for a tsig key in the master statement, then
10064	 * try for a server key.
10065	 */
10066	if ((zone->masterkeynames != NULL) &&
10067	    (zone->masterkeynames[zone->curmaster] != NULL)) {
10068		dns_view_t *view = dns_zone_getview(zone);
10069		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10070		result = dns_view_gettsig(view, keyname, &key);
10071		if (result != ISC_R_SUCCESS) {
10072			char namebuf[DNS_NAME_FORMATSIZE];
10073			dns_name_format(keyname, namebuf, sizeof(namebuf));
10074			dns_zone_log(zone, ISC_LOG_ERROR,
10075				     "unable to find key: %s", namebuf);
10076			goto skip_master;
10077		}
10078	}
10079	if (key == NULL) {
10080		result = dns_view_getpeertsig(zone->view, &masterip, &key);
10081		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
10082			char addrbuf[ISC_NETADDR_FORMATSIZE];
10083			isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
10084			dns_zone_log(zone, ISC_LOG_ERROR,
10085				     "unable to find TSIG key for %s", addrbuf);
10086			goto skip_master;
10087		}
10088	}
10089
10090	have_xfrsource = ISC_FALSE;
10091	reqnsid = zone->view->requestnsid;
10092	if (zone->view->peers != NULL) {
10093		dns_peer_t *peer = NULL;
10094		isc_boolean_t edns;
10095		result = dns_peerlist_peerbyaddr(zone->view->peers,
10096						 &masterip, &peer);
10097		if (result == ISC_R_SUCCESS) {
10098			result = dns_peer_getsupportedns(peer, &edns);
10099			if (result == ISC_R_SUCCESS && !edns)
10100				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10101			result = dns_peer_gettransfersource(peer,
10102							    &zone->sourceaddr);
10103			if (result == ISC_R_SUCCESS)
10104				have_xfrsource = ISC_TRUE;
10105			if (zone->view->resolver != NULL)
10106				udpsize =
10107				  dns_resolver_getudpsize(zone->view->resolver);
10108			(void)dns_peer_getudpsize(peer, &udpsize);
10109			(void)dns_peer_getrequestnsid(peer, &reqnsid);
10110		}
10111	}
10112
10113	switch (isc_sockaddr_pf(&zone->masteraddr)) {
10114	case PF_INET:
10115		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10116			if (isc_sockaddr_equal(&zone->altxfrsource4,
10117					       &zone->xfrsource4))
10118				goto skip_master;
10119			zone->sourceaddr = zone->altxfrsource4;
10120		} else if (!have_xfrsource)
10121			zone->sourceaddr = zone->xfrsource4;
10122		break;
10123	case PF_INET6:
10124		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10125			if (isc_sockaddr_equal(&zone->altxfrsource6,
10126					       &zone->xfrsource6))
10127				goto skip_master;
10128			zone->sourceaddr = zone->altxfrsource6;
10129		} else if (!have_xfrsource)
10130			zone->sourceaddr = zone->xfrsource6;
10131		break;
10132	default:
10133		result = ISC_R_NOTIMPLEMENTED;
10134		goto cleanup;
10135	}
10136
10137	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
10138		  DNS_REQUESTOPT_TCP : 0;
10139
10140	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10141		result = add_opt(message, udpsize, reqnsid);
10142		if (result != ISC_R_SUCCESS)
10143			zone_debuglog(zone, me, 1,
10144				      "unable to add opt record: %s",
10145				      dns_result_totext(result));
10146	}
10147
10148	zone_iattach(zone, &dummy);
10149	timeout = 15;
10150	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10151		timeout = 30;
10152	result = dns_request_createvia2(zone->view->requestmgr, message,
10153					&zone->sourceaddr, &zone->masteraddr,
10154					options, key, timeout * 3, timeout,
10155					zone->task, refresh_callback, zone,
10156					&zone->request);
10157	if (result != ISC_R_SUCCESS) {
10158		zone_idetach(&dummy);
10159		zone_debuglog(zone, me, 1,
10160			      "dns_request_createvia2() failed: %s",
10161			      dns_result_totext(result));
10162		goto cleanup;
10163	} else {
10164		if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
10165			inc_stats(zone, dns_zonestatscounter_soaoutv4);
10166		else
10167			inc_stats(zone, dns_zonestatscounter_soaoutv6);
10168	}
10169	cancel = ISC_FALSE;
10170
10171 cleanup:
10172	if (key != NULL)
10173		dns_tsigkey_detach(&key);
10174	if (result != ISC_R_SUCCESS)
10175		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10176	if (message != NULL)
10177		dns_message_destroy(&message);
10178	if (cancel)
10179		cancel_refresh(zone);
10180	isc_event_free(&event);
10181	UNLOCK_ZONE(zone);
10182	dns_zone_idetach(&zone);
10183	return;
10184
10185 skip_master:
10186	if (key != NULL)
10187		dns_tsigkey_detach(&key);
10188	/*
10189	 * Skip to next failed / untried master.
10190	 */
10191	do {
10192		zone->curmaster++;
10193	} while (zone->curmaster < zone->masterscnt &&
10194		 zone->mastersok[zone->curmaster]);
10195	if (zone->curmaster < zone->masterscnt)
10196		goto again;
10197	zone->curmaster = 0;
10198	goto cleanup;
10199}
10200
10201static void
10202ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
10203	const char me[] = "ns_query";
10204	isc_result_t result;
10205	dns_message_t *message = NULL;
10206	isc_netaddr_t masterip;
10207	dns_tsigkey_t *key = NULL;
10208	dns_dbnode_t *node = NULL;
10209	int timeout;
10210	isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
10211	isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10212
10213	REQUIRE(DNS_ZONE_VALID(zone));
10214	REQUIRE(LOCKED_ZONE(zone));
10215	REQUIRE((soardataset != NULL && stub == NULL) ||
10216		(soardataset == NULL && stub != NULL));
10217	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
10218
10219	ENTER;
10220
10221	if (stub == NULL) {
10222		stub = isc_mem_get(zone->mctx, sizeof(*stub));
10223		if (stub == NULL)
10224			goto cleanup;
10225		stub->magic = STUB_MAGIC;
10226		stub->mctx = zone->mctx;
10227		stub->zone = NULL;
10228		stub->db = NULL;
10229		stub->version = NULL;
10230
10231		/*
10232		 * Attach so that the zone won't disappear from under us.
10233		 */
10234		zone_iattach(zone, &stub->zone);
10235
10236		/*
10237		 * If a db exists we will update it, otherwise we create a
10238		 * new one and attach it to the zone once we have the NS
10239		 * RRset and glue.
10240		 */
10241		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10242		if (zone->db != NULL) {
10243			dns_db_attach(zone->db, &stub->db);
10244			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10245		} else {
10246			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10247
10248			INSIST(zone->db_argc >= 1);
10249			result = dns_db_create(zone->mctx, zone->db_argv[0],
10250					       &zone->origin, dns_dbtype_stub,
10251					       zone->rdclass,
10252					       zone->db_argc - 1,
10253					       zone->db_argv + 1,
10254					       &stub->db);
10255			if (result != ISC_R_SUCCESS) {
10256				dns_zone_log(zone, ISC_LOG_ERROR,
10257					     "refreshing stub: "
10258					     "could not create "
10259					     "database: %s",
10260					     dns_result_totext(result));
10261				goto cleanup;
10262			}
10263			dns_db_settask(stub->db, zone->task);
10264		}
10265
10266		result = dns_db_newversion(stub->db, &stub->version);
10267		if (result != ISC_R_SUCCESS) {
10268			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10269				     "dns_db_newversion() failed: %s",
10270				     dns_result_totext(result));
10271			goto cleanup;
10272		}
10273
10274		/*
10275		 * Update SOA record.
10276		 */
10277		result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
10278					 &node);
10279		if (result != ISC_R_SUCCESS) {
10280			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10281				     "dns_db_findnode() failed: %s",
10282				     dns_result_totext(result));
10283			goto cleanup;
10284		}
10285
10286		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
10287					    soardataset, 0, NULL);
10288		dns_db_detachnode(stub->db, &node);
10289		if (result != ISC_R_SUCCESS) {
10290			dns_zone_log(zone, ISC_LOG_INFO,
10291				     "refreshing stub: "
10292				     "dns_db_addrdataset() failed: %s",
10293				     dns_result_totext(result));
10294			goto cleanup;
10295		}
10296	}
10297
10298	/*
10299	 * XXX Optimisation: Create message when zone is setup and reuse.
10300	 */
10301	result = create_query(zone, dns_rdatatype_ns, &message);
10302	INSIST(result == ISC_R_SUCCESS);
10303
10304	INSIST(zone->masterscnt > 0);
10305	INSIST(zone->curmaster < zone->masterscnt);
10306	zone->masteraddr = zone->masters[zone->curmaster];
10307
10308	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10309	/*
10310	 * First, look for a tsig key in the master statement, then
10311	 * try for a server key.
10312	 */
10313	if ((zone->masterkeynames != NULL) &&
10314	    (zone->masterkeynames[zone->curmaster] != NULL)) {
10315		dns_view_t *view = dns_zone_getview(zone);
10316		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10317		result = dns_view_gettsig(view, keyname, &key);
10318		if (result != ISC_R_SUCCESS) {
10319			char namebuf[DNS_NAME_FORMATSIZE];
10320			dns_name_format(keyname, namebuf, sizeof(namebuf));
10321			dns_zone_log(zone, ISC_LOG_ERROR,
10322				     "unable to find key: %s", namebuf);
10323		}
10324	}
10325	if (key == NULL)
10326		(void)dns_view_getpeertsig(zone->view, &masterip, &key);
10327
10328	reqnsid = zone->view->requestnsid;
10329	if (zone->view->peers != NULL) {
10330		dns_peer_t *peer = NULL;
10331		isc_boolean_t edns;
10332		result = dns_peerlist_peerbyaddr(zone->view->peers,
10333						 &masterip, &peer);
10334		if (result == ISC_R_SUCCESS) {
10335			result = dns_peer_getsupportedns(peer, &edns);
10336			if (result == ISC_R_SUCCESS && !edns)
10337				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10338			result = dns_peer_gettransfersource(peer,
10339							    &zone->sourceaddr);
10340			if (result == ISC_R_SUCCESS)
10341				have_xfrsource = ISC_TRUE;
10342			if (zone->view->resolver != NULL)
10343				udpsize =
10344				  dns_resolver_getudpsize(zone->view->resolver);
10345			(void)dns_peer_getudpsize(peer, &udpsize);
10346			(void)dns_peer_getrequestnsid(peer, &reqnsid);
10347		}
10348
10349	}
10350	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10351		result = add_opt(message, udpsize, reqnsid);
10352		if (result != ISC_R_SUCCESS)
10353			zone_debuglog(zone, me, 1,
10354				      "unable to add opt record: %s",
10355				      dns_result_totext(result));
10356	}
10357
10358	/*
10359	 * Always use TCP so that we shouldn't truncate in additional section.
10360	 */
10361	switch (isc_sockaddr_pf(&zone->masteraddr)) {
10362	case PF_INET:
10363		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10364			zone->sourceaddr = zone->altxfrsource4;
10365		else if (!have_xfrsource)
10366			zone->sourceaddr = zone->xfrsource4;
10367		break;
10368	case PF_INET6:
10369		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10370			zone->sourceaddr = zone->altxfrsource6;
10371		else if (!have_xfrsource)
10372			zone->sourceaddr = zone->xfrsource6;
10373		break;
10374	default:
10375		result = ISC_R_NOTIMPLEMENTED;
10376		POST(result);
10377		goto cleanup;
10378	}
10379	timeout = 15;
10380	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10381		timeout = 30;
10382	result = dns_request_createvia2(zone->view->requestmgr, message,
10383					&zone->sourceaddr, &zone->masteraddr,
10384					DNS_REQUESTOPT_TCP, key, timeout * 3,
10385					timeout, zone->task, stub_callback,
10386					stub, &zone->request);
10387	if (result != ISC_R_SUCCESS) {
10388		zone_debuglog(zone, me, 1,
10389			      "dns_request_createvia() failed: %s",
10390			      dns_result_totext(result));
10391		goto cleanup;
10392	}
10393	dns_message_destroy(&message);
10394	goto unlock;
10395
10396 cleanup:
10397	cancel_refresh(zone);
10398	if (stub != NULL) {
10399		stub->magic = 0;
10400		if (stub->version != NULL)
10401			dns_db_closeversion(stub->db, &stub->version,
10402					    ISC_FALSE);
10403		if (stub->db != NULL)
10404			dns_db_detach(&stub->db);
10405		if (stub->zone != NULL)
10406			zone_idetach(&stub->zone);
10407		isc_mem_put(stub->mctx, stub, sizeof(*stub));
10408	}
10409	if (message != NULL)
10410		dns_message_destroy(&message);
10411 unlock:
10412	if (key != NULL)
10413		dns_tsigkey_detach(&key);
10414	return;
10415}
10416
10417/*
10418 * Handle the control event.  Note that although this event causes the zone
10419 * to shut down, it is not a shutdown event in the sense of the task library.
10420 */
10421static void
10422zone_shutdown(isc_task_t *task, isc_event_t *event) {
10423	dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
10424	isc_boolean_t free_needed, linked = ISC_FALSE;
10425
10426	UNUSED(task);
10427	REQUIRE(DNS_ZONE_VALID(zone));
10428	INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
10429	INSIST(isc_refcount_current(&zone->erefs) == 0);
10430
10431	zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
10432
10433	/*
10434	 * Stop things being restarted after we cancel them below.
10435	 */
10436	LOCK_ZONE(zone);
10437	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
10438	UNLOCK_ZONE(zone);
10439
10440	/*
10441	 * If we were waiting for xfrin quota, step out of
10442	 * the queue.
10443	 * If there's no zone manager, we can't be waiting for the
10444	 * xfrin quota
10445	 */
10446	if (zone->zmgr != NULL) {
10447		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10448		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
10449			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
10450					statelink);
10451			linked = ISC_TRUE;
10452			zone->statelist = NULL;
10453		}
10454		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10455	}
10456
10457	/*
10458	 * In task context, no locking required.  See zone_xfrdone().
10459	 */
10460	if (zone->xfr != NULL)
10461		dns_xfrin_shutdown(zone->xfr);
10462
10463	LOCK_ZONE(zone);
10464	if (linked) {
10465		INSIST(zone->irefs > 0);
10466		zone->irefs--;
10467	}
10468	if (zone->request != NULL) {
10469		dns_request_cancel(zone->request);
10470	}
10471
10472	if (zone->readio != NULL)
10473		zonemgr_cancelio(zone->readio);
10474
10475	if (zone->lctx != NULL)
10476		dns_loadctx_cancel(zone->lctx);
10477
10478	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
10479	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10480		if (zone->writeio != NULL)
10481			zonemgr_cancelio(zone->writeio);
10482
10483		if (zone->dctx != NULL)
10484			dns_dumpctx_cancel(zone->dctx);
10485	}
10486
10487	notify_cancel(zone);
10488
10489	forward_cancel(zone);
10490
10491	if (zone->timer != NULL) {
10492		isc_timer_detach(&zone->timer);
10493		INSIST(zone->irefs > 0);
10494		zone->irefs--;
10495	}
10496
10497	if (zone->view != NULL)
10498		dns_view_weakdetach(&zone->view);
10499
10500	/*
10501	 * We have now canceled everything set the flag to allow exit_check()
10502	 * to succeed.	We must not unlock between setting this flag and
10503	 * calling exit_check().
10504	 */
10505	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
10506	free_needed = exit_check(zone);
10507	UNLOCK_ZONE(zone);
10508	if (free_needed)
10509		zone_free(zone);
10510}
10511
10512static void
10513zone_timer(isc_task_t *task, isc_event_t *event) {
10514	const char me[] = "zone_timer";
10515	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
10516
10517	UNUSED(task);
10518	REQUIRE(DNS_ZONE_VALID(zone));
10519
10520	ENTER;
10521
10522	zone_maintenance(zone);
10523
10524	isc_event_free(&event);
10525}
10526
10527static void
10528zone_settimer(dns_zone_t *zone, isc_time_t *now) {
10529	const char me[] = "zone_settimer";
10530	isc_time_t next;
10531	isc_result_t result;
10532
10533	ENTER;
10534	REQUIRE(DNS_ZONE_VALID(zone));
10535	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10536		return;
10537
10538	isc_time_settoepoch(&next);
10539
10540	switch (zone->type) {
10541	case dns_zone_master:
10542		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10543			next = zone->notifytime;
10544		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10545		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10546			INSIST(!isc_time_isepoch(&zone->dumptime));
10547			if (isc_time_isepoch(&next) ||
10548			    isc_time_compare(&zone->dumptime, &next) < 0)
10549				next = zone->dumptime;
10550		}
10551		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
10552		    !isc_time_isepoch(&zone->refreshkeytime)) {
10553			if (isc_time_isepoch(&next) ||
10554			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
10555				next = zone->refreshkeytime;
10556		}
10557		if (!isc_time_isepoch(&zone->resigntime)) {
10558			if (isc_time_isepoch(&next) ||
10559			    isc_time_compare(&zone->resigntime, &next) < 0)
10560				next = zone->resigntime;
10561		}
10562		if (!isc_time_isepoch(&zone->keywarntime)) {
10563			if (isc_time_isepoch(&next) ||
10564			    isc_time_compare(&zone->keywarntime, &next) < 0)
10565				next = zone->keywarntime;
10566		}
10567		if (!isc_time_isepoch(&zone->signingtime)) {
10568			if (isc_time_isepoch(&next) ||
10569			    isc_time_compare(&zone->signingtime, &next) < 0)
10570				next = zone->signingtime;
10571		}
10572		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
10573			if (isc_time_isepoch(&next) ||
10574			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
10575				next = zone->nsec3chaintime;
10576		}
10577		break;
10578
10579	case dns_zone_slave:
10580		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10581			next = zone->notifytime;
10582		/*FALLTHROUGH*/
10583
10584	case dns_zone_stub:
10585		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
10586		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
10587		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
10588		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
10589			INSIST(!isc_time_isepoch(&zone->refreshtime));
10590			if (isc_time_isepoch(&next) ||
10591			    isc_time_compare(&zone->refreshtime, &next) < 0)
10592				next = zone->refreshtime;
10593		}
10594		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10595			INSIST(!isc_time_isepoch(&zone->expiretime));
10596			if (isc_time_isepoch(&next) ||
10597			    isc_time_compare(&zone->expiretime, &next) < 0)
10598				next = zone->expiretime;
10599		}
10600		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10601		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10602			INSIST(!isc_time_isepoch(&zone->dumptime));
10603			if (isc_time_isepoch(&next) ||
10604			    isc_time_compare(&zone->dumptime, &next) < 0)
10605				next = zone->dumptime;
10606		}
10607		break;
10608
10609	case dns_zone_key:
10610		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10611		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10612			INSIST(!isc_time_isepoch(&zone->dumptime));
10613			if (isc_time_isepoch(&next) ||
10614			    isc_time_compare(&zone->dumptime, &next) < 0)
10615				next = zone->dumptime;
10616		}
10617		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10618			if (isc_time_isepoch(&next) ||
10619			    (!isc_time_isepoch(&zone->refreshkeytime) &&
10620			    isc_time_compare(&zone->refreshkeytime, &next) < 0))
10621				next = zone->refreshkeytime;
10622		}
10623		break;
10624
10625	default:
10626		break;
10627	}
10628
10629	if (isc_time_isepoch(&next)) {
10630		zone_debuglog(zone, me, 10, "settimer inactive");
10631		result = isc_timer_reset(zone->timer, isc_timertype_inactive,
10632					  NULL, NULL, ISC_TRUE);
10633		if (result != ISC_R_SUCCESS)
10634			dns_zone_log(zone, ISC_LOG_ERROR,
10635				     "could not deactivate zone timer: %s",
10636				     isc_result_totext(result));
10637	} else {
10638		if (isc_time_compare(&next, now) <= 0)
10639			next = *now;
10640		result = isc_timer_reset(zone->timer, isc_timertype_once,
10641					 &next, NULL, ISC_TRUE);
10642		if (result != ISC_R_SUCCESS)
10643			dns_zone_log(zone, ISC_LOG_ERROR,
10644				     "could not reset zone timer: %s",
10645				     isc_result_totext(result));
10646	}
10647}
10648
10649static void
10650cancel_refresh(dns_zone_t *zone) {
10651	const char me[] = "cancel_refresh";
10652	isc_time_t now;
10653
10654	/*
10655	 * 'zone' locked by caller.
10656	 */
10657
10658	REQUIRE(DNS_ZONE_VALID(zone));
10659	REQUIRE(LOCKED_ZONE(zone));
10660
10661	ENTER;
10662
10663	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10664	TIME_NOW(&now);
10665	zone_settimer(zone, &now);
10666}
10667
10668static isc_result_t
10669notify_createmessage(dns_zone_t *zone, unsigned int flags,
10670		     dns_message_t **messagep)
10671{
10672	dns_db_t *zonedb = NULL;
10673	dns_dbnode_t *node = NULL;
10674	dns_dbversion_t *version = NULL;
10675	dns_message_t *message = NULL;
10676	dns_rdataset_t rdataset;
10677	dns_rdata_t rdata = DNS_RDATA_INIT;
10678
10679	dns_name_t *tempname = NULL;
10680	dns_rdata_t *temprdata = NULL;
10681	dns_rdatalist_t *temprdatalist = NULL;
10682	dns_rdataset_t *temprdataset = NULL;
10683
10684	isc_result_t result;
10685	isc_region_t r;
10686	isc_buffer_t *b = NULL;
10687
10688	REQUIRE(DNS_ZONE_VALID(zone));
10689	REQUIRE(messagep != NULL && *messagep == NULL);
10690
10691	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10692				    &message);
10693	if (result != ISC_R_SUCCESS)
10694		return (result);
10695
10696	message->opcode = dns_opcode_notify;
10697	message->flags |= DNS_MESSAGEFLAG_AA;
10698	message->rdclass = zone->rdclass;
10699
10700	result = dns_message_gettempname(message, &tempname);
10701	if (result != ISC_R_SUCCESS)
10702		goto cleanup;
10703
10704	result = dns_message_gettemprdataset(message, &temprdataset);
10705	if (result != ISC_R_SUCCESS)
10706		goto cleanup;
10707
10708	/*
10709	 * Make question.
10710	 */
10711	dns_name_init(tempname, NULL);
10712	dns_name_clone(&zone->origin, tempname);
10713	dns_rdataset_init(temprdataset);
10714	dns_rdataset_makequestion(temprdataset, zone->rdclass,
10715				  dns_rdatatype_soa);
10716	ISC_LIST_APPEND(tempname->list, temprdataset, link);
10717	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
10718	tempname = NULL;
10719	temprdataset = NULL;
10720
10721	if ((flags & DNS_NOTIFY_NOSOA) != 0)
10722		goto done;
10723
10724	result = dns_message_gettempname(message, &tempname);
10725	if (result != ISC_R_SUCCESS)
10726		goto soa_cleanup;
10727	result = dns_message_gettemprdata(message, &temprdata);
10728	if (result != ISC_R_SUCCESS)
10729		goto soa_cleanup;
10730	result = dns_message_gettemprdataset(message, &temprdataset);
10731	if (result != ISC_R_SUCCESS)
10732		goto soa_cleanup;
10733	result = dns_message_gettemprdatalist(message, &temprdatalist);
10734	if (result != ISC_R_SUCCESS)
10735		goto soa_cleanup;
10736
10737	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10738	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
10739	dns_db_attach(zone->db, &zonedb);
10740	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10741
10742	dns_name_init(tempname, NULL);
10743	dns_name_clone(&zone->origin, tempname);
10744	dns_db_currentversion(zonedb, &version);
10745	result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
10746	if (result != ISC_R_SUCCESS)
10747		goto soa_cleanup;
10748
10749	dns_rdataset_init(&rdataset);
10750	result = dns_db_findrdataset(zonedb, node, version,
10751				     dns_rdatatype_soa,
10752				     dns_rdatatype_none, 0, &rdataset,
10753				     NULL);
10754	if (result != ISC_R_SUCCESS)
10755		goto soa_cleanup;
10756	result = dns_rdataset_first(&rdataset);
10757	if (result != ISC_R_SUCCESS)
10758		goto soa_cleanup;
10759	dns_rdataset_current(&rdataset, &rdata);
10760	dns_rdata_toregion(&rdata, &r);
10761	result = isc_buffer_allocate(zone->mctx, &b, r.length);
10762	if (result != ISC_R_SUCCESS)
10763		goto soa_cleanup;
10764	isc_buffer_putmem(b, r.base, r.length);
10765	isc_buffer_usedregion(b, &r);
10766	dns_rdata_init(temprdata);
10767	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
10768	dns_message_takebuffer(message, &b);
10769	result = dns_rdataset_next(&rdataset);
10770	dns_rdataset_disassociate(&rdataset);
10771	if (result != ISC_R_NOMORE)
10772		goto soa_cleanup;
10773	temprdatalist->rdclass = rdata.rdclass;
10774	temprdatalist->type = rdata.type;
10775	temprdatalist->covers = 0;
10776	temprdatalist->ttl = rdataset.ttl;
10777	ISC_LIST_INIT(temprdatalist->rdata);
10778	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
10779
10780	dns_rdataset_init(temprdataset);
10781	result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
10782	if (result != ISC_R_SUCCESS)
10783		goto soa_cleanup;
10784
10785	ISC_LIST_APPEND(tempname->list, temprdataset, link);
10786	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
10787	temprdatalist = NULL;
10788	temprdataset = NULL;
10789	temprdata = NULL;
10790	tempname = NULL;
10791
10792 soa_cleanup:
10793	if (node != NULL)
10794		dns_db_detachnode(zonedb, &node);
10795	if (version != NULL)
10796		dns_db_closeversion(zonedb, &version, ISC_FALSE);
10797	if (zonedb != NULL)
10798		dns_db_detach(&zonedb);
10799	if (tempname != NULL)
10800		dns_message_puttempname(message, &tempname);
10801	if (temprdata != NULL)
10802		dns_message_puttemprdata(message, &temprdata);
10803	if (temprdataset != NULL)
10804		dns_message_puttemprdataset(message, &temprdataset);
10805	if (temprdatalist != NULL)
10806		dns_message_puttemprdatalist(message, &temprdatalist);
10807
10808 done:
10809	*messagep = message;
10810	return (ISC_R_SUCCESS);
10811
10812 cleanup:
10813	if (tempname != NULL)
10814		dns_message_puttempname(message, &tempname);
10815	if (temprdataset != NULL)
10816		dns_message_puttemprdataset(message, &temprdataset);
10817	dns_message_destroy(&message);
10818	return (result);
10819}
10820
10821isc_result_t
10822dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
10823		       dns_message_t *msg)
10824{
10825	unsigned int i;
10826	dns_rdata_soa_t soa;
10827	dns_rdataset_t *rdataset = NULL;
10828	dns_rdata_t rdata = DNS_RDATA_INIT;
10829	isc_result_t result;
10830	char fromtext[ISC_SOCKADDR_FORMATSIZE];
10831	int match = 0;
10832	isc_netaddr_t netaddr;
10833	isc_sockaddr_t local, remote;
10834
10835	REQUIRE(DNS_ZONE_VALID(zone));
10836
10837	/*
10838	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
10839	 * ROLLOVER.
10840	 *
10841	 * SOA:	RFC1996
10842	 * Check that 'from' is a valid notify source, (zone->masters).
10843	 *	Return DNS_R_REFUSED if not.
10844	 *
10845	 * If the notify message contains a serial number check it
10846	 * against the zones serial and return if <= current serial
10847	 *
10848	 * If a refresh check is progress, if so just record the
10849	 * fact we received a NOTIFY and from where and return.
10850	 * We will perform a new refresh check when the current one
10851	 * completes. Return ISC_R_SUCCESS.
10852	 *
10853	 * Otherwise initiate a refresh check using 'from' as the
10854	 * first address to check.  Return ISC_R_SUCCESS.
10855	 */
10856
10857	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
10858
10859	/*
10860	 *  We only handle NOTIFY (SOA) at the present.
10861	 */
10862	LOCK_ZONE(zone);
10863	if (isc_sockaddr_pf(from) == PF_INET)
10864		inc_stats(zone, dns_zonestatscounter_notifyinv4);
10865	else
10866		inc_stats(zone, dns_zonestatscounter_notifyinv6);
10867	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
10868	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
10869				 dns_rdatatype_soa, dns_rdatatype_none,
10870				 NULL, NULL) != ISC_R_SUCCESS) {
10871		UNLOCK_ZONE(zone);
10872		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
10873			dns_zone_log(zone, ISC_LOG_NOTICE,
10874				     "NOTIFY with no "
10875				     "question section from: %s", fromtext);
10876			return (DNS_R_FORMERR);
10877		}
10878		dns_zone_log(zone, ISC_LOG_NOTICE,
10879			     "NOTIFY zone does not match");
10880		return (DNS_R_NOTIMP);
10881	}
10882
10883	/*
10884	 * If we are a master zone just succeed.
10885	 */
10886	if (zone->type == dns_zone_master) {
10887		UNLOCK_ZONE(zone);
10888		return (ISC_R_SUCCESS);
10889	}
10890
10891	isc_netaddr_fromsockaddr(&netaddr, from);
10892	for (i = 0; i < zone->masterscnt; i++) {
10893		if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
10894			break;
10895		if (zone->view->aclenv.match_mapped &&
10896		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
10897		    isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
10898			isc_netaddr_t na1, na2;
10899			isc_netaddr_fromv4mapped(&na1, &netaddr);
10900			isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
10901			if (isc_netaddr_equal(&na1, &na2))
10902				break;
10903		}
10904	}
10905
10906	/*
10907	 * Accept notify requests from non masters if they are on
10908	 * 'zone->notify_acl'.
10909	 */
10910	if (i >= zone->masterscnt && zone->notify_acl != NULL &&
10911	    dns_acl_match(&netaddr, NULL, zone->notify_acl,
10912			  &zone->view->aclenv,
10913			  &match, NULL) == ISC_R_SUCCESS &&
10914	    match > 0)
10915	{
10916		/* Accept notify. */
10917	} else if (i >= zone->masterscnt) {
10918		UNLOCK_ZONE(zone);
10919		dns_zone_log(zone, ISC_LOG_INFO,
10920			     "refused notify from non-master: %s", fromtext);
10921		inc_stats(zone, dns_zonestatscounter_notifyrej);
10922		return (DNS_R_REFUSED);
10923	}
10924
10925	/*
10926	 * If the zone is loaded and there are answers check the serial
10927	 * to see if we need to do a refresh.  Do not worry about this
10928	 * check if we are a dialup zone as we use the notify request
10929	 * to trigger a refresh check.
10930	 */
10931	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
10932	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10933	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
10934		result = dns_message_findname(msg, DNS_SECTION_ANSWER,
10935					      &zone->origin,
10936					      dns_rdatatype_soa,
10937					      dns_rdatatype_none, NULL,
10938					      &rdataset);
10939		if (result == ISC_R_SUCCESS)
10940			result = dns_rdataset_first(rdataset);
10941		if (result == ISC_R_SUCCESS) {
10942			isc_uint32_t serial = 0, oldserial;
10943
10944			dns_rdataset_current(rdataset, &rdata);
10945			result = dns_rdata_tostruct(&rdata, &soa, NULL);
10946			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10947			serial = soa.serial;
10948			/*
10949			 * The following should safely be performed without DB
10950			 * lock and succeed in this context.
10951			 */
10952			result = zone_get_from_db(zone, zone->db, NULL, NULL,
10953						  &oldserial, NULL, NULL, NULL,
10954						  NULL, NULL);
10955			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10956			if (isc_serial_le(serial, oldserial)) {
10957				dns_zone_log(zone,
10958					     ISC_LOG_INFO,
10959					     "notify from %s: "
10960					     "zone is up to date",
10961					     fromtext);
10962				UNLOCK_ZONE(zone);
10963				return (ISC_R_SUCCESS);
10964			}
10965		}
10966	}
10967
10968	/*
10969	 * If we got this far and there was a refresh in progress just
10970	 * let it complete.  Record where we got the notify from so we
10971	 * can perform a refresh check when the current one completes
10972	 */
10973	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
10974		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10975		zone->notifyfrom = *from;
10976		UNLOCK_ZONE(zone);
10977		dns_zone_log(zone, ISC_LOG_INFO,
10978			     "notify from %s: refresh in progress, "
10979			     "refresh check queued",
10980			     fromtext);
10981		return (ISC_R_SUCCESS);
10982	}
10983	zone->notifyfrom = *from;
10984	local = zone->masteraddr;
10985	remote = zone->sourceaddr;
10986	UNLOCK_ZONE(zone);
10987	dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
10988	dns_zone_refresh(zone);
10989	return (ISC_R_SUCCESS);
10990}
10991
10992void
10993dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
10994
10995	REQUIRE(DNS_ZONE_VALID(zone));
10996
10997	LOCK_ZONE(zone);
10998	if (zone->notify_acl != NULL)
10999		dns_acl_detach(&zone->notify_acl);
11000	dns_acl_attach(acl, &zone->notify_acl);
11001	UNLOCK_ZONE(zone);
11002}
11003
11004void
11005dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
11006
11007	REQUIRE(DNS_ZONE_VALID(zone));
11008
11009	LOCK_ZONE(zone);
11010	if (zone->query_acl != NULL)
11011		dns_acl_detach(&zone->query_acl);
11012	dns_acl_attach(acl, &zone->query_acl);
11013	UNLOCK_ZONE(zone);
11014}
11015
11016void
11017dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
11018
11019	REQUIRE(DNS_ZONE_VALID(zone));
11020
11021	LOCK_ZONE(zone);
11022	if (zone->queryon_acl != NULL)
11023		dns_acl_detach(&zone->queryon_acl);
11024	dns_acl_attach(acl, &zone->queryon_acl);
11025	UNLOCK_ZONE(zone);
11026}
11027
11028void
11029dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
11030
11031	REQUIRE(DNS_ZONE_VALID(zone));
11032
11033	LOCK_ZONE(zone);
11034	if (zone->update_acl != NULL)
11035		dns_acl_detach(&zone->update_acl);
11036	dns_acl_attach(acl, &zone->update_acl);
11037	UNLOCK_ZONE(zone);
11038}
11039
11040void
11041dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
11042
11043	REQUIRE(DNS_ZONE_VALID(zone));
11044
11045	LOCK_ZONE(zone);
11046	if (zone->forward_acl != NULL)
11047		dns_acl_detach(&zone->forward_acl);
11048	dns_acl_attach(acl, &zone->forward_acl);
11049	UNLOCK_ZONE(zone);
11050}
11051
11052void
11053dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
11054
11055	REQUIRE(DNS_ZONE_VALID(zone));
11056
11057	LOCK_ZONE(zone);
11058	if (zone->xfr_acl != NULL)
11059		dns_acl_detach(&zone->xfr_acl);
11060	dns_acl_attach(acl, &zone->xfr_acl);
11061	UNLOCK_ZONE(zone);
11062}
11063
11064dns_acl_t *
11065dns_zone_getnotifyacl(dns_zone_t *zone) {
11066
11067	REQUIRE(DNS_ZONE_VALID(zone));
11068
11069	return (zone->notify_acl);
11070}
11071
11072dns_acl_t *
11073dns_zone_getqueryacl(dns_zone_t *zone) {
11074
11075	REQUIRE(DNS_ZONE_VALID(zone));
11076
11077	return (zone->query_acl);
11078}
11079
11080dns_acl_t *
11081dns_zone_getqueryonacl(dns_zone_t *zone) {
11082
11083	REQUIRE(DNS_ZONE_VALID(zone));
11084
11085	return (zone->queryon_acl);
11086}
11087
11088dns_acl_t *
11089dns_zone_getupdateacl(dns_zone_t *zone) {
11090
11091	REQUIRE(DNS_ZONE_VALID(zone));
11092
11093	return (zone->update_acl);
11094}
11095
11096dns_acl_t *
11097dns_zone_getforwardacl(dns_zone_t *zone) {
11098
11099	REQUIRE(DNS_ZONE_VALID(zone));
11100
11101	return (zone->forward_acl);
11102}
11103
11104dns_acl_t *
11105dns_zone_getxfracl(dns_zone_t *zone) {
11106
11107	REQUIRE(DNS_ZONE_VALID(zone));
11108
11109	return (zone->xfr_acl);
11110}
11111
11112void
11113dns_zone_clearupdateacl(dns_zone_t *zone) {
11114
11115	REQUIRE(DNS_ZONE_VALID(zone));
11116
11117	LOCK_ZONE(zone);
11118	if (zone->update_acl != NULL)
11119		dns_acl_detach(&zone->update_acl);
11120	UNLOCK_ZONE(zone);
11121}
11122
11123void
11124dns_zone_clearforwardacl(dns_zone_t *zone) {
11125
11126	REQUIRE(DNS_ZONE_VALID(zone));
11127
11128	LOCK_ZONE(zone);
11129	if (zone->forward_acl != NULL)
11130		dns_acl_detach(&zone->forward_acl);
11131	UNLOCK_ZONE(zone);
11132}
11133
11134void
11135dns_zone_clearnotifyacl(dns_zone_t *zone) {
11136
11137	REQUIRE(DNS_ZONE_VALID(zone));
11138
11139	LOCK_ZONE(zone);
11140	if (zone->notify_acl != NULL)
11141		dns_acl_detach(&zone->notify_acl);
11142	UNLOCK_ZONE(zone);
11143}
11144
11145void
11146dns_zone_clearqueryacl(dns_zone_t *zone) {
11147
11148	REQUIRE(DNS_ZONE_VALID(zone));
11149
11150	LOCK_ZONE(zone);
11151	if (zone->query_acl != NULL)
11152		dns_acl_detach(&zone->query_acl);
11153	UNLOCK_ZONE(zone);
11154}
11155
11156void
11157dns_zone_clearqueryonacl(dns_zone_t *zone) {
11158
11159	REQUIRE(DNS_ZONE_VALID(zone));
11160
11161	LOCK_ZONE(zone);
11162	if (zone->queryon_acl != NULL)
11163		dns_acl_detach(&zone->queryon_acl);
11164	UNLOCK_ZONE(zone);
11165}
11166
11167void
11168dns_zone_clearxfracl(dns_zone_t *zone) {
11169
11170	REQUIRE(DNS_ZONE_VALID(zone));
11171
11172	LOCK_ZONE(zone);
11173	if (zone->xfr_acl != NULL)
11174		dns_acl_detach(&zone->xfr_acl);
11175	UNLOCK_ZONE(zone);
11176}
11177
11178isc_boolean_t
11179dns_zone_getupdatedisabled(dns_zone_t *zone) {
11180	REQUIRE(DNS_ZONE_VALID(zone));
11181	return (zone->update_disabled);
11182
11183}
11184
11185void
11186dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
11187	REQUIRE(DNS_ZONE_VALID(zone));
11188	zone->update_disabled = state;
11189}
11190
11191isc_boolean_t
11192dns_zone_getzeronosoattl(dns_zone_t *zone) {
11193	REQUIRE(DNS_ZONE_VALID(zone));
11194	return (zone->zero_no_soa_ttl);
11195
11196}
11197
11198void
11199dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
11200	REQUIRE(DNS_ZONE_VALID(zone));
11201	zone->zero_no_soa_ttl = state;
11202}
11203
11204void
11205dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
11206
11207	REQUIRE(DNS_ZONE_VALID(zone));
11208
11209	zone->check_names = severity;
11210}
11211
11212dns_severity_t
11213dns_zone_getchecknames(dns_zone_t *zone) {
11214
11215	REQUIRE(DNS_ZONE_VALID(zone));
11216
11217	return (zone->check_names);
11218}
11219
11220void
11221dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
11222
11223	REQUIRE(DNS_ZONE_VALID(zone));
11224
11225	zone->journalsize = size;
11226}
11227
11228isc_int32_t
11229dns_zone_getjournalsize(dns_zone_t *zone) {
11230
11231	REQUIRE(DNS_ZONE_VALID(zone));
11232
11233	return (zone->journalsize);
11234}
11235
11236static void
11237zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
11238	isc_result_t result = ISC_R_FAILURE;
11239	isc_buffer_t buffer;
11240
11241	REQUIRE(buf != NULL);
11242	REQUIRE(length > 1U);
11243
11244	/*
11245	 * Leave space for terminating '\0'.
11246	 */
11247	isc_buffer_init(&buffer, buf, length - 1);
11248	if (dns_name_dynamic(&zone->origin))
11249		result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11250	if (result != ISC_R_SUCCESS &&
11251	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11252		isc_buffer_putstr(&buffer, "<UNKNOWN>");
11253
11254	if (isc_buffer_availablelength(&buffer) > 0)
11255		isc_buffer_putstr(&buffer, "/");
11256	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
11257
11258	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
11259	    strcmp(zone->view->name, "_default") != 0 &&
11260	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
11261		isc_buffer_putstr(&buffer, "/");
11262		isc_buffer_putstr(&buffer, zone->view->name);
11263	}
11264
11265	buf[isc_buffer_usedlength(&buffer)] = '\0';
11266}
11267
11268static void
11269zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
11270	isc_result_t result = ISC_R_FAILURE;
11271	isc_buffer_t buffer;
11272
11273	REQUIRE(buf != NULL);
11274	REQUIRE(length > 1U);
11275
11276	/*
11277	 * Leave space for terminating '\0'.
11278	 */
11279	isc_buffer_init(&buffer, buf, length - 1);
11280	if (dns_name_dynamic(&zone->origin))
11281		result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11282	if (result != ISC_R_SUCCESS &&
11283	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11284		isc_buffer_putstr(&buffer, "<UNKNOWN>");
11285
11286	buf[isc_buffer_usedlength(&buffer)] = '\0';
11287}
11288
11289static void
11290zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
11291	isc_buffer_t buffer;
11292
11293	REQUIRE(buf != NULL);
11294	REQUIRE(length > 1U);
11295
11296	/*
11297	 * Leave space for terminating '\0'.
11298	 */
11299	isc_buffer_init(&buffer, buf, length - 1);
11300	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
11301
11302	buf[isc_buffer_usedlength(&buffer)] = '\0';
11303}
11304
11305static void
11306zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
11307	isc_buffer_t buffer;
11308
11309	REQUIRE(buf != NULL);
11310	REQUIRE(length > 1U);
11311
11312
11313	/*
11314	 * Leave space for terminating '\0'.
11315	 */
11316	isc_buffer_init(&buffer, buf, length - 1);
11317
11318	if (zone->view == NULL) {
11319		isc_buffer_putstr(&buffer, "_none");
11320	} else if (strlen(zone->view->name)
11321		   < isc_buffer_availablelength(&buffer)) {
11322		isc_buffer_putstr(&buffer, zone->view->name);
11323	} else {
11324		isc_buffer_putstr(&buffer, "_toolong");
11325	}
11326
11327	buf[isc_buffer_usedlength(&buffer)] = '\0';
11328}
11329
11330void
11331dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
11332	REQUIRE(DNS_ZONE_VALID(zone));
11333	REQUIRE(buf != NULL);
11334	zone_namerd_tostr(zone, buf, length);
11335}
11336
11337static void
11338notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11339	va_list ap;
11340	char message[4096];
11341
11342	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11343		return;
11344
11345	va_start(ap, fmt);
11346	vsnprintf(message, sizeof(message), fmt, ap);
11347	va_end(ap);
11348	isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
11349		      level, "zone %s: %s", zone->strnamerd, message);
11350}
11351
11352void
11353dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
11354	      int level, const char *fmt, ...) {
11355	va_list ap;
11356	char message[4096];
11357
11358	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11359		return;
11360
11361	va_start(ap, fmt);
11362	vsnprintf(message, sizeof(message), fmt, ap);
11363	va_end(ap);
11364	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
11365		      level, "%s %s: %s", (zone->type == dns_zone_key) ?
11366		      "managed-keys-zone" : "zone", zone->strnamerd, message);
11367}
11368
11369void
11370dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11371	va_list ap;
11372	char message[4096];
11373
11374	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11375		return;
11376
11377	va_start(ap, fmt);
11378	vsnprintf(message, sizeof(message), fmt, ap);
11379	va_end(ap);
11380	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11381		      level, "%s %s: %s", (zone->type == dns_zone_key) ?
11382		      "managed-keys-zone" : "zone", zone->strnamerd, message);
11383}
11384
11385static void
11386zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
11387	      const char *fmt, ...)
11388{
11389	va_list ap;
11390	char message[4096];
11391	int level = ISC_LOG_DEBUG(debuglevel);
11392
11393	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11394		return;
11395
11396	va_start(ap, fmt);
11397	vsnprintf(message, sizeof(message), fmt, ap);
11398	va_end(ap);
11399	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11400		      level, "%s: %s %s: %s", me, zone->type != dns_zone_key ?
11401		      "zone" : "managed-keys-zone", zone->strnamerd, message);
11402}
11403
11404static int
11405message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
11406{
11407	isc_result_t result;
11408	dns_name_t *name;
11409	dns_rdataset_t *curr;
11410	int count = 0;
11411
11412	result = dns_message_firstname(msg, section);
11413	while (result == ISC_R_SUCCESS) {
11414		name = NULL;
11415		dns_message_currentname(msg, section, &name);
11416
11417		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
11418		     curr = ISC_LIST_PREV(curr, link)) {
11419			if (curr->type == type)
11420				count++;
11421		}
11422		result = dns_message_nextname(msg, section);
11423	}
11424
11425	return (count);
11426}
11427
11428void
11429dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
11430	REQUIRE(DNS_ZONE_VALID(zone));
11431
11432	zone->maxxfrin = maxxfrin;
11433}
11434
11435isc_uint32_t
11436dns_zone_getmaxxfrin(dns_zone_t *zone) {
11437	REQUIRE(DNS_ZONE_VALID(zone));
11438
11439	return (zone->maxxfrin);
11440}
11441
11442void
11443dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
11444	REQUIRE(DNS_ZONE_VALID(zone));
11445	zone->maxxfrout = maxxfrout;
11446}
11447
11448isc_uint32_t
11449dns_zone_getmaxxfrout(dns_zone_t *zone) {
11450	REQUIRE(DNS_ZONE_VALID(zone));
11451
11452	return (zone->maxxfrout);
11453}
11454
11455dns_zonetype_t
11456dns_zone_gettype(dns_zone_t *zone) {
11457	REQUIRE(DNS_ZONE_VALID(zone));
11458
11459	return (zone->type);
11460}
11461
11462dns_name_t *
11463dns_zone_getorigin(dns_zone_t *zone) {
11464	REQUIRE(DNS_ZONE_VALID(zone));
11465
11466	return (&zone->origin);
11467}
11468
11469void
11470dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
11471	REQUIRE(DNS_ZONE_VALID(zone));
11472
11473	LOCK_ZONE(zone);
11474	if (zone->task != NULL)
11475		isc_task_detach(&zone->task);
11476	isc_task_attach(task, &zone->task);
11477	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11478	if (zone->db != NULL)
11479		dns_db_settask(zone->db, zone->task);
11480	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11481	UNLOCK_ZONE(zone);
11482}
11483
11484void
11485dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
11486	REQUIRE(DNS_ZONE_VALID(zone));
11487	isc_task_attach(zone->task, target);
11488}
11489
11490void
11491dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
11492	REQUIRE(DNS_ZONE_VALID(zone));
11493
11494	if (idlein == 0)
11495		idlein = DNS_DEFAULT_IDLEIN;
11496	zone->idlein = idlein;
11497}
11498
11499isc_uint32_t
11500dns_zone_getidlein(dns_zone_t *zone) {
11501	REQUIRE(DNS_ZONE_VALID(zone));
11502
11503	return (zone->idlein);
11504}
11505
11506void
11507dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
11508	REQUIRE(DNS_ZONE_VALID(zone));
11509
11510	zone->idleout = idleout;
11511}
11512
11513isc_uint32_t
11514dns_zone_getidleout(dns_zone_t *zone) {
11515	REQUIRE(DNS_ZONE_VALID(zone));
11516
11517	return (zone->idleout);
11518}
11519
11520static void
11521notify_done(isc_task_t *task, isc_event_t *event) {
11522	dns_requestevent_t *revent = (dns_requestevent_t *)event;
11523	dns_notify_t *notify;
11524	isc_result_t result;
11525	dns_message_t *message = NULL;
11526	isc_buffer_t buf;
11527	char rcode[128];
11528	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
11529
11530	UNUSED(task);
11531
11532	notify = event->ev_arg;
11533	REQUIRE(DNS_NOTIFY_VALID(notify));
11534	INSIST(task == notify->zone->task);
11535
11536	isc_buffer_init(&buf, rcode, sizeof(rcode));
11537	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
11538
11539	result = revent->result;
11540	if (result == ISC_R_SUCCESS)
11541		result = dns_message_create(notify->zone->mctx,
11542					    DNS_MESSAGE_INTENTPARSE, &message);
11543	if (result == ISC_R_SUCCESS)
11544		result = dns_request_getresponse(revent->request, message,
11545					DNS_MESSAGEPARSE_PRESERVEORDER);
11546	if (result == ISC_R_SUCCESS)
11547		result = dns_rcode_totext(message->rcode, &buf);
11548	if (result == ISC_R_SUCCESS)
11549		notify_log(notify->zone, ISC_LOG_DEBUG(3),
11550			   "notify response from %s: %.*s",
11551			   addrbuf, (int)buf.used, rcode);
11552	else
11553		notify_log(notify->zone, ISC_LOG_DEBUG(2),
11554			   "notify to %s failed: %s", addrbuf,
11555			   dns_result_totext(result));
11556
11557	/*
11558	 * Old bind's return formerr if they see a soa record.	Retry w/o
11559	 * the soa if we see a formerr and had sent a SOA.
11560	 */
11561	isc_event_free(&event);
11562	if (message != NULL && message->rcode == dns_rcode_formerr &&
11563	    (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
11564		notify->flags |= DNS_NOTIFY_NOSOA;
11565		dns_request_destroy(&notify->request);
11566		result = notify_send_queue(notify);
11567		if (result != ISC_R_SUCCESS)
11568			notify_destroy(notify, ISC_FALSE);
11569	} else {
11570		if (result == ISC_R_TIMEDOUT)
11571			notify_log(notify->zone, ISC_LOG_DEBUG(1),
11572				   "notify to %s: retries exceeded", addrbuf);
11573		notify_destroy(notify, ISC_FALSE);
11574	}
11575	if (message != NULL)
11576		dns_message_destroy(&message);
11577}
11578
11579isc_result_t
11580dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11581	isc_result_t result;
11582
11583	REQUIRE(DNS_ZONE_VALID(zone));
11584	LOCK_ZONE(zone);
11585	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11586	result = zone_replacedb(zone, db, dump);
11587	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11588	UNLOCK_ZONE(zone);
11589	return (result);
11590}
11591
11592static isc_result_t
11593zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11594	dns_dbversion_t *ver;
11595	isc_result_t result;
11596	unsigned int soacount = 0;
11597	unsigned int nscount = 0;
11598
11599	/*
11600	 * 'zone' and 'zonedb' locked by caller.
11601	 */
11602	REQUIRE(DNS_ZONE_VALID(zone));
11603	REQUIRE(LOCKED_ZONE(zone));
11604
11605	result = zone_get_from_db(zone, db, &nscount, &soacount,
11606				  NULL, NULL, NULL, NULL, NULL, NULL);
11607	if (result == ISC_R_SUCCESS) {
11608		if (soacount != 1) {
11609			dns_zone_log(zone, ISC_LOG_ERROR,
11610				     "has %d SOA records", soacount);
11611			result = DNS_R_BADZONE;
11612		}
11613		if (nscount == 0 && zone->type != dns_zone_key) {
11614			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
11615			result = DNS_R_BADZONE;
11616		}
11617		if (result != ISC_R_SUCCESS)
11618			return (result);
11619	} else {
11620		dns_zone_log(zone, ISC_LOG_ERROR,
11621			    "retrieving SOA and NS records failed: %s",
11622			    dns_result_totext(result));
11623		return (result);
11624	}
11625
11626	result = check_nsec3param(zone, db);
11627	if (result != ISC_R_SUCCESS)
11628		return (result);
11629
11630	ver = NULL;
11631	dns_db_currentversion(db, &ver);
11632
11633	/*
11634	 * The initial version of a slave zone is always dumped;
11635	 * subsequent versions may be journaled instead if this
11636	 * is enabled in the configuration.
11637	 */
11638	if (zone->db != NULL && zone->journal != NULL &&
11639	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
11640	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
11641		isc_uint32_t serial, oldserial;
11642
11643		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
11644
11645		result = dns_db_getsoaserial(db, ver, &serial);
11646		if (result != ISC_R_SUCCESS) {
11647			dns_zone_log(zone, ISC_LOG_ERROR,
11648				     "ixfr-from-differences: unable to get "
11649				     "new serial");
11650			goto fail;
11651		}
11652
11653		/*
11654		 * This is checked in zone_postload() for master zones.
11655		 */
11656		result = zone_get_from_db(zone, zone->db, NULL, NULL,
11657					  &oldserial, NULL, NULL, NULL, NULL,
11658					  NULL);
11659		RUNTIME_CHECK(result == ISC_R_SUCCESS);
11660		if (zone->type == dns_zone_slave &&
11661		    !isc_serial_gt(serial, oldserial)) {
11662			isc_uint32_t serialmin, serialmax;
11663			serialmin = (oldserial + 1) & 0xffffffffU;
11664			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
11665			dns_zone_log(zone, ISC_LOG_ERROR,
11666				     "ixfr-from-differences: failed: "
11667				     "new serial (%u) out of range [%u - %u]",
11668				     serial, serialmin, serialmax);
11669			result = ISC_R_RANGE;
11670			goto fail;
11671		}
11672
11673		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
11674				     zone->journal);
11675		if (result != ISC_R_SUCCESS)
11676			goto fail;
11677		if (dump)
11678			zone_needdump(zone, DNS_DUMP_DELAY);
11679		else if (zone->journalsize != -1) {
11680			result = dns_journal_compact(zone->mctx, zone->journal,
11681						     serial, zone->journalsize);
11682			switch (result) {
11683			case ISC_R_SUCCESS:
11684			case ISC_R_NOSPACE:
11685			case ISC_R_NOTFOUND:
11686				dns_zone_log(zone, ISC_LOG_DEBUG(3),
11687					     "dns_journal_compact: %s",
11688					     dns_result_totext(result));
11689				break;
11690			default:
11691				dns_zone_log(zone, ISC_LOG_ERROR,
11692					     "dns_journal_compact failed: %s",
11693					     dns_result_totext(result));
11694				break;
11695			}
11696		}
11697	} else {
11698		if (dump && zone->masterfile != NULL) {
11699			/*
11700			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
11701			 * to keep the old masterfile.
11702			 */
11703			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
11704			    remove(zone->masterfile) < 0 && errno != ENOENT) {
11705				char strbuf[ISC_STRERRORSIZE];
11706				isc__strerror(errno, strbuf, sizeof(strbuf));
11707				isc_log_write(dns_lctx,
11708					      DNS_LOGCATEGORY_GENERAL,
11709					      DNS_LOGMODULE_ZONE,
11710					      ISC_LOG_WARNING,
11711					      "unable to remove masterfile "
11712					      "'%s': '%s'",
11713					      zone->masterfile, strbuf);
11714			}
11715			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
11716				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
11717			else
11718				zone_needdump(zone, 0);
11719		}
11720		if (dump && zone->journal != NULL) {
11721			/*
11722			 * The in-memory database just changed, and
11723			 * because 'dump' is set, it didn't change by
11724			 * being loaded from disk.  Also, we have not
11725			 * journaled diffs for this change.
11726			 * Therefore, the on-disk journal is missing
11727			 * the deltas for this change.	Since it can
11728			 * no longer be used to bring the zone
11729			 * up-to-date, it is useless and should be
11730			 * removed.
11731			 */
11732			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11733				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
11734				      "removing journal file");
11735			if (remove(zone->journal) < 0 && errno != ENOENT) {
11736				char strbuf[ISC_STRERRORSIZE];
11737				isc__strerror(errno, strbuf, sizeof(strbuf));
11738				isc_log_write(dns_lctx,
11739					      DNS_LOGCATEGORY_GENERAL,
11740					      DNS_LOGMODULE_ZONE,
11741					      ISC_LOG_WARNING,
11742					      "unable to remove journal "
11743					      "'%s': '%s'",
11744					      zone->journal, strbuf);
11745			}
11746		}
11747	}
11748
11749	dns_db_closeversion(db, &ver, ISC_FALSE);
11750
11751	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11752		      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
11753		      "replacing zone database");
11754
11755	if (zone->db != NULL)
11756		zone_detachdb(zone);
11757	zone_attachdb(zone, db);
11758	dns_db_settask(zone->db, zone->task);
11759	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
11760	return (ISC_R_SUCCESS);
11761
11762 fail:
11763	dns_db_closeversion(db, &ver, ISC_FALSE);
11764	return (result);
11765}
11766
11767/* The caller must hold the dblock as a writer. */
11768static inline void
11769zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
11770	REQUIRE(zone->db == NULL && db != NULL);
11771
11772	dns_db_attach(db, &zone->db);
11773	if (zone->acache != NULL) {
11774		isc_result_t result;
11775		result = dns_acache_setdb(zone->acache, db);
11776		if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
11777			UNEXPECTED_ERROR(__FILE__, __LINE__,
11778					 "dns_acache_setdb() failed: %s",
11779					 isc_result_totext(result));
11780		}
11781	}
11782}
11783
11784/* The caller must hold the dblock as a writer. */
11785static inline void
11786zone_detachdb(dns_zone_t *zone) {
11787	REQUIRE(zone->db != NULL);
11788
11789	if (zone->acache != NULL)
11790		(void)dns_acache_putdb(zone->acache, zone->db);
11791	dns_db_detach(&zone->db);
11792}
11793
11794static void
11795zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
11796	isc_time_t now;
11797	isc_boolean_t again = ISC_FALSE;
11798	unsigned int soacount;
11799	unsigned int nscount;
11800	isc_uint32_t serial, refresh, retry, expire, minimum;
11801	isc_result_t xfrresult = result;
11802	isc_boolean_t free_needed;
11803
11804	REQUIRE(DNS_ZONE_VALID(zone));
11805
11806	dns_zone_log(zone, ISC_LOG_DEBUG(1),
11807		     "zone transfer finished: %s", dns_result_totext(result));
11808
11809	LOCK_ZONE(zone);
11810	INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
11811	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11812	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
11813
11814	TIME_NOW(&now);
11815	switch (result) {
11816	case ISC_R_SUCCESS:
11817		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11818		/*FALLTHROUGH*/
11819	case DNS_R_UPTODATE:
11820		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
11821		/*
11822		 * Has the zone expired underneath us?
11823		 */
11824		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11825		if (zone->db == NULL) {
11826			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11827			goto same_master;
11828		}
11829
11830		/*
11831		 * Update the zone structure's data from the actual
11832		 * SOA received.
11833		 */
11834		nscount = 0;
11835		soacount = 0;
11836		INSIST(zone->db != NULL);
11837		result = zone_get_from_db(zone, zone->db, &nscount,
11838					  &soacount, &serial, &refresh,
11839					  &retry, &expire, &minimum, NULL);
11840		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11841		if (result == ISC_R_SUCCESS) {
11842			if (soacount != 1)
11843				dns_zone_log(zone, ISC_LOG_ERROR,
11844					     "transferred zone "
11845					     "has %d SOA record%s", soacount,
11846					     (soacount != 0) ? "s" : "");
11847			if (nscount == 0) {
11848				dns_zone_log(zone, ISC_LOG_ERROR,
11849					     "transferred zone "
11850					     "has no NS records");
11851				if (DNS_ZONE_FLAG(zone,
11852						  DNS_ZONEFLG_HAVETIMERS)) {
11853					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11854					zone->retry = DNS_ZONE_DEFAULTRETRY;
11855				}
11856				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11857				zone_unload(zone);
11858				goto next_master;
11859			}
11860			zone->refresh = RANGE(refresh, zone->minrefresh,
11861					      zone->maxrefresh);
11862			zone->retry = RANGE(retry, zone->minretry,
11863					    zone->maxretry);
11864			zone->expire = RANGE(expire,
11865					     zone->refresh + zone->retry,
11866					     DNS_MAX_EXPIRE);
11867			zone->minimum = minimum;
11868			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11869		}
11870
11871		/*
11872		 * Set our next update/expire times.
11873		 */
11874		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
11875			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11876			zone->refreshtime = now;
11877			DNS_ZONE_TIME_ADD(&now, zone->expire,
11878					  &zone->expiretime);
11879		} else {
11880			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
11881					    &zone->refreshtime);
11882			DNS_ZONE_TIME_ADD(&now, zone->expire,
11883					  &zone->expiretime);
11884		}
11885		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
11886			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
11887			if (zone->tsigkey != NULL) {
11888				char namebuf[DNS_NAME_FORMATSIZE];
11889				dns_name_format(&zone->tsigkey->name, namebuf,
11890						sizeof(namebuf));
11891				snprintf(buf, sizeof(buf), ": TSIG '%s'",
11892					 namebuf);
11893			} else
11894				buf[0] = '\0';
11895			dns_zone_log(zone, ISC_LOG_INFO,
11896				     "transferred serial %u%s",
11897				     serial, buf);
11898		}
11899
11900		/*
11901		 * This is not necessary if we just performed a AXFR
11902		 * however it is necessary for an IXFR / UPTODATE and
11903		 * won't hurt with an AXFR.
11904		 */
11905		if (zone->masterfile != NULL || zone->journal != NULL) {
11906			result = ISC_R_FAILURE;
11907			if (zone->journal != NULL)
11908				result = isc_file_settime(zone->journal, &now);
11909			if (result != ISC_R_SUCCESS &&
11910			    zone->masterfile != NULL)
11911				result = isc_file_settime(zone->masterfile,
11912							  &now);
11913			/* Someone removed the file from underneath us! */
11914			if (result == ISC_R_FILENOTFOUND &&
11915			    zone->masterfile != NULL) {
11916				unsigned int delay = DNS_DUMP_DELAY;
11917				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY))
11918					delay = 0;
11919				zone_needdump(zone, delay);
11920			} else if (result != ISC_R_SUCCESS)
11921				dns_zone_log(zone, ISC_LOG_ERROR,
11922					     "transfer: could not set file "
11923					     "modification time of '%s': %s",
11924					     zone->masterfile,
11925					     dns_result_totext(result));
11926		}
11927		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
11928		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
11929		break;
11930
11931	case DNS_R_BADIXFR:
11932		/* Force retry with AXFR. */
11933		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
11934		goto same_master;
11935
11936	default:
11937	next_master:
11938		/*
11939		 * Skip to next failed / untried master.
11940		 */
11941		do {
11942			zone->curmaster++;
11943		} while (zone->curmaster < zone->masterscnt &&
11944			 zone->mastersok[zone->curmaster]);
11945		/* FALLTHROUGH */
11946	same_master:
11947		if (zone->curmaster >= zone->masterscnt) {
11948			zone->curmaster = 0;
11949			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
11950			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11951				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11952				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11953				while (zone->curmaster < zone->masterscnt &&
11954				       zone->mastersok[zone->curmaster])
11955					zone->curmaster++;
11956				again = ISC_TRUE;
11957			} else
11958				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11959		} else {
11960			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11961			again = ISC_TRUE;
11962		}
11963		inc_stats(zone, dns_zonestatscounter_xfrfail);
11964		break;
11965	}
11966	zone_settimer(zone, &now);
11967
11968	/*
11969	 * If creating the transfer object failed, zone->xfr is NULL.
11970	 * Otherwise, we are called as the done callback of a zone
11971	 * transfer object that just entered its shutting-down
11972	 * state.  Since we are no longer responsible for shutting
11973	 * it down, we can detach our reference.
11974	 */
11975	if (zone->xfr != NULL)
11976		dns_xfrin_detach(&zone->xfr);
11977
11978	if (zone->tsigkey != NULL)
11979		dns_tsigkey_detach(&zone->tsigkey);
11980
11981	/*
11982	 * Handle any deferred journal compaction.
11983	 */
11984	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
11985		result = dns_journal_compact(zone->mctx, zone->journal,
11986					     zone->compact_serial,
11987					     zone->journalsize);
11988		switch (result) {
11989		case ISC_R_SUCCESS:
11990		case ISC_R_NOSPACE:
11991		case ISC_R_NOTFOUND:
11992			dns_zone_log(zone, ISC_LOG_DEBUG(3),
11993				     "dns_journal_compact: %s",
11994				     dns_result_totext(result));
11995			break;
11996		default:
11997			dns_zone_log(zone, ISC_LOG_ERROR,
11998				     "dns_journal_compact failed: %s",
11999				     dns_result_totext(result));
12000			break;
12001		}
12002		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
12003	}
12004
12005	/*
12006	 * This transfer finishing freed up a transfer quota slot.
12007	 * Let any other zones waiting for quota have it.
12008	 */
12009	UNLOCK_ZONE(zone);
12010	RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12011	ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
12012	zone->statelist = NULL;
12013	zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
12014	RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12015	LOCK_ZONE(zone);
12016
12017	/*
12018	 * Retry with a different server if necessary.
12019	 */
12020	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12021		queue_soa_query(zone);
12022
12023	INSIST(zone->irefs > 0);
12024	zone->irefs--;
12025	free_needed = exit_check(zone);
12026	UNLOCK_ZONE(zone);
12027	if (free_needed)
12028		zone_free(zone);
12029}
12030
12031static void
12032zone_loaddone(void *arg, isc_result_t result) {
12033	static char me[] = "zone_loaddone";
12034	dns_load_t *load = arg;
12035	dns_zone_t *zone;
12036	isc_result_t tresult;
12037
12038	REQUIRE(DNS_LOAD_VALID(load));
12039	zone = load->zone;
12040
12041	ENTER;
12042
12043	tresult = dns_db_endload(load->db, &load->callbacks.add_private);
12044	if (tresult != ISC_R_SUCCESS &&
12045	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
12046		result = tresult;
12047
12048	LOCK_ZONE(load->zone);
12049	(void)zone_postload(load->zone, load->db, load->loadtime, result);
12050	zonemgr_putio(&load->zone->readio);
12051	DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
12052	/*
12053	 * Leave the zone frozen if the reload fails.
12054	 */
12055	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
12056	     DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW))
12057		zone->update_disabled = ISC_FALSE;
12058	DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW);
12059	UNLOCK_ZONE(load->zone);
12060
12061	load->magic = 0;
12062	dns_db_detach(&load->db);
12063	if (load->zone->lctx != NULL)
12064		dns_loadctx_detach(&load->zone->lctx);
12065	dns_zone_idetach(&load->zone);
12066	isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
12067}
12068
12069void
12070dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
12071	REQUIRE(DNS_ZONE_VALID(zone));
12072	REQUIRE(table != NULL);
12073	REQUIRE(*table == NULL);
12074
12075	LOCK_ZONE(zone);
12076	if (zone->ssutable != NULL)
12077		dns_ssutable_attach(zone->ssutable, table);
12078	UNLOCK_ZONE(zone);
12079}
12080
12081void
12082dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
12083	REQUIRE(DNS_ZONE_VALID(zone));
12084
12085	LOCK_ZONE(zone);
12086	if (zone->ssutable != NULL)
12087		dns_ssutable_detach(&zone->ssutable);
12088	if (table != NULL)
12089		dns_ssutable_attach(table, &zone->ssutable);
12090	UNLOCK_ZONE(zone);
12091}
12092
12093void
12094dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
12095	REQUIRE(DNS_ZONE_VALID(zone));
12096
12097	zone->sigvalidityinterval = interval;
12098}
12099
12100isc_uint32_t
12101dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
12102	REQUIRE(DNS_ZONE_VALID(zone));
12103
12104	return (zone->sigvalidityinterval);
12105}
12106
12107void
12108dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
12109	REQUIRE(DNS_ZONE_VALID(zone));
12110
12111	zone->sigresigninginterval = interval;
12112}
12113
12114isc_uint32_t
12115dns_zone_getsigresigninginterval(dns_zone_t *zone) {
12116	REQUIRE(DNS_ZONE_VALID(zone));
12117
12118	return (zone->sigresigninginterval);
12119}
12120
12121static void
12122queue_xfrin(dns_zone_t *zone) {
12123	const char me[] = "queue_xfrin";
12124	isc_result_t result;
12125	dns_zonemgr_t *zmgr = zone->zmgr;
12126
12127	ENTER;
12128
12129	INSIST(zone->statelist == NULL);
12130
12131	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12132	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
12133	LOCK_ZONE(zone);
12134	zone->irefs++;
12135	UNLOCK_ZONE(zone);
12136	zone->statelist = &zmgr->waiting_for_xfrin;
12137	result = zmgr_start_xfrin_ifquota(zmgr, zone);
12138	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12139
12140	if (result == ISC_R_QUOTA) {
12141		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
12142			      "zone transfer deferred due to quota");
12143	} else if (result != ISC_R_SUCCESS) {
12144		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
12145			      "starting zone transfer: %s",
12146			      isc_result_totext(result));
12147	}
12148}
12149
12150/*
12151 * This event callback is called when a zone has received
12152 * any necessary zone transfer quota.  This is the time
12153 * to go ahead and start the transfer.
12154 */
12155static void
12156got_transfer_quota(isc_task_t *task, isc_event_t *event) {
12157	isc_result_t result;
12158	dns_peer_t *peer = NULL;
12159	char master[ISC_SOCKADDR_FORMATSIZE];
12160	char source[ISC_SOCKADDR_FORMATSIZE];
12161	dns_rdatatype_t xfrtype;
12162	dns_zone_t *zone = event->ev_arg;
12163	isc_netaddr_t masterip;
12164	isc_sockaddr_t sourceaddr;
12165	isc_sockaddr_t masteraddr;
12166	isc_time_t now;
12167	const char *soa_before = "";
12168
12169	UNUSED(task);
12170
12171	INSIST(task == zone->task);
12172
12173	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12174		result = ISC_R_CANCELED;
12175		goto cleanup;
12176	}
12177
12178	TIME_NOW(&now);
12179
12180	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12181	if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
12182				    &zone->sourceaddr, &now))
12183	{
12184		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12185		dns_zone_log(zone, ISC_LOG_INFO,
12186			     "got_transfer_quota: skipping zone transfer as "
12187			     "master %s (source %s) is unreachable (cached)",
12188			     master, source);
12189		result = ISC_R_CANCELED;
12190		goto cleanup;
12191	}
12192
12193	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12194	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
12195
12196	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12197		soa_before = "SOA before ";
12198	/*
12199	 * Decide whether we should request IXFR or AXFR.
12200	 */
12201	if (zone->db == NULL) {
12202		dns_zone_log(zone, ISC_LOG_DEBUG(1),
12203			     "no database exists yet, requesting AXFR of "
12204			     "initial version from %s", master);
12205		xfrtype = dns_rdatatype_axfr;
12206	} else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
12207		dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
12208			     "set, requesting %sAXFR from %s", soa_before,
12209			     master);
12210		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12211			xfrtype = dns_rdatatype_soa;
12212		else
12213			xfrtype = dns_rdatatype_axfr;
12214	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
12215		dns_zone_log(zone, ISC_LOG_DEBUG(1),
12216			     "forced reload, requesting AXFR of "
12217			     "initial version from %s", master);
12218		xfrtype = dns_rdatatype_axfr;
12219	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
12220		dns_zone_log(zone, ISC_LOG_DEBUG(1),
12221			     "retrying with AXFR from %s due to "
12222			     "previous IXFR failure", master);
12223		xfrtype = dns_rdatatype_axfr;
12224		LOCK_ZONE(zone);
12225		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
12226		UNLOCK_ZONE(zone);
12227	} else {
12228		isc_boolean_t use_ixfr = ISC_TRUE;
12229		if (peer != NULL &&
12230		    dns_peer_getrequestixfr(peer, &use_ixfr) ==
12231		    ISC_R_SUCCESS) {
12232			; /* Using peer setting */
12233		} else {
12234			use_ixfr = zone->view->requestixfr;
12235		}
12236		if (use_ixfr == ISC_FALSE) {
12237			dns_zone_log(zone, ISC_LOG_DEBUG(1),
12238				     "IXFR disabled, requesting %sAXFR from %s",
12239				     soa_before, master);
12240			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12241				xfrtype = dns_rdatatype_soa;
12242			else
12243				xfrtype = dns_rdatatype_axfr;
12244		} else {
12245			dns_zone_log(zone, ISC_LOG_DEBUG(1),
12246				     "requesting IXFR from %s", master);
12247			xfrtype = dns_rdatatype_ixfr;
12248		}
12249	}
12250
12251	/*
12252	 * Determine if we should attempt to sign the request with TSIG.
12253	 */
12254	result = ISC_R_NOTFOUND;
12255	/*
12256	 * First, look for a tsig key in the master statement, then
12257	 * try for a server key.
12258	 */
12259	if ((zone->masterkeynames != NULL) &&
12260	    (zone->masterkeynames[zone->curmaster] != NULL)) {
12261		dns_view_t *view = dns_zone_getview(zone);
12262		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12263		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
12264	}
12265	if (zone->tsigkey == NULL)
12266		result = dns_view_getpeertsig(zone->view, &masterip,
12267					      &zone->tsigkey);
12268
12269	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12270		dns_zone_log(zone, ISC_LOG_ERROR,
12271			     "could not get TSIG key for zone transfer: %s",
12272			     isc_result_totext(result));
12273	}
12274
12275	LOCK_ZONE(zone);
12276	masteraddr = zone->masteraddr;
12277	sourceaddr = zone->sourceaddr;
12278	UNLOCK_ZONE(zone);
12279	INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
12280	result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
12281				   zone->tsigkey, zone->mctx,
12282				   zone->zmgr->timermgr, zone->zmgr->socketmgr,
12283				   zone->task, zone_xfrdone, &zone->xfr);
12284	if (result == ISC_R_SUCCESS) {
12285		LOCK_ZONE(zone);
12286		if (xfrtype == dns_rdatatype_axfr) {
12287			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12288				inc_stats(zone, dns_zonestatscounter_axfrreqv4);
12289			else
12290				inc_stats(zone, dns_zonestatscounter_axfrreqv6);
12291		} else if (xfrtype == dns_rdatatype_ixfr) {
12292			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12293				inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
12294			else
12295				inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
12296		}
12297		UNLOCK_ZONE(zone);
12298	}
12299 cleanup:
12300	/*
12301	 * Any failure in this function is handled like a failed
12302	 * zone transfer.  This ensures that we get removed from
12303	 * zmgr->xfrin_in_progress.
12304	 */
12305	if (result != ISC_R_SUCCESS)
12306		zone_xfrdone(zone, result);
12307
12308	isc_event_free(&event);
12309}
12310
12311/*
12312 * Update forwarding support.
12313 */
12314
12315static void
12316forward_destroy(dns_forward_t *forward) {
12317
12318	forward->magic = 0;
12319	if (forward->request != NULL)
12320		dns_request_destroy(&forward->request);
12321	if (forward->msgbuf != NULL)
12322		isc_buffer_free(&forward->msgbuf);
12323	if (forward->zone != NULL) {
12324		LOCK(&forward->zone->lock);
12325		if (ISC_LINK_LINKED(forward, link))
12326			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
12327		UNLOCK(&forward->zone->lock);
12328		dns_zone_idetach(&forward->zone);
12329	}
12330	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
12331}
12332
12333static isc_result_t
12334sendtomaster(dns_forward_t *forward) {
12335	isc_result_t result;
12336	isc_sockaddr_t src;
12337
12338	LOCK_ZONE(forward->zone);
12339
12340	if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
12341		UNLOCK_ZONE(forward->zone);
12342		return (ISC_R_CANCELED);
12343	}
12344
12345	if (forward->which >= forward->zone->masterscnt) {
12346		UNLOCK_ZONE(forward->zone);
12347		return (ISC_R_NOMORE);
12348	}
12349
12350	forward->addr = forward->zone->masters[forward->which];
12351	/*
12352	 * Always use TCP regardless of whether the original update
12353	 * used TCP.
12354	 * XXX The timeout may but a bit small if we are far down a
12355	 * transfer graph and the master has to try several masters.
12356	 */
12357	switch (isc_sockaddr_pf(&forward->addr)) {
12358	case PF_INET:
12359		src = forward->zone->xfrsource4;
12360		break;
12361	case PF_INET6:
12362		src = forward->zone->xfrsource6;
12363		break;
12364	default:
12365		result = ISC_R_NOTIMPLEMENTED;
12366		goto unlock;
12367	}
12368	result = dns_request_createraw(forward->zone->view->requestmgr,
12369				       forward->msgbuf,
12370				       &src, &forward->addr,
12371				       DNS_REQUESTOPT_TCP, 15 /* XXX */,
12372				       forward->zone->task,
12373				       forward_callback, forward,
12374				       &forward->request);
12375	if (result == ISC_R_SUCCESS) {
12376		if (!ISC_LINK_LINKED(forward, link))
12377			ISC_LIST_APPEND(forward->zone->forwards, forward, link);
12378	}
12379
12380 unlock:
12381	UNLOCK_ZONE(forward->zone);
12382	return (result);
12383}
12384
12385static void
12386forward_callback(isc_task_t *task, isc_event_t *event) {
12387	const char me[] = "forward_callback";
12388	dns_requestevent_t *revent = (dns_requestevent_t *)event;
12389	dns_message_t *msg = NULL;
12390	char master[ISC_SOCKADDR_FORMATSIZE];
12391	isc_result_t result;
12392	dns_forward_t *forward;
12393	dns_zone_t *zone;
12394
12395	UNUSED(task);
12396
12397	forward = revent->ev_arg;
12398	INSIST(DNS_FORWARD_VALID(forward));
12399	zone = forward->zone;
12400	INSIST(DNS_ZONE_VALID(zone));
12401
12402	ENTER;
12403
12404	isc_sockaddr_format(&forward->addr, master, sizeof(master));
12405
12406	if (revent->result != ISC_R_SUCCESS) {
12407		dns_zone_log(zone, ISC_LOG_INFO,
12408			     "could not forward dynamic update to %s: %s",
12409			     master, dns_result_totext(revent->result));
12410		goto next_master;
12411	}
12412
12413	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12414	if (result != ISC_R_SUCCESS)
12415		goto next_master;
12416
12417	result = dns_request_getresponse(revent->request, msg,
12418					 DNS_MESSAGEPARSE_PRESERVEORDER |
12419					 DNS_MESSAGEPARSE_CLONEBUFFER);
12420	if (result != ISC_R_SUCCESS)
12421		goto next_master;
12422
12423	switch (msg->rcode) {
12424	/*
12425	 * Pass these rcodes back to client.
12426	 */
12427	case dns_rcode_noerror:
12428	case dns_rcode_yxdomain:
12429	case dns_rcode_yxrrset:
12430	case dns_rcode_nxrrset:
12431	case dns_rcode_refused:
12432	case dns_rcode_nxdomain:
12433		break;
12434
12435	/* These should not occur if the masters/zone are valid. */
12436	case dns_rcode_notzone:
12437	case dns_rcode_notauth: {
12438		char rcode[128];
12439		isc_buffer_t rb;
12440
12441		isc_buffer_init(&rb, rcode, sizeof(rcode));
12442		(void)dns_rcode_totext(msg->rcode, &rb);
12443		dns_zone_log(zone, ISC_LOG_WARNING,
12444			     "forwarding dynamic update: "
12445			     "unexpected response: master %s returned: %.*s",
12446			     master, (int)rb.used, rcode);
12447		goto next_master;
12448	}
12449
12450	/* Try another server for these rcodes. */
12451	case dns_rcode_formerr:
12452	case dns_rcode_servfail:
12453	case dns_rcode_notimp:
12454	case dns_rcode_badvers:
12455	default:
12456		goto next_master;
12457	}
12458
12459	/* call callback */
12460	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
12461	msg = NULL;
12462	dns_request_destroy(&forward->request);
12463	forward_destroy(forward);
12464	isc_event_free(&event);
12465	return;
12466
12467 next_master:
12468	if (msg != NULL)
12469		dns_message_destroy(&msg);
12470	isc_event_free(&event);
12471	forward->which++;
12472	dns_request_destroy(&forward->request);
12473	result = sendtomaster(forward);
12474	if (result != ISC_R_SUCCESS) {
12475		/* call callback */
12476		dns_zone_log(zone, ISC_LOG_DEBUG(3),
12477			     "exhausted dynamic update forwarder list");
12478		(forward->callback)(forward->callback_arg, result, NULL);
12479		forward_destroy(forward);
12480	}
12481}
12482
12483isc_result_t
12484dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
12485		       dns_updatecallback_t callback, void *callback_arg)
12486{
12487	dns_forward_t *forward;
12488	isc_result_t result;
12489	isc_region_t *mr;
12490
12491	REQUIRE(DNS_ZONE_VALID(zone));
12492	REQUIRE(msg != NULL);
12493	REQUIRE(callback != NULL);
12494
12495	forward = isc_mem_get(zone->mctx, sizeof(*forward));
12496	if (forward == NULL)
12497		return (ISC_R_NOMEMORY);
12498
12499	forward->request = NULL;
12500	forward->zone = NULL;
12501	forward->msgbuf = NULL;
12502	forward->which = 0;
12503	forward->mctx = 0;
12504	forward->callback = callback;
12505	forward->callback_arg = callback_arg;
12506	ISC_LINK_INIT(forward, link);
12507	forward->magic = FORWARD_MAGIC;
12508
12509	mr = dns_message_getrawmessage(msg);
12510	if (mr == NULL) {
12511		result = ISC_R_UNEXPECTEDEND;
12512		goto cleanup;
12513	}
12514
12515	result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
12516	if (result != ISC_R_SUCCESS)
12517		goto cleanup;
12518	result = isc_buffer_copyregion(forward->msgbuf, mr);
12519	if (result != ISC_R_SUCCESS)
12520		goto cleanup;
12521
12522	isc_mem_attach(zone->mctx, &forward->mctx);
12523	dns_zone_iattach(zone, &forward->zone);
12524	result = sendtomaster(forward);
12525
12526 cleanup:
12527	if (result != ISC_R_SUCCESS) {
12528		forward_destroy(forward);
12529	}
12530	return (result);
12531}
12532
12533isc_result_t
12534dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
12535	REQUIRE(DNS_ZONE_VALID(zone));
12536	REQUIRE(next != NULL && *next == NULL);
12537
12538	*next = ISC_LIST_NEXT(zone, link);
12539	if (*next == NULL)
12540		return (ISC_R_NOMORE);
12541	else
12542		return (ISC_R_SUCCESS);
12543}
12544
12545isc_result_t
12546dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
12547	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12548	REQUIRE(first != NULL && *first == NULL);
12549
12550	*first = ISC_LIST_HEAD(zmgr->zones);
12551	if (*first == NULL)
12552		return (ISC_R_NOMORE);
12553	else
12554		return (ISC_R_SUCCESS);
12555}
12556
12557/***
12558 ***	Zone manager.
12559 ***/
12560
12561isc_result_t
12562dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
12563		   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
12564		   dns_zonemgr_t **zmgrp)
12565{
12566	dns_zonemgr_t *zmgr;
12567	isc_result_t result;
12568	isc_interval_t interval;
12569
12570	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
12571	if (zmgr == NULL)
12572		return (ISC_R_NOMEMORY);
12573	zmgr->mctx = NULL;
12574	zmgr->refs = 1;
12575	isc_mem_attach(mctx, &zmgr->mctx);
12576	zmgr->taskmgr = taskmgr;
12577	zmgr->timermgr = timermgr;
12578	zmgr->socketmgr = socketmgr;
12579	zmgr->zonetasks = NULL;
12580	zmgr->task = NULL;
12581	zmgr->rl = NULL;
12582	ISC_LIST_INIT(zmgr->zones);
12583	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
12584	ISC_LIST_INIT(zmgr->xfrin_in_progress);
12585	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
12586	result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
12587	if (result != ISC_R_SUCCESS)
12588		goto free_mem;
12589
12590	zmgr->transfersin = 10;
12591	zmgr->transfersperns = 2;
12592
12593	/* Unreachable lock. */
12594	result = isc_rwlock_init(&zmgr->urlock, 0, 0);
12595	if (result != ISC_R_SUCCESS)
12596		goto free_rwlock;
12597
12598	/* Create a single task for queueing of SOA queries. */
12599	result = isc_task_create(taskmgr, 1, &zmgr->task);
12600	if (result != ISC_R_SUCCESS)
12601		goto free_urlock;
12602
12603	isc_task_setname(zmgr->task, "zmgr", zmgr);
12604	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
12605					&zmgr->rl);
12606	if (result != ISC_R_SUCCESS)
12607		goto free_task;
12608
12609	/* default to 20 refresh queries / notifies per second. */
12610	isc_interval_set(&interval, 0, 1000000000/2);
12611	result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
12612	RUNTIME_CHECK(result == ISC_R_SUCCESS);
12613	isc_ratelimiter_setpertic(zmgr->rl, 10);
12614
12615	zmgr->iolimit = 1;
12616	zmgr->ioactive = 0;
12617	ISC_LIST_INIT(zmgr->high);
12618	ISC_LIST_INIT(zmgr->low);
12619
12620	result = isc_mutex_init(&zmgr->iolock);
12621	if (result != ISC_R_SUCCESS)
12622		goto free_rl;
12623
12624	zmgr->magic = ZONEMGR_MAGIC;
12625
12626	*zmgrp = zmgr;
12627	return (ISC_R_SUCCESS);
12628
12629#if 0
12630 free_iolock:
12631	DESTROYLOCK(&zmgr->iolock);
12632#endif
12633 free_rl:
12634	isc_ratelimiter_detach(&zmgr->rl);
12635 free_task:
12636	isc_task_detach(&zmgr->task);
12637 free_urlock:
12638	isc_rwlock_destroy(&zmgr->urlock);
12639 free_rwlock:
12640	isc_rwlock_destroy(&zmgr->rwlock);
12641 free_mem:
12642	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
12643	isc_mem_detach(&mctx);
12644	return (result);
12645}
12646
12647isc_result_t
12648dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12649	isc_result_t result;
12650
12651	REQUIRE(DNS_ZONE_VALID(zone));
12652	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12653
12654	if (zmgr->zonetasks == NULL)
12655		return (ISC_R_FAILURE);
12656
12657	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12658	LOCK_ZONE(zone);
12659	REQUIRE(zone->task == NULL);
12660	REQUIRE(zone->timer == NULL);
12661	REQUIRE(zone->zmgr == NULL);
12662
12663	isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
12664
12665	/*
12666	 * Set the task name.  The tag will arbitrarily point to one
12667	 * of the zones sharing the task (in practice, the one
12668	 * to be managed last).
12669	 */
12670	isc_task_setname(zone->task, "zone", zone);
12671
12672	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
12673				  NULL, NULL,
12674				  zone->task, zone_timer, zone,
12675				  &zone->timer);
12676
12677	if (result != ISC_R_SUCCESS)
12678		goto cleanup_task;
12679
12680	/*
12681	 * The timer "holds" a iref.
12682	 */
12683	zone->irefs++;
12684	INSIST(zone->irefs != 0);
12685
12686	ISC_LIST_APPEND(zmgr->zones, zone, link);
12687	zone->zmgr = zmgr;
12688	zmgr->refs++;
12689
12690	goto unlock;
12691
12692 cleanup_task:
12693	isc_task_detach(&zone->task);
12694
12695 unlock:
12696	UNLOCK_ZONE(zone);
12697	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12698	return (result);
12699}
12700
12701void
12702dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12703	isc_boolean_t free_now = ISC_FALSE;
12704
12705	REQUIRE(DNS_ZONE_VALID(zone));
12706	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12707	REQUIRE(zone->zmgr == zmgr);
12708
12709	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12710	LOCK_ZONE(zone);
12711
12712	ISC_LIST_UNLINK(zmgr->zones, zone, link);
12713	zone->zmgr = NULL;
12714	zmgr->refs--;
12715	if (zmgr->refs == 0)
12716		free_now = ISC_TRUE;
12717
12718	UNLOCK_ZONE(zone);
12719	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12720
12721	if (free_now)
12722		zonemgr_free(zmgr);
12723	ENSURE(zone->zmgr == NULL);
12724}
12725
12726void
12727dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
12728	REQUIRE(DNS_ZONEMGR_VALID(source));
12729	REQUIRE(target != NULL && *target == NULL);
12730
12731	RWLOCK(&source->rwlock, isc_rwlocktype_write);
12732	REQUIRE(source->refs > 0);
12733	source->refs++;
12734	INSIST(source->refs > 0);
12735	RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
12736	*target = source;
12737}
12738
12739void
12740dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
12741	dns_zonemgr_t *zmgr;
12742	isc_boolean_t free_now = ISC_FALSE;
12743
12744	REQUIRE(zmgrp != NULL);
12745	zmgr = *zmgrp;
12746	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12747
12748	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12749	zmgr->refs--;
12750	if (zmgr->refs == 0)
12751		free_now = ISC_TRUE;
12752	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12753
12754	if (free_now)
12755		zonemgr_free(zmgr);
12756	*zmgrp = NULL;
12757}
12758
12759isc_result_t
12760dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
12761	dns_zone_t *p;
12762
12763	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12764
12765	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12766	for (p = ISC_LIST_HEAD(zmgr->zones);
12767	     p != NULL;
12768	     p = ISC_LIST_NEXT(p, link))
12769	{
12770		dns_zone_maintenance(p);
12771	}
12772	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12773
12774	/*
12775	 * Recent configuration changes may have increased the
12776	 * amount of available transfers quota.  Make sure any
12777	 * transfers currently blocked on quota get started if
12778	 * possible.
12779	 */
12780	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12781	zmgr_resume_xfrs(zmgr, ISC_TRUE);
12782	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12783	return (ISC_R_SUCCESS);
12784}
12785
12786void
12787dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
12788
12789	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12790
12791	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12792	zmgr_resume_xfrs(zmgr, ISC_TRUE);
12793	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12794}
12795
12796void
12797dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
12798	dns_zone_t *zone;
12799
12800	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12801
12802	isc_ratelimiter_shutdown(zmgr->rl);
12803
12804	if (zmgr->task != NULL)
12805		isc_task_destroy(&zmgr->task);
12806	if (zmgr->zonetasks != NULL)
12807		isc_taskpool_destroy(&zmgr->zonetasks);
12808
12809	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12810	for (zone = ISC_LIST_HEAD(zmgr->zones);
12811	     zone != NULL;
12812	     zone = ISC_LIST_NEXT(zone, link))
12813	{
12814		LOCK_ZONE(zone);
12815		forward_cancel(zone);
12816		UNLOCK_ZONE(zone);
12817	}
12818	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12819}
12820
12821isc_result_t
12822dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
12823	isc_result_t result;
12824	int ntasks = num_zones / 100;
12825	isc_taskpool_t *pool = NULL;
12826
12827	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12828
12829	/*
12830	 * For anything fewer than 1000 zones we use 10 tasks in
12831	 * the task pool.  More than that, and we'll scale at one
12832	 * task per 100 zones.
12833	 */
12834	if (ntasks < 10)
12835		ntasks = 10;
12836
12837	/* Create or resize the zone task pool. */
12838	if (zmgr->zonetasks == NULL)
12839		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
12840					     ntasks, 2, &pool);
12841	else
12842		result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
12843
12844	if (result == ISC_R_SUCCESS)
12845		zmgr->zonetasks = pool;
12846
12847	return (result);
12848}
12849
12850static void
12851zonemgr_free(dns_zonemgr_t *zmgr) {
12852	isc_mem_t *mctx;
12853
12854	INSIST(zmgr->refs == 0);
12855	INSIST(ISC_LIST_EMPTY(zmgr->zones));
12856
12857	zmgr->magic = 0;
12858
12859	DESTROYLOCK(&zmgr->iolock);
12860	isc_ratelimiter_detach(&zmgr->rl);
12861
12862	isc_rwlock_destroy(&zmgr->urlock);
12863	isc_rwlock_destroy(&zmgr->rwlock);
12864	mctx = zmgr->mctx;
12865	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
12866	isc_mem_detach(&mctx);
12867}
12868
12869void
12870dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
12871	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12872
12873	zmgr->transfersin = value;
12874}
12875
12876isc_uint32_t
12877dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
12878	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12879
12880	return (zmgr->transfersin);
12881}
12882
12883void
12884dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
12885	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12886
12887	zmgr->transfersperns = value;
12888}
12889
12890isc_uint32_t
12891dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
12892	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12893
12894	return (zmgr->transfersperns);
12895}
12896
12897/*
12898 * Try to start a new incoming zone transfer to fill a quota
12899 * slot that was just vacated.
12900 *
12901 * Requires:
12902 *	The zone manager is locked by the caller.
12903 */
12904static void
12905zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
12906	dns_zone_t *zone;
12907	dns_zone_t *next;
12908
12909	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
12910	     zone != NULL;
12911	     zone = next)
12912	{
12913		isc_result_t result;
12914		next = ISC_LIST_NEXT(zone, statelink);
12915		result = zmgr_start_xfrin_ifquota(zmgr, zone);
12916		if (result == ISC_R_SUCCESS) {
12917			if (multi)
12918				continue;
12919			/*
12920			 * We successfully filled the slot.  We're done.
12921			 */
12922			break;
12923		} else if (result == ISC_R_QUOTA) {
12924			/*
12925			 * Not enough quota.  This is probably the per-server
12926			 * quota, because we usually get called when a unit of
12927			 * global quota has just been freed.  Try the next
12928			 * zone, it may succeed if it uses another master.
12929			 */
12930			continue;
12931		} else {
12932			dns_zone_log(zone, ISC_LOG_DEBUG(1),
12933				     "starting zone transfer: %s",
12934				     isc_result_totext(result));
12935			break;
12936		}
12937	}
12938}
12939
12940/*
12941 * Try to start an incoming zone transfer for 'zone', quota permitting.
12942 *
12943 * Requires:
12944 *	The zone manager is locked by the caller.
12945 *
12946 * Returns:
12947 *	ISC_R_SUCCESS	There was enough quota and we attempted to
12948 *			start a transfer.  zone_xfrdone() has been or will
12949 *			be called.
12950 *	ISC_R_QUOTA	Not enough quota.
12951 *	Others		Failure.
12952 */
12953static isc_result_t
12954zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12955	dns_peer_t *peer = NULL;
12956	isc_netaddr_t masterip;
12957	isc_uint32_t nxfrsin, nxfrsperns;
12958	dns_zone_t *x;
12959	isc_uint32_t maxtransfersin, maxtransfersperns;
12960	isc_event_t *e;
12961
12962	/*
12963	 * If we are exiting just pretend we got quota so the zone will
12964	 * be cleaned up in the zone's task context.
12965	 */
12966	LOCK_ZONE(zone);
12967	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12968		UNLOCK_ZONE(zone);
12969		goto gotquota;
12970	}
12971
12972	/*
12973	 * Find any configured information about the server we'd
12974	 * like to transfer this zone from.
12975	 */
12976	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12977	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
12978	UNLOCK_ZONE(zone);
12979
12980	/*
12981	 * Determine the total maximum number of simultaneous
12982	 * transfers allowed, and the maximum for this specific
12983	 * master.
12984	 */
12985	maxtransfersin = zmgr->transfersin;
12986	maxtransfersperns = zmgr->transfersperns;
12987	if (peer != NULL)
12988		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
12989
12990	/*
12991	 * Count the total number of transfers that are in progress,
12992	 * and the number of transfers in progress from this master.
12993	 * We linearly scan a list of all transfers; if this turns
12994	 * out to be too slow, we could hash on the master address.
12995	 */
12996	nxfrsin = nxfrsperns = 0;
12997	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
12998	     x != NULL;
12999	     x = ISC_LIST_NEXT(x, statelink))
13000	{
13001		isc_netaddr_t xip;
13002
13003		LOCK_ZONE(x);
13004		isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
13005		UNLOCK_ZONE(x);
13006
13007		nxfrsin++;
13008		if (isc_netaddr_equal(&xip, &masterip))
13009			nxfrsperns++;
13010	}
13011
13012	/* Enforce quota. */
13013	if (nxfrsin >= maxtransfersin)
13014		return (ISC_R_QUOTA);
13015
13016	if (nxfrsperns >= maxtransfersperns)
13017		return (ISC_R_QUOTA);
13018
13019 gotquota:
13020	/*
13021	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
13022	 * list and send it an event to let it start the actual transfer in the
13023	 * context of its own task.
13024	 */
13025	e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
13026			       got_transfer_quota, zone, sizeof(isc_event_t));
13027	if (e == NULL)
13028		return (ISC_R_NOMEMORY);
13029
13030	LOCK_ZONE(zone);
13031	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
13032	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
13033	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
13034	zone->statelist = &zmgr->xfrin_in_progress;
13035	isc_task_send(zone->task, &e);
13036	dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
13037	UNLOCK_ZONE(zone);
13038
13039	return (ISC_R_SUCCESS);
13040}
13041
13042void
13043dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
13044
13045	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13046	REQUIRE(iolimit > 0);
13047
13048	zmgr->iolimit = iolimit;
13049}
13050
13051isc_uint32_t
13052dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
13053
13054	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13055
13056	return (zmgr->iolimit);
13057}
13058
13059/*
13060 * Get permission to request a file handle from the OS.
13061 * An event will be sent to action when one is available.
13062 * There are two queues available (high and low), the high
13063 * queue will be serviced before the low one.
13064 *
13065 * zonemgr_putio() must be called after the event is delivered to
13066 * 'action'.
13067 */
13068
13069static isc_result_t
13070zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
13071	      isc_task_t *task, isc_taskaction_t action, void *arg,
13072	      dns_io_t **iop)
13073{
13074	dns_io_t *io;
13075	isc_boolean_t queue;
13076
13077	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13078	REQUIRE(iop != NULL && *iop == NULL);
13079
13080	io = isc_mem_get(zmgr->mctx, sizeof(*io));
13081	if (io == NULL)
13082		return (ISC_R_NOMEMORY);
13083	io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
13084				       action, arg, sizeof(*io->event));
13085	if (io->event == NULL) {
13086		isc_mem_put(zmgr->mctx, io, sizeof(*io));
13087		return (ISC_R_NOMEMORY);
13088	}
13089	io->zmgr = zmgr;
13090	io->high = high;
13091	io->task = NULL;
13092	isc_task_attach(task, &io->task);
13093	ISC_LINK_INIT(io, link);
13094	io->magic = IO_MAGIC;
13095
13096	LOCK(&zmgr->iolock);
13097	zmgr->ioactive++;
13098	queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
13099	if (queue) {
13100		if (io->high)
13101			ISC_LIST_APPEND(zmgr->high, io, link);
13102		else
13103			ISC_LIST_APPEND(zmgr->low, io, link);
13104	}
13105	UNLOCK(&zmgr->iolock);
13106	*iop = io;
13107
13108	if (!queue) {
13109		isc_task_send(io->task, &io->event);
13110	}
13111	return (ISC_R_SUCCESS);
13112}
13113
13114static void
13115zonemgr_putio(dns_io_t **iop) {
13116	dns_io_t *io;
13117	dns_io_t *next;
13118	dns_zonemgr_t *zmgr;
13119
13120	REQUIRE(iop != NULL);
13121	io = *iop;
13122	REQUIRE(DNS_IO_VALID(io));
13123
13124	*iop = NULL;
13125
13126	INSIST(!ISC_LINK_LINKED(io, link));
13127	INSIST(io->event == NULL);
13128
13129	zmgr = io->zmgr;
13130	isc_task_detach(&io->task);
13131	io->magic = 0;
13132	isc_mem_put(zmgr->mctx, io, sizeof(*io));
13133
13134	LOCK(&zmgr->iolock);
13135	INSIST(zmgr->ioactive > 0);
13136	zmgr->ioactive--;
13137	next = HEAD(zmgr->high);
13138	if (next == NULL)
13139		next = HEAD(zmgr->low);
13140	if (next != NULL) {
13141		if (next->high)
13142			ISC_LIST_UNLINK(zmgr->high, next, link);
13143		else
13144			ISC_LIST_UNLINK(zmgr->low, next, link);
13145		INSIST(next->event != NULL);
13146	}
13147	UNLOCK(&zmgr->iolock);
13148	if (next != NULL)
13149		isc_task_send(next->task, &next->event);
13150}
13151
13152static void
13153zonemgr_cancelio(dns_io_t *io) {
13154	isc_boolean_t send_event = ISC_FALSE;
13155
13156	REQUIRE(DNS_IO_VALID(io));
13157
13158	/*
13159	 * If we are queued to be run then dequeue.
13160	 */
13161	LOCK(&io->zmgr->iolock);
13162	if (ISC_LINK_LINKED(io, link)) {
13163		if (io->high)
13164			ISC_LIST_UNLINK(io->zmgr->high, io, link);
13165		else
13166			ISC_LIST_UNLINK(io->zmgr->low, io, link);
13167
13168		send_event = ISC_TRUE;
13169		INSIST(io->event != NULL);
13170	}
13171	UNLOCK(&io->zmgr->iolock);
13172	if (send_event) {
13173		io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
13174		isc_task_send(io->task, &io->event);
13175	}
13176}
13177
13178static void
13179zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
13180	char *buf;
13181	int buflen;
13182	isc_result_t result;
13183
13184	buflen = strlen(path) + strlen(templat) + 2;
13185
13186	buf = isc_mem_get(zone->mctx, buflen);
13187	if (buf == NULL)
13188		return;
13189
13190	result = isc_file_template(path, templat, buf, buflen);
13191	if (result != ISC_R_SUCCESS)
13192		goto cleanup;
13193
13194	result = isc_file_renameunique(path, buf);
13195	if (result != ISC_R_SUCCESS)
13196		goto cleanup;
13197
13198	dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
13199		     "renaming file to '%s' for failure analysis and "
13200		     "retransferring.", path, buf);
13201
13202 cleanup:
13203	isc_mem_put(zone->mctx, buf, buflen);
13204}
13205
13206#if 0
13207/* Hook for ondestroy notification from a database. */
13208
13209static void
13210dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
13211	dns_db_t *db = event->sender;
13212	UNUSED(task);
13213
13214	isc_event_free(&event);
13215
13216	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13217		      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13218		      "database (%p) destroyed", (void*) db);
13219}
13220#endif
13221
13222void
13223dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
13224	isc_interval_t interval;
13225	isc_uint32_t s, ns;
13226	isc_uint32_t pertic;
13227	isc_result_t result;
13228
13229	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13230
13231	if (value == 0)
13232		value = 1;
13233
13234	if (value == 1) {
13235		s = 1;
13236		ns = 0;
13237		pertic = 1;
13238	} else if (value <= 10) {
13239		s = 0;
13240		ns = 1000000000 / value;
13241		pertic = 1;
13242	} else {
13243		s = 0;
13244		ns = (1000000000 / value) * 10;
13245		pertic = 10;
13246	}
13247
13248	isc_interval_set(&interval, s, ns);
13249	result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
13250	RUNTIME_CHECK(result == ISC_R_SUCCESS);
13251	isc_ratelimiter_setpertic(zmgr->rl, pertic);
13252
13253	zmgr->serialqueryrate = value;
13254}
13255
13256unsigned int
13257dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
13258	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13259
13260	return (zmgr->serialqueryrate);
13261}
13262
13263isc_boolean_t
13264dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13265			isc_sockaddr_t *local, isc_time_t *now)
13266{
13267	unsigned int i;
13268	isc_rwlocktype_t locktype;
13269	isc_result_t result;
13270	isc_uint32_t seconds = isc_time_seconds(now);
13271
13272	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13273
13274	locktype = isc_rwlocktype_read;
13275	RWLOCK(&zmgr->urlock, locktype);
13276	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13277		if (zmgr->unreachable[i].expire >= seconds &&
13278		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13279		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
13280			result = isc_rwlock_tryupgrade(&zmgr->urlock);
13281			if (result == ISC_R_SUCCESS) {
13282				locktype = isc_rwlocktype_write;
13283				zmgr->unreachable[i].last = seconds;
13284			}
13285			break;
13286		}
13287	}
13288	RWUNLOCK(&zmgr->urlock, locktype);
13289	return (ISC_TF(i < UNREACH_CHACHE_SIZE));
13290}
13291
13292void
13293dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13294			   isc_sockaddr_t *local)
13295{
13296	unsigned int i;
13297	isc_rwlocktype_t locktype;
13298	isc_result_t result;
13299
13300	char master[ISC_SOCKADDR_FORMATSIZE];
13301	char source[ISC_SOCKADDR_FORMATSIZE];
13302
13303	isc_sockaddr_format(remote, master, sizeof(master));
13304	isc_sockaddr_format(local, source, sizeof(source));
13305
13306	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13307
13308	locktype = isc_rwlocktype_read;
13309	RWLOCK(&zmgr->urlock, locktype);
13310	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13311		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13312		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
13313			result = isc_rwlock_tryupgrade(&zmgr->urlock);
13314			if (result == ISC_R_SUCCESS) {
13315				locktype = isc_rwlocktype_write;
13316				zmgr->unreachable[i].expire = 0;
13317				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13318					      DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
13319					      "master %s (source %s) deleted "
13320					      "from unreachable cache",
13321					      master, source);
13322			}
13323			break;
13324		}
13325	}
13326	RWUNLOCK(&zmgr->urlock, locktype);
13327}
13328
13329void
13330dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13331			   isc_sockaddr_t *local, isc_time_t *now)
13332{
13333	isc_uint32_t seconds = isc_time_seconds(now);
13334	isc_uint32_t last = seconds;
13335	unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
13336
13337	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13338
13339	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
13340	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13341		/* Existing entry? */
13342		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13343		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
13344			break;
13345		/* Empty slot? */
13346		if (zmgr->unreachable[i].expire < seconds)
13347			slot = i;
13348		/* Least recently used slot? */
13349		if (zmgr->unreachable[i].last < last) {
13350			last = zmgr->unreachable[i].last;
13351			oldest = i;
13352		}
13353	}
13354	if (i < UNREACH_CHACHE_SIZE) {
13355		/*
13356		 * Found a existing entry.  Update the expire timer and
13357		 * last usage timestamps.
13358		 */
13359		zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
13360		zmgr->unreachable[i].last = seconds;
13361	} else if (slot != UNREACH_CHACHE_SIZE) {
13362		/*
13363		 * Found a empty slot. Add a new entry to the cache.
13364		 */
13365		zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
13366		zmgr->unreachable[slot].last = seconds;
13367		zmgr->unreachable[slot].remote = *remote;
13368		zmgr->unreachable[slot].local = *local;
13369	} else {
13370		/*
13371		 * Replace the least recently used entry in the cache.
13372		 */
13373		zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
13374		zmgr->unreachable[oldest].last = seconds;
13375		zmgr->unreachable[oldest].remote = *remote;
13376		zmgr->unreachable[oldest].local = *local;
13377	}
13378	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
13379}
13380
13381void
13382dns_zone_forcereload(dns_zone_t *zone) {
13383	REQUIRE(DNS_ZONE_VALID(zone));
13384
13385	if (zone->type == dns_zone_master)
13386		return;
13387
13388	LOCK_ZONE(zone);
13389	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13390	UNLOCK_ZONE(zone);
13391	dns_zone_refresh(zone);
13392}
13393
13394isc_boolean_t
13395dns_zone_isforced(dns_zone_t *zone) {
13396	REQUIRE(DNS_ZONE_VALID(zone));
13397
13398	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
13399}
13400
13401isc_result_t
13402dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
13403	/*
13404	 * This function is obsoleted.
13405	 */
13406	UNUSED(zone);
13407	UNUSED(on);
13408	return (ISC_R_NOTIMPLEMENTED);
13409}
13410
13411isc_uint64_t *
13412dns_zone_getstatscounters(dns_zone_t *zone) {
13413	/*
13414	 * This function is obsoleted.
13415	 */
13416	UNUSED(zone);
13417	return (NULL);
13418}
13419
13420void
13421dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
13422	REQUIRE(DNS_ZONE_VALID(zone));
13423	REQUIRE(zone->stats == NULL);
13424
13425	LOCK_ZONE(zone);
13426	zone->stats = NULL;
13427	isc_stats_attach(stats, &zone->stats);
13428	UNLOCK_ZONE(zone);
13429}
13430
13431void
13432dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
13433	REQUIRE(DNS_ZONE_VALID(zone));
13434
13435	LOCK_ZONE(zone);
13436	if (zone->requeststats_on && stats == NULL)
13437		zone->requeststats_on = ISC_FALSE;
13438	else if (!zone->requeststats_on && stats != NULL) {
13439		if (zone->requeststats == NULL) {
13440			isc_stats_attach(stats, &zone->requeststats);
13441			zone->requeststats_on = ISC_TRUE;
13442		}
13443	}
13444	UNLOCK_ZONE(zone);
13445
13446	return;
13447}
13448
13449isc_stats_t *
13450dns_zone_getrequeststats(dns_zone_t *zone) {
13451	/*
13452	 * We don't lock zone for efficiency reason.  This is not catastrophic
13453	 * because requeststats must always be valid when requeststats_on is
13454	 * true.
13455	 * Some counters may be incremented while requeststats_on is becoming
13456	 * false, or some cannot be incremented just after the statistics are
13457	 * installed, but it shouldn't matter much in practice.
13458	 */
13459	if (zone->requeststats_on)
13460		return (zone->requeststats);
13461	else
13462		return (NULL);
13463}
13464
13465void
13466dns_zone_dialup(dns_zone_t *zone) {
13467
13468	REQUIRE(DNS_ZONE_VALID(zone));
13469
13470	zone_debuglog(zone, "dns_zone_dialup", 3,
13471		      "notify = %d, refresh = %d",
13472		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
13473		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
13474
13475	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
13476		dns_zone_notify(zone);
13477	if (zone->type != dns_zone_master &&
13478	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
13479		dns_zone_refresh(zone);
13480}
13481
13482void
13483dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
13484	REQUIRE(DNS_ZONE_VALID(zone));
13485
13486	LOCK_ZONE(zone);
13487	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
13488			 DNS_ZONEFLG_DIALREFRESH |
13489			 DNS_ZONEFLG_NOREFRESH);
13490	switch (dialup) {
13491	case dns_dialuptype_no:
13492		break;
13493	case dns_dialuptype_yes:
13494		DNS_ZONE_SETFLAG(zone,	(DNS_ZONEFLG_DIALNOTIFY |
13495				 DNS_ZONEFLG_DIALREFRESH |
13496				 DNS_ZONEFLG_NOREFRESH));
13497		break;
13498	case dns_dialuptype_notify:
13499		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13500		break;
13501	case dns_dialuptype_notifypassive:
13502		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13503		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13504		break;
13505	case dns_dialuptype_refresh:
13506		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
13507		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13508		break;
13509	case dns_dialuptype_passive:
13510		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13511		break;
13512	default:
13513		INSIST(0);
13514	}
13515	UNLOCK_ZONE(zone);
13516}
13517
13518isc_result_t
13519dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
13520	isc_result_t result = ISC_R_SUCCESS;
13521
13522	REQUIRE(DNS_ZONE_VALID(zone));
13523
13524	LOCK_ZONE(zone);
13525	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
13526	UNLOCK_ZONE(zone);
13527
13528	return (result);
13529}
13530
13531const char *
13532dns_zone_getkeydirectory(dns_zone_t *zone) {
13533	REQUIRE(DNS_ZONE_VALID(zone));
13534
13535	return (zone->keydirectory);
13536}
13537
13538unsigned int
13539dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
13540	dns_zone_t *zone;
13541	unsigned int count = 0;
13542
13543	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13544
13545	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13546	switch (state) {
13547	case DNS_ZONESTATE_XFERRUNNING:
13548		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
13549		     zone != NULL;
13550		     zone = ISC_LIST_NEXT(zone, statelink))
13551			count++;
13552		break;
13553	case DNS_ZONESTATE_XFERDEFERRED:
13554		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
13555		     zone != NULL;
13556		     zone = ISC_LIST_NEXT(zone, statelink))
13557			count++;
13558		break;
13559	case DNS_ZONESTATE_SOAQUERY:
13560		for (zone = ISC_LIST_HEAD(zmgr->zones);
13561		     zone != NULL;
13562		     zone = ISC_LIST_NEXT(zone, link))
13563			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
13564				count++;
13565		break;
13566	case DNS_ZONESTATE_ANY:
13567		for (zone = ISC_LIST_HEAD(zmgr->zones);
13568		     zone != NULL;
13569		     zone = ISC_LIST_NEXT(zone, link)) {
13570			dns_view_t *view = zone->view;
13571			if (view != NULL && strcmp(view->name, "_bind") == 0)
13572				continue;
13573			count++;
13574		}
13575		break;
13576	default:
13577		INSIST(0);
13578	}
13579
13580	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13581
13582	return (count);
13583}
13584
13585isc_result_t
13586dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
13587	isc_boolean_t ok = ISC_TRUE;
13588	isc_boolean_t fail = ISC_FALSE;
13589	char namebuf[DNS_NAME_FORMATSIZE];
13590	char namebuf2[DNS_NAME_FORMATSIZE];
13591	char typebuf[DNS_RDATATYPE_FORMATSIZE];
13592	int level = ISC_LOG_WARNING;
13593	dns_name_t bad;
13594
13595	REQUIRE(DNS_ZONE_VALID(zone));
13596
13597	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
13598		return (ISC_R_SUCCESS);
13599
13600	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
13601		level = ISC_LOG_ERROR;
13602		fail = ISC_TRUE;
13603	}
13604
13605	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
13606	if (!ok) {
13607		dns_name_format(name, namebuf, sizeof(namebuf));
13608		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13609		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
13610			     dns_result_totext(DNS_R_BADOWNERNAME));
13611		if (fail)
13612			return (DNS_R_BADOWNERNAME);
13613	}
13614
13615	dns_name_init(&bad, NULL);
13616	ok = dns_rdata_checknames(rdata, name, &bad);
13617	if (!ok) {
13618		dns_name_format(name, namebuf, sizeof(namebuf));
13619		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
13620		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13621		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
13622			     namebuf2, dns_result_totext(DNS_R_BADNAME));
13623		if (fail)
13624			return (DNS_R_BADNAME);
13625	}
13626
13627	return (ISC_R_SUCCESS);
13628}
13629
13630void
13631dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
13632	REQUIRE(DNS_ZONE_VALID(zone));
13633	zone->checkmx = checkmx;
13634}
13635
13636void
13637dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
13638	REQUIRE(DNS_ZONE_VALID(zone));
13639	zone->checksrv = checksrv;
13640}
13641
13642void
13643dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
13644	REQUIRE(DNS_ZONE_VALID(zone));
13645	zone->checkns = checkns;
13646}
13647
13648void
13649dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
13650	REQUIRE(DNS_ZONE_VALID(zone));
13651
13652	LOCK_ZONE(zone);
13653	zone->isself = isself;
13654	zone->isselfarg = arg;
13655	UNLOCK_ZONE(zone);
13656}
13657
13658void
13659dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
13660	REQUIRE(DNS_ZONE_VALID(zone));
13661
13662	LOCK_ZONE(zone);
13663	zone->notifydelay = delay;
13664	UNLOCK_ZONE(zone);
13665}
13666
13667isc_uint32_t
13668dns_zone_getnotifydelay(dns_zone_t *zone) {
13669	REQUIRE(DNS_ZONE_VALID(zone));
13670
13671	return (zone->notifydelay);
13672}
13673
13674isc_result_t
13675dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
13676		     isc_uint16_t keyid, isc_boolean_t delete)
13677{
13678	isc_result_t result;
13679	REQUIRE(DNS_ZONE_VALID(zone));
13680
13681	dns_zone_log(zone, ISC_LOG_NOTICE,
13682		     "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
13683		     algorithm, keyid);
13684	LOCK_ZONE(zone);
13685	result = zone_signwithkey(zone, algorithm, keyid, delete);
13686	UNLOCK_ZONE(zone);
13687
13688	return (result);
13689}
13690
13691static const char *hex = "0123456789ABCDEF";
13692
13693isc_result_t
13694dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
13695	isc_result_t result;
13696	char salt[255*2+1];
13697	unsigned int i, j;
13698
13699	REQUIRE(DNS_ZONE_VALID(zone));
13700
13701	if (nsec3param->salt_length != 0) {
13702		INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
13703		for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
13704			salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
13705			salt[j++] = hex[nsec3param->salt[i] & 0xf];
13706		}
13707		salt[j] = '\0';
13708	} else
13709		strcpy(salt, "-");
13710	dns_zone_log(zone, ISC_LOG_NOTICE,
13711		     "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
13712		     nsec3param->hash, nsec3param->iterations,
13713		     salt);
13714	LOCK_ZONE(zone);
13715	result = zone_addnsec3chain(zone, nsec3param);
13716	UNLOCK_ZONE(zone);
13717
13718	return (result);
13719}
13720
13721void
13722dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
13723	REQUIRE(DNS_ZONE_VALID(zone));
13724
13725	if (nodes == 0)
13726		nodes = 1;
13727	zone->nodes = nodes;
13728}
13729
13730void
13731dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
13732	REQUIRE(DNS_ZONE_VALID(zone));
13733
13734	/*
13735	 * We treat signatures as a signed value so explicitly
13736	 * limit its range here.
13737	 */
13738	if (signatures > ISC_INT32_MAX)
13739		signatures = ISC_INT32_MAX;
13740	else if (signatures == 0)
13741		signatures = 1;
13742	zone->signatures = signatures;
13743}
13744
13745void
13746dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
13747	REQUIRE(DNS_ZONE_VALID(zone));
13748	zone->privatetype = type;
13749}
13750
13751dns_rdatatype_t
13752dns_zone_getprivatetype(dns_zone_t *zone) {
13753	REQUIRE(DNS_ZONE_VALID(zone));
13754	return (zone->privatetype);
13755}
13756
13757static isc_result_t
13758zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
13759		 isc_boolean_t delete)
13760{
13761	dns_signing_t *signing;
13762	dns_signing_t *current;
13763	isc_result_t result = ISC_R_SUCCESS;
13764	isc_time_t now;
13765
13766	signing = isc_mem_get(zone->mctx, sizeof *signing);
13767	if (signing == NULL)
13768		return (ISC_R_NOMEMORY);
13769
13770	signing->magic = 0;
13771	signing->db  = NULL;
13772	signing->dbiterator = NULL;
13773	signing->algorithm = algorithm;
13774	signing->keyid = keyid;
13775	signing->delete = delete;
13776	signing->done = ISC_FALSE;
13777
13778	TIME_NOW(&now);
13779
13780	for (current = ISC_LIST_HEAD(zone->signing);
13781	     current != NULL;
13782	     current = ISC_LIST_NEXT(current, link)) {
13783		if (current->db == zone->db &&
13784		    current->algorithm == signing->algorithm &&
13785		    current->keyid == signing->keyid) {
13786			if (current->delete != signing->delete)
13787				current->done = ISC_TRUE;
13788			else
13789				goto cleanup;
13790		}
13791	}
13792
13793	if (zone->db != NULL) {
13794		dns_db_attach(zone->db, &signing->db);
13795		result = dns_db_createiterator(signing->db, 0,
13796					       &signing->dbiterator);
13797
13798		if (result == ISC_R_SUCCESS)
13799			result = dns_dbiterator_first(signing->dbiterator);
13800		if (result == ISC_R_SUCCESS) {
13801			dns_dbiterator_pause(signing->dbiterator);
13802			ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
13803			signing = NULL;
13804			if (isc_time_isepoch(&zone->signingtime)) {
13805				zone->signingtime = now;
13806				if (zone->task != NULL)
13807					zone_settimer(zone, &now);
13808			}
13809		}
13810	} else
13811		result = ISC_R_NOTFOUND;
13812
13813 cleanup:
13814	if (signing != NULL) {
13815		if (signing->db != NULL)
13816			dns_db_detach(&signing->db);
13817		if (signing->dbiterator != NULL)
13818			dns_dbiterator_destroy(&signing->dbiterator);
13819		isc_mem_put(zone->mctx, signing, sizeof *signing);
13820	}
13821	return (result);
13822}
13823
13824static void
13825logmsg(const char *format, ...) {
13826	va_list args;
13827	va_start(args, format);
13828	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
13829		       ISC_LOG_DEBUG(1), format, args);
13830	va_end(args);
13831}
13832
13833static void
13834clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
13835	dns_dnsseckey_t *key;
13836	while (!ISC_LIST_EMPTY(*list)) {
13837		key = ISC_LIST_HEAD(*list);
13838		ISC_LIST_UNLINK(*list, key, link);
13839		dns_dnsseckey_destroy(mctx, &key);
13840	}
13841}
13842
13843/* Called once; *timep should be set to the current time. */
13844static isc_result_t
13845next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
13846	isc_result_t result;
13847	isc_stdtime_t now, then = 0, event;
13848	int i;
13849
13850	now = *timep;
13851
13852	for (i = 0; i <= DST_MAX_TIMES; i++) {
13853		result = dst_key_gettime(key, i, &event);
13854		if (result == ISC_R_SUCCESS && event > now &&
13855		    (then == 0 || event < then))
13856			then = event;
13857	}
13858
13859	if (then != 0) {
13860		*timep = then;
13861		return (ISC_R_SUCCESS);
13862	}
13863
13864	return (ISC_R_NOTFOUND);
13865}
13866
13867static isc_result_t
13868rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
13869	  const dns_rdata_t *rdata, isc_boolean_t *flag)
13870{
13871	dns_rdataset_t rdataset;
13872	dns_dbnode_t *node = NULL;
13873	isc_result_t result;
13874
13875	dns_rdataset_init(&rdataset);
13876	if (rdata->type == dns_rdatatype_nsec3)
13877		CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
13878	else
13879		CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
13880	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
13881				     (isc_stdtime_t) 0, &rdataset, NULL);
13882	if (result == ISC_R_NOTFOUND) {
13883		*flag = ISC_FALSE;
13884		result = ISC_R_SUCCESS;
13885		goto failure;
13886	}
13887
13888	for (result = dns_rdataset_first(&rdataset);
13889	     result == ISC_R_SUCCESS;
13890	     result = dns_rdataset_next(&rdataset)) {
13891		dns_rdata_t myrdata = DNS_RDATA_INIT;
13892		dns_rdataset_current(&rdataset, &myrdata);
13893		if (!dns_rdata_compare(&myrdata, rdata))
13894			break;
13895	}
13896	dns_rdataset_disassociate(&rdataset);
13897	if (result == ISC_R_SUCCESS) {
13898		*flag = ISC_TRUE;
13899	} else if (result == ISC_R_NOMORE) {
13900		*flag = ISC_FALSE;
13901		result = ISC_R_SUCCESS;
13902	}
13903
13904 failure:
13905	if (node != NULL)
13906		dns_db_detachnode(db, &node);
13907	return (result);
13908}
13909
13910/*
13911 * Add records to signal the state of signing or of key removal.
13912 */
13913static isc_result_t
13914add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
13915		    dns_dbversion_t *ver, dns_diff_t *diff,
13916		    isc_boolean_t sign_all)
13917{
13918	dns_difftuple_t *tuple, *newtuple = NULL;
13919	dns_rdata_dnskey_t dnskey;
13920	dns_rdata_t rdata = DNS_RDATA_INIT;
13921	isc_boolean_t flag;
13922	isc_region_t r;
13923	isc_result_t result = ISC_R_SUCCESS;
13924	isc_uint16_t keyid;
13925	unsigned char buf[5];
13926	dns_name_t *name = dns_db_origin(db);
13927
13928	for (tuple = ISC_LIST_HEAD(diff->tuples);
13929	     tuple != NULL;
13930	     tuple = ISC_LIST_NEXT(tuple, link)) {
13931		if (tuple->rdata.type != dns_rdatatype_dnskey)
13932			continue;
13933
13934		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
13935		RUNTIME_CHECK(result == ISC_R_SUCCESS);
13936		if ((dnskey.flags &
13937		     (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
13938			 != DNS_KEYOWNER_ZONE)
13939			continue;
13940
13941		dns_rdata_toregion(&tuple->rdata, &r);
13942
13943		keyid = dst_region_computeid(&r, dnskey.algorithm);
13944
13945		buf[0] = dnskey.algorithm;
13946		buf[1] = (keyid & 0xff00) >> 8;
13947		buf[2] = (keyid & 0xff);
13948		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
13949		buf[4] = 0;
13950		rdata.data = buf;
13951		rdata.length = sizeof(buf);
13952		rdata.type = privatetype;
13953		rdata.rdclass = tuple->rdata.rdclass;
13954
13955		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
13956			CHECK(rr_exists(db, ver, name, &rdata, &flag));
13957			if (flag)
13958				continue;
13959			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
13960						   name, 0, &rdata, &newtuple));
13961			CHECK(do_one_tuple(&newtuple, db, ver, diff));
13962			INSIST(newtuple == NULL);
13963		}
13964
13965		/*
13966		 * Remove any record which says this operation has already
13967		 * completed.
13968		 */
13969		buf[4] = 1;
13970		CHECK(rr_exists(db, ver, name, &rdata, &flag));
13971		if (flag) {
13972			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
13973						   name, 0, &rdata, &newtuple));
13974			CHECK(do_one_tuple(&newtuple, db, ver, diff));
13975			INSIST(newtuple == NULL);
13976		}
13977	}
13978 failure:
13979	return (result);
13980}
13981
13982static isc_result_t
13983sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
13984	  dns_diff_t *diff, dns_diff_t *sig_diff)
13985{
13986	isc_result_t result;
13987	isc_stdtime_t now, inception, soaexpire;
13988	isc_boolean_t check_ksk, keyset_kskonly;
13989	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
13990	unsigned int nkeys = 0, i;
13991	dns_difftuple_t *tuple;
13992
13993	result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
13994				zone_keys, &nkeys);
13995	if (result != ISC_R_SUCCESS) {
13996		dns_zone_log(zone, ISC_LOG_ERROR,
13997			     "sign_apex:find_zone_keys -> %s\n",
13998			     dns_result_totext(result));
13999		return (result);
14000	}
14001
14002	isc_stdtime_get(&now);
14003	inception = now - 3600;	/* Allow for clock skew. */
14004	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
14005
14006	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
14007	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
14008
14009	/*
14010	 * See if update_sigs will update DNSKEY signature and if not
14011	 * cause them to sign so that so that newly activated keys
14012	 * are used.
14013	 */
14014	for (tuple = ISC_LIST_HEAD(diff->tuples);
14015	     tuple != NULL;
14016	     tuple = ISC_LIST_NEXT(tuple, link)) {
14017		if (tuple->rdata.type == dns_rdatatype_dnskey &&
14018		    dns_name_equal(&tuple->name, &zone->origin))
14019			break;
14020	}
14021
14022	if (tuple == NULL) {
14023		result = del_sigs(zone, db, ver, &zone->origin,
14024				  dns_rdatatype_dnskey, sig_diff,
14025				  zone_keys, nkeys, now, ISC_FALSE);
14026		if (result != ISC_R_SUCCESS) {
14027			dns_zone_log(zone, ISC_LOG_ERROR,
14028				     "sign_apex:del_sigs -> %s\n",
14029				     dns_result_totext(result));
14030			goto failure;
14031		}
14032		result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
14033				  sig_diff, zone_keys, nkeys, zone->mctx,
14034				  inception, soaexpire, check_ksk,
14035				  keyset_kskonly);
14036		if (result != ISC_R_SUCCESS) {
14037			dns_zone_log(zone, ISC_LOG_ERROR,
14038				     "sign_apex:add_sigs -> %s\n",
14039				     dns_result_totext(result));
14040			goto failure;
14041		}
14042	}
14043
14044	result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
14045			     inception, soaexpire, now, check_ksk,
14046			     keyset_kskonly, sig_diff);
14047
14048	if (result != ISC_R_SUCCESS) {
14049		dns_zone_log(zone, ISC_LOG_ERROR,
14050			     "sign_apex:update_sigs -> %s\n",
14051			     dns_result_totext(result));
14052		goto failure;
14053	}
14054
14055 failure:
14056	for (i = 0; i < nkeys; i++)
14057		dst_key_free(&zone_keys[i]);
14058	return (result);
14059}
14060
14061/*
14062 * Prevent the zone entering a inconsistent state where
14063 * NSEC only DNSKEYs are present with NSEC3 chains.
14064 * See update.c:check_dnssec()
14065 */
14066static isc_boolean_t
14067dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14068	    dns_diff_t *diff)
14069{
14070	isc_result_t result;
14071	dns_difftuple_t *tuple;
14072	isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
14073	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
14074
14075	/* Scan the tuples for an NSEC-only DNSKEY */
14076	for (tuple = ISC_LIST_HEAD(diff->tuples);
14077	     tuple != NULL;
14078	     tuple = ISC_LIST_NEXT(tuple, link)) {
14079		isc_uint8_t alg;
14080		if (tuple->rdata.type != dns_rdatatype_dnskey ||
14081		    tuple->op != DNS_DIFFOP_ADD)
14082			continue;
14083
14084		alg = tuple->rdata.data[3];
14085		if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
14086		    alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
14087			nseconly = ISC_TRUE;
14088			break;
14089		}
14090	}
14091
14092	/* Check existing DB for NSEC-only DNSKEY */
14093	if (!nseconly)
14094		CHECK(dns_nsec_nseconly(db, ver, &nseconly));
14095
14096	/* Check existing DB for NSEC3 */
14097	if (!nsec3)
14098		CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
14099					privatetype, &nsec3));
14100
14101	/* Refuse to allow NSEC3 with NSEC-only keys */
14102	if (nseconly && nsec3) {
14103		dns_zone_log(zone, ISC_LOG_ERROR,
14104			   "NSEC only DNSKEYs and NSEC3 chains not allowed");
14105		goto failure;
14106	}
14107
14108	return (ISC_TRUE);
14109
14110 failure:
14111	return (ISC_FALSE);
14112}
14113
14114static isc_result_t
14115clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14116		 dns_diff_t *diff)
14117{
14118	isc_result_t result;
14119	dns_dbnode_t *node = NULL;
14120	dns_rdataset_t rdataset;
14121
14122	dns_rdataset_init(&rdataset);
14123	CHECK(dns_db_getoriginnode(db, &node));
14124
14125	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
14126				     dns_rdatatype_none, 0, &rdataset, NULL);
14127	if (dns_rdataset_isassociated(&rdataset))
14128		dns_rdataset_disassociate(&rdataset);
14129	if (result != ISC_R_NOTFOUND)
14130		goto failure;
14131
14132	result = dns_nsec3param_deletechains(db, ver, zone, diff);
14133
14134 failure:
14135	if (node != NULL)
14136		dns_db_detachnode(db, &node);
14137	return (result);
14138}
14139
14140/*
14141 * Given an RRSIG rdataset and an algorithm, determine whether there
14142 * are any signatures using that algorithm.
14143 */
14144static isc_boolean_t
14145signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
14146	dns_rdata_t rdata = DNS_RDATA_INIT;
14147	dns_rdata_rrsig_t rrsig;
14148	isc_result_t result;
14149
14150	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
14151	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
14152		return (ISC_FALSE);
14153	}
14154
14155	for (result = dns_rdataset_first(rdataset);
14156	     result == ISC_R_SUCCESS;
14157	     result = dns_rdataset_next(rdataset))
14158	{
14159		dns_rdataset_current(rdataset, &rdata);
14160		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
14161		RUNTIME_CHECK(result == ISC_R_SUCCESS);
14162		dns_rdata_reset(&rdata);
14163		if (rrsig.algorithm == alg)
14164			return (ISC_TRUE);
14165	}
14166
14167	return (ISC_FALSE);
14168}
14169
14170static isc_result_t
14171add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14172	   dns_diff_t *diff)
14173{
14174	dns_name_t *origin;
14175	isc_boolean_t build_nsec3;
14176	isc_result_t result;
14177
14178	origin = dns_db_origin(db);
14179	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
14180				 &build_nsec3));
14181	if (build_nsec3)
14182		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
14183					   ISC_FALSE, zone->privatetype, diff));
14184	CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
14185
14186 failure:
14187	return (result);
14188}
14189
14190static void
14191zone_rekey(dns_zone_t *zone) {
14192	isc_result_t result;
14193	dns_db_t *db = NULL;
14194	dns_dbnode_t *node = NULL;
14195	dns_dbversion_t *ver = NULL;
14196	dns_rdataset_t soaset, soasigs, keyset, keysigs;
14197	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
14198	dns_dnsseckey_t *key;
14199	dns_diff_t diff, sig_diff;
14200	isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
14201	isc_boolean_t newalg = ISC_FALSE;
14202	isc_boolean_t fullsign;
14203	dns_ttl_t ttl = 3600;
14204	const char *dir;
14205	isc_mem_t *mctx;
14206	isc_stdtime_t now;
14207	isc_time_t timenow;
14208	isc_interval_t ival;
14209	char timebuf[80];
14210
14211	REQUIRE(DNS_ZONE_VALID(zone));
14212
14213	ISC_LIST_INIT(dnskeys);
14214	ISC_LIST_INIT(keys);
14215	ISC_LIST_INIT(rmkeys);
14216	dns_rdataset_init(&soaset);
14217	dns_rdataset_init(&soasigs);
14218	dns_rdataset_init(&keyset);
14219	dns_rdataset_init(&keysigs);
14220	dir = dns_zone_getkeydirectory(zone);
14221	mctx = zone->mctx;
14222	dns_diff_init(mctx, &diff);
14223	dns_diff_init(mctx, &sig_diff);
14224	sig_diff.resign = zone->sigresigninginterval;
14225
14226	CHECK(dns_zone_getdb(zone, &db));
14227	CHECK(dns_db_newversion(db, &ver));
14228	CHECK(dns_db_getoriginnode(db, &node));
14229
14230	TIME_NOW(&timenow);
14231	now = isc_time_seconds(&timenow);
14232
14233	dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
14234
14235	/* Get the SOA record's TTL */
14236	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
14237				  dns_rdatatype_none, 0, &soaset, &soasigs));
14238	ttl = soaset.ttl;
14239	dns_rdataset_disassociate(&soaset);
14240
14241	/* Get the DNSKEY rdataset */
14242	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
14243				     dns_rdatatype_none, 0, &keyset, &keysigs);
14244	if (result == ISC_R_SUCCESS) {
14245		ttl = keyset.ttl;
14246		result = dns_dnssec_keylistfromrdataset(&zone->origin, dir,
14247							mctx, &keyset,
14248							&keysigs, &soasigs,
14249							ISC_FALSE, ISC_FALSE,
14250							&dnskeys);
14251		/* Can't get keys for some reason; try again later. */
14252		if (result != ISC_R_SUCCESS)
14253			goto trylater;
14254	} else if (result != ISC_R_NOTFOUND)
14255		goto failure;
14256
14257	/*
14258	 * True when called from "rndc sign".  Indicates the zone should be
14259	 * fully signed now.
14260	 */
14261	fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
14262
14263	result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
14264	if (result == ISC_R_SUCCESS) {
14265		isc_boolean_t check_ksk;
14266		check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
14267
14268		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
14269					       &zone->origin, ttl, &diff,
14270					       ISC_TF(!check_ksk),
14271					       mctx, logmsg);
14272
14273		/* Keys couldn't be updated for some reason;
14274		 * try again later. */
14275		if (result != ISC_R_SUCCESS) {
14276			dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
14277				     "couldn't update zone keys: %s",
14278				     isc_result_totext(result));
14279			goto trylater;
14280		}
14281
14282		/*
14283		 * See if any pre-existing keys have newly become active;
14284		 * also, see if any new key is for a new algorithm, as in that
14285		 * event, we need to sign the zone fully.  (If there's a new
14286		 * key, but it's for an already-existing algorithm, then
14287		 * the zone signing can be handled incrementally.)
14288		 */
14289		for (key = ISC_LIST_HEAD(dnskeys);
14290		     key != NULL;
14291		     key = ISC_LIST_NEXT(key, link)) {
14292			if (!key->first_sign)
14293				continue;
14294
14295			newactive = ISC_TRUE;
14296
14297			if (!dns_rdataset_isassociated(&keysigs)) {
14298				newalg = ISC_TRUE;
14299				break;
14300			}
14301
14302			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
14303				/*
14304				 * This isn't a new algorithm; clear
14305				 * first_sign so we won't sign the
14306				 * whole zone with this key later
14307				 */
14308				key->first_sign = ISC_FALSE;
14309			} else {
14310				newalg = ISC_TRUE;
14311				break;
14312			}
14313		}
14314
14315		if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
14316		    dnskey_sane(zone, db, ver, &diff)) {
14317			CHECK(dns_diff_apply(&diff, db, ver));
14318			CHECK(clean_nsec3param(zone, db, ver, &diff));
14319			CHECK(add_signing_records(db, zone->privatetype,
14320						  ver, &diff,
14321						  ISC_TF(newalg || fullsign)));
14322			CHECK(increment_soa_serial(db, ver, &diff, mctx));
14323			CHECK(add_chains(zone, db, ver, &diff));
14324			CHECK(sign_apex(zone, db, ver, &diff, &sig_diff));
14325			CHECK(zone_journal(zone, &sig_diff, "zone_rekey"));
14326			commit = ISC_TRUE;
14327		}
14328	}
14329
14330	dns_db_closeversion(db, &ver, commit);
14331
14332	if (commit) {
14333		dns_difftuple_t *tuple;
14334
14335		LOCK_ZONE(zone);
14336		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14337
14338		zone_needdump(zone, DNS_DUMP_DELAY);
14339
14340		zone_settimer(zone, &timenow);
14341
14342		/* Remove any signatures from removed keys.  */
14343		if (!ISC_LIST_EMPTY(rmkeys)) {
14344			for (key = ISC_LIST_HEAD(rmkeys);
14345			     key != NULL;
14346			     key = ISC_LIST_NEXT(key, link)) {
14347				result = zone_signwithkey(zone,
14348							  dst_key_alg(key->key),
14349							  dst_key_id(key->key),
14350							  ISC_TRUE);
14351				if (result != ISC_R_SUCCESS) {
14352					dns_zone_log(zone, ISC_LOG_ERROR,
14353					     "zone_signwithkey failed: %s",
14354					     dns_result_totext(result));
14355				}
14356			}
14357		}
14358
14359		if (fullsign) {
14360			/*
14361			 * "rndc sign" was called, so we now sign the zone
14362			 * with all active keys, whether they're new or not.
14363			 */
14364			for (key = ISC_LIST_HEAD(dnskeys);
14365			     key != NULL;
14366			     key = ISC_LIST_NEXT(key, link)) {
14367				if (!key->force_sign && !key->hint_sign)
14368					continue;
14369
14370				result = zone_signwithkey(zone,
14371							  dst_key_alg(key->key),
14372							  dst_key_id(key->key),
14373							  ISC_FALSE);
14374				if (result != ISC_R_SUCCESS) {
14375					dns_zone_log(zone, ISC_LOG_ERROR,
14376					     "zone_signwithkey failed: %s",
14377					     dns_result_totext(result));
14378				}
14379			}
14380		} else if (newalg) {
14381			/*
14382			 * We haven't been told to sign fully, but a new
14383			 * algorithm was added to the DNSKEY.  We sign
14384			 * the full zone, but only with newly active
14385			 * keys.
14386			 */
14387			for (key = ISC_LIST_HEAD(dnskeys);
14388			     key != NULL;
14389			     key = ISC_LIST_NEXT(key, link)) {
14390				if (!key->first_sign)
14391					continue;
14392
14393				result = zone_signwithkey(zone,
14394							  dst_key_alg(key->key),
14395							  dst_key_id(key->key),
14396							  ISC_FALSE);
14397				if (result != ISC_R_SUCCESS) {
14398					dns_zone_log(zone, ISC_LOG_ERROR,
14399					     "zone_signwithkey failed: %s",
14400					     dns_result_totext(result));
14401				}
14402			}
14403		}
14404
14405		/*
14406		 * Clear fullsign flag, if it was set, so we don't do
14407		 * another full signing next time
14408		 */
14409		zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
14410
14411		/*
14412		 * Cause the zone to add/delete NSEC3 chains for the
14413		 * deferred NSEC3PARAM changes.
14414		 */
14415		for (tuple = ISC_LIST_HEAD(sig_diff.tuples);
14416		     tuple != NULL;
14417		     tuple = ISC_LIST_NEXT(tuple, link)) {
14418			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
14419			dns_rdata_t rdata = DNS_RDATA_INIT;
14420			dns_rdata_nsec3param_t nsec3param;
14421
14422			if (tuple->rdata.type != zone->privatetype ||
14423			    tuple->op != DNS_DIFFOP_ADD)
14424				continue;
14425
14426			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
14427							buf, sizeof(buf)))
14428				continue;
14429			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
14430			RUNTIME_CHECK(result == ISC_R_SUCCESS);
14431			if (nsec3param.flags == 0)
14432				continue;
14433
14434			result = zone_addnsec3chain(zone, &nsec3param);
14435			if (result != ISC_R_SUCCESS) {
14436				dns_zone_log(zone, ISC_LOG_ERROR,
14437					     "zone_addnsec3chain failed: %s",
14438					     dns_result_totext(result));
14439			}
14440		}
14441
14442		/*
14443		 * Schedule the next resigning event
14444		 */
14445		set_resigntime(zone);
14446		UNLOCK_ZONE(zone);
14447	}
14448
14449	isc_time_settoepoch(&zone->refreshkeytime);
14450
14451	/*
14452	 * If we're doing key maintenance, set the key refresh timer to
14453	 * the next scheduled key event or to one hour in the future,
14454	 * whichever is sooner.
14455	 */
14456	if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
14457		isc_time_t timethen;
14458		isc_stdtime_t then;
14459
14460		LOCK_ZONE(zone);
14461		DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
14462		zone->refreshkeytime = timethen;
14463		UNLOCK_ZONE(zone);
14464
14465		for (key = ISC_LIST_HEAD(dnskeys);
14466		     key != NULL;
14467		     key = ISC_LIST_NEXT(key, link)) {
14468			then = now;
14469			result = next_keyevent(key->key, &then);
14470			if (result != ISC_R_SUCCESS)
14471				continue;
14472
14473			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
14474			LOCK_ZONE(zone);
14475			if (isc_time_compare(&timethen,
14476					     &zone->refreshkeytime) < 0) {
14477				zone->refreshkeytime = timethen;
14478			}
14479			UNLOCK_ZONE(zone);
14480		}
14481
14482		zone_settimer(zone, &timenow);
14483
14484		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
14485		dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
14486	}
14487
14488 failure:
14489	dns_diff_clear(&diff);
14490	dns_diff_clear(&sig_diff);
14491
14492	clear_keylist(&dnskeys, mctx);
14493	clear_keylist(&keys, mctx);
14494	clear_keylist(&rmkeys, mctx);
14495
14496	if (ver != NULL)
14497		dns_db_closeversion(db, &ver, ISC_FALSE);
14498	if (dns_rdataset_isassociated(&keyset))
14499		dns_rdataset_disassociate(&keyset);
14500	if (dns_rdataset_isassociated(&keysigs))
14501		dns_rdataset_disassociate(&keysigs);
14502	if (dns_rdataset_isassociated(&soasigs))
14503		dns_rdataset_disassociate(&soasigs);
14504	if (node != NULL)
14505		dns_db_detachnode(db, &node);
14506	if (db != NULL)
14507		dns_db_detach(&db);
14508	return;
14509
14510 trylater:
14511	isc_interval_set(&ival, HOUR, 0);
14512	isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
14513	goto failure;
14514}
14515
14516void
14517dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
14518	isc_time_t now;
14519
14520	if (zone->type == dns_zone_master && zone->task != NULL) {
14521		LOCK_ZONE(zone);
14522
14523		if (fullsign)
14524			zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
14525
14526		TIME_NOW(&now);
14527		zone->refreshkeytime = now;
14528		zone_settimer(zone, &now);
14529
14530		UNLOCK_ZONE(zone);
14531	}
14532}
14533
14534isc_result_t
14535dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
14536		 unsigned int *errors)
14537{
14538	isc_result_t result;
14539	dns_dbnode_t *node = NULL;
14540
14541	REQUIRE(DNS_ZONE_VALID(zone));
14542	REQUIRE(errors != NULL);
14543
14544	result = dns_db_getoriginnode(db, &node);
14545	if (result != ISC_R_SUCCESS)
14546		return (result);
14547	result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
14548				  ISC_FALSE);
14549	dns_db_detachnode(db, &node);
14550	return (result);
14551}
14552
14553void
14554dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
14555	REQUIRE(DNS_ZONE_VALID(zone));
14556	LOCK_ZONE(zone);
14557	zone->added = added;
14558	UNLOCK_ZONE(zone);
14559}
14560
14561isc_boolean_t
14562dns_zone_getadded(dns_zone_t *zone) {
14563	REQUIRE(DNS_ZONE_VALID(zone));
14564	return (zone->added);
14565}
14566
14567isc_result_t
14568dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
14569{
14570	isc_time_t loadtime;
14571	isc_result_t result;
14572	TIME_NOW(&loadtime);
14573
14574	LOCK_ZONE(zone);
14575	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
14576	UNLOCK_ZONE(zone);
14577	return result;
14578}
14579