1/*	$NetBSD: zone.c,v 1.4.4.3 2012/12/15 05:40:00 riz Exp $	*/
2
3/*
4 * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003  Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/* Id */
21
22/*! \file */
23
24#include <config.h>
25#include <errno.h>
26
27#include <isc/file.h>
28#include <isc/hex.h>
29#include <isc/mutex.h>
30#include <isc/print.h>
31#include <isc/random.h>
32#include <isc/ratelimiter.h>
33#include <isc/refcount.h>
34#include <isc/rwlock.h>
35#include <isc/serial.h>
36#include <isc/stats.h>
37#include <isc/stdtime.h>
38#include <isc/strerror.h>
39#include <isc/string.h>
40#include <isc/taskpool.h>
41#include <isc/timer.h>
42#include <isc/util.h>
43
44#include <dns/acache.h>
45#include <dns/acl.h>
46#include <dns/adb.h>
47#include <dns/callbacks.h>
48#include <dns/db.h>
49#include <dns/dbiterator.h>
50#include <dns/dnssec.h>
51#include <dns/events.h>
52#include <dns/journal.h>
53#include <dns/keydata.h>
54#include <dns/keytable.h>
55#include <dns/keyvalues.h>
56#include <dns/log.h>
57#include <dns/master.h>
58#include <dns/masterdump.h>
59#include <dns/message.h>
60#include <dns/name.h>
61#include <dns/nsec.h>
62#include <dns/nsec3.h>
63#include <dns/peer.h>
64#include <dns/private.h>
65#include <dns/rbt.h>
66#include <dns/rcode.h>
67#include <dns/rdata.h>
68#include <dns/rdataclass.h>
69#include <dns/rdatalist.h>
70#include <dns/rdataset.h>
71#include <dns/rdatasetiter.h>
72#include <dns/rdatastruct.h>
73#include <dns/rdatatype.h>
74#include <dns/request.h>
75#include <dns/resolver.h>
76#include <dns/result.h>
77#include <dns/rriterator.h>
78#include <dns/soa.h>
79#include <dns/ssu.h>
80#include <dns/stats.h>
81#include <dns/time.h>
82#include <dns/tsig.h>
83#include <dns/update.h>
84#include <dns/xfrin.h>
85#include <dns/zone.h>
86#include <dns/zt.h>
87
88#include <dst/dst.h>
89
90#define ZONE_MAGIC			ISC_MAGIC('Z', 'O', 'N', 'E')
91#define DNS_ZONE_VALID(zone)		ISC_MAGIC_VALID(zone, ZONE_MAGIC)
92
93#define NOTIFY_MAGIC			ISC_MAGIC('N', 't', 'f', 'y')
94#define DNS_NOTIFY_VALID(notify)	ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
95
96#define STUB_MAGIC			ISC_MAGIC('S', 't', 'u', 'b')
97#define DNS_STUB_VALID(stub)		ISC_MAGIC_VALID(stub, STUB_MAGIC)
98
99#define ZONEMGR_MAGIC			ISC_MAGIC('Z', 'm', 'g', 'r')
100#define DNS_ZONEMGR_VALID(stub)		ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
101
102#define LOAD_MAGIC			ISC_MAGIC('L', 'o', 'a', 'd')
103#define DNS_LOAD_VALID(load)		ISC_MAGIC_VALID(load, LOAD_MAGIC)
104
105#define FORWARD_MAGIC			ISC_MAGIC('F', 'o', 'r', 'w')
106#define DNS_FORWARD_VALID(load)		ISC_MAGIC_VALID(load, FORWARD_MAGIC)
107
108#define IO_MAGIC			ISC_MAGIC('Z', 'm', 'I', 'O')
109#define DNS_IO_VALID(load)		ISC_MAGIC_VALID(load, IO_MAGIC)
110
111/*%
112 * Ensure 'a' is at least 'min' but not more than 'max'.
113 */
114#define RANGE(a, min, max) \
115		(((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
116
117#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
118
119/*%
120 * Key flags
121 */
122#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
123#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
124#define ALG(x) dst_key_alg(x)
125
126/*
127 * Default values.
128 */
129#define DNS_DEFAULT_IDLEIN 3600		/*%< 1 hour */
130#define DNS_DEFAULT_IDLEOUT 3600	/*%< 1 hour */
131#define MAX_XFER_TIME (2*3600)		/*%< Documented default is 2 hours */
132#define RESIGN_DELAY 3600		/*%< 1 hour */
133
134#ifndef DNS_MAX_EXPIRE
135#define DNS_MAX_EXPIRE	14515200	/*%< 24 weeks */
136#endif
137
138#ifndef DNS_DUMP_DELAY
139#define DNS_DUMP_DELAY 900		/*%< 15 minutes */
140#endif
141
142typedef struct dns_notify dns_notify_t;
143typedef struct dns_stub dns_stub_t;
144typedef struct dns_load dns_load_t;
145typedef struct dns_forward dns_forward_t;
146typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
147typedef struct dns_io dns_io_t;
148typedef ISC_LIST(dns_io_t) dns_iolist_t;
149typedef struct dns_signing dns_signing_t;
150typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
151typedef struct dns_nsec3chain dns_nsec3chain_t;
152typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
153typedef struct dns_keyfetch dns_keyfetch_t;
154typedef struct dns_asyncload dns_asyncload_t;
155
156#define DNS_ZONE_CHECKLOCK
157#ifdef DNS_ZONE_CHECKLOCK
158#define LOCK_ZONE(z) \
159	 do { LOCK(&(z)->lock); \
160	      INSIST((z)->locked == ISC_FALSE); \
161	     (z)->locked = ISC_TRUE; \
162		} while (/*CONSTCOND*/0)
163#define UNLOCK_ZONE(z) \
164	do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (/*CONSTCOND*/0)
165#define LOCKED_ZONE(z) ((z)->locked)
166#else
167#define LOCK_ZONE(z) LOCK(&(z)->lock)
168#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
169#define LOCKED_ZONE(z) ISC_TRUE
170#endif
171
172#ifdef ISC_RWLOCK_USEATOMIC
173#define ZONEDB_INITLOCK(l)	isc_rwlock_init((l), 0, 0)
174#define ZONEDB_DESTROYLOCK(l)	isc_rwlock_destroy(l)
175#define ZONEDB_LOCK(l, t)	RWLOCK((l), (t))
176#define ZONEDB_UNLOCK(l, t)	RWUNLOCK((l), (t))
177#else
178#define ZONEDB_INITLOCK(l)	isc_mutex_init(l)
179#define ZONEDB_DESTROYLOCK(l)	DESTROYLOCK(l)
180#define ZONEDB_LOCK(l, t)	LOCK(l)
181#define ZONEDB_UNLOCK(l, t)	UNLOCK(l)
182#endif
183
184struct dns_zone {
185	/* Unlocked */
186	unsigned int		magic;
187	isc_mutex_t		lock;
188#ifdef DNS_ZONE_CHECKLOCK
189	isc_boolean_t		locked;
190#endif
191	isc_mem_t		*mctx;
192	isc_refcount_t		erefs;
193
194#ifdef ISC_RWLOCK_USEATOMIC
195	isc_rwlock_t		dblock;
196#else
197	isc_mutex_t		dblock;
198#endif
199	dns_db_t		*db;		/* Locked by dblock */
200
201	/* Locked */
202	dns_zonemgr_t		*zmgr;
203	ISC_LINK(dns_zone_t)	link;		/* Used by zmgr. */
204	isc_timer_t		*timer;
205	unsigned int		irefs;
206	dns_name_t		origin;
207	char			*masterfile;
208	dns_masterformat_t	masterformat;
209	char			*journal;
210	isc_int32_t		journalsize;
211	dns_rdataclass_t	rdclass;
212	dns_zonetype_t		type;
213	unsigned int		flags;
214	unsigned int		options;
215	unsigned int		db_argc;
216	char			**db_argv;
217	isc_time_t		expiretime;
218	isc_time_t		refreshtime;
219	isc_time_t		dumptime;
220	isc_time_t		loadtime;
221	isc_time_t		notifytime;
222	isc_time_t		resigntime;
223	isc_time_t		keywarntime;
224	isc_time_t		signingtime;
225	isc_time_t		nsec3chaintime;
226	isc_time_t		refreshkeytime;
227	isc_uint32_t		refreshkeyinterval;
228	isc_uint32_t		refreshkeycount;
229	isc_uint32_t		refresh;
230	isc_uint32_t		retry;
231	isc_uint32_t		expire;
232	isc_uint32_t		minimum;
233	isc_stdtime_t		key_expiry;
234	isc_stdtime_t		log_key_expired_timer;
235	char			*keydirectory;
236
237	isc_uint32_t		maxrefresh;
238	isc_uint32_t		minrefresh;
239	isc_uint32_t		maxretry;
240	isc_uint32_t		minretry;
241
242	isc_sockaddr_t		*masters;
243	dns_name_t		**masterkeynames;
244	isc_boolean_t		*mastersok;
245	unsigned int		masterscnt;
246	unsigned int		curmaster;
247	isc_sockaddr_t		masteraddr;
248	dns_notifytype_t	notifytype;
249	isc_sockaddr_t		*notify;
250	dns_name_t		**notifykeynames;
251	unsigned int		notifycnt;
252	isc_sockaddr_t		notifyfrom;
253	isc_task_t		*task;
254	isc_task_t		*loadtask;
255	isc_sockaddr_t		notifysrc4;
256	isc_sockaddr_t		notifysrc6;
257	isc_sockaddr_t		xfrsource4;
258	isc_sockaddr_t		xfrsource6;
259	isc_sockaddr_t		altxfrsource4;
260	isc_sockaddr_t		altxfrsource6;
261	isc_sockaddr_t		sourceaddr;
262	dns_xfrin_ctx_t		*xfr;		/* task locked */
263	dns_tsigkey_t		*tsigkey;	/* key used for xfr */
264	/* Access Control Lists */
265	dns_acl_t		*update_acl;
266	dns_acl_t		*forward_acl;
267	dns_acl_t		*notify_acl;
268	dns_acl_t		*query_acl;
269	dns_acl_t		*queryon_acl;
270	dns_acl_t		*xfr_acl;
271	isc_boolean_t		update_disabled;
272	isc_boolean_t		zero_no_soa_ttl;
273	dns_severity_t		check_names;
274	ISC_LIST(dns_notify_t)	notifies;
275	dns_request_t		*request;
276	dns_loadctx_t		*lctx;
277	dns_io_t		*readio;
278	dns_dumpctx_t		*dctx;
279	dns_io_t		*writeio;
280	isc_uint32_t		maxxfrin;
281	isc_uint32_t		maxxfrout;
282	isc_uint32_t		idlein;
283	isc_uint32_t		idleout;
284	isc_event_t		ctlevent;
285	dns_ssutable_t		*ssutable;
286	isc_uint32_t		sigvalidityinterval;
287	isc_uint32_t		sigresigninginterval;
288	dns_view_t		*view;
289	dns_acache_t		*acache;
290	dns_checkmxfunc_t	checkmx;
291	dns_checksrvfunc_t	checksrv;
292	dns_checknsfunc_t	checkns;
293	/*%
294	 * Zones in certain states such as "waiting for zone transfer"
295	 * or "zone transfer in progress" are kept on per-state linked lists
296	 * in the zone manager using the 'statelink' field.  The 'statelist'
297	 * field points at the list the zone is currently on.  It the zone
298	 * is not on any such list, statelist is NULL.
299	 */
300	ISC_LINK(dns_zone_t)	statelink;
301	dns_zonelist_t		*statelist;
302	/*%
303	 * Statistics counters about zone management.
304	 */
305	isc_stats_t		*stats;
306	/*%
307	 * Optional per-zone statistics counters.  Counted outside of this
308	 * module.
309	 */
310	isc_boolean_t		requeststats_on;
311	isc_stats_t		*requeststats;
312	isc_uint32_t		notifydelay;
313	dns_isselffunc_t	isself;
314	void			*isselfarg;
315
316	char *			strnamerd;
317	char *			strname;
318	char *			strrdclass;
319	char *			strviewname;
320
321	/*%
322	 * Serial number for deferred journal compaction.
323	 */
324	isc_uint32_t		compact_serial;
325	/*%
326	 * Keys that are signing the zone for the first time.
327	 */
328	dns_signinglist_t	signing;
329	dns_nsec3chainlist_t	nsec3chain;
330	/*%
331	 * Signing / re-signing quantum stopping parameters.
332	 */
333	isc_uint32_t		signatures;
334	isc_uint32_t		nodes;
335	dns_rdatatype_t		privatetype;
336
337	/*%
338	 * Autosigning/key-maintenance options
339	 */
340	isc_uint32_t		keyopts;
341
342	/*%
343	 * True if added by "rndc addzone"
344	 */
345	isc_boolean_t           added;
346
347	/*%
348	 * whether a rpz radix was needed when last loaded
349	 */
350	isc_boolean_t           rpz_zone;
351
352	/*%
353	 * Serial number update method.
354	 */
355	dns_updatemethod_t	updatemethod;
356
357	/*%
358	 * whether ixfr is requested
359	 */
360	isc_boolean_t		requestixfr;
361
362	/*%
363	 * Outstanding forwarded UPDATE requests.
364	 */
365	dns_forwardlist_t	forwards;
366
367	dns_zone_t		*raw;
368	dns_zone_t		*secure;
369
370	isc_boolean_t		sourceserialset;
371	isc_uint32_t		sourceserial;
372};
373
374#define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
375#define DNS_ZONE_SETFLAG(z,f) do { \
376		INSIST(LOCKED_ZONE(z)); \
377		(z)->flags |= (f); \
378		} while (/*CONSTCOND*/0)
379#define DNS_ZONE_CLRFLAG(z,f) do { \
380		INSIST(LOCKED_ZONE(z)); \
381		(z)->flags &= ~(f); \
382		} while (/*CONSTCOND*/0)
383	/* XXX MPA these may need to go back into zone.h */
384#define DNS_ZONEFLG_REFRESH	0x00000001U	/*%< refresh check in progress */
385#define DNS_ZONEFLG_NEEDDUMP	0x00000002U	/*%< zone need consolidation */
386#define DNS_ZONEFLG_USEVC	0x00000004U	/*%< use tcp for refresh query */
387#define DNS_ZONEFLG_DUMPING	0x00000008U	/*%< a dump is in progress */
388#define DNS_ZONEFLG_HASINCLUDE	0x00000010U	/*%< $INCLUDE in zone file */
389#define DNS_ZONEFLG_LOADED	0x00000020U	/*%< database has loaded */
390#define DNS_ZONEFLG_EXITING	0x00000040U	/*%< zone is being destroyed */
391#define DNS_ZONEFLG_EXPIRED	0x00000080U	/*%< zone has expired */
392#define DNS_ZONEFLG_NEEDREFRESH	0x00000100U	/*%< refresh check needed */
393#define DNS_ZONEFLG_UPTODATE	0x00000200U	/*%< zone contents are
394						 * uptodate */
395#define DNS_ZONEFLG_NEEDNOTIFY	0x00000400U	/*%< need to send out notify
396						 * messages */
397#define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U	/*%< generate a journal diff on
398						 * reload */
399#define DNS_ZONEFLG_NOMASTERS	0x00001000U	/*%< an attempt to refresh a
400						 * zone with no masters
401						 * occurred */
402#define DNS_ZONEFLG_LOADING	0x00002000U	/*%< load from disk in progress*/
403#define DNS_ZONEFLG_HAVETIMERS	0x00004000U	/*%< timer values have been set
404						 * from SOA (if not set, we
405						 * are still using
406						 * default timer values) */
407#define DNS_ZONEFLG_FORCEXFER	0x00008000U	/*%< Force a zone xfer */
408#define DNS_ZONEFLG_NOREFRESH	0x00010000U
409#define DNS_ZONEFLG_DIALNOTIFY	0x00020000U
410#define DNS_ZONEFLG_DIALREFRESH	0x00040000U
411#define DNS_ZONEFLG_SHUTDOWN	0x00080000U
412#define DNS_ZONEFLAG_NOIXFR	0x00100000U	/*%< IXFR failed, force AXFR */
413#define DNS_ZONEFLG_FLUSH	0x00200000U
414#define DNS_ZONEFLG_NOEDNS	0x00400000U
415#define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
416#define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
417#define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
418#define DNS_ZONEFLG_REFRESHING	0x04000000U	/*%< Refreshing keydata */
419#define DNS_ZONEFLG_THAW	0x08000000U
420#define DNS_ZONEFLG_LOADPENDING	0x10000000U	/*%< Loading scheduled */
421#define DNS_ZONEFLG_NODELAY	0x20000000U
422#define DNS_ZONEFLG_SENDSECURE  0x40000000U
423
424#define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
425#define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
426
427/* Flags for zone_load() */
428#define DNS_ZONELOADFLAG_NOSTAT	0x00000001U	/* Do not stat() master files */
429#define DNS_ZONELOADFLAG_THAW	0x00000002U	/* Thaw the zone on successful
430						   load. */
431
432#define UNREACH_CHACHE_SIZE	10U
433#define UNREACH_HOLD_TIME	600	/* 10 minutes */
434
435#define CHECK(op) \
436	do { result = (op); \
437		if (result != ISC_R_SUCCESS) goto failure; \
438	} while (/*CONSTCOND*/0)
439
440struct dns_unreachable {
441	isc_sockaddr_t	remote;
442	isc_sockaddr_t	local;
443	isc_uint32_t	expire;
444	isc_uint32_t	last;
445};
446
447struct dns_zonemgr {
448	unsigned int		magic;
449	isc_mem_t *		mctx;
450	int			refs;		/* Locked by rwlock */
451	isc_taskmgr_t *		taskmgr;
452	isc_timermgr_t *	timermgr;
453	isc_socketmgr_t *	socketmgr;
454	isc_taskpool_t *	zonetasks;
455	isc_taskpool_t *	loadtasks;
456	isc_task_t *		task;
457	isc_ratelimiter_t *	rl;
458	isc_rwlock_t		rwlock;
459	isc_mutex_t		iolock;
460	isc_rwlock_t		urlock;
461
462	/* Locked by rwlock. */
463	dns_zonelist_t		zones;
464	dns_zonelist_t		waiting_for_xfrin;
465	dns_zonelist_t		xfrin_in_progress;
466
467	/* Configuration data. */
468	isc_uint32_t		transfersin;
469	isc_uint32_t		transfersperns;
470	unsigned int		serialqueryrate;
471
472	/* Locked by iolock */
473	isc_uint32_t		iolimit;
474	isc_uint32_t		ioactive;
475	dns_iolist_t		high;
476	dns_iolist_t		low;
477
478	/* Locked by urlock. */
479	/* LRU cache */
480	struct dns_unreachable	unreachable[UNREACH_CHACHE_SIZE];
481};
482
483/*%
484 * Hold notify state.
485 */
486struct dns_notify {
487	unsigned int		magic;
488	unsigned int		flags;
489	isc_mem_t		*mctx;
490	dns_zone_t		*zone;
491	dns_adbfind_t		*find;
492	dns_request_t		*request;
493	dns_name_t		ns;
494	isc_sockaddr_t		dst;
495	dns_tsigkey_t		*key;
496	ISC_LINK(dns_notify_t)	link;
497};
498
499#define DNS_NOTIFY_NOSOA	0x0001U
500
501/*%
502 *	dns_stub holds state while performing a 'stub' transfer.
503 *	'db' is the zone's 'db' or a new one if this is the initial
504 *	transfer.
505 */
506
507struct dns_stub {
508	unsigned int		magic;
509	isc_mem_t		*mctx;
510	dns_zone_t		*zone;
511	dns_db_t		*db;
512	dns_dbversion_t		*version;
513};
514
515/*%
516 *	Hold load state.
517 */
518struct dns_load {
519	unsigned int		magic;
520	isc_mem_t		*mctx;
521	dns_zone_t		*zone;
522	dns_db_t		*db;
523	isc_time_t		loadtime;
524	dns_rdatacallbacks_t	callbacks;
525};
526
527/*%
528 *	Hold forward state.
529 */
530struct dns_forward {
531	unsigned int		magic;
532	isc_mem_t		*mctx;
533	dns_zone_t		*zone;
534	isc_buffer_t		*msgbuf;
535	dns_request_t		*request;
536	isc_uint32_t		which;
537	isc_sockaddr_t		addr;
538	dns_updatecallback_t	callback;
539	void			*callback_arg;
540	ISC_LINK(dns_forward_t)	link;
541};
542
543/*%
544 *	Hold IO request state.
545 */
546struct dns_io {
547	unsigned int	magic;
548	dns_zonemgr_t	*zmgr;
549	isc_boolean_t	high;
550	isc_task_t	*task;
551	ISC_LINK(dns_io_t) link;
552	isc_event_t	*event;
553};
554
555/*%
556 *	Hold state for when we are signing a zone with a new
557 *	DNSKEY as result of an update.
558 */
559struct dns_signing {
560	unsigned int		magic;
561	dns_db_t		*db;
562	dns_dbiterator_t	*dbiterator;
563	dns_secalg_t		algorithm;
564	isc_uint16_t		keyid;
565	isc_boolean_t		delete;
566	isc_boolean_t		done;
567	ISC_LINK(dns_signing_t)	link;
568};
569
570struct dns_nsec3chain {
571	unsigned int			magic;
572	dns_db_t			*db;
573	dns_dbiterator_t		*dbiterator;
574	dns_rdata_nsec3param_t		nsec3param;
575	unsigned char			salt[255];
576	isc_boolean_t			done;
577	isc_boolean_t			seen_nsec;
578	isc_boolean_t			delete_nsec;
579	isc_boolean_t			save_delete_nsec;
580	ISC_LINK(dns_nsec3chain_t)	link;
581};
582/*%<
583 * 'dbiterator' contains a iterator for the database.  If we are creating
584 * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
585 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
586 * iterated.
587 *
588 * 'nsec3param' contains the parameters of the NSEC3 chain being created
589 * or removed.
590 *
591 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
592 *
593 * 'seen_nsec' will be set to true if, while iterating the zone to create a
594 * NSEC3 chain, a NSEC record is seen.
595 *
596 * 'delete_nsec' will be set to true if, at the completion of the creation
597 * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
598 * are in the process of deleting the NSEC chain.
599 *
600 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
601 * so it can be recovered in the event of a error.
602 */
603
604struct dns_keyfetch {
605	dns_fixedname_t name;
606	dns_rdataset_t keydataset;
607	dns_rdataset_t dnskeyset;
608	dns_rdataset_t dnskeysigset;
609	dns_zone_t *zone;
610	dns_db_t *db;
611	dns_fetch_t *fetch;
612};
613
614/*%
615 * Hold state for an asynchronous load
616 */
617struct dns_asyncload {
618	dns_zone_t *zone;
619	dns_zt_zoneloaded_t loaded;
620	void *loaded_arg;
621};
622
623#define HOUR 3600
624#define DAY (24*HOUR)
625#define MONTH (30*DAY)
626
627#define SEND_BUFFER_SIZE 2048
628
629static void zone_settimer(dns_zone_t *, isc_time_t *);
630static void cancel_refresh(dns_zone_t *);
631static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
632			  const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
633static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
634     ISC_FORMAT_PRINTF(3, 4);
635static void queue_xfrin(dns_zone_t *zone);
636static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
637				  dns_diff_t *diff, dns_diffop_t op,
638				  dns_name_t *name, dns_ttl_t ttl,
639				  dns_rdata_t *rdata);
640static void zone_unload(dns_zone_t *zone);
641static void zone_expire(dns_zone_t *zone);
642static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
643static void zone_idetach(dns_zone_t **zonep);
644static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
645				   isc_boolean_t dump);
646static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
647static inline void zone_detachdb(dns_zone_t *zone);
648static isc_result_t default_journal(dns_zone_t *zone);
649static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
650static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
651				  isc_time_t loadtime, isc_result_t result);
652static void zone_needdump(dns_zone_t *zone, unsigned int delay);
653static void zone_shutdown(isc_task_t *, isc_event_t *);
654static void zone_loaddone(void *arg, isc_result_t result);
655static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
656				   isc_time_t loadtime);
657static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
658static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
659static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
660static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
661static isc_result_t zone_send_secureserial(dns_zone_t *zone,
662					   isc_boolean_t secure_locked,
663					   isc_uint32_t serial);
664
665#if 0
666/* ondestroy example */
667static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
668#endif
669
670static void refresh_callback(isc_task_t *, isc_event_t *);
671static void stub_callback(isc_task_t *, isc_event_t *);
672static void queue_soa_query(dns_zone_t *zone);
673static void soa_query(isc_task_t *, isc_event_t *);
674static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
675		     dns_stub_t *stub);
676static int message_count(dns_message_t *msg, dns_section_t section,
677			 dns_rdatatype_t type);
678static void notify_cancel(dns_zone_t *zone);
679static void notify_find_address(dns_notify_t *notify);
680static void notify_send(dns_notify_t *notify);
681static isc_result_t notify_createmessage(dns_zone_t *zone,
682					 unsigned int flags,
683					 dns_message_t **messagep);
684static void notify_done(isc_task_t *task, isc_event_t *event);
685static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
686static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
687static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
688static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
689					     dns_zone_t *zone);
690static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
691static void zonemgr_free(dns_zonemgr_t *zmgr);
692static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
693				  isc_task_t *task, isc_taskaction_t action,
694				  void *arg, dns_io_t **iop);
695static void zonemgr_putio(dns_io_t **iop);
696static void zonemgr_cancelio(dns_io_t *io);
697
698static isc_result_t
699zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
700		 unsigned int *soacount, isc_uint32_t *serial,
701		 isc_uint32_t *refresh, isc_uint32_t *retry,
702		 isc_uint32_t *expire, isc_uint32_t *minimum,
703		 unsigned int *errors);
704
705static void zone_freedbargs(dns_zone_t *zone);
706static void forward_callback(isc_task_t *task, isc_event_t *event);
707static void zone_saveunique(dns_zone_t *zone, const char *path,
708			    const char *templat);
709static void zone_maintenance(dns_zone_t *zone);
710static void zone_notify(dns_zone_t *zone, isc_time_t *now);
711static void dump_done(void *arg, isc_result_t result);
712static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
713				     isc_uint16_t keyid, isc_boolean_t delete);
714static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
715				dns_dbnode_t *node, dns_name_t *name,
716				dns_diff_t *diff);
717static void zone_rekey(dns_zone_t *zone);
718static isc_boolean_t delsig_ok(dns_rdata_rrsig_t *rrsig_ptr,
719			       dst_key_t **keys, unsigned int nkeys);
720static isc_result_t zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked,
721				       dns_db_t *db);
722
723#define ENTER zone_debuglog(zone, me, 1, "enter")
724
725static const unsigned int dbargc_default = 1;
726static const char *dbargv_default[] = { "rbt" };
727
728#define DNS_ZONE_JITTER_ADD(a, b, c) \
729	do { \
730		isc_interval_t _i; \
731		isc_uint32_t _j; \
732		_j = isc_random_jitter((b), (b)/4); \
733		isc_interval_set(&_i, _j, 0); \
734		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
735			dns_zone_log(zone, ISC_LOG_WARNING, \
736				     "epoch approaching: upgrade required: " \
737				     "now + %s failed", #b); \
738			isc_interval_set(&_i, _j/2, 0); \
739			(void)isc_time_add((a), &_i, (c)); \
740		} \
741	} while (/*CONSTCOND*/0)
742
743#define DNS_ZONE_TIME_ADD(a, b, c) \
744	do { \
745		isc_interval_t _i; \
746		isc_interval_set(&_i, (b), 0); \
747		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
748			dns_zone_log(zone, ISC_LOG_WARNING, \
749				     "epoch approaching: upgrade required: " \
750				     "now + %s failed", #b); \
751			isc_interval_set(&_i, (b)/2, 0); \
752			(void)isc_time_add((a), &_i, (c)); \
753		} \
754	} while (/*CONSTCOND*/0)
755
756/*%
757 * Increment resolver-related statistics counters.  Zone must be locked.
758 */
759static inline void
760inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
761	if (zone->stats != NULL)
762		isc_stats_increment(zone->stats, counter);
763}
764
765/***
766 ***	Public functions.
767 ***/
768
769isc_result_t
770dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
771	isc_result_t result;
772	dns_zone_t *zone;
773	isc_time_t now;
774
775	REQUIRE(zonep != NULL && *zonep == NULL);
776	REQUIRE(mctx != NULL);
777
778	TIME_NOW(&now);
779	zone = isc_mem_get(mctx, sizeof(*zone));
780	if (zone == NULL)
781		return (ISC_R_NOMEMORY);
782
783	zone->mctx = NULL;
784	isc_mem_attach(mctx, &zone->mctx);
785
786	result = isc_mutex_init(&zone->lock);
787	if (result != ISC_R_SUCCESS)
788		goto free_zone;
789
790	result = ZONEDB_INITLOCK(&zone->dblock);
791	if (result != ISC_R_SUCCESS)
792		goto free_mutex;
793
794	/* XXX MPA check that all elements are initialised */
795#ifdef DNS_ZONE_CHECKLOCK
796	zone->locked = ISC_FALSE;
797#endif
798	zone->db = NULL;
799	zone->zmgr = NULL;
800	ISC_LINK_INIT(zone, link);
801	result = isc_refcount_init(&zone->erefs, 1);	/* Implicit attach. */
802	if (result != ISC_R_SUCCESS)
803		goto free_dblock;
804	zone->irefs = 0;
805	dns_name_init(&zone->origin, NULL);
806	zone->strnamerd = NULL;
807	zone->strname = NULL;
808	zone->strrdclass = NULL;
809	zone->strviewname = NULL;
810	zone->masterfile = NULL;
811	zone->masterformat = dns_masterformat_none;
812	zone->keydirectory = NULL;
813	zone->journalsize = -1;
814	zone->journal = NULL;
815	zone->rdclass = dns_rdataclass_none;
816	zone->type = dns_zone_none;
817	zone->flags = 0;
818	zone->options = 0;
819	zone->keyopts = 0;
820	zone->db_argc = 0;
821	zone->db_argv = NULL;
822	isc_time_settoepoch(&zone->expiretime);
823	isc_time_settoepoch(&zone->refreshtime);
824	isc_time_settoepoch(&zone->dumptime);
825	isc_time_settoepoch(&zone->loadtime);
826	zone->notifytime = now;
827	isc_time_settoepoch(&zone->resigntime);
828	isc_time_settoepoch(&zone->keywarntime);
829	isc_time_settoepoch(&zone->signingtime);
830	isc_time_settoepoch(&zone->nsec3chaintime);
831	isc_time_settoepoch(&zone->refreshkeytime);
832	zone->refreshkeyinterval = 0;
833	zone->refreshkeycount = 0;
834	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
835	zone->retry = DNS_ZONE_DEFAULTRETRY;
836	zone->expire = 0;
837	zone->minimum = 0;
838	zone->maxrefresh = DNS_ZONE_MAXREFRESH;
839	zone->minrefresh = DNS_ZONE_MINREFRESH;
840	zone->maxretry = DNS_ZONE_MAXRETRY;
841	zone->minretry = DNS_ZONE_MINRETRY;
842	zone->masters = NULL;
843	zone->masterkeynames = NULL;
844	zone->mastersok = NULL;
845	zone->masterscnt = 0;
846	zone->curmaster = 0;
847	zone->notify = NULL;
848	zone->notifykeynames = NULL;
849	zone->notifytype = dns_notifytype_yes;
850	zone->notifycnt = 0;
851	zone->task = NULL;
852	zone->loadtask = NULL;
853	zone->update_acl = NULL;
854	zone->forward_acl = NULL;
855	zone->notify_acl = NULL;
856	zone->query_acl = NULL;
857	zone->queryon_acl = NULL;
858	zone->xfr_acl = NULL;
859	zone->update_disabled = ISC_FALSE;
860	zone->zero_no_soa_ttl = ISC_TRUE;
861	zone->check_names = dns_severity_ignore;
862	zone->request = NULL;
863	zone->lctx = NULL;
864	zone->readio = NULL;
865	zone->dctx = NULL;
866	zone->writeio = NULL;
867	zone->timer = NULL;
868	zone->idlein = DNS_DEFAULT_IDLEIN;
869	zone->idleout = DNS_DEFAULT_IDLEOUT;
870	zone->log_key_expired_timer = 0;
871	ISC_LIST_INIT(zone->notifies);
872	isc_sockaddr_any(&zone->notifysrc4);
873	isc_sockaddr_any6(&zone->notifysrc6);
874	isc_sockaddr_any(&zone->xfrsource4);
875	isc_sockaddr_any6(&zone->xfrsource6);
876	isc_sockaddr_any(&zone->altxfrsource4);
877	isc_sockaddr_any6(&zone->altxfrsource6);
878	zone->xfr = NULL;
879	zone->tsigkey = NULL;
880	zone->maxxfrin = MAX_XFER_TIME;
881	zone->maxxfrout = MAX_XFER_TIME;
882	zone->ssutable = NULL;
883	zone->sigvalidityinterval = 30 * 24 * 3600;
884	zone->sigresigninginterval = 7 * 24 * 3600;
885	zone->view = NULL;
886	zone->acache = NULL;
887	zone->checkmx = NULL;
888	zone->checksrv = NULL;
889	zone->checkns = NULL;
890	ISC_LINK_INIT(zone, statelink);
891	zone->statelist = NULL;
892	zone->stats = NULL;
893	zone->requeststats_on = ISC_FALSE;
894	zone->requeststats = NULL;
895	zone->notifydelay = 5;
896	zone->isself = NULL;
897	zone->isselfarg = NULL;
898	ISC_LIST_INIT(zone->signing);
899	ISC_LIST_INIT(zone->nsec3chain);
900	zone->signatures = 10;
901	zone->nodes = 100;
902	zone->privatetype = (dns_rdatatype_t)0xffffU;
903	zone->added = ISC_FALSE;
904	zone->rpz_zone = ISC_FALSE;
905	ISC_LIST_INIT(zone->forwards);
906	zone->raw = NULL;
907	zone->secure = NULL;
908	zone->sourceserial = 0;
909	zone->sourceserialset = ISC_FALSE;
910
911	zone->magic = ZONE_MAGIC;
912
913	/* Must be after magic is set. */
914	result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
915	if (result != ISC_R_SUCCESS)
916		goto free_erefs;
917
918	ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
919		       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
920		       NULL, NULL);
921	*zonep = zone;
922	return (ISC_R_SUCCESS);
923
924 free_erefs:
925	isc_refcount_decrement(&zone->erefs, NULL);
926	isc_refcount_destroy(&zone->erefs);
927
928 free_dblock:
929	ZONEDB_DESTROYLOCK(&zone->dblock);
930
931 free_mutex:
932	DESTROYLOCK(&zone->lock);
933
934 free_zone:
935	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
936	return (result);
937}
938
939/*
940 * Free a zone.  Because we require that there be no more
941 * outstanding events or references, no locking is necessary.
942 */
943static void
944zone_free(dns_zone_t *zone) {
945	isc_mem_t *mctx = NULL;
946	dns_signing_t *signing;
947	dns_nsec3chain_t *nsec3chain;
948
949	REQUIRE(DNS_ZONE_VALID(zone));
950	REQUIRE(isc_refcount_current(&zone->erefs) == 0);
951	REQUIRE(zone->irefs == 0);
952	REQUIRE(!LOCKED_ZONE(zone));
953	REQUIRE(zone->timer == NULL);
954
955	/*
956	 * Managed objects.  Order is important.
957	 */
958	if (zone->request != NULL)
959		dns_request_destroy(&zone->request); /* XXXMPA */
960	INSIST(zone->readio == NULL);
961	INSIST(zone->statelist == NULL);
962	INSIST(zone->writeio == NULL);
963
964	if (zone->task != NULL)
965		isc_task_detach(&zone->task);
966	if (zone->loadtask != NULL)
967		isc_task_detach(&zone->loadtask);
968	if (zone->zmgr != NULL)
969		dns_zonemgr_releasezone(zone->zmgr, zone);
970
971	/* Unmanaged objects */
972	for (signing = ISC_LIST_HEAD(zone->signing);
973	     signing != NULL;
974	     signing = ISC_LIST_HEAD(zone->signing)) {
975		ISC_LIST_UNLINK(zone->signing, signing, link);
976		dns_db_detach(&signing->db);
977		dns_dbiterator_destroy(&signing->dbiterator);
978		isc_mem_put(zone->mctx, signing, sizeof *signing);
979	}
980	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
981	     nsec3chain != NULL;
982	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
983		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
984		dns_db_detach(&nsec3chain->db);
985		dns_dbiterator_destroy(&nsec3chain->dbiterator);
986		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
987	}
988	if (zone->masterfile != NULL)
989		isc_mem_free(zone->mctx, zone->masterfile);
990	zone->masterfile = NULL;
991	if (zone->keydirectory != NULL)
992		isc_mem_free(zone->mctx, zone->keydirectory);
993	zone->keydirectory = NULL;
994	zone->journalsize = -1;
995	if (zone->journal != NULL)
996		isc_mem_free(zone->mctx, zone->journal);
997	zone->journal = NULL;
998	if (zone->stats != NULL)
999		isc_stats_detach(&zone->stats);
1000	if (zone->requeststats != NULL)
1001		isc_stats_detach(&zone->requeststats);
1002	if (zone->db != NULL)
1003		zone_detachdb(zone);
1004	if (zone->acache != NULL)
1005		dns_acache_detach(&zone->acache);
1006	zone_freedbargs(zone);
1007	RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
1008		      == ISC_R_SUCCESS);
1009	RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
1010		      == ISC_R_SUCCESS);
1011	zone->check_names = dns_severity_ignore;
1012	if (zone->update_acl != NULL)
1013		dns_acl_detach(&zone->update_acl);
1014	if (zone->forward_acl != NULL)
1015		dns_acl_detach(&zone->forward_acl);
1016	if (zone->notify_acl != NULL)
1017		dns_acl_detach(&zone->notify_acl);
1018	if (zone->query_acl != NULL)
1019		dns_acl_detach(&zone->query_acl);
1020	if (zone->queryon_acl != NULL)
1021		dns_acl_detach(&zone->queryon_acl);
1022	if (zone->xfr_acl != NULL)
1023		dns_acl_detach(&zone->xfr_acl);
1024	if (dns_name_dynamic(&zone->origin))
1025		dns_name_free(&zone->origin, zone->mctx);
1026	if (zone->strnamerd != NULL)
1027		isc_mem_free(zone->mctx, zone->strnamerd);
1028	if (zone->strname != NULL)
1029		isc_mem_free(zone->mctx, zone->strname);
1030	if (zone->strrdclass != NULL)
1031		isc_mem_free(zone->mctx, zone->strrdclass);
1032	if (zone->strviewname != NULL)
1033		isc_mem_free(zone->mctx, zone->strviewname);
1034	if (zone->ssutable != NULL)
1035		dns_ssutable_detach(&zone->ssutable);
1036
1037	/* last stuff */
1038	ZONEDB_DESTROYLOCK(&zone->dblock);
1039	DESTROYLOCK(&zone->lock);
1040	isc_refcount_destroy(&zone->erefs);
1041	zone->magic = 0;
1042	mctx = zone->mctx;
1043	isc_mem_put(mctx, zone, sizeof(*zone));
1044	isc_mem_detach(&mctx);
1045}
1046
1047/*
1048 * Returns ISC_TRUE iff this the signed side of an inline-signing zone
1049 */
1050static inline isc_boolean_t
1051inline_secure(dns_zone_t *zone) {
1052	REQUIRE(DNS_ZONE_VALID(zone));
1053	if (zone->raw != NULL)
1054		return (ISC_TRUE);
1055	return (ISC_FALSE);
1056}
1057
1058/*
1059 * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone
1060 */
1061static inline isc_boolean_t
1062inline_raw(dns_zone_t *zone) {
1063	REQUIRE(DNS_ZONE_VALID(zone));
1064	if (zone->secure != NULL)
1065		return (ISC_TRUE);
1066	return (ISC_FALSE);
1067}
1068
1069/*
1070 *	Single shot.
1071 */
1072void
1073dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1074	char namebuf[1024];
1075
1076	REQUIRE(DNS_ZONE_VALID(zone));
1077	REQUIRE(rdclass != dns_rdataclass_none);
1078
1079	/*
1080	 * Test and set.
1081	 */
1082	LOCK_ZONE(zone);
1083	REQUIRE(zone->rdclass == dns_rdataclass_none ||
1084		zone->rdclass == rdclass);
1085	zone->rdclass = rdclass;
1086
1087	if (zone->strnamerd != NULL)
1088		isc_mem_free(zone->mctx, zone->strnamerd);
1089	if (zone->strrdclass != NULL)
1090		isc_mem_free(zone->mctx, zone->strrdclass);
1091
1092	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1093	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1094	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1095	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1096
1097	if (inline_secure(zone))
1098		dns_zone_setclass(zone->raw, rdclass);
1099	UNLOCK_ZONE(zone);
1100}
1101
1102dns_rdataclass_t
1103dns_zone_getclass(dns_zone_t *zone) {
1104	REQUIRE(DNS_ZONE_VALID(zone));
1105
1106	return (zone->rdclass);
1107}
1108
1109void
1110dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1111	REQUIRE(DNS_ZONE_VALID(zone));
1112
1113	LOCK_ZONE(zone);
1114	zone->notifytype = notifytype;
1115	UNLOCK_ZONE(zone);
1116}
1117
1118isc_result_t
1119dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1120	isc_result_t result;
1121
1122	REQUIRE(DNS_ZONE_VALID(zone));
1123	REQUIRE(serialp != NULL);
1124
1125	LOCK_ZONE(zone);
1126	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1127	if (zone->db != NULL) {
1128		result = zone_get_from_db(zone, zone->db, NULL, NULL, serialp,
1129					  NULL, NULL, NULL, NULL, NULL);
1130	} else
1131		result = DNS_R_NOTLOADED;
1132	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1133	UNLOCK_ZONE(zone);
1134
1135	return (result);
1136}
1137
1138isc_uint32_t
1139dns_zone_getserial(dns_zone_t *zone) {
1140	isc_result_t result;
1141	isc_uint32_t serial;
1142
1143	result = dns_zone_getserial2(zone, &serial);
1144	if (result != ISC_R_SUCCESS)
1145		serial = 0; /* XXX: not really correct, but no other choice */
1146
1147	return (serial);
1148}
1149
1150/*
1151 *	Single shot.
1152 */
1153void
1154dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1155	char namebuf[1024];
1156
1157	REQUIRE(DNS_ZONE_VALID(zone));
1158	REQUIRE(type != dns_zone_none);
1159
1160	/*
1161	 * Test and set.
1162	 */
1163	LOCK_ZONE(zone);
1164	REQUIRE(zone->type == dns_zone_none || zone->type == type);
1165	zone->type = type;
1166
1167	if (zone->strnamerd != NULL)
1168		isc_mem_free(zone->mctx, zone->strnamerd);
1169
1170	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1171	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1172	UNLOCK_ZONE(zone);
1173}
1174
1175static void
1176zone_freedbargs(dns_zone_t *zone) {
1177	unsigned int i;
1178
1179	/* Free the old database argument list. */
1180	if (zone->db_argv != NULL) {
1181		for (i = 0; i < zone->db_argc; i++)
1182			isc_mem_free(zone->mctx, zone->db_argv[i]);
1183		isc_mem_put(zone->mctx, zone->db_argv,
1184			    zone->db_argc * sizeof(*zone->db_argv));
1185	}
1186	zone->db_argc = 0;
1187	zone->db_argv = NULL;
1188}
1189
1190isc_result_t
1191dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1192	size_t size = 0;
1193	unsigned int i;
1194	isc_result_t result = ISC_R_SUCCESS;
1195	void *mem;
1196	char **tmp, *tmp2;
1197
1198	REQUIRE(DNS_ZONE_VALID(zone));
1199	REQUIRE(argv != NULL && *argv == NULL);
1200
1201	LOCK_ZONE(zone);
1202	size = (zone->db_argc + 1) * sizeof(char *);
1203	for (i = 0; i < zone->db_argc; i++)
1204		size += strlen(zone->db_argv[i]) + 1;
1205	mem = isc_mem_allocate(mctx, size);
1206	if (mem != NULL) {
1207		tmp = mem;
1208		tmp2 = mem;
1209		tmp2 += (zone->db_argc + 1) * sizeof(char *);
1210		for (i = 0; i < zone->db_argc; i++) {
1211			*tmp++ = tmp2;
1212			strcpy(tmp2, zone->db_argv[i]);
1213			tmp2 += strlen(tmp2) + 1;
1214		}
1215		*tmp = NULL;
1216	} else
1217		result = ISC_R_NOMEMORY;
1218	UNLOCK_ZONE(zone);
1219	*argv = mem;
1220	return (result);
1221}
1222
1223isc_result_t
1224dns_zone_setdbtype(dns_zone_t *zone,
1225		   unsigned int dbargc, const char * const *dbargv) {
1226	isc_result_t result = ISC_R_SUCCESS;
1227	char **new = NULL;
1228	unsigned int i;
1229
1230	REQUIRE(DNS_ZONE_VALID(zone));
1231	REQUIRE(dbargc >= 1);
1232	REQUIRE(dbargv != NULL);
1233
1234	LOCK_ZONE(zone);
1235
1236	/* Set up a new database argument list. */
1237	new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1238	if (new == NULL)
1239		goto nomem;
1240	for (i = 0; i < dbargc; i++)
1241		new[i] = NULL;
1242	for (i = 0; i < dbargc; i++) {
1243		new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1244		if (new[i] == NULL)
1245			goto nomem;
1246	}
1247
1248	/* Free the old list. */
1249	zone_freedbargs(zone);
1250
1251	zone->db_argc = dbargc;
1252	zone->db_argv = new;
1253	result = ISC_R_SUCCESS;
1254	goto unlock;
1255
1256 nomem:
1257	if (new != NULL) {
1258		for (i = 0; i < dbargc; i++)
1259			if (new[i] != NULL)
1260				isc_mem_free(zone->mctx, new[i]);
1261		isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1262	}
1263	result = ISC_R_NOMEMORY;
1264
1265 unlock:
1266	UNLOCK_ZONE(zone);
1267	return (result);
1268}
1269
1270void
1271dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1272	char namebuf[1024];
1273	REQUIRE(DNS_ZONE_VALID(zone));
1274
1275	LOCK_ZONE(zone);
1276	if (zone->view != NULL)
1277		dns_view_weakdetach(&zone->view);
1278	dns_view_weakattach(view, &zone->view);
1279
1280	if (zone->strviewname != NULL)
1281		isc_mem_free(zone->mctx, zone->strviewname);
1282	if (zone->strnamerd != NULL)
1283		isc_mem_free(zone->mctx, zone->strnamerd);
1284
1285	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1286	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1287	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1288	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1289
1290	if (inline_secure(zone))
1291		dns_zone_setview(zone->raw, view);
1292
1293	UNLOCK_ZONE(zone);
1294}
1295
1296dns_view_t *
1297dns_zone_getview(dns_zone_t *zone) {
1298	REQUIRE(DNS_ZONE_VALID(zone));
1299
1300	return (zone->view);
1301}
1302
1303
1304isc_result_t
1305dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1306	isc_result_t result;
1307	char namebuf[1024];
1308
1309	REQUIRE(DNS_ZONE_VALID(zone));
1310	REQUIRE(origin != NULL);
1311
1312	LOCK_ZONE(zone);
1313	if (dns_name_dynamic(&zone->origin)) {
1314		dns_name_free(&zone->origin, zone->mctx);
1315		dns_name_init(&zone->origin, NULL);
1316	}
1317	result = dns_name_dup(origin, zone->mctx, &zone->origin);
1318
1319	if (zone->strnamerd != NULL)
1320		isc_mem_free(zone->mctx, zone->strnamerd);
1321	if (zone->strname != NULL)
1322		isc_mem_free(zone->mctx, zone->strname);
1323
1324	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1325	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1326	zone_name_tostr(zone, namebuf, sizeof namebuf);
1327	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1328
1329	if (result == ISC_R_SUCCESS && inline_secure(zone))
1330		result = dns_zone_setorigin(zone->raw, origin);
1331	UNLOCK_ZONE(zone);
1332	return (result);
1333}
1334
1335void
1336dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1337	REQUIRE(DNS_ZONE_VALID(zone));
1338	REQUIRE(acache != NULL);
1339
1340	LOCK_ZONE(zone);
1341	if (zone->acache != NULL)
1342		dns_acache_detach(&zone->acache);
1343	dns_acache_attach(acache, &zone->acache);
1344	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1345	if (zone->db != NULL) {
1346		isc_result_t result;
1347
1348		/*
1349		 * If the zone reuses an existing DB, the DB needs to be
1350		 * set in the acache explicitly.  We can safely ignore the
1351		 * case where the DB is already set.  If other error happens,
1352		 * the acache will not work effectively.
1353		 */
1354		result = dns_acache_setdb(acache, zone->db);
1355		if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1356			UNEXPECTED_ERROR(__FILE__, __LINE__,
1357					 "dns_acache_setdb() failed: %s",
1358					 isc_result_totext(result));
1359		}
1360	}
1361	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1362	UNLOCK_ZONE(zone);
1363}
1364
1365static isc_result_t
1366dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1367	char *copy;
1368
1369	if (value != NULL) {
1370		copy = isc_mem_strdup(zone->mctx, value);
1371		if (copy == NULL)
1372			return (ISC_R_NOMEMORY);
1373	} else {
1374		copy = NULL;
1375	}
1376
1377	if (*field != NULL)
1378		isc_mem_free(zone->mctx, *field);
1379
1380	*field = copy;
1381	return (ISC_R_SUCCESS);
1382}
1383
1384isc_result_t
1385dns_zone_setfile(dns_zone_t *zone, const char *file) {
1386	return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1387}
1388
1389isc_result_t
1390dns_zone_setfile2(dns_zone_t *zone, const char *file,
1391		  dns_masterformat_t format) {
1392	isc_result_t result = ISC_R_SUCCESS;
1393
1394	REQUIRE(DNS_ZONE_VALID(zone));
1395
1396	LOCK_ZONE(zone);
1397	result = dns_zone_setstring(zone, &zone->masterfile, file);
1398	if (result == ISC_R_SUCCESS) {
1399		zone->masterformat = format;
1400		result = default_journal(zone);
1401	}
1402	UNLOCK_ZONE(zone);
1403
1404	return (result);
1405}
1406
1407const char *
1408dns_zone_getfile(dns_zone_t *zone) {
1409	REQUIRE(DNS_ZONE_VALID(zone));
1410
1411	return (zone->masterfile);
1412}
1413
1414static isc_result_t
1415default_journal(dns_zone_t *zone) {
1416	isc_result_t result;
1417	char *journal;
1418
1419	REQUIRE(DNS_ZONE_VALID(zone));
1420	REQUIRE(LOCKED_ZONE(zone));
1421
1422	if (zone->masterfile != NULL) {
1423		/* Calculate string length including '\0'. */
1424		int len = strlen(zone->masterfile) + sizeof(".jnl");
1425		journal = isc_mem_allocate(zone->mctx, len);
1426		if (journal == NULL)
1427			return (ISC_R_NOMEMORY);
1428		strcpy(journal, zone->masterfile);
1429		strcat(journal, ".jnl");
1430	} else {
1431		journal = NULL;
1432	}
1433	result = dns_zone_setstring(zone, &zone->journal, journal);
1434	if (journal != NULL)
1435		isc_mem_free(zone->mctx, journal);
1436	return (result);
1437}
1438
1439isc_result_t
1440dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1441	isc_result_t result = ISC_R_SUCCESS;
1442
1443	REQUIRE(DNS_ZONE_VALID(zone));
1444
1445	LOCK_ZONE(zone);
1446	result = dns_zone_setstring(zone, &zone->journal, journal);
1447	UNLOCK_ZONE(zone);
1448
1449	return (result);
1450}
1451
1452char *
1453dns_zone_getjournal(dns_zone_t *zone) {
1454	REQUIRE(DNS_ZONE_VALID(zone));
1455
1456	return (zone->journal);
1457}
1458
1459/*
1460 * Return true iff the zone is "dynamic", in the sense that the zone's
1461 * master file (if any) is written by the server, rather than being
1462 * updated manually and read by the server.
1463 *
1464 * This is true for slave zones, stub zones, key zones, and zones that
1465 * allow dynamic updates either by having an update policy ("ssutable")
1466 * or an "allow-update" ACL with a value other than exactly "{ none; }".
1467 */
1468isc_boolean_t
1469dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) {
1470	REQUIRE(DNS_ZONE_VALID(zone));
1471
1472	if (zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1473	    zone->type == dns_zone_key ||
1474	    (zone->type == dns_zone_redirect && zone->masters != NULL))
1475		return (ISC_TRUE);
1476
1477	/* If !ignore_freeze, we need check whether updates are disabled.  */
1478	if (zone->type == dns_zone_master &&
1479	    (!zone->update_disabled || ignore_freeze) &&
1480	    ((zone->ssutable != NULL) ||
1481	     (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1482		return (ISC_TRUE);
1483
1484	return (ISC_FALSE);
1485
1486}
1487
1488static isc_result_t
1489zone_load(dns_zone_t *zone, unsigned int flags) {
1490	isc_result_t result;
1491	isc_time_t now;
1492	isc_time_t loadtime, filetime;
1493	dns_db_t *db = NULL;
1494	isc_boolean_t rbt;
1495
1496	REQUIRE(DNS_ZONE_VALID(zone));
1497
1498	if (inline_secure(zone)) {
1499		result = zone_load(zone->raw, flags);
1500		if (result != ISC_R_SUCCESS)
1501			return(result);
1502	}
1503
1504	/*
1505	 * Lock hierachy zmgr, raw, zone.
1506	 */
1507	if (inline_secure(zone))
1508		LOCK_ZONE(zone->raw);
1509	LOCK_ZONE(zone);
1510	TIME_NOW(&now);
1511
1512	INSIST(zone->type != dns_zone_none);
1513
1514	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1515		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1516			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1517		result = DNS_R_CONTINUE;
1518		goto cleanup;
1519	}
1520
1521	INSIST(zone->db_argc >= 1);
1522
1523	rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1524	      strcmp(zone->db_argv[0], "rbt64") == 0;
1525
1526	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1527		/*
1528		 * The zone has no master file configured.
1529		 */
1530		result = ISC_R_SUCCESS;
1531		goto cleanup;
1532	}
1533
1534	if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) {
1535		/*
1536		 * This is a slave, stub, or dynamically updated
1537		 * zone being reloaded.  Do nothing - the database
1538		 * we already have is guaranteed to be up-to-date.
1539		 */
1540		if (zone->type == dns_zone_master)
1541			result = DNS_R_DYNAMIC;
1542		else
1543			result = ISC_R_SUCCESS;
1544		goto cleanup;
1545	}
1546
1547	/*
1548	 * Store the current time before the zone is loaded, so that if the
1549	 * file changes between the time of the load and the time that
1550	 * zone->loadtime is set, then the file will still be reloaded
1551	 * the next time dns_zone_load is called.
1552	 */
1553	TIME_NOW(&loadtime);
1554
1555	/*
1556	 * Don't do the load if the file that stores the zone is older
1557	 * than the last time the zone was loaded.  If the zone has not
1558	 * been loaded yet, zone->loadtime will be the epoch.
1559	 */
1560	if (zone->masterfile != NULL) {
1561		/*
1562		 * The file is already loaded.	If we are just doing a
1563		 * "rndc reconfig", we are done.
1564		 */
1565		if (!isc_time_isepoch(&zone->loadtime) &&
1566		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0 &&
1567		    zone->rpz_zone == dns_rpz_needed()) {
1568			result = ISC_R_SUCCESS;
1569			goto cleanup;
1570		}
1571
1572		result = isc_file_getmodtime(zone->masterfile, &filetime);
1573		if (result == ISC_R_SUCCESS) {
1574			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1575			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1576			    isc_time_compare(&filetime, &zone->loadtime) <= 0 &&
1577			    zone->rpz_zone == dns_rpz_needed()) {
1578				dns_zone_log(zone, ISC_LOG_DEBUG(1),
1579					     "skipping load: master file "
1580					     "older than last load");
1581				result = DNS_R_UPTODATE;
1582				goto cleanup;
1583			}
1584			loadtime = filetime;
1585			zone->rpz_zone = dns_rpz_needed();
1586		}
1587	}
1588
1589	/*
1590	 * Built in zones (with the exception of empty zones) don't need
1591	 * to be reloaded.
1592	 */
1593	if (zone->type == dns_zone_master &&
1594	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
1595	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1596	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1597		result = ISC_R_SUCCESS;
1598		goto cleanup;
1599	}
1600
1601	if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1602	     (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
1603	    rbt) {
1604		if (zone->masterfile == NULL ||
1605		    !isc_file_exists(zone->masterfile)) {
1606			if (zone->masterfile != NULL) {
1607				dns_zone_log(zone, ISC_LOG_DEBUG(1),
1608					     "no master file");
1609			}
1610			zone->refreshtime = now;
1611			if (zone->task != NULL)
1612				zone_settimer(zone, &now);
1613			result = ISC_R_SUCCESS;
1614			goto cleanup;
1615		}
1616	}
1617
1618	dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1619
1620	result = dns_db_create(zone->mctx, zone->db_argv[0],
1621			       &zone->origin, (zone->type == dns_zone_stub) ?
1622			       dns_dbtype_stub : dns_dbtype_zone,
1623			       zone->rdclass,
1624			       zone->db_argc - 1, zone->db_argv + 1,
1625			       &db);
1626
1627	if (result != ISC_R_SUCCESS) {
1628		dns_zone_log(zone, ISC_LOG_ERROR,
1629			     "loading zone: creating database: %s",
1630			     isc_result_totext(result));
1631		goto cleanup;
1632	}
1633	dns_db_settask(db, zone->task);
1634
1635	if (! dns_db_ispersistent(db)) {
1636		if (zone->masterfile != NULL) {
1637			result = zone_startload(db, zone, loadtime);
1638		} else {
1639			result = DNS_R_NOMASTERFILE;
1640			if (zone->type == dns_zone_master ||
1641			    (zone->type == dns_zone_redirect &&
1642			     zone->masters == NULL)) {
1643				dns_zone_log(zone, ISC_LOG_ERROR,
1644					     "loading zone: "
1645					     "no master file configured");
1646				goto cleanup;
1647			}
1648			dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1649				     "no master file configured: continuing");
1650		}
1651	}
1652
1653	if (result == DNS_R_CONTINUE) {
1654		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1655		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1656			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1657		goto cleanup;
1658	}
1659
1660	result = zone_postload(zone, db, loadtime, result);
1661
1662 cleanup:
1663	UNLOCK_ZONE(zone);
1664	if (inline_secure(zone))
1665		UNLOCK_ZONE(zone->raw);
1666	if (db != NULL)
1667		dns_db_detach(&db);
1668	return (result);
1669}
1670
1671isc_result_t
1672dns_zone_load(dns_zone_t *zone) {
1673	return (zone_load(zone, 0));
1674}
1675
1676isc_result_t
1677dns_zone_loadnew(dns_zone_t *zone) {
1678	return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1679}
1680
1681static void
1682zone_asyncload(isc_task_t *task, isc_event_t *event) {
1683	dns_asyncload_t *asl = event->ev_arg;
1684	dns_zone_t *zone = asl->zone;
1685	isc_result_t result = ISC_R_SUCCESS;
1686
1687	UNUSED(task);
1688
1689	REQUIRE(DNS_ZONE_VALID(zone));
1690
1691	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1692		result = ISC_R_CANCELED;
1693	isc_event_free(&event);
1694	if (result == ISC_R_CANCELED ||
1695	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
1696		goto cleanup;
1697
1698	zone_load(zone, 0);
1699
1700	LOCK_ZONE(zone);
1701	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1702	UNLOCK_ZONE(zone);
1703
1704	/* Inform the zone table we've finished loading */
1705	if (asl->loaded != NULL)
1706		(asl->loaded)(asl->loaded_arg, zone, task);
1707
1708 cleanup:
1709	isc_mem_put(zone->mctx, asl, sizeof (*asl));
1710	dns_zone_idetach(&zone);
1711}
1712
1713isc_result_t
1714dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
1715	isc_event_t *e;
1716	dns_asyncload_t *asl = NULL;
1717	isc_result_t result = ISC_R_SUCCESS;
1718
1719	REQUIRE(DNS_ZONE_VALID(zone));
1720
1721	if (zone->zmgr == NULL)
1722		return (ISC_R_FAILURE);
1723
1724	asl = isc_mem_get(zone->mctx, sizeof (*asl));
1725	if (asl == NULL)
1726		CHECK(ISC_R_NOMEMORY);
1727
1728	asl->zone = NULL;
1729	asl->loaded = done;
1730	asl->loaded_arg = arg;
1731
1732	e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
1733			       DNS_EVENT_ZONELOAD,
1734			       zone_asyncload, asl,
1735			       sizeof(isc_event_t));
1736	if (e == NULL)
1737		CHECK(ISC_R_NOMEMORY);
1738
1739	LOCK_ZONE(zone);
1740	zone_iattach(zone, &asl->zone);
1741	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1742	isc_task_send(zone->loadtask, &e);
1743	UNLOCK_ZONE(zone);
1744
1745	return (ISC_R_SUCCESS);
1746
1747  failure:
1748	if (asl != NULL)
1749		isc_mem_put(zone->mctx, asl, sizeof (*asl));
1750	return (result);
1751}
1752
1753isc_boolean_t
1754dns__zone_loadpending(dns_zone_t *zone) {
1755	REQUIRE(DNS_ZONE_VALID(zone));
1756
1757	return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)));
1758}
1759
1760isc_result_t
1761dns_zone_loadandthaw(dns_zone_t *zone) {
1762	isc_result_t result;
1763
1764	if (inline_raw(zone))
1765		result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW);
1766	else
1767		result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1768
1769	switch (result) {
1770	case DNS_R_CONTINUE:
1771		/* Deferred thaw. */
1772		break;
1773	case DNS_R_UPTODATE:
1774	case ISC_R_SUCCESS:
1775	case DNS_R_SEENINCLUDE:
1776		zone->update_disabled = ISC_FALSE;
1777		break;
1778	case DNS_R_NOMASTERFILE:
1779		zone->update_disabled = ISC_FALSE;
1780		break;
1781	default:
1782		/* Error, remain in disabled state. */
1783		break;
1784	}
1785	return (result);
1786}
1787
1788static unsigned int
1789get_master_options(dns_zone_t *zone) {
1790	unsigned int options;
1791
1792	options = DNS_MASTER_ZONE;
1793	if (zone->type == dns_zone_slave ||
1794	    (zone->type == dns_zone_redirect && zone->masters == NULL))
1795		options |= DNS_MASTER_SLAVE;
1796	if (zone->type == dns_zone_key)
1797		options |= DNS_MASTER_KEY;
1798	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1799		options |= DNS_MASTER_CHECKNS;
1800	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1801		options |= DNS_MASTER_FATALNS;
1802	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1803		options |= DNS_MASTER_CHECKNAMES;
1804	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1805		options |= DNS_MASTER_CHECKNAMESFAIL;
1806	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1807		options |= DNS_MASTER_CHECKMX;
1808	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1809		options |= DNS_MASTER_CHECKMXFAIL;
1810	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1811		options |= DNS_MASTER_CHECKWILDCARD;
1812	if (inline_secure(zone) || (zone->type == dns_zone_master &&
1813	    ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1814	      zone->ssutable != NULL)))
1815		options |= DNS_MASTER_RESIGN;
1816	return (options);
1817}
1818
1819static void
1820zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1821	dns_load_t *load = event->ev_arg;
1822	isc_result_t result = ISC_R_SUCCESS;
1823	unsigned int options;
1824
1825	REQUIRE(DNS_LOAD_VALID(load));
1826
1827	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1828		result = ISC_R_CANCELED;
1829	isc_event_free(&event);
1830	if (result == ISC_R_CANCELED)
1831		goto fail;
1832
1833	options = get_master_options(load->zone);
1834
1835	result = dns_master_loadfileinc3(load->zone->masterfile,
1836					 dns_db_origin(load->db),
1837					 dns_db_origin(load->db),
1838					 load->zone->rdclass, options,
1839					 load->zone->sigresigninginterval,
1840					 &load->callbacks, task,
1841					 zone_loaddone, load,
1842					 &load->zone->lctx, load->zone->mctx,
1843					 load->zone->masterformat);
1844	if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1845	    result != DNS_R_SEENINCLUDE)
1846		goto fail;
1847	return;
1848
1849 fail:
1850	zone_loaddone(load, result);
1851}
1852
1853static void
1854get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
1855	isc_result_t result;
1856
1857	LOCK(&raw->lock);
1858	if (raw->db != NULL) {
1859		result = zone_get_from_db(raw, raw->db, NULL, NULL,
1860					  &rawdata->sourceserial,
1861					  NULL, NULL, NULL, NULL,
1862					  NULL);
1863		if (result == ISC_R_SUCCESS)
1864			rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
1865	}
1866	UNLOCK(&raw->lock);
1867}
1868
1869static void
1870zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1871	const char me[] = "zone_gotwritehandle";
1872	dns_zone_t *zone = event->ev_arg;
1873	isc_result_t result = ISC_R_SUCCESS;
1874	dns_dbversion_t *version = NULL;
1875	dns_masterrawheader_t rawdata;
1876
1877	REQUIRE(DNS_ZONE_VALID(zone));
1878	INSIST(task == zone->task);
1879	ENTER;
1880
1881	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1882		result = ISC_R_CANCELED;
1883	isc_event_free(&event);
1884	if (result == ISC_R_CANCELED)
1885		goto fail;
1886
1887	LOCK_ZONE(zone);
1888	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1889	if (zone->db != NULL) {
1890		dns_db_currentversion(zone->db, &version);
1891		dns_master_initrawheader(&rawdata);
1892		if (inline_secure(zone))
1893			get_raw_serial(zone->raw, &rawdata);
1894		result = dns_master_dumpinc3(zone->mctx, zone->db, version,
1895					     &dns_master_style_default,
1896					     zone->masterfile, zone->task,
1897					     dump_done, zone, &zone->dctx,
1898					     zone->masterformat, &rawdata);
1899		dns_db_closeversion(zone->db, &version, ISC_FALSE);
1900	} else
1901		result = ISC_R_CANCELED;
1902	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1903	UNLOCK_ZONE(zone);
1904	if (result != DNS_R_CONTINUE)
1905		goto fail;
1906	return;
1907
1908 fail:
1909	dump_done(zone, result);
1910}
1911
1912/*
1913 * Save the raw serial number for inline-signing zones.
1914 * (XXX: Other information from the header will be used
1915 * for other purposes in the future, but for now this is
1916 * all we're interested in.)
1917 */
1918static void
1919zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
1920	if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
1921		return;
1922
1923	zone->sourceserial = header->sourceserial;
1924	zone->sourceserialset = ISC_TRUE;
1925}
1926
1927void
1928dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
1929	if (zone == NULL)
1930		return;
1931
1932	LOCK_ZONE(zone);
1933	zone_setrawdata(zone, header);
1934	UNLOCK_ZONE(zone);
1935}
1936
1937static isc_result_t
1938zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1939	dns_load_t *load;
1940	isc_result_t result;
1941	isc_result_t tresult;
1942	unsigned int options;
1943
1944	options = get_master_options(zone);
1945
1946	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1947		options |= DNS_MASTER_MANYERRORS;
1948
1949	if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
1950		load = isc_mem_get(zone->mctx, sizeof(*load));
1951		if (load == NULL)
1952			return (ISC_R_NOMEMORY);
1953
1954		load->mctx = NULL;
1955		load->zone = NULL;
1956		load->db = NULL;
1957		load->loadtime = loadtime;
1958		load->magic = LOAD_MAGIC;
1959
1960		isc_mem_attach(zone->mctx, &load->mctx);
1961		zone_iattach(zone, &load->zone);
1962		dns_db_attach(db, &load->db);
1963		dns_rdatacallbacks_init(&load->callbacks);
1964		load->callbacks.rawdata = zone_setrawdata;
1965		zone_iattach(zone, &load->callbacks.zone);
1966		result = dns_db_beginload(db, &load->callbacks.add,
1967					  &load->callbacks.add_private);
1968		if (result != ISC_R_SUCCESS)
1969			goto cleanup;
1970		result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask,
1971				       zone_gotreadhandle, load,
1972				       &zone->readio);
1973		if (result != ISC_R_SUCCESS) {
1974			/*
1975			 * We can't report multiple errors so ignore
1976			 * the result of dns_db_endload().
1977			 */
1978			(void)dns_db_endload(load->db,
1979					     &load->callbacks.add_private);
1980			goto cleanup;
1981		} else
1982			result = DNS_R_CONTINUE;
1983	} else {
1984		dns_rdatacallbacks_t callbacks;
1985
1986		dns_rdatacallbacks_init(&callbacks);
1987		callbacks.rawdata = zone_setrawdata;
1988		zone_iattach(zone, &callbacks.zone);
1989		result = dns_db_beginload(db, &callbacks.add,
1990					  &callbacks.add_private);
1991		if (result != ISC_R_SUCCESS) {
1992			zone_idetach(&callbacks.zone);
1993			return (result);
1994		}
1995		result = dns_master_loadfile3(zone->masterfile,
1996					      &zone->origin, &zone->origin,
1997					      zone->rdclass, options,
1998					      zone->sigresigninginterval,
1999					      &callbacks, zone->mctx,
2000					      zone->masterformat);
2001		tresult = dns_db_endload(db, &callbacks.add_private);
2002		if (result == ISC_R_SUCCESS)
2003			result = tresult;
2004		zone_idetach(&callbacks.zone);
2005	}
2006
2007	return (result);
2008
2009 cleanup:
2010	load->magic = 0;
2011	dns_db_detach(&load->db);
2012	zone_idetach(&load->zone);
2013	zone_idetach(&load->callbacks.zone);
2014	isc_mem_detach(&load->mctx);
2015	isc_mem_put(zone->mctx, load, sizeof(*load));
2016	return (result);
2017}
2018
2019static isc_boolean_t
2020zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2021	      dns_name_t *owner)
2022{
2023	isc_result_t result;
2024	char ownerbuf[DNS_NAME_FORMATSIZE];
2025	char namebuf[DNS_NAME_FORMATSIZE];
2026	char altbuf[DNS_NAME_FORMATSIZE];
2027	dns_fixedname_t fixed;
2028	dns_name_t *foundname;
2029	int level;
2030
2031	/*
2032	 * "." means the services does not exist.
2033	 */
2034	if (dns_name_equal(name, dns_rootname))
2035		return (ISC_TRUE);
2036
2037	/*
2038	 * Outside of zone.
2039	 */
2040	if (!dns_name_issubdomain(name, &zone->origin)) {
2041		if (zone->checkmx != NULL)
2042			return ((zone->checkmx)(zone, name, owner));
2043		return (ISC_TRUE);
2044	}
2045
2046	if (zone->type == dns_zone_master)
2047		level = ISC_LOG_ERROR;
2048	else
2049		level = ISC_LOG_WARNING;
2050
2051	dns_fixedname_init(&fixed);
2052	foundname = dns_fixedname_name(&fixed);
2053
2054	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2055			     0, 0, NULL, foundname, NULL, NULL);
2056	if (result == ISC_R_SUCCESS)
2057		return (ISC_TRUE);
2058
2059	if (result == DNS_R_NXRRSET) {
2060		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2061				     0, 0, NULL, foundname, NULL, NULL);
2062		if (result == ISC_R_SUCCESS)
2063			return (ISC_TRUE);
2064	}
2065
2066	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2067	dns_name_format(name, namebuf, sizeof namebuf);
2068	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2069	    result == DNS_R_EMPTYNAME) {
2070		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2071			level = ISC_LOG_WARNING;
2072		dns_zone_log(zone, level,
2073			     "%s/MX '%s' has no address records (A or AAAA)",
2074			     ownerbuf, namebuf);
2075		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2076	}
2077
2078	if (result == DNS_R_CNAME) {
2079		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2080		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2081			level = ISC_LOG_WARNING;
2082		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2083			dns_zone_log(zone, level,
2084				     "%s/MX '%s' is a CNAME (illegal)",
2085				     ownerbuf, namebuf);
2086		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2087	}
2088
2089	if (result == DNS_R_DNAME) {
2090		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2091		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2092			level = ISC_LOG_WARNING;
2093		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2094			dns_name_format(foundname, altbuf, sizeof altbuf);
2095			dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2096				     " '%s' (illegal)", ownerbuf, namebuf,
2097				     altbuf);
2098		}
2099		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2100	}
2101
2102	if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2103		return ((zone->checkmx)(zone, name, owner));
2104
2105	return (ISC_TRUE);
2106}
2107
2108static isc_boolean_t
2109zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2110	       dns_name_t *owner)
2111{
2112	isc_result_t result;
2113	char ownerbuf[DNS_NAME_FORMATSIZE];
2114	char namebuf[DNS_NAME_FORMATSIZE];
2115	char altbuf[DNS_NAME_FORMATSIZE];
2116	dns_fixedname_t fixed;
2117	dns_name_t *foundname;
2118	int level;
2119
2120	/*
2121	 * "." means the services does not exist.
2122	 */
2123	if (dns_name_equal(name, dns_rootname))
2124		return (ISC_TRUE);
2125
2126	/*
2127	 * Outside of zone.
2128	 */
2129	if (!dns_name_issubdomain(name, &zone->origin)) {
2130		if (zone->checksrv != NULL)
2131			return ((zone->checksrv)(zone, name, owner));
2132		return (ISC_TRUE);
2133	}
2134
2135	if (zone->type == dns_zone_master)
2136		level = ISC_LOG_ERROR;
2137	else
2138		level = ISC_LOG_WARNING;
2139
2140	dns_fixedname_init(&fixed);
2141	foundname = dns_fixedname_name(&fixed);
2142
2143	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2144			     0, 0, NULL, foundname, NULL, NULL);
2145	if (result == ISC_R_SUCCESS)
2146		return (ISC_TRUE);
2147
2148	if (result == DNS_R_NXRRSET) {
2149		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2150				     0, 0, NULL, foundname, NULL, NULL);
2151		if (result == ISC_R_SUCCESS)
2152			return (ISC_TRUE);
2153	}
2154
2155	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2156	dns_name_format(name, namebuf, sizeof namebuf);
2157	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2158	    result == DNS_R_EMPTYNAME) {
2159		dns_zone_log(zone, level,
2160			     "%s/SRV '%s' has no address records (A or AAAA)",
2161			     ownerbuf, namebuf);
2162		/* XXX950 make fatal for 9.5.0. */
2163		return (ISC_TRUE);
2164	}
2165
2166	if (result == DNS_R_CNAME) {
2167		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2168		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2169			level = ISC_LOG_WARNING;
2170		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2171			dns_zone_log(zone, level,
2172				     "%s/SRV '%s' is a CNAME (illegal)",
2173				     ownerbuf, namebuf);
2174		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2175	}
2176
2177	if (result == DNS_R_DNAME) {
2178		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2179		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2180			level = ISC_LOG_WARNING;
2181		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2182			dns_name_format(foundname, altbuf, sizeof altbuf);
2183			dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2184				     "DNAME '%s' (illegal)", ownerbuf, namebuf,
2185				     altbuf);
2186		}
2187		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2188	}
2189
2190	if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2191		return ((zone->checksrv)(zone, name, owner));
2192
2193	return (ISC_TRUE);
2194}
2195
2196static isc_boolean_t
2197zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2198		dns_name_t *owner)
2199{
2200	isc_boolean_t answer = ISC_TRUE;
2201	isc_result_t result, tresult;
2202	char ownerbuf[DNS_NAME_FORMATSIZE];
2203	char namebuf[DNS_NAME_FORMATSIZE];
2204	char altbuf[DNS_NAME_FORMATSIZE];
2205	dns_fixedname_t fixed;
2206	dns_name_t *foundname;
2207	dns_rdataset_t a;
2208	dns_rdataset_t aaaa;
2209	int level;
2210
2211	/*
2212	 * Outside of zone.
2213	 */
2214	if (!dns_name_issubdomain(name, &zone->origin)) {
2215		if (zone->checkns != NULL)
2216			return ((zone->checkns)(zone, name, owner, NULL, NULL));
2217		return (ISC_TRUE);
2218	}
2219
2220	if (zone->type == dns_zone_master)
2221		level = ISC_LOG_ERROR;
2222	else
2223		level = ISC_LOG_WARNING;
2224
2225	dns_fixedname_init(&fixed);
2226	foundname = dns_fixedname_name(&fixed);
2227	dns_rdataset_init(&a);
2228	dns_rdataset_init(&aaaa);
2229
2230	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2231			     DNS_DBFIND_GLUEOK, 0, NULL,
2232			     foundname, &a, NULL);
2233
2234	if (result == ISC_R_SUCCESS) {
2235		dns_rdataset_disassociate(&a);
2236		return (ISC_TRUE);
2237	} else if (result == DNS_R_DELEGATION)
2238		dns_rdataset_disassociate(&a);
2239
2240	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2241	    result == DNS_R_GLUE) {
2242		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2243				     DNS_DBFIND_GLUEOK, 0, NULL,
2244				     foundname, &aaaa, NULL);
2245		if (tresult == ISC_R_SUCCESS) {
2246			dns_rdataset_disassociate(&aaaa);
2247			return (ISC_TRUE);
2248		}
2249		if (tresult == DNS_R_DELEGATION)
2250			dns_rdataset_disassociate(&aaaa);
2251		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2252			/*
2253			 * Check glue against child zone.
2254			 */
2255			if (zone->checkns != NULL)
2256				answer = (zone->checkns)(zone, name, owner,
2257							 &a, &aaaa);
2258			if (dns_rdataset_isassociated(&a))
2259				dns_rdataset_disassociate(&a);
2260			if (dns_rdataset_isassociated(&aaaa))
2261				dns_rdataset_disassociate(&aaaa);
2262			return (answer);
2263		}
2264	}
2265
2266	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2267	dns_name_format(name, namebuf, sizeof namebuf);
2268	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2269	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2270		const char *what;
2271		isc_boolean_t required = ISC_FALSE;
2272		if (dns_name_issubdomain(name, owner)) {
2273			what = "REQUIRED GLUE ";
2274			required = ISC_TRUE;
2275		 } else if (result == DNS_R_DELEGATION)
2276			what = "SIBLING GLUE ";
2277		else
2278			what = "";
2279
2280		if (result != DNS_R_DELEGATION || required ||
2281		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2282			dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2283				     "address records (A or AAAA)",
2284				     ownerbuf, namebuf, what);
2285			/*
2286			 * Log missing address record.
2287			 */
2288			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2289				(void)(zone->checkns)(zone, name, owner,
2290						      &a, &aaaa);
2291			/* XXX950 make fatal for 9.5.0. */
2292			/* answer = ISC_FALSE; */
2293		}
2294	} else if (result == DNS_R_CNAME) {
2295		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2296			     ownerbuf, namebuf);
2297		/* XXX950 make fatal for 9.5.0. */
2298		/* answer = ISC_FALSE; */
2299	} else if (result == DNS_R_DNAME) {
2300		dns_name_format(foundname, altbuf, sizeof altbuf);
2301		dns_zone_log(zone, level,
2302			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
2303			     ownerbuf, namebuf, altbuf);
2304		/* XXX950 make fatal for 9.5.0. */
2305		/* answer = ISC_FALSE; */
2306	}
2307
2308	if (dns_rdataset_isassociated(&a))
2309		dns_rdataset_disassociate(&a);
2310	if (dns_rdataset_isassociated(&aaaa))
2311		dns_rdataset_disassociate(&aaaa);
2312	return (answer);
2313}
2314
2315static isc_boolean_t
2316zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2317		     dns_rdataset_t *rdataset)
2318{
2319	dns_rdataset_t tmprdataset;
2320	isc_result_t result;
2321	isc_boolean_t answer = ISC_TRUE;
2322	isc_boolean_t format = ISC_TRUE;
2323	int level = ISC_LOG_WARNING;
2324	char ownerbuf[DNS_NAME_FORMATSIZE];
2325	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2326	unsigned int count1 = 0;
2327
2328	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2329		level = ISC_LOG_ERROR;
2330
2331	dns_rdataset_init(&tmprdataset);
2332	for (result = dns_rdataset_first(rdataset);
2333	     result == ISC_R_SUCCESS;
2334	     result = dns_rdataset_next(rdataset)) {
2335		dns_rdata_t rdata1 = DNS_RDATA_INIT;
2336		unsigned int count2 = 0;
2337
2338		count1++;
2339		dns_rdataset_current(rdataset, &rdata1);
2340		dns_rdataset_clone(rdataset, &tmprdataset);
2341		for (result = dns_rdataset_first(&tmprdataset);
2342		     result == ISC_R_SUCCESS;
2343		     result = dns_rdataset_next(&tmprdataset)) {
2344			dns_rdata_t rdata2 = DNS_RDATA_INIT;
2345			count2++;
2346			if (count1 >= count2)
2347				continue;
2348			dns_rdataset_current(&tmprdataset, &rdata2);
2349			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2350				if (format) {
2351					dns_name_format(owner, ownerbuf,
2352							sizeof ownerbuf);
2353					dns_rdatatype_format(rdata1.type,
2354							     typebuf,
2355							     sizeof(typebuf));
2356					format = ISC_FALSE;
2357				}
2358				dns_zone_log(zone, level, "%s/%s has "
2359					     "semantically identical records",
2360					     ownerbuf, typebuf);
2361				if (level == ISC_LOG_ERROR)
2362					answer = ISC_FALSE;
2363				break;
2364			}
2365		}
2366		dns_rdataset_disassociate(&tmprdataset);
2367		if (!format)
2368			break;
2369	}
2370	return (answer);
2371}
2372
2373static isc_boolean_t
2374zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2375	dns_dbiterator_t *dbiterator = NULL;
2376	dns_dbnode_t *node = NULL;
2377	dns_fixedname_t fixed;
2378	dns_name_t *name;
2379	dns_rdataset_t rdataset;
2380	dns_rdatasetiter_t *rdsit = NULL;
2381	isc_boolean_t ok = ISC_TRUE;
2382	isc_result_t result;
2383
2384	dns_fixedname_init(&fixed);
2385	name = dns_fixedname_name(&fixed);
2386	dns_rdataset_init(&rdataset);
2387
2388	result = dns_db_createiterator(db, 0, &dbiterator);
2389	if (result != ISC_R_SUCCESS)
2390		return (ISC_TRUE);
2391
2392	for (result = dns_dbiterator_first(dbiterator);
2393	     result == ISC_R_SUCCESS;
2394	     result = dns_dbiterator_next(dbiterator)) {
2395		result = dns_dbiterator_current(dbiterator, &node, name);
2396		if (result != ISC_R_SUCCESS)
2397			continue;
2398
2399		result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2400		if (result != ISC_R_SUCCESS)
2401			continue;
2402
2403		for (result = dns_rdatasetiter_first(rdsit);
2404		     result == ISC_R_SUCCESS;
2405		     result = dns_rdatasetiter_next(rdsit)) {
2406			dns_rdatasetiter_current(rdsit, &rdataset);
2407			if (!zone_rrset_check_dup(zone, name, &rdataset))
2408				ok = ISC_FALSE;
2409			dns_rdataset_disassociate(&rdataset);
2410		}
2411		dns_rdatasetiter_destroy(&rdsit);
2412		dns_db_detachnode(db, &node);
2413	}
2414
2415	if (node != NULL)
2416		dns_db_detachnode(db, &node);
2417	dns_dbiterator_destroy(&dbiterator);
2418
2419	return (ok);
2420}
2421
2422static isc_boolean_t
2423integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2424	dns_dbiterator_t *dbiterator = NULL;
2425	dns_dbnode_t *node = NULL;
2426	dns_rdataset_t rdataset;
2427	dns_fixedname_t fixed;
2428	dns_fixedname_t fixedbottom;
2429	dns_rdata_mx_t mx;
2430	dns_rdata_ns_t ns;
2431	dns_rdata_in_srv_t srv;
2432	dns_rdata_t rdata;
2433	dns_name_t *name;
2434	dns_name_t *bottom;
2435	isc_result_t result;
2436	isc_boolean_t ok = ISC_TRUE;
2437
2438	dns_fixedname_init(&fixed);
2439	name = dns_fixedname_name(&fixed);
2440	dns_fixedname_init(&fixedbottom);
2441	bottom = dns_fixedname_name(&fixedbottom);
2442	dns_rdataset_init(&rdataset);
2443	dns_rdata_init(&rdata);
2444
2445	result = dns_db_createiterator(db, 0, &dbiterator);
2446	if (result != ISC_R_SUCCESS)
2447		return (ISC_TRUE);
2448
2449	result = dns_dbiterator_first(dbiterator);
2450	while (result == ISC_R_SUCCESS) {
2451		result = dns_dbiterator_current(dbiterator, &node, name);
2452		if (result != ISC_R_SUCCESS)
2453			goto cleanup;
2454
2455		/*
2456		 * Is this name visible in the zone?
2457		 */
2458		if (!dns_name_issubdomain(name, &zone->origin) ||
2459		    (dns_name_countlabels(bottom) > 0 &&
2460		     dns_name_issubdomain(name, bottom)))
2461			goto next;
2462
2463		/*
2464		 * Don't check the NS records at the origin.
2465		 */
2466		if (dns_name_equal(name, &zone->origin))
2467			goto checkmx;
2468
2469		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2470					     0, 0, &rdataset, NULL);
2471		if (result != ISC_R_SUCCESS)
2472			goto checkmx;
2473		/*
2474		 * Remember bottom of zone.
2475		 */
2476		dns_name_copy(name, bottom, NULL);
2477
2478		result = dns_rdataset_first(&rdataset);
2479		while (result == ISC_R_SUCCESS) {
2480			dns_rdataset_current(&rdataset, &rdata);
2481			result = dns_rdata_tostruct(&rdata, &ns, NULL);
2482			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2483			if (!zone_check_glue(zone, db, &ns.name, name))
2484				ok = ISC_FALSE;
2485			dns_rdata_reset(&rdata);
2486			result = dns_rdataset_next(&rdataset);
2487		}
2488		dns_rdataset_disassociate(&rdataset);
2489		goto next;
2490
2491 checkmx:
2492		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2493					     0, 0, &rdataset, NULL);
2494		if (result != ISC_R_SUCCESS)
2495			goto checksrv;
2496		result = dns_rdataset_first(&rdataset);
2497		while (result == ISC_R_SUCCESS) {
2498			dns_rdataset_current(&rdataset, &rdata);
2499			result = dns_rdata_tostruct(&rdata, &mx, NULL);
2500			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2501			if (!zone_check_mx(zone, db, &mx.mx, name))
2502				ok = ISC_FALSE;
2503			dns_rdata_reset(&rdata);
2504			result = dns_rdataset_next(&rdataset);
2505		}
2506		dns_rdataset_disassociate(&rdataset);
2507
2508 checksrv:
2509		if (zone->rdclass != dns_rdataclass_in)
2510			goto next;
2511		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2512					     0, 0, &rdataset, NULL);
2513		if (result != ISC_R_SUCCESS)
2514			goto next;
2515		result = dns_rdataset_first(&rdataset);
2516		while (result == ISC_R_SUCCESS) {
2517			dns_rdataset_current(&rdataset, &rdata);
2518			result = dns_rdata_tostruct(&rdata, &srv, NULL);
2519			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2520			if (!zone_check_srv(zone, db, &srv.target, name))
2521				ok = ISC_FALSE;
2522			dns_rdata_reset(&rdata);
2523			result = dns_rdataset_next(&rdataset);
2524		}
2525		dns_rdataset_disassociate(&rdataset);
2526
2527 next:
2528		dns_db_detachnode(db, &node);
2529		result = dns_dbiterator_next(dbiterator);
2530	}
2531
2532 cleanup:
2533	if (node != NULL)
2534		dns_db_detachnode(db, &node);
2535	dns_dbiterator_destroy(&dbiterator);
2536
2537	return (ok);
2538}
2539
2540/*
2541 * OpenSSL verification of RSA keys with exponent 3 is known to be
2542 * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
2543 * if they are in use.
2544 */
2545static void
2546zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2547	dns_dbnode_t *node = NULL;
2548	dns_dbversion_t *version = NULL;
2549	dns_rdata_dnskey_t dnskey;
2550	dns_rdata_t rdata = DNS_RDATA_INIT;
2551	dns_rdataset_t rdataset;
2552	isc_result_t result;
2553	isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2554	const char *algorithm;
2555
2556	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2557	if (result != ISC_R_SUCCESS)
2558		goto cleanup;
2559
2560	dns_db_currentversion(db, &version);
2561	dns_rdataset_init(&rdataset);
2562	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2563				     dns_rdatatype_none, 0, &rdataset, NULL);
2564	if (result != ISC_R_SUCCESS)
2565		goto cleanup;
2566
2567	for (result = dns_rdataset_first(&rdataset);
2568	     result == ISC_R_SUCCESS;
2569	     result = dns_rdataset_next(&rdataset))
2570	{
2571		dns_rdataset_current(&rdataset, &rdata);
2572		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2573		INSIST(result == ISC_R_SUCCESS);
2574
2575		if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2576		     dnskey.algorithm == DST_ALG_RSAMD5) &&
2577		     dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2578		     dnskey.data[1] == 3)
2579		{
2580			if (dnskey.algorithm == DST_ALG_RSASHA1) {
2581				logit = !foundrsa;
2582				foundrsa = ISC_TRUE;
2583				algorithm = "RSASHA1";
2584			} else {
2585				logit = !foundmd5;
2586				foundmd5 = ISC_TRUE;
2587				algorithm = "RSAMD5";
2588			}
2589			if (logit)
2590				dns_zone_log(zone, ISC_LOG_WARNING,
2591					     "weak %s (%u) key found "
2592					     "(exponent=3)", algorithm,
2593					     dnskey.algorithm);
2594			if (foundrsa && foundmd5)
2595				break;
2596		}
2597		dns_rdata_reset(&rdata);
2598	}
2599	dns_rdataset_disassociate(&rdataset);
2600
2601 cleanup:
2602	if (node != NULL)
2603		dns_db_detachnode(db, &node);
2604	if (version != NULL)
2605		dns_db_closeversion(db, &version, ISC_FALSE);
2606}
2607
2608static void
2609resume_signingwithkey(dns_zone_t *zone) {
2610	dns_dbnode_t *node = NULL;
2611	dns_dbversion_t *version = NULL;
2612	dns_rdata_t rdata = DNS_RDATA_INIT;
2613	dns_rdataset_t rdataset;
2614	isc_result_t result;
2615
2616	result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2617	if (result != ISC_R_SUCCESS)
2618		goto cleanup;
2619
2620	dns_db_currentversion(zone->db, &version);
2621	dns_rdataset_init(&rdataset);
2622	result = dns_db_findrdataset(zone->db, node, version,
2623				     zone->privatetype,
2624				     dns_rdatatype_none, 0,
2625				     &rdataset, NULL);
2626	if (result != ISC_R_SUCCESS) {
2627		INSIST(!dns_rdataset_isassociated(&rdataset));
2628		goto cleanup;
2629	}
2630
2631	for (result = dns_rdataset_first(&rdataset);
2632	     result == ISC_R_SUCCESS;
2633	     result = dns_rdataset_next(&rdataset))
2634	{
2635		dns_rdataset_current(&rdataset, &rdata);
2636		if (rdata.length != 5 ||
2637		    rdata.data[0] == 0 || rdata.data[4] != 0) {
2638			dns_rdata_reset(&rdata);
2639			continue;
2640		}
2641
2642		result = zone_signwithkey(zone, rdata.data[0],
2643					  (rdata.data[1] << 8) | rdata.data[2],
2644					  ISC_TF(rdata.data[3]));
2645		if (result != ISC_R_SUCCESS) {
2646			dns_zone_log(zone, ISC_LOG_ERROR,
2647				     "zone_signwithkey failed: %s",
2648				     dns_result_totext(result));
2649		}
2650		dns_rdata_reset(&rdata);
2651	}
2652	dns_rdataset_disassociate(&rdataset);
2653
2654 cleanup:
2655	if (node != NULL)
2656		dns_db_detachnode(zone->db, &node);
2657	if (version != NULL)
2658		dns_db_closeversion(zone->db, &version, ISC_FALSE);
2659}
2660
2661static isc_result_t
2662zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2663	dns_nsec3chain_t *nsec3chain, *current;
2664	dns_dbversion_t *version = NULL;
2665	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
2666	isc_result_t result;
2667	isc_time_t now;
2668	unsigned int options = 0;
2669	char saltbuf[255*2+1];
2670	char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
2671	int i;
2672
2673	dns_db_currentversion(zone->db, &version);
2674	result = dns_nsec_nseconly(zone->db, version, &nseconly);
2675	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
2676	dns_db_closeversion(zone->db, &version, ISC_FALSE);
2677	if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0)
2678		return (ISC_R_SUCCESS);
2679
2680	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2681	if (nsec3chain == NULL)
2682		return (ISC_R_NOMEMORY);
2683
2684	nsec3chain->magic = 0;
2685	nsec3chain->done = ISC_FALSE;
2686	nsec3chain->db = NULL;
2687	nsec3chain->dbiterator = NULL;
2688	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2689	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2690	nsec3chain->nsec3param.hash = nsec3param->hash;
2691	nsec3chain->nsec3param.iterations = nsec3param->iterations;
2692	nsec3chain->nsec3param.flags = nsec3param->flags;
2693	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2694	memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2695	nsec3chain->nsec3param.salt = nsec3chain->salt;
2696	nsec3chain->seen_nsec = ISC_FALSE;
2697	nsec3chain->delete_nsec = ISC_FALSE;
2698	nsec3chain->save_delete_nsec = ISC_FALSE;
2699
2700	if (nsec3param->flags == 0)
2701		strlcpy(flags, "NONE", sizeof(flags));
2702	else {
2703		flags[0] = '\0';
2704		if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2705			strlcat(flags, "REMOVE", sizeof(flags));
2706		if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) {
2707			if (flags[0] == '\0')
2708				strlcpy(flags, "INITIAL", sizeof(flags));
2709			else
2710				strlcat(flags, "|INITIAL", sizeof(flags));
2711		}
2712		if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2713			if (flags[0] == '\0')
2714				strlcpy(flags, "CREATE", sizeof(flags));
2715			else
2716				strlcat(flags, "|CREATE", sizeof(flags));
2717		}
2718		if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2719			if (flags[0] == '\0')
2720				strlcpy(flags, "NONSEC", sizeof(flags));
2721			else
2722				strlcat(flags, "|NONSEC", sizeof(flags));
2723		}
2724		if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2725			if (flags[0] == '\0')
2726				strlcpy(flags, "OPTOUT", sizeof(flags));
2727			else
2728				strlcat(flags, "|OPTOUT", sizeof(flags));
2729		}
2730	}
2731	if (nsec3param->salt_length == 0)
2732		strlcpy(saltbuf, "-", sizeof(saltbuf));
2733	else
2734		for (i = 0; i < nsec3param->salt_length; i++)
2735			sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2736	dns_zone_log(zone, ISC_LOG_INFO,
2737		     "zone_addnsec3chain(%u,%s,%u,%s)",
2738		      nsec3param->hash, flags, nsec3param->iterations,
2739		      saltbuf);
2740
2741	for (current = ISC_LIST_HEAD(zone->nsec3chain);
2742	     current != NULL;
2743	     current = ISC_LIST_NEXT(current, link)) {
2744		if (current->db == zone->db &&
2745		    current->nsec3param.hash == nsec3param->hash &&
2746		    current->nsec3param.iterations == nsec3param->iterations &&
2747		    current->nsec3param.salt_length == nsec3param->salt_length
2748		    && !memcmp(current->nsec3param.salt, nsec3param->salt,
2749			       nsec3param->salt_length))
2750			current->done = ISC_TRUE;
2751	}
2752
2753	if (zone->db != NULL) {
2754		dns_db_attach(zone->db, &nsec3chain->db);
2755		if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2756			options = DNS_DB_NONSEC3;
2757		result = dns_db_createiterator(nsec3chain->db, options,
2758					       &nsec3chain->dbiterator);
2759		if (result == ISC_R_SUCCESS)
2760			dns_dbiterator_first(nsec3chain->dbiterator);
2761		if (result == ISC_R_SUCCESS) {
2762			dns_dbiterator_pause(nsec3chain->dbiterator);
2763			ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2764					       nsec3chain, link);
2765			nsec3chain = NULL;
2766			if (isc_time_isepoch(&zone->nsec3chaintime)) {
2767				TIME_NOW(&now);
2768				zone->nsec3chaintime = now;
2769				if (zone->task != NULL)
2770					zone_settimer(zone, &now);
2771			}
2772		}
2773	} else
2774		result = ISC_R_NOTFOUND;
2775
2776	if (nsec3chain != NULL) {
2777		if (nsec3chain->db != NULL)
2778			dns_db_detach(&nsec3chain->db);
2779		if (nsec3chain->dbiterator != NULL)
2780			dns_dbiterator_destroy(&nsec3chain->dbiterator);
2781		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2782	}
2783	return (result);
2784}
2785
2786static void
2787resume_addnsec3chain(dns_zone_t *zone) {
2788	dns_dbnode_t *node = NULL;
2789	dns_dbversion_t *version = NULL;
2790	dns_rdataset_t rdataset;
2791	isc_result_t result;
2792	dns_rdata_nsec3param_t nsec3param;
2793	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
2794
2795	if (zone->privatetype == 0)
2796		return;
2797
2798	result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2799	if (result != ISC_R_SUCCESS)
2800		goto cleanup;
2801
2802	dns_db_currentversion(zone->db, &version);
2803
2804	result = dns_nsec_nseconly(zone->db, version, &nseconly);
2805	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
2806
2807	dns_rdataset_init(&rdataset);
2808	result = dns_db_findrdataset(zone->db, node, version,
2809				     zone->privatetype, dns_rdatatype_none,
2810				     0, &rdataset, NULL);
2811	if (result != ISC_R_SUCCESS) {
2812		INSIST(!dns_rdataset_isassociated(&rdataset));
2813		goto cleanup;
2814	}
2815
2816	for (result = dns_rdataset_first(&rdataset);
2817	     result == ISC_R_SUCCESS;
2818	     result = dns_rdataset_next(&rdataset))
2819	{
2820		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
2821		dns_rdata_t rdata = DNS_RDATA_INIT;
2822		dns_rdata_t private = DNS_RDATA_INIT;
2823
2824		dns_rdataset_current(&rdataset, &private);
2825		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
2826						sizeof(buf)))
2827			continue;
2828		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2829		RUNTIME_CHECK(result == ISC_R_SUCCESS);
2830		if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
2831		    ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
2832		{
2833			result = zone_addnsec3chain(zone, &nsec3param);
2834			if (result != ISC_R_SUCCESS) {
2835				dns_zone_log(zone, ISC_LOG_ERROR,
2836					     "zone_addnsec3chain failed: %s",
2837					     dns_result_totext(result));
2838			}
2839		}
2840	}
2841	dns_rdataset_disassociate(&rdataset);
2842 cleanup:
2843	if (node != NULL)
2844		dns_db_detachnode(zone->db, &node);
2845	if (version != NULL)
2846		dns_db_closeversion(zone->db, &version, ISC_FALSE);
2847}
2848
2849static void
2850set_resigntime(dns_zone_t *zone) {
2851	dns_rdataset_t rdataset;
2852	dns_fixedname_t fixed;
2853	unsigned int resign;
2854	isc_result_t result;
2855	isc_uint32_t nanosecs;
2856
2857	dns_rdataset_init(&rdataset);
2858	dns_fixedname_init(&fixed);
2859	result = dns_db_getsigningtime(zone->db, &rdataset,
2860				       dns_fixedname_name(&fixed));
2861	if (result != ISC_R_SUCCESS) {
2862		isc_time_settoepoch(&zone->resigntime);
2863		return;
2864	}
2865	resign = rdataset.resign;
2866	dns_rdataset_disassociate(&rdataset);
2867	isc_random_get(&nanosecs);
2868	nanosecs %= 1000000000;
2869	isc_time_set(&zone->resigntime, resign, nanosecs);
2870}
2871
2872static isc_result_t
2873check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
2874	dns_dbnode_t *node = NULL;
2875	dns_rdataset_t rdataset;
2876	dns_dbversion_t *version = NULL;
2877	dns_rdata_nsec3param_t nsec3param;
2878	isc_boolean_t ok = ISC_FALSE;
2879	isc_result_t result;
2880	dns_rdata_t rdata = DNS_RDATA_INIT;
2881	isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
2882				dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE;
2883
2884	dns_rdataset_init(&rdataset);
2885	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2886	if (result != ISC_R_SUCCESS) {
2887		dns_zone_log(zone, ISC_LOG_ERROR,
2888			     "nsec3param lookup failure: %s",
2889			     dns_result_totext(result));
2890		return (result);
2891	}
2892	dns_db_currentversion(db, &version);
2893
2894	result = dns_db_findrdataset(db, node, version,
2895				     dns_rdatatype_nsec3param,
2896				     dns_rdatatype_none, 0, &rdataset, NULL);
2897	if (result == ISC_R_NOTFOUND) {
2898		INSIST(!dns_rdataset_isassociated(&rdataset));
2899		result = ISC_R_SUCCESS;
2900		goto cleanup;
2901	}
2902	if (result != ISC_R_SUCCESS) {
2903		INSIST(!dns_rdataset_isassociated(&rdataset));
2904		dns_zone_log(zone, ISC_LOG_ERROR,
2905			     "nsec3param lookup failure: %s",
2906			     dns_result_totext(result));
2907		goto cleanup;
2908	}
2909
2910	/*
2911	 * For dynamic zones we must support every algorithm so we can
2912	 * regenerate all the NSEC3 chains.
2913	 * For non-dynamic zones we only need to find a supported algorithm.
2914	 */
2915	for (result = dns_rdataset_first(&rdataset);
2916	     result == ISC_R_SUCCESS;
2917	     result = dns_rdataset_next(&rdataset))
2918	{
2919		dns_rdataset_current(&rdataset, &rdata);
2920		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2921		dns_rdata_reset(&rdata);
2922		INSIST(result == ISC_R_SUCCESS);
2923		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
2924		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
2925		{
2926			dns_zone_log(zone, ISC_LOG_WARNING,
2927			     "nsec3 test \"unknown\" hash algorithm found: %u",
2928				     nsec3param.hash);
2929			ok = ISC_TRUE;
2930		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
2931			if (dynamic) {
2932				dns_zone_log(zone, ISC_LOG_ERROR,
2933					     "unsupported nsec3 hash algorithm"
2934					     " in dynamic zone: %u",
2935					     nsec3param.hash);
2936				result = DNS_R_BADZONE;
2937				/* Stop second error message. */
2938				ok = ISC_TRUE;
2939				break;
2940			} else
2941				dns_zone_log(zone, ISC_LOG_WARNING,
2942				     "unsupported nsec3 hash algorithm: %u",
2943					     nsec3param.hash);
2944		} else
2945			ok = ISC_TRUE;
2946	}
2947	if (result == ISC_R_NOMORE)
2948		result = ISC_R_SUCCESS;
2949
2950	if (!ok) {
2951		result = DNS_R_BADZONE;
2952		dns_zone_log(zone, ISC_LOG_ERROR,
2953			     "no supported nsec3 hash algorithm");
2954	}
2955
2956 cleanup:
2957	if (dns_rdataset_isassociated(&rdataset))
2958		dns_rdataset_disassociate(&rdataset);
2959	dns_db_closeversion(db, &version, ISC_FALSE);
2960	dns_db_detachnode(db, &node);
2961	return (result);
2962}
2963
2964/*
2965 * Set the timer for refreshing the key zone to the soonest future time
2966 * of the set (current timer, keydata->refresh, keydata->addhd,
2967 * keydata->removehd).
2968 */
2969static void
2970set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
2971		    isc_stdtime_t now)
2972{
2973	const char me[] = "set_refreshkeytimer";
2974	isc_stdtime_t then;
2975	isc_time_t timenow, timethen;
2976	char timebuf[80];
2977
2978	ENTER;
2979	then = key->refresh;
2980	if (key->addhd > now && key->addhd < then)
2981		then = key->addhd;
2982	if (key->removehd > now && key->removehd < then)
2983		then = key->removehd;
2984
2985	TIME_NOW(&timenow);
2986	if (then > now)
2987		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
2988	else
2989		timethen = timenow;
2990	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
2991	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
2992		zone->refreshkeytime = timethen;
2993
2994	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
2995	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
2996	zone_settimer(zone, &timenow);
2997}
2998
2999/*
3000 * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3001 * If the key zone is changed, set '*changed' to ISC_TRUE.
3002 */
3003static isc_result_t
3004create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3005	       dns_diff_t *diff, dns_keytable_t *keytable,
3006	       dns_keynode_t **keynodep, isc_boolean_t *changed)
3007{
3008	const char me[] = "create_keydata";
3009	isc_result_t result = ISC_R_SUCCESS;
3010	isc_buffer_t keyb, dstb;
3011	unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3012	dns_rdata_keydata_t keydata;
3013	dns_rdata_dnskey_t dnskey;
3014	dns_rdata_t rdata = DNS_RDATA_INIT;
3015	dns_keynode_t *keynode;
3016	isc_stdtime_t now;
3017	isc_region_t r;
3018	dst_key_t *key;
3019
3020	REQUIRE(keynodep != NULL);
3021	keynode = *keynodep;
3022
3023	ENTER;
3024	isc_stdtime_get(&now);
3025
3026	/* Loop in case there's more than one key. */
3027	while (result == ISC_R_SUCCESS) {
3028		dns_keynode_t *nextnode = NULL;
3029
3030		key = dns_keynode_key(keynode);
3031		if (key == NULL)
3032			goto skip;
3033
3034		isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3035		CHECK(dst_key_todns(key, &dstb));
3036
3037		/* Convert DST key to DNSKEY. */
3038		dns_rdata_reset(&rdata);
3039		isc_buffer_usedregion(&dstb, &r);
3040		dns_rdata_fromregion(&rdata, dst_key_class(key),
3041				     dns_rdatatype_dnskey, &r);
3042
3043		/* DSTKEY to KEYDATA. */
3044		CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3045		CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3046					     NULL));
3047
3048		/* KEYDATA to rdata. */
3049		dns_rdata_reset(&rdata);
3050		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3051		CHECK(dns_rdata_fromstruct(&rdata,
3052					   zone->rdclass, dns_rdatatype_keydata,
3053					   &keydata, &keyb));
3054
3055		/* Add rdata to zone. */
3056		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3057				    dst_key_name(key), 0, &rdata));
3058		*changed = ISC_TRUE;
3059
3060 skip:
3061		result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3062		if (result != ISC_R_NOTFOUND) {
3063			dns_keytable_detachkeynode(keytable, &keynode);
3064			keynode = nextnode;
3065		}
3066	}
3067
3068	/* Refresh new keys from the zone apex as soon as possible. */
3069	if (*changed)
3070		set_refreshkeytimer(zone, &keydata, now);
3071
3072	if (keynode != NULL)
3073		dns_keytable_detachkeynode(keytable, &keynode);
3074	*keynodep = NULL;
3075
3076	return (ISC_R_SUCCESS);
3077
3078  failure:
3079	return (result);
3080}
3081
3082/*
3083 * Remove from the key zone all the KEYDATA records found in rdataset.
3084 */
3085static isc_result_t
3086delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3087	       dns_name_t *name, dns_rdataset_t *rdataset)
3088{
3089	dns_rdata_t rdata = DNS_RDATA_INIT;
3090	isc_result_t result, uresult;
3091
3092	for (result = dns_rdataset_first(rdataset);
3093	     result == ISC_R_SUCCESS;
3094	     result = dns_rdataset_next(rdataset)) {
3095		dns_rdata_reset(&rdata);
3096		dns_rdataset_current(rdataset, &rdata);
3097		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3098					name, 0, &rdata);
3099		if (uresult != ISC_R_SUCCESS)
3100			return (uresult);
3101	}
3102	if (result == ISC_R_NOMORE)
3103		result = ISC_R_SUCCESS;
3104	return (result);
3105}
3106
3107/*
3108 * Compute the DNSSEC key ID for a DNSKEY record.
3109 */
3110static isc_result_t
3111compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3112	    dns_keytag_t *tag)
3113{
3114	isc_result_t result;
3115	dns_rdata_t rdata = DNS_RDATA_INIT;
3116	unsigned char data[4096];
3117	isc_buffer_t buffer;
3118	dst_key_t *dstkey = NULL;
3119
3120	isc_buffer_init(&buffer, data, sizeof(data));
3121	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3122			     dns_rdatatype_dnskey, dnskey, &buffer);
3123
3124	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3125	if (result == ISC_R_SUCCESS)
3126		*tag = dst_key_id(dstkey);
3127	dst_key_free(&dstkey);
3128
3129	return (result);
3130}
3131
3132/*
3133 * Add key to the security roots.
3134 */
3135static void
3136trust_key(dns_zone_t *zone, dns_name_t *keyname,
3137	  dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
3138	isc_result_t result;
3139	dns_rdata_t rdata = DNS_RDATA_INIT;
3140	unsigned char data[4096];
3141	isc_buffer_t buffer;
3142	dns_keytable_t *sr = NULL;
3143	dst_key_t *dstkey = NULL;
3144
3145	/* Convert dnskey to DST key. */
3146	isc_buffer_init(&buffer, data, sizeof(data));
3147	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3148			     dns_rdatatype_dnskey, dnskey, &buffer);
3149
3150	result = dns_view_getsecroots(zone->view, &sr);
3151	if (result != ISC_R_SUCCESS)
3152		goto failure;
3153
3154	CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
3155	CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
3156	dns_keytable_detach(&sr);
3157
3158  failure:
3159	if (dstkey != NULL)
3160		dst_key_free(&dstkey);
3161	if (sr != NULL)
3162		dns_keytable_detach(&sr);
3163	return;
3164}
3165
3166/*
3167 * Add a null key to the security roots for so that all queries
3168 * to the zone will fail.
3169 */
3170static void
3171fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
3172	isc_result_t result;
3173	dns_keytable_t *sr = NULL;
3174
3175	result = dns_view_getsecroots(zone->view, &sr);
3176	if (result == ISC_R_SUCCESS) {
3177		dns_keytable_marksecure(sr, keyname);
3178		dns_keytable_detach(&sr);
3179	}
3180}
3181
3182/*
3183 * Scan a set of KEYDATA records from the key zone.  The ones that are
3184 * valid (i.e., the add holddown timer has expired) become trusted keys.
3185 */
3186static void
3187load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
3188	isc_result_t result;
3189	dns_rdata_t rdata = DNS_RDATA_INIT;
3190	dns_rdata_keydata_t keydata;
3191	dns_rdata_dnskey_t dnskey;
3192	isc_mem_t *mctx = zone->mctx;
3193	int trusted = 0, revoked = 0, pending = 0;
3194	isc_stdtime_t now;
3195	dns_keytable_t *sr = NULL;
3196
3197	isc_stdtime_get(&now);
3198
3199	result = dns_view_getsecroots(zone->view, &sr);
3200	if (result == ISC_R_SUCCESS) {
3201		dns_keytable_delete(sr, name);
3202		dns_keytable_detach(&sr);
3203	}
3204
3205	/* Now insert all the accepted trust anchors from this keydata set. */
3206	for (result = dns_rdataset_first(rdataset);
3207	     result == ISC_R_SUCCESS;
3208	     result = dns_rdataset_next(rdataset)) {
3209		dns_rdata_reset(&rdata);
3210		dns_rdataset_current(rdataset, &rdata);
3211
3212		/* Convert rdata to keydata. */
3213		dns_rdata_tostruct(&rdata, &keydata, NULL);
3214
3215		/* Set the key refresh timer. */
3216		set_refreshkeytimer(zone, &keydata, now);
3217
3218		/* If the removal timer is nonzero, this key was revoked. */
3219		if (keydata.removehd != 0) {
3220			revoked++;
3221			continue;
3222		}
3223
3224		/*
3225		 * If the add timer is still pending, this key is not
3226		 * trusted yet.
3227		 */
3228		if (now < keydata.addhd) {
3229			pending++;
3230			continue;
3231		}
3232
3233		/* Convert keydata to dnskey. */
3234		dns_keydata_todnskey(&keydata, &dnskey, NULL);
3235
3236		/* Add to keytables. */
3237		trusted++;
3238		trust_key(zone, name, &dnskey, mctx);
3239	}
3240
3241	if (trusted == 0 && pending != 0) {
3242		char namebuf[DNS_NAME_FORMATSIZE];
3243		dns_name_format(name, namebuf, sizeof namebuf);
3244		dns_zone_log(zone, ISC_LOG_ERROR,
3245			     "No valid trust anchors for '%s'!", namebuf);
3246		dns_zone_log(zone, ISC_LOG_ERROR,
3247			     "%d key(s) revoked, %d still pending",
3248			     revoked, pending);
3249		dns_zone_log(zone, ISC_LOG_ERROR,
3250			     "All queries to '%s' will fail", namebuf);
3251		fail_secure(zone, name);
3252	}
3253}
3254
3255static isc_result_t
3256do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3257	     dns_diff_t *diff)
3258{
3259	dns_diff_t temp_diff;
3260	isc_result_t result;
3261
3262	/*
3263	 * Create a singleton diff.
3264	 */
3265	dns_diff_init(diff->mctx, &temp_diff);
3266	temp_diff.resign = diff->resign;
3267	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3268
3269	/*
3270	 * Apply it to the database.
3271	 */
3272	result = dns_diff_apply(&temp_diff, db, ver);
3273	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3274	if (result != ISC_R_SUCCESS) {
3275		dns_difftuple_free(tuple);
3276		return (result);
3277	}
3278
3279	/*
3280	 * Merge it into the current pending journal entry.
3281	 */
3282	dns_diff_appendminimal(diff, tuple);
3283
3284	/*
3285	 * Do not clear temp_diff.
3286	 */
3287	return (ISC_R_SUCCESS);
3288}
3289
3290static isc_result_t
3291update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3292	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3293	      dns_rdata_t *rdata)
3294{
3295	dns_difftuple_t *tuple = NULL;
3296	isc_result_t result;
3297	result = dns_difftuple_create(diff->mctx, op,
3298				      name, ttl, rdata, &tuple);
3299	if (result != ISC_R_SUCCESS)
3300		return (result);
3301	return (do_one_tuple(&tuple, db, ver, diff));
3302}
3303
3304static isc_result_t
3305update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3306		  isc_mem_t *mctx, dns_updatemethod_t method) {
3307	dns_difftuple_t *deltuple = NULL;
3308	dns_difftuple_t *addtuple = NULL;
3309	isc_uint32_t serial;
3310	isc_result_t result;
3311
3312	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3313	CHECK(dns_difftuple_copy(deltuple, &addtuple));
3314	addtuple->op = DNS_DIFFOP_ADD;
3315
3316	serial = dns_soa_getserial(&addtuple->rdata);
3317	serial = dns_update_soaserial(serial, method);
3318	dns_soa_setserial(serial, &addtuple->rdata);
3319	CHECK(do_one_tuple(&deltuple, db, ver, diff));
3320	CHECK(do_one_tuple(&addtuple, db, ver, diff));
3321	result = ISC_R_SUCCESS;
3322
3323	failure:
3324	if (addtuple != NULL)
3325		dns_difftuple_free(&addtuple);
3326	if (deltuple != NULL)
3327		dns_difftuple_free(&deltuple);
3328	return (result);
3329}
3330
3331/*
3332 * Write all transactions in 'diff' to the zone journal file.
3333 */
3334static isc_result_t
3335zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial,
3336	     const char *caller)
3337{
3338	const char me[] = "zone_journal";
3339	const char *journalfile;
3340	isc_result_t result = ISC_R_SUCCESS;
3341	dns_journal_t *journal = NULL;
3342	unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
3343
3344	ENTER;
3345	journalfile = dns_zone_getjournal(zone);
3346	if (journalfile != NULL) {
3347		result = dns_journal_open(zone->mctx, journalfile, mode,
3348					  &journal);
3349		if (result != ISC_R_SUCCESS) {
3350			dns_zone_log(zone, ISC_LOG_ERROR,
3351				     "%s:dns_journal_open -> %s",
3352				     caller, dns_result_totext(result));
3353			return (result);
3354		}
3355
3356		if (sourceserial != NULL)
3357			dns_journal_set_sourceserial(journal, *sourceserial);
3358
3359		result = dns_journal_write_transaction(journal, diff);
3360		if (result != ISC_R_SUCCESS) {
3361			dns_zone_log(zone, ISC_LOG_ERROR,
3362				     "%s:dns_journal_write_transaction -> %s",
3363				     caller, dns_result_totext(result));
3364		}
3365		dns_journal_destroy(&journal);
3366	}
3367
3368	return (result);
3369}
3370
3371/*
3372 * Create an SOA record for a newly-created zone
3373 */
3374static isc_result_t
3375add_soa(dns_zone_t *zone, dns_db_t *db) {
3376	isc_result_t result;
3377	dns_rdata_t rdata = DNS_RDATA_INIT;
3378	unsigned char buf[DNS_SOA_BUFFERSIZE];
3379	dns_dbversion_t *ver = NULL;
3380	dns_diff_t diff;
3381
3382	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3383
3384	dns_diff_init(zone->mctx, &diff);
3385	result = dns_db_newversion(db, &ver);
3386	if (result != ISC_R_SUCCESS) {
3387		dns_zone_log(zone, ISC_LOG_ERROR,
3388			     "add_soa:dns_db_newversion -> %s",
3389			     dns_result_totext(result));
3390		goto failure;
3391	}
3392
3393	/* Build SOA record */
3394	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3395				    0, 0, 0, 0, 0, buf, &rdata);
3396	if (result != ISC_R_SUCCESS) {
3397		dns_zone_log(zone, ISC_LOG_ERROR,
3398			     "add_soa:dns_soa_buildrdata -> %s",
3399			     dns_result_totext(result));
3400		goto failure;
3401	}
3402
3403	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3404			       &zone->origin, 0, &rdata);
3405
3406failure:
3407	dns_diff_clear(&diff);
3408	if (ver != NULL)
3409		dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3410
3411	return (result);
3412}
3413
3414/*
3415 * Synchronize the set of initializing keys found in managed-keys {}
3416 * statements with the set of trust anchors found in the managed-keys.bind
3417 * zone.  If a domain is no longer named in managed-keys, delete all keys
3418 * from that domain from the key zone.	If a domain is mentioned in in
3419 * managed-keys but there are no references to it in the key zone, load
3420 * the key zone with the initializing key(s) for that domain.
3421 */
3422static isc_result_t
3423sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3424	isc_result_t result = ISC_R_SUCCESS;
3425	isc_boolean_t changed = ISC_FALSE;
3426	isc_boolean_t commit = ISC_FALSE;
3427	dns_rbtnodechain_t chain;
3428	dns_fixedname_t fn;
3429	dns_name_t foundname, *origin;
3430	dns_keynode_t *keynode = NULL;
3431	dns_view_t *view = zone->view;
3432	dns_keytable_t *sr = NULL;
3433	dns_dbversion_t *ver = NULL;
3434	dns_diff_t diff;
3435	dns_rriterator_t rrit;
3436
3437	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3438
3439	dns_name_init(&foundname, NULL);
3440	dns_fixedname_init(&fn);
3441	origin = dns_fixedname_name(&fn);
3442
3443	dns_diff_init(zone->mctx, &diff);
3444
3445	CHECK(dns_view_getsecroots(view, &sr));
3446
3447	result = dns_db_newversion(db, &ver);
3448	if (result != ISC_R_SUCCESS) {
3449		dns_zone_log(zone, ISC_LOG_ERROR,
3450			     "sync_keyzone:dns_db_newversion -> %s",
3451			     dns_result_totext(result));
3452		goto failure;
3453	}
3454
3455	/*
3456	 * Walk the zone DB.  If we find any keys whose names are no longer
3457	 * in managed-keys (or *are* in trusted-keys, meaning they are
3458	 * permanent and not RFC5011-maintained), delete them from the
3459	 * zone.  Otherwise call load_secroots(), which loads keys into
3460	 * secroots as appropriate.
3461	 */
3462	dns_rriterator_init(&rrit, db, ver, 0);
3463	for (result = dns_rriterator_first(&rrit);
3464	     result == ISC_R_SUCCESS;
3465	     result = dns_rriterator_nextrrset(&rrit)) {
3466		dns_rdataset_t *rdataset = NULL;
3467		dns_name_t *rrname = NULL;
3468		isc_uint32_t ttl;
3469
3470		dns_rriterator_current(&rrit, &rrname, &ttl,
3471				       &rdataset, NULL);
3472		if (!dns_rdataset_isassociated(rdataset)) {
3473			dns_rriterator_destroy(&rrit);
3474			goto failure;
3475		}
3476
3477		if (rdataset->type != dns_rdatatype_keydata)
3478			continue;
3479
3480		result = dns_keytable_find(sr, rrname, &keynode);
3481		if ((result != ISC_R_SUCCESS &&
3482		     result != DNS_R_PARTIALMATCH) ||
3483		    dns_keynode_managed(keynode) == ISC_FALSE) {
3484			CHECK(delete_keydata(db, ver, &diff,
3485					     rrname, rdataset));
3486			changed = ISC_TRUE;
3487		} else {
3488			load_secroots(zone, rrname, rdataset);
3489		}
3490
3491		if (keynode != NULL)
3492			dns_keytable_detachkeynode(sr, &keynode);
3493	}
3494	dns_rriterator_destroy(&rrit);
3495
3496	/*
3497	 * Now walk secroots to find any managed keys that aren't
3498	 * in the zone.  If we find any, we add them to the zone.
3499	 */
3500	RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3501	dns_rbtnodechain_init(&chain, zone->mctx);
3502	result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3503	if (result == ISC_R_NOTFOUND)
3504		result = ISC_R_NOMORE;
3505	while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3506		dns_rbtnode_t *rbtnode = NULL;
3507
3508		dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3509		if (rbtnode->data == NULL)
3510			goto skip;
3511
3512		dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3513		if (dns_keynode_managed(keynode)) {
3514			dns_fixedname_t fname;
3515			dns_name_t *keyname;
3516			dst_key_t *key;
3517
3518			key = dns_keynode_key(keynode);
3519			dns_fixedname_init(&fname);
3520
3521			if (key == NULL)   /* fail_secure() was called. */
3522				goto skip;
3523
3524			keyname = dst_key_name(key);
3525			result = dns_db_find(db, keyname, ver,
3526					     dns_rdatatype_keydata,
3527					     DNS_DBFIND_NOWILD, 0, NULL,
3528					     dns_fixedname_name(&fname),
3529					     NULL, NULL);
3530			if (result != ISC_R_SUCCESS)
3531				result = create_keydata(zone, db, ver, &diff,
3532							sr, &keynode, &changed);
3533			if (result != ISC_R_SUCCESS)
3534				break;
3535		}
3536  skip:
3537		result = dns_rbtnodechain_next(&chain, &foundname, origin);
3538		if (keynode != NULL)
3539			dns_keytable_detachkeynode(sr, &keynode);
3540	}
3541	RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3542
3543	if (result == ISC_R_NOMORE)
3544		result = ISC_R_SUCCESS;
3545
3546	if (changed) {
3547		/* Write changes to journal file. */
3548		CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
3549					zone->updatemethod));
3550		CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
3551
3552		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3553		zone_needdump(zone, 30);
3554		commit = ISC_TRUE;
3555	}
3556
3557 failure:
3558	if (keynode != NULL)
3559		dns_keytable_detachkeynode(sr, &keynode);
3560	if (sr != NULL)
3561		dns_keytable_detach(&sr);
3562	if (ver != NULL)
3563		dns_db_closeversion(db, &ver, commit);
3564	dns_diff_clear(&diff);
3565
3566	return (result);
3567}
3568
3569isc_result_t
3570dns_zone_synckeyzone(dns_zone_t *zone) {
3571	isc_result_t result;
3572	dns_db_t *db = NULL;
3573
3574	if (zone->type != dns_zone_key)
3575		return (DNS_R_BADZONE);
3576
3577	CHECK(dns_zone_getdb(zone, &db));
3578
3579	LOCK_ZONE(zone);
3580	result = sync_keyzone(zone, db);
3581	UNLOCK_ZONE(zone);
3582
3583 failure:
3584	if (db != NULL)
3585		dns_db_detach(&db);
3586	return (result);
3587}
3588
3589static void
3590maybe_send_secure(dns_zone_t *zone) {
3591	isc_result_t result;
3592
3593	/*
3594	 * We've finished loading, or else failed to load, an inline-signing
3595	 * 'secure' zone.  We now need information about the status of the
3596	 * 'raw' zone.  If we failed to load, then we need it to send a
3597	 * copy of its database; if we succeeded, we need it to send its
3598	 * serial number so that we can sync with it.  If it has not yet
3599	 * loaded, we set a flag so that it will send the necessary
3600	 * information when it has finished loading.
3601	 */
3602	if (zone->raw->db != NULL) {
3603		if (zone->db != NULL) {
3604			isc_uint32_t serial;
3605			result = zone_get_from_db(zone->raw, zone->raw->db,
3606						  NULL, NULL, &serial, NULL,
3607						  NULL, NULL, NULL, NULL);
3608			if (result == ISC_R_SUCCESS)
3609				zone_send_secureserial(zone->raw, ISC_TRUE, serial);
3610		} else
3611			zone_send_securedb(zone->raw, ISC_TRUE, zone->raw->db);
3612
3613	} else
3614		DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
3615}
3616
3617static isc_boolean_t
3618zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
3619	isc_result_t result;
3620	isc_boolean_t answer = ISC_FALSE;
3621	dns_diff_t diff;
3622
3623	dns_diff_init(mctx, &diff);
3624	result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
3625	if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
3626		answer = ISC_TRUE;
3627	dns_diff_clear(&diff);
3628	return (answer);
3629}
3630
3631/*
3632 * The zone is presumed to be locked.
3633 */
3634static isc_result_t
3635zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3636	      isc_result_t result)
3637{
3638	unsigned int soacount = 0;
3639	unsigned int nscount = 0;
3640	unsigned int errors = 0;
3641	isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3642	isc_time_t now;
3643	isc_boolean_t needdump = ISC_FALSE;
3644	isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3645	isc_boolean_t nomaster = ISC_FALSE;
3646	unsigned int options;
3647
3648	TIME_NOW(&now);
3649
3650	/*
3651	 * Initiate zone transfer?  We may need a error code that
3652	 * indicates that the "permanent" form does not exist.
3653	 * XXX better error feedback to log.
3654	 */
3655	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3656		if (zone->type == dns_zone_slave ||
3657		    zone->type == dns_zone_stub ||
3658		    (zone->type == dns_zone_redirect &&
3659		     zone->masters == NULL)) {
3660			if (result == ISC_R_FILENOTFOUND)
3661				dns_zone_log(zone, ISC_LOG_DEBUG(1),
3662					     "no master file");
3663			else if (result != DNS_R_NOMASTERFILE)
3664				dns_zone_log(zone, ISC_LOG_ERROR,
3665					     "loading from master file %s "
3666					     "failed: %s",
3667					     zone->masterfile,
3668					     dns_result_totext(result));
3669		} else if (zone->type == dns_zone_master &&
3670			   inline_secure(zone) && result == ISC_R_FILENOTFOUND)
3671		{
3672			dns_zone_log(zone, ISC_LOG_DEBUG(1),
3673				     "no master file, requesting db");
3674			maybe_send_secure(zone);
3675		} else {
3676			int level = ISC_LOG_ERROR;
3677			if (zone->type == dns_zone_key &&
3678			    result == ISC_R_FILENOTFOUND)
3679				level = ISC_LOG_DEBUG(1);
3680			dns_zone_log(zone, level,
3681				     "loading from master file %s failed: %s",
3682				     zone->masterfile,
3683				     dns_result_totext(result));
3684			nomaster = ISC_TRUE;
3685		}
3686
3687		if (zone->type != dns_zone_key)
3688			goto cleanup;
3689	}
3690
3691	dns_zone_log(zone, ISC_LOG_DEBUG(2),
3692		     "number of nodes in database: %u",
3693		     dns_db_nodecount(db));
3694
3695	if (result == DNS_R_SEENINCLUDE)
3696		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3697	else
3698		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3699
3700	/*
3701	 * If there's no master file for a key zone, then the zone is new:
3702	 * create an SOA record.  (We do this now, instead of later, so that
3703	 * if there happens to be a journal file, we can roll forward from
3704	 * a sane starting point.)
3705	 */
3706	if (nomaster && zone->type == dns_zone_key) {
3707		result = add_soa(zone, db);
3708		if (result != ISC_R_SUCCESS)
3709			goto cleanup;
3710	}
3711
3712	/*
3713	 * Apply update log, if any, on initial load.
3714	 */
3715	if (zone->journal != NULL &&
3716	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
3717	    ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3718	{
3719		if (zone->type == dns_zone_master &&
3720		    (zone->update_acl != NULL || zone->ssutable != NULL))
3721			options = DNS_JOURNALOPT_RESIGN;
3722		else
3723			options = 0;
3724		result = dns_journal_rollforward2(zone->mctx, db, options,
3725						  zone->sigresigninginterval,
3726						  zone->journal);
3727		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
3728		    result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
3729		    result != ISC_R_RANGE) {
3730			dns_zone_log(zone, ISC_LOG_ERROR,
3731				     "journal rollforward failed: %s",
3732				     dns_result_totext(result));
3733			goto cleanup;
3734
3735
3736		}
3737		if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
3738			dns_zone_log(zone, ISC_LOG_ERROR,
3739				     "journal rollforward failed: "
3740				     "journal out of sync with zone");
3741			goto cleanup;
3742		}
3743		dns_zone_log(zone, ISC_LOG_DEBUG(1),
3744			     "journal rollforward completed "
3745			     "successfully: %s",
3746			     dns_result_totext(result));
3747		if (result == ISC_R_SUCCESS)
3748			needdump = ISC_TRUE;
3749	}
3750
3751	/*
3752	 * Obtain ns, soa and cname counts for top of zone.
3753	 */
3754	INSIST(db != NULL);
3755	result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
3756				  &refresh, &retry, &expire, &minimum,
3757				  &errors);
3758	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
3759		dns_zone_log(zone, ISC_LOG_ERROR,
3760			     "could not find NS and/or SOA records");
3761	}
3762
3763	/*
3764	 * Check to make sure the journal is up to date, and remove the
3765	 * journal file if it isn't, as we wouldn't be able to apply
3766	 * updates otherwise.
3767	 */
3768	if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) &&
3769	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
3770		isc_uint32_t jserial;
3771		dns_journal_t *journal = NULL;
3772
3773		result = dns_journal_open(zone->mctx, zone->journal,
3774					  DNS_JOURNAL_READ, &journal);
3775		if (result == ISC_R_SUCCESS) {
3776			jserial = dns_journal_last_serial(journal);
3777			dns_journal_destroy(&journal);
3778		} else {
3779			jserial = serial;
3780			result = ISC_R_SUCCESS;
3781		}
3782
3783		if (jserial != serial) {
3784			dns_zone_log(zone, ISC_LOG_INFO,
3785				     "journal file is out of date: "
3786				     "removing journal file");
3787			if (remove(zone->journal) < 0 && errno != ENOENT) {
3788				char strbuf[ISC_STRERRORSIZE];
3789				isc__strerror(errno, strbuf, sizeof(strbuf));
3790				isc_log_write(dns_lctx,
3791					      DNS_LOGCATEGORY_GENERAL,
3792					      DNS_LOGMODULE_ZONE,
3793					      ISC_LOG_WARNING,
3794					      "unable to remove journal "
3795					      "'%s': '%s'",
3796					      zone->journal, strbuf);
3797			}
3798		}
3799	}
3800
3801	dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
3802
3803	/*
3804	 * Master / Slave / Stub zones require both NS and SOA records at
3805	 * the top of the zone.
3806	 */
3807
3808	switch (zone->type) {
3809	case dns_zone_dlz:
3810	case dns_zone_master:
3811	case dns_zone_slave:
3812	case dns_zone_stub:
3813	case dns_zone_redirect:
3814		if (soacount != 1) {
3815			dns_zone_log(zone, ISC_LOG_ERROR,
3816				     "has %d SOA records", soacount);
3817			result = DNS_R_BADZONE;
3818		}
3819		if (nscount == 0) {
3820			dns_zone_log(zone, ISC_LOG_ERROR,
3821				     "has no NS records");
3822			result = DNS_R_BADZONE;
3823		}
3824		if (result != ISC_R_SUCCESS)
3825			goto cleanup;
3826		if (zone->type == dns_zone_master && errors != 0) {
3827			result = DNS_R_BADZONE;
3828			goto cleanup;
3829		}
3830		if (zone->type != dns_zone_stub &&
3831		    zone->type != dns_zone_redirect) {
3832			result = check_nsec3param(zone, db);
3833			if (result != ISC_R_SUCCESS)
3834				goto cleanup;
3835		}
3836		if (zone->type == dns_zone_master &&
3837		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
3838		    !integrity_checks(zone, db)) {
3839			result = DNS_R_BADZONE;
3840			goto cleanup;
3841		}
3842		if (zone->type == dns_zone_master &&
3843		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
3844		    !zone_check_dup(zone, db)) {
3845			result = DNS_R_BADZONE;
3846			goto cleanup;
3847		}
3848
3849		if (zone->db != NULL) {
3850			/*
3851			 * This is checked in zone_replacedb() for slave zones
3852			 * as they don't reload from disk.
3853			 */
3854			result = zone_get_from_db(zone, zone->db, NULL, NULL,
3855						  &oldserial, NULL, NULL, NULL,
3856						  NULL, NULL);
3857			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3858			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
3859			    !isc_serial_gt(serial, oldserial)) {
3860				isc_uint32_t serialmin, serialmax;
3861
3862				INSIST(zone->type == dns_zone_master);
3863
3864				if (serial == oldserial &&
3865				    zone_unchanged(zone->db, db, zone->mctx)) {
3866					dns_zone_log(zone, ISC_LOG_INFO,
3867						     "ixfr-from-differences: "
3868						     "unchanged");
3869					return(ISC_R_SUCCESS);
3870				}
3871
3872				serialmin = (oldserial + 1) & 0xffffffffU;
3873				serialmax = (oldserial + 0x7fffffffU) &
3874					     0xffffffffU;
3875				dns_zone_log(zone, ISC_LOG_ERROR,
3876					     "ixfr-from-differences: "
3877					     "new serial (%u) out of range "
3878					     "[%u - %u]", serial, serialmin,
3879					     serialmax);
3880				result = DNS_R_BADZONE;
3881				goto cleanup;
3882			} else if (!isc_serial_ge(serial, oldserial))
3883				dns_zone_log(zone, ISC_LOG_ERROR,
3884					     "zone serial (%u/%u) has gone "
3885					     "backwards", serial, oldserial);
3886			else if (serial == oldserial && !hasinclude &&
3887				 strcmp(zone->db_argv[0], "_builtin") != 0)
3888				dns_zone_log(zone, ISC_LOG_ERROR,
3889					     "zone serial (%u) unchanged. "
3890					     "zone may fail to transfer "
3891					     "to slaves.", serial);
3892		}
3893
3894		if (zone->type == dns_zone_master &&
3895		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
3896		    zone->sigresigninginterval < (3 * refresh) &&
3897		    dns_db_issecure(db))
3898		{
3899			dns_zone_log(zone, ISC_LOG_WARNING,
3900				     "sig-re-signing-interval less than "
3901				     "3 * refresh.");
3902		}
3903
3904		zone->refresh = RANGE(refresh,
3905				      zone->minrefresh, zone->maxrefresh);
3906		zone->retry = RANGE(retry,
3907				    zone->minretry, zone->maxretry);
3908		zone->expire = RANGE(expire, zone->refresh + zone->retry,
3909				     DNS_MAX_EXPIRE);
3910		zone->minimum = minimum;
3911		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
3912
3913		if (zone->type == dns_zone_slave ||
3914		    zone->type == dns_zone_stub ||
3915		    (zone->type == dns_zone_redirect &&
3916		     zone->masters != NULL)) {
3917			isc_time_t t;
3918			isc_uint32_t delay;
3919
3920			result = isc_file_getmodtime(zone->journal, &t);
3921			if (result != ISC_R_SUCCESS)
3922				result = isc_file_getmodtime(zone->masterfile,
3923							     &t);
3924			if (result == ISC_R_SUCCESS)
3925				DNS_ZONE_TIME_ADD(&t, zone->expire,
3926						  &zone->expiretime);
3927			else
3928				DNS_ZONE_TIME_ADD(&now, zone->retry,
3929						  &zone->expiretime);
3930
3931			delay = isc_random_jitter(zone->retry,
3932						  (zone->retry * 3) / 4);
3933			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
3934			if (isc_time_compare(&zone->refreshtime,
3935					     &zone->expiretime) >= 0)
3936				zone->refreshtime = now;
3937		}
3938
3939		break;
3940
3941	case dns_zone_key:
3942		result = sync_keyzone(zone, db);
3943		if (result != ISC_R_SUCCESS)
3944			goto cleanup;
3945		break;
3946
3947	default:
3948		UNEXPECTED_ERROR(__FILE__, __LINE__,
3949				 "unexpected zone type %d", zone->type);
3950		result = ISC_R_UNEXPECTED;
3951		goto cleanup;
3952	}
3953
3954	/*
3955	 * Check for weak DNSKEY's.
3956	 */
3957	if (zone->type == dns_zone_master)
3958		zone_check_dnskeys(zone, db);
3959
3960	/*
3961	 * Schedule DNSSEC key refresh.
3962	 */
3963	if (zone->type == dns_zone_master &&
3964	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
3965		zone->refreshkeytime = now;
3966
3967#if 0
3968	/* destroy notification example. */
3969	{
3970		isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
3971						    DNS_EVENT_DBDESTROYED,
3972						    dns_zonemgr_dbdestroyed,
3973						    zone,
3974						    sizeof(isc_event_t));
3975		dns_db_ondestroy(db, zone->task, &e);
3976	}
3977#endif
3978
3979	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
3980	if (zone->db != NULL) {
3981		result = zone_replacedb(zone, db, ISC_FALSE);
3982		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3983		if (result != ISC_R_SUCCESS)
3984			goto cleanup;
3985	} else {
3986		zone_attachdb(zone, db);
3987		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3988		DNS_ZONE_SETFLAG(zone,
3989				 DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
3990		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
3991		    inline_raw(zone))
3992		{
3993			if (zone->secure->db == NULL)
3994				zone_send_securedb(zone, ISC_FALSE, db);
3995			else
3996				zone_send_secureserial(zone, ISC_FALSE, serial);
3997		}
3998	}
3999
4000	/*
4001	 * Finished loading inline-signing zone; need to get status
4002	 * from the raw side now.
4003	 */
4004	if (zone->type == dns_zone_master && inline_secure(zone))
4005		maybe_send_secure(zone);
4006
4007
4008	result = ISC_R_SUCCESS;
4009
4010	if (needdump) {
4011		if (zone->type == dns_zone_key)
4012			zone_needdump(zone, 30);
4013		else
4014			zone_needdump(zone, DNS_DUMP_DELAY);
4015	}
4016
4017	if (zone->task != NULL) {
4018		if (zone->type == dns_zone_master) {
4019			set_resigntime(zone);
4020			resume_signingwithkey(zone);
4021			resume_addnsec3chain(zone);
4022		}
4023
4024		if (zone->type == dns_zone_master &&
4025		    !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4026		    dns_zone_isdynamic(zone, ISC_FALSE) &&
4027		    dns_db_issecure(db)) {
4028			dns_name_t *name;
4029			dns_fixedname_t fixed;
4030			dns_rdataset_t next;
4031
4032			dns_rdataset_init(&next);
4033			dns_fixedname_init(&fixed);
4034			name = dns_fixedname_name(&fixed);
4035
4036			result = dns_db_getsigningtime(db, &next, name);
4037			if (result == ISC_R_SUCCESS) {
4038				isc_stdtime_t timenow;
4039				char namebuf[DNS_NAME_FORMATSIZE];
4040				char typebuf[DNS_RDATATYPE_FORMATSIZE];
4041
4042				isc_stdtime_get(&timenow);
4043				dns_name_format(name, namebuf, sizeof(namebuf));
4044				dns_rdatatype_format(next.covers,
4045						     typebuf, sizeof(typebuf));
4046				dns_zone_log(zone, ISC_LOG_DEBUG(3),
4047					     "next resign: %s/%s in %d seconds",
4048					     namebuf, typebuf,
4049					     next.resign - timenow);
4050				dns_rdataset_disassociate(&next);
4051			} else
4052				dns_zone_log(zone, ISC_LOG_WARNING,
4053					     "signed dynamic zone has no "
4054					     "resign event scheduled");
4055		}
4056
4057		zone_settimer(zone, &now);
4058	}
4059
4060	if (! dns_db_ispersistent(db))
4061		dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
4062			     dns_db_issecure(db) ? " (DNSSEC signed)" : "");
4063
4064	zone->loadtime = loadtime;
4065	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
4066	return (result);
4067
4068 cleanup:
4069	if (zone->type == dns_zone_slave ||
4070	    zone->type == dns_zone_stub ||
4071	    zone->type == dns_zone_key ||
4072	    (zone->type == dns_zone_redirect && zone->masters != NULL)) {
4073		if (zone->journal != NULL)
4074			zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
4075		if (zone->masterfile != NULL)
4076			zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
4077
4078		/* Mark the zone for immediate refresh. */
4079		zone->refreshtime = now;
4080		if (zone->task != NULL)
4081			zone_settimer(zone, &now);
4082		result = ISC_R_SUCCESS;
4083	} else if (zone->type == dns_zone_master ||
4084		   zone->type == dns_zone_redirect) {
4085		if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND))
4086			dns_zone_log(zone, ISC_LOG_ERROR,
4087				     "not loaded due to errors.");
4088	}
4089
4090	return (result);
4091}
4092
4093static isc_boolean_t
4094exit_check(dns_zone_t *zone) {
4095
4096	REQUIRE(LOCKED_ZONE(zone));
4097
4098	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
4099	    zone->irefs == 0)
4100	{
4101		/*
4102		 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
4103		 */
4104		INSIST(isc_refcount_current(&zone->erefs) == 0);
4105		return (ISC_TRUE);
4106	}
4107	return (ISC_FALSE);
4108}
4109
4110static isc_boolean_t
4111zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
4112	      dns_name_t *name, isc_boolean_t logit)
4113{
4114	isc_result_t result;
4115	char namebuf[DNS_NAME_FORMATSIZE];
4116	char altbuf[DNS_NAME_FORMATSIZE];
4117	dns_fixedname_t fixed;
4118	dns_name_t *foundname;
4119	int level;
4120
4121	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
4122		return (ISC_TRUE);
4123
4124	if (zone->type == dns_zone_master)
4125		level = ISC_LOG_ERROR;
4126	else
4127		level = ISC_LOG_WARNING;
4128
4129	dns_fixedname_init(&fixed);
4130	foundname = dns_fixedname_name(&fixed);
4131
4132	result = dns_db_find(db, name, version, dns_rdatatype_a,
4133			     0, 0, NULL, foundname, NULL, NULL);
4134	if (result == ISC_R_SUCCESS)
4135		return (ISC_TRUE);
4136
4137	if (result == DNS_R_NXRRSET) {
4138		result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
4139				     0, 0, NULL, foundname, NULL, NULL);
4140		if (result == ISC_R_SUCCESS)
4141			return (ISC_TRUE);
4142	}
4143
4144	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
4145	    result == DNS_R_EMPTYNAME) {
4146		if (logit) {
4147			dns_name_format(name, namebuf, sizeof namebuf);
4148			dns_zone_log(zone, level, "NS '%s' has no address "
4149				     "records (A or AAAA)", namebuf);
4150		}
4151		return (ISC_FALSE);
4152	}
4153
4154	if (result == DNS_R_CNAME) {
4155		if (logit) {
4156			dns_name_format(name, namebuf, sizeof namebuf);
4157			dns_zone_log(zone, level, "NS '%s' is a CNAME "
4158				     "(illegal)", namebuf);
4159		}
4160		return (ISC_FALSE);
4161	}
4162
4163	if (result == DNS_R_DNAME) {
4164		if (logit) {
4165			dns_name_format(name, namebuf, sizeof namebuf);
4166			dns_name_format(foundname, altbuf, sizeof altbuf);
4167			dns_zone_log(zone, level, "NS '%s' is below a DNAME "
4168				     "'%s' (illegal)", namebuf, altbuf);
4169		}
4170		return (ISC_FALSE);
4171	}
4172
4173	return (ISC_TRUE);
4174}
4175
4176static isc_result_t
4177zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
4178		 dns_dbversion_t *version, unsigned int *nscount,
4179		 unsigned int *errors, isc_boolean_t logit)
4180{
4181	isc_result_t result;
4182	unsigned int count = 0;
4183	unsigned int ecount = 0;
4184	dns_rdataset_t rdataset;
4185	dns_rdata_t rdata;
4186	dns_rdata_ns_t ns;
4187
4188	dns_rdataset_init(&rdataset);
4189	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
4190				     dns_rdatatype_none, 0, &rdataset, NULL);
4191	if (result == ISC_R_NOTFOUND) {
4192		INSIST(!dns_rdataset_isassociated(&rdataset));
4193		goto success;
4194	}
4195	if (result != ISC_R_SUCCESS) {
4196		INSIST(!dns_rdataset_isassociated(&rdataset));
4197		goto invalidate_rdataset;
4198	}
4199
4200	result = dns_rdataset_first(&rdataset);
4201	while (result == ISC_R_SUCCESS) {
4202		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
4203		    (zone->type == dns_zone_master ||
4204		     zone->type == dns_zone_slave)) {
4205			dns_rdata_init(&rdata);
4206			dns_rdataset_current(&rdataset, &rdata);
4207			result = dns_rdata_tostruct(&rdata, &ns, NULL);
4208			RUNTIME_CHECK(result == ISC_R_SUCCESS);
4209			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
4210			    !zone_check_ns(zone, db, version, &ns.name, logit))
4211				ecount++;
4212		}
4213		count++;
4214		result = dns_rdataset_next(&rdataset);
4215	}
4216	dns_rdataset_disassociate(&rdataset);
4217
4218 success:
4219	if (nscount != NULL)
4220		*nscount = count;
4221	if (errors != NULL)
4222		*errors = ecount;
4223
4224	result = ISC_R_SUCCESS;
4225
4226 invalidate_rdataset:
4227	dns_rdataset_invalidate(&rdataset);
4228
4229	return (result);
4230}
4231
4232static isc_result_t
4233zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
4234		 unsigned int *soacount,
4235		 isc_uint32_t *serial, isc_uint32_t *refresh,
4236		 isc_uint32_t *retry, isc_uint32_t *expire,
4237		 isc_uint32_t *minimum)
4238{
4239	isc_result_t result;
4240	unsigned int count;
4241	dns_rdataset_t rdataset;
4242	dns_rdata_t rdata = DNS_RDATA_INIT;
4243	dns_rdata_soa_t soa;
4244
4245	dns_rdataset_init(&rdataset);
4246	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
4247				     dns_rdatatype_none, 0, &rdataset, NULL);
4248	if (result == ISC_R_NOTFOUND) {
4249		INSIST(!dns_rdataset_isassociated(&rdataset));
4250		if (soacount != NULL)
4251			*soacount = 0;
4252		if (serial != NULL)
4253			*serial = 0;
4254		if (refresh != NULL)
4255			*refresh = 0;
4256		if (retry != NULL)
4257			*retry = 0;
4258		if (expire != NULL)
4259			*expire = 0;
4260		if (minimum != NULL)
4261			*minimum = 0;
4262		result = ISC_R_SUCCESS;
4263		goto invalidate_rdataset;
4264	}
4265	if (result != ISC_R_SUCCESS) {
4266		INSIST(!dns_rdataset_isassociated(&rdataset));
4267		goto invalidate_rdataset;
4268	}
4269
4270	count = 0;
4271	result = dns_rdataset_first(&rdataset);
4272	while (result == ISC_R_SUCCESS) {
4273		dns_rdata_init(&rdata);
4274		dns_rdataset_current(&rdataset, &rdata);
4275		count++;
4276		if (count == 1) {
4277			result = dns_rdata_tostruct(&rdata, &soa, NULL);
4278			RUNTIME_CHECK(result == ISC_R_SUCCESS);
4279		}
4280
4281		result = dns_rdataset_next(&rdataset);
4282		dns_rdata_reset(&rdata);
4283	}
4284	dns_rdataset_disassociate(&rdataset);
4285
4286	if (soacount != NULL)
4287		*soacount = count;
4288
4289	if (count > 0) {
4290		if (serial != NULL)
4291			*serial = soa.serial;
4292		if (refresh != NULL)
4293			*refresh = soa.refresh;
4294		if (retry != NULL)
4295			*retry = soa.retry;
4296		if (expire != NULL)
4297			*expire = soa.expire;
4298		if (minimum != NULL)
4299			*minimum = soa.minimum;
4300	}
4301
4302	result = ISC_R_SUCCESS;
4303
4304 invalidate_rdataset:
4305	dns_rdataset_invalidate(&rdataset);
4306
4307	return (result);
4308}
4309
4310/*
4311 * zone must be locked.
4312 */
4313static isc_result_t
4314zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
4315		 unsigned int *soacount, isc_uint32_t *serial,
4316		 isc_uint32_t *refresh, isc_uint32_t *retry,
4317		 isc_uint32_t *expire, isc_uint32_t *minimum,
4318		 unsigned int *errors)
4319{
4320	isc_result_t result;
4321	isc_result_t answer = ISC_R_SUCCESS;
4322	dns_dbversion_t *version = NULL;
4323	dns_dbnode_t *node;
4324
4325	REQUIRE(db != NULL);
4326	REQUIRE(zone != NULL);
4327
4328	dns_db_currentversion(db, &version);
4329
4330	node = NULL;
4331	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
4332	if (result != ISC_R_SUCCESS) {
4333		answer = result;
4334		goto closeversion;
4335	}
4336
4337	if (nscount != NULL || errors != NULL) {
4338		result = zone_count_ns_rr(zone, db, node, version,
4339					  nscount, errors, ISC_TRUE);
4340		if (result != ISC_R_SUCCESS)
4341			answer = result;
4342	}
4343
4344	if (soacount != NULL || serial != NULL || refresh != NULL
4345	    || retry != NULL || expire != NULL || minimum != NULL) {
4346		result = zone_load_soa_rr(db, node, version, soacount,
4347					  serial, refresh, retry, expire,
4348					  minimum);
4349		if (result != ISC_R_SUCCESS)
4350			answer = result;
4351	}
4352
4353	dns_db_detachnode(db, &node);
4354 closeversion:
4355	dns_db_closeversion(db, &version, ISC_FALSE);
4356
4357	return (answer);
4358}
4359
4360void
4361dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
4362	REQUIRE(DNS_ZONE_VALID(source));
4363	REQUIRE(target != NULL && *target == NULL);
4364	isc_refcount_increment(&source->erefs, NULL);
4365	*target = source;
4366}
4367
4368void
4369dns_zone_detach(dns_zone_t **zonep) {
4370	dns_zone_t *zone;
4371	dns_zone_t *raw = NULL;
4372	dns_zone_t *secure = NULL;
4373	unsigned int refs;
4374	isc_boolean_t free_now = ISC_FALSE;
4375
4376	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4377
4378	zone = *zonep;
4379
4380	isc_refcount_decrement(&zone->erefs, &refs);
4381
4382	if (refs == 0) {
4383		LOCK_ZONE(zone);
4384		/*
4385		 * We just detached the last external reference.
4386		 */
4387		if (zone->task != NULL) {
4388			/*
4389			 * This zone is being managed.	Post
4390			 * its control event and let it clean
4391			 * up synchronously in the context of
4392			 * its task.
4393			 */
4394			isc_event_t *ev = &zone->ctlevent;
4395			isc_task_send(zone->task, &ev);
4396		} else {
4397			/*
4398			 * This zone is not being managed; it has
4399			 * no task and can have no outstanding
4400			 * events.  Free it immediately.
4401			 */
4402			/*
4403			 * Unmanaged zones should not have non-null views;
4404			 * we have no way of detaching from the view here
4405			 * without causing deadlock because this code is called
4406			 * with the view already locked.
4407			 */
4408			INSIST(zone->view == NULL);
4409			free_now = ISC_TRUE;
4410			raw = zone->raw;
4411			zone->raw = NULL;
4412			secure = zone->secure;
4413			zone->secure = NULL;
4414		}
4415		UNLOCK_ZONE(zone);
4416	}
4417	*zonep = NULL;
4418	if (free_now) {
4419		if (raw != NULL)
4420			dns_zone_detach(&raw);
4421		if (secure != NULL)
4422			dns_zone_idetach(&secure);
4423		zone_free(zone);
4424	}
4425}
4426
4427void
4428dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4429	REQUIRE(DNS_ZONE_VALID(source));
4430	REQUIRE(target != NULL && *target == NULL);
4431	LOCK_ZONE(source);
4432	zone_iattach(source, target);
4433	UNLOCK_ZONE(source);
4434}
4435
4436static void
4437zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4438
4439	/*
4440	 * 'source' locked by caller.
4441	 */
4442	REQUIRE(LOCKED_ZONE(source));
4443	REQUIRE(DNS_ZONE_VALID(source));
4444	REQUIRE(target != NULL && *target == NULL);
4445	INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
4446	source->irefs++;
4447	INSIST(source->irefs != 0);
4448	*target = source;
4449}
4450
4451static void
4452zone_idetach(dns_zone_t **zonep) {
4453	dns_zone_t *zone;
4454
4455	/*
4456	 * 'zone' locked by caller.
4457	 */
4458	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4459	zone = *zonep;
4460	REQUIRE(LOCKED_ZONE(*zonep));
4461	*zonep = NULL;
4462
4463	INSIST(zone->irefs > 0);
4464	zone->irefs--;
4465	INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4466}
4467
4468void
4469dns_zone_idetach(dns_zone_t **zonep) {
4470	dns_zone_t *zone;
4471	isc_boolean_t free_needed;
4472
4473	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4474	zone = *zonep;
4475	*zonep = NULL;
4476
4477	LOCK_ZONE(zone);
4478	INSIST(zone->irefs > 0);
4479	zone->irefs--;
4480	free_needed = exit_check(zone);
4481	UNLOCK_ZONE(zone);
4482	if (free_needed)
4483		zone_free(zone);
4484}
4485
4486isc_mem_t *
4487dns_zone_getmctx(dns_zone_t *zone) {
4488	REQUIRE(DNS_ZONE_VALID(zone));
4489
4490	return (zone->mctx);
4491}
4492
4493dns_zonemgr_t *
4494dns_zone_getmgr(dns_zone_t *zone) {
4495	REQUIRE(DNS_ZONE_VALID(zone));
4496
4497	return (zone->zmgr);
4498}
4499
4500void
4501dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4502	REQUIRE(DNS_ZONE_VALID(zone));
4503
4504	LOCK_ZONE(zone);
4505	if (value)
4506		DNS_ZONE_SETFLAG(zone, flags);
4507	else
4508		DNS_ZONE_CLRFLAG(zone, flags);
4509	UNLOCK_ZONE(zone);
4510}
4511
4512void
4513dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4514{
4515	REQUIRE(DNS_ZONE_VALID(zone));
4516
4517	LOCK_ZONE(zone);
4518	if (value)
4519		zone->options |= option;
4520	else
4521		zone->options &= ~option;
4522	UNLOCK_ZONE(zone);
4523}
4524
4525unsigned int
4526dns_zone_getoptions(dns_zone_t *zone) {
4527
4528	REQUIRE(DNS_ZONE_VALID(zone));
4529
4530	return (zone->options);
4531}
4532
4533void
4534dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4535{
4536	REQUIRE(DNS_ZONE_VALID(zone));
4537
4538	LOCK_ZONE(zone);
4539	if (value)
4540		zone->keyopts |= keyopt;
4541	else
4542		zone->keyopts &= ~keyopt;
4543	UNLOCK_ZONE(zone);
4544}
4545
4546unsigned int
4547dns_zone_getkeyopts(dns_zone_t *zone) {
4548
4549	REQUIRE(DNS_ZONE_VALID(zone));
4550
4551	return (zone->keyopts);
4552}
4553
4554isc_result_t
4555dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4556	REQUIRE(DNS_ZONE_VALID(zone));
4557
4558	LOCK_ZONE(zone);
4559	zone->xfrsource4 = *xfrsource;
4560	UNLOCK_ZONE(zone);
4561
4562	return (ISC_R_SUCCESS);
4563}
4564
4565isc_sockaddr_t *
4566dns_zone_getxfrsource4(dns_zone_t *zone) {
4567	REQUIRE(DNS_ZONE_VALID(zone));
4568	return (&zone->xfrsource4);
4569}
4570
4571isc_result_t
4572dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4573	REQUIRE(DNS_ZONE_VALID(zone));
4574
4575	LOCK_ZONE(zone);
4576	zone->xfrsource6 = *xfrsource;
4577	UNLOCK_ZONE(zone);
4578
4579	return (ISC_R_SUCCESS);
4580}
4581
4582isc_sockaddr_t *
4583dns_zone_getxfrsource6(dns_zone_t *zone) {
4584	REQUIRE(DNS_ZONE_VALID(zone));
4585	return (&zone->xfrsource6);
4586}
4587
4588isc_result_t
4589dns_zone_setaltxfrsource4(dns_zone_t *zone,
4590			  const isc_sockaddr_t *altxfrsource)
4591{
4592	REQUIRE(DNS_ZONE_VALID(zone));
4593
4594	LOCK_ZONE(zone);
4595	zone->altxfrsource4 = *altxfrsource;
4596	UNLOCK_ZONE(zone);
4597
4598	return (ISC_R_SUCCESS);
4599}
4600
4601isc_sockaddr_t *
4602dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4603	REQUIRE(DNS_ZONE_VALID(zone));
4604	return (&zone->altxfrsource4);
4605}
4606
4607isc_result_t
4608dns_zone_setaltxfrsource6(dns_zone_t *zone,
4609			  const isc_sockaddr_t *altxfrsource)
4610{
4611	REQUIRE(DNS_ZONE_VALID(zone));
4612
4613	LOCK_ZONE(zone);
4614	zone->altxfrsource6 = *altxfrsource;
4615	UNLOCK_ZONE(zone);
4616
4617	return (ISC_R_SUCCESS);
4618}
4619
4620isc_sockaddr_t *
4621dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4622	REQUIRE(DNS_ZONE_VALID(zone));
4623	return (&zone->altxfrsource6);
4624}
4625
4626isc_result_t
4627dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4628	REQUIRE(DNS_ZONE_VALID(zone));
4629
4630	LOCK_ZONE(zone);
4631	zone->notifysrc4 = *notifysrc;
4632	UNLOCK_ZONE(zone);
4633
4634	return (ISC_R_SUCCESS);
4635}
4636
4637isc_sockaddr_t *
4638dns_zone_getnotifysrc4(dns_zone_t *zone) {
4639	REQUIRE(DNS_ZONE_VALID(zone));
4640	return (&zone->notifysrc4);
4641}
4642
4643isc_result_t
4644dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4645	REQUIRE(DNS_ZONE_VALID(zone));
4646
4647	LOCK_ZONE(zone);
4648	zone->notifysrc6 = *notifysrc;
4649	UNLOCK_ZONE(zone);
4650
4651	return (ISC_R_SUCCESS);
4652}
4653
4654isc_sockaddr_t *
4655dns_zone_getnotifysrc6(dns_zone_t *zone) {
4656	REQUIRE(DNS_ZONE_VALID(zone));
4657	return (&zone->notifysrc6);
4658}
4659
4660static isc_boolean_t
4661same_addrs(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4662	     isc_uint32_t count)
4663{
4664	unsigned int i;
4665
4666	for (i = 0; i < count; i++)
4667		if (!isc_sockaddr_equal(&old[i], &new[i]))
4668			return (ISC_FALSE);
4669	return (ISC_TRUE);
4670}
4671
4672static isc_boolean_t
4673same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
4674	unsigned int i;
4675
4676	if (old == NULL && new == NULL)
4677		return (ISC_TRUE);
4678	if (old == NULL || new == NULL)
4679		return (ISC_FALSE);
4680
4681	for (i = 0; i < count; i++) {
4682		if (old[i] == NULL && new[i] == NULL)
4683			continue;
4684		if (old[i] == NULL || new[i] == NULL ||
4685		     !dns_name_equal(old[i], new[i]))
4686			return (ISC_FALSE);
4687	}
4688	return (ISC_TRUE);
4689}
4690
4691static void
4692clear_addresskeylist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
4693		     unsigned int *countp, isc_mem_t *mctx)
4694{
4695	unsigned int count;
4696	isc_sockaddr_t *addrs;
4697	dns_name_t **keynames;
4698
4699	REQUIRE(countp != NULL && addrsp != NULL && keynamesp != NULL);
4700
4701	count = *countp;
4702	*countp = 0;
4703	addrs = *addrsp;
4704	*addrsp = NULL;
4705	keynames = *keynamesp;
4706	*keynamesp = NULL;
4707
4708	if (addrs != NULL)
4709		isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
4710
4711	if (keynames != NULL) {
4712		unsigned int i;
4713		for (i = 0; i < count; i++) {
4714			if (keynames[i] != NULL) {
4715				dns_name_free(keynames[i], mctx);
4716				isc_mem_put(mctx, keynames[i],
4717					    sizeof(dns_name_t));
4718				keynames[i] = NULL;
4719			}
4720		}
4721		isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
4722	}
4723}
4724
4725static isc_result_t
4726set_addrkeylist(unsigned int count,
4727		const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
4728		dns_name_t **names, dns_name_t ***newnamesp,
4729		isc_mem_t *mctx)
4730{
4731	isc_result_t result;
4732	isc_sockaddr_t *newaddrs = NULL;
4733	dns_name_t **newnames = NULL;
4734	unsigned int i;
4735
4736	REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
4737	REQUIRE(newnamesp != NULL && *newnamesp == NULL);
4738
4739	newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
4740	if (newaddrs == NULL)
4741		return (ISC_R_NOMEMORY);
4742	memcpy(newaddrs, addrs, count * sizeof(*newaddrs));
4743
4744	newnames = NULL;
4745	if (names != NULL) {
4746		newnames = isc_mem_get(mctx, count * sizeof(*newnames));
4747		if (newnames == NULL) {
4748			isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
4749			return (ISC_R_NOMEMORY);
4750		}
4751		for (i = 0; i < count; i++)
4752			newnames[i] = NULL;
4753		for (i = 0; i < count; i++) {
4754			if (names[i] != NULL) {
4755				newnames[i] = isc_mem_get(mctx,
4756							 sizeof(dns_name_t));
4757				if (newnames[i] == NULL)
4758					goto allocfail;
4759				dns_name_init(newnames[i], NULL);
4760				result = dns_name_dup(names[i], mctx,
4761						      newnames[i]);
4762				if (result != ISC_R_SUCCESS) {
4763				allocfail:
4764					for (i = 0; i < count; i++)
4765						if (newnames[i] != NULL)
4766							dns_name_free(
4767							       newnames[i],
4768							       mctx);
4769					isc_mem_put(mctx, newaddrs,
4770						    count * sizeof(*newaddrs));
4771					isc_mem_put(mctx, newnames,
4772						    count * sizeof(*newnames));
4773					return (ISC_R_NOMEMORY);
4774				}
4775			}
4776		}
4777	}
4778
4779	*newaddrsp = newaddrs;
4780	*newnamesp = newnames;
4781	return (ISC_R_SUCCESS);
4782}
4783
4784isc_result_t
4785dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
4786		       isc_uint32_t count)
4787{
4788	return (dns_zone_setalsonotifywithkeys(zone, notify, NULL, count));
4789}
4790
4791isc_result_t
4792dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
4793			       dns_name_t **keynames, isc_uint32_t count)
4794{
4795	isc_result_t result;
4796	isc_sockaddr_t *newaddrs = NULL;
4797	dns_name_t **newnames = NULL;
4798
4799	REQUIRE(DNS_ZONE_VALID(zone));
4800	REQUIRE(count == 0 || notify != NULL);
4801	if (keynames != NULL)
4802		REQUIRE(count != 0);
4803
4804	LOCK_ZONE(zone);
4805
4806	if (count == zone->notifycnt &&
4807	    same_addrs(zone->notify, notify, count) &&
4808	    same_keynames(zone->notifykeynames, keynames, count))
4809		goto unlock;
4810
4811	clear_addresskeylist(&zone->notify, &zone->notifykeynames,
4812			     &zone->notifycnt, zone->mctx);
4813
4814	if (count == 0)
4815		goto unlock;
4816
4817	/*
4818	 * Set up the notify and notifykey lists
4819	 */
4820	result = set_addrkeylist(count, notify, &newaddrs,
4821				 keynames, &newnames, zone->mctx);
4822	if (result != ISC_R_SUCCESS)
4823		goto unlock;
4824
4825	/*
4826	 * Everything is ok so attach to the zone.
4827	 */
4828	zone->notify = newaddrs;
4829	zone->notifykeynames = newnames;
4830	zone->notifycnt = count;
4831 unlock:
4832	UNLOCK_ZONE(zone);
4833	return (ISC_R_SUCCESS);
4834}
4835
4836isc_result_t
4837dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
4838		    isc_uint32_t count)
4839{
4840	isc_result_t result;
4841
4842	result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
4843	return (result);
4844}
4845
4846isc_result_t
4847dns_zone_setmasterswithkeys(dns_zone_t *zone,
4848			    const isc_sockaddr_t *masters,
4849			    dns_name_t **keynames,
4850			    isc_uint32_t count)
4851{
4852	isc_result_t result = ISC_R_SUCCESS;
4853	isc_sockaddr_t *newaddrs = NULL;
4854	dns_name_t **newnames = NULL;
4855	isc_boolean_t *newok;
4856	unsigned int i;
4857
4858	REQUIRE(DNS_ZONE_VALID(zone));
4859	REQUIRE(count == 0 || masters != NULL);
4860	if (keynames != NULL) {
4861		REQUIRE(count != 0);
4862	}
4863
4864	LOCK_ZONE(zone);
4865	/*
4866	 * The refresh code assumes that 'masters' wouldn't change under it.
4867	 * If it will change then kill off any current refresh in progress
4868	 * and update the masters info.  If it won't change then we can just
4869	 * unlock and exit.
4870	 */
4871	if (count != zone->masterscnt ||
4872	    !same_addrs(zone->masters, masters, count) ||
4873	    !same_keynames(zone->masterkeynames, keynames, count)) {
4874		if (zone->request != NULL)
4875			dns_request_cancel(zone->request);
4876	} else
4877		goto unlock;
4878
4879	/*
4880	 * This needs to happen before clear_addresskeylist() sets
4881	 * zone->masterscnt to 0:
4882	 */
4883	if (zone->mastersok != NULL) {
4884		isc_mem_put(zone->mctx, zone->mastersok,
4885			    zone->masterscnt * sizeof(isc_boolean_t));
4886		zone->mastersok = NULL;
4887	}
4888	clear_addresskeylist(&zone->masters, &zone->masterkeynames,
4889			     &zone->masterscnt, zone->mctx);
4890	/*
4891	 * If count == 0, don't allocate any space for masters, mastersok or
4892	 * keynames so internally, those pointers are NULL if count == 0
4893	 */
4894	if (count == 0)
4895		goto unlock;
4896
4897	/*
4898	 * mastersok must contain count elements
4899	 */
4900	newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
4901	if (newok == NULL) {
4902		result = ISC_R_NOMEMORY;
4903		isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
4904		goto unlock;
4905	};
4906	for (i = 0; i < count; i++)
4907		newok[i] = ISC_FALSE;
4908
4909	/*
4910	 * Now set up the masters and masterkey lists
4911	 */
4912	result = set_addrkeylist(count, masters, &newaddrs,
4913				 keynames, &newnames, zone->mctx);
4914	if (result != ISC_R_SUCCESS) {
4915		isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
4916		goto unlock;
4917	}
4918
4919	/*
4920	 * Everything is ok so attach to the zone.
4921	 */
4922	zone->curmaster = 0;
4923	zone->mastersok = newok;
4924	zone->masters = newaddrs;
4925	zone->masterkeynames = newnames;
4926	zone->masterscnt = count;
4927	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
4928
4929 unlock:
4930	UNLOCK_ZONE(zone);
4931	return (result);
4932}
4933
4934isc_result_t
4935dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
4936	isc_result_t result = ISC_R_SUCCESS;
4937
4938	REQUIRE(DNS_ZONE_VALID(zone));
4939
4940	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4941	if (zone->db == NULL)
4942		result = DNS_R_NOTLOADED;
4943	else
4944		dns_db_attach(zone->db, dpb);
4945	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4946
4947	return (result);
4948}
4949
4950void
4951dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
4952	REQUIRE(DNS_ZONE_VALID(zone));
4953	REQUIRE(zone->type == dns_zone_staticstub);
4954
4955	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4956	REQUIRE(zone->db == NULL);
4957	dns_db_attach(db, &zone->db);
4958	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4959}
4960
4961/*
4962 * Co-ordinates the starting of routine jobs.
4963 */
4964
4965void
4966dns_zone_maintenance(dns_zone_t *zone) {
4967	const char me[] = "dns_zone_maintenance";
4968	isc_time_t now;
4969
4970	REQUIRE(DNS_ZONE_VALID(zone));
4971	ENTER;
4972
4973	LOCK_ZONE(zone);
4974	TIME_NOW(&now);
4975	zone_settimer(zone, &now);
4976	UNLOCK_ZONE(zone);
4977}
4978
4979static inline isc_boolean_t
4980was_dumping(dns_zone_t *zone) {
4981	isc_boolean_t dumping;
4982
4983	REQUIRE(LOCKED_ZONE(zone));
4984
4985	dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
4986	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
4987	if (!dumping) {
4988		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
4989		isc_time_settoepoch(&zone->dumptime);
4990	}
4991	return (dumping);
4992}
4993
4994static isc_result_t
4995find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4996	       isc_mem_t *mctx, unsigned int maxkeys,
4997	       dst_key_t **keys, unsigned int *nkeys)
4998{
4999	isc_result_t result;
5000	dns_dbnode_t *node = NULL;
5001	const char *directory = dns_zone_getkeydirectory(zone);
5002
5003	CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
5004	result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
5005					  directory, mctx, maxkeys, keys,
5006					  nkeys);
5007	if (result == ISC_R_NOTFOUND)
5008		result = ISC_R_SUCCESS;
5009 failure:
5010	if (node != NULL)
5011		dns_db_detachnode(db, &node);
5012	return (result);
5013}
5014
5015static isc_result_t
5016offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name,
5017	dns_ttl_t ttl, dns_rdata_t *rdata)
5018{
5019	isc_result_t result;
5020
5021	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
5022		return (ISC_R_SUCCESS);
5023	result = update_one_rr(db, ver, diff, DNS_DIFFOP_DELRESIGN,
5024			       name, ttl, rdata);
5025	if (result != ISC_R_SUCCESS)
5026		return (result);
5027	rdata->flags |= DNS_RDATA_OFFLINE;
5028	result = update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
5029			       name, ttl, rdata);
5030	return (result);
5031}
5032
5033static void
5034set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
5035{
5036	unsigned int delta;
5037	char timebuf[80];
5038
5039	zone->key_expiry = when;
5040	if (when <= now) {
5041		dns_zone_log(zone, ISC_LOG_ERROR,
5042			     "DNSKEY RRSIG(s) have expired");
5043		isc_time_settoepoch(&zone->keywarntime);
5044	} else if (when < now + 7 * 24 * 3600) {
5045		isc_time_t t;
5046		isc_time_set(&t, when, 0);
5047		isc_time_formattimestamp(&t, timebuf, 80);
5048		dns_zone_log(zone, ISC_LOG_WARNING,
5049			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
5050			     timebuf);
5051		delta = when - now;
5052		delta--;		/* loop prevention */
5053		delta /= 24 * 3600;	/* to whole days */
5054		delta *= 24 * 3600;	/* to seconds */
5055		isc_time_set(&zone->keywarntime, when - delta, 0);
5056	}  else {
5057		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
5058		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
5059		dns_zone_log(zone, ISC_LOG_NOTICE,
5060			     "setting keywarntime to %s", timebuf);
5061	}
5062}
5063
5064/*
5065 * Helper function to del_sigs(). We don't want to delete RRSIGs that
5066 * have no new key.
5067 */
5068static isc_boolean_t
5069delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys) {
5070	unsigned int i = 0;
5071
5072	/*
5073	 * It's okay to delete a signature if there is an active ZSK
5074	 * with the same algorithm
5075	 */
5076	for (i = 0; i < nkeys; i++) {
5077		if (rrsig_ptr->algorithm == dst_key_alg(keys[i]) &&
5078		    (dst_key_isprivate(keys[i])) && !KSK(keys[i]))
5079			return (ISC_TRUE);
5080	}
5081
5082	/*
5083	 * Failing that, it is *not* okay to delete a signature
5084	 * if the associated public key is still in the DNSKEY RRset
5085	 */
5086	for (i = 0; i < nkeys; i++) {
5087		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
5088		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
5089			return (ISC_FALSE);
5090	}
5091
5092	/*
5093	 * But if the key is gone, then go ahead.
5094	 */
5095	return (ISC_TRUE);
5096}
5097
5098/*
5099 * Delete expired RRsigs and any RRsigs we are about to re-sign.
5100 * See also update.c:del_keysigs().
5101 */
5102static isc_result_t
5103del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5104	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
5105	 unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
5106{
5107	isc_result_t result;
5108	dns_dbnode_t *node = NULL;
5109	dns_rdataset_t rdataset;
5110	unsigned int i;
5111	dns_rdata_rrsig_t rrsig;
5112	isc_boolean_t found, changed;
5113	isc_int64_t warn = 0, maybe = 0;
5114
5115	dns_rdataset_init(&rdataset);
5116
5117	if (type == dns_rdatatype_nsec3)
5118		result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5119	else
5120		result = dns_db_findnode(db, name, ISC_FALSE, &node);
5121	if (result == ISC_R_NOTFOUND)
5122		return (ISC_R_SUCCESS);
5123	if (result != ISC_R_SUCCESS)
5124		goto failure;
5125	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
5126				     (isc_stdtime_t) 0, &rdataset, NULL);
5127	dns_db_detachnode(db, &node);
5128
5129	if (result == ISC_R_NOTFOUND) {
5130		INSIST(!dns_rdataset_isassociated(&rdataset));
5131		return (ISC_R_SUCCESS);
5132	}
5133	if (result != ISC_R_SUCCESS) {
5134		INSIST(!dns_rdataset_isassociated(&rdataset));
5135		goto failure;
5136	}
5137
5138	changed = ISC_FALSE;
5139	for (result = dns_rdataset_first(&rdataset);
5140	     result == ISC_R_SUCCESS;
5141	     result = dns_rdataset_next(&rdataset)) {
5142		dns_rdata_t rdata = DNS_RDATA_INIT;
5143
5144		dns_rdataset_current(&rdataset, &rdata);
5145		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5146		RUNTIME_CHECK(result == ISC_R_SUCCESS);
5147
5148		if (type != dns_rdatatype_dnskey) {
5149			if (delsig_ok(&rrsig, keys, nkeys)) {
5150				result = update_one_rr(db, ver, diff,
5151					       DNS_DIFFOP_DELRESIGN, name,
5152					       rdataset.ttl, &rdata);
5153				if (incremental)
5154					changed = ISC_TRUE;
5155				if (result != ISC_R_SUCCESS)
5156					break;
5157			} else {
5158				/*
5159				 * At this point, we've got an RRSIG,
5160				 * which is signed by an inactive key.
5161				 * An administrator needs to provide a new
5162				 * key/alg, but until that time, we want to
5163				 * keep the old RRSIG.  Marking the key as
5164				 * offline will prevent us spinning waiting
5165				 * for the private part.
5166				 */
5167				if (incremental) {
5168					result = offline(db, ver, diff, name,
5169							 rdataset.ttl, &rdata);
5170					changed = ISC_TRUE;
5171					if (result != ISC_R_SUCCESS)
5172						break;
5173				}
5174
5175				/*
5176				 * Log the key id and algorithm of
5177				 * the inactive key with no replacement
5178				 */
5179				if (zone->log_key_expired_timer <= now) {
5180					char origin[DNS_NAME_FORMATSIZE];
5181					char algbuf[DNS_NAME_FORMATSIZE];
5182					dns_name_format(&zone->origin, origin,
5183							sizeof(origin));
5184					dns_secalg_format(rrsig.algorithm,
5185							  algbuf,
5186							  sizeof(algbuf));
5187					dns_zone_log(zone, ISC_LOG_WARNING,
5188						     "Key %s/%s/%d "
5189						     "missing or inactive "
5190						     "and has no replacement: "
5191						     "retaining signatures.",
5192						     origin, algbuf,
5193						     rrsig.keyid);
5194					zone->log_key_expired_timer = now +
5195									3600;
5196				}
5197			}
5198			continue;
5199		}
5200
5201		/*
5202		 * RRSIG(DNSKEY) requires special processing.
5203		 */
5204		found = ISC_FALSE;
5205		for (i = 0; i < nkeys; i++) {
5206			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
5207			    rrsig.keyid == dst_key_id(keys[i])) {
5208				found = ISC_TRUE;
5209				/*
5210				 * Mark offline RRSIG(DNSKEY).
5211				 * We want the earliest offline expire time
5212				 * iff there is a new offline signature.
5213				 */
5214				if (!dst_key_isprivate(keys[i])) {
5215					isc_int64_t timeexpire =
5216					   dns_time64_from32(rrsig.timeexpire);
5217					if (warn != 0 && warn > timeexpire)
5218						warn = timeexpire;
5219					if (rdata.flags & DNS_RDATA_OFFLINE) {
5220						if (maybe == 0 ||
5221						    maybe > timeexpire)
5222							maybe = timeexpire;
5223						break;
5224					}
5225					if (warn == 0)
5226						warn = maybe;
5227					if (warn == 0 || warn > timeexpire)
5228						warn = timeexpire;
5229					result = offline(db, ver, diff, name,
5230							 rdataset.ttl, &rdata);
5231					break;
5232				}
5233				result = update_one_rr(db, ver, diff,
5234						       DNS_DIFFOP_DELRESIGN,
5235						       name, rdataset.ttl,
5236						       &rdata);
5237				break;
5238			}
5239		}
5240
5241		/*
5242		 * If there is not a matching DNSKEY then
5243		 * delete the RRSIG.
5244		 */
5245		if (!found)
5246			result = update_one_rr(db, ver, diff,
5247					       DNS_DIFFOP_DELRESIGN, name,
5248					       rdataset.ttl, &rdata);
5249		if (result != ISC_R_SUCCESS)
5250			break;
5251	}
5252
5253	if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0)
5254		dns_db_resigned(db, &rdataset, ver);
5255
5256	dns_rdataset_disassociate(&rdataset);
5257	if (result == ISC_R_NOMORE)
5258		result = ISC_R_SUCCESS;
5259	if (warn > 0) {
5260#if defined(STDTIME_ON_32BITS)
5261		isc_stdtime_t stdwarn = (isc_stdtime_t)warn;
5262		if (warn == stdwarn)
5263#endif
5264			set_key_expiry_warning(zone, (isc_stdtime_t)warn, now);
5265#if defined(STDTIME_ON_32BITS)
5266		else
5267			dns_zone_log(zone, ISC_LOG_ERROR,
5268				     "key expiry warning time out of range");
5269#endif
5270	}
5271 failure:
5272	if (node != NULL)
5273		dns_db_detachnode(db, &node);
5274	return (result);
5275}
5276
5277static isc_result_t
5278add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5279	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
5280	 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
5281	 isc_stdtime_t expire, isc_boolean_t check_ksk,
5282	 isc_boolean_t keyset_kskonly)
5283{
5284	isc_result_t result;
5285	dns_dbnode_t *node = NULL;
5286	dns_rdataset_t rdataset;
5287	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
5288	unsigned char data[1024]; /* XXX */
5289	isc_buffer_t buffer;
5290	unsigned int i, j;
5291
5292	dns_rdataset_init(&rdataset);
5293	isc_buffer_init(&buffer, data, sizeof(data));
5294
5295	if (type == dns_rdatatype_nsec3)
5296		result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5297	else
5298		result = dns_db_findnode(db, name, ISC_FALSE, &node);
5299	if (result == ISC_R_NOTFOUND)
5300		return (ISC_R_SUCCESS);
5301	if (result != ISC_R_SUCCESS)
5302		goto failure;
5303	result = dns_db_findrdataset(db, node, ver, type, 0,
5304				     (isc_stdtime_t) 0, &rdataset, NULL);
5305	dns_db_detachnode(db, &node);
5306	if (result == ISC_R_NOTFOUND) {
5307		INSIST(!dns_rdataset_isassociated(&rdataset));
5308		return (ISC_R_SUCCESS);
5309	}
5310	if (result != ISC_R_SUCCESS) {
5311		INSIST(!dns_rdataset_isassociated(&rdataset));
5312		goto failure;
5313	}
5314
5315	for (i = 0; i < nkeys; i++) {
5316		isc_boolean_t both = ISC_FALSE;
5317
5318		if (!dst_key_isprivate(keys[i]))
5319			continue;
5320
5321		if (check_ksk && !REVOKE(keys[i])) {
5322			isc_boolean_t have_ksk, have_nonksk;
5323			if (KSK(keys[i])) {
5324				have_ksk = ISC_TRUE;
5325				have_nonksk = ISC_FALSE;
5326			} else {
5327				have_ksk = ISC_FALSE;
5328				have_nonksk = ISC_TRUE;
5329			}
5330			for (j = 0; j < nkeys; j++) {
5331				if (j == i || ALG(keys[i]) != ALG(keys[j]))
5332					continue;
5333				if (REVOKE(keys[j]))
5334					continue;
5335				if (KSK(keys[j]))
5336					have_ksk = ISC_TRUE;
5337				else
5338					have_nonksk = ISC_TRUE;
5339				both = have_ksk && have_nonksk;
5340				if (both)
5341					break;
5342			}
5343		}
5344		if (both) {
5345			if (type == dns_rdatatype_dnskey) {
5346				if (!KSK(keys[i]) && keyset_kskonly)
5347					continue;
5348			} else if (KSK(keys[i]))
5349				continue;
5350		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
5351				continue;
5352
5353		/* Calculate the signature, creating a RRSIG RDATA. */
5354		isc_buffer_clear(&buffer);
5355		CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
5356				      &inception, &expire,
5357				      mctx, &buffer, &sig_rdata));
5358		/* Update the database and journal with the RRSIG. */
5359		/* XXX inefficient - will cause dataset merging */
5360		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
5361				    name, rdataset.ttl, &sig_rdata));
5362		dns_rdata_reset(&sig_rdata);
5363		isc_buffer_init(&buffer, data, sizeof(data));
5364	}
5365
5366 failure:
5367	if (dns_rdataset_isassociated(&rdataset))
5368		dns_rdataset_disassociate(&rdataset);
5369	if (node != NULL)
5370		dns_db_detachnode(db, &node);
5371	return (result);
5372}
5373
5374static void
5375zone_resigninc(dns_zone_t *zone) {
5376	dns_db_t *db = NULL;
5377	dns_dbversion_t *version = NULL;
5378	dns_diff_t sig_diff;
5379	dns_fixedname_t fixed;
5380	dns_name_t *name;
5381	dns_rdataset_t rdataset;
5382	dns_rdatatype_t covers;
5383	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
5384	isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
5385	isc_result_t result;
5386	isc_stdtime_t now, inception, soaexpire, expire, stop;
5387	isc_uint32_t jitter;
5388	unsigned int i;
5389	unsigned int nkeys = 0;
5390	unsigned int resign;
5391
5392	dns_rdataset_init(&rdataset);
5393	dns_fixedname_init(&fixed);
5394	dns_diff_init(zone->mctx, &sig_diff);
5395	sig_diff.resign = zone->sigresigninginterval;
5396
5397
5398	/*
5399	 * Zone is frozen or automatic resigning is disabled.
5400	 * Pause for 5 minutes.
5401	 */
5402	if (zone->update_disabled ||
5403	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
5404	{
5405		result = ISC_R_FAILURE;
5406		goto failure;
5407	}
5408
5409	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5410	dns_db_attach(zone->db, &db);
5411	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5412
5413	result = dns_db_newversion(db, &version);
5414	if (result != ISC_R_SUCCESS) {
5415		dns_zone_log(zone, ISC_LOG_ERROR,
5416			     "zone_resigninc:dns_db_newversion -> %s",
5417			     dns_result_totext(result));
5418		goto failure;
5419	}
5420
5421	result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
5422				zone_keys, &nkeys);
5423	if (result != ISC_R_SUCCESS) {
5424		dns_zone_log(zone, ISC_LOG_ERROR,
5425			     "zone_resigninc:find_zone_keys -> %s",
5426			     dns_result_totext(result));
5427		goto failure;
5428	}
5429
5430	isc_stdtime_get(&now);
5431	inception = now - 3600;	/* Allow for clock skew. */
5432	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5433	/*
5434	 * Spread out signatures over time if they happen to be
5435	 * clumped.  We don't do this for each add_sigs() call as
5436	 * we still want some clustering to occur.
5437	 */
5438	isc_random_get(&jitter);
5439	expire = soaexpire - jitter % 3600;
5440	stop = now + 5;
5441
5442	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5443	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5444
5445	name = dns_fixedname_name(&fixed);
5446	result = dns_db_getsigningtime(db, &rdataset, name);
5447	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
5448		dns_zone_log(zone, ISC_LOG_ERROR,
5449			     "zone_resigninc:dns_db_getsigningtime -> %s",
5450			     dns_result_totext(result));
5451	}
5452
5453	i = 0;
5454	while (result == ISC_R_SUCCESS) {
5455		resign = rdataset.resign;
5456		covers = rdataset.covers;
5457		dns_rdataset_disassociate(&rdataset);
5458
5459		/*
5460		 * Stop if we hit the SOA as that means we have walked the
5461		 * entire zone.  The SOA record should always be the most
5462		 * recent signature.
5463		 */
5464		/* XXXMPA increase number of RRsets signed pre call */
5465		if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
5466		    resign > stop)
5467			break;
5468
5469		result = del_sigs(zone, db, version, name, covers, &sig_diff,
5470				  zone_keys, nkeys, now, ISC_TRUE);
5471		if (result != ISC_R_SUCCESS) {
5472			dns_zone_log(zone, ISC_LOG_ERROR,
5473				     "zone_resigninc:del_sigs -> %s",
5474				     dns_result_totext(result));
5475			break;
5476		}
5477
5478		result = add_sigs(db, version, name, covers, &sig_diff,
5479				  zone_keys, nkeys, zone->mctx, inception,
5480				  expire, check_ksk, keyset_kskonly);
5481		if (result != ISC_R_SUCCESS) {
5482			dns_zone_log(zone, ISC_LOG_ERROR,
5483				     "zone_resigninc:add_sigs -> %s",
5484				     dns_result_totext(result));
5485			break;
5486		}
5487		result	= dns_db_getsigningtime(db, &rdataset,
5488						dns_fixedname_name(&fixed));
5489		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
5490			result = ISC_R_SUCCESS;
5491			break;
5492		}
5493		if (result != ISC_R_SUCCESS)
5494			dns_zone_log(zone, ISC_LOG_ERROR,
5495			     "zone_resigninc:dns_db_getsigningtime -> %s",
5496				     dns_result_totext(result));
5497	}
5498
5499	if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
5500		goto failure;
5501
5502	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5503			  &sig_diff, zone_keys, nkeys, now, ISC_TRUE);
5504	if (result != ISC_R_SUCCESS) {
5505		dns_zone_log(zone, ISC_LOG_ERROR,
5506			     "zone_resigninc:del_sigs -> %s",
5507			     dns_result_totext(result));
5508		goto failure;
5509	}
5510
5511	/*
5512	 * Did we change anything in the zone?
5513	 */
5514	if (ISC_LIST_EMPTY(sig_diff.tuples))
5515		goto failure;
5516
5517	/* Increment SOA serial if we have made changes */
5518	result = update_soa_serial(db, version, &sig_diff, zone->mctx,
5519				   zone->updatemethod);
5520	if (result != ISC_R_SUCCESS) {
5521		dns_zone_log(zone, ISC_LOG_ERROR,
5522			     "zone_resigninc:update_soa_serial -> %s",
5523			     dns_result_totext(result));
5524		goto failure;
5525	}
5526
5527	/*
5528	 * Generate maximum life time signatures so that the above loop
5529	 * termination is sensible.
5530	 */
5531	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5532			  &sig_diff, zone_keys, nkeys, zone->mctx, inception,
5533			  soaexpire, check_ksk, keyset_kskonly);
5534	if (result != ISC_R_SUCCESS) {
5535		dns_zone_log(zone, ISC_LOG_ERROR,
5536			     "zone_resigninc:add_sigs -> %s",
5537			     dns_result_totext(result));
5538		goto failure;
5539	}
5540
5541	/* Write changes to journal file. */
5542	CHECK(zone_journal(zone, &sig_diff, NULL, "zone_resigninc"));
5543
5544	/* Everything has succeeded. Commit the changes. */
5545	dns_db_closeversion(db, &version, ISC_TRUE);
5546
5547 failure:
5548	dns_diff_clear(&sig_diff);
5549	for (i = 0; i < nkeys; i++)
5550		dst_key_free(&zone_keys[i]);
5551	if (version != NULL) {
5552		dns_db_closeversion(zone->db, &version, ISC_FALSE);
5553		dns_db_detach(&db);
5554	} else if (db != NULL)
5555		dns_db_detach(&db);
5556	if (result == ISC_R_SUCCESS) {
5557		set_resigntime(zone);
5558		LOCK_ZONE(zone);
5559		zone_needdump(zone, DNS_DUMP_DELAY);
5560		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5561		UNLOCK_ZONE(zone);
5562	} else {
5563		/*
5564		 * Something failed.  Retry in 5 minutes.
5565		 */
5566		isc_interval_t ival;
5567		isc_interval_set(&ival, 300, 0);
5568		isc_time_nowplusinterval(&zone->resigntime, &ival);
5569	}
5570}
5571
5572static isc_result_t
5573next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
5574	    dns_name_t *newname, isc_boolean_t bottom)
5575{
5576	isc_result_t result;
5577	dns_dbiterator_t *dbit = NULL;
5578	dns_rdatasetiter_t *rdsit = NULL;
5579	dns_dbnode_t *node = NULL;
5580
5581	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
5582	CHECK(dns_dbiterator_seek(dbit, oldname));
5583	do {
5584		result = dns_dbiterator_next(dbit);
5585		if (result == ISC_R_NOMORE)
5586			CHECK(dns_dbiterator_first(dbit));
5587		CHECK(dns_dbiterator_current(dbit, &node, newname));
5588		if (bottom && dns_name_issubdomain(newname, oldname) &&
5589		    !dns_name_equal(newname, oldname)) {
5590			dns_db_detachnode(db, &node);
5591			continue;
5592		}
5593		/*
5594		 * Is this node empty?
5595		 */
5596		CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
5597		result = dns_rdatasetiter_first(rdsit);
5598		dns_db_detachnode(db, &node);
5599		dns_rdatasetiter_destroy(&rdsit);
5600		if (result != ISC_R_NOMORE)
5601			break;
5602	} while (1);
5603 failure:
5604	if (node != NULL)
5605		dns_db_detachnode(db, &node);
5606	if (dbit != NULL)
5607		dns_dbiterator_destroy(&dbit);
5608	return (result);
5609}
5610
5611static isc_boolean_t
5612signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5613		dns_rdatatype_t type, dst_key_t *key)
5614{
5615	isc_result_t result;
5616	dns_rdataset_t rdataset;
5617	dns_rdata_t rdata = DNS_RDATA_INIT;
5618	dns_rdata_rrsig_t rrsig;
5619
5620	dns_rdataset_init(&rdataset);
5621	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
5622				     type, 0, &rdataset, NULL);
5623	if (result != ISC_R_SUCCESS) {
5624		INSIST(!dns_rdataset_isassociated(&rdataset));
5625		return (ISC_FALSE);
5626	}
5627	for (result = dns_rdataset_first(&rdataset);
5628	     result == ISC_R_SUCCESS;
5629	     result = dns_rdataset_next(&rdataset)) {
5630		dns_rdataset_current(&rdataset, &rdata);
5631		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5632		INSIST(result == ISC_R_SUCCESS);
5633		if (rrsig.algorithm == dst_key_alg(key) &&
5634		    rrsig.keyid == dst_key_id(key)) {
5635			dns_rdataset_disassociate(&rdataset);
5636			return (ISC_TRUE);
5637		}
5638		dns_rdata_reset(&rdata);
5639	}
5640	dns_rdataset_disassociate(&rdataset);
5641	return (ISC_FALSE);
5642}
5643
5644static isc_result_t
5645add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5646	 dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
5647	 dns_diff_t *diff)
5648{
5649	dns_fixedname_t fixed;
5650	dns_name_t *next;
5651	dns_rdata_t rdata = DNS_RDATA_INIT;
5652	isc_result_t result;
5653	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
5654
5655	dns_fixedname_init(&fixed);
5656	next = dns_fixedname_name(&fixed);
5657
5658	CHECK(next_active(db, version, name, next, bottom));
5659	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
5660				  &rdata));
5661	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
5662			    &rdata));
5663 failure:
5664	return (result);
5665}
5666
5667static isc_result_t
5668sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
5669	    dns_dbversion_t *version, isc_boolean_t build_nsec3,
5670	    isc_boolean_t build_nsec, dst_key_t *key,
5671	    isc_stdtime_t inception, isc_stdtime_t expire,
5672	    unsigned int minimum, isc_boolean_t is_ksk,
5673	    isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
5674	    dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
5675{
5676	isc_result_t result;
5677	dns_rdatasetiter_t *iterator = NULL;
5678	dns_rdataset_t rdataset;
5679	dns_rdata_t rdata = DNS_RDATA_INIT;
5680	isc_buffer_t buffer;
5681	unsigned char data[1024];
5682	isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
5683		      seen_nsec3, seen_ds;
5684	isc_boolean_t bottom;
5685
5686	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5687	if (result != ISC_R_SUCCESS) {
5688		if (result == ISC_R_NOTFOUND)
5689			result = ISC_R_SUCCESS;
5690		return (result);
5691	}
5692
5693	dns_rdataset_init(&rdataset);
5694	isc_buffer_init(&buffer, data, sizeof(data));
5695	seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
5696	seen_nsec3 = seen_ds = ISC_FALSE;
5697	for (result = dns_rdatasetiter_first(iterator);
5698	     result == ISC_R_SUCCESS;
5699	     result = dns_rdatasetiter_next(iterator)) {
5700		dns_rdatasetiter_current(iterator, &rdataset);
5701		if (rdataset.type == dns_rdatatype_soa)
5702			seen_soa = ISC_TRUE;
5703		else if (rdataset.type == dns_rdatatype_ns)
5704			seen_ns = ISC_TRUE;
5705		else if (rdataset.type == dns_rdatatype_ds)
5706			seen_ds = ISC_TRUE;
5707		else if (rdataset.type == dns_rdatatype_dname)
5708			seen_dname = ISC_TRUE;
5709		else if (rdataset.type == dns_rdatatype_nsec)
5710			seen_nsec = ISC_TRUE;
5711		else if (rdataset.type == dns_rdatatype_nsec3)
5712			seen_nsec3 = ISC_TRUE;
5713		if (rdataset.type != dns_rdatatype_rrsig)
5714			seen_rr = ISC_TRUE;
5715		dns_rdataset_disassociate(&rdataset);
5716	}
5717	if (result != ISC_R_NOMORE)
5718		goto failure;
5719	if (seen_ns && !seen_soa)
5720		*delegation = ISC_TRUE;
5721	/*
5722	 * Going from insecure to NSEC3.
5723	 * Don't generate NSEC3 records for NSEC3 records.
5724	 */
5725	if (build_nsec3 && !seen_nsec3 && seen_rr) {
5726		isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
5727		CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
5728					  unsecure, diff));
5729		(*signatures)--;
5730	}
5731	/*
5732	 * Going from insecure to NSEC.
5733	 * Don't generate NSEC records for NSEC3 records.
5734	 */
5735	if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
5736		/* Build and add NSEC. */
5737		bottom = (seen_ns && !seen_soa) || seen_dname;
5738		/*
5739		 * Build a NSEC record except at the origin.
5740		 */
5741		if (!dns_name_equal(name, dns_db_origin(db))) {
5742			CHECK(add_nsec(db, version, name, node, minimum,
5743				       bottom, diff));
5744			/* Count a NSEC generation as a signature generation. */
5745			(*signatures)--;
5746		}
5747	}
5748	result = dns_rdatasetiter_first(iterator);
5749	while (result == ISC_R_SUCCESS) {
5750		dns_rdatasetiter_current(iterator, &rdataset);
5751		if (rdataset.type == dns_rdatatype_soa ||
5752		    rdataset.type == dns_rdatatype_rrsig)
5753			goto next_rdataset;
5754		if (rdataset.type == dns_rdatatype_dnskey) {
5755			if (!is_ksk && keyset_kskonly)
5756				goto next_rdataset;
5757		} else if (is_ksk)
5758			goto next_rdataset;
5759		if (*delegation &&
5760		    rdataset.type != dns_rdatatype_ds &&
5761		    rdataset.type != dns_rdatatype_nsec)
5762			goto next_rdataset;
5763		if (signed_with_key(db, node, version, rdataset.type, key))
5764			goto next_rdataset;
5765		/* Calculate the signature, creating a RRSIG RDATA. */
5766		isc_buffer_clear(&buffer);
5767		CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
5768				      &expire, mctx, &buffer, &rdata));
5769		/* Update the database and journal with the RRSIG. */
5770		/* XXX inefficient - will cause dataset merging */
5771		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
5772				    name, rdataset.ttl, &rdata));
5773		dns_rdata_reset(&rdata);
5774		(*signatures)--;
5775 next_rdataset:
5776		dns_rdataset_disassociate(&rdataset);
5777		result = dns_rdatasetiter_next(iterator);
5778	}
5779	if (result == ISC_R_NOMORE)
5780		result = ISC_R_SUCCESS;
5781	if (seen_dname)
5782		*delegation = ISC_TRUE;
5783 failure:
5784	if (dns_rdataset_isassociated(&rdataset))
5785		dns_rdataset_disassociate(&rdataset);
5786	if (iterator != NULL)
5787		dns_rdatasetiter_destroy(&iterator);
5788	return (result);
5789}
5790
5791/*
5792 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
5793 */
5794static isc_result_t
5795updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5796	     dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
5797{
5798	isc_result_t result;
5799	dns_rdataset_t rdataset;
5800	dns_dbnode_t *node = NULL;
5801
5802	CHECK(dns_db_getoriginnode(db, &node));
5803	if (update_only) {
5804		dns_rdataset_init(&rdataset);
5805		result = dns_db_findrdataset(db, node, version,
5806					     dns_rdatatype_nsec,
5807					     dns_rdatatype_none,
5808					     0, &rdataset, NULL);
5809		if (dns_rdataset_isassociated(&rdataset))
5810			dns_rdataset_disassociate(&rdataset);
5811		if (result == ISC_R_NOTFOUND)
5812			goto success;
5813		if (result != ISC_R_SUCCESS)
5814			goto failure;
5815	}
5816	CHECK(delete_nsec(db, version, node, name, diff));
5817	CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
5818 success:
5819	result = ISC_R_SUCCESS;
5820 failure:
5821	if (node != NULL)
5822		dns_db_detachnode(db, &node);
5823	return (result);
5824}
5825
5826static isc_result_t
5827updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
5828		  dns_dbversion_t *version, isc_boolean_t build_nsec3,
5829		  dns_ttl_t minimum, dns_diff_t *diff)
5830{
5831	isc_result_t result;
5832	dns_dbnode_t *node = NULL;
5833	dns_rdataset_t rdataset;
5834	dns_rdata_t rdata = DNS_RDATA_INIT;
5835	unsigned char data[5];
5836	isc_boolean_t seen_done = ISC_FALSE;
5837	isc_boolean_t have_rr = ISC_FALSE;
5838
5839	dns_rdataset_init(&rdataset);
5840	result = dns_db_getoriginnode(signing->db, &node);
5841	if (result != ISC_R_SUCCESS)
5842		goto failure;
5843
5844	result = dns_db_findrdataset(signing->db, node, version,
5845				     zone->privatetype, dns_rdatatype_none,
5846				     0, &rdataset, NULL);
5847	if (result == ISC_R_NOTFOUND) {
5848		INSIST(!dns_rdataset_isassociated(&rdataset));
5849		result = ISC_R_SUCCESS;
5850		goto failure;
5851	}
5852	if (result != ISC_R_SUCCESS) {
5853		INSIST(!dns_rdataset_isassociated(&rdataset));
5854		goto failure;
5855	}
5856	for (result = dns_rdataset_first(&rdataset);
5857	     result == ISC_R_SUCCESS;
5858	     result = dns_rdataset_next(&rdataset)) {
5859		dns_rdataset_current(&rdataset, &rdata);
5860		/*
5861		 * If we don't match the algorithm or keyid skip the record.
5862		 */
5863		if (rdata.length != 5 ||
5864		    rdata.data[0] != signing->algorithm ||
5865		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
5866		    rdata.data[2] != (signing->keyid & 0xff)) {
5867			have_rr = ISC_TRUE;
5868			dns_rdata_reset(&rdata);
5869			continue;
5870		}
5871		/*
5872		 * We have a match.  If we were signing (!signing->delete)
5873		 * and we already have a record indicating that we have
5874		 * finished signing (rdata.data[4] != 0) then keep it.
5875		 * Otherwise it needs to be deleted as we have removed all
5876		 * the signatures (signing->delete), so any record indicating
5877		 * completion is now out of date, or we have finished signing
5878		 * with the new record so we no longer need to remember that
5879		 * we need to sign the zone with the matching key across a
5880		 * nameserver re-start.
5881		 */
5882		if (!signing->delete && rdata.data[4] != 0) {
5883			seen_done = ISC_TRUE;
5884			have_rr = ISC_TRUE;
5885		} else
5886			CHECK(update_one_rr(signing->db, version, diff,
5887					    DNS_DIFFOP_DEL, &zone->origin,
5888					    rdataset.ttl, &rdata));
5889		dns_rdata_reset(&rdata);
5890	}
5891	if (result == ISC_R_NOMORE)
5892		result = ISC_R_SUCCESS;
5893	if (!signing->delete && !seen_done) {
5894		/*
5895		 * If we were signing then we need to indicate that we have
5896		 * finished signing the zone with this key.  If it is already
5897		 * there we don't need to add it a second time.
5898		 */
5899		data[0] = signing->algorithm;
5900		data[1] = (signing->keyid >> 8) & 0xff;
5901		data[2] = signing->keyid & 0xff;
5902		data[3] = 0;
5903		data[4] = 1;
5904		rdata.length = sizeof(data);
5905		rdata.data = data;
5906		rdata.type = zone->privatetype;
5907		rdata.rdclass = dns_db_class(signing->db);
5908		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
5909				    &zone->origin, rdataset.ttl, &rdata));
5910	} else if (!have_rr) {
5911		dns_name_t *origin = dns_db_origin(signing->db);
5912		/*
5913		 * Rebuild the NSEC/NSEC3 record for the origin as we no
5914		 * longer have any private records.
5915		 */
5916		if (build_nsec3)
5917			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
5918						  minimum, ISC_FALSE, diff));
5919		CHECK(updatesecure(signing->db, version, origin, minimum,
5920				   ISC_TRUE, diff));
5921	}
5922
5923 failure:
5924	if (dns_rdataset_isassociated(&rdataset))
5925		dns_rdataset_disassociate(&rdataset);
5926	if (node != NULL)
5927		dns_db_detachnode(signing->db, &node);
5928	return (result);
5929}
5930
5931/*
5932 * If 'active' is set then we are not done with the chain yet so only
5933 * delete the nsec3param record which indicates a full chain exists
5934 * (flags == 0).
5935 */
5936static isc_result_t
5937fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
5938		 isc_boolean_t active, dns_rdatatype_t privatetype,
5939		 dns_diff_t *diff)
5940{
5941	dns_dbnode_t *node = NULL;
5942	dns_name_t *name = dns_db_origin(db);
5943	dns_rdata_t rdata = DNS_RDATA_INIT;
5944	dns_rdataset_t rdataset;
5945	dns_rdata_nsec3param_t nsec3param;
5946	isc_result_t result;
5947	isc_buffer_t buffer;
5948	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
5949	dns_ttl_t ttl = 0;
5950	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
5951
5952	dns_rdataset_init(&rdataset);
5953
5954	result = dns_db_getoriginnode(db, &node);
5955	RUNTIME_CHECK(result == ISC_R_SUCCESS);
5956	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5957				     0, 0, &rdataset, NULL);
5958	if (result == ISC_R_NOTFOUND)
5959		goto try_private;
5960	if (result != ISC_R_SUCCESS)
5961		goto failure;
5962
5963	/*
5964	 * Preserve the existing ttl.
5965	 */
5966	ttl = rdataset.ttl;
5967
5968	/*
5969	 * Delete all NSEC3PARAM records which match that in nsec3chain.
5970	 */
5971	for (result = dns_rdataset_first(&rdataset);
5972	     result == ISC_R_SUCCESS;
5973	     result = dns_rdataset_next(&rdataset)) {
5974
5975		dns_rdataset_current(&rdataset, &rdata);
5976		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5977
5978		if (nsec3param.hash != chain->nsec3param.hash ||
5979		    (active && nsec3param.flags != 0) ||
5980		    nsec3param.iterations != chain->nsec3param.iterations ||
5981		    nsec3param.salt_length != chain->nsec3param.salt_length ||
5982		    memcmp(nsec3param.salt, chain->nsec3param.salt,
5983			   nsec3param.salt_length)) {
5984			dns_rdata_reset(&rdata);
5985			continue;
5986		}
5987
5988		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5989				    name, rdataset.ttl, &rdata));
5990		dns_rdata_reset(&rdata);
5991	}
5992	if (result != ISC_R_NOMORE)
5993		goto failure;
5994
5995	dns_rdataset_disassociate(&rdataset);
5996
5997 try_private:
5998
5999	if (active)
6000		goto add;
6001
6002	result = dns_nsec_nseconly(db, ver, &nseconly);
6003	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
6004
6005	/*
6006	 * Delete all private records which match that in nsec3chain.
6007	 */
6008	result = dns_db_findrdataset(db, node, ver, privatetype,
6009				     0, 0, &rdataset, NULL);
6010	if (result == ISC_R_NOTFOUND)
6011		goto add;
6012	if (result != ISC_R_SUCCESS)
6013		goto failure;
6014
6015	for (result = dns_rdataset_first(&rdataset);
6016	     result == ISC_R_SUCCESS;
6017	     result = dns_rdataset_next(&rdataset)) {
6018		dns_rdata_t private = DNS_RDATA_INIT;
6019		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
6020
6021		dns_rdataset_current(&rdataset, &private);
6022		if (!dns_nsec3param_fromprivate(&private, &rdata,
6023						buf, sizeof(buf)))
6024			continue;
6025		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6026
6027		if ((!nsec3ok &&
6028		     (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
6029		    nsec3param.hash != chain->nsec3param.hash ||
6030		    nsec3param.iterations != chain->nsec3param.iterations ||
6031		    nsec3param.salt_length != chain->nsec3param.salt_length ||
6032		    memcmp(nsec3param.salt, chain->nsec3param.salt,
6033			   nsec3param.salt_length)) {
6034			dns_rdata_reset(&rdata);
6035			continue;
6036		}
6037
6038		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6039				    name, rdataset.ttl, &private));
6040		dns_rdata_reset(&rdata);
6041	}
6042	if (result != ISC_R_NOMORE)
6043		goto failure;
6044
6045  add:
6046	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
6047		result = ISC_R_SUCCESS;
6048		goto failure;
6049	}
6050
6051	/*
6052	 * Add a NSEC3PARAM record which matches that in nsec3chain but
6053	 * with all flags bits cleared.
6054	 *
6055	 * Note: we do not clear chain->nsec3param.flags as this change
6056	 * may be reversed.
6057	 */
6058	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
6059	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
6060				   dns_rdatatype_nsec3param,
6061				   &chain->nsec3param, &buffer));
6062	rdata.data[1] = 0;	/* Clear flag bits. */
6063	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
6064
6065  failure:
6066	dns_db_detachnode(db, &node);
6067	if (dns_rdataset_isassociated(&rdataset))
6068		dns_rdataset_disassociate(&rdataset);
6069	return (result);
6070}
6071
6072static isc_result_t
6073delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6074	    dns_name_t *name, dns_diff_t *diff)
6075{
6076	dns_rdataset_t rdataset;
6077	isc_result_t result;
6078
6079	dns_rdataset_init(&rdataset);
6080
6081	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6082				     0, 0, &rdataset, NULL);
6083	if (result == ISC_R_NOTFOUND)
6084		return (ISC_R_SUCCESS);
6085	if (result != ISC_R_SUCCESS)
6086		return (result);
6087	for (result = dns_rdataset_first(&rdataset);
6088	     result == ISC_R_SUCCESS;
6089	     result = dns_rdataset_next(&rdataset)) {
6090		dns_rdata_t rdata = DNS_RDATA_INIT;
6091
6092		dns_rdataset_current(&rdataset, &rdata);
6093		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6094				    rdataset.ttl, &rdata));
6095	}
6096	if (result == ISC_R_NOMORE)
6097		result = ISC_R_SUCCESS;
6098 failure:
6099	dns_rdataset_disassociate(&rdataset);
6100	return (result);
6101}
6102
6103static isc_result_t
6104deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6105		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
6106		    dns_diff_t *diff)
6107{
6108	dns_rdataset_t rdataset;
6109	dns_rdata_nsec3_t nsec3;
6110	isc_result_t result;
6111
6112	dns_rdataset_init(&rdataset);
6113	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
6114				     0, 0, &rdataset, NULL);
6115	if (result == ISC_R_NOTFOUND)
6116		return (ISC_R_SUCCESS);
6117	if (result != ISC_R_SUCCESS)
6118		return (result);
6119
6120	for (result = dns_rdataset_first(&rdataset);
6121	     result == ISC_R_SUCCESS;
6122	     result = dns_rdataset_next(&rdataset)) {
6123		dns_rdata_t rdata = DNS_RDATA_INIT;
6124
6125		dns_rdataset_current(&rdataset, &rdata);
6126		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
6127		if (nsec3.hash != param->hash ||
6128		    nsec3.iterations != param->iterations ||
6129		    nsec3.salt_length != param->salt_length ||
6130		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
6131			continue;
6132		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6133				    rdataset.ttl, &rdata));
6134	}
6135	if (result == ISC_R_NOMORE)
6136		result = ISC_R_SUCCESS;
6137 failure:
6138	dns_rdataset_disassociate(&rdataset);
6139	return (result);
6140}
6141
6142static isc_result_t
6143need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
6144		const dns_rdata_nsec3param_t *param,
6145		isc_boolean_t *answer)
6146{
6147	dns_dbnode_t *node = NULL;
6148	dns_rdata_t rdata = DNS_RDATA_INIT;
6149	dns_rdata_nsec3param_t myparam;
6150	dns_rdataset_t rdataset;
6151	isc_result_t result;
6152
6153	*answer = ISC_FALSE;
6154
6155	result = dns_db_getoriginnode(db, &node);
6156	RUNTIME_CHECK(result == ISC_R_SUCCESS);
6157
6158	dns_rdataset_init(&rdataset);
6159
6160	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6161				     0, 0, &rdataset, NULL);
6162	if (result == ISC_R_SUCCESS) {
6163		dns_rdataset_disassociate(&rdataset);
6164		dns_db_detachnode(db, &node);
6165		return (result);
6166	}
6167	if (result != ISC_R_NOTFOUND) {
6168		dns_db_detachnode(db, &node);
6169		return (result);
6170	}
6171
6172	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6173				     0, 0, &rdataset, NULL);
6174	if (result == ISC_R_NOTFOUND) {
6175		*answer = ISC_TRUE;
6176		dns_db_detachnode(db, &node);
6177		return (ISC_R_SUCCESS);
6178	}
6179	if (result != ISC_R_SUCCESS) {
6180		dns_db_detachnode(db, &node);
6181		return (result);
6182	}
6183
6184	for (result = dns_rdataset_first(&rdataset);
6185	     result == ISC_R_SUCCESS;
6186	     result = dns_rdataset_next(&rdataset)) {
6187		dns_rdataset_current(&rdataset, &rdata);
6188		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
6189		dns_rdata_reset(&rdata);
6190		/*
6191		 * Ignore any NSEC3PARAM removals.
6192		 */
6193		if (NSEC3REMOVE(myparam.flags))
6194			continue;
6195		/*
6196		 * Ignore the chain that we are in the process of deleting.
6197		 */
6198		if (myparam.hash == param->hash &&
6199		    myparam.iterations == param->iterations &&
6200		    myparam.salt_length == param->salt_length &&
6201		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
6202			continue;
6203		/*
6204		 * Found an active NSEC3 chain.
6205		 */
6206		break;
6207	}
6208	if (result == ISC_R_NOMORE) {
6209		*answer = ISC_TRUE;
6210		result = ISC_R_SUCCESS;
6211	}
6212
6213 failure:
6214	if (dns_rdataset_isassociated(&rdataset))
6215		dns_rdataset_disassociate(&rdataset);
6216	dns_db_detachnode(db, &node);
6217	return (result);
6218}
6219
6220static isc_result_t
6221update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
6222	    dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
6223	    isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
6224	    isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
6225	    dns_diff_t *sig_diff)
6226{
6227	dns_difftuple_t *tuple;
6228	isc_result_t result;
6229
6230	for (tuple = ISC_LIST_HEAD(diff->tuples);
6231	     tuple != NULL;
6232	     tuple = ISC_LIST_HEAD(diff->tuples)) {
6233		result = del_sigs(zone, db, version, &tuple->name,
6234				  tuple->rdata.type, sig_diff,
6235				  zone_keys, nkeys, now, ISC_FALSE);
6236		if (result != ISC_R_SUCCESS) {
6237			dns_zone_log(zone, ISC_LOG_ERROR,
6238				     "update_sigs:del_sigs -> %s",
6239				     dns_result_totext(result));
6240			return (result);
6241		}
6242		result = add_sigs(db, version, &tuple->name,
6243				  tuple->rdata.type, sig_diff,
6244				  zone_keys, nkeys, zone->mctx, inception,
6245				  expire, check_ksk, keyset_kskonly);
6246		if (result != ISC_R_SUCCESS) {
6247			dns_zone_log(zone, ISC_LOG_ERROR,
6248				     "update_sigs:add_sigs -> %s",
6249				     dns_result_totext(result));
6250			return (result);
6251		}
6252
6253		do {
6254			dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
6255			while (next != NULL &&
6256			       (tuple->rdata.type != next->rdata.type ||
6257				!dns_name_equal(&tuple->name, &next->name)))
6258				next = ISC_LIST_NEXT(next, link);
6259			ISC_LIST_UNLINK(diff->tuples, tuple, link);
6260			dns_diff_appendminimal(sig_diff, &tuple);
6261			INSIST(tuple == NULL);
6262			tuple = next;
6263		} while (tuple != NULL);
6264	}
6265	return (ISC_R_SUCCESS);
6266}
6267
6268/*
6269 * Incrementally build and sign a new NSEC3 chain using the parameters
6270 * requested.
6271 */
6272static void
6273zone_nsec3chain(dns_zone_t *zone) {
6274	dns_db_t *db = NULL;
6275	dns_dbnode_t *node = NULL;
6276	dns_dbversion_t *version = NULL;
6277	dns_diff_t sig_diff;
6278	dns_diff_t nsec_diff;
6279	dns_diff_t nsec3_diff;
6280	dns_diff_t param_diff;
6281	dns_fixedname_t fixed;
6282	dns_fixedname_t nextfixed;
6283	dns_name_t *name, *nextname;
6284	dns_rdataset_t rdataset;
6285	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
6286	dns_nsec3chainlist_t cleanup;
6287	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6288	isc_int32_t signatures;
6289	isc_boolean_t check_ksk, keyset_kskonly;
6290	isc_boolean_t delegation;
6291	isc_boolean_t first;
6292	isc_result_t result;
6293	isc_stdtime_t now, inception, soaexpire, expire;
6294	isc_uint32_t jitter;
6295	unsigned int i;
6296	unsigned int nkeys = 0;
6297	isc_uint32_t nodes;
6298	isc_boolean_t unsecure = ISC_FALSE;
6299	isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
6300	isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
6301	dns_rdatasetiter_t *iterator = NULL;
6302	isc_boolean_t buildnsecchain;
6303	isc_boolean_t updatensec = ISC_FALSE;
6304	dns_rdatatype_t privatetype = zone->privatetype;
6305
6306	dns_rdataset_init(&rdataset);
6307	dns_fixedname_init(&fixed);
6308	name = dns_fixedname_name(&fixed);
6309	dns_fixedname_init(&nextfixed);
6310	nextname = dns_fixedname_name(&nextfixed);
6311	dns_diff_init(zone->mctx, &param_diff);
6312	dns_diff_init(zone->mctx, &nsec3_diff);
6313	dns_diff_init(zone->mctx, &nsec_diff);
6314	dns_diff_init(zone->mctx, &sig_diff);
6315	sig_diff.resign = zone->sigresigninginterval;
6316	ISC_LIST_INIT(cleanup);
6317
6318	/*
6319	 * Updates are disabled.  Pause for 5 minutes.
6320	 */
6321	if (zone->update_disabled) {
6322		result = ISC_R_FAILURE;
6323		goto failure;
6324	}
6325
6326	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6327	dns_db_attach(zone->db, &db);
6328	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6329
6330	result = dns_db_newversion(db, &version);
6331	if (result != ISC_R_SUCCESS) {
6332		dns_zone_log(zone, ISC_LOG_ERROR,
6333			     "zone_nsec3chain:dns_db_newversion -> %s",
6334			     dns_result_totext(result));
6335		goto failure;
6336	}
6337
6338	result = find_zone_keys(zone, db, version, zone->mctx,
6339				DNS_MAXZONEKEYS, zone_keys, &nkeys);
6340	if (result != ISC_R_SUCCESS) {
6341		dns_zone_log(zone, ISC_LOG_ERROR,
6342			     "zone_nsec3chain:find_zone_keys -> %s",
6343			     dns_result_totext(result));
6344		goto failure;
6345	}
6346
6347	isc_stdtime_get(&now);
6348	inception = now - 3600;	/* Allow for clock skew. */
6349	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6350
6351	/*
6352	 * Spread out signatures over time if they happen to be
6353	 * clumped.  We don't do this for each add_sigs() call as
6354	 * we still want some clustering to occur.
6355	 */
6356	isc_random_get(&jitter);
6357	expire = soaexpire - jitter % 3600;
6358
6359	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6360	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6361
6362	/*
6363	 * We keep pulling nodes off each iterator in turn until
6364	 * we have no more nodes to pull off or we reach the limits
6365	 * for this quantum.
6366	 */
6367	nodes = zone->nodes;
6368	signatures = zone->signatures;
6369	LOCK_ZONE(zone);
6370	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6371	UNLOCK_ZONE(zone);
6372	first = ISC_TRUE;
6373
6374	if (nsec3chain != NULL)
6375		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6376	/*
6377	 * Generate new NSEC3 chains first.
6378	 */
6379	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6380		LOCK_ZONE(zone);
6381		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6382
6383		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6384		if (nsec3chain->done || nsec3chain->db != zone->db) {
6385			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
6386			ISC_LIST_APPEND(cleanup, nsec3chain, link);
6387		}
6388		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6389		UNLOCK_ZONE(zone);
6390		if (ISC_LIST_TAIL(cleanup) == nsec3chain)
6391			goto next_addchain;
6392
6393		/*
6394		 * Possible future db.
6395		 */
6396		if (nsec3chain->db != db) {
6397			goto next_addchain;
6398		}
6399
6400		if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
6401			goto next_addchain;
6402
6403		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6404
6405		if (nsec3chain->delete_nsec) {
6406			delegation = ISC_FALSE;
6407			dns_dbiterator_pause(nsec3chain->dbiterator);
6408			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
6409			goto next_addnode;
6410		}
6411		/*
6412		 * On the first pass we need to check if the current node
6413		 * has not been obscured.
6414		 */
6415		delegation = ISC_FALSE;
6416		unsecure = ISC_FALSE;
6417		if (first) {
6418			dns_fixedname_t ffound;
6419			dns_name_t *found;
6420			dns_fixedname_init(&ffound);
6421			found = dns_fixedname_name(&ffound);
6422			result = dns_db_find(db, name, version,
6423					     dns_rdatatype_soa,
6424					     DNS_DBFIND_NOWILD, 0, NULL, found,
6425					     NULL, NULL);
6426			if ((result == DNS_R_DELEGATION ||
6427			    result == DNS_R_DNAME) &&
6428			    !dns_name_equal(name, found)) {
6429				/*
6430				 * Remember the obscuring name so that
6431				 * we skip all obscured names.
6432				 */
6433				dns_name_copy(found, name, NULL);
6434				delegation = ISC_TRUE;
6435				goto next_addnode;
6436			}
6437		}
6438
6439		/*
6440		 * Check to see if this is a bottom of zone node.
6441		 */
6442		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6443		if (result == ISC_R_NOTFOUND)	/* Empty node? */
6444			goto next_addnode;
6445		if (result != ISC_R_SUCCESS)
6446			goto failure;
6447
6448		seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
6449			ISC_FALSE;
6450		for (result = dns_rdatasetiter_first(iterator);
6451		     result == ISC_R_SUCCESS;
6452		     result = dns_rdatasetiter_next(iterator)) {
6453			dns_rdatasetiter_current(iterator, &rdataset);
6454			INSIST(rdataset.type != dns_rdatatype_nsec3);
6455			if (rdataset.type == dns_rdatatype_soa)
6456				seen_soa = ISC_TRUE;
6457			else if (rdataset.type == dns_rdatatype_ns)
6458				seen_ns = ISC_TRUE;
6459			else if (rdataset.type == dns_rdatatype_dname)
6460				seen_dname = ISC_TRUE;
6461			else if (rdataset.type == dns_rdatatype_ds)
6462				seen_ds = ISC_TRUE;
6463			else if (rdataset.type == dns_rdatatype_nsec)
6464				seen_nsec = ISC_TRUE;
6465			dns_rdataset_disassociate(&rdataset);
6466		}
6467		dns_rdatasetiter_destroy(&iterator);
6468		/*
6469		 * Is there a NSEC chain than needs to be cleaned up?
6470		 */
6471		if (seen_nsec)
6472			nsec3chain->seen_nsec = ISC_TRUE;
6473		if (seen_ns && !seen_soa && !seen_ds)
6474			unsecure = ISC_TRUE;
6475		if ((seen_ns && !seen_soa) || seen_dname)
6476			delegation = ISC_TRUE;
6477
6478		/*
6479		 * Process one node.
6480		 */
6481		dns_dbiterator_pause(nsec3chain->dbiterator);
6482		result = dns_nsec3_addnsec3(db, version, name,
6483					    &nsec3chain->nsec3param,
6484					    zone->minimum, unsecure,
6485					    &nsec3_diff);
6486		if (result != ISC_R_SUCCESS) {
6487			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6488				     "dns_nsec3_addnsec3 -> %s",
6489				     dns_result_totext(result));
6490			goto failure;
6491		}
6492
6493		/*
6494		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
6495		 * two signatures.  Additionally there will, in general, be
6496		 * two signature generated below.
6497		 *
6498		 * If we are only changing the optout flag the cost is half
6499		 * that of the cost of generating a completely new chain.
6500		 */
6501		signatures -= 4;
6502
6503		/*
6504		 * Go onto next node.
6505		 */
6506 next_addnode:
6507		first = ISC_FALSE;
6508		dns_db_detachnode(db, &node);
6509		do {
6510			result = dns_dbiterator_next(nsec3chain->dbiterator);
6511
6512			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
6513				CHECK(fixup_nsec3param(db, version, nsec3chain,
6514						       ISC_FALSE, privatetype,
6515						       &param_diff));
6516				LOCK_ZONE(zone);
6517				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6518						link);
6519				UNLOCK_ZONE(zone);
6520				ISC_LIST_APPEND(cleanup, nsec3chain, link);
6521				goto next_addchain;
6522			}
6523			if (result == ISC_R_NOMORE) {
6524				dns_dbiterator_pause(nsec3chain->dbiterator);
6525				if (nsec3chain->seen_nsec) {
6526					CHECK(fixup_nsec3param(db, version,
6527							       nsec3chain,
6528							       ISC_TRUE,
6529							       privatetype,
6530							       &param_diff));
6531					nsec3chain->delete_nsec = ISC_TRUE;
6532					goto same_addchain;
6533				}
6534				CHECK(fixup_nsec3param(db, version, nsec3chain,
6535						       ISC_FALSE, privatetype,
6536						       &param_diff));
6537				LOCK_ZONE(zone);
6538				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6539						link);
6540				UNLOCK_ZONE(zone);
6541				ISC_LIST_APPEND(cleanup, nsec3chain, link);
6542				goto next_addchain;
6543			} else if (result != ISC_R_SUCCESS) {
6544				dns_zone_log(zone, ISC_LOG_ERROR,
6545					     "zone_nsec3chain:"
6546					     "dns_dbiterator_next -> %s",
6547					     dns_result_totext(result));
6548				goto failure;
6549			} else if (delegation) {
6550				dns_dbiterator_current(nsec3chain->dbiterator,
6551						       &node, nextname);
6552				dns_db_detachnode(db, &node);
6553				if (!dns_name_issubdomain(nextname, name))
6554					break;
6555			} else
6556				break;
6557		} while (1);
6558		continue;
6559
6560 same_addchain:
6561		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6562		first = ISC_TRUE;
6563		continue;
6564
6565 next_addchain:
6566		dns_dbiterator_pause(nsec3chain->dbiterator);
6567		nsec3chain = nextnsec3chain;
6568		first = ISC_TRUE;
6569		if (nsec3chain != NULL)
6570			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6571	}
6572
6573	/*
6574	 * Process removals.
6575	 */
6576	LOCK_ZONE(zone);
6577	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6578	UNLOCK_ZONE(zone);
6579	first = ISC_TRUE;
6580	buildnsecchain = ISC_FALSE;
6581	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6582		LOCK_ZONE(zone);
6583		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6584		UNLOCK_ZONE(zone);
6585
6586		if (nsec3chain->db != db)
6587			goto next_removechain;
6588
6589		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
6590			goto next_removechain;
6591
6592		/*
6593		 * Work out if we need to build a NSEC chain as a consequence
6594		 * of removing this NSEC3 chain.
6595		 */
6596		if (first && !updatensec &&
6597		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
6598		{
6599			result = need_nsec_chain(db, version,
6600						 &nsec3chain->nsec3param,
6601						 &buildnsecchain);
6602			if (result != ISC_R_SUCCESS) {
6603				dns_zone_log(zone, ISC_LOG_ERROR,
6604					     "zone_nsec3chain:"
6605					     "need_nsec_chain -> %s",
6606					     dns_result_totext(result));
6607				goto failure;
6608			}
6609		}
6610
6611		if (first)
6612			dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
6613				     "buildnsecchain = %u\n", buildnsecchain);
6614
6615		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6616		delegation = ISC_FALSE;
6617
6618		if (!buildnsecchain) {
6619			/*
6620			 * Delete the NSECPARAM record that matches this chain.
6621			 */
6622			if (first) {
6623				result = fixup_nsec3param(db, version,
6624							  nsec3chain,
6625							  ISC_TRUE, privatetype,
6626							  &param_diff);
6627				if (result != ISC_R_SUCCESS) {
6628					dns_zone_log(zone, ISC_LOG_ERROR,
6629						     "zone_nsec3chain:"
6630						     "fixup_nsec3param -> %s",
6631						     dns_result_totext(result));
6632					goto failure;
6633				}
6634			}
6635
6636			/*
6637			 *  Delete the NSEC3 records.
6638			 */
6639			result = deletematchingnsec3(db, version, node, name,
6640						     &nsec3chain->nsec3param,
6641						     &nsec3_diff);
6642			if (result != ISC_R_SUCCESS) {
6643				dns_zone_log(zone, ISC_LOG_ERROR,
6644					     "zone_nsec3chain:"
6645					     "deletematchingnsec3 -> %s",
6646					     dns_result_totext(result));
6647				goto failure;
6648			}
6649			goto next_removenode;
6650		}
6651
6652		if (first) {
6653			dns_fixedname_t ffound;
6654			dns_name_t *found;
6655			dns_fixedname_init(&ffound);
6656			found = dns_fixedname_name(&ffound);
6657			result = dns_db_find(db, name, version,
6658					     dns_rdatatype_soa,
6659					     DNS_DBFIND_NOWILD, 0, NULL, found,
6660					     NULL, NULL);
6661			if ((result == DNS_R_DELEGATION ||
6662			     result == DNS_R_DNAME) &&
6663			    !dns_name_equal(name, found)) {
6664				/*
6665				 * Remember the obscuring name so that
6666				 * we skip all obscured names.
6667				 */
6668				dns_name_copy(found, name, NULL);
6669				delegation = ISC_TRUE;
6670				goto next_removenode;
6671			}
6672		}
6673
6674		/*
6675		 * Check to see if this is a bottom of zone node.
6676		 */
6677		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6678		if (result == ISC_R_NOTFOUND)	/* Empty node? */
6679			goto next_removenode;
6680		if (result != ISC_R_SUCCESS)
6681			goto failure;
6682
6683		seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
6684			seen_rr = ISC_FALSE;
6685		for (result = dns_rdatasetiter_first(iterator);
6686		     result == ISC_R_SUCCESS;
6687		     result = dns_rdatasetiter_next(iterator)) {
6688			dns_rdatasetiter_current(iterator, &rdataset);
6689			if (rdataset.type == dns_rdatatype_soa)
6690				seen_soa = ISC_TRUE;
6691			else if (rdataset.type == dns_rdatatype_ns)
6692				seen_ns = ISC_TRUE;
6693			else if (rdataset.type == dns_rdatatype_dname)
6694				seen_dname = ISC_TRUE;
6695			else if (rdataset.type == dns_rdatatype_nsec)
6696				seen_nsec = ISC_TRUE;
6697			else if (rdataset.type == dns_rdatatype_nsec3)
6698				seen_nsec3 = ISC_TRUE;
6699			if (rdataset.type != dns_rdatatype_rrsig)
6700				seen_rr = ISC_TRUE;
6701			dns_rdataset_disassociate(&rdataset);
6702		}
6703		dns_rdatasetiter_destroy(&iterator);
6704
6705		if (!seen_rr || seen_nsec3 || seen_nsec)
6706			goto next_removenode;
6707		if ((seen_ns && !seen_soa) || seen_dname)
6708			delegation = ISC_TRUE;
6709
6710		/*
6711		 * Add a NSEC record except at the origin.
6712		 */
6713		if (!dns_name_equal(name, dns_db_origin(db))) {
6714			dns_dbiterator_pause(nsec3chain->dbiterator);
6715			CHECK(add_nsec(db, version, name, node, zone->minimum,
6716				       delegation, &nsec_diff));
6717		}
6718
6719 next_removenode:
6720		first = ISC_FALSE;
6721		dns_db_detachnode(db, &node);
6722		do {
6723			result = dns_dbiterator_next(nsec3chain->dbiterator);
6724			if (result == ISC_R_NOMORE && buildnsecchain) {
6725				/*
6726				 * The NSEC chain should now be built.
6727				 * We can now remove the NSEC3 chain.
6728				 */
6729				updatensec = ISC_TRUE;
6730				goto same_removechain;
6731			}
6732			if (result == ISC_R_NOMORE) {
6733				LOCK_ZONE(zone);
6734				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6735						link);
6736				UNLOCK_ZONE(zone);
6737				ISC_LIST_APPEND(cleanup, nsec3chain, link);
6738				dns_dbiterator_pause(nsec3chain->dbiterator);
6739				result = fixup_nsec3param(db, version,
6740							  nsec3chain, ISC_FALSE,
6741							  privatetype,
6742							  &param_diff);
6743				if (result != ISC_R_SUCCESS) {
6744					dns_zone_log(zone, ISC_LOG_ERROR,
6745						     "zone_nsec3chain:"
6746						     "fixup_nsec3param -> %s",
6747						     dns_result_totext(result));
6748					goto failure;
6749				}
6750				goto next_removechain;
6751			} else if (result != ISC_R_SUCCESS) {
6752				dns_zone_log(zone, ISC_LOG_ERROR,
6753					     "zone_nsec3chain:"
6754					     "dns_dbiterator_next -> %s",
6755					     dns_result_totext(result));
6756				goto failure;
6757			} else if (delegation) {
6758				dns_dbiterator_current(nsec3chain->dbiterator,
6759						       &node, nextname);
6760				dns_db_detachnode(db, &node);
6761				if (!dns_name_issubdomain(nextname, name))
6762					break;
6763			} else
6764				break;
6765		} while (1);
6766		continue;
6767
6768 same_removechain:
6769		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6770		buildnsecchain = ISC_FALSE;
6771		first = ISC_TRUE;
6772		continue;
6773
6774 next_removechain:
6775		dns_dbiterator_pause(nsec3chain->dbiterator);
6776		nsec3chain = nextnsec3chain;
6777		first = ISC_TRUE;
6778	}
6779
6780	/*
6781	 * We may need to update the NSEC/NSEC3 records for the zone apex.
6782	 */
6783	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
6784		isc_boolean_t rebuild_nsec = ISC_FALSE,
6785			      rebuild_nsec3 = ISC_FALSE;
6786		result = dns_db_getoriginnode(db, &node);
6787		RUNTIME_CHECK(result == ISC_R_SUCCESS);
6788		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6789		if (result != ISC_R_SUCCESS) {
6790			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6791				     "dns_db_allrdatasets -> %s",
6792				     dns_result_totext(result));
6793			goto failure;
6794		}
6795		for (result = dns_rdatasetiter_first(iterator);
6796		     result == ISC_R_SUCCESS;
6797		     result = dns_rdatasetiter_next(iterator)) {
6798			dns_rdatasetiter_current(iterator, &rdataset);
6799			if (rdataset.type == dns_rdatatype_nsec)
6800				rebuild_nsec = ISC_TRUE;
6801			if (rdataset.type == dns_rdatatype_nsec3param)
6802				rebuild_nsec3 = ISC_TRUE;
6803			dns_rdataset_disassociate(&rdataset);
6804		}
6805		dns_rdatasetiter_destroy(&iterator);
6806		dns_db_detachnode(db, &node);
6807
6808		if (rebuild_nsec) {
6809			if (nsec3chain != NULL)
6810				dns_dbiterator_pause(nsec3chain->dbiterator);
6811			result = updatesecure(db, version, &zone->origin,
6812					      zone->minimum, ISC_TRUE,
6813					      &nsec_diff);
6814			if (result != ISC_R_SUCCESS) {
6815				dns_zone_log(zone, ISC_LOG_ERROR,
6816					     "zone_nsec3chain:"
6817					     "updatesecure -> %s",
6818					     dns_result_totext(result));
6819				goto failure;
6820			}
6821		}
6822		if (rebuild_nsec3) {
6823			result = dns_nsec3_addnsec3s(db, version,
6824						     dns_db_origin(db),
6825						     zone->minimum, ISC_FALSE,
6826						     &nsec3_diff);
6827			if (result != ISC_R_SUCCESS) {
6828				dns_zone_log(zone, ISC_LOG_ERROR,
6829					     "zone_nsec3chain:"
6830					     "dns_nsec3_addnsec3s -> %s",
6831					     dns_result_totext(result));
6832				goto failure;
6833			}
6834		}
6835	}
6836
6837	/*
6838	 * Add / update signatures for the NSEC3 records.
6839	 */
6840	result = update_sigs(&nsec3_diff, db, version, zone_keys,
6841			     nkeys, zone, inception, expire, now,
6842			     check_ksk, keyset_kskonly, &sig_diff);
6843	if (result != ISC_R_SUCCESS) {
6844		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6845			     "update_sigs -> %s", dns_result_totext(result));
6846		goto failure;
6847	}
6848
6849	/*
6850	 * We have changed the NSEC3PARAM or private RRsets
6851	 * above so we need to update the signatures.
6852	 */
6853	result = update_sigs(&param_diff, db, version, zone_keys,
6854			     nkeys, zone, inception, expire, now,
6855			     check_ksk, keyset_kskonly, &sig_diff);
6856	if (result != ISC_R_SUCCESS) {
6857		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6858			     "update_sigs -> %s", dns_result_totext(result));
6859		goto failure;
6860	}
6861
6862	if (updatensec) {
6863		if (nsec3chain != NULL)
6864			dns_dbiterator_pause(nsec3chain->dbiterator);
6865		result = updatesecure(db, version, &zone->origin,
6866				      zone->minimum, ISC_FALSE, &nsec_diff);
6867		if (result != ISC_R_SUCCESS) {
6868			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6869				     "updatesecure -> %s",
6870				     dns_result_totext(result));
6871			goto failure;
6872		}
6873	}
6874
6875	result = update_sigs(&nsec_diff, db, version, zone_keys,
6876			     nkeys, zone, inception, expire, now,
6877			     check_ksk, keyset_kskonly, &sig_diff);
6878	if (result != ISC_R_SUCCESS) {
6879		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6880			     "update_sigs -> %s", dns_result_totext(result));
6881		goto failure;
6882	}
6883
6884	/*
6885	 * If we made no effective changes to the zone then we can just
6886	 * cleanup otherwise we need to increment the serial.
6887	 */
6888	if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
6889		goto done;
6890
6891	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6892			  &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
6893	if (result != ISC_R_SUCCESS) {
6894		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6895			     "del_sigs -> %s", dns_result_totext(result));
6896		goto failure;
6897	}
6898
6899	result = update_soa_serial(db, version, &sig_diff, zone->mctx,
6900				   zone->updatemethod);
6901	if (result != ISC_R_SUCCESS) {
6902		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6903			     "update_soa_serial -> %s",
6904			     dns_result_totext(result));
6905		goto failure;
6906	}
6907
6908	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6909			  &sig_diff, zone_keys, nkeys, zone->mctx, inception,
6910			  soaexpire, check_ksk, keyset_kskonly);
6911	if (result != ISC_R_SUCCESS) {
6912		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6913			     "add_sigs -> %s", dns_result_totext(result));
6914		goto failure;
6915	}
6916
6917	/* Write changes to journal file. */
6918	CHECK(zone_journal(zone, &sig_diff, NULL, "zone_nsec3chain"));
6919
6920	LOCK_ZONE(zone);
6921	zone_needdump(zone, DNS_DUMP_DELAY);
6922	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6923	UNLOCK_ZONE(zone);
6924
6925 done:
6926	/*
6927	 * Pause all iterators so that dns_db_closeversion() can succeed.
6928	 */
6929	LOCK_ZONE(zone);
6930	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6931	     nsec3chain != NULL;
6932	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6933		dns_dbiterator_pause(nsec3chain->dbiterator);
6934	UNLOCK_ZONE(zone);
6935
6936	/*
6937	 * Everything has succeeded. Commit the changes.
6938	 */
6939	dns_db_closeversion(db, &version, ISC_TRUE);
6940
6941	/*
6942	 * Everything succeeded so we can clean these up now.
6943	 */
6944	nsec3chain = ISC_LIST_HEAD(cleanup);
6945	while (nsec3chain != NULL) {
6946		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6947		dns_db_detach(&nsec3chain->db);
6948		dns_dbiterator_destroy(&nsec3chain->dbiterator);
6949		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6950		nsec3chain = ISC_LIST_HEAD(cleanup);
6951	}
6952
6953	set_resigntime(zone);
6954
6955 failure:
6956	if (result != ISC_R_SUCCESS)
6957		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
6958			     dns_result_totext(result));
6959	/*
6960	 * On error roll back the current nsec3chain.
6961	 */
6962	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
6963		if (nsec3chain->done) {
6964			dns_db_detach(&nsec3chain->db);
6965			dns_dbiterator_destroy(&nsec3chain->dbiterator);
6966			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6967		} else {
6968			result = dns_dbiterator_first(nsec3chain->dbiterator);
6969			RUNTIME_CHECK(result == ISC_R_SUCCESS);
6970			dns_dbiterator_pause(nsec3chain->dbiterator);
6971			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6972		}
6973	}
6974
6975	/*
6976	 * Rollback the cleanup list.
6977	 */
6978	nsec3chain = ISC_LIST_TAIL(cleanup);
6979	while (nsec3chain != NULL) {
6980		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6981		if (nsec3chain->done) {
6982			dns_db_detach(&nsec3chain->db);
6983			dns_dbiterator_destroy(&nsec3chain->dbiterator);
6984			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6985		} else {
6986			LOCK_ZONE(zone);
6987			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
6988			UNLOCK_ZONE(zone);
6989			result = dns_dbiterator_first(nsec3chain->dbiterator);
6990			RUNTIME_CHECK(result == ISC_R_SUCCESS);
6991			dns_dbiterator_pause(nsec3chain->dbiterator);
6992			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6993		}
6994		nsec3chain = ISC_LIST_TAIL(cleanup);
6995	}
6996
6997	LOCK_ZONE(zone);
6998	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6999	     nsec3chain != NULL;
7000	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7001		dns_dbiterator_pause(nsec3chain->dbiterator);
7002	UNLOCK_ZONE(zone);
7003
7004	dns_diff_clear(&param_diff);
7005	dns_diff_clear(&nsec3_diff);
7006	dns_diff_clear(&nsec_diff);
7007	dns_diff_clear(&sig_diff);
7008
7009	if (iterator != NULL)
7010		dns_rdatasetiter_destroy(&iterator);
7011
7012	for (i = 0; i < nkeys; i++)
7013		dst_key_free(&zone_keys[i]);
7014
7015	if (node != NULL)
7016		dns_db_detachnode(db, &node);
7017	if (version != NULL) {
7018		dns_db_closeversion(db, &version, ISC_FALSE);
7019		dns_db_detach(&db);
7020	} else if (db != NULL)
7021		dns_db_detach(&db);
7022
7023	LOCK_ZONE(zone);
7024	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
7025		isc_interval_t i;
7026		if (zone->update_disabled || result != ISC_R_SUCCESS)
7027			isc_interval_set(&i, 60, 0);		/* 1 minute */
7028		else
7029			isc_interval_set(&i, 0, 10000000);	/* 10 ms */
7030		isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
7031	} else
7032		isc_time_settoepoch(&zone->nsec3chaintime);
7033	UNLOCK_ZONE(zone);
7034}
7035
7036static isc_result_t
7037del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7038	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
7039	isc_uint16_t keyid, dns_diff_t *diff)
7040{
7041	dns_rdata_rrsig_t rrsig;
7042	dns_rdataset_t rdataset;
7043	dns_rdatasetiter_t *iterator = NULL;
7044	isc_result_t result;
7045
7046	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7047	if (result != ISC_R_SUCCESS) {
7048		if (result == ISC_R_NOTFOUND)
7049			result = ISC_R_SUCCESS;
7050		return (result);
7051	}
7052
7053	dns_rdataset_init(&rdataset);
7054	for (result = dns_rdatasetiter_first(iterator);
7055	     result == ISC_R_SUCCESS;
7056	     result = dns_rdatasetiter_next(iterator)) {
7057		dns_rdatasetiter_current(iterator, &rdataset);
7058		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
7059			for (result = dns_rdataset_first(&rdataset);
7060			     result == ISC_R_SUCCESS;
7061			     result = dns_rdataset_next(&rdataset)) {
7062				dns_rdata_t rdata = DNS_RDATA_INIT;
7063				dns_rdataset_current(&rdataset, &rdata);
7064				CHECK(update_one_rr(db, version, diff,
7065						    DNS_DIFFOP_DEL, name,
7066						    rdataset.ttl, &rdata));
7067			}
7068			if (result != ISC_R_NOMORE)
7069				goto failure;
7070			dns_rdataset_disassociate(&rdataset);
7071			continue;
7072		}
7073		if (rdataset.type != dns_rdatatype_rrsig) {
7074			dns_rdataset_disassociate(&rdataset);
7075			continue;
7076		}
7077		for (result = dns_rdataset_first(&rdataset);
7078		     result == ISC_R_SUCCESS;
7079		     result = dns_rdataset_next(&rdataset)) {
7080			dns_rdata_t rdata = DNS_RDATA_INIT;
7081			dns_rdataset_current(&rdataset, &rdata);
7082			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
7083			if (rrsig.algorithm != algorithm ||
7084			    rrsig.keyid != keyid)
7085				continue;
7086			CHECK(update_one_rr(db, version, diff,
7087					    DNS_DIFFOP_DELRESIGN, name,
7088					    rdataset.ttl, &rdata));
7089		}
7090		dns_rdataset_disassociate(&rdataset);
7091		if (result != ISC_R_NOMORE)
7092			break;
7093	}
7094	if (result == ISC_R_NOMORE)
7095		result = ISC_R_SUCCESS;
7096 failure:
7097	if (dns_rdataset_isassociated(&rdataset))
7098		dns_rdataset_disassociate(&rdataset);
7099	dns_rdatasetiter_destroy(&iterator);
7100	return (result);
7101}
7102
7103/*
7104 * Incrementally sign the zone using the keys requested.
7105 * Builds the NSEC chain if required.
7106 */
7107static void
7108zone_sign(dns_zone_t *zone) {
7109	dns_db_t *db = NULL;
7110	dns_dbnode_t *node = NULL;
7111	dns_dbversion_t *version = NULL;
7112	dns_diff_t sig_diff;
7113	dns_diff_t post_diff;
7114	dns_fixedname_t fixed;
7115	dns_fixedname_t nextfixed;
7116	dns_name_t *name, *nextname;
7117	dns_rdataset_t rdataset;
7118	dns_signing_t *signing, *nextsigning;
7119	dns_signinglist_t cleanup;
7120	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7121	isc_int32_t signatures;
7122	isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
7123	isc_boolean_t commit = ISC_FALSE;
7124	isc_boolean_t delegation;
7125	isc_boolean_t build_nsec = ISC_FALSE;
7126	isc_boolean_t build_nsec3 = ISC_FALSE;
7127	isc_boolean_t first;
7128	isc_result_t result;
7129	isc_stdtime_t now, inception, soaexpire, expire;
7130	isc_uint32_t jitter;
7131	unsigned int i, j;
7132	unsigned int nkeys = 0;
7133	isc_uint32_t nodes;
7134
7135	dns_rdataset_init(&rdataset);
7136	dns_fixedname_init(&fixed);
7137	name = dns_fixedname_name(&fixed);
7138	dns_fixedname_init(&nextfixed);
7139	nextname = dns_fixedname_name(&nextfixed);
7140	dns_diff_init(zone->mctx, &sig_diff);
7141	sig_diff.resign = zone->sigresigninginterval;
7142	dns_diff_init(zone->mctx, &post_diff);
7143	ISC_LIST_INIT(cleanup);
7144
7145	/*
7146	 * Updates are disabled.  Pause for 5 minutes.
7147	 */
7148	if (zone->update_disabled) {
7149		result = ISC_R_FAILURE;
7150		goto failure;
7151	}
7152
7153	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7154	dns_db_attach(zone->db, &db);
7155	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7156
7157	result = dns_db_newversion(db, &version);
7158	if (result != ISC_R_SUCCESS) {
7159		dns_zone_log(zone, ISC_LOG_ERROR,
7160			     "zone_sign:dns_db_newversion -> %s",
7161			     dns_result_totext(result));
7162		goto failure;
7163	}
7164
7165	result = find_zone_keys(zone, db, version, zone->mctx,
7166				DNS_MAXZONEKEYS, zone_keys, &nkeys);
7167	if (result != ISC_R_SUCCESS) {
7168		dns_zone_log(zone, ISC_LOG_ERROR,
7169			     "zone_sign:find_zone_keys -> %s",
7170			     dns_result_totext(result));
7171		goto failure;
7172	}
7173
7174	isc_stdtime_get(&now);
7175	inception = now - 3600;	/* Allow for clock skew. */
7176	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
7177
7178	/*
7179	 * Spread out signatures over time if they happen to be
7180	 * clumped.  We don't do this for each add_sigs() call as
7181	 * we still want some clustering to occur.
7182	 */
7183	isc_random_get(&jitter);
7184	expire = soaexpire - jitter % 3600;
7185
7186	/*
7187	 * We keep pulling nodes off each iterator in turn until
7188	 * we have no more nodes to pull off or we reach the limits
7189	 * for this quantum.
7190	 */
7191	nodes = zone->nodes;
7192	signatures = zone->signatures;
7193	signing = ISC_LIST_HEAD(zone->signing);
7194	first = ISC_TRUE;
7195
7196	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7197	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7198
7199	/* Determine which type of chain to build */
7200	CHECK(dns_private_chains(db, version, zone->privatetype,
7201				 &build_nsec, &build_nsec3));
7202
7203	/* If neither chain is found, default to NSEC */
7204	if (!build_nsec && !build_nsec3)
7205		build_nsec = ISC_TRUE;
7206
7207	while (signing != NULL && nodes-- > 0 && signatures > 0) {
7208		nextsigning = ISC_LIST_NEXT(signing, link);
7209
7210		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7211		if (signing->done || signing->db != zone->db) {
7212			/*
7213			 * The zone has been reloaded.	We will have
7214			 * created new signings as part of the reload
7215			 * process so we can destroy this one.
7216			 */
7217			ISC_LIST_UNLINK(zone->signing, signing, link);
7218			ISC_LIST_APPEND(cleanup, signing, link);
7219			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7220			goto next_signing;
7221		}
7222		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7223
7224		if (signing->db != db)
7225			goto next_signing;
7226
7227		delegation = ISC_FALSE;
7228
7229		if (first && signing->delete) {
7230			/*
7231			 * Remove the key we are deleting from consideration.
7232			 */
7233			for (i = 0, j = 0; i < nkeys; i++) {
7234				/*
7235				 * Find the key we want to remove.
7236				 */
7237				if (ALG(zone_keys[i]) == signing->algorithm &&
7238				    dst_key_id(zone_keys[i]) == signing->keyid)
7239				{
7240					if (KSK(zone_keys[i]))
7241						dst_key_free(&zone_keys[i]);
7242					continue;
7243				}
7244				zone_keys[j] = zone_keys[i];
7245				j++;
7246			}
7247			nkeys = j;
7248		}
7249
7250		dns_dbiterator_current(signing->dbiterator, &node, name);
7251
7252		if (signing->delete) {
7253			dns_dbiterator_pause(signing->dbiterator);
7254			CHECK(del_sig(db, version, name, node, nkeys,
7255				      signing->algorithm, signing->keyid,
7256				      &sig_diff));
7257		}
7258
7259		/*
7260		 * On the first pass we need to check if the current node
7261		 * has not been obscured.
7262		 */
7263		if (first) {
7264			dns_fixedname_t ffound;
7265			dns_name_t *found;
7266			dns_fixedname_init(&ffound);
7267			found = dns_fixedname_name(&ffound);
7268			result = dns_db_find(db, name, version,
7269					     dns_rdatatype_soa,
7270					     DNS_DBFIND_NOWILD, 0, NULL, found,
7271					     NULL, NULL);
7272			if ((result == DNS_R_DELEGATION ||
7273			    result == DNS_R_DNAME) &&
7274			    !dns_name_equal(name, found)) {
7275				/*
7276				 * Remember the obscuring name so that
7277				 * we skip all obscured names.
7278				 */
7279				dns_name_copy(found, name, NULL);
7280				delegation = ISC_TRUE;
7281				goto next_node;
7282			}
7283		}
7284
7285		/*
7286		 * Process one node.
7287		 */
7288		dns_dbiterator_pause(signing->dbiterator);
7289		for (i = 0; i < nkeys; i++) {
7290			isc_boolean_t both = ISC_FALSE;
7291
7292			/*
7293			 * Find the keys we want to sign with.
7294			 */
7295			if (!dst_key_isprivate(zone_keys[i]))
7296				continue;
7297
7298			/*
7299			 * When adding look for the specific key.
7300			 */
7301			if (!signing->delete &&
7302			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
7303			     dst_key_id(zone_keys[i]) != signing->keyid))
7304				continue;
7305
7306			/*
7307			 * When deleting make sure we are properly signed
7308			 * with the algorithm that was being removed.
7309			 */
7310			if (signing->delete &&
7311			    ALG(zone_keys[i]) != signing->algorithm)
7312				continue;
7313
7314			/*
7315			 * Do we do KSK processing?
7316			 */
7317			if (check_ksk && !REVOKE(zone_keys[i])) {
7318				isc_boolean_t have_ksk, have_nonksk;
7319				if (KSK(zone_keys[i])) {
7320					have_ksk = ISC_TRUE;
7321					have_nonksk = ISC_FALSE;
7322				} else {
7323					have_ksk = ISC_FALSE;
7324					have_nonksk = ISC_TRUE;
7325				}
7326				for (j = 0; j < nkeys; j++) {
7327					if (j == i ||
7328					    ALG(zone_keys[i]) !=
7329					    ALG(zone_keys[j]))
7330						continue;
7331					if (REVOKE(zone_keys[j]))
7332						continue;
7333					if (KSK(zone_keys[j]))
7334						have_ksk = ISC_TRUE;
7335					else
7336						have_nonksk = ISC_TRUE;
7337					both = have_ksk && have_nonksk;
7338					if (both)
7339						break;
7340				}
7341			}
7342			if (both || REVOKE(zone_keys[i]))
7343				is_ksk = KSK(zone_keys[i]);
7344			else
7345				is_ksk = ISC_FALSE;
7346
7347			CHECK(sign_a_node(db, name, node, version, build_nsec3,
7348					  build_nsec, zone_keys[i], inception,
7349					  expire, zone->minimum, is_ksk,
7350					  ISC_TF(both && keyset_kskonly),
7351					  &delegation, &sig_diff,
7352					  &signatures, zone->mctx));
7353			/*
7354			 * If we are adding we are done.  Look for other keys
7355			 * of the same algorithm if deleting.
7356			 */
7357			if (!signing->delete)
7358				break;
7359		}
7360
7361		/*
7362		 * Go onto next node.
7363		 */
7364 next_node:
7365		first = ISC_FALSE;
7366		dns_db_detachnode(db, &node);
7367		do {
7368			result = dns_dbiterator_next(signing->dbiterator);
7369			if (result == ISC_R_NOMORE) {
7370				ISC_LIST_UNLINK(zone->signing, signing, link);
7371				ISC_LIST_APPEND(cleanup, signing, link);
7372				dns_dbiterator_pause(signing->dbiterator);
7373				if (nkeys != 0 && build_nsec) {
7374					/*
7375					 * We have finished regenerating the
7376					 * zone with a zone signing key.
7377					 * The NSEC chain is now complete and
7378					 * there is a full set of signatures
7379					 * for the zone.  We can now clear the
7380					 * OPT bit from the NSEC record.
7381					 */
7382					result = updatesecure(db, version,
7383							      &zone->origin,
7384							      zone->minimum,
7385							      ISC_FALSE,
7386							      &post_diff);
7387					if (result != ISC_R_SUCCESS) {
7388						dns_zone_log(zone,
7389							     ISC_LOG_ERROR,
7390						    "updatesecure -> %s",
7391						    dns_result_totext(result));
7392						goto failure;
7393					}
7394				}
7395				result = updatesignwithkey(zone, signing,
7396							   version,
7397							   build_nsec3,
7398							   zone->minimum,
7399							   &post_diff);
7400				if (result != ISC_R_SUCCESS) {
7401					dns_zone_log(zone, ISC_LOG_ERROR,
7402						     "updatesignwithkey -> %s",
7403						     dns_result_totext(result));
7404					goto failure;
7405				}
7406				build_nsec = ISC_FALSE;
7407				goto next_signing;
7408			} else if (result != ISC_R_SUCCESS) {
7409				dns_zone_log(zone, ISC_LOG_ERROR,
7410					"zone_sign:dns_dbiterator_next -> %s",
7411					     dns_result_totext(result));
7412				goto failure;
7413			} else if (delegation) {
7414				dns_dbiterator_current(signing->dbiterator,
7415						       &node, nextname);
7416				dns_db_detachnode(db, &node);
7417				if (!dns_name_issubdomain(nextname, name))
7418					break;
7419			} else
7420				break;
7421		} while (1);
7422		continue;
7423
7424 next_signing:
7425		dns_dbiterator_pause(signing->dbiterator);
7426		signing = nextsigning;
7427		first = ISC_TRUE;
7428	}
7429
7430	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
7431		result = update_sigs(&post_diff, db, version, zone_keys,
7432				     nkeys, zone, inception, expire, now,
7433				     check_ksk, keyset_kskonly, &sig_diff);
7434		if (result != ISC_R_SUCCESS) {
7435			dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
7436				     "update_sigs -> %s",
7437				     dns_result_totext(result));
7438			goto failure;
7439		}
7440	}
7441
7442	/*
7443	 * Have we changed anything?
7444	 */
7445	if (ISC_LIST_HEAD(sig_diff.tuples) == NULL) {
7446		result = ISC_R_SUCCESS;
7447		goto pauseall;
7448	}
7449
7450	commit = ISC_TRUE;
7451
7452	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7453			  &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
7454	if (result != ISC_R_SUCCESS) {
7455		dns_zone_log(zone, ISC_LOG_ERROR,
7456			     "zone_sign:del_sigs -> %s",
7457			     dns_result_totext(result));
7458		goto failure;
7459	}
7460
7461	result = update_soa_serial(db, version, &sig_diff, zone->mctx,
7462				   zone->updatemethod);
7463	if (result != ISC_R_SUCCESS) {
7464		dns_zone_log(zone, ISC_LOG_ERROR,
7465			     "zone_sign:update_soa_serial -> %s",
7466			     dns_result_totext(result));
7467		goto failure;
7468	}
7469
7470	/*
7471	 * Generate maximum life time signatures so that the above loop
7472	 * termination is sensible.
7473	 */
7474	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7475			  &sig_diff, zone_keys, nkeys, zone->mctx, inception,
7476			  soaexpire, check_ksk, keyset_kskonly);
7477	if (result != ISC_R_SUCCESS) {
7478		dns_zone_log(zone, ISC_LOG_ERROR,
7479			     "zone_sign:add_sigs -> %s",
7480			     dns_result_totext(result));
7481		goto failure;
7482	}
7483
7484	/*
7485	 * Write changes to journal file.
7486	 */
7487	CHECK(zone_journal(zone, &sig_diff, NULL, "zone_sign"));
7488
7489 pauseall:
7490	/*
7491	 * Pause all iterators so that dns_db_closeversion() can succeed.
7492	 */
7493	for (signing = ISC_LIST_HEAD(zone->signing);
7494	     signing != NULL;
7495	     signing = ISC_LIST_NEXT(signing, link))
7496		dns_dbiterator_pause(signing->dbiterator);
7497
7498	for (signing = ISC_LIST_HEAD(cleanup);
7499	     signing != NULL;
7500	     signing = ISC_LIST_NEXT(signing, link))
7501		dns_dbiterator_pause(signing->dbiterator);
7502
7503	/*
7504	 * Everything has succeeded. Commit the changes.
7505	 */
7506	dns_db_closeversion(db, &version, commit);
7507
7508	/*
7509	 * Everything succeeded so we can clean these up now.
7510	 */
7511	signing = ISC_LIST_HEAD(cleanup);
7512	while (signing != NULL) {
7513		ISC_LIST_UNLINK(cleanup, signing, link);
7514		dns_db_detach(&signing->db);
7515		dns_dbiterator_destroy(&signing->dbiterator);
7516		isc_mem_put(zone->mctx, signing, sizeof *signing);
7517		signing = ISC_LIST_HEAD(cleanup);
7518	}
7519
7520	set_resigntime(zone);
7521
7522	if (commit) {
7523		LOCK_ZONE(zone);
7524		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7525		zone_needdump(zone, DNS_DUMP_DELAY);
7526		UNLOCK_ZONE(zone);
7527	}
7528
7529 failure:
7530	/*
7531	 * Rollback the cleanup list.
7532	 */
7533	signing = ISC_LIST_HEAD(cleanup);
7534	while (signing != NULL) {
7535		ISC_LIST_UNLINK(cleanup, signing, link);
7536		ISC_LIST_PREPEND(zone->signing, signing, link);
7537		dns_dbiterator_first(signing->dbiterator);
7538		dns_dbiterator_pause(signing->dbiterator);
7539		signing = ISC_LIST_HEAD(cleanup);
7540	}
7541
7542	for (signing = ISC_LIST_HEAD(zone->signing);
7543	     signing != NULL;
7544	     signing = ISC_LIST_NEXT(signing, link))
7545		dns_dbiterator_pause(signing->dbiterator);
7546
7547	dns_diff_clear(&sig_diff);
7548
7549	for (i = 0; i < nkeys; i++)
7550		dst_key_free(&zone_keys[i]);
7551
7552	if (node != NULL)
7553		dns_db_detachnode(db, &node);
7554
7555	if (version != NULL) {
7556		dns_db_closeversion(db, &version, ISC_FALSE);
7557		dns_db_detach(&db);
7558	} else if (db != NULL)
7559		dns_db_detach(&db);
7560
7561	if (ISC_LIST_HEAD(zone->signing) != NULL) {
7562		isc_interval_t i;
7563		if (zone->update_disabled || result != ISC_R_SUCCESS)
7564			isc_interval_set(&i, 60, 0);		/* 1 minute */
7565		else
7566			isc_interval_set(&i, 0, 10000000);	/* 10 ms */
7567		isc_time_nowplusinterval(&zone->signingtime, &i);
7568	} else
7569		isc_time_settoepoch(&zone->signingtime);
7570}
7571
7572static void
7573normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
7574	      unsigned char *data, int size) {
7575	dns_rdata_dnskey_t dnskey;
7576	dns_rdata_keydata_t keydata;
7577	isc_buffer_t buf;
7578
7579	dns_rdata_reset(target);
7580	isc_buffer_init(&buf, data, size);
7581
7582	switch (rr->type) {
7583	    case dns_rdatatype_dnskey:
7584		dns_rdata_tostruct(rr, &dnskey, NULL);
7585		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
7586		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7587				     &dnskey, &buf);
7588		break;
7589	    case dns_rdatatype_keydata:
7590		dns_rdata_tostruct(rr, &keydata, NULL);
7591		dns_keydata_todnskey(&keydata, &dnskey, NULL);
7592		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7593				     &dnskey, &buf);
7594		break;
7595	    default:
7596		INSIST(0);
7597	}
7598}
7599
7600/*
7601 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
7602 * a KEYDATA rdataset from the key zone.
7603 *
7604 * 'rr' contains either a DNSKEY record, or a KEYDATA record
7605 *
7606 * After normalizing keys to the same format (DNSKEY, with revoke bit
7607 * cleared), return ISC_TRUE if a key that matches 'rr' is found in
7608 * 'rdset', or ISC_FALSE if not.
7609 */
7610
7611static isc_boolean_t
7612matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
7613	unsigned char data1[4096], data2[4096];
7614	dns_rdata_t rdata, rdata1, rdata2;
7615	isc_result_t result;
7616
7617	dns_rdata_init(&rdata);
7618	dns_rdata_init(&rdata1);
7619	dns_rdata_init(&rdata2);
7620
7621	normalize_key(rr, &rdata1, data1, sizeof(data1));
7622
7623	for (result = dns_rdataset_first(rdset);
7624	     result == ISC_R_SUCCESS;
7625	     result = dns_rdataset_next(rdset)) {
7626		dns_rdata_reset(&rdata);
7627		dns_rdataset_current(rdset, &rdata);
7628		normalize_key(&rdata, &rdata2, data2, sizeof(data2));
7629		if (dns_rdata_compare(&rdata1, &rdata2) == 0)
7630			return (ISC_TRUE);
7631	}
7632
7633	return (ISC_FALSE);
7634}
7635
7636/*
7637 * Calculate the refresh interval for a keydata zone, per
7638 * RFC5011: MAX(1 hr,
7639 *		MIN(15 days,
7640 *		    1/2 * OrigTTL,
7641 *		    1/2 * RRSigExpirationInterval))
7642 * or for retries: MAX(1 hr,
7643 *		       MIN(1 day,
7644 *			   1/10 * OrigTTL,
7645 *			   1/10 * RRSigExpirationInterval))
7646 */
7647static inline isc_stdtime_t
7648refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
7649	isc_result_t result;
7650	isc_uint32_t t;
7651	dns_rdataset_t *rdset;
7652	dns_rdata_t sigrr = DNS_RDATA_INIT;
7653	dns_rdata_sig_t sig;
7654	isc_stdtime_t now;
7655
7656	isc_stdtime_get(&now);
7657
7658	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7659		rdset = &kfetch->dnskeysigset;
7660	else
7661		return (now + HOUR);
7662
7663	result = dns_rdataset_first(rdset);
7664	if (result != ISC_R_SUCCESS)
7665		return (now + HOUR);
7666
7667	dns_rdataset_current(rdset, &sigrr);
7668	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7669	RUNTIME_CHECK(result == ISC_R_SUCCESS);
7670
7671	if (!retry) {
7672		t = sig.originalttl / 2;
7673
7674		if (isc_serial_gt(sig.timeexpire, now)) {
7675			isc_uint32_t exp = (sig.timeexpire - now) / 2;
7676			if (t > exp)
7677				t = exp;
7678		}
7679
7680		if (t > (15*DAY))
7681			t = (15*DAY);
7682
7683		if (t < HOUR)
7684			t = HOUR;
7685	} else {
7686		t = sig.originalttl / 10;
7687
7688		if (isc_serial_gt(sig.timeexpire, now)) {
7689			isc_uint32_t exp = (sig.timeexpire - now) / 10;
7690			if (t > exp)
7691				t = exp;
7692		}
7693
7694		if (t > DAY)
7695			t = DAY;
7696
7697		if (t < HOUR)
7698			t = HOUR;
7699	}
7700
7701	return (now + t);
7702}
7703
7704/*
7705 * This routine is called when no changes are needed in a KEYDATA
7706 * record except to simply update the refresh timer.  Caller should
7707 * hold zone lock.
7708 */
7709static isc_result_t
7710minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
7711{
7712	isc_result_t result;
7713	isc_buffer_t keyb;
7714	unsigned char key_buf[4096];
7715	dns_rdata_t rdata = DNS_RDATA_INIT;
7716	dns_rdata_keydata_t keydata;
7717	dns_name_t *name;
7718	dns_zone_t *zone = kfetch->zone;
7719	isc_stdtime_t now;
7720
7721	name = dns_fixedname_name(&kfetch->name);
7722	isc_stdtime_get(&now);
7723
7724	for (result = dns_rdataset_first(&kfetch->keydataset);
7725	     result == ISC_R_SUCCESS;
7726	     result = dns_rdataset_next(&kfetch->keydataset)) {
7727		dns_rdata_reset(&rdata);
7728		dns_rdataset_current(&kfetch->keydataset, &rdata);
7729
7730		/* Delete old version */
7731		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
7732				    name, 0, &rdata));
7733
7734		/* Update refresh timer */
7735		CHECK(dns_rdata_tostruct(&rdata, &keydata, NULL));
7736		keydata.refresh = refresh_time(kfetch, ISC_TRUE);
7737		set_refreshkeytimer(zone, &keydata, now);
7738
7739		dns_rdata_reset(&rdata);
7740		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7741		CHECK(dns_rdata_fromstruct(&rdata,
7742					   zone->rdclass, dns_rdatatype_keydata,
7743					   &keydata, &keyb));
7744
7745		/* Insert updated version */
7746		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
7747				    name, 0, &rdata));
7748	}
7749	result = ISC_R_SUCCESS;
7750  failure:
7751	return (result);
7752}
7753
7754/*
7755 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
7756 */
7757static isc_boolean_t
7758revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
7759	isc_result_t result;
7760	dns_name_t *keyname;
7761	isc_mem_t *mctx;
7762	dns_rdata_t sigrr = DNS_RDATA_INIT;
7763	dns_rdata_t rr = DNS_RDATA_INIT;
7764	dns_rdata_rrsig_t sig;
7765	dns_rdata_dnskey_t dnskey;
7766	dst_key_t *dstkey = NULL;
7767	unsigned char key_buf[4096];
7768	isc_buffer_t keyb;
7769	isc_boolean_t answer = ISC_FALSE;
7770
7771	REQUIRE(kfetch != NULL && keydata != NULL);
7772	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
7773
7774	keyname = dns_fixedname_name(&kfetch->name);
7775	mctx = kfetch->zone->view->mctx;
7776
7777	/* Generate a key from keydata */
7778	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7779	dns_keydata_todnskey(keydata, &dnskey, NULL);
7780	dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
7781				     &dnskey, &keyb);
7782	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
7783	if (result != ISC_R_SUCCESS)
7784		return (ISC_FALSE);
7785
7786	/* See if that key generated any of the signatures */
7787	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7788	     result == ISC_R_SUCCESS;
7789	     result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7790		dns_fixedname_t fixed;
7791		dns_fixedname_init(&fixed);
7792
7793		dns_rdata_reset(&sigrr);
7794		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7795		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7796		RUNTIME_CHECK(result == ISC_R_SUCCESS);
7797
7798		if (dst_key_alg(dstkey) == sig.algorithm &&
7799		    (dst_key_id(dstkey) == sig.keyid ||
7800		     dst_key_rid(dstkey) == sig.keyid)) {
7801			result = dns_dnssec_verify2(keyname,
7802					    &kfetch->dnskeyset,
7803					    dstkey, ISC_FALSE, mctx, &sigrr,
7804					    dns_fixedname_name(&fixed));
7805
7806			dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
7807				     "Confirm revoked DNSKEY is self-signed: "
7808				     "%s", dns_result_totext(result));
7809
7810			if (result == ISC_R_SUCCESS) {
7811				answer = ISC_TRUE;
7812				break;
7813			}
7814		}
7815	}
7816
7817	dst_key_free(&dstkey);
7818	return (answer);
7819}
7820
7821/*
7822 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
7823 * anchors are being managed; scan the keyset, and update the key zone and the
7824 * local trust anchors according to RFC5011.
7825 */
7826static void
7827keyfetch_done(isc_task_t *task, isc_event_t *event) {
7828	isc_result_t result, eresult;
7829	dns_fetchevent_t *devent;
7830	dns_keyfetch_t *kfetch;
7831	dns_zone_t *zone;
7832	isc_mem_t *mctx = NULL;
7833	dns_keytable_t *secroots = NULL;
7834	dns_dbversion_t *ver = NULL;
7835	dns_diff_t diff;
7836	isc_boolean_t alldone = ISC_FALSE;
7837	isc_boolean_t commit = ISC_FALSE;
7838	dns_name_t *keyname;
7839	dns_rdata_t sigrr = DNS_RDATA_INIT;
7840	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
7841	dns_rdata_t keydatarr = DNS_RDATA_INIT;
7842	dns_rdata_rrsig_t sig;
7843	dns_rdata_dnskey_t dnskey;
7844	dns_rdata_keydata_t keydata;
7845	isc_boolean_t initializing;
7846	char namebuf[DNS_NAME_FORMATSIZE];
7847	unsigned char key_buf[4096];
7848	isc_buffer_t keyb;
7849	dst_key_t *dstkey;
7850	isc_stdtime_t now;
7851	int pending = 0;
7852	isc_boolean_t secure;
7853	isc_boolean_t free_needed;
7854
7855	UNUSED(task);
7856	INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
7857	INSIST(event->ev_arg != NULL);
7858
7859	kfetch = event->ev_arg;
7860	zone = kfetch->zone;
7861	isc_mem_attach(zone->mctx, &mctx);
7862	keyname = dns_fixedname_name(&kfetch->name);
7863
7864	devent = (dns_fetchevent_t *) event;
7865	eresult = devent->result;
7866
7867	/* Free resources which are not of interest */
7868	if (devent->node != NULL)
7869		dns_db_detachnode(devent->db, &devent->node);
7870	if (devent->db != NULL)
7871		dns_db_detach(&devent->db);
7872	isc_event_free(&event);
7873	dns_resolver_destroyfetch(&kfetch->fetch);
7874
7875	LOCK_ZONE(zone);
7876	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
7877		goto cleanup;
7878
7879	isc_stdtime_get(&now);
7880	dns_name_format(keyname, namebuf, sizeof(namebuf));
7881
7882	result = dns_view_getsecroots(zone->view, &secroots);
7883	INSIST(result == ISC_R_SUCCESS);
7884
7885	dns_diff_init(mctx, &diff);
7886	diff.resign = zone->sigresigninginterval;
7887
7888	CHECK(dns_db_newversion(kfetch->db, &ver));
7889
7890	zone->refreshkeycount--;
7891	alldone = ISC_TF(zone->refreshkeycount == 0);
7892
7893	if (alldone)
7894		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
7895
7896	/* Fetch failed */
7897	if (eresult != ISC_R_SUCCESS ||
7898	    !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
7899		dns_zone_log(zone, ISC_LOG_WARNING,
7900			     "Unable to fetch DNSKEY set "
7901			     "'%s': %s", namebuf, dns_result_totext(eresult));
7902		CHECK(minimal_update(kfetch, ver, &diff));
7903		goto done;
7904	}
7905
7906	/* No RRSIGs found */
7907	if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
7908		dns_zone_log(zone, ISC_LOG_WARNING,
7909			     "No DNSKEY RRSIGs found for "
7910			     "'%s': %s", namebuf, dns_result_totext(eresult));
7911		CHECK(minimal_update(kfetch, ver, &diff));
7912		goto done;
7913	}
7914
7915	/*
7916	 * Validate the dnskeyset against the current trusted keys.
7917	 */
7918	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7919	     result == ISC_R_SUCCESS;
7920	     result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7921		dns_keynode_t *keynode = NULL;
7922
7923		dns_rdata_reset(&sigrr);
7924		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7925		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7926		RUNTIME_CHECK(result == ISC_R_SUCCESS);
7927
7928		result = dns_keytable_find(secroots, keyname, &keynode);
7929		while (result == ISC_R_SUCCESS) {
7930			dns_keynode_t *nextnode = NULL;
7931			dns_fixedname_t fixed;
7932			dns_fixedname_init(&fixed);
7933
7934			dstkey = dns_keynode_key(keynode);
7935			if (dstkey == NULL) /* fail_secure() was called */
7936				break;
7937
7938			if (dst_key_alg(dstkey) == sig.algorithm &&
7939			    dst_key_id(dstkey) == sig.keyid) {
7940				result = dns_dnssec_verify2(keyname,
7941						    &kfetch->dnskeyset,
7942						    dstkey, ISC_FALSE,
7943						    zone->view->mctx, &sigrr,
7944						    dns_fixedname_name(&fixed));
7945
7946				dns_zone_log(zone, ISC_LOG_DEBUG(3),
7947					     "Verifying DNSKEY set for zone "
7948					     "'%s': %s", namebuf,
7949					     dns_result_totext(result));
7950
7951				if (result == ISC_R_SUCCESS) {
7952					kfetch->dnskeyset.trust =
7953						dns_trust_secure;
7954					kfetch->dnskeysigset.trust =
7955						dns_trust_secure;
7956					dns_keytable_detachkeynode(secroots,
7957								   &keynode);
7958					break;
7959				}
7960			}
7961
7962			result = dns_keytable_nextkeynode(secroots,
7963							  keynode, &nextnode);
7964			dns_keytable_detachkeynode(secroots, &keynode);
7965			keynode = nextnode;
7966		}
7967
7968		if (kfetch->dnskeyset.trust == dns_trust_secure)
7969			break;
7970	}
7971
7972	/*
7973	 * If we were not able to verify the answer using the current
7974	 * trusted keys then all we can do is look at any revoked keys.
7975	 */
7976	secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
7977
7978	/*
7979	 * First scan keydataset to find keys that are not in dnskeyset
7980	 *   - Missing keys which are not scheduled for removal,
7981	 *     log a warning
7982	 *   - Missing keys which are scheduled for removal and
7983	 *     the remove hold-down timer has completed should
7984	 *     be removed from the key zone
7985	 *   - Missing keys whose acceptance timers have not yet
7986	 *     completed, log a warning and reset the acceptance
7987	 *     timer to 30 days in the future
7988	 *   - All keys not being removed have their refresh timers
7989	 *     updated
7990	 */
7991	initializing = ISC_TRUE;
7992	for (result = dns_rdataset_first(&kfetch->keydataset);
7993	     result == ISC_R_SUCCESS;
7994	     result = dns_rdataset_next(&kfetch->keydataset)) {
7995		dns_rdata_reset(&keydatarr);
7996		dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7997		dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7998
7999		/*
8000		 * If any keydata record has a nonzero add holddown, then
8001		 * there was a pre-existing trust anchor for this domain;
8002		 * that means we are *not* initializing it and shouldn't
8003		 * automatically trust all the keys we find at the zone apex.
8004		 */
8005		initializing = initializing && ISC_TF(keydata.addhd == 0);
8006
8007		if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
8008			isc_boolean_t deletekey = ISC_FALSE;
8009
8010			if (!secure) {
8011				if (now > keydata.removehd)
8012					deletekey = ISC_TRUE;
8013			} else if (now < keydata.addhd) {
8014				dns_zone_log(zone, ISC_LOG_WARNING,
8015					     "Pending key unexpectedly missing "
8016					     "from %s; restarting acceptance "
8017					     "timer", namebuf);
8018				keydata.addhd = now + MONTH;
8019				keydata.refresh = refresh_time(kfetch,
8020							       ISC_FALSE);
8021			} else if (keydata.addhd == 0) {
8022				keydata.addhd = now;
8023			} else if (keydata.removehd == 0) {
8024				dns_zone_log(zone, ISC_LOG_WARNING,
8025					     "Active key unexpectedly missing "
8026					     "from %s", namebuf);
8027				keydata.refresh = now + HOUR;
8028			} else if (now > keydata.removehd) {
8029				deletekey = ISC_TRUE;
8030			} else {
8031				keydata.refresh = refresh_time(kfetch,
8032							       ISC_FALSE);
8033			}
8034
8035			if  (secure || deletekey) {
8036				/* Delete old version */
8037				CHECK(update_one_rr(kfetch->db, ver, &diff,
8038						    DNS_DIFFOP_DEL, keyname, 0,
8039						    &keydatarr));
8040			}
8041
8042			if (!secure || deletekey)
8043				continue;
8044
8045			dns_rdata_reset(&keydatarr);
8046			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8047			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8048					     dns_rdatatype_keydata,
8049					     &keydata, &keyb);
8050
8051			/* Insert updated version */
8052			CHECK(update_one_rr(kfetch->db, ver, &diff,
8053					    DNS_DIFFOP_ADD, keyname, 0,
8054					    &keydatarr));
8055
8056			set_refreshkeytimer(zone, &keydata, now);
8057		}
8058	}
8059
8060	/*
8061	 * Next scan dnskeyset:
8062	 *   - If new keys are found (i.e., lacking a match in keydataset)
8063	 *     add them to the key zone and set the acceptance timer
8064	 *     to 30 days in the future (or to immediately if we've
8065	 *     determined that we're initializing the zone for the
8066	 *     first time)
8067	 *   - Previously-known keys that have been revoked
8068	 *     must be scheduled for removal from the key zone (or,
8069	 *     if they hadn't been accepted as trust anchors yet
8070	 *     anyway, removed at once)
8071	 *   - Previously-known unrevoked keys whose acceptance timers
8072	 *     have completed are promoted to trust anchors
8073	 *   - All keys not being removed have their refresh
8074	 *     timers updated
8075	 */
8076	for (result = dns_rdataset_first(&kfetch->dnskeyset);
8077	     result == ISC_R_SUCCESS;
8078	     result = dns_rdataset_next(&kfetch->dnskeyset)) {
8079		isc_boolean_t revoked = ISC_FALSE;
8080		isc_boolean_t newkey = ISC_FALSE;
8081		isc_boolean_t updatekey = ISC_FALSE;
8082		isc_boolean_t deletekey = ISC_FALSE;
8083		isc_boolean_t trustkey = ISC_FALSE;
8084
8085		dns_rdata_reset(&dnskeyrr);
8086		dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
8087		dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8088
8089		/* Skip ZSK's */
8090		if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
8091			continue;
8092
8093		revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
8094
8095		if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
8096			dns_rdata_reset(&keydatarr);
8097			dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8098			dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8099
8100			if (revoked && revocable(kfetch, &keydata)) {
8101				if (keydata.addhd > now) {
8102					/*
8103					 * Key wasn't trusted yet, and now
8104					 * it's been revoked?  Just remove it
8105					 */
8106					deletekey = ISC_TRUE;
8107				} else if (keydata.removehd == 0) {
8108					/* Remove from secroots */
8109					dns_view_untrust(zone->view, keyname,
8110							 &dnskey, mctx);
8111
8112					/* If initializing, delete now */
8113					if (keydata.addhd == 0)
8114						deletekey = ISC_TRUE;
8115					else
8116						keydata.removehd = now + MONTH;
8117				} else if (keydata.removehd < now) {
8118					/* Scheduled for removal */
8119					deletekey = ISC_TRUE;
8120				}
8121			} else if (revoked) {
8122				if (secure && keydata.removehd == 0) {
8123					dns_zone_log(zone, ISC_LOG_WARNING,
8124						     "Active key for zone "
8125						     "'%s' is revoked but "
8126						     "did not self-sign; "
8127							 "ignoring.", namebuf);
8128						continue;
8129				}
8130			} else if (secure) {
8131				if (keydata.removehd != 0) {
8132					/*
8133					 * Key isn't revoked--but it
8134					 * seems it used to be.
8135					 * Remove it now and add it
8136					 * back as if it were a fresh key.
8137					 */
8138					deletekey = ISC_TRUE;
8139					newkey = ISC_TRUE;
8140				} else if (keydata.addhd > now)
8141					pending++;
8142				else if (keydata.addhd == 0)
8143					keydata.addhd = now;
8144
8145				if (keydata.addhd <= now)
8146					trustkey = ISC_TRUE;
8147			}
8148
8149			if (!deletekey && !newkey)
8150				updatekey = ISC_TRUE;
8151		} else if (secure) {
8152			/*
8153			 * Key wasn't in the key zone but it's
8154			 * revoked now anyway, so just skip it
8155			 */
8156			if (revoked)
8157				continue;
8158
8159			/* Key wasn't in the key zone: add it */
8160			newkey = ISC_TRUE;
8161
8162			if (initializing) {
8163				dns_keytag_t tag = 0;
8164				CHECK(compute_tag(keyname, &dnskey,
8165						  mctx, &tag));
8166				dns_zone_log(zone, ISC_LOG_WARNING,
8167					     "Initializing automatic trust "
8168					     "anchor management for zone '%s'; "
8169					     "DNSKEY ID %d is now trusted, "
8170					     "waiving the normal 30-day "
8171					     "waiting period.",
8172					     namebuf, tag);
8173				trustkey = ISC_TRUE;
8174			}
8175		}
8176
8177		/* Delete old version */
8178		if (deletekey || !newkey)
8179			CHECK(update_one_rr(kfetch->db, ver, &diff,
8180					    DNS_DIFFOP_DEL, keyname, 0,
8181					    &keydatarr));
8182
8183		if (updatekey) {
8184			/* Set refresh timer */
8185			keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8186			dns_rdata_reset(&keydatarr);
8187			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8188			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8189					     dns_rdatatype_keydata,
8190					     &keydata, &keyb);
8191
8192			/* Insert updated version */
8193			CHECK(update_one_rr(kfetch->db, ver, &diff,
8194					    DNS_DIFFOP_ADD, keyname, 0,
8195					    &keydatarr));
8196		} else if (newkey) {
8197			/* Convert DNSKEY to KEYDATA */
8198			dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8199			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
8200					       NULL);
8201			keydata.addhd = initializing ? now : now + MONTH;
8202			keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8203			dns_rdata_reset(&keydatarr);
8204			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8205			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8206					     dns_rdatatype_keydata,
8207					     &keydata, &keyb);
8208
8209			/* Insert into key zone */
8210			CHECK(update_one_rr(kfetch->db, ver, &diff,
8211					    DNS_DIFFOP_ADD, keyname, 0,
8212					    &keydatarr));
8213		}
8214
8215		if (trustkey) {
8216			/* Trust this key. */
8217			dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8218			trust_key(zone, keyname, &dnskey, mctx);
8219		}
8220
8221		if (!deletekey)
8222			set_refreshkeytimer(zone, &keydata, now);
8223	}
8224
8225	/*
8226	 * RFC5011 says, "A trust point that has all of its trust anchors
8227	 * revoked is considered deleted and is treated as if the trust
8228	 * point was never configured."  But if someone revoked their
8229	 * active key before the standby was trusted, that would mean the
8230	 * zone would suddenly be nonsecured.  We avoid this by checking to
8231	 * see if there's pending keydata.  If so, we put a null key in
8232	 * the security roots; then all queries to the zone will fail.
8233	 */
8234	if (pending != 0)
8235		fail_secure(zone, keyname);
8236
8237 done:
8238
8239	if (!ISC_LIST_EMPTY(diff.tuples)) {
8240		/* Write changes to journal file. */
8241		CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
8242					zone->updatemethod));
8243		CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
8244		commit = ISC_TRUE;
8245
8246		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8247		zone_needdump(zone, 30);
8248	}
8249
8250  failure:
8251
8252	dns_diff_clear(&diff);
8253	if (ver != NULL)
8254		dns_db_closeversion(kfetch->db, &ver, commit);
8255
8256 cleanup:
8257	dns_db_detach(&kfetch->db);
8258
8259	INSIST(zone->irefs > 0);
8260	zone->irefs--;
8261	kfetch->zone = NULL;
8262
8263	if (dns_rdataset_isassociated(&kfetch->keydataset))
8264		dns_rdataset_disassociate(&kfetch->keydataset);
8265	if (dns_rdataset_isassociated(&kfetch->dnskeyset))
8266		dns_rdataset_disassociate(&kfetch->dnskeyset);
8267	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8268		dns_rdataset_disassociate(&kfetch->dnskeysigset);
8269
8270	dns_name_free(keyname, mctx);
8271	isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
8272	isc_mem_detach(&mctx);
8273
8274	if (secroots != NULL)
8275		dns_keytable_detach(&secroots);
8276
8277	free_needed = exit_check(zone);
8278	UNLOCK_ZONE(zone);
8279	if (free_needed)
8280		zone_free(zone);
8281}
8282
8283/*
8284 * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
8285 * records from the zone apex.
8286 */
8287static void
8288zone_refreshkeys(dns_zone_t *zone) {
8289	const char me[] = "zone_refreshkeys";
8290	isc_result_t result;
8291	dns_rriterator_t rrit;
8292	dns_db_t *db = NULL;
8293	dns_dbversion_t *ver = NULL;
8294	dns_diff_t diff;
8295	dns_rdata_t rdata = DNS_RDATA_INIT;
8296	dns_rdata_keydata_t kd;
8297	isc_stdtime_t now;
8298	isc_boolean_t commit = ISC_FALSE;
8299	isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
8300
8301	ENTER;
8302	REQUIRE(zone->db != NULL);
8303
8304	isc_stdtime_get(&now);
8305
8306	LOCK_ZONE(zone);
8307	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
8308		isc_time_settoepoch(&zone->refreshkeytime);
8309		UNLOCK_ZONE(zone);
8310		return;
8311	}
8312
8313	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8314	dns_db_attach(zone->db, &db);
8315	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8316
8317	dns_diff_init(zone->mctx, &diff);
8318
8319	CHECK(dns_db_newversion(db, &ver));
8320
8321	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
8322
8323	dns_rriterator_init(&rrit, db, ver, 0);
8324	for (result = dns_rriterator_first(&rrit);
8325	     result == ISC_R_SUCCESS;
8326	     result = dns_rriterator_nextrrset(&rrit)) {
8327		isc_stdtime_t timer = 0xffffffff;
8328		dns_name_t *name = NULL, *kname = NULL;
8329		dns_rdataset_t *kdset = NULL;
8330		dns_keyfetch_t *kfetch;
8331		isc_uint32_t ttl;
8332
8333		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
8334		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
8335		    !dns_rdataset_isassociated(kdset))
8336			continue;
8337
8338		/*
8339		 * Scan the stored keys looking for ones that need
8340		 * removal or refreshing
8341		 */
8342		for (result = dns_rdataset_first(kdset);
8343		     result == ISC_R_SUCCESS;
8344		     result = dns_rdataset_next(kdset)) {
8345			dns_rdata_reset(&rdata);
8346			dns_rdataset_current(kdset, &rdata);
8347			result = dns_rdata_tostruct(&rdata, &kd, NULL);
8348			RUNTIME_CHECK(result == ISC_R_SUCCESS);
8349
8350			/* Removal timer expired? */
8351			if (kd.removehd != 0 && kd.removehd < now) {
8352				CHECK(update_one_rr(db, ver, &diff,
8353						    DNS_DIFFOP_DEL, name, ttl,
8354						    &rdata));
8355				continue;
8356			}
8357
8358			/* Acceptance timer expired? */
8359			if (kd.addhd != 0 && kd.addhd < now)
8360				timer = kd.addhd;
8361
8362			/* Or do we just need to refresh the keyset? */
8363			if (timer > kd.refresh)
8364				timer = kd.refresh;
8365		}
8366
8367		if (timer > now)
8368			continue;
8369
8370		kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
8371		if (kfetch == NULL) {
8372			fetch_err = ISC_TRUE;
8373			goto failure;
8374		}
8375
8376		zone->refreshkeycount++;
8377		kfetch->zone = zone;
8378		zone->irefs++;
8379		INSIST(zone->irefs != 0);
8380		dns_fixedname_init(&kfetch->name);
8381		kname = dns_fixedname_name(&kfetch->name);
8382		dns_name_dup(name, zone->mctx, kname);
8383		dns_rdataset_init(&kfetch->dnskeyset);
8384		dns_rdataset_init(&kfetch->dnskeysigset);
8385		dns_rdataset_init(&kfetch->keydataset);
8386		dns_rdataset_clone(kdset, &kfetch->keydataset);
8387		kfetch->db = NULL;
8388		dns_db_attach(db, &kfetch->db);
8389		kfetch->fetch = NULL;
8390
8391		result = dns_resolver_createfetch(zone->view->resolver,
8392						  kname, dns_rdatatype_dnskey,
8393						  NULL, NULL, NULL,
8394						  DNS_FETCHOPT_NOVALIDATE,
8395						  zone->task,
8396						  keyfetch_done, kfetch,
8397						  &kfetch->dnskeyset,
8398						  &kfetch->dnskeysigset,
8399						  &kfetch->fetch);
8400		if (result == ISC_R_SUCCESS)
8401			fetching = ISC_TRUE;
8402		else {
8403			zone->refreshkeycount--;
8404			zone->irefs--;
8405			dns_db_detach(&kfetch->db);
8406			dns_rdataset_disassociate(&kfetch->keydataset);
8407			dns_name_free(kname, zone->mctx);
8408			isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
8409			dns_zone_log(zone, ISC_LOG_WARNING,
8410				     "Failed to create fetch for "
8411				     "DNSKEY update");
8412			fetch_err = ISC_TRUE;
8413		}
8414	}
8415	if (!ISC_LIST_EMPTY(diff.tuples)) {
8416		CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
8417					zone->updatemethod));
8418		CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
8419		commit = ISC_TRUE;
8420		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8421		zone_needdump(zone, 30);
8422	}
8423
8424  failure:
8425	if (fetch_err) {
8426		/*
8427		 * Error during a key fetch; retry in an hour.
8428		 */
8429		isc_time_t timenow, timethen;
8430		char timebuf[80];
8431
8432		TIME_NOW(&timenow);
8433		DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
8434		zone->refreshkeytime = timethen;
8435		zone_settimer(zone, &timenow);
8436
8437		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
8438		dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
8439			     timebuf);
8440
8441		if (!fetching)
8442			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8443	}
8444
8445	UNLOCK_ZONE(zone);
8446
8447	dns_diff_clear(&diff);
8448	if (ver != NULL) {
8449		dns_rriterator_destroy(&rrit);
8450		dns_db_closeversion(db, &ver, commit);
8451	}
8452	dns_db_detach(&db);
8453}
8454
8455static void
8456zone_maintenance(dns_zone_t *zone) {
8457	const char me[] = "zone_maintenance";
8458	isc_time_t now;
8459	isc_result_t result;
8460	isc_boolean_t dumping;
8461
8462	REQUIRE(DNS_ZONE_VALID(zone));
8463	ENTER;
8464
8465	/*
8466	 * Are we pending load/reload?
8467	 */
8468	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
8469		return;
8470
8471	/*
8472	 * Configuring the view of this zone may have
8473	 * failed, for example because the config file
8474	 * had a syntax error.	In that case, the view
8475	 * adb or resolver will be NULL, and we had better not try
8476	 * to do further maintenance on it.
8477	 */
8478	if (zone->view == NULL || zone->view->adb == NULL)
8479		return;
8480
8481	TIME_NOW(&now);
8482
8483	/*
8484	 * Expire check.
8485	 */
8486	switch (zone->type) {
8487	case dns_zone_redirect:
8488		if (zone->masters == NULL)
8489			break;
8490	case dns_zone_slave:
8491	case dns_zone_stub:
8492		LOCK_ZONE(zone);
8493		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
8494		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8495			zone_expire(zone);
8496			zone->refreshtime = now;
8497		}
8498		UNLOCK_ZONE(zone);
8499		break;
8500	default:
8501		break;
8502	}
8503
8504	/*
8505	 * Up to date check.
8506	 */
8507	switch (zone->type) {
8508	case dns_zone_redirect:
8509		if (zone->masters == NULL)
8510			break;
8511	case dns_zone_slave:
8512	case dns_zone_stub:
8513		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8514		    isc_time_compare(&now, &zone->refreshtime) >= 0)
8515			dns_zone_refresh(zone);
8516		break;
8517	default:
8518		break;
8519	}
8520
8521	/*
8522	 * Do we need to consolidate the backing store?
8523	 */
8524	switch (zone->type) {
8525	case dns_zone_master:
8526	case dns_zone_slave:
8527	case dns_zone_key:
8528	case dns_zone_redirect:
8529	case dns_zone_stub:
8530		LOCK_ZONE(zone);
8531		if (zone->masterfile != NULL &&
8532		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
8533		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8534		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
8535			dumping = was_dumping(zone);
8536		} else
8537			dumping = ISC_TRUE;
8538		UNLOCK_ZONE(zone);
8539		if (!dumping) {
8540			result = zone_dump(zone, ISC_TRUE); /* task locked */
8541			if (result != ISC_R_SUCCESS)
8542				dns_zone_log(zone, ISC_LOG_WARNING,
8543					     "dump failed: %s",
8544					     dns_result_totext(result));
8545		}
8546		break;
8547	default:
8548		break;
8549	}
8550
8551	/*
8552	 * Do we need to refresh keys?
8553	 */
8554	switch (zone->type) {
8555	case dns_zone_key:
8556		if (isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
8557		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8558		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
8559			zone_refreshkeys(zone);
8560		break;
8561	case dns_zone_master:
8562		if (!isc_time_isepoch(&zone->refreshkeytime) &&
8563		    isc_time_compare(&now, &zone->refreshkeytime) >= 0)
8564			zone_rekey(zone);
8565	default:
8566		break;
8567	}
8568
8569	switch (zone->type) {
8570	case dns_zone_master:
8571	case dns_zone_redirect:
8572	case dns_zone_slave:
8573		/*
8574		 * Do we need to send out notify messages?
8575		 */
8576		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8577		    isc_time_compare(&now, &zone->notifytime) >= 0)
8578			zone_notify(zone, &now);
8579		/*
8580		 * Do we need to sign/resign some RRsets?
8581		 */
8582		if (!isc_time_isepoch(&zone->signingtime) &&
8583		    isc_time_compare(&now, &zone->signingtime) >= 0)
8584			zone_sign(zone);
8585		else if (!isc_time_isepoch(&zone->resigntime) &&
8586		    isc_time_compare(&now, &zone->resigntime) >= 0)
8587			zone_resigninc(zone);
8588		else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
8589			isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
8590			zone_nsec3chain(zone);
8591		/*
8592		 * Do we need to issue a key expiry warning.
8593		 */
8594		if (!isc_time_isepoch(&zone->keywarntime) &&
8595		    isc_time_compare(&now, &zone->keywarntime) >= 0)
8596			set_key_expiry_warning(zone, zone->key_expiry,
8597					       isc_time_seconds(&now));
8598		break;
8599
8600	default:
8601		break;
8602	}
8603	zone_settimer(zone, &now);
8604}
8605
8606void
8607dns_zone_markdirty(dns_zone_t *zone) {
8608	isc_uint32_t serial;
8609	isc_result_t result;
8610
8611	LOCK_ZONE(zone);
8612	if (zone->type == dns_zone_master) {
8613		if (inline_raw(zone)) {
8614			ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8615			if (zone->db != NULL) {
8616				result = zone_get_from_db(zone, zone->db, NULL,
8617							  NULL, &serial, NULL,
8618							  NULL, NULL, NULL,
8619							  NULL);
8620			} else
8621				result = DNS_R_NOTLOADED;
8622			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8623			if (result == ISC_R_SUCCESS)
8624				zone_send_secureserial(zone, ISC_FALSE, serial);
8625		}
8626		set_resigntime(zone);	/* XXXMPA make separate call back */
8627	}
8628	zone_needdump(zone, DNS_DUMP_DELAY);
8629	UNLOCK_ZONE(zone);
8630}
8631
8632void
8633dns_zone_expire(dns_zone_t *zone) {
8634	REQUIRE(DNS_ZONE_VALID(zone));
8635
8636	LOCK_ZONE(zone);
8637	zone_expire(zone);
8638	UNLOCK_ZONE(zone);
8639}
8640
8641static void
8642zone_expire(dns_zone_t *zone) {
8643	/*
8644	 * 'zone' locked by caller.
8645	 */
8646
8647	REQUIRE(LOCKED_ZONE(zone));
8648
8649	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
8650
8651	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
8652	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
8653	zone->retry = DNS_ZONE_DEFAULTRETRY;
8654	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
8655	zone_unload(zone);
8656}
8657
8658void
8659dns_zone_refresh(dns_zone_t *zone) {
8660	isc_interval_t i;
8661	isc_uint32_t oldflags;
8662	unsigned int j;
8663	isc_result_t result;
8664
8665	REQUIRE(DNS_ZONE_VALID(zone));
8666
8667	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
8668		return;
8669
8670	/*
8671	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
8672	 * in progress at a time.
8673	 */
8674
8675	LOCK_ZONE(zone);
8676	oldflags = zone->flags;
8677	if (zone->masterscnt == 0) {
8678		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
8679		if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
8680			dns_zone_log(zone, ISC_LOG_ERROR,
8681				     "cannot refresh: no masters");
8682		goto unlock;
8683	}
8684	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
8685	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
8686	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
8687	if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
8688		goto unlock;
8689
8690	/*
8691	 * Set the next refresh time as if refresh check has failed.
8692	 * Setting this to the retry time will do that.  XXXMLG
8693	 * If we are successful it will be reset using zone->refresh.
8694	 */
8695	isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
8696			 0);
8697	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
8698	if (result != ISC_R_SUCCESS)
8699		dns_zone_log(zone, ISC_LOG_WARNING,
8700			     "isc_time_nowplusinterval() failed: %s",
8701			     dns_result_totext(result));
8702
8703	/*
8704	 * When lacking user-specified timer values from the SOA,
8705	 * do exponential backoff of the retry time up to a
8706	 * maximum of six hours.
8707	 */
8708	if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
8709		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
8710
8711	zone->curmaster = 0;
8712	for (j = 0; j < zone->masterscnt; j++)
8713		zone->mastersok[j] = ISC_FALSE;
8714	/* initiate soa query */
8715	queue_soa_query(zone);
8716 unlock:
8717	UNLOCK_ZONE(zone);
8718}
8719
8720isc_result_t
8721dns_zone_flush(dns_zone_t *zone) {
8722	isc_result_t result = ISC_R_SUCCESS;
8723	isc_boolean_t dumping;
8724
8725	REQUIRE(DNS_ZONE_VALID(zone));
8726
8727	LOCK_ZONE(zone);
8728	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
8729	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8730	    zone->masterfile != NULL) {
8731		result = ISC_R_ALREADYRUNNING;
8732		dumping = was_dumping(zone);
8733	} else
8734		dumping = ISC_TRUE;
8735	UNLOCK_ZONE(zone);
8736	if (!dumping)
8737		result = zone_dump(zone, ISC_FALSE);	/* Unknown task. */
8738	return (result);
8739}
8740
8741isc_result_t
8742dns_zone_dump(dns_zone_t *zone) {
8743	isc_result_t result = ISC_R_ALREADYRUNNING;
8744	isc_boolean_t dumping;
8745
8746	REQUIRE(DNS_ZONE_VALID(zone));
8747
8748	LOCK_ZONE(zone);
8749	dumping = was_dumping(zone);
8750	UNLOCK_ZONE(zone);
8751	if (!dumping)
8752		result = zone_dump(zone, ISC_FALSE);	/* Unknown task. */
8753	return (result);
8754}
8755
8756static void
8757zone_needdump(dns_zone_t *zone, unsigned int delay) {
8758	isc_time_t dumptime;
8759	isc_time_t now;
8760
8761	/*
8762	 * 'zone' locked by caller
8763	 */
8764
8765	REQUIRE(DNS_ZONE_VALID(zone));
8766	REQUIRE(LOCKED_ZONE(zone));
8767
8768	/*
8769	 * Do we have a place to dump to and are we loaded?
8770	 */
8771	if (zone->masterfile == NULL ||
8772	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
8773		return;
8774
8775	TIME_NOW(&now);
8776	/* add some noise */
8777	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
8778
8779	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8780	if (isc_time_isepoch(&zone->dumptime) ||
8781	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
8782		zone->dumptime = dumptime;
8783	if (zone->task != NULL)
8784		zone_settimer(zone, &now);
8785}
8786
8787static void
8788dump_done(void *arg, isc_result_t result) {
8789	const char me[] = "dump_done";
8790	dns_zone_t *zone = arg;
8791	dns_db_t *db;
8792	dns_dbversion_t *version;
8793	isc_boolean_t again = ISC_FALSE;
8794	isc_boolean_t compact = ISC_FALSE;
8795	isc_uint32_t serial;
8796	isc_result_t tresult;
8797
8798	REQUIRE(DNS_ZONE_VALID(zone));
8799
8800	ENTER;
8801
8802	if (result == ISC_R_SUCCESS && zone->journal != NULL &&
8803	    zone->journalsize != -1) {
8804
8805		/*
8806		 * We don't own these, zone->dctx must stay valid.
8807		 */
8808		db = dns_dumpctx_db(zone->dctx);
8809		version = dns_dumpctx_version(zone->dctx);
8810
8811		tresult = dns_db_getsoaserial(db, version, &serial);
8812		/*
8813		 * If there is a secure version of this zone
8814		 * use its serial if it is less than ours.
8815		 */
8816		if (tresult == ISC_R_SUCCESS && inline_raw(zone) &&
8817		    zone->secure->db != NULL)
8818		{
8819			isc_uint32_t sserial;
8820			isc_result_t mresult;
8821
8822			mresult = dns_db_getsoaserial(zone->secure->db,
8823						      NULL, &sserial);
8824			if (mresult == ISC_R_SUCCESS &&
8825			    isc_serial_lt(sserial, serial))
8826				serial = sserial;
8827		}
8828		/*
8829		 * Note: we are task locked here so we can test
8830		 * zone->xfr safely.
8831		 */
8832		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
8833			tresult = dns_journal_compact(zone->mctx,
8834						      zone->journal,
8835						      serial,
8836						      zone->journalsize);
8837			switch (tresult) {
8838			case ISC_R_SUCCESS:
8839			case ISC_R_NOSPACE:
8840			case ISC_R_NOTFOUND:
8841				dns_zone_log(zone, ISC_LOG_DEBUG(3),
8842					     "dns_journal_compact: %s",
8843					     dns_result_totext(tresult));
8844				break;
8845			default:
8846				dns_zone_log(zone, ISC_LOG_ERROR,
8847					     "dns_journal_compact failed: %s",
8848					     dns_result_totext(tresult));
8849				break;
8850			}
8851		} else if (tresult == ISC_R_SUCCESS) {
8852			compact = ISC_TRUE;
8853			zone->compact_serial = serial;
8854		}
8855	}
8856
8857	LOCK_ZONE(zone);
8858	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8859	if (compact)
8860		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
8861	if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
8862		/*
8863		 * Try again in a short while.
8864		 */
8865		zone_needdump(zone, DNS_DUMP_DELAY);
8866	} else if (result == ISC_R_SUCCESS &&
8867		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8868		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8869		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8870		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8871		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8872		isc_time_settoepoch(&zone->dumptime);
8873		again = ISC_TRUE;
8874	} else if (result == ISC_R_SUCCESS)
8875		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8876
8877	if (zone->dctx != NULL)
8878		dns_dumpctx_detach(&zone->dctx);
8879	zonemgr_putio(&zone->writeio);
8880	UNLOCK_ZONE(zone);
8881	if (again)
8882		(void)zone_dump(zone, ISC_FALSE);
8883	dns_zone_idetach(&zone);
8884}
8885
8886static isc_result_t
8887zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
8888	const char me[] = "zone_dump";
8889	isc_result_t result;
8890	dns_dbversion_t *version = NULL;
8891	isc_boolean_t again;
8892	dns_db_t *db = NULL;
8893	char *masterfile = NULL;
8894	dns_masterformat_t masterformat = dns_masterformat_none;
8895
8896/*
8897 * 'compact' MUST only be set if we are task locked.
8898 */
8899
8900	REQUIRE(DNS_ZONE_VALID(zone));
8901	ENTER;
8902
8903 redo:
8904	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8905	if (zone->db != NULL)
8906		dns_db_attach(zone->db, &db);
8907	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8908	LOCK_ZONE(zone);
8909	if (zone->masterfile != NULL) {
8910		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
8911		masterformat = zone->masterformat;
8912	}
8913	UNLOCK_ZONE(zone);
8914	if (db == NULL) {
8915		result = DNS_R_NOTLOADED;
8916		goto fail;
8917	}
8918	if (masterfile == NULL) {
8919		result = DNS_R_NOMASTERFILE;
8920		goto fail;
8921	}
8922
8923	if (compact && zone->type != dns_zone_stub) {
8924		dns_zone_t *dummy = NULL;
8925		LOCK_ZONE(zone);
8926		zone_iattach(zone, &dummy);
8927		result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
8928				       zone_gotwritehandle, zone,
8929				       &zone->writeio);
8930		if (result != ISC_R_SUCCESS)
8931			zone_idetach(&dummy);
8932		else
8933			result = DNS_R_CONTINUE;
8934		UNLOCK_ZONE(zone);
8935	} else {
8936		dns_masterrawheader_t rawdata;
8937		dns_db_currentversion(db, &version);
8938		dns_master_initrawheader(&rawdata);
8939		if (inline_secure(zone))
8940			get_raw_serial(zone->raw, &rawdata);
8941		result = dns_master_dump3(zone->mctx, db, version,
8942					  &dns_master_style_default,
8943					  masterfile, masterformat,
8944					  &rawdata);
8945		dns_db_closeversion(db, &version, ISC_FALSE);
8946	}
8947 fail:
8948	if (db != NULL)
8949		dns_db_detach(&db);
8950	if (masterfile != NULL)
8951		isc_mem_free(zone->mctx, masterfile);
8952	masterfile = NULL;
8953
8954	if (result == DNS_R_CONTINUE)
8955		return (ISC_R_SUCCESS); /* XXXMPA */
8956
8957	again = ISC_FALSE;
8958	LOCK_ZONE(zone);
8959	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8960	if (result != ISC_R_SUCCESS) {
8961		/*
8962		 * Try again in a short while.
8963		 */
8964		zone_needdump(zone, DNS_DUMP_DELAY);
8965	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8966		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8967		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8968		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8969		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8970		isc_time_settoepoch(&zone->dumptime);
8971		again = ISC_TRUE;
8972	} else
8973		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8974	UNLOCK_ZONE(zone);
8975	if (again)
8976		goto redo;
8977
8978	return (result);
8979}
8980
8981static isc_result_t
8982dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
8983	     dns_masterformat_t format, const isc_uint32_t rawversion)
8984{
8985	isc_result_t result;
8986	dns_dbversion_t *version = NULL;
8987	dns_db_t *db = NULL;
8988	dns_masterrawheader_t rawdata;
8989
8990	REQUIRE(DNS_ZONE_VALID(zone));
8991
8992	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8993	if (zone->db != NULL)
8994		dns_db_attach(zone->db, &db);
8995	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8996	if (db == NULL)
8997		return (DNS_R_NOTLOADED);
8998
8999	dns_db_currentversion(db, &version);
9000	dns_master_initrawheader(&rawdata);
9001	if (rawversion == 0)
9002		rawdata.flags |= DNS_MASTERRAW_COMPAT;
9003	else if (inline_secure(zone))
9004		get_raw_serial(zone->raw, &rawdata);
9005	else if (zone->sourceserialset) {
9006		rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
9007		rawdata.sourceserial = zone->sourceserial;
9008	}
9009	result = dns_master_dumptostream3(zone->mctx, db, version, style,
9010					  format, &rawdata, fd);
9011	dns_db_closeversion(db, &version, ISC_FALSE);
9012	dns_db_detach(&db);
9013	return (result);
9014}
9015
9016isc_result_t
9017dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9018		       const dns_master_style_t *style,
9019		       const isc_uint32_t rawversion)
9020{
9021	return (dumptostream(zone, fd, style, format, rawversion));
9022}
9023
9024isc_result_t
9025dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9026		       const dns_master_style_t *style) {
9027	return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
9028}
9029
9030isc_result_t
9031dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
9032	return (dumptostream(zone, fd, &dns_master_style_default,
9033			     dns_masterformat_text, 0));
9034}
9035
9036isc_result_t
9037dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
9038	return (dumptostream(zone, fd, &dns_master_style_full,
9039			     dns_masterformat_text, 0));
9040}
9041
9042void
9043dns_zone_unload(dns_zone_t *zone) {
9044	REQUIRE(DNS_ZONE_VALID(zone));
9045
9046	LOCK_ZONE(zone);
9047	zone_unload(zone);
9048	UNLOCK_ZONE(zone);
9049}
9050
9051static void
9052notify_cancel(dns_zone_t *zone) {
9053	dns_notify_t *notify;
9054
9055	/*
9056	 * 'zone' locked by caller.
9057	 */
9058
9059	REQUIRE(LOCKED_ZONE(zone));
9060
9061	for (notify = ISC_LIST_HEAD(zone->notifies);
9062	     notify != NULL;
9063	     notify = ISC_LIST_NEXT(notify, link)) {
9064		if (notify->find != NULL)
9065			dns_adb_cancelfind(notify->find);
9066		if (notify->request != NULL)
9067			dns_request_cancel(notify->request);
9068	}
9069}
9070
9071static void
9072forward_cancel(dns_zone_t *zone) {
9073	dns_forward_t *forward;
9074
9075	/*
9076	 * 'zone' locked by caller.
9077	 */
9078
9079	REQUIRE(LOCKED_ZONE(zone));
9080
9081	for (forward = ISC_LIST_HEAD(zone->forwards);
9082	     forward != NULL;
9083	     forward = ISC_LIST_NEXT(forward, link)) {
9084		if (forward->request != NULL)
9085			dns_request_cancel(forward->request);
9086	}
9087}
9088
9089static void
9090zone_unload(dns_zone_t *zone) {
9091
9092	/*
9093	 * 'zone' locked by caller.
9094	 */
9095
9096	REQUIRE(LOCKED_ZONE(zone));
9097
9098	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
9099	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9100		if (zone->writeio != NULL)
9101			zonemgr_cancelio(zone->writeio);
9102
9103		if (zone->dctx != NULL)
9104			dns_dumpctx_cancel(zone->dctx);
9105	}
9106	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9107	zone_detachdb(zone);
9108	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9109	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
9110	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9111}
9112
9113void
9114dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9115	REQUIRE(DNS_ZONE_VALID(zone));
9116	REQUIRE(val > 0);
9117
9118	zone->minrefresh = val;
9119}
9120
9121void
9122dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9123	REQUIRE(DNS_ZONE_VALID(zone));
9124	REQUIRE(val > 0);
9125
9126	zone->maxrefresh = val;
9127}
9128
9129void
9130dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
9131	REQUIRE(DNS_ZONE_VALID(zone));
9132	REQUIRE(val > 0);
9133
9134	zone->minretry = val;
9135}
9136
9137void
9138dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
9139	REQUIRE(DNS_ZONE_VALID(zone));
9140	REQUIRE(val > 0);
9141
9142	zone->maxretry = val;
9143}
9144
9145static isc_boolean_t
9146notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
9147	dns_notify_t *notify;
9148
9149	for (notify = ISC_LIST_HEAD(zone->notifies);
9150	     notify != NULL;
9151	     notify = ISC_LIST_NEXT(notify, link)) {
9152		if (notify->request != NULL)
9153			continue;
9154		if (name != NULL && dns_name_dynamic(&notify->ns) &&
9155		    dns_name_equal(name, &notify->ns))
9156			return (ISC_TRUE);
9157		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
9158			return (ISC_TRUE);
9159	}
9160	return (ISC_FALSE);
9161}
9162
9163static isc_boolean_t
9164notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
9165	dns_tsigkey_t *key = NULL;
9166	isc_sockaddr_t src;
9167	isc_sockaddr_t any;
9168	isc_boolean_t isself;
9169	isc_netaddr_t dstaddr;
9170	isc_result_t result;
9171
9172	if (zone->view == NULL || zone->isself == NULL)
9173		return (ISC_FALSE);
9174
9175	switch (isc_sockaddr_pf(dst)) {
9176	case PF_INET:
9177		src = zone->notifysrc4;
9178		isc_sockaddr_any(&any);
9179		break;
9180	case PF_INET6:
9181		src = zone->notifysrc6;
9182		isc_sockaddr_any6(&any);
9183		break;
9184	default:
9185		return (ISC_FALSE);
9186	}
9187
9188	/*
9189	 * When sending from any the kernel will assign a source address
9190	 * that matches the destination address.
9191	 */
9192	if (isc_sockaddr_eqaddr(&any, &src))
9193		src = *dst;
9194
9195	isc_netaddr_fromsockaddr(&dstaddr, dst);
9196	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
9197	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
9198		return (ISC_FALSE);
9199	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
9200				zone->isselfarg);
9201	if (key != NULL)
9202		dns_tsigkey_detach(&key);
9203	return (isself);
9204}
9205
9206static void
9207notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
9208	isc_mem_t *mctx;
9209
9210	/*
9211	 * Caller holds zone lock.
9212	 */
9213	REQUIRE(DNS_NOTIFY_VALID(notify));
9214
9215	if (notify->zone != NULL) {
9216		if (!locked)
9217			LOCK_ZONE(notify->zone);
9218		REQUIRE(LOCKED_ZONE(notify->zone));
9219		if (ISC_LINK_LINKED(notify, link))
9220			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
9221		if (!locked)
9222			UNLOCK_ZONE(notify->zone);
9223		if (locked)
9224			zone_idetach(&notify->zone);
9225		else
9226			dns_zone_idetach(&notify->zone);
9227	}
9228	if (notify->find != NULL)
9229		dns_adb_destroyfind(&notify->find);
9230	if (notify->request != NULL)
9231		dns_request_destroy(&notify->request);
9232	if (dns_name_dynamic(&notify->ns))
9233		dns_name_free(&notify->ns, notify->mctx);
9234	if (notify->key != NULL)
9235		dns_tsigkey_detach(&notify->key);
9236	mctx = notify->mctx;
9237	isc_mem_put(notify->mctx, notify, sizeof(*notify));
9238	isc_mem_detach(&mctx);
9239}
9240
9241static isc_result_t
9242notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
9243	dns_notify_t *notify;
9244
9245	REQUIRE(notifyp != NULL && *notifyp == NULL);
9246
9247	notify = isc_mem_get(mctx, sizeof(*notify));
9248	if (notify == NULL)
9249		return (ISC_R_NOMEMORY);
9250
9251	notify->mctx = NULL;
9252	isc_mem_attach(mctx, &notify->mctx);
9253	notify->flags = flags;
9254	notify->zone = NULL;
9255	notify->find = NULL;
9256	notify->request = NULL;
9257	notify->key = NULL;
9258	isc_sockaddr_any(&notify->dst);
9259	dns_name_init(&notify->ns, NULL);
9260	ISC_LINK_INIT(notify, link);
9261	notify->magic = NOTIFY_MAGIC;
9262	*notifyp = notify;
9263	return (ISC_R_SUCCESS);
9264}
9265
9266/*
9267 * XXXAG should check for DNS_ZONEFLG_EXITING
9268 */
9269static void
9270process_adb_event(isc_task_t *task, isc_event_t *ev) {
9271	dns_notify_t *notify;
9272	isc_eventtype_t result;
9273
9274	UNUSED(task);
9275
9276	notify = ev->ev_arg;
9277	REQUIRE(DNS_NOTIFY_VALID(notify));
9278	INSIST(task == notify->zone->task);
9279	result = ev->ev_type;
9280	isc_event_free(&ev);
9281	if (result == DNS_EVENT_ADBMOREADDRESSES) {
9282		dns_adb_destroyfind(&notify->find);
9283		notify_find_address(notify);
9284		return;
9285	}
9286	if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
9287		LOCK_ZONE(notify->zone);
9288		notify_send(notify);
9289		UNLOCK_ZONE(notify->zone);
9290	}
9291	notify_destroy(notify, ISC_FALSE);
9292}
9293
9294static void
9295notify_find_address(dns_notify_t *notify) {
9296	isc_result_t result;
9297	unsigned int options;
9298
9299	REQUIRE(DNS_NOTIFY_VALID(notify));
9300	options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
9301		  DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
9302
9303	if (notify->zone->view->adb == NULL)
9304		goto destroy;
9305
9306	result = dns_adb_createfind(notify->zone->view->adb,
9307				    notify->zone->task,
9308				    process_adb_event, notify,
9309				    &notify->ns, dns_rootname, 0,
9310				    options, 0, NULL,
9311				    notify->zone->view->dstport,
9312				    &notify->find);
9313
9314	/* Something failed? */
9315	if (result != ISC_R_SUCCESS)
9316		goto destroy;
9317
9318	/* More addresses pending? */
9319	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
9320		return;
9321
9322	/* We have as many addresses as we can get. */
9323	LOCK_ZONE(notify->zone);
9324	notify_send(notify);
9325	UNLOCK_ZONE(notify->zone);
9326
9327 destroy:
9328	notify_destroy(notify, ISC_FALSE);
9329}
9330
9331
9332static isc_result_t
9333notify_send_queue(dns_notify_t *notify) {
9334	isc_event_t *e;
9335	isc_result_t result;
9336
9337	e = isc_event_allocate(notify->mctx, NULL,
9338			       DNS_EVENT_NOTIFYSENDTOADDR,
9339			       notify_send_toaddr,
9340			       notify, sizeof(isc_event_t));
9341	if (e == NULL)
9342		return (ISC_R_NOMEMORY);
9343	e->ev_arg = notify;
9344	e->ev_sender = NULL;
9345	result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
9346					 notify->zone->task, &e);
9347	if (result != ISC_R_SUCCESS)
9348		isc_event_free(&e);
9349	return (result);
9350}
9351
9352static void
9353notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
9354	dns_notify_t *notify;
9355	isc_result_t result;
9356	dns_message_t *message = NULL;
9357	isc_netaddr_t dstip;
9358	dns_tsigkey_t *key = NULL;
9359	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9360	isc_sockaddr_t src;
9361	int timeout;
9362	isc_boolean_t have_notifysource = ISC_FALSE;
9363
9364	notify = event->ev_arg;
9365	REQUIRE(DNS_NOTIFY_VALID(notify));
9366
9367	UNUSED(task);
9368
9369	LOCK_ZONE(notify->zone);
9370
9371	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
9372		result = ISC_R_CANCELED;
9373		goto cleanup;
9374	}
9375
9376	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
9377	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
9378	    notify->zone->view->requestmgr == NULL ||
9379	    notify->zone->db == NULL) {
9380		result = ISC_R_CANCELED;
9381		goto cleanup;
9382	}
9383
9384	/*
9385	 * The raw IPv4 address should also exist.  Don't send to the
9386	 * mapped form.
9387	 */
9388	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
9389	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
9390		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9391		notify_log(notify->zone, ISC_LOG_DEBUG(3),
9392			   "notify: ignoring IPv6 mapped IPV4 address: %s",
9393			   addrbuf);
9394		result = ISC_R_CANCELED;
9395		goto cleanup;
9396	}
9397
9398	result = notify_createmessage(notify->zone, notify->flags, &message);
9399	if (result != ISC_R_SUCCESS)
9400		goto cleanup;
9401
9402	if (notify->key != NULL) {
9403		/* Transfer ownership of key */
9404		key = notify->key;
9405		notify->key = NULL;
9406	} else {
9407		isc_netaddr_fromsockaddr(&dstip, &notify->dst);
9408		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9409		result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
9410		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9411			notify_log(notify->zone, ISC_LOG_ERROR,
9412				   "NOTIFY to %s not sent. "
9413				   "Peer TSIG key lookup failure.", addrbuf);
9414			goto cleanup_message;
9415		}
9416	}
9417
9418	/* XXX: should we log the tsig key too? */
9419	notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
9420		   addrbuf);
9421	if (notify->zone->view->peers != NULL) {
9422		dns_peer_t *peer = NULL;
9423		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
9424						 &dstip, &peer);
9425		if (result == ISC_R_SUCCESS) {
9426			result = dns_peer_getnotifysource(peer, &src);
9427			if (result == ISC_R_SUCCESS)
9428				have_notifysource = ISC_TRUE;
9429		}
9430	}
9431	switch (isc_sockaddr_pf(&notify->dst)) {
9432	case PF_INET:
9433		if (!have_notifysource)
9434			src = notify->zone->notifysrc4;
9435		break;
9436	case PF_INET6:
9437		if (!have_notifysource)
9438			src = notify->zone->notifysrc6;
9439		break;
9440	default:
9441		result = ISC_R_NOTIMPLEMENTED;
9442		goto cleanup_key;
9443	}
9444	timeout = 15;
9445	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
9446		timeout = 30;
9447	result = dns_request_createvia2(notify->zone->view->requestmgr,
9448					message, &src, &notify->dst, 0, key,
9449					timeout * 3, timeout,
9450					notify->zone->task, notify_done,
9451					notify, &notify->request);
9452	if (result == ISC_R_SUCCESS) {
9453		if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
9454			inc_stats(notify->zone,
9455				  dns_zonestatscounter_notifyoutv4);
9456		} else {
9457			inc_stats(notify->zone,
9458				  dns_zonestatscounter_notifyoutv6);
9459		}
9460	}
9461
9462 cleanup_key:
9463	if (key != NULL)
9464		dns_tsigkey_detach(&key);
9465 cleanup_message:
9466	dns_message_destroy(&message);
9467 cleanup:
9468	UNLOCK_ZONE(notify->zone);
9469	if (result != ISC_R_SUCCESS)
9470		notify_destroy(notify, ISC_FALSE);
9471	isc_event_free(&event);
9472}
9473
9474static void
9475notify_send(dns_notify_t *notify) {
9476	dns_adbaddrinfo_t *ai;
9477	isc_sockaddr_t dst;
9478	isc_result_t result;
9479	dns_notify_t *new = NULL;
9480
9481	/*
9482	 * Zone lock held by caller.
9483	 */
9484	REQUIRE(DNS_NOTIFY_VALID(notify));
9485	REQUIRE(LOCKED_ZONE(notify->zone));
9486
9487	for (ai = ISC_LIST_HEAD(notify->find->list);
9488	     ai != NULL;
9489	     ai = ISC_LIST_NEXT(ai, publink)) {
9490		dst = ai->sockaddr;
9491		if (notify_isqueued(notify->zone, NULL, &dst))
9492			continue;
9493		if (notify_isself(notify->zone, &dst))
9494			continue;
9495		new = NULL;
9496		result = notify_create(notify->mctx,
9497				       (notify->flags & DNS_NOTIFY_NOSOA),
9498				       &new);
9499		if (result != ISC_R_SUCCESS)
9500			goto cleanup;
9501		zone_iattach(notify->zone, &new->zone);
9502		ISC_LIST_APPEND(new->zone->notifies, new, link);
9503		new->dst = dst;
9504		result = notify_send_queue(new);
9505		if (result != ISC_R_SUCCESS)
9506			goto cleanup;
9507		new = NULL;
9508	}
9509
9510 cleanup:
9511	if (new != NULL)
9512		notify_destroy(new, ISC_TRUE);
9513}
9514
9515void
9516dns_zone_notify(dns_zone_t *zone) {
9517	isc_time_t now;
9518
9519	REQUIRE(DNS_ZONE_VALID(zone));
9520
9521	LOCK_ZONE(zone);
9522	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9523
9524	TIME_NOW(&now);
9525	zone_settimer(zone, &now);
9526	UNLOCK_ZONE(zone);
9527}
9528
9529static void
9530zone_notify(dns_zone_t *zone, isc_time_t *now) {
9531	dns_dbnode_t *node = NULL;
9532	dns_db_t *zonedb = NULL;
9533	dns_dbversion_t *version = NULL;
9534	dns_name_t *origin = NULL;
9535	dns_name_t master;
9536	dns_rdata_ns_t ns;
9537	dns_rdata_soa_t soa;
9538	isc_uint32_t serial;
9539	dns_rdata_t rdata = DNS_RDATA_INIT;
9540	dns_rdataset_t nsrdset;
9541	dns_rdataset_t soardset;
9542	isc_result_t result;
9543	dns_notify_t *notify = NULL;
9544	unsigned int i;
9545	isc_sockaddr_t dst;
9546	isc_boolean_t isqueued;
9547	dns_notifytype_t notifytype;
9548	unsigned int flags = 0;
9549	isc_boolean_t loggednotify = ISC_FALSE;
9550
9551	REQUIRE(DNS_ZONE_VALID(zone));
9552
9553	LOCK_ZONE(zone);
9554	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9555	notifytype = zone->notifytype;
9556	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
9557	UNLOCK_ZONE(zone);
9558
9559	if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
9560		return;
9561
9562	if (notifytype == dns_notifytype_no)
9563		return;
9564
9565	if (notifytype == dns_notifytype_masteronly &&
9566	    zone->type != dns_zone_master)
9567		return;
9568
9569	origin = &zone->origin;
9570
9571	/*
9572	 * If the zone is dialup we are done as we don't want to send
9573	 * the current soa so as to force a refresh query.
9574	 */
9575	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
9576		flags |= DNS_NOTIFY_NOSOA;
9577
9578	/*
9579	 * Get SOA RRset.
9580	 */
9581	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9582	if (zone->db != NULL)
9583		dns_db_attach(zone->db, &zonedb);
9584	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9585	if (zonedb == NULL)
9586		return;
9587	dns_db_currentversion(zonedb, &version);
9588	result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
9589	if (result != ISC_R_SUCCESS)
9590		goto cleanup1;
9591
9592	dns_rdataset_init(&soardset);
9593	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
9594				     dns_rdatatype_none, 0, &soardset, NULL);
9595	if (result != ISC_R_SUCCESS)
9596		goto cleanup2;
9597
9598	/*
9599	 * Find serial and master server's name.
9600	 */
9601	dns_name_init(&master, NULL);
9602	result = dns_rdataset_first(&soardset);
9603	if (result != ISC_R_SUCCESS)
9604		goto cleanup3;
9605	dns_rdataset_current(&soardset, &rdata);
9606	result = dns_rdata_tostruct(&rdata, &soa, NULL);
9607	RUNTIME_CHECK(result == ISC_R_SUCCESS);
9608	dns_rdata_reset(&rdata);
9609	result = dns_name_dup(&soa.origin, zone->mctx, &master);
9610	serial = soa.serial;
9611	dns_rdataset_disassociate(&soardset);
9612	if (result != ISC_R_SUCCESS)
9613		goto cleanup3;
9614
9615	/*
9616	 * Enqueue notify requests for 'also-notify' servers.
9617	 */
9618	LOCK_ZONE(zone);
9619	for (i = 0; i < zone->notifycnt; i++) {
9620		dns_tsigkey_t *key = NULL;
9621
9622		dst = zone->notify[i];
9623		if (notify_isqueued(zone, NULL, &dst))
9624			continue;
9625
9626		result = notify_create(zone->mctx, flags, &notify);
9627		if (result != ISC_R_SUCCESS)
9628			continue;
9629
9630		zone_iattach(zone, &notify->zone);
9631		notify->dst = dst;
9632
9633		if ((zone->notifykeynames != NULL) &&
9634		    (zone->notifykeynames[i] != NULL)) {
9635			dns_view_t *view = dns_zone_getview(zone);
9636			dns_name_t *keyname = zone->notifykeynames[i];
9637			result = dns_view_gettsig(view, keyname, &key);
9638			if (result == ISC_R_SUCCESS) {
9639				notify->key = key;
9640				key = NULL;
9641			}
9642		}
9643
9644		ISC_LIST_APPEND(zone->notifies, notify, link);
9645		result = notify_send_queue(notify);
9646		if (result != ISC_R_SUCCESS)
9647			notify_destroy(notify, ISC_TRUE);
9648		if (!loggednotify) {
9649			notify_log(zone, ISC_LOG_INFO,
9650				   "sending notifies (serial %u)",
9651				   serial);
9652			loggednotify = ISC_TRUE;
9653		}
9654		notify = NULL;
9655	}
9656	UNLOCK_ZONE(zone);
9657
9658	if (notifytype == dns_notifytype_explicit)
9659		goto cleanup3;
9660
9661	/*
9662	 * Process NS RRset to generate notifies.
9663	 */
9664
9665	dns_rdataset_init(&nsrdset);
9666	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
9667				     dns_rdatatype_none, 0, &nsrdset, NULL);
9668	if (result != ISC_R_SUCCESS)
9669		goto cleanup3;
9670
9671	result = dns_rdataset_first(&nsrdset);
9672	while (result == ISC_R_SUCCESS) {
9673		dns_rdataset_current(&nsrdset, &rdata);
9674		result = dns_rdata_tostruct(&rdata, &ns, NULL);
9675		RUNTIME_CHECK(result == ISC_R_SUCCESS);
9676		dns_rdata_reset(&rdata);
9677		/*
9678		 * Don't notify the master server unless explicitly
9679		 * configured to do so.
9680		 */
9681		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
9682		    dns_name_compare(&master, &ns.name) == 0) {
9683			result = dns_rdataset_next(&nsrdset);
9684			continue;
9685		}
9686
9687		if (!loggednotify) {
9688			notify_log(zone, ISC_LOG_INFO,
9689				   "sending notifies (serial %u)",
9690				   serial);
9691			loggednotify = ISC_TRUE;
9692		}
9693
9694		LOCK_ZONE(zone);
9695		isqueued = notify_isqueued(zone, &ns.name, NULL);
9696		UNLOCK_ZONE(zone);
9697		if (isqueued) {
9698			result = dns_rdataset_next(&nsrdset);
9699			continue;
9700		}
9701		result = notify_create(zone->mctx, flags, &notify);
9702		if (result != ISC_R_SUCCESS)
9703			continue;
9704		dns_zone_iattach(zone, &notify->zone);
9705		result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
9706		if (result != ISC_R_SUCCESS) {
9707			LOCK_ZONE(zone);
9708			notify_destroy(notify, ISC_TRUE);
9709			UNLOCK_ZONE(zone);
9710			continue;
9711		}
9712		LOCK_ZONE(zone);
9713		ISC_LIST_APPEND(zone->notifies, notify, link);
9714		UNLOCK_ZONE(zone);
9715		notify_find_address(notify);
9716		notify = NULL;
9717		result = dns_rdataset_next(&nsrdset);
9718	}
9719	dns_rdataset_disassociate(&nsrdset);
9720
9721 cleanup3:
9722	if (dns_name_dynamic(&master))
9723		dns_name_free(&master, zone->mctx);
9724 cleanup2:
9725	dns_db_detachnode(zonedb, &node);
9726 cleanup1:
9727	dns_db_closeversion(zonedb, &version, ISC_FALSE);
9728	dns_db_detach(&zonedb);
9729}
9730
9731/***
9732 *** Private
9733 ***/
9734
9735static inline isc_result_t
9736save_nsrrset(dns_message_t *message, dns_name_t *name,
9737	     dns_db_t *db, dns_dbversion_t *version)
9738{
9739	dns_rdataset_t *nsrdataset = NULL;
9740	dns_rdataset_t *rdataset = NULL;
9741	dns_dbnode_t *node = NULL;
9742	dns_rdata_ns_t ns;
9743	isc_result_t result;
9744	dns_rdata_t rdata = DNS_RDATA_INIT;
9745
9746	/*
9747	 * Extract NS RRset from message.
9748	 */
9749	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
9750				      dns_rdatatype_ns, dns_rdatatype_none,
9751				      NULL, &nsrdataset);
9752	if (result != ISC_R_SUCCESS)
9753		goto fail;
9754
9755	/*
9756	 * Add NS rdataset.
9757	 */
9758	result = dns_db_findnode(db, name, ISC_TRUE, &node);
9759	if (result != ISC_R_SUCCESS)
9760		goto fail;
9761	result = dns_db_addrdataset(db, node, version, 0,
9762				    nsrdataset, 0, NULL);
9763	dns_db_detachnode(db, &node);
9764	if (result != ISC_R_SUCCESS)
9765		goto fail;
9766	/*
9767	 * Add glue rdatasets.
9768	 */
9769	for (result = dns_rdataset_first(nsrdataset);
9770	     result == ISC_R_SUCCESS;
9771	     result = dns_rdataset_next(nsrdataset)) {
9772		dns_rdataset_current(nsrdataset, &rdata);
9773		result = dns_rdata_tostruct(&rdata, &ns, NULL);
9774		RUNTIME_CHECK(result == ISC_R_SUCCESS);
9775		dns_rdata_reset(&rdata);
9776		if (!dns_name_issubdomain(&ns.name, name))
9777			continue;
9778		rdataset = NULL;
9779		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9780					      &ns.name, dns_rdatatype_aaaa,
9781					      dns_rdatatype_none, NULL,
9782					      &rdataset);
9783		if (result == ISC_R_SUCCESS) {
9784			result = dns_db_findnode(db, &ns.name,
9785						 ISC_TRUE, &node);
9786			if (result != ISC_R_SUCCESS)
9787				goto fail;
9788			result = dns_db_addrdataset(db, node, version, 0,
9789						    rdataset, 0, NULL);
9790			dns_db_detachnode(db, &node);
9791			if (result != ISC_R_SUCCESS)
9792				goto fail;
9793		}
9794		rdataset = NULL;
9795		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9796					      &ns.name, dns_rdatatype_a,
9797					      dns_rdatatype_none, NULL,
9798					      &rdataset);
9799		if (result == ISC_R_SUCCESS) {
9800			result = dns_db_findnode(db, &ns.name,
9801						 ISC_TRUE, &node);
9802			if (result != ISC_R_SUCCESS)
9803				goto fail;
9804			result = dns_db_addrdataset(db, node, version, 0,
9805						    rdataset, 0, NULL);
9806			dns_db_detachnode(db, &node);
9807			if (result != ISC_R_SUCCESS)
9808				goto fail;
9809		}
9810	}
9811	if (result != ISC_R_NOMORE)
9812		goto fail;
9813
9814	return (ISC_R_SUCCESS);
9815
9816fail:
9817	return (result);
9818}
9819
9820static void
9821stub_callback(isc_task_t *task, isc_event_t *event) {
9822	const char me[] = "stub_callback";
9823	dns_requestevent_t *revent = (dns_requestevent_t *)event;
9824	dns_stub_t *stub = NULL;
9825	dns_message_t *msg = NULL;
9826	dns_zone_t *zone = NULL;
9827	char master[ISC_SOCKADDR_FORMATSIZE];
9828	char source[ISC_SOCKADDR_FORMATSIZE];
9829	isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
9830	isc_result_t result;
9831	isc_time_t now;
9832	isc_boolean_t exiting = ISC_FALSE;
9833	isc_interval_t i;
9834	unsigned int j;
9835
9836	stub = revent->ev_arg;
9837	INSIST(DNS_STUB_VALID(stub));
9838
9839	UNUSED(task);
9840
9841	zone = stub->zone;
9842
9843	ENTER;
9844
9845	TIME_NOW(&now);
9846
9847	LOCK_ZONE(zone);
9848
9849	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9850		zone_debuglog(zone, me, 1, "exiting");
9851		exiting = ISC_TRUE;
9852		goto next_master;
9853	}
9854
9855	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9856	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9857
9858	if (revent->result != ISC_R_SUCCESS) {
9859		if (revent->result == ISC_R_TIMEDOUT &&
9860		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9861			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9862			dns_zone_log(zone, ISC_LOG_DEBUG(1),
9863				     "refreshing stub: timeout retrying "
9864				     " without EDNS master %s (source %s)",
9865				     master, source);
9866			goto same_master;
9867		}
9868		dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
9869					   &zone->sourceaddr, &now);
9870		dns_zone_log(zone, ISC_LOG_INFO,
9871			     "could not refresh stub from master %s"
9872			     " (source %s): %s", master, source,
9873			     dns_result_totext(revent->result));
9874		goto next_master;
9875	}
9876
9877	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9878	if (result != ISC_R_SUCCESS)
9879		goto next_master;
9880
9881	result = dns_request_getresponse(revent->request, msg, 0);
9882	if (result != ISC_R_SUCCESS)
9883		goto next_master;
9884
9885	/*
9886	 * Unexpected rcode.
9887	 */
9888	if (msg->rcode != dns_rcode_noerror) {
9889		char rcode[128];
9890		isc_buffer_t rb;
9891
9892		isc_buffer_init(&rb, rcode, sizeof(rcode));
9893		(void)dns_rcode_totext(msg->rcode, &rb);
9894
9895		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9896		    (msg->rcode == dns_rcode_servfail ||
9897		     msg->rcode == dns_rcode_notimp ||
9898		     msg->rcode == dns_rcode_formerr)) {
9899			dns_zone_log(zone, ISC_LOG_DEBUG(1),
9900				     "refreshing stub: rcode (%.*s) retrying "
9901				     "without EDNS master %s (source %s)",
9902				     (int)rb.used, rcode, master, source);
9903			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9904			goto same_master;
9905		}
9906
9907		dns_zone_log(zone, ISC_LOG_INFO,
9908			     "refreshing stub: "
9909			     "unexpected rcode (%.*s) from %s (source %s)",
9910			     (int)rb.used, rcode, master, source);
9911		goto next_master;
9912	}
9913
9914	/*
9915	 * We need complete messages.
9916	 */
9917	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9918		if (dns_request_usedtcp(revent->request)) {
9919			dns_zone_log(zone, ISC_LOG_INFO,
9920				     "refreshing stub: truncated TCP "
9921				     "response from master %s (source %s)",
9922				     master, source);
9923			goto next_master;
9924		}
9925		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9926		goto same_master;
9927	}
9928
9929	/*
9930	 * If non-auth log and next master.
9931	 */
9932	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9933		dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
9934			     "non-authoritative answer from "
9935			     "master %s (source %s)", master, source);
9936		goto next_master;
9937	}
9938
9939	/*
9940	 * Sanity checks.
9941	 */
9942	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9943	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
9944
9945	if (cnamecnt != 0) {
9946		dns_zone_log(zone, ISC_LOG_INFO,
9947			     "refreshing stub: unexpected CNAME response "
9948			     "from master %s (source %s)", master, source);
9949		goto next_master;
9950	}
9951
9952	if (nscnt == 0) {
9953		dns_zone_log(zone, ISC_LOG_INFO,
9954			     "refreshing stub: no NS records in response "
9955			     "from master %s (source %s)", master, source);
9956		goto next_master;
9957	}
9958
9959	/*
9960	 * Save answer.
9961	 */
9962	result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
9963	if (result != ISC_R_SUCCESS) {
9964		dns_zone_log(zone, ISC_LOG_INFO,
9965			     "refreshing stub: unable to save NS records "
9966			     "from master %s (source %s)", master, source);
9967		goto next_master;
9968	}
9969
9970	/*
9971	 * Tidy up.
9972	 */
9973	dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
9974	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9975	if (zone->db == NULL)
9976		zone_attachdb(zone, stub->db);
9977	result = zone_get_from_db(zone, zone->db, NULL, NULL, NULL, &refresh,
9978				  &retry, &expire, NULL, NULL);
9979	if (result == ISC_R_SUCCESS) {
9980		zone->refresh = RANGE(refresh, zone->minrefresh,
9981				      zone->maxrefresh);
9982		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
9983		zone->expire = RANGE(expire, zone->refresh + zone->retry,
9984				     DNS_MAX_EXPIRE);
9985		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9986	}
9987	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9988	dns_db_detach(&stub->db);
9989
9990	dns_message_destroy(&msg);
9991	isc_event_free(&event);
9992	dns_request_destroy(&zone->request);
9993
9994	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9995	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
9996	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9997	isc_interval_set(&i, zone->expire, 0);
9998	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9999
10000	if (zone->masterfile != NULL)
10001		zone_needdump(zone, 0);
10002
10003	zone_settimer(zone, &now);
10004	goto free_stub;
10005
10006 next_master:
10007	if (stub->version != NULL)
10008		dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
10009	if (stub->db != NULL)
10010		dns_db_detach(&stub->db);
10011	if (msg != NULL)
10012		dns_message_destroy(&msg);
10013	isc_event_free(&event);
10014	dns_request_destroy(&zone->request);
10015	/*
10016	 * Skip to next failed / untried master.
10017	 */
10018	do {
10019		zone->curmaster++;
10020	} while (zone->curmaster < zone->masterscnt &&
10021		 zone->mastersok[zone->curmaster]);
10022	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10023	if (exiting || zone->curmaster >= zone->masterscnt) {
10024		isc_boolean_t done = ISC_TRUE;
10025		if (!exiting &&
10026		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10027		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10028			/*
10029			 * Did we get a good answer from all the masters?
10030			 */
10031			for (j = 0; j < zone->masterscnt; j++)
10032				if (zone->mastersok[j] == ISC_FALSE) {
10033					done = ISC_FALSE;
10034					break;
10035				}
10036		} else
10037			done = ISC_TRUE;
10038		if (!done) {
10039			zone->curmaster = 0;
10040			/*
10041			 * Find the next failed master.
10042			 */
10043			while (zone->curmaster < zone->masterscnt &&
10044			       zone->mastersok[zone->curmaster])
10045				zone->curmaster++;
10046			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10047		} else {
10048			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10049
10050			zone_settimer(zone, &now);
10051			goto free_stub;
10052		}
10053	}
10054	queue_soa_query(zone);
10055	goto free_stub;
10056
10057 same_master:
10058	if (msg != NULL)
10059		dns_message_destroy(&msg);
10060	isc_event_free(&event);
10061	dns_request_destroy(&zone->request);
10062	ns_query(zone, NULL, stub);
10063	UNLOCK_ZONE(zone);
10064	goto done;
10065
10066 free_stub:
10067	UNLOCK_ZONE(zone);
10068	stub->magic = 0;
10069	dns_zone_idetach(&stub->zone);
10070	INSIST(stub->db == NULL);
10071	INSIST(stub->version == NULL);
10072	isc_mem_put(stub->mctx, stub, sizeof(*stub));
10073
10074 done:
10075	INSIST(event == NULL);
10076	return;
10077}
10078
10079/*
10080 * An SOA query has finished (successfully or not).
10081 */
10082static void
10083refresh_callback(isc_task_t *task, isc_event_t *event) {
10084	const char me[] = "refresh_callback";
10085	dns_requestevent_t *revent = (dns_requestevent_t *)event;
10086	dns_zone_t *zone;
10087	dns_message_t *msg = NULL;
10088	isc_uint32_t soacnt, cnamecnt, soacount, nscount;
10089	isc_time_t now;
10090	char master[ISC_SOCKADDR_FORMATSIZE];
10091	char source[ISC_SOCKADDR_FORMATSIZE];
10092	dns_rdataset_t *rdataset = NULL;
10093	dns_rdata_t rdata = DNS_RDATA_INIT;
10094	dns_rdata_soa_t soa;
10095	isc_result_t result;
10096	isc_uint32_t serial, oldserial = 0;
10097	unsigned int j;
10098	isc_boolean_t do_queue_xfrin = ISC_FALSE;
10099
10100	zone = revent->ev_arg;
10101	INSIST(DNS_ZONE_VALID(zone));
10102
10103	UNUSED(task);
10104
10105	ENTER;
10106
10107	TIME_NOW(&now);
10108
10109	LOCK_ZONE(zone);
10110
10111	/*
10112	 * if timeout log and next master;
10113	 */
10114
10115	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10116	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10117
10118	if (revent->result != ISC_R_SUCCESS) {
10119		if (revent->result == ISC_R_TIMEDOUT &&
10120		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10121			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10122			dns_zone_log(zone, ISC_LOG_DEBUG(1),
10123				     "refresh: timeout retrying without EDNS "
10124				     "master %s (source %s)", master, source);
10125			goto same_master;
10126		}
10127		if (revent->result == ISC_R_TIMEDOUT &&
10128		    !dns_request_usedtcp(revent->request)) {
10129			dns_zone_log(zone, ISC_LOG_INFO,
10130				     "refresh: retry limit for "
10131				     "master %s exceeded (source %s)",
10132				     master, source);
10133			/* Try with slave with TCP. */
10134			if ((zone->type == dns_zone_slave ||
10135			     zone->type == dns_zone_redirect) &&
10136			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
10137				if (!dns_zonemgr_unreachable(zone->zmgr,
10138							     &zone->masteraddr,
10139							     &zone->sourceaddr,
10140							     &now))
10141				{
10142					DNS_ZONE_SETFLAG(zone,
10143						     DNS_ZONEFLG_SOABEFOREAXFR);
10144					goto tcp_transfer;
10145				}
10146				dns_zone_log(zone, ISC_LOG_DEBUG(1),
10147					     "refresh: skipped tcp fallback "
10148					     "as master %s (source %s) is "
10149					     "unreachable (cached)",
10150					      master, source);
10151			}
10152		} else
10153			dns_zone_log(zone, ISC_LOG_INFO,
10154				     "refresh: failure trying master "
10155				     "%s (source %s): %s", master, source,
10156				     dns_result_totext(revent->result));
10157		goto next_master;
10158	}
10159
10160	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10161	if (result != ISC_R_SUCCESS)
10162		goto next_master;
10163	result = dns_request_getresponse(revent->request, msg, 0);
10164	if (result != ISC_R_SUCCESS) {
10165		dns_zone_log(zone, ISC_LOG_INFO,
10166			     "refresh: failure trying master "
10167			     "%s (source %s): %s", master, source,
10168			     dns_result_totext(result));
10169		goto next_master;
10170	}
10171
10172	/*
10173	 * Unexpected rcode.
10174	 */
10175	if (msg->rcode != dns_rcode_noerror) {
10176		char rcode[128];
10177		isc_buffer_t rb;
10178
10179		isc_buffer_init(&rb, rcode, sizeof(rcode));
10180		(void)dns_rcode_totext(msg->rcode, &rb);
10181
10182		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10183		    (msg->rcode == dns_rcode_servfail ||
10184		     msg->rcode == dns_rcode_notimp ||
10185		     msg->rcode == dns_rcode_formerr)) {
10186			dns_zone_log(zone, ISC_LOG_DEBUG(1),
10187				     "refresh: rcode (%.*s) retrying without "
10188				     "EDNS master %s (source %s)",
10189				     (int)rb.used, rcode, master, source);
10190			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10191			goto same_master;
10192		}
10193		dns_zone_log(zone, ISC_LOG_INFO,
10194			     "refresh: unexpected rcode (%.*s) from "
10195			     "master %s (source %s)", (int)rb.used, rcode,
10196			     master, source);
10197		/*
10198		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
10199		 */
10200		if (msg->rcode == dns_rcode_refused &&
10201		    (zone->type == dns_zone_slave ||
10202		     zone->type == dns_zone_redirect))
10203			goto tcp_transfer;
10204		goto next_master;
10205	}
10206
10207	/*
10208	 * If truncated punt to zone transfer which will query again.
10209	 */
10210	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10211		if (zone->type == dns_zone_slave ||
10212		    zone->type == dns_zone_redirect) {
10213			dns_zone_log(zone, ISC_LOG_INFO,
10214				     "refresh: truncated UDP answer, "
10215				     "initiating TCP zone xfer "
10216				     "for master %s (source %s)",
10217				     master, source);
10218			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
10219			goto tcp_transfer;
10220		} else {
10221			INSIST(zone->type == dns_zone_stub);
10222			if (dns_request_usedtcp(revent->request)) {
10223				dns_zone_log(zone, ISC_LOG_INFO,
10224					     "refresh: truncated TCP response "
10225					     "from master %s (source %s)",
10226					     master, source);
10227				goto next_master;
10228			}
10229			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10230			goto same_master;
10231		}
10232	}
10233
10234	/*
10235	 * if non-auth log and next master;
10236	 */
10237	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10238		dns_zone_log(zone, ISC_LOG_INFO,
10239			     "refresh: non-authoritative answer from "
10240			     "master %s (source %s)", master, source);
10241		goto next_master;
10242	}
10243
10244	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10245	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
10246	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
10247	soacount = message_count(msg, DNS_SECTION_AUTHORITY,
10248				 dns_rdatatype_soa);
10249
10250	/*
10251	 * There should not be a CNAME record at top of zone.
10252	 */
10253	if (cnamecnt != 0) {
10254		dns_zone_log(zone, ISC_LOG_INFO,
10255			     "refresh: CNAME at top of zone "
10256			     "in master %s (source %s)", master, source);
10257		goto next_master;
10258	}
10259
10260	/*
10261	 * if referral log and next master;
10262	 */
10263	if (soacnt == 0 && soacount == 0 && nscount != 0) {
10264		dns_zone_log(zone, ISC_LOG_INFO,
10265			     "refresh: referral response "
10266			     "from master %s (source %s)", master, source);
10267		goto next_master;
10268	}
10269
10270	/*
10271	 * if nodata log and next master;
10272	 */
10273	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
10274		dns_zone_log(zone, ISC_LOG_INFO,
10275			     "refresh: NODATA response "
10276			     "from master %s (source %s)", master, source);
10277		goto next_master;
10278	}
10279
10280	/*
10281	 * Only one soa at top of zone.
10282	 */
10283	if (soacnt != 1) {
10284		dns_zone_log(zone, ISC_LOG_INFO,
10285			     "refresh: answer SOA count (%d) != 1 "
10286			     "from master %s (source %s)",
10287			     soacnt, master, source);
10288		goto next_master;
10289	}
10290
10291	/*
10292	 * Extract serial
10293	 */
10294	rdataset = NULL;
10295	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
10296				      dns_rdatatype_soa, dns_rdatatype_none,
10297				      NULL, &rdataset);
10298	if (result != ISC_R_SUCCESS) {
10299		dns_zone_log(zone, ISC_LOG_INFO,
10300			     "refresh: unable to get SOA record "
10301			     "from master %s (source %s)", master, source);
10302		goto next_master;
10303	}
10304
10305	result = dns_rdataset_first(rdataset);
10306	if (result != ISC_R_SUCCESS) {
10307		dns_zone_log(zone, ISC_LOG_INFO,
10308			     "refresh: dns_rdataset_first() failed");
10309		goto next_master;
10310	}
10311
10312	dns_rdataset_current(rdataset, &rdata);
10313	result = dns_rdata_tostruct(&rdata, &soa, NULL);
10314	RUNTIME_CHECK(result == ISC_R_SUCCESS);
10315
10316	serial = soa.serial;
10317	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10318		result = zone_get_from_db(zone, zone->db, NULL, NULL,
10319					  &oldserial, NULL, NULL, NULL, NULL,
10320					  NULL);
10321		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10322		zone_debuglog(zone, me, 1, "serial: new %u, old %u",
10323			      serial, oldserial);
10324	} else
10325		zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
10326			      serial);
10327
10328	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
10329	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
10330	    isc_serial_gt(serial, oldserial)) {
10331		if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
10332					    &zone->sourceaddr, &now))
10333		{
10334			dns_zone_log(zone, ISC_LOG_INFO,
10335				     "refresh: skipping %s as master %s "
10336				     "(source %s) is unreachable (cached)",
10337				     (zone->type == dns_zone_slave ||
10338				      zone->type == dns_zone_redirect) ?
10339				     "zone transfer" : "NS query",
10340				     master, source);
10341			goto next_master;
10342		}
10343 tcp_transfer:
10344		isc_event_free(&event);
10345		dns_request_destroy(&zone->request);
10346		if (zone->type == dns_zone_slave ||
10347		    zone->type == dns_zone_redirect) {
10348			do_queue_xfrin = ISC_TRUE;
10349		} else {
10350			INSIST(zone->type == dns_zone_stub);
10351			ns_query(zone, rdataset, NULL);
10352		}
10353		if (msg != NULL)
10354			dns_message_destroy(&msg);
10355	} else if (isc_serial_eq(soa.serial, oldserial)) {
10356		if (zone->masterfile != NULL) {
10357			result = ISC_R_FAILURE;
10358			if (zone->journal != NULL)
10359				result = isc_file_settime(zone->journal, &now);
10360			if (result == ISC_R_SUCCESS &&
10361			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10362			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10363				result = isc_file_settime(zone->masterfile,
10364							  &now);
10365			} else if (result != ISC_R_SUCCESS)
10366				result = isc_file_settime(zone->masterfile,
10367							  &now);
10368			/* Someone removed the file from underneath us! */
10369			if (result == ISC_R_FILENOTFOUND) {
10370				zone_needdump(zone, DNS_DUMP_DELAY);
10371			} else if (result != ISC_R_SUCCESS)
10372				dns_zone_log(zone, ISC_LOG_ERROR,
10373					     "refresh: could not set file "
10374					     "modification time of '%s': %s",
10375					     zone->masterfile,
10376					     dns_result_totext(result));
10377		}
10378		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10379		DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10380		zone->mastersok[zone->curmaster] = ISC_TRUE;
10381		goto next_master;
10382	} else {
10383		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
10384			dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
10385				     "received from master %s < ours (%u)",
10386				     soa.serial, master, oldserial);
10387		else
10388			zone_debuglog(zone, me, 1, "ahead");
10389		zone->mastersok[zone->curmaster] = ISC_TRUE;
10390		goto next_master;
10391	}
10392	if (msg != NULL)
10393		dns_message_destroy(&msg);
10394	goto detach;
10395
10396 next_master:
10397	if (msg != NULL)
10398		dns_message_destroy(&msg);
10399	isc_event_free(&event);
10400	dns_request_destroy(&zone->request);
10401	/*
10402	 * Skip to next failed / untried master.
10403	 */
10404	do {
10405		zone->curmaster++;
10406	} while (zone->curmaster < zone->masterscnt &&
10407		 zone->mastersok[zone->curmaster]);
10408	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10409	if (zone->curmaster >= zone->masterscnt) {
10410		isc_boolean_t done = ISC_TRUE;
10411		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10412		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10413			/*
10414			 * Did we get a good answer from all the masters?
10415			 */
10416			for (j = 0; j < zone->masterscnt; j++)
10417				if (zone->mastersok[j] == ISC_FALSE) {
10418					done = ISC_FALSE;
10419					break;
10420				}
10421		} else
10422			done = ISC_TRUE;
10423		if (!done) {
10424			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10425			zone->curmaster = 0;
10426			/*
10427			 * Find the next failed master.
10428			 */
10429			while (zone->curmaster < zone->masterscnt &&
10430			       zone->mastersok[zone->curmaster])
10431				zone->curmaster++;
10432			goto requeue;
10433		}
10434		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10435		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
10436			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10437			zone->refreshtime = now;
10438		}
10439		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10440		zone_settimer(zone, &now);
10441		goto detach;
10442	}
10443
10444 requeue:
10445	queue_soa_query(zone);
10446	goto detach;
10447
10448 same_master:
10449	if (msg != NULL)
10450		dns_message_destroy(&msg);
10451	isc_event_free(&event);
10452	dns_request_destroy(&zone->request);
10453	queue_soa_query(zone);
10454
10455 detach:
10456	UNLOCK_ZONE(zone);
10457	if (do_queue_xfrin)
10458		queue_xfrin(zone);
10459	dns_zone_idetach(&zone);
10460	return;
10461}
10462
10463static void
10464queue_soa_query(dns_zone_t *zone) {
10465	const char me[] = "queue_soa_query";
10466	isc_event_t *e;
10467	dns_zone_t *dummy = NULL;
10468	isc_result_t result;
10469
10470	ENTER;
10471	/*
10472	 * Locked by caller
10473	 */
10474	REQUIRE(LOCKED_ZONE(zone));
10475
10476	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10477		cancel_refresh(zone);
10478		return;
10479	}
10480
10481	e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
10482			       soa_query, zone, sizeof(isc_event_t));
10483	if (e == NULL) {
10484		cancel_refresh(zone);
10485		return;
10486	}
10487
10488	/*
10489	 * Attach so that we won't clean up
10490	 * until the event is delivered.
10491	 */
10492	zone_iattach(zone, &dummy);
10493
10494	e->ev_arg = zone;
10495	e->ev_sender = NULL;
10496	result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
10497	if (result != ISC_R_SUCCESS) {
10498		zone_idetach(&dummy);
10499		isc_event_free(&e);
10500		cancel_refresh(zone);
10501	}
10502}
10503
10504static inline isc_result_t
10505create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
10506	     dns_message_t **messagep)
10507{
10508	dns_message_t *message = NULL;
10509	dns_name_t *qname = NULL;
10510	dns_rdataset_t *qrdataset = NULL;
10511	isc_result_t result;
10512
10513	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10514				    &message);
10515	if (result != ISC_R_SUCCESS)
10516		goto cleanup;
10517
10518	message->opcode = dns_opcode_query;
10519	message->rdclass = zone->rdclass;
10520
10521	result = dns_message_gettempname(message, &qname);
10522	if (result != ISC_R_SUCCESS)
10523		goto cleanup;
10524
10525	result = dns_message_gettemprdataset(message, &qrdataset);
10526	if (result != ISC_R_SUCCESS)
10527		goto cleanup;
10528
10529	/*
10530	 * Make question.
10531	 */
10532	dns_name_init(qname, NULL);
10533	dns_name_clone(&zone->origin, qname);
10534	dns_rdataset_init(qrdataset);
10535	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
10536	ISC_LIST_APPEND(qname->list, qrdataset, link);
10537	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
10538
10539	*messagep = message;
10540	return (ISC_R_SUCCESS);
10541
10542 cleanup:
10543	if (qname != NULL)
10544		dns_message_puttempname(message, &qname);
10545	if (qrdataset != NULL)
10546		dns_message_puttemprdataset(message, &qrdataset);
10547	if (message != NULL)
10548		dns_message_destroy(&message);
10549	return (result);
10550}
10551
10552static isc_result_t
10553add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
10554	dns_rdataset_t *rdataset = NULL;
10555	dns_rdatalist_t *rdatalist = NULL;
10556	dns_rdata_t *rdata = NULL;
10557	isc_result_t result;
10558
10559	result = dns_message_gettemprdatalist(message, &rdatalist);
10560	if (result != ISC_R_SUCCESS)
10561		goto cleanup;
10562	result = dns_message_gettemprdata(message, &rdata);
10563	if (result != ISC_R_SUCCESS)
10564		goto cleanup;
10565	result = dns_message_gettemprdataset(message, &rdataset);
10566	if (result != ISC_R_SUCCESS)
10567		goto cleanup;
10568	dns_rdataset_init(rdataset);
10569
10570	rdatalist->type = dns_rdatatype_opt;
10571	rdatalist->covers = 0;
10572
10573	/*
10574	 * Set Maximum UDP buffer size.
10575	 */
10576	rdatalist->rdclass = udpsize;
10577
10578	/*
10579	 * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
10580	 */
10581	rdatalist->ttl = 0;
10582
10583	/* Set EDNS options if applicable */
10584	if (reqnsid) {
10585		unsigned char data[4];
10586		isc_buffer_t buf;
10587
10588		isc_buffer_init(&buf, data, sizeof(data));
10589		isc_buffer_putuint16(&buf, DNS_OPT_NSID);
10590		isc_buffer_putuint16(&buf, 0);
10591		rdata->data = data;
10592		rdata->length = sizeof(data);
10593	} else {
10594		rdata->data = NULL;
10595		rdata->length = 0;
10596	}
10597
10598	rdata->rdclass = rdatalist->rdclass;
10599	rdata->type = rdatalist->type;
10600	rdata->flags = 0;
10601
10602	ISC_LIST_INIT(rdatalist->rdata);
10603	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
10604	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
10605		      == ISC_R_SUCCESS);
10606
10607	return (dns_message_setopt(message, rdataset));
10608
10609 cleanup:
10610	if (rdatalist != NULL)
10611		dns_message_puttemprdatalist(message, &rdatalist);
10612	if (rdataset != NULL)
10613		dns_message_puttemprdataset(message, &rdataset);
10614	if (rdata != NULL)
10615		dns_message_puttemprdata(message, &rdata);
10616
10617	return (result);
10618}
10619
10620static void
10621soa_query(isc_task_t *task, isc_event_t *event) {
10622	const char me[] = "soa_query";
10623	isc_result_t result = ISC_R_FAILURE;
10624	dns_message_t *message = NULL;
10625	dns_zone_t *zone = event->ev_arg;
10626	dns_zone_t *dummy = NULL;
10627	isc_netaddr_t masterip;
10628	dns_tsigkey_t *key = NULL;
10629	isc_uint32_t options;
10630	isc_boolean_t cancel = ISC_TRUE;
10631	int timeout;
10632	isc_boolean_t have_xfrsource, reqnsid;
10633	isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10634
10635	REQUIRE(DNS_ZONE_VALID(zone));
10636
10637	UNUSED(task);
10638
10639	ENTER;
10640
10641	LOCK_ZONE(zone);
10642	if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
10643	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
10644	    zone->view->requestmgr == NULL) {
10645		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10646			cancel = ISC_FALSE;
10647		goto cleanup;
10648	}
10649
10650	/*
10651	 * XXX Optimisation: Create message when zone is setup and reuse.
10652	 */
10653	result = create_query(zone, dns_rdatatype_soa, &message);
10654	if (result != ISC_R_SUCCESS)
10655		goto cleanup;
10656
10657 again:
10658	INSIST(zone->masterscnt > 0);
10659	INSIST(zone->curmaster < zone->masterscnt);
10660
10661	zone->masteraddr = zone->masters[zone->curmaster];
10662
10663	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10664	/*
10665	 * First, look for a tsig key in the master statement, then
10666	 * try for a server key.
10667	 */
10668	if ((zone->masterkeynames != NULL) &&
10669	    (zone->masterkeynames[zone->curmaster] != NULL)) {
10670		dns_view_t *view = dns_zone_getview(zone);
10671		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10672		result = dns_view_gettsig(view, keyname, &key);
10673		if (result != ISC_R_SUCCESS) {
10674			char namebuf[DNS_NAME_FORMATSIZE];
10675			dns_name_format(keyname, namebuf, sizeof(namebuf));
10676			dns_zone_log(zone, ISC_LOG_ERROR,
10677				     "unable to find key: %s", namebuf);
10678			goto skip_master;
10679		}
10680	}
10681	if (key == NULL) {
10682		result = dns_view_getpeertsig(zone->view, &masterip, &key);
10683		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
10684			char addrbuf[ISC_NETADDR_FORMATSIZE];
10685			isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
10686			dns_zone_log(zone, ISC_LOG_ERROR,
10687				     "unable to find TSIG key for %s", addrbuf);
10688			goto skip_master;
10689		}
10690	}
10691
10692	have_xfrsource = ISC_FALSE;
10693	reqnsid = zone->view->requestnsid;
10694	if (zone->view->peers != NULL) {
10695		dns_peer_t *peer = NULL;
10696		isc_boolean_t edns;
10697		result = dns_peerlist_peerbyaddr(zone->view->peers,
10698						 &masterip, &peer);
10699		if (result == ISC_R_SUCCESS) {
10700			result = dns_peer_getsupportedns(peer, &edns);
10701			if (result == ISC_R_SUCCESS && !edns)
10702				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10703			result = dns_peer_gettransfersource(peer,
10704							    &zone->sourceaddr);
10705			if (result == ISC_R_SUCCESS)
10706				have_xfrsource = ISC_TRUE;
10707			if (zone->view->resolver != NULL)
10708				udpsize =
10709				  dns_resolver_getudpsize(zone->view->resolver);
10710			(void)dns_peer_getudpsize(peer, &udpsize);
10711			(void)dns_peer_getrequestnsid(peer, &reqnsid);
10712		}
10713	}
10714
10715	switch (isc_sockaddr_pf(&zone->masteraddr)) {
10716	case PF_INET:
10717		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10718			if (isc_sockaddr_equal(&zone->altxfrsource4,
10719					       &zone->xfrsource4))
10720				goto skip_master;
10721			zone->sourceaddr = zone->altxfrsource4;
10722		} else if (!have_xfrsource)
10723			zone->sourceaddr = zone->xfrsource4;
10724		break;
10725	case PF_INET6:
10726		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10727			if (isc_sockaddr_equal(&zone->altxfrsource6,
10728					       &zone->xfrsource6))
10729				goto skip_master;
10730			zone->sourceaddr = zone->altxfrsource6;
10731		} else if (!have_xfrsource)
10732			zone->sourceaddr = zone->xfrsource6;
10733		break;
10734	default:
10735		result = ISC_R_NOTIMPLEMENTED;
10736		goto cleanup;
10737	}
10738
10739	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
10740		  DNS_REQUESTOPT_TCP : 0;
10741
10742	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10743		result = add_opt(message, udpsize, reqnsid);
10744		if (result != ISC_R_SUCCESS)
10745			zone_debuglog(zone, me, 1,
10746				      "unable to add opt record: %s",
10747				      dns_result_totext(result));
10748	}
10749
10750	zone_iattach(zone, &dummy);
10751	timeout = 15;
10752	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10753		timeout = 30;
10754	result = dns_request_createvia2(zone->view->requestmgr, message,
10755					&zone->sourceaddr, &zone->masteraddr,
10756					options, key, timeout * 3, timeout,
10757					zone->task, refresh_callback, zone,
10758					&zone->request);
10759	if (result != ISC_R_SUCCESS) {
10760		zone_idetach(&dummy);
10761		zone_debuglog(zone, me, 1,
10762			      "dns_request_createvia2() failed: %s",
10763			      dns_result_totext(result));
10764		goto cleanup;
10765	} else {
10766		if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
10767			inc_stats(zone, dns_zonestatscounter_soaoutv4);
10768		else
10769			inc_stats(zone, dns_zonestatscounter_soaoutv6);
10770	}
10771	cancel = ISC_FALSE;
10772
10773 cleanup:
10774	if (key != NULL)
10775		dns_tsigkey_detach(&key);
10776	if (result != ISC_R_SUCCESS)
10777		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10778	if (message != NULL)
10779		dns_message_destroy(&message);
10780	if (cancel)
10781		cancel_refresh(zone);
10782	isc_event_free(&event);
10783	UNLOCK_ZONE(zone);
10784	dns_zone_idetach(&zone);
10785	return;
10786
10787 skip_master:
10788	if (key != NULL)
10789		dns_tsigkey_detach(&key);
10790	/*
10791	 * Skip to next failed / untried master.
10792	 */
10793	do {
10794		zone->curmaster++;
10795	} while (zone->curmaster < zone->masterscnt &&
10796		 zone->mastersok[zone->curmaster]);
10797	if (zone->curmaster < zone->masterscnt)
10798		goto again;
10799	zone->curmaster = 0;
10800	goto cleanup;
10801}
10802
10803static void
10804ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
10805	const char me[] = "ns_query";
10806	isc_result_t result;
10807	dns_message_t *message = NULL;
10808	isc_netaddr_t masterip;
10809	dns_tsigkey_t *key = NULL;
10810	dns_dbnode_t *node = NULL;
10811	int timeout;
10812	isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
10813	isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10814
10815	REQUIRE(DNS_ZONE_VALID(zone));
10816	REQUIRE(LOCKED_ZONE(zone));
10817	REQUIRE((soardataset != NULL && stub == NULL) ||
10818		(soardataset == NULL && stub != NULL));
10819	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
10820
10821	ENTER;
10822
10823	if (stub == NULL) {
10824		stub = isc_mem_get(zone->mctx, sizeof(*stub));
10825		if (stub == NULL)
10826			goto cleanup;
10827		stub->magic = STUB_MAGIC;
10828		stub->mctx = zone->mctx;
10829		stub->zone = NULL;
10830		stub->db = NULL;
10831		stub->version = NULL;
10832
10833		/*
10834		 * Attach so that the zone won't disappear from under us.
10835		 */
10836		zone_iattach(zone, &stub->zone);
10837
10838		/*
10839		 * If a db exists we will update it, otherwise we create a
10840		 * new one and attach it to the zone once we have the NS
10841		 * RRset and glue.
10842		 */
10843		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10844		if (zone->db != NULL) {
10845			dns_db_attach(zone->db, &stub->db);
10846			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10847		} else {
10848			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10849
10850			INSIST(zone->db_argc >= 1);
10851			result = dns_db_create(zone->mctx, zone->db_argv[0],
10852					       &zone->origin, dns_dbtype_stub,
10853					       zone->rdclass,
10854					       zone->db_argc - 1,
10855					       zone->db_argv + 1,
10856					       &stub->db);
10857			if (result != ISC_R_SUCCESS) {
10858				dns_zone_log(zone, ISC_LOG_ERROR,
10859					     "refreshing stub: "
10860					     "could not create "
10861					     "database: %s",
10862					     dns_result_totext(result));
10863				goto cleanup;
10864			}
10865			dns_db_settask(stub->db, zone->task);
10866		}
10867
10868		result = dns_db_newversion(stub->db, &stub->version);
10869		if (result != ISC_R_SUCCESS) {
10870			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10871				     "dns_db_newversion() failed: %s",
10872				     dns_result_totext(result));
10873			goto cleanup;
10874		}
10875
10876		/*
10877		 * Update SOA record.
10878		 */
10879		result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
10880					 &node);
10881		if (result != ISC_R_SUCCESS) {
10882			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10883				     "dns_db_findnode() failed: %s",
10884				     dns_result_totext(result));
10885			goto cleanup;
10886		}
10887
10888		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
10889					    soardataset, 0, NULL);
10890		dns_db_detachnode(stub->db, &node);
10891		if (result != ISC_R_SUCCESS) {
10892			dns_zone_log(zone, ISC_LOG_INFO,
10893				     "refreshing stub: "
10894				     "dns_db_addrdataset() failed: %s",
10895				     dns_result_totext(result));
10896			goto cleanup;
10897		}
10898	}
10899
10900	/*
10901	 * XXX Optimisation: Create message when zone is setup and reuse.
10902	 */
10903	result = create_query(zone, dns_rdatatype_ns, &message);
10904	INSIST(result == ISC_R_SUCCESS);
10905
10906	INSIST(zone->masterscnt > 0);
10907	INSIST(zone->curmaster < zone->masterscnt);
10908	zone->masteraddr = zone->masters[zone->curmaster];
10909
10910	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10911	/*
10912	 * First, look for a tsig key in the master statement, then
10913	 * try for a server key.
10914	 */
10915	if ((zone->masterkeynames != NULL) &&
10916	    (zone->masterkeynames[zone->curmaster] != NULL)) {
10917		dns_view_t *view = dns_zone_getview(zone);
10918		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10919		result = dns_view_gettsig(view, keyname, &key);
10920		if (result != ISC_R_SUCCESS) {
10921			char namebuf[DNS_NAME_FORMATSIZE];
10922			dns_name_format(keyname, namebuf, sizeof(namebuf));
10923			dns_zone_log(zone, ISC_LOG_ERROR,
10924				     "unable to find key: %s", namebuf);
10925		}
10926	}
10927	if (key == NULL)
10928		(void)dns_view_getpeertsig(zone->view, &masterip, &key);
10929
10930	reqnsid = zone->view->requestnsid;
10931	if (zone->view->peers != NULL) {
10932		dns_peer_t *peer = NULL;
10933		isc_boolean_t edns;
10934		result = dns_peerlist_peerbyaddr(zone->view->peers,
10935						 &masterip, &peer);
10936		if (result == ISC_R_SUCCESS) {
10937			result = dns_peer_getsupportedns(peer, &edns);
10938			if (result == ISC_R_SUCCESS && !edns)
10939				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10940			result = dns_peer_gettransfersource(peer,
10941							    &zone->sourceaddr);
10942			if (result == ISC_R_SUCCESS)
10943				have_xfrsource = ISC_TRUE;
10944			if (zone->view->resolver != NULL)
10945				udpsize =
10946				  dns_resolver_getudpsize(zone->view->resolver);
10947			(void)dns_peer_getudpsize(peer, &udpsize);
10948			(void)dns_peer_getrequestnsid(peer, &reqnsid);
10949		}
10950
10951	}
10952	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10953		result = add_opt(message, udpsize, reqnsid);
10954		if (result != ISC_R_SUCCESS)
10955			zone_debuglog(zone, me, 1,
10956				      "unable to add opt record: %s",
10957				      dns_result_totext(result));
10958	}
10959
10960	/*
10961	 * Always use TCP so that we shouldn't truncate in additional section.
10962	 */
10963	switch (isc_sockaddr_pf(&zone->masteraddr)) {
10964	case PF_INET:
10965		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10966			zone->sourceaddr = zone->altxfrsource4;
10967		else if (!have_xfrsource)
10968			zone->sourceaddr = zone->xfrsource4;
10969		break;
10970	case PF_INET6:
10971		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10972			zone->sourceaddr = zone->altxfrsource6;
10973		else if (!have_xfrsource)
10974			zone->sourceaddr = zone->xfrsource6;
10975		break;
10976	default:
10977		result = ISC_R_NOTIMPLEMENTED;
10978		POST(result);
10979		goto cleanup;
10980	}
10981	timeout = 15;
10982	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10983		timeout = 30;
10984	result = dns_request_createvia2(zone->view->requestmgr, message,
10985					&zone->sourceaddr, &zone->masteraddr,
10986					DNS_REQUESTOPT_TCP, key, timeout * 3,
10987					timeout, zone->task, stub_callback,
10988					stub, &zone->request);
10989	if (result != ISC_R_SUCCESS) {
10990		zone_debuglog(zone, me, 1,
10991			      "dns_request_createvia() failed: %s",
10992			      dns_result_totext(result));
10993		goto cleanup;
10994	}
10995	dns_message_destroy(&message);
10996	goto unlock;
10997
10998 cleanup:
10999	cancel_refresh(zone);
11000	if (stub != NULL) {
11001		stub->magic = 0;
11002		if (stub->version != NULL)
11003			dns_db_closeversion(stub->db, &stub->version,
11004					    ISC_FALSE);
11005		if (stub->db != NULL)
11006			dns_db_detach(&stub->db);
11007		if (stub->zone != NULL)
11008			zone_idetach(&stub->zone);
11009		isc_mem_put(stub->mctx, stub, sizeof(*stub));
11010	}
11011	if (message != NULL)
11012		dns_message_destroy(&message);
11013 unlock:
11014	if (key != NULL)
11015		dns_tsigkey_detach(&key);
11016	return;
11017}
11018
11019/*
11020 * Handle the control event.  Note that although this event causes the zone
11021 * to shut down, it is not a shutdown event in the sense of the task library.
11022 */
11023static void
11024zone_shutdown(isc_task_t *task, isc_event_t *event) {
11025	dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
11026	isc_boolean_t free_needed, linked = ISC_FALSE;
11027	dns_zone_t *raw = NULL, *secure = NULL;
11028
11029	UNUSED(task);
11030	REQUIRE(DNS_ZONE_VALID(zone));
11031	INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
11032	INSIST(isc_refcount_current(&zone->erefs) == 0);
11033
11034	zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
11035
11036	/*
11037	 * Stop things being restarted after we cancel them below.
11038	 */
11039	LOCK_ZONE(zone);
11040	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
11041	UNLOCK_ZONE(zone);
11042
11043	/*
11044	 * If we were waiting for xfrin quota, step out of
11045	 * the queue.
11046	 * If there's no zone manager, we can't be waiting for the
11047	 * xfrin quota
11048	 */
11049	if (zone->zmgr != NULL) {
11050		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11051		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
11052			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
11053					statelink);
11054			linked = ISC_TRUE;
11055			zone->statelist = NULL;
11056		}
11057		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11058	}
11059
11060	/*
11061	 * In task context, no locking required.  See zone_xfrdone().
11062	 */
11063	if (zone->xfr != NULL)
11064		dns_xfrin_shutdown(zone->xfr);
11065
11066	LOCK_ZONE(zone);
11067	if (linked) {
11068		INSIST(zone->irefs > 0);
11069		zone->irefs--;
11070	}
11071	if (zone->request != NULL) {
11072		dns_request_cancel(zone->request);
11073	}
11074
11075	if (zone->readio != NULL)
11076		zonemgr_cancelio(zone->readio);
11077
11078	if (zone->lctx != NULL)
11079		dns_loadctx_cancel(zone->lctx);
11080
11081	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11082	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11083		if (zone->writeio != NULL)
11084			zonemgr_cancelio(zone->writeio);
11085
11086		if (zone->dctx != NULL)
11087			dns_dumpctx_cancel(zone->dctx);
11088	}
11089
11090	notify_cancel(zone);
11091
11092	forward_cancel(zone);
11093
11094	if (zone->timer != NULL) {
11095		isc_timer_detach(&zone->timer);
11096		INSIST(zone->irefs > 0);
11097		zone->irefs--;
11098	}
11099
11100	if (zone->view != NULL)
11101		dns_view_weakdetach(&zone->view);
11102
11103	/*
11104	 * We have now canceled everything set the flag to allow exit_check()
11105	 * to succeed.	We must not unlock between setting this flag and
11106	 * calling exit_check().
11107	 */
11108	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
11109	free_needed = exit_check(zone);
11110	if (inline_secure(zone)) {
11111		raw = zone->raw;
11112		zone->raw = NULL;
11113	}
11114	if (inline_raw(zone)) {
11115		secure = zone->secure;
11116		zone->secure = NULL;
11117	}
11118	UNLOCK_ZONE(zone);
11119	if (raw != NULL)
11120		dns_zone_detach(&raw);
11121	if (secure != NULL)
11122		dns_zone_idetach(&secure);
11123	if (free_needed)
11124		zone_free(zone);
11125}
11126
11127static void
11128zone_timer(isc_task_t *task, isc_event_t *event) {
11129	const char me[] = "zone_timer";
11130	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
11131
11132	UNUSED(task);
11133	REQUIRE(DNS_ZONE_VALID(zone));
11134
11135	ENTER;
11136
11137	zone_maintenance(zone);
11138
11139	isc_event_free(&event);
11140}
11141
11142static void
11143zone_settimer(dns_zone_t *zone, isc_time_t *now) {
11144	const char me[] = "zone_settimer";
11145	isc_time_t next;
11146	isc_result_t result;
11147
11148	ENTER;
11149	REQUIRE(DNS_ZONE_VALID(zone));
11150	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11151		return;
11152
11153	isc_time_settoepoch(&next);
11154
11155	switch (zone->type) {
11156	case dns_zone_redirect:
11157		if (zone->masters != NULL)
11158			goto treat_as_slave;
11159		/* FALLTHROUGH */
11160
11161	case dns_zone_master:
11162		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
11163			next = zone->notifytime;
11164		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11165		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11166			INSIST(!isc_time_isepoch(&zone->dumptime));
11167			if (isc_time_isepoch(&next) ||
11168			    isc_time_compare(&zone->dumptime, &next) < 0)
11169				next = zone->dumptime;
11170		}
11171		if (zone->type == dns_zone_redirect)
11172			break;
11173		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
11174		    !isc_time_isepoch(&zone->refreshkeytime)) {
11175			if (isc_time_isepoch(&next) ||
11176			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
11177				next = zone->refreshkeytime;
11178		}
11179		if (!isc_time_isepoch(&zone->resigntime)) {
11180			if (isc_time_isepoch(&next) ||
11181			    isc_time_compare(&zone->resigntime, &next) < 0)
11182				next = zone->resigntime;
11183		}
11184		if (!isc_time_isepoch(&zone->keywarntime)) {
11185			if (isc_time_isepoch(&next) ||
11186			    isc_time_compare(&zone->keywarntime, &next) < 0)
11187				next = zone->keywarntime;
11188		}
11189		if (!isc_time_isepoch(&zone->signingtime)) {
11190			if (isc_time_isepoch(&next) ||
11191			    isc_time_compare(&zone->signingtime, &next) < 0)
11192				next = zone->signingtime;
11193		}
11194		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
11195			if (isc_time_isepoch(&next) ||
11196			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
11197				next = zone->nsec3chaintime;
11198		}
11199		break;
11200
11201	case dns_zone_slave:
11202	treat_as_slave:
11203		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
11204			next = zone->notifytime;
11205		/* FALLTHROUGH */
11206
11207	case dns_zone_stub:
11208		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
11209		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
11210		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
11211		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
11212			INSIST(!isc_time_isepoch(&zone->refreshtime));
11213			if (isc_time_isepoch(&next) ||
11214			    isc_time_compare(&zone->refreshtime, &next) < 0)
11215				next = zone->refreshtime;
11216		}
11217		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
11218			INSIST(!isc_time_isepoch(&zone->expiretime));
11219			if (isc_time_isepoch(&next) ||
11220			    isc_time_compare(&zone->expiretime, &next) < 0)
11221				next = zone->expiretime;
11222		}
11223		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11224		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11225			INSIST(!isc_time_isepoch(&zone->dumptime));
11226			if (isc_time_isepoch(&next) ||
11227			    isc_time_compare(&zone->dumptime, &next) < 0)
11228				next = zone->dumptime;
11229		}
11230		break;
11231
11232	case dns_zone_key:
11233		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11234		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11235			INSIST(!isc_time_isepoch(&zone->dumptime));
11236			if (isc_time_isepoch(&next) ||
11237			    isc_time_compare(&zone->dumptime, &next) < 0)
11238				next = zone->dumptime;
11239		}
11240		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
11241			if (isc_time_isepoch(&next) ||
11242			    (!isc_time_isepoch(&zone->refreshkeytime) &&
11243			    isc_time_compare(&zone->refreshkeytime, &next) < 0))
11244				next = zone->refreshkeytime;
11245		}
11246		break;
11247
11248	default:
11249		break;
11250	}
11251
11252	if (isc_time_isepoch(&next)) {
11253		zone_debuglog(zone, me, 10, "settimer inactive");
11254		result = isc_timer_reset(zone->timer, isc_timertype_inactive,
11255					  NULL, NULL, ISC_TRUE);
11256		if (result != ISC_R_SUCCESS)
11257			dns_zone_log(zone, ISC_LOG_ERROR,
11258				     "could not deactivate zone timer: %s",
11259				     isc_result_totext(result));
11260	} else {
11261		if (isc_time_compare(&next, now) <= 0)
11262			next = *now;
11263		result = isc_timer_reset(zone->timer, isc_timertype_once,
11264					 &next, NULL, ISC_TRUE);
11265		if (result != ISC_R_SUCCESS)
11266			dns_zone_log(zone, ISC_LOG_ERROR,
11267				     "could not reset zone timer: %s",
11268				     isc_result_totext(result));
11269	}
11270}
11271
11272static void
11273cancel_refresh(dns_zone_t *zone) {
11274	const char me[] = "cancel_refresh";
11275	isc_time_t now;
11276
11277	/*
11278	 * 'zone' locked by caller.
11279	 */
11280
11281	REQUIRE(DNS_ZONE_VALID(zone));
11282	REQUIRE(LOCKED_ZONE(zone));
11283
11284	ENTER;
11285
11286	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11287	TIME_NOW(&now);
11288	zone_settimer(zone, &now);
11289}
11290
11291static isc_result_t
11292notify_createmessage(dns_zone_t *zone, unsigned int flags,
11293		     dns_message_t **messagep)
11294{
11295	dns_db_t *zonedb = NULL;
11296	dns_dbnode_t *node = NULL;
11297	dns_dbversion_t *version = NULL;
11298	dns_message_t *message = NULL;
11299	dns_rdataset_t rdataset;
11300	dns_rdata_t rdata = DNS_RDATA_INIT;
11301
11302	dns_name_t *tempname = NULL;
11303	dns_rdata_t *temprdata = NULL;
11304	dns_rdatalist_t *temprdatalist = NULL;
11305	dns_rdataset_t *temprdataset = NULL;
11306
11307	isc_result_t result;
11308	isc_region_t r;
11309	isc_buffer_t *b = NULL;
11310
11311	REQUIRE(DNS_ZONE_VALID(zone));
11312	REQUIRE(messagep != NULL && *messagep == NULL);
11313
11314	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11315				    &message);
11316	if (result != ISC_R_SUCCESS)
11317		return (result);
11318
11319	message->opcode = dns_opcode_notify;
11320	message->flags |= DNS_MESSAGEFLAG_AA;
11321	message->rdclass = zone->rdclass;
11322
11323	result = dns_message_gettempname(message, &tempname);
11324	if (result != ISC_R_SUCCESS)
11325		goto cleanup;
11326
11327	result = dns_message_gettemprdataset(message, &temprdataset);
11328	if (result != ISC_R_SUCCESS)
11329		goto cleanup;
11330
11331	/*
11332	 * Make question.
11333	 */
11334	dns_name_init(tempname, NULL);
11335	dns_name_clone(&zone->origin, tempname);
11336	dns_rdataset_init(temprdataset);
11337	dns_rdataset_makequestion(temprdataset, zone->rdclass,
11338				  dns_rdatatype_soa);
11339	ISC_LIST_APPEND(tempname->list, temprdataset, link);
11340	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
11341	tempname = NULL;
11342	temprdataset = NULL;
11343
11344	if ((flags & DNS_NOTIFY_NOSOA) != 0)
11345		goto done;
11346
11347	result = dns_message_gettempname(message, &tempname);
11348	if (result != ISC_R_SUCCESS)
11349		goto soa_cleanup;
11350	result = dns_message_gettemprdata(message, &temprdata);
11351	if (result != ISC_R_SUCCESS)
11352		goto soa_cleanup;
11353	result = dns_message_gettemprdataset(message, &temprdataset);
11354	if (result != ISC_R_SUCCESS)
11355		goto soa_cleanup;
11356	result = dns_message_gettemprdatalist(message, &temprdatalist);
11357	if (result != ISC_R_SUCCESS)
11358		goto soa_cleanup;
11359
11360	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11361	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
11362	dns_db_attach(zone->db, &zonedb);
11363	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11364
11365	dns_name_init(tempname, NULL);
11366	dns_name_clone(&zone->origin, tempname);
11367	dns_db_currentversion(zonedb, &version);
11368	result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
11369	if (result != ISC_R_SUCCESS)
11370		goto soa_cleanup;
11371
11372	dns_rdataset_init(&rdataset);
11373	result = dns_db_findrdataset(zonedb, node, version,
11374				     dns_rdatatype_soa,
11375				     dns_rdatatype_none, 0, &rdataset,
11376				     NULL);
11377	if (result != ISC_R_SUCCESS)
11378		goto soa_cleanup;
11379	result = dns_rdataset_first(&rdataset);
11380	if (result != ISC_R_SUCCESS)
11381		goto soa_cleanup;
11382	dns_rdataset_current(&rdataset, &rdata);
11383	dns_rdata_toregion(&rdata, &r);
11384	result = isc_buffer_allocate(zone->mctx, &b, r.length);
11385	if (result != ISC_R_SUCCESS)
11386		goto soa_cleanup;
11387	isc_buffer_putmem(b, r.base, r.length);
11388	isc_buffer_usedregion(b, &r);
11389	dns_rdata_init(temprdata);
11390	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
11391	dns_message_takebuffer(message, &b);
11392	result = dns_rdataset_next(&rdataset);
11393	dns_rdataset_disassociate(&rdataset);
11394	if (result != ISC_R_NOMORE)
11395		goto soa_cleanup;
11396	temprdatalist->rdclass = rdata.rdclass;
11397	temprdatalist->type = rdata.type;
11398	temprdatalist->covers = 0;
11399	temprdatalist->ttl = rdataset.ttl;
11400	ISC_LIST_INIT(temprdatalist->rdata);
11401	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
11402
11403	dns_rdataset_init(temprdataset);
11404	result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
11405	if (result != ISC_R_SUCCESS)
11406		goto soa_cleanup;
11407
11408	ISC_LIST_APPEND(tempname->list, temprdataset, link);
11409	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
11410	temprdatalist = NULL;
11411	temprdataset = NULL;
11412	temprdata = NULL;
11413	tempname = NULL;
11414
11415 soa_cleanup:
11416	if (node != NULL)
11417		dns_db_detachnode(zonedb, &node);
11418	if (version != NULL)
11419		dns_db_closeversion(zonedb, &version, ISC_FALSE);
11420	if (zonedb != NULL)
11421		dns_db_detach(&zonedb);
11422	if (tempname != NULL)
11423		dns_message_puttempname(message, &tempname);
11424	if (temprdata != NULL)
11425		dns_message_puttemprdata(message, &temprdata);
11426	if (temprdataset != NULL)
11427		dns_message_puttemprdataset(message, &temprdataset);
11428	if (temprdatalist != NULL)
11429		dns_message_puttemprdatalist(message, &temprdatalist);
11430
11431 done:
11432	*messagep = message;
11433	return (ISC_R_SUCCESS);
11434
11435 cleanup:
11436	if (tempname != NULL)
11437		dns_message_puttempname(message, &tempname);
11438	if (temprdataset != NULL)
11439		dns_message_puttemprdataset(message, &temprdataset);
11440	dns_message_destroy(&message);
11441	return (result);
11442}
11443
11444isc_result_t
11445dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
11446		       dns_message_t *msg)
11447{
11448	unsigned int i;
11449	dns_rdata_soa_t soa;
11450	dns_rdataset_t *rdataset = NULL;
11451	dns_rdata_t rdata = DNS_RDATA_INIT;
11452	isc_result_t result;
11453	char fromtext[ISC_SOCKADDR_FORMATSIZE];
11454	int match = 0;
11455	isc_netaddr_t netaddr;
11456	isc_sockaddr_t local, remote;
11457
11458	REQUIRE(DNS_ZONE_VALID(zone));
11459
11460	/*
11461	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
11462	 * ROLLOVER.
11463	 *
11464	 * SOA:	RFC1996
11465	 * Check that 'from' is a valid notify source, (zone->masters).
11466	 *	Return DNS_R_REFUSED if not.
11467	 *
11468	 * If the notify message contains a serial number check it
11469	 * against the zones serial and return if <= current serial
11470	 *
11471	 * If a refresh check is progress, if so just record the
11472	 * fact we received a NOTIFY and from where and return.
11473	 * We will perform a new refresh check when the current one
11474	 * completes. Return ISC_R_SUCCESS.
11475	 *
11476	 * Otherwise initiate a refresh check using 'from' as the
11477	 * first address to check.  Return ISC_R_SUCCESS.
11478	 */
11479
11480	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
11481
11482	/*
11483	 * Notify messages are processed by the raw zone.
11484	 */
11485	LOCK_ZONE(zone);
11486	if (inline_secure(zone)) {
11487		result = dns_zone_notifyreceive(zone->raw, from, msg);
11488		UNLOCK_ZONE(zone);
11489		return (result);
11490	}
11491	/*
11492	 *  We only handle NOTIFY (SOA) at the present.
11493	 */
11494	if (isc_sockaddr_pf(from) == PF_INET)
11495		inc_stats(zone, dns_zonestatscounter_notifyinv4);
11496	else
11497		inc_stats(zone, dns_zonestatscounter_notifyinv6);
11498	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
11499	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
11500				 dns_rdatatype_soa, dns_rdatatype_none,
11501				 NULL, NULL) != ISC_R_SUCCESS) {
11502		UNLOCK_ZONE(zone);
11503		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
11504			dns_zone_log(zone, ISC_LOG_NOTICE,
11505				     "NOTIFY with no "
11506				     "question section from: %s", fromtext);
11507			return (DNS_R_FORMERR);
11508		}
11509		dns_zone_log(zone, ISC_LOG_NOTICE,
11510			     "NOTIFY zone does not match");
11511		return (DNS_R_NOTIMP);
11512	}
11513
11514	/*
11515	 * If we are a master zone just succeed.
11516	 */
11517	if (zone->type == dns_zone_master) {
11518		UNLOCK_ZONE(zone);
11519		return (ISC_R_SUCCESS);
11520	}
11521
11522	isc_netaddr_fromsockaddr(&netaddr, from);
11523	for (i = 0; i < zone->masterscnt; i++) {
11524		if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
11525			break;
11526		if (zone->view->aclenv.match_mapped &&
11527		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
11528		    isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
11529			isc_netaddr_t na1, na2;
11530			isc_netaddr_fromv4mapped(&na1, &netaddr);
11531			isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
11532			if (isc_netaddr_equal(&na1, &na2))
11533				break;
11534		}
11535	}
11536
11537	/*
11538	 * Accept notify requests from non masters if they are on
11539	 * 'zone->notify_acl'.
11540	 */
11541	if (i >= zone->masterscnt && zone->notify_acl != NULL &&
11542	    dns_acl_match(&netaddr, NULL, zone->notify_acl,
11543			  &zone->view->aclenv,
11544			  &match, NULL) == ISC_R_SUCCESS &&
11545	    match > 0)
11546	{
11547		/* Accept notify. */
11548	} else if (i >= zone->masterscnt) {
11549		UNLOCK_ZONE(zone);
11550		dns_zone_log(zone, ISC_LOG_INFO,
11551			     "refused notify from non-master: %s", fromtext);
11552		inc_stats(zone, dns_zonestatscounter_notifyrej);
11553		return (DNS_R_REFUSED);
11554	}
11555
11556	/*
11557	 * If the zone is loaded and there are answers check the serial
11558	 * to see if we need to do a refresh.  Do not worry about this
11559	 * check if we are a dialup zone as we use the notify request
11560	 * to trigger a refresh check.
11561	 */
11562	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
11563	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11564	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
11565		result = dns_message_findname(msg, DNS_SECTION_ANSWER,
11566					      &zone->origin,
11567					      dns_rdatatype_soa,
11568					      dns_rdatatype_none, NULL,
11569					      &rdataset);
11570		if (result == ISC_R_SUCCESS)
11571			result = dns_rdataset_first(rdataset);
11572		if (result == ISC_R_SUCCESS) {
11573			isc_uint32_t serial = 0, oldserial;
11574
11575			dns_rdataset_current(rdataset, &rdata);
11576			result = dns_rdata_tostruct(&rdata, &soa, NULL);
11577			RUNTIME_CHECK(result == ISC_R_SUCCESS);
11578			serial = soa.serial;
11579			/*
11580			 * The following should safely be performed without DB
11581			 * lock and succeed in this context.
11582			 */
11583			result = zone_get_from_db(zone, zone->db, NULL, NULL,
11584						  &oldserial, NULL, NULL, NULL,
11585						  NULL, NULL);
11586			RUNTIME_CHECK(result == ISC_R_SUCCESS);
11587			if (isc_serial_le(serial, oldserial)) {
11588				dns_zone_log(zone,
11589					     ISC_LOG_INFO,
11590					     "notify from %s: "
11591					     "zone is up to date",
11592					     fromtext);
11593				UNLOCK_ZONE(zone);
11594				return (ISC_R_SUCCESS);
11595			}
11596		}
11597	}
11598
11599	/*
11600	 * If we got this far and there was a refresh in progress just
11601	 * let it complete.  Record where we got the notify from so we
11602	 * can perform a refresh check when the current one completes
11603	 */
11604	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
11605		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11606		zone->notifyfrom = *from;
11607		UNLOCK_ZONE(zone);
11608		dns_zone_log(zone, ISC_LOG_INFO,
11609			     "notify from %s: refresh in progress, "
11610			     "refresh check queued",
11611			     fromtext);
11612		return (ISC_R_SUCCESS);
11613	}
11614	zone->notifyfrom = *from;
11615	local = zone->masteraddr;
11616	remote = zone->sourceaddr;
11617	UNLOCK_ZONE(zone);
11618	dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
11619	dns_zone_refresh(zone);
11620	return (ISC_R_SUCCESS);
11621}
11622
11623void
11624dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
11625
11626	REQUIRE(DNS_ZONE_VALID(zone));
11627
11628	LOCK_ZONE(zone);
11629	if (zone->notify_acl != NULL)
11630		dns_acl_detach(&zone->notify_acl);
11631	dns_acl_attach(acl, &zone->notify_acl);
11632	UNLOCK_ZONE(zone);
11633}
11634
11635void
11636dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
11637
11638	REQUIRE(DNS_ZONE_VALID(zone));
11639
11640	LOCK_ZONE(zone);
11641	if (zone->query_acl != NULL)
11642		dns_acl_detach(&zone->query_acl);
11643	dns_acl_attach(acl, &zone->query_acl);
11644	UNLOCK_ZONE(zone);
11645}
11646
11647void
11648dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
11649
11650	REQUIRE(DNS_ZONE_VALID(zone));
11651
11652	LOCK_ZONE(zone);
11653	if (zone->queryon_acl != NULL)
11654		dns_acl_detach(&zone->queryon_acl);
11655	dns_acl_attach(acl, &zone->queryon_acl);
11656	UNLOCK_ZONE(zone);
11657}
11658
11659void
11660dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
11661
11662	REQUIRE(DNS_ZONE_VALID(zone));
11663
11664	LOCK_ZONE(zone);
11665	if (zone->update_acl != NULL)
11666		dns_acl_detach(&zone->update_acl);
11667	dns_acl_attach(acl, &zone->update_acl);
11668	UNLOCK_ZONE(zone);
11669}
11670
11671void
11672dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
11673
11674	REQUIRE(DNS_ZONE_VALID(zone));
11675
11676	LOCK_ZONE(zone);
11677	if (zone->forward_acl != NULL)
11678		dns_acl_detach(&zone->forward_acl);
11679	dns_acl_attach(acl, &zone->forward_acl);
11680	UNLOCK_ZONE(zone);
11681}
11682
11683void
11684dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
11685
11686	REQUIRE(DNS_ZONE_VALID(zone));
11687
11688	LOCK_ZONE(zone);
11689	if (zone->xfr_acl != NULL)
11690		dns_acl_detach(&zone->xfr_acl);
11691	dns_acl_attach(acl, &zone->xfr_acl);
11692	UNLOCK_ZONE(zone);
11693}
11694
11695dns_acl_t *
11696dns_zone_getnotifyacl(dns_zone_t *zone) {
11697
11698	REQUIRE(DNS_ZONE_VALID(zone));
11699
11700	return (zone->notify_acl);
11701}
11702
11703dns_acl_t *
11704dns_zone_getqueryacl(dns_zone_t *zone) {
11705
11706	REQUIRE(DNS_ZONE_VALID(zone));
11707
11708	return (zone->query_acl);
11709}
11710
11711dns_acl_t *
11712dns_zone_getqueryonacl(dns_zone_t *zone) {
11713
11714	REQUIRE(DNS_ZONE_VALID(zone));
11715
11716	return (zone->queryon_acl);
11717}
11718
11719dns_acl_t *
11720dns_zone_getupdateacl(dns_zone_t *zone) {
11721
11722	REQUIRE(DNS_ZONE_VALID(zone));
11723
11724	return (zone->update_acl);
11725}
11726
11727dns_acl_t *
11728dns_zone_getforwardacl(dns_zone_t *zone) {
11729
11730	REQUIRE(DNS_ZONE_VALID(zone));
11731
11732	return (zone->forward_acl);
11733}
11734
11735dns_acl_t *
11736dns_zone_getxfracl(dns_zone_t *zone) {
11737
11738	REQUIRE(DNS_ZONE_VALID(zone));
11739
11740	return (zone->xfr_acl);
11741}
11742
11743void
11744dns_zone_clearupdateacl(dns_zone_t *zone) {
11745
11746	REQUIRE(DNS_ZONE_VALID(zone));
11747
11748	LOCK_ZONE(zone);
11749	if (zone->update_acl != NULL)
11750		dns_acl_detach(&zone->update_acl);
11751	UNLOCK_ZONE(zone);
11752}
11753
11754void
11755dns_zone_clearforwardacl(dns_zone_t *zone) {
11756
11757	REQUIRE(DNS_ZONE_VALID(zone));
11758
11759	LOCK_ZONE(zone);
11760	if (zone->forward_acl != NULL)
11761		dns_acl_detach(&zone->forward_acl);
11762	UNLOCK_ZONE(zone);
11763}
11764
11765void
11766dns_zone_clearnotifyacl(dns_zone_t *zone) {
11767
11768	REQUIRE(DNS_ZONE_VALID(zone));
11769
11770	LOCK_ZONE(zone);
11771	if (zone->notify_acl != NULL)
11772		dns_acl_detach(&zone->notify_acl);
11773	UNLOCK_ZONE(zone);
11774}
11775
11776void
11777dns_zone_clearqueryacl(dns_zone_t *zone) {
11778
11779	REQUIRE(DNS_ZONE_VALID(zone));
11780
11781	LOCK_ZONE(zone);
11782	if (zone->query_acl != NULL)
11783		dns_acl_detach(&zone->query_acl);
11784	UNLOCK_ZONE(zone);
11785}
11786
11787void
11788dns_zone_clearqueryonacl(dns_zone_t *zone) {
11789
11790	REQUIRE(DNS_ZONE_VALID(zone));
11791
11792	LOCK_ZONE(zone);
11793	if (zone->queryon_acl != NULL)
11794		dns_acl_detach(&zone->queryon_acl);
11795	UNLOCK_ZONE(zone);
11796}
11797
11798void
11799dns_zone_clearxfracl(dns_zone_t *zone) {
11800
11801	REQUIRE(DNS_ZONE_VALID(zone));
11802
11803	LOCK_ZONE(zone);
11804	if (zone->xfr_acl != NULL)
11805		dns_acl_detach(&zone->xfr_acl);
11806	UNLOCK_ZONE(zone);
11807}
11808
11809isc_boolean_t
11810dns_zone_getupdatedisabled(dns_zone_t *zone) {
11811	REQUIRE(DNS_ZONE_VALID(zone));
11812	return (zone->update_disabled);
11813
11814}
11815
11816void
11817dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
11818	REQUIRE(DNS_ZONE_VALID(zone));
11819	zone->update_disabled = state;
11820}
11821
11822isc_boolean_t
11823dns_zone_getzeronosoattl(dns_zone_t *zone) {
11824	REQUIRE(DNS_ZONE_VALID(zone));
11825	return (zone->zero_no_soa_ttl);
11826
11827}
11828
11829void
11830dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
11831	REQUIRE(DNS_ZONE_VALID(zone));
11832	zone->zero_no_soa_ttl = state;
11833}
11834
11835void
11836dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
11837
11838	REQUIRE(DNS_ZONE_VALID(zone));
11839
11840	zone->check_names = severity;
11841}
11842
11843dns_severity_t
11844dns_zone_getchecknames(dns_zone_t *zone) {
11845
11846	REQUIRE(DNS_ZONE_VALID(zone));
11847
11848	return (zone->check_names);
11849}
11850
11851void
11852dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
11853
11854	REQUIRE(DNS_ZONE_VALID(zone));
11855
11856	zone->journalsize = size;
11857}
11858
11859isc_int32_t
11860dns_zone_getjournalsize(dns_zone_t *zone) {
11861
11862	REQUIRE(DNS_ZONE_VALID(zone));
11863
11864	return (zone->journalsize);
11865}
11866
11867static void
11868zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
11869	isc_result_t result = ISC_R_FAILURE;
11870	isc_buffer_t buffer;
11871
11872	REQUIRE(buf != NULL);
11873	REQUIRE(length > 1U);
11874
11875	/*
11876	 * Leave space for terminating '\0'.
11877	 */
11878	isc_buffer_init(&buffer, buf, length - 1);
11879	if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
11880		if (dns_name_dynamic(&zone->origin))
11881			result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11882		if (result != ISC_R_SUCCESS &&
11883		    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11884			isc_buffer_putstr(&buffer, "<UNKNOWN>");
11885
11886		if (isc_buffer_availablelength(&buffer) > 0)
11887			isc_buffer_putstr(&buffer, "/");
11888		(void)dns_rdataclass_totext(zone->rdclass, &buffer);
11889	}
11890
11891	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
11892	    strcmp(zone->view->name, "_default") != 0 &&
11893	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
11894		isc_buffer_putstr(&buffer, "/");
11895		isc_buffer_putstr(&buffer, zone->view->name);
11896	}
11897	if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
11898		isc_buffer_putstr(&buffer, " (signed)");
11899	if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
11900		isc_buffer_putstr(&buffer, " (unsigned)");
11901
11902	buf[isc_buffer_usedlength(&buffer)] = '\0';
11903}
11904
11905static void
11906zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
11907	isc_result_t result = ISC_R_FAILURE;
11908	isc_buffer_t buffer;
11909
11910	REQUIRE(buf != NULL);
11911	REQUIRE(length > 1U);
11912
11913	/*
11914	 * Leave space for terminating '\0'.
11915	 */
11916	isc_buffer_init(&buffer, buf, length - 1);
11917	if (dns_name_dynamic(&zone->origin))
11918		result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11919	if (result != ISC_R_SUCCESS &&
11920	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11921		isc_buffer_putstr(&buffer, "<UNKNOWN>");
11922
11923	buf[isc_buffer_usedlength(&buffer)] = '\0';
11924}
11925
11926static void
11927zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
11928	isc_buffer_t buffer;
11929
11930	REQUIRE(buf != NULL);
11931	REQUIRE(length > 1U);
11932
11933	/*
11934	 * Leave space for terminating '\0'.
11935	 */
11936	isc_buffer_init(&buffer, buf, length - 1);
11937	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
11938
11939	buf[isc_buffer_usedlength(&buffer)] = '\0';
11940}
11941
11942static void
11943zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
11944	isc_buffer_t buffer;
11945
11946	REQUIRE(buf != NULL);
11947	REQUIRE(length > 1U);
11948
11949
11950	/*
11951	 * Leave space for terminating '\0'.
11952	 */
11953	isc_buffer_init(&buffer, buf, length - 1);
11954
11955	if (zone->view == NULL) {
11956		isc_buffer_putstr(&buffer, "_none");
11957	} else if (strlen(zone->view->name)
11958		   < isc_buffer_availablelength(&buffer)) {
11959		isc_buffer_putstr(&buffer, zone->view->name);
11960	} else {
11961		isc_buffer_putstr(&buffer, "_toolong");
11962	}
11963
11964	buf[isc_buffer_usedlength(&buffer)] = '\0';
11965}
11966
11967void
11968dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
11969	REQUIRE(DNS_ZONE_VALID(zone));
11970	REQUIRE(buf != NULL);
11971	zone_namerd_tostr(zone, buf, length);
11972}
11973
11974static void
11975notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11976	va_list ap;
11977	char message[4096];
11978
11979	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11980		return;
11981
11982	va_start(ap, fmt);
11983	vsnprintf(message, sizeof(message), fmt, ap);
11984	va_end(ap);
11985	isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
11986		      level, "zone %s: %s", zone->strnamerd, message);
11987}
11988
11989void
11990dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
11991	      int level, const char *fmt, ...) {
11992	va_list ap;
11993	char message[4096];
11994
11995	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11996		return;
11997
11998	va_start(ap, fmt);
11999	vsnprintf(message, sizeof(message), fmt, ap);
12000	va_end(ap);
12001	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
12002		      level, "%s%s: %s", (zone->type == dns_zone_key) ?
12003		      "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12004		      "redirect-zone" : "zone ", zone->strnamerd, message);
12005}
12006
12007void
12008dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12009	va_list ap;
12010	char message[4096];
12011
12012	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12013		return;
12014
12015	va_start(ap, fmt);
12016	vsnprintf(message, sizeof(message), fmt, ap);
12017	va_end(ap);
12018	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12019		      level, "%s%s: %s", (zone->type == dns_zone_key) ?
12020		      "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12021		      "redirect-zone" : "zone ", zone->strnamerd, message);
12022}
12023
12024static void
12025zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
12026	      const char *fmt, ...)
12027{
12028	va_list ap;
12029	char message[4096];
12030	int level = ISC_LOG_DEBUG(debuglevel);
12031
12032	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12033		return;
12034
12035	va_start(ap, fmt);
12036	vsnprintf(message, sizeof(message), fmt, ap);
12037	va_end(ap);
12038	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12039		      level, "%s: %s %s: %s", me, zone->type != dns_zone_key ?
12040		      "zone" : "managed-keys-zone", zone->strnamerd, message);
12041}
12042
12043static int
12044message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
12045{
12046	isc_result_t result;
12047	dns_name_t *name;
12048	dns_rdataset_t *curr;
12049	int count = 0;
12050
12051	result = dns_message_firstname(msg, section);
12052	while (result == ISC_R_SUCCESS) {
12053		name = NULL;
12054		dns_message_currentname(msg, section, &name);
12055
12056		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
12057		     curr = ISC_LIST_PREV(curr, link)) {
12058			if (curr->type == type)
12059				count++;
12060		}
12061		result = dns_message_nextname(msg, section);
12062	}
12063
12064	return (count);
12065}
12066
12067void
12068dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
12069	REQUIRE(DNS_ZONE_VALID(zone));
12070
12071	zone->maxxfrin = maxxfrin;
12072}
12073
12074isc_uint32_t
12075dns_zone_getmaxxfrin(dns_zone_t *zone) {
12076	REQUIRE(DNS_ZONE_VALID(zone));
12077
12078	return (zone->maxxfrin);
12079}
12080
12081void
12082dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
12083	REQUIRE(DNS_ZONE_VALID(zone));
12084	zone->maxxfrout = maxxfrout;
12085}
12086
12087isc_uint32_t
12088dns_zone_getmaxxfrout(dns_zone_t *zone) {
12089	REQUIRE(DNS_ZONE_VALID(zone));
12090
12091	return (zone->maxxfrout);
12092}
12093
12094dns_zonetype_t
12095dns_zone_gettype(dns_zone_t *zone) {
12096	REQUIRE(DNS_ZONE_VALID(zone));
12097
12098	return (zone->type);
12099}
12100
12101dns_name_t *
12102dns_zone_getorigin(dns_zone_t *zone) {
12103	REQUIRE(DNS_ZONE_VALID(zone));
12104
12105	return (&zone->origin);
12106}
12107
12108void
12109dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
12110	REQUIRE(DNS_ZONE_VALID(zone));
12111
12112	LOCK_ZONE(zone);
12113	if (zone->task != NULL)
12114		isc_task_detach(&zone->task);
12115	isc_task_attach(task, &zone->task);
12116	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12117	if (zone->db != NULL)
12118		dns_db_settask(zone->db, zone->task);
12119	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12120	UNLOCK_ZONE(zone);
12121}
12122
12123void
12124dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
12125	REQUIRE(DNS_ZONE_VALID(zone));
12126	isc_task_attach(zone->task, target);
12127}
12128
12129void
12130dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
12131	REQUIRE(DNS_ZONE_VALID(zone));
12132
12133	if (idlein == 0)
12134		idlein = DNS_DEFAULT_IDLEIN;
12135	zone->idlein = idlein;
12136}
12137
12138isc_uint32_t
12139dns_zone_getidlein(dns_zone_t *zone) {
12140	REQUIRE(DNS_ZONE_VALID(zone));
12141
12142	return (zone->idlein);
12143}
12144
12145void
12146dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
12147	REQUIRE(DNS_ZONE_VALID(zone));
12148
12149	zone->idleout = idleout;
12150}
12151
12152isc_uint32_t
12153dns_zone_getidleout(dns_zone_t *zone) {
12154	REQUIRE(DNS_ZONE_VALID(zone));
12155
12156	return (zone->idleout);
12157}
12158
12159static void
12160notify_done(isc_task_t *task, isc_event_t *event) {
12161	dns_requestevent_t *revent = (dns_requestevent_t *)event;
12162	dns_notify_t *notify;
12163	isc_result_t result;
12164	dns_message_t *message = NULL;
12165	isc_buffer_t buf;
12166	char rcode[128];
12167	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12168
12169	UNUSED(task);
12170
12171	notify = event->ev_arg;
12172	REQUIRE(DNS_NOTIFY_VALID(notify));
12173	INSIST(task == notify->zone->task);
12174
12175	isc_buffer_init(&buf, rcode, sizeof(rcode));
12176	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12177
12178	result = revent->result;
12179	if (result == ISC_R_SUCCESS)
12180		result = dns_message_create(notify->zone->mctx,
12181					    DNS_MESSAGE_INTENTPARSE, &message);
12182	if (result == ISC_R_SUCCESS)
12183		result = dns_request_getresponse(revent->request, message,
12184					DNS_MESSAGEPARSE_PRESERVEORDER);
12185	if (result == ISC_R_SUCCESS)
12186		result = dns_rcode_totext(message->rcode, &buf);
12187	if (result == ISC_R_SUCCESS)
12188		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12189			   "notify response from %s: %.*s",
12190			   addrbuf, (int)buf.used, rcode);
12191	else
12192		notify_log(notify->zone, ISC_LOG_DEBUG(2),
12193			   "notify to %s failed: %s", addrbuf,
12194			   dns_result_totext(result));
12195
12196	/*
12197	 * Old bind's return formerr if they see a soa record.	Retry w/o
12198	 * the soa if we see a formerr and had sent a SOA.
12199	 */
12200	isc_event_free(&event);
12201	if (message != NULL && message->rcode == dns_rcode_formerr &&
12202	    (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
12203		notify->flags |= DNS_NOTIFY_NOSOA;
12204		dns_request_destroy(&notify->request);
12205		result = notify_send_queue(notify);
12206		if (result != ISC_R_SUCCESS)
12207			notify_destroy(notify, ISC_FALSE);
12208	} else {
12209		if (result == ISC_R_TIMEDOUT)
12210			notify_log(notify->zone, ISC_LOG_DEBUG(1),
12211				   "notify to %s: retries exceeded", addrbuf);
12212		notify_destroy(notify, ISC_FALSE);
12213	}
12214	if (message != NULL)
12215		dns_message_destroy(&message);
12216}
12217
12218struct secure_event {
12219	isc_event_t e;
12220	dns_db_t *db;
12221	isc_uint32_t serial;
12222};
12223
12224static void
12225update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
12226	UNUSED(arg);
12227	dns_zone_log(zone, level, "%s", message);
12228}
12229
12230static isc_result_t
12231sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal,
12232		    isc_uint32_t start, isc_uint32_t end,
12233		    dns_difftuple_t **soatuplep, dns_diff_t *diff)
12234{
12235	isc_result_t result;
12236	dns_difftuple_t *tuple = NULL;
12237	dns_diffop_t op = DNS_DIFFOP_ADD;
12238	int n_soa = 0;
12239
12240	REQUIRE(soatuplep != NULL);
12241
12242	if (start == end)
12243		return (DNS_R_UNCHANGED);
12244
12245	CHECK(dns_journal_iter_init(journal, start, end));
12246	for (result = dns_journal_first_rr(journal);
12247	     result == ISC_R_SUCCESS;
12248	     result = dns_journal_next_rr(journal))
12249	{
12250		dns_name_t *name = NULL;
12251		isc_uint32_t ttl;
12252		dns_rdata_t *rdata = NULL;
12253		dns_journal_current_rr(journal, &name, &ttl, &rdata);
12254
12255		if (rdata->type == dns_rdatatype_soa) {
12256			n_soa++;
12257			if (n_soa == 2) {
12258				/*
12259				 * Save the latest raw SOA record.
12260				 */
12261				if (*soatuplep != NULL)
12262					dns_difftuple_free(soatuplep);
12263				CHECK(dns_difftuple_create(diff->mctx,
12264							   DNS_DIFFOP_ADD,
12265							   name, ttl, rdata,
12266							   soatuplep));
12267			}
12268			if (n_soa == 3)
12269				n_soa = 1;
12270			continue;
12271		}
12272
12273		/* Sanity. */
12274		if (n_soa == 0) {
12275			dns_zone_log(zone->raw, ISC_LOG_ERROR,
12276				     "corrupt journal file: '%s'\n",
12277				     zone->raw->journal);
12278			return (ISC_R_FAILURE);
12279		}
12280
12281		if (zone->privatetype != 0 &&
12282		    rdata->type == zone->privatetype)
12283			continue;
12284
12285		if (rdata->type == dns_rdatatype_nsec ||
12286		    rdata->type == dns_rdatatype_rrsig ||
12287		    rdata->type == dns_rdatatype_nsec3 ||
12288		    rdata->type == dns_rdatatype_dnskey ||
12289		    rdata->type == dns_rdatatype_nsec3param)
12290			continue;
12291
12292		op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
12293
12294		CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
12295					   &tuple));
12296		dns_diff_appendminimal(diff, &tuple);
12297	}
12298	if (result == ISC_R_NOMORE)
12299		result = ISC_R_SUCCESS;
12300
12301 failure:
12302	return(result);
12303}
12304
12305static isc_result_t
12306sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb,
12307	       dns_dbversion_t *secver, dns_diff_t *diff)
12308{
12309	isc_result_t result;
12310	dns_db_t *rawdb = NULL;
12311	dns_dbversion_t *rawver = NULL;
12312	dns_difftuple_t *tuple = NULL, *next;
12313
12314	REQUIRE(DNS_ZONE_VALID(seczone));
12315	REQUIRE(inline_secure(seczone));
12316
12317	if (!seczone->sourceserialset)
12318		return (DNS_R_UNCHANGED);
12319
12320	dns_db_attach(seczone->raw->db, &rawdb);
12321	dns_db_currentversion(rawdb, &rawver);
12322	result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
12323	dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
12324	dns_db_detach(&rawdb);
12325
12326	if (result != ISC_R_SUCCESS)
12327		return (result);
12328
12329	for (tuple = ISC_LIST_HEAD(diff->tuples);
12330	     tuple != NULL;
12331	     tuple = next)
12332	{
12333		next = ISC_LIST_NEXT(tuple, link);
12334		if (tuple->rdata.type == dns_rdatatype_nsec ||
12335		    tuple->rdata.type == dns_rdatatype_rrsig ||
12336		    tuple->rdata.type == dns_rdatatype_dnskey ||
12337		    tuple->rdata.type == dns_rdatatype_nsec3 ||
12338		    tuple->rdata.type == dns_rdatatype_soa ||
12339		    tuple->rdata.type == dns_rdatatype_nsec3param)
12340		{
12341			ISC_LIST_UNLINK(diff->tuples, tuple, link);
12342			dns_difftuple_free(&tuple);
12343		}
12344	}
12345
12346	if (ISC_LIST_EMPTY(diff->tuples))
12347		return (DNS_R_UNCHANGED);
12348
12349	return (ISC_R_SUCCESS);
12350}
12351
12352static void
12353receive_secure_serial(isc_task_t *task, isc_event_t *event) {
12354	isc_result_t result;
12355	dns_journal_t *rjournal = NULL;
12356	isc_uint32_t start, end;
12357	dns_zone_t *zone;
12358	dns_db_t *db = NULL;
12359	dns_dbnode_t *node = NULL;
12360	dns_dbversion_t *newver = NULL, *oldver = NULL;
12361	dns_diff_t diff;
12362	dns_difftuple_t *tuple = NULL, *soatuple = NULL;
12363	dns_update_log_t log = { update_log_cb, NULL };
12364	isc_time_t timenow;
12365
12366	zone = event->ev_arg;
12367	end = ((struct secure_event *)event)->serial;
12368	isc_event_free(&event);
12369
12370	REQUIRE(inline_secure(zone));
12371
12372	dns_diff_init(zone->mctx, &diff);
12373
12374	UNUSED(task);
12375
12376	/*
12377	 * zone->db may be NULL if the load from disk failed.
12378	 */
12379	if (zone->db == NULL) {
12380		result = ISC_R_FAILURE;
12381		goto failure;
12382	}
12383
12384	/*
12385	 * We first attempt to sync the raw zone to the secure zone
12386	 * by using the raw zone's journal, applying all the deltas
12387	 * from the latest source-serial of the secure zone up to
12388	 * the current serial number of the raw zone.
12389	 *
12390	 * If that fails, then we'll fall back to a direct comparison
12391	 * between raw and secure zones.
12392	 */
12393	result = dns_journal_open(zone->raw->mctx, zone->raw->journal,
12394				  DNS_JOURNAL_WRITE, &rjournal);
12395	if (result != ISC_R_SUCCESS)
12396		goto failure;
12397	else {
12398		dns_journal_t *sjournal = NULL;
12399
12400		result = dns_journal_open(zone->raw->mctx, zone->journal,
12401					  DNS_JOURNAL_READ, &sjournal);
12402		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
12403			goto failure;
12404
12405		if (!dns_journal_get_sourceserial(rjournal, &start)) {
12406			start = dns_journal_first_serial(rjournal);
12407			dns_journal_set_sourceserial(rjournal, start);
12408		}
12409		if (sjournal != NULL) {
12410			isc_uint32_t serial;
12411			/*
12412			 * We read the secure journal first, if that exists
12413			 * use its value provided it is greater that from the
12414			 * raw journal.
12415			 */
12416			if (dns_journal_get_sourceserial(sjournal, &serial)) {
12417				if (isc_serial_gt(serial, start))
12418					start = serial;
12419			}
12420			dns_journal_destroy(&sjournal);
12421		}
12422	}
12423
12424	dns_db_attach(zone->db, &db);
12425	dns_db_currentversion(db, &oldver);
12426	CHECK(dns_db_newversion(db, &newver));
12427
12428	/*
12429	 * Try to apply diffs from the raw zone's journal to the secure
12430	 * zone.  If that fails, we recover by syncing up the databases
12431	 * directly.
12432	 */
12433	result = sync_secure_journal(zone, rjournal, start, end,
12434				     &soatuple, &diff);
12435	if (result == DNS_R_UNCHANGED)
12436		goto failure;
12437	else if (result != ISC_R_SUCCESS) {
12438		CHECK(sync_secure_db(zone, db, oldver, &diff));
12439	}
12440
12441	CHECK(dns_diff_apply(&diff, db, newver));
12442
12443	if (soatuple != NULL) {
12444		isc_uint32_t oldserial, newserial, desired;
12445
12446		CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
12447					    DNS_DIFFOP_DEL, &tuple));
12448		oldserial = dns_soa_getserial(&tuple->rdata);
12449		newserial = desired = dns_soa_getserial(&soatuple->rdata);
12450		if (!isc_serial_gt(newserial, oldserial)) {
12451			newserial = oldserial + 1;
12452			if (newserial == 0)
12453				newserial++;
12454			dns_soa_setserial(newserial, &soatuple->rdata);
12455		}
12456		CHECK(do_one_tuple(&tuple, db, newver, &diff));
12457		CHECK(do_one_tuple(&soatuple, db, newver, &diff));
12458		dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
12459			     newserial, desired);
12460	} else
12461		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
12462					zone->updatemethod));
12463
12464	CHECK(dns_update_signatures(&log, zone, db, oldver, newver,
12465				    &diff, zone->sigvalidityinterval));
12466
12467	CHECK(zone_journal(zone, &diff, &end, "receive_secure_serial"));
12468
12469	dns_journal_set_sourceserial(rjournal, end);
12470	dns_journal_commit(rjournal);
12471
12472	LOCK_ZONE(zone);
12473	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12474
12475	zone->sourceserial = end;
12476	zone->sourceserialset = ISC_TRUE;
12477	zone_needdump(zone, DNS_DUMP_DELAY);
12478
12479	TIME_NOW(&timenow);
12480	zone_settimer(zone, &timenow);
12481
12482	UNLOCK_ZONE(zone);
12483
12484	dns_db_closeversion(db, &oldver, ISC_FALSE);
12485	dns_db_closeversion(db, &newver, ISC_TRUE);
12486
12487 failure:
12488	if (result != ISC_R_SUCCESS)
12489		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
12490			     dns_result_totext(result));
12491	if (tuple != NULL)
12492		dns_difftuple_free(&tuple);
12493	if (soatuple != NULL)
12494		dns_difftuple_free(&soatuple);
12495	if (db != NULL) {
12496		if (oldver != NULL)
12497			dns_db_closeversion(db, &oldver, ISC_FALSE);
12498		if (newver != NULL)
12499			dns_db_closeversion(db, &newver, ISC_FALSE);
12500		if (node != NULL)
12501			dns_db_detachnode(db, &node);
12502		dns_db_detach(&db);
12503	}
12504	if (rjournal != NULL)
12505		dns_journal_destroy(&rjournal);
12506	dns_diff_clear(&diff);
12507	dns_zone_idetach(&zone);
12508}
12509
12510static isc_result_t
12511zone_send_secureserial(dns_zone_t *zone, isc_boolean_t locked,
12512		       isc_uint32_t serial)
12513{
12514	isc_event_t *e;
12515	dns_zone_t *dummy = NULL;
12516
12517	e = isc_event_allocate(zone->secure->mctx, zone,
12518			       DNS_EVENT_ZONESECURESERIAL,
12519			       receive_secure_serial, zone->secure,
12520			       sizeof(struct secure_event));
12521	if (e == NULL)
12522		return (ISC_R_NOMEMORY);
12523	((struct secure_event *)e)->serial = serial;
12524	if (locked)
12525		zone_iattach(zone->secure, &dummy);
12526	else
12527		dns_zone_iattach(zone->secure, &dummy);
12528	isc_task_send(zone->secure->task, &e);
12529
12530	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
12531	return (ISC_R_SUCCESS);
12532}
12533
12534static isc_result_t
12535checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
12536	       dns_rdataset_t *rdataset, isc_uint32_t oldserial)
12537{
12538	dns_rdata_soa_t soa;
12539	dns_rdata_t rdata = DNS_RDATA_INIT;
12540	dns_rdatalist_t temprdatalist;
12541	dns_rdataset_t temprdataset;
12542	isc_buffer_t b;
12543	isc_result_t result;
12544	unsigned char buf[DNS_SOA_BUFFERSIZE];
12545
12546	result = dns_rdataset_first(rdataset);
12547	RUNTIME_CHECK(result == ISC_R_SUCCESS);
12548	dns_rdataset_current(rdataset, &rdata);
12549	dns_rdata_tostruct(&rdata, &soa, NULL);
12550
12551	if (isc_serial_gt(soa.serial, oldserial))
12552		return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
12553					   NULL));
12554	/*
12555	 * Always bump the serial.
12556	 */
12557	oldserial++;
12558	if (oldserial == 0)
12559		oldserial++;
12560	soa.serial = oldserial;
12561
12562	/*
12563	 * Construct a replacement rdataset.
12564	 */
12565	dns_rdata_reset(&rdata);
12566	isc_buffer_init(&b, buf, sizeof(buf));
12567	result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
12568				      dns_rdatatype_soa, &soa, &b);
12569	RUNTIME_CHECK(result == ISC_R_SUCCESS);
12570	temprdatalist.rdclass = rdata.rdclass;
12571	temprdatalist.type = rdata.type;
12572	temprdatalist.covers = 0;
12573	temprdatalist.ttl = rdataset->ttl;
12574	ISC_LIST_INIT(temprdatalist.rdata);
12575	ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
12576
12577	dns_rdataset_init(&temprdataset);
12578	result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
12579	RUNTIME_CHECK(result == ISC_R_SUCCESS);
12580	return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
12581				   0, NULL));
12582}
12583
12584static void
12585receive_secure_db(isc_task_t *task, isc_event_t *event) {
12586	isc_result_t result;
12587	dns_zone_t *zone;
12588	dns_db_t *rawdb, *db = NULL;
12589	dns_dbnode_t *rawnode = NULL, *node = NULL;
12590	dns_fixedname_t fname;
12591	dns_name_t *name;
12592	dns_dbiterator_t *dbiterator = NULL;
12593	dns_rdatasetiter_t *rdsit = NULL;
12594	dns_rdataset_t rdataset;
12595	dns_dbversion_t *version = NULL;
12596	isc_time_t loadtime;
12597	unsigned int oldserial = 0;
12598	isc_boolean_t have_oldserial = ISC_FALSE;
12599
12600	UNUSED(task);
12601
12602	zone = event->ev_arg;
12603	rawdb = ((struct secure_event *)event)->db;
12604	isc_event_free(&event);
12605
12606	REQUIRE(inline_secure(zone));
12607
12608	dns_fixedname_init(&fname);
12609	name = dns_fixedname_name(&fname);
12610	dns_rdataset_init(&rdataset);
12611
12612	TIME_NOW(&loadtime);
12613	if (zone->db != NULL) {
12614		result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
12615		if (result == ISC_R_SUCCESS)
12616			have_oldserial = ISC_TRUE;
12617	}
12618
12619	result = dns_db_create(zone->mctx, zone->db_argv[0],
12620			       &zone->origin, dns_dbtype_zone, zone->rdclass,
12621			       zone->db_argc - 1, zone->db_argv + 1, &db);
12622	if (result != ISC_R_SUCCESS)
12623		goto failure;
12624
12625	result = dns_db_newversion(db, &version);
12626	if (result != ISC_R_SUCCESS)
12627		goto failure;
12628
12629	result = dns_db_createiterator(rawdb, 0, &dbiterator);
12630	if (result != ISC_R_SUCCESS)
12631		goto failure;
12632
12633	for (result = dns_dbiterator_first(dbiterator);
12634	     result == ISC_R_SUCCESS;
12635	     result = dns_dbiterator_next(dbiterator)) {
12636		result = dns_dbiterator_current(dbiterator, &rawnode, name);
12637		if (result != ISC_R_SUCCESS)
12638			continue;
12639
12640		result = dns_db_findnode(db, name, ISC_TRUE, &node);
12641		if (result != ISC_R_SUCCESS)
12642			goto failure;
12643
12644		result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
12645		if (result != ISC_R_SUCCESS)
12646			goto failure;
12647
12648		for (result = dns_rdatasetiter_first(rdsit);
12649		     result == ISC_R_SUCCESS;
12650		     result = dns_rdatasetiter_next(rdsit)) {
12651			dns_rdatasetiter_current(rdsit, &rdataset);
12652			if (rdataset.type == dns_rdatatype_nsec ||
12653			    rdataset.type == dns_rdatatype_rrsig ||
12654			    rdataset.type == dns_rdatatype_nsec3 ||
12655			    rdataset.type == dns_rdatatype_dnskey ||
12656			    rdataset.type == dns_rdatatype_nsec3param) {
12657				dns_rdataset_disassociate(&rdataset);
12658				continue;
12659			}
12660			if (rdataset.type == dns_rdatatype_soa &&
12661			    have_oldserial) {
12662				result = checkandaddsoa(db, node, version,
12663							&rdataset, oldserial);
12664			} else
12665				result = dns_db_addrdataset(db, node, version,
12666							    0, &rdataset, 0,
12667							    NULL);
12668			if (result != ISC_R_SUCCESS)
12669				goto failure;
12670
12671			dns_rdataset_disassociate(&rdataset);
12672		}
12673		dns_rdatasetiter_destroy(&rdsit);
12674		dns_db_detachnode(rawdb, &rawnode);
12675		dns_db_detachnode(db, &node);
12676	}
12677
12678	dns_db_closeversion(db, &version, ISC_TRUE);
12679	/*
12680	 * Lock hierachy zmgr, raw, zone.
12681	 */
12682	if (inline_secure(zone))
12683		LOCK_ZONE(zone->raw);
12684	LOCK_ZONE(zone);
12685	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12686	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
12687	zone_needdump(zone, 0); /* XXXMPA */
12688	UNLOCK_ZONE(zone);
12689	if (inline_secure(zone))
12690		UNLOCK_ZONE(zone->raw);
12691
12692 failure:
12693	if (result != ISC_R_SUCCESS)
12694		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
12695			     dns_result_totext(result));
12696
12697	if (dns_rdataset_isassociated(&rdataset))
12698		dns_rdataset_disassociate(&rdataset);
12699	if (db != NULL) {
12700		if (node != NULL)
12701			dns_db_detachnode(db, &node);
12702		dns_db_detach(&db);
12703	}
12704	if (rawnode != NULL)
12705		dns_db_detachnode(rawdb, &rawnode);
12706	dns_db_detach(&rawdb);
12707	if (dbiterator != NULL)
12708		dns_dbiterator_destroy(&dbiterator);
12709	dns_zone_idetach(&zone);
12710}
12711
12712static isc_result_t
12713zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked, dns_db_t *db) {
12714	isc_event_t *e;
12715	dns_db_t *dummy = NULL;
12716	dns_zone_t *secure = NULL;
12717
12718	e = isc_event_allocate(zone->secure->mctx, zone,
12719			       DNS_EVENT_ZONESECUREDB,
12720			       receive_secure_db, zone->secure,
12721			       sizeof(struct secure_event));
12722	if (e == NULL)
12723		return (ISC_R_NOMEMORY);
12724	dns_db_attach(db, &dummy);
12725	((struct secure_event *)e)->db = dummy;
12726	if (locked)
12727		zone_iattach(zone->secure, &secure);
12728	else
12729		dns_zone_iattach(zone->secure, &secure);
12730
12731	isc_task_send(zone->secure->task, &e);
12732	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
12733	return (ISC_R_SUCCESS);
12734}
12735
12736isc_result_t
12737dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
12738	isc_result_t result;
12739
12740	REQUIRE(DNS_ZONE_VALID(zone));
12741	LOCK_ZONE(zone);
12742	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12743	result = zone_replacedb(zone, db, dump);
12744	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12745	UNLOCK_ZONE(zone);
12746	return (result);
12747}
12748
12749static isc_result_t
12750zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
12751	dns_dbversion_t *ver;
12752	isc_result_t result;
12753	unsigned int soacount = 0;
12754	unsigned int nscount = 0;
12755
12756	/*
12757	 * 'zone' and 'zonedb' locked by caller.
12758	 */
12759	REQUIRE(DNS_ZONE_VALID(zone));
12760	REQUIRE(LOCKED_ZONE(zone));
12761
12762	result = zone_get_from_db(zone, db, &nscount, &soacount,
12763				  NULL, NULL, NULL, NULL, NULL, NULL);
12764	if (result == ISC_R_SUCCESS) {
12765		if (soacount != 1) {
12766			dns_zone_log(zone, ISC_LOG_ERROR,
12767				     "has %d SOA records", soacount);
12768			result = DNS_R_BADZONE;
12769		}
12770		if (nscount == 0 && zone->type != dns_zone_key) {
12771			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
12772			result = DNS_R_BADZONE;
12773		}
12774		if (result != ISC_R_SUCCESS)
12775			return (result);
12776	} else {
12777		dns_zone_log(zone, ISC_LOG_ERROR,
12778			    "retrieving SOA and NS records failed: %s",
12779			    dns_result_totext(result));
12780		return (result);
12781	}
12782
12783	result = check_nsec3param(zone, db);
12784	if (result != ISC_R_SUCCESS)
12785		return (result);
12786
12787	ver = NULL;
12788	dns_db_currentversion(db, &ver);
12789
12790	/*
12791	 * The initial version of a slave zone is always dumped;
12792	 * subsequent versions may be journaled instead if this
12793	 * is enabled in the configuration.
12794	 */
12795	if (zone->db != NULL && zone->journal != NULL &&
12796	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
12797	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
12798	{
12799		isc_uint32_t serial, oldserial;
12800
12801		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
12802
12803		result = dns_db_getsoaserial(db, ver, &serial);
12804		if (result != ISC_R_SUCCESS) {
12805			dns_zone_log(zone, ISC_LOG_ERROR,
12806				     "ixfr-from-differences: unable to get "
12807				     "new serial");
12808			goto fail;
12809		}
12810
12811		/*
12812		 * This is checked in zone_postload() for master zones.
12813		 */
12814		result = zone_get_from_db(zone, zone->db, NULL, NULL,
12815					  &oldserial, NULL, NULL, NULL, NULL,
12816					  NULL);
12817		RUNTIME_CHECK(result == ISC_R_SUCCESS);
12818		if ((zone->type == dns_zone_slave ||
12819		     (zone->type == dns_zone_redirect &&
12820		      zone->masters != NULL))
12821		    && !isc_serial_gt(serial, oldserial)) {
12822			isc_uint32_t serialmin, serialmax;
12823			serialmin = (oldserial + 1) & 0xffffffffU;
12824			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
12825			dns_zone_log(zone, ISC_LOG_ERROR,
12826				     "ixfr-from-differences: failed: "
12827				     "new serial (%u) out of range [%u - %u]",
12828				     serial, serialmin, serialmax);
12829			result = ISC_R_RANGE;
12830			goto fail;
12831		}
12832
12833		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
12834				     zone->journal);
12835		if (result != ISC_R_SUCCESS)
12836			goto fail;
12837		if (dump)
12838			zone_needdump(zone, DNS_DUMP_DELAY);
12839		else if (zone->journalsize != -1) {
12840			result = dns_journal_compact(zone->mctx, zone->journal,
12841						     serial, zone->journalsize);
12842			switch (result) {
12843			case ISC_R_SUCCESS:
12844			case ISC_R_NOSPACE:
12845			case ISC_R_NOTFOUND:
12846				dns_zone_log(zone, ISC_LOG_DEBUG(3),
12847					     "dns_journal_compact: %s",
12848					     dns_result_totext(result));
12849				break;
12850			default:
12851				dns_zone_log(zone, ISC_LOG_ERROR,
12852					     "dns_journal_compact failed: %s",
12853					     dns_result_totext(result));
12854				break;
12855			}
12856		}
12857		if (zone->type == dns_zone_master && inline_raw(zone))
12858			zone_send_secureserial(zone, ISC_FALSE, serial);
12859	} else {
12860		if (dump && zone->masterfile != NULL) {
12861			/*
12862			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
12863			 * to keep the old masterfile.
12864			 */
12865			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
12866			    remove(zone->masterfile) < 0 && errno != ENOENT) {
12867				char strbuf[ISC_STRERRORSIZE];
12868				isc__strerror(errno, strbuf, sizeof(strbuf));
12869				isc_log_write(dns_lctx,
12870					      DNS_LOGCATEGORY_GENERAL,
12871					      DNS_LOGMODULE_ZONE,
12872					      ISC_LOG_WARNING,
12873					      "unable to remove masterfile "
12874					      "'%s': '%s'",
12875					      zone->masterfile, strbuf);
12876			}
12877			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
12878				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
12879			else
12880				zone_needdump(zone, 0);
12881		}
12882		if (dump && zone->journal != NULL) {
12883			/*
12884			 * The in-memory database just changed, and
12885			 * because 'dump' is set, it didn't change by
12886			 * being loaded from disk.  Also, we have not
12887			 * journaled diffs for this change.
12888			 * Therefore, the on-disk journal is missing
12889			 * the deltas for this change.	Since it can
12890			 * no longer be used to bring the zone
12891			 * up-to-date, it is useless and should be
12892			 * removed.
12893			 */
12894			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
12895				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
12896				      "removing journal file");
12897			if (remove(zone->journal) < 0 && errno != ENOENT) {
12898				char strbuf[ISC_STRERRORSIZE];
12899				isc__strerror(errno, strbuf, sizeof(strbuf));
12900				isc_log_write(dns_lctx,
12901					      DNS_LOGCATEGORY_GENERAL,
12902					      DNS_LOGMODULE_ZONE,
12903					      ISC_LOG_WARNING,
12904					      "unable to remove journal "
12905					      "'%s': '%s'",
12906					      zone->journal, strbuf);
12907			}
12908		}
12909
12910		if (inline_raw(zone))
12911			zone_send_securedb(zone, ISC_FALSE, db);
12912	}
12913
12914	dns_db_closeversion(db, &ver, ISC_FALSE);
12915
12916	dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
12917
12918	if (zone->db != NULL)
12919		zone_detachdb(zone);
12920	zone_attachdb(zone, db);
12921	dns_db_settask(zone->db, zone->task);
12922	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
12923	return (ISC_R_SUCCESS);
12924
12925 fail:
12926	dns_db_closeversion(db, &ver, ISC_FALSE);
12927	return (result);
12928}
12929
12930/* The caller must hold the dblock as a writer. */
12931static inline void
12932zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
12933	REQUIRE(zone->db == NULL && db != NULL);
12934
12935	dns_db_attach(db, &zone->db);
12936	if (zone->acache != NULL) {
12937		isc_result_t result;
12938		result = dns_acache_setdb(zone->acache, db);
12939		if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
12940			UNEXPECTED_ERROR(__FILE__, __LINE__,
12941					 "dns_acache_setdb() failed: %s",
12942					 isc_result_totext(result));
12943		}
12944	}
12945}
12946
12947/* The caller must hold the dblock as a writer. */
12948static inline void
12949zone_detachdb(dns_zone_t *zone) {
12950	REQUIRE(zone->db != NULL);
12951
12952	if (zone->acache != NULL)
12953		(void)dns_acache_putdb(zone->acache, zone->db);
12954	dns_db_detach(&zone->db);
12955}
12956
12957static void
12958zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
12959	isc_time_t now;
12960	isc_boolean_t again = ISC_FALSE;
12961	unsigned int soacount;
12962	unsigned int nscount;
12963	isc_uint32_t serial, refresh, retry, expire, minimum;
12964	isc_result_t xfrresult = result;
12965	isc_boolean_t free_needed;
12966
12967	REQUIRE(DNS_ZONE_VALID(zone));
12968
12969	dns_zone_log(zone, ISC_LOG_DEBUG(1),
12970		     "zone transfer finished: %s", dns_result_totext(result));
12971
12972	LOCK_ZONE(zone);
12973	INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
12974	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12975	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
12976
12977	TIME_NOW(&now);
12978	switch (result) {
12979	case ISC_R_SUCCESS:
12980		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12981		/*FALLTHROUGH*/
12982	case DNS_R_UPTODATE:
12983		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
12984		/*
12985		 * Has the zone expired underneath us?
12986		 */
12987		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12988		if (zone->db == NULL) {
12989			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12990			goto same_master;
12991		}
12992
12993		/*
12994		 * Update the zone structure's data from the actual
12995		 * SOA received.
12996		 */
12997		nscount = 0;
12998		soacount = 0;
12999		INSIST(zone->db != NULL);
13000		result = zone_get_from_db(zone, zone->db, &nscount,
13001					  &soacount, &serial, &refresh,
13002					  &retry, &expire, &minimum, NULL);
13003		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13004		if (result == ISC_R_SUCCESS) {
13005			if (soacount != 1)
13006				dns_zone_log(zone, ISC_LOG_ERROR,
13007					     "transferred zone "
13008					     "has %d SOA record%s", soacount,
13009					     (soacount != 0) ? "s" : "");
13010			if (nscount == 0) {
13011				dns_zone_log(zone, ISC_LOG_ERROR,
13012					     "transferred zone "
13013					     "has no NS records");
13014				if (DNS_ZONE_FLAG(zone,
13015						  DNS_ZONEFLG_HAVETIMERS)) {
13016					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
13017					zone->retry = DNS_ZONE_DEFAULTRETRY;
13018				}
13019				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13020				zone_unload(zone);
13021				goto next_master;
13022			}
13023			zone->refresh = RANGE(refresh, zone->minrefresh,
13024					      zone->maxrefresh);
13025			zone->retry = RANGE(retry, zone->minretry,
13026					    zone->maxretry);
13027			zone->expire = RANGE(expire,
13028					     zone->refresh + zone->retry,
13029					     DNS_MAX_EXPIRE);
13030			zone->minimum = minimum;
13031			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13032		}
13033
13034		/*
13035		 * Set our next update/expire times.
13036		 */
13037		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
13038			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13039			zone->refreshtime = now;
13040			DNS_ZONE_TIME_ADD(&now, zone->expire,
13041					  &zone->expiretime);
13042		} else {
13043			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
13044					    &zone->refreshtime);
13045			DNS_ZONE_TIME_ADD(&now, zone->expire,
13046					  &zone->expiretime);
13047		}
13048		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
13049			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
13050			if (zone->tsigkey != NULL) {
13051				char namebuf[DNS_NAME_FORMATSIZE];
13052				dns_name_format(&zone->tsigkey->name, namebuf,
13053						sizeof(namebuf));
13054				snprintf(buf, sizeof(buf), ": TSIG '%s'",
13055					 namebuf);
13056			} else
13057				buf[0] = '\0';
13058			dns_zone_log(zone, ISC_LOG_INFO,
13059				     "transferred serial %u%s",
13060				     serial, buf);
13061			if (inline_raw(zone))
13062				zone_send_secureserial(zone, ISC_FALSE, serial);
13063		}
13064
13065		/*
13066		 * This is not necessary if we just performed a AXFR
13067		 * however it is necessary for an IXFR / UPTODATE and
13068		 * won't hurt with an AXFR.
13069		 */
13070		if (zone->masterfile != NULL || zone->journal != NULL) {
13071			result = ISC_R_FAILURE;
13072			if (zone->journal != NULL)
13073				result = isc_file_settime(zone->journal, &now);
13074			if (result != ISC_R_SUCCESS &&
13075			    zone->masterfile != NULL)
13076				result = isc_file_settime(zone->masterfile,
13077							  &now);
13078			/* Someone removed the file from underneath us! */
13079			if (result == ISC_R_FILENOTFOUND &&
13080			    zone->masterfile != NULL) {
13081				unsigned int delay = DNS_DUMP_DELAY;
13082				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY))
13083					delay = 0;
13084				zone_needdump(zone, delay);
13085			} else if (result != ISC_R_SUCCESS)
13086				dns_zone_log(zone, ISC_LOG_ERROR,
13087					     "transfer: could not set file "
13088					     "modification time of '%s': %s",
13089					     zone->masterfile,
13090					     dns_result_totext(result));
13091		}
13092		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
13093		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
13094		break;
13095
13096	case DNS_R_BADIXFR:
13097		/* Force retry with AXFR. */
13098		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
13099		goto same_master;
13100
13101	default:
13102	next_master:
13103		/*
13104		 * Skip to next failed / untried master.
13105		 */
13106		do {
13107			zone->curmaster++;
13108		} while (zone->curmaster < zone->masterscnt &&
13109			 zone->mastersok[zone->curmaster]);
13110		/* FALLTHROUGH */
13111	same_master:
13112		if (zone->curmaster >= zone->masterscnt) {
13113			zone->curmaster = 0;
13114			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13115			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13116				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
13117				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13118				while (zone->curmaster < zone->masterscnt &&
13119				       zone->mastersok[zone->curmaster])
13120					zone->curmaster++;
13121				again = ISC_TRUE;
13122			} else
13123				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13124		} else {
13125			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
13126			again = ISC_TRUE;
13127		}
13128		inc_stats(zone, dns_zonestatscounter_xfrfail);
13129		break;
13130	}
13131	zone_settimer(zone, &now);
13132
13133	/*
13134	 * If creating the transfer object failed, zone->xfr is NULL.
13135	 * Otherwise, we are called as the done callback of a zone
13136	 * transfer object that just entered its shutting-down
13137	 * state.  Since we are no longer responsible for shutting
13138	 * it down, we can detach our reference.
13139	 */
13140	if (zone->xfr != NULL)
13141		dns_xfrin_detach(&zone->xfr);
13142
13143	if (zone->tsigkey != NULL)
13144		dns_tsigkey_detach(&zone->tsigkey);
13145
13146	/*
13147	 * Handle any deferred journal compaction.
13148	 */
13149	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
13150		result = dns_journal_compact(zone->mctx, zone->journal,
13151					     zone->compact_serial,
13152					     zone->journalsize);
13153		switch (result) {
13154		case ISC_R_SUCCESS:
13155		case ISC_R_NOSPACE:
13156		case ISC_R_NOTFOUND:
13157			dns_zone_log(zone, ISC_LOG_DEBUG(3),
13158				     "dns_journal_compact: %s",
13159				     dns_result_totext(result));
13160			break;
13161		default:
13162			dns_zone_log(zone, ISC_LOG_ERROR,
13163				     "dns_journal_compact failed: %s",
13164				     dns_result_totext(result));
13165			break;
13166		}
13167		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
13168	}
13169
13170	/*
13171	 * This transfer finishing freed up a transfer quota slot.
13172	 * Let any other zones waiting for quota have it.
13173	 */
13174	UNLOCK_ZONE(zone);
13175	RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13176	ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
13177	zone->statelist = NULL;
13178	zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
13179	RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13180	LOCK_ZONE(zone);
13181
13182	/*
13183	 * Retry with a different server if necessary.
13184	 */
13185	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
13186		queue_soa_query(zone);
13187
13188	INSIST(zone->irefs > 0);
13189	zone->irefs--;
13190	free_needed = exit_check(zone);
13191	UNLOCK_ZONE(zone);
13192	if (free_needed)
13193		zone_free(zone);
13194}
13195
13196static void
13197zone_loaddone(void *arg, isc_result_t result) {
13198	static char me[] = "zone_loaddone";
13199	dns_load_t *load = arg;
13200	dns_zone_t *zone;
13201	isc_result_t tresult;
13202
13203	REQUIRE(DNS_LOAD_VALID(load));
13204	zone = load->zone;
13205
13206	ENTER;
13207
13208	tresult = dns_db_endload(load->db, &load->callbacks.add_private);
13209	if (tresult != ISC_R_SUCCESS &&
13210	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
13211		result = tresult;
13212
13213	/*
13214	 * Lock hierachy zmgr, raw, zone.
13215	 */
13216	if (inline_secure(zone))
13217		LOCK_ZONE(zone->raw);
13218	LOCK_ZONE(load->zone);
13219	(void)zone_postload(load->zone, load->db, load->loadtime, result);
13220	zonemgr_putio(&load->zone->readio);
13221	DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
13222	zone_idetach(&load->callbacks.zone);
13223	/*
13224	 * Leave the zone frozen if the reload fails.
13225	 */
13226	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
13227	     DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW))
13228		zone->update_disabled = ISC_FALSE;
13229	DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW);
13230	UNLOCK_ZONE(load->zone);
13231	if (inline_secure(zone))
13232		UNLOCK_ZONE(zone->raw);
13233
13234	load->magic = 0;
13235	dns_db_detach(&load->db);
13236	if (load->zone->lctx != NULL)
13237		dns_loadctx_detach(&load->zone->lctx);
13238	dns_zone_idetach(&load->zone);
13239	isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
13240}
13241
13242void
13243dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
13244	REQUIRE(DNS_ZONE_VALID(zone));
13245	REQUIRE(table != NULL);
13246	REQUIRE(*table == NULL);
13247
13248	LOCK_ZONE(zone);
13249	if (zone->ssutable != NULL)
13250		dns_ssutable_attach(zone->ssutable, table);
13251	UNLOCK_ZONE(zone);
13252}
13253
13254void
13255dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
13256	REQUIRE(DNS_ZONE_VALID(zone));
13257
13258	LOCK_ZONE(zone);
13259	if (zone->ssutable != NULL)
13260		dns_ssutable_detach(&zone->ssutable);
13261	if (table != NULL)
13262		dns_ssutable_attach(table, &zone->ssutable);
13263	UNLOCK_ZONE(zone);
13264}
13265
13266void
13267dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
13268	REQUIRE(DNS_ZONE_VALID(zone));
13269
13270	zone->sigvalidityinterval = interval;
13271}
13272
13273isc_uint32_t
13274dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
13275	REQUIRE(DNS_ZONE_VALID(zone));
13276
13277	return (zone->sigvalidityinterval);
13278}
13279
13280void
13281dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
13282	REQUIRE(DNS_ZONE_VALID(zone));
13283
13284	zone->sigresigninginterval = interval;
13285}
13286
13287isc_uint32_t
13288dns_zone_getsigresigninginterval(dns_zone_t *zone) {
13289	REQUIRE(DNS_ZONE_VALID(zone));
13290
13291	return (zone->sigresigninginterval);
13292}
13293
13294static void
13295queue_xfrin(dns_zone_t *zone) {
13296	const char me[] = "queue_xfrin";
13297	isc_result_t result;
13298	dns_zonemgr_t *zmgr = zone->zmgr;
13299
13300	ENTER;
13301
13302	INSIST(zone->statelist == NULL);
13303
13304	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13305	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
13306	LOCK_ZONE(zone);
13307	zone->irefs++;
13308	UNLOCK_ZONE(zone);
13309	zone->statelist = &zmgr->waiting_for_xfrin;
13310	result = zmgr_start_xfrin_ifquota(zmgr, zone);
13311	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13312
13313	if (result == ISC_R_QUOTA) {
13314		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
13315			      "zone transfer deferred due to quota");
13316	} else if (result != ISC_R_SUCCESS) {
13317		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
13318			      "starting zone transfer: %s",
13319			      isc_result_totext(result));
13320	}
13321}
13322
13323/*
13324 * This event callback is called when a zone has received
13325 * any necessary zone transfer quota.  This is the time
13326 * to go ahead and start the transfer.
13327 */
13328static void
13329got_transfer_quota(isc_task_t *task, isc_event_t *event) {
13330	isc_result_t result = ISC_R_SUCCESS;
13331	dns_peer_t *peer = NULL;
13332	char master[ISC_SOCKADDR_FORMATSIZE];
13333	char source[ISC_SOCKADDR_FORMATSIZE];
13334	dns_rdatatype_t xfrtype;
13335	dns_zone_t *zone = event->ev_arg;
13336	isc_netaddr_t masterip;
13337	isc_sockaddr_t sourceaddr;
13338	isc_sockaddr_t masteraddr;
13339	isc_time_t now;
13340	const char *soa_before = "";
13341
13342	UNUSED(task);
13343
13344	INSIST(task == zone->task);
13345
13346	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13347		result = ISC_R_CANCELED;
13348		goto cleanup;
13349	}
13350
13351	TIME_NOW(&now);
13352
13353	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13354	if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
13355				    &zone->sourceaddr, &now))
13356	{
13357		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13358		dns_zone_log(zone, ISC_LOG_INFO,
13359			     "got_transfer_quota: skipping zone transfer as "
13360			     "master %s (source %s) is unreachable (cached)",
13361			     master, source);
13362		result = ISC_R_CANCELED;
13363		goto cleanup;
13364	}
13365
13366	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
13367	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
13368
13369	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
13370		soa_before = "SOA before ";
13371	/*
13372	 * Decide whether we should request IXFR or AXFR.
13373	 */
13374	if (zone->db == NULL) {
13375		dns_zone_log(zone, ISC_LOG_DEBUG(1),
13376			     "no database exists yet, requesting AXFR of "
13377			     "initial version from %s", master);
13378		xfrtype = dns_rdatatype_axfr;
13379	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
13380		dns_zone_log(zone, ISC_LOG_DEBUG(1),
13381			     "forced reload, requesting AXFR of "
13382			     "initial version from %s", master);
13383		xfrtype = dns_rdatatype_axfr;
13384	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
13385		dns_zone_log(zone, ISC_LOG_DEBUG(1),
13386			     "retrying with AXFR from %s due to "
13387			     "previous IXFR failure", master);
13388		xfrtype = dns_rdatatype_axfr;
13389		LOCK_ZONE(zone);
13390		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
13391		UNLOCK_ZONE(zone);
13392	} else {
13393		isc_boolean_t use_ixfr = ISC_TRUE;
13394		if (peer != NULL)
13395			result = dns_peer_getrequestixfr(peer, &use_ixfr);
13396		if (peer == NULL || result != ISC_R_SUCCESS)
13397			use_ixfr = zone->requestixfr;
13398		if (use_ixfr == ISC_FALSE) {
13399			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13400				     "IXFR disabled, requesting %sAXFR from %s",
13401				     soa_before, master);
13402			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
13403				xfrtype = dns_rdatatype_soa;
13404			else
13405				xfrtype = dns_rdatatype_axfr;
13406		} else {
13407			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13408				     "requesting IXFR from %s", master);
13409			xfrtype = dns_rdatatype_ixfr;
13410		}
13411	}
13412
13413	/*
13414	 * Determine if we should attempt to sign the request with TSIG.
13415	 */
13416	result = ISC_R_NOTFOUND;
13417	/*
13418	 * First, look for a tsig key in the master statement, then
13419	 * try for a server key.
13420	 */
13421	if ((zone->masterkeynames != NULL) &&
13422	    (zone->masterkeynames[zone->curmaster] != NULL)) {
13423		dns_view_t *view = dns_zone_getview(zone);
13424		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
13425		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
13426	}
13427	if (zone->tsigkey == NULL)
13428		result = dns_view_getpeertsig(zone->view, &masterip,
13429					      &zone->tsigkey);
13430
13431	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
13432		dns_zone_log(zone, ISC_LOG_ERROR,
13433			     "could not get TSIG key for zone transfer: %s",
13434			     isc_result_totext(result));
13435	}
13436
13437	LOCK_ZONE(zone);
13438	masteraddr = zone->masteraddr;
13439	sourceaddr = zone->sourceaddr;
13440	UNLOCK_ZONE(zone);
13441	INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
13442	result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
13443				   zone->tsigkey, zone->mctx,
13444				   zone->zmgr->timermgr, zone->zmgr->socketmgr,
13445				   zone->task, zone_xfrdone, &zone->xfr);
13446	if (result == ISC_R_SUCCESS) {
13447		LOCK_ZONE(zone);
13448		if (xfrtype == dns_rdatatype_axfr) {
13449			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
13450				inc_stats(zone, dns_zonestatscounter_axfrreqv4);
13451			else
13452				inc_stats(zone, dns_zonestatscounter_axfrreqv6);
13453		} else if (xfrtype == dns_rdatatype_ixfr) {
13454			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
13455				inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
13456			else
13457				inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
13458		}
13459		UNLOCK_ZONE(zone);
13460	}
13461 cleanup:
13462	/*
13463	 * Any failure in this function is handled like a failed
13464	 * zone transfer.  This ensures that we get removed from
13465	 * zmgr->xfrin_in_progress.
13466	 */
13467	if (result != ISC_R_SUCCESS)
13468		zone_xfrdone(zone, result);
13469
13470	isc_event_free(&event);
13471}
13472
13473/*
13474 * Update forwarding support.
13475 */
13476
13477static void
13478forward_destroy(dns_forward_t *forward) {
13479
13480	forward->magic = 0;
13481	if (forward->request != NULL)
13482		dns_request_destroy(&forward->request);
13483	if (forward->msgbuf != NULL)
13484		isc_buffer_free(&forward->msgbuf);
13485	if (forward->zone != NULL) {
13486		LOCK(&forward->zone->lock);
13487		if (ISC_LINK_LINKED(forward, link))
13488			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
13489		UNLOCK(&forward->zone->lock);
13490		dns_zone_idetach(&forward->zone);
13491	}
13492	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
13493}
13494
13495static isc_result_t
13496sendtomaster(dns_forward_t *forward) {
13497	isc_result_t result;
13498	isc_sockaddr_t src;
13499
13500	LOCK_ZONE(forward->zone);
13501
13502	if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
13503		UNLOCK_ZONE(forward->zone);
13504		return (ISC_R_CANCELED);
13505	}
13506
13507	if (forward->which >= forward->zone->masterscnt) {
13508		UNLOCK_ZONE(forward->zone);
13509		return (ISC_R_NOMORE);
13510	}
13511
13512	forward->addr = forward->zone->masters[forward->which];
13513	/*
13514	 * Always use TCP regardless of whether the original update
13515	 * used TCP.
13516	 * XXX The timeout may but a bit small if we are far down a
13517	 * transfer graph and the master has to try several masters.
13518	 */
13519	switch (isc_sockaddr_pf(&forward->addr)) {
13520	case PF_INET:
13521		src = forward->zone->xfrsource4;
13522		break;
13523	case PF_INET6:
13524		src = forward->zone->xfrsource6;
13525		break;
13526	default:
13527		result = ISC_R_NOTIMPLEMENTED;
13528		goto unlock;
13529	}
13530	result = dns_request_createraw(forward->zone->view->requestmgr,
13531				       forward->msgbuf,
13532				       &src, &forward->addr,
13533				       DNS_REQUESTOPT_TCP, 15 /* XXX */,
13534				       forward->zone->task,
13535				       forward_callback, forward,
13536				       &forward->request);
13537	if (result == ISC_R_SUCCESS) {
13538		if (!ISC_LINK_LINKED(forward, link))
13539			ISC_LIST_APPEND(forward->zone->forwards, forward, link);
13540	}
13541
13542 unlock:
13543	UNLOCK_ZONE(forward->zone);
13544	return (result);
13545}
13546
13547static void
13548forward_callback(isc_task_t *task, isc_event_t *event) {
13549	const char me[] = "forward_callback";
13550	dns_requestevent_t *revent = (dns_requestevent_t *)event;
13551	dns_message_t *msg = NULL;
13552	char master[ISC_SOCKADDR_FORMATSIZE];
13553	isc_result_t result;
13554	dns_forward_t *forward;
13555	dns_zone_t *zone;
13556
13557	UNUSED(task);
13558
13559	forward = revent->ev_arg;
13560	INSIST(DNS_FORWARD_VALID(forward));
13561	zone = forward->zone;
13562	INSIST(DNS_ZONE_VALID(zone));
13563
13564	ENTER;
13565
13566	isc_sockaddr_format(&forward->addr, master, sizeof(master));
13567
13568	if (revent->result != ISC_R_SUCCESS) {
13569		dns_zone_log(zone, ISC_LOG_INFO,
13570			     "could not forward dynamic update to %s: %s",
13571			     master, dns_result_totext(revent->result));
13572		goto next_master;
13573	}
13574
13575	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13576	if (result != ISC_R_SUCCESS)
13577		goto next_master;
13578
13579	result = dns_request_getresponse(revent->request, msg,
13580					 DNS_MESSAGEPARSE_PRESERVEORDER |
13581					 DNS_MESSAGEPARSE_CLONEBUFFER);
13582	if (result != ISC_R_SUCCESS)
13583		goto next_master;
13584
13585	switch (msg->rcode) {
13586	/*
13587	 * Pass these rcodes back to client.
13588	 */
13589	case dns_rcode_noerror:
13590	case dns_rcode_yxdomain:
13591	case dns_rcode_yxrrset:
13592	case dns_rcode_nxrrset:
13593	case dns_rcode_refused:
13594	case dns_rcode_nxdomain:
13595		break;
13596
13597	/* These should not occur if the masters/zone are valid. */
13598	case dns_rcode_notzone:
13599	case dns_rcode_notauth: {
13600		char rcode[128];
13601		isc_buffer_t rb;
13602
13603		isc_buffer_init(&rb, rcode, sizeof(rcode));
13604		(void)dns_rcode_totext(msg->rcode, &rb);
13605		dns_zone_log(zone, ISC_LOG_WARNING,
13606			     "forwarding dynamic update: "
13607			     "unexpected response: master %s returned: %.*s",
13608			     master, (int)rb.used, rcode);
13609		goto next_master;
13610	}
13611
13612	/* Try another server for these rcodes. */
13613	case dns_rcode_formerr:
13614	case dns_rcode_servfail:
13615	case dns_rcode_notimp:
13616	case dns_rcode_badvers:
13617	default:
13618		goto next_master;
13619	}
13620
13621	/* call callback */
13622	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
13623	msg = NULL;
13624	dns_request_destroy(&forward->request);
13625	forward_destroy(forward);
13626	isc_event_free(&event);
13627	return;
13628
13629 next_master:
13630	if (msg != NULL)
13631		dns_message_destroy(&msg);
13632	isc_event_free(&event);
13633	forward->which++;
13634	dns_request_destroy(&forward->request);
13635	result = sendtomaster(forward);
13636	if (result != ISC_R_SUCCESS) {
13637		/* call callback */
13638		dns_zone_log(zone, ISC_LOG_DEBUG(3),
13639			     "exhausted dynamic update forwarder list");
13640		(forward->callback)(forward->callback_arg, result, NULL);
13641		forward_destroy(forward);
13642	}
13643}
13644
13645isc_result_t
13646dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
13647		       dns_updatecallback_t callback, void *callback_arg)
13648{
13649	dns_forward_t *forward;
13650	isc_result_t result;
13651	isc_region_t *mr;
13652
13653	REQUIRE(DNS_ZONE_VALID(zone));
13654	REQUIRE(msg != NULL);
13655	REQUIRE(callback != NULL);
13656
13657	forward = isc_mem_get(zone->mctx, sizeof(*forward));
13658	if (forward == NULL)
13659		return (ISC_R_NOMEMORY);
13660
13661	forward->request = NULL;
13662	forward->zone = NULL;
13663	forward->msgbuf = NULL;
13664	forward->which = 0;
13665	forward->mctx = 0;
13666	forward->callback = callback;
13667	forward->callback_arg = callback_arg;
13668	ISC_LINK_INIT(forward, link);
13669	forward->magic = FORWARD_MAGIC;
13670
13671	mr = dns_message_getrawmessage(msg);
13672	if (mr == NULL) {
13673		result = ISC_R_UNEXPECTEDEND;
13674		goto cleanup;
13675	}
13676
13677	result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
13678	if (result != ISC_R_SUCCESS)
13679		goto cleanup;
13680	result = isc_buffer_copyregion(forward->msgbuf, mr);
13681	if (result != ISC_R_SUCCESS)
13682		goto cleanup;
13683
13684	isc_mem_attach(zone->mctx, &forward->mctx);
13685	dns_zone_iattach(zone, &forward->zone);
13686	result = sendtomaster(forward);
13687
13688 cleanup:
13689	if (result != ISC_R_SUCCESS) {
13690		forward_destroy(forward);
13691	}
13692	return (result);
13693}
13694
13695isc_result_t
13696dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
13697	REQUIRE(DNS_ZONE_VALID(zone));
13698	REQUIRE(next != NULL && *next == NULL);
13699
13700	*next = ISC_LIST_NEXT(zone, link);
13701	if (*next == NULL)
13702		return (ISC_R_NOMORE);
13703	else
13704		return (ISC_R_SUCCESS);
13705}
13706
13707isc_result_t
13708dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
13709	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13710	REQUIRE(first != NULL && *first == NULL);
13711
13712	*first = ISC_LIST_HEAD(zmgr->zones);
13713	if (*first == NULL)
13714		return (ISC_R_NOMORE);
13715	else
13716		return (ISC_R_SUCCESS);
13717}
13718
13719/***
13720 ***	Zone manager.
13721 ***/
13722
13723isc_result_t
13724dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
13725		   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
13726		   dns_zonemgr_t **zmgrp)
13727{
13728	dns_zonemgr_t *zmgr;
13729	isc_result_t result;
13730	isc_interval_t interval;
13731
13732	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
13733	if (zmgr == NULL)
13734		return (ISC_R_NOMEMORY);
13735	zmgr->mctx = NULL;
13736	zmgr->refs = 1;
13737	isc_mem_attach(mctx, &zmgr->mctx);
13738	zmgr->taskmgr = taskmgr;
13739	zmgr->timermgr = timermgr;
13740	zmgr->socketmgr = socketmgr;
13741	zmgr->zonetasks = NULL;
13742	zmgr->loadtasks = NULL;
13743	zmgr->task = NULL;
13744	zmgr->rl = NULL;
13745	ISC_LIST_INIT(zmgr->zones);
13746	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
13747	ISC_LIST_INIT(zmgr->xfrin_in_progress);
13748	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
13749	result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
13750	if (result != ISC_R_SUCCESS)
13751		goto free_mem;
13752
13753	zmgr->transfersin = 10;
13754	zmgr->transfersperns = 2;
13755
13756	/* Unreachable lock. */
13757	result = isc_rwlock_init(&zmgr->urlock, 0, 0);
13758	if (result != ISC_R_SUCCESS)
13759		goto free_rwlock;
13760
13761	/* Create a single task for queueing of SOA queries. */
13762	result = isc_task_create(taskmgr, 1, &zmgr->task);
13763	if (result != ISC_R_SUCCESS)
13764		goto free_urlock;
13765
13766	isc_task_setname(zmgr->task, "zmgr", zmgr);
13767	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
13768					&zmgr->rl);
13769	if (result != ISC_R_SUCCESS)
13770		goto free_task;
13771
13772	/* default to 20 refresh queries / notifies per second. */
13773	isc_interval_set(&interval, 0, 1000000000/2);
13774	result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
13775	RUNTIME_CHECK(result == ISC_R_SUCCESS);
13776	isc_ratelimiter_setpertic(zmgr->rl, 10);
13777
13778	zmgr->iolimit = 1;
13779	zmgr->ioactive = 0;
13780	ISC_LIST_INIT(zmgr->high);
13781	ISC_LIST_INIT(zmgr->low);
13782
13783	result = isc_mutex_init(&zmgr->iolock);
13784	if (result != ISC_R_SUCCESS)
13785		goto free_rl;
13786
13787	zmgr->magic = ZONEMGR_MAGIC;
13788
13789	*zmgrp = zmgr;
13790	return (ISC_R_SUCCESS);
13791
13792#if 0
13793 free_iolock:
13794	DESTROYLOCK(&zmgr->iolock);
13795#endif
13796 free_rl:
13797	isc_ratelimiter_detach(&zmgr->rl);
13798 free_task:
13799	isc_task_detach(&zmgr->task);
13800 free_urlock:
13801	isc_rwlock_destroy(&zmgr->urlock);
13802 free_rwlock:
13803	isc_rwlock_destroy(&zmgr->rwlock);
13804 free_mem:
13805	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
13806	isc_mem_detach(&mctx);
13807	return (result);
13808}
13809
13810isc_result_t
13811dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
13812	isc_result_t result;
13813
13814	REQUIRE(DNS_ZONE_VALID(zone));
13815	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13816
13817	if (zmgr->zonetasks == NULL)
13818		return (ISC_R_FAILURE);
13819
13820	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13821	LOCK_ZONE(zone);
13822	REQUIRE(zone->task == NULL);
13823	REQUIRE(zone->timer == NULL);
13824	REQUIRE(zone->zmgr == NULL);
13825
13826	isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
13827	isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
13828
13829	/*
13830	 * Set the task name.  The tag will arbitrarily point to one
13831	 * of the zones sharing the task (in practice, the one
13832	 * to be managed last).
13833	 */
13834	isc_task_setname(zone->task, "zone", zone);
13835	isc_task_setname(zone->loadtask, "loadzone", zone);
13836
13837	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
13838				  NULL, NULL,
13839				  zone->task, zone_timer, zone,
13840				  &zone->timer);
13841
13842	if (result != ISC_R_SUCCESS)
13843		goto cleanup_tasks;
13844
13845	/*
13846	 * The timer "holds" a iref.
13847	 */
13848	zone->irefs++;
13849	INSIST(zone->irefs != 0);
13850
13851	ISC_LIST_APPEND(zmgr->zones, zone, link);
13852	zone->zmgr = zmgr;
13853	zmgr->refs++;
13854
13855	goto unlock;
13856
13857 cleanup_tasks:
13858	isc_task_detach(&zone->loadtask);
13859	isc_task_detach(&zone->task);
13860
13861 unlock:
13862	UNLOCK_ZONE(zone);
13863	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13864	return (result);
13865}
13866
13867void
13868dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
13869	isc_boolean_t free_now = ISC_FALSE;
13870
13871	REQUIRE(DNS_ZONE_VALID(zone));
13872	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13873	REQUIRE(zone->zmgr == zmgr);
13874
13875	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13876	LOCK_ZONE(zone);
13877
13878	ISC_LIST_UNLINK(zmgr->zones, zone, link);
13879	zone->zmgr = NULL;
13880	zmgr->refs--;
13881	if (zmgr->refs == 0)
13882		free_now = ISC_TRUE;
13883
13884	UNLOCK_ZONE(zone);
13885	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13886
13887	if (free_now)
13888		zonemgr_free(zmgr);
13889	ENSURE(zone->zmgr == NULL);
13890}
13891
13892void
13893dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
13894	REQUIRE(DNS_ZONEMGR_VALID(source));
13895	REQUIRE(target != NULL && *target == NULL);
13896
13897	RWLOCK(&source->rwlock, isc_rwlocktype_write);
13898	REQUIRE(source->refs > 0);
13899	source->refs++;
13900	INSIST(source->refs > 0);
13901	RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
13902	*target = source;
13903}
13904
13905void
13906dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
13907	dns_zonemgr_t *zmgr;
13908	isc_boolean_t free_now = ISC_FALSE;
13909
13910	REQUIRE(zmgrp != NULL);
13911	zmgr = *zmgrp;
13912	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13913
13914	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13915	zmgr->refs--;
13916	if (zmgr->refs == 0)
13917		free_now = ISC_TRUE;
13918	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13919
13920	if (free_now)
13921		zonemgr_free(zmgr);
13922	*zmgrp = NULL;
13923}
13924
13925isc_result_t
13926dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
13927	dns_zone_t *p;
13928
13929	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13930
13931	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13932	for (p = ISC_LIST_HEAD(zmgr->zones);
13933	     p != NULL;
13934	     p = ISC_LIST_NEXT(p, link))
13935	{
13936		dns_zone_maintenance(p);
13937	}
13938	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13939
13940	/*
13941	 * Recent configuration changes may have increased the
13942	 * amount of available transfers quota.  Make sure any
13943	 * transfers currently blocked on quota get started if
13944	 * possible.
13945	 */
13946	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13947	zmgr_resume_xfrs(zmgr, ISC_TRUE);
13948	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13949	return (ISC_R_SUCCESS);
13950}
13951
13952void
13953dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
13954
13955	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13956
13957	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13958	zmgr_resume_xfrs(zmgr, ISC_TRUE);
13959	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13960}
13961
13962void
13963dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
13964	dns_zone_t *zone;
13965
13966	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13967
13968	isc_ratelimiter_shutdown(zmgr->rl);
13969
13970	if (zmgr->task != NULL)
13971		isc_task_destroy(&zmgr->task);
13972	if (zmgr->zonetasks != NULL)
13973		isc_taskpool_destroy(&zmgr->zonetasks);
13974	if (zmgr->loadtasks != NULL)
13975		isc_taskpool_destroy(&zmgr->loadtasks);
13976
13977	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13978	for (zone = ISC_LIST_HEAD(zmgr->zones);
13979	     zone != NULL;
13980	     zone = ISC_LIST_NEXT(zone, link))
13981	{
13982		LOCK_ZONE(zone);
13983		forward_cancel(zone);
13984		UNLOCK_ZONE(zone);
13985	}
13986	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13987}
13988
13989isc_result_t
13990dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
13991	isc_result_t result;
13992	int ntasks = num_zones / 100;
13993	isc_taskpool_t *pool = NULL;
13994
13995	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13996
13997	/*
13998	 * For anything fewer than 1000 zones we use 10 tasks in
13999	 * the task pools.  More than that, and we'll scale at one
14000	 * task per 100 zones.
14001	 */
14002	if (ntasks < 10)
14003		ntasks = 10;
14004
14005	/* Create or resize the zone task pools. */
14006	if (zmgr->zonetasks == NULL)
14007		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
14008					     ntasks, 2, &pool);
14009	else
14010		result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
14011
14012	if (result == ISC_R_SUCCESS)
14013		zmgr->zonetasks = pool;
14014
14015	pool = NULL;
14016	if (zmgr->loadtasks == NULL)
14017		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
14018					     ntasks, 2, &pool);
14019	else
14020		result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
14021
14022	if (result == ISC_R_SUCCESS)
14023		zmgr->loadtasks = pool;
14024
14025#ifdef BIND9
14026	/*
14027	 * We always set all tasks in the zone-load task pool to
14028	 * privileged.  This prevents other tasks in the system from
14029	 * running while the server task manager is in privileged
14030	 * mode.
14031	 *
14032	 * NOTE: If we start using task privileges for any other
14033	 * part of the system than zone tasks, then this will need to be
14034	 * revisted.  In that case we'd want to turn on privileges for
14035	 * zone tasks only when we were loading, and turn them off the
14036	 * rest of the time.  For now, however, it's okay to just
14037	 * set it and forget it.
14038	 */
14039	isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
14040#endif
14041
14042	return (result);
14043}
14044
14045static void
14046zonemgr_free(dns_zonemgr_t *zmgr) {
14047	isc_mem_t *mctx;
14048
14049	INSIST(zmgr->refs == 0);
14050	INSIST(ISC_LIST_EMPTY(zmgr->zones));
14051
14052	zmgr->magic = 0;
14053
14054	DESTROYLOCK(&zmgr->iolock);
14055	isc_ratelimiter_detach(&zmgr->rl);
14056
14057	isc_rwlock_destroy(&zmgr->urlock);
14058	isc_rwlock_destroy(&zmgr->rwlock);
14059	mctx = zmgr->mctx;
14060	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14061	isc_mem_detach(&mctx);
14062}
14063
14064void
14065dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
14066	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14067
14068	zmgr->transfersin = value;
14069}
14070
14071isc_uint32_t
14072dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
14073	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14074
14075	return (zmgr->transfersin);
14076}
14077
14078void
14079dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
14080	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14081
14082	zmgr->transfersperns = value;
14083}
14084
14085isc_uint32_t
14086dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
14087	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14088
14089	return (zmgr->transfersperns);
14090}
14091
14092/*
14093 * Try to start a new incoming zone transfer to fill a quota
14094 * slot that was just vacated.
14095 *
14096 * Requires:
14097 *	The zone manager is locked by the caller.
14098 */
14099static void
14100zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
14101	dns_zone_t *zone;
14102	dns_zone_t *next;
14103
14104	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
14105	     zone != NULL;
14106	     zone = next)
14107	{
14108		isc_result_t result;
14109		next = ISC_LIST_NEXT(zone, statelink);
14110		result = zmgr_start_xfrin_ifquota(zmgr, zone);
14111		if (result == ISC_R_SUCCESS) {
14112			if (multi)
14113				continue;
14114			/*
14115			 * We successfully filled the slot.  We're done.
14116			 */
14117			break;
14118		} else if (result == ISC_R_QUOTA) {
14119			/*
14120			 * Not enough quota.  This is probably the per-server
14121			 * quota, because we usually get called when a unit of
14122			 * global quota has just been freed.  Try the next
14123			 * zone, it may succeed if it uses another master.
14124			 */
14125			continue;
14126		} else {
14127			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14128				     "starting zone transfer: %s",
14129				     isc_result_totext(result));
14130			break;
14131		}
14132	}
14133}
14134
14135/*
14136 * Try to start an incoming zone transfer for 'zone', quota permitting.
14137 *
14138 * Requires:
14139 *	The zone manager is locked by the caller.
14140 *
14141 * Returns:
14142 *	ISC_R_SUCCESS	There was enough quota and we attempted to
14143 *			start a transfer.  zone_xfrdone() has been or will
14144 *			be called.
14145 *	ISC_R_QUOTA	Not enough quota.
14146 *	Others		Failure.
14147 */
14148static isc_result_t
14149zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14150	dns_peer_t *peer = NULL;
14151	isc_netaddr_t masterip;
14152	isc_uint32_t nxfrsin, nxfrsperns;
14153	dns_zone_t *x;
14154	isc_uint32_t maxtransfersin, maxtransfersperns;
14155	isc_event_t *e;
14156
14157	/*
14158	 * If we are exiting just pretend we got quota so the zone will
14159	 * be cleaned up in the zone's task context.
14160	 */
14161	LOCK_ZONE(zone);
14162	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14163		UNLOCK_ZONE(zone);
14164		goto gotquota;
14165	}
14166
14167	/*
14168	 * Find any configured information about the server we'd
14169	 * like to transfer this zone from.
14170	 */
14171	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14172	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
14173	UNLOCK_ZONE(zone);
14174
14175	/*
14176	 * Determine the total maximum number of simultaneous
14177	 * transfers allowed, and the maximum for this specific
14178	 * master.
14179	 */
14180	maxtransfersin = zmgr->transfersin;
14181	maxtransfersperns = zmgr->transfersperns;
14182	if (peer != NULL)
14183		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
14184
14185	/*
14186	 * Count the total number of transfers that are in progress,
14187	 * and the number of transfers in progress from this master.
14188	 * We linearly scan a list of all transfers; if this turns
14189	 * out to be too slow, we could hash on the master address.
14190	 */
14191	nxfrsin = nxfrsperns = 0;
14192	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
14193	     x != NULL;
14194	     x = ISC_LIST_NEXT(x, statelink))
14195	{
14196		isc_netaddr_t xip;
14197
14198		LOCK_ZONE(x);
14199		isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
14200		UNLOCK_ZONE(x);
14201
14202		nxfrsin++;
14203		if (isc_netaddr_equal(&xip, &masterip))
14204			nxfrsperns++;
14205	}
14206
14207	/* Enforce quota. */
14208	if (nxfrsin >= maxtransfersin)
14209		return (ISC_R_QUOTA);
14210
14211	if (nxfrsperns >= maxtransfersperns)
14212		return (ISC_R_QUOTA);
14213
14214 gotquota:
14215	/*
14216	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
14217	 * list and send it an event to let it start the actual transfer in the
14218	 * context of its own task.
14219	 */
14220	e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
14221			       got_transfer_quota, zone, sizeof(isc_event_t));
14222	if (e == NULL)
14223		return (ISC_R_NOMEMORY);
14224
14225	LOCK_ZONE(zone);
14226	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
14227	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
14228	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
14229	zone->statelist = &zmgr->xfrin_in_progress;
14230	isc_task_send(zone->task, &e);
14231	dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
14232	UNLOCK_ZONE(zone);
14233
14234	return (ISC_R_SUCCESS);
14235}
14236
14237void
14238dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
14239
14240	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14241	REQUIRE(iolimit > 0);
14242
14243	zmgr->iolimit = iolimit;
14244}
14245
14246isc_uint32_t
14247dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
14248
14249	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14250
14251	return (zmgr->iolimit);
14252}
14253
14254/*
14255 * Get permission to request a file handle from the OS.
14256 * An event will be sent to action when one is available.
14257 * There are two queues available (high and low), the high
14258 * queue will be serviced before the low one.
14259 *
14260 * zonemgr_putio() must be called after the event is delivered to
14261 * 'action'.
14262 */
14263
14264static isc_result_t
14265zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
14266	      isc_task_t *task, isc_taskaction_t action, void *arg,
14267	      dns_io_t **iop)
14268{
14269	dns_io_t *io;
14270	isc_boolean_t queue;
14271
14272	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14273	REQUIRE(iop != NULL && *iop == NULL);
14274
14275	io = isc_mem_get(zmgr->mctx, sizeof(*io));
14276	if (io == NULL)
14277		return (ISC_R_NOMEMORY);
14278
14279	io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
14280				       action, arg, sizeof(*io->event));
14281	if (io->event == NULL) {
14282		isc_mem_put(zmgr->mctx, io, sizeof(*io));
14283		return (ISC_R_NOMEMORY);
14284	}
14285
14286	io->zmgr = zmgr;
14287	io->high = high;
14288	io->task = NULL;
14289	isc_task_attach(task, &io->task);
14290	ISC_LINK_INIT(io, link);
14291	io->magic = IO_MAGIC;
14292
14293	LOCK(&zmgr->iolock);
14294	zmgr->ioactive++;
14295	queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
14296	if (queue) {
14297		if (io->high)
14298			ISC_LIST_APPEND(zmgr->high, io, link);
14299		else
14300			ISC_LIST_APPEND(zmgr->low, io, link);
14301	}
14302	UNLOCK(&zmgr->iolock);
14303	*iop = io;
14304
14305	if (!queue)
14306		isc_task_send(io->task, &io->event);
14307	return (ISC_R_SUCCESS);
14308}
14309
14310static void
14311zonemgr_putio(dns_io_t **iop) {
14312	dns_io_t *io;
14313	dns_io_t *next;
14314	dns_zonemgr_t *zmgr;
14315
14316	REQUIRE(iop != NULL);
14317	io = *iop;
14318	REQUIRE(DNS_IO_VALID(io));
14319
14320	*iop = NULL;
14321
14322	INSIST(!ISC_LINK_LINKED(io, link));
14323	INSIST(io->event == NULL);
14324
14325	zmgr = io->zmgr;
14326	isc_task_detach(&io->task);
14327	io->magic = 0;
14328	isc_mem_put(zmgr->mctx, io, sizeof(*io));
14329
14330	LOCK(&zmgr->iolock);
14331	INSIST(zmgr->ioactive > 0);
14332	zmgr->ioactive--;
14333	next = HEAD(zmgr->high);
14334	if (next == NULL)
14335		next = HEAD(zmgr->low);
14336	if (next != NULL) {
14337		if (next->high)
14338			ISC_LIST_UNLINK(zmgr->high, next, link);
14339		else
14340			ISC_LIST_UNLINK(zmgr->low, next, link);
14341		INSIST(next->event != NULL);
14342	}
14343	UNLOCK(&zmgr->iolock);
14344	if (next != NULL)
14345		isc_task_send(next->task, &next->event);
14346}
14347
14348static void
14349zonemgr_cancelio(dns_io_t *io) {
14350	isc_boolean_t send_event = ISC_FALSE;
14351
14352	REQUIRE(DNS_IO_VALID(io));
14353
14354	/*
14355	 * If we are queued to be run then dequeue.
14356	 */
14357	LOCK(&io->zmgr->iolock);
14358	if (ISC_LINK_LINKED(io, link)) {
14359		if (io->high)
14360			ISC_LIST_UNLINK(io->zmgr->high, io, link);
14361		else
14362			ISC_LIST_UNLINK(io->zmgr->low, io, link);
14363
14364		send_event = ISC_TRUE;
14365		INSIST(io->event != NULL);
14366	}
14367	UNLOCK(&io->zmgr->iolock);
14368	if (send_event) {
14369		io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
14370		isc_task_send(io->task, &io->event);
14371	}
14372}
14373
14374static void
14375zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
14376	char *buf;
14377	int buflen;
14378	isc_result_t result;
14379
14380	buflen = strlen(path) + strlen(templat) + 2;
14381
14382	buf = isc_mem_get(zone->mctx, buflen);
14383	if (buf == NULL)
14384		return;
14385
14386	result = isc_file_template(path, templat, buf, buflen);
14387	if (result != ISC_R_SUCCESS)
14388		goto cleanup;
14389
14390	result = isc_file_renameunique(path, buf);
14391	if (result != ISC_R_SUCCESS)
14392		goto cleanup;
14393
14394	dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
14395		     "renaming file to '%s' for failure analysis and "
14396		     "retransferring.", path, buf);
14397
14398 cleanup:
14399	isc_mem_put(zone->mctx, buf, buflen);
14400}
14401
14402#if 0
14403/* Hook for ondestroy notification from a database. */
14404
14405static void
14406dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
14407	dns_db_t *db = event->sender;
14408	UNUSED(task);
14409
14410	isc_event_free(&event);
14411
14412	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14413		      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
14414		      "database (%p) destroyed", (void*) db);
14415}
14416#endif
14417
14418void
14419dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
14420	isc_interval_t interval;
14421	isc_uint32_t s, ns;
14422	isc_uint32_t pertic;
14423	isc_result_t result;
14424
14425	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14426
14427	if (value == 0)
14428		value = 1;
14429
14430	if (value == 1) {
14431		s = 1;
14432		ns = 0;
14433		pertic = 1;
14434	} else if (value <= 10) {
14435		s = 0;
14436		ns = 1000000000 / value;
14437		pertic = 1;
14438	} else {
14439		s = 0;
14440		ns = (1000000000 / value) * 10;
14441		pertic = 10;
14442	}
14443
14444	isc_interval_set(&interval, s, ns);
14445	result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
14446	RUNTIME_CHECK(result == ISC_R_SUCCESS);
14447	isc_ratelimiter_setpertic(zmgr->rl, pertic);
14448
14449	zmgr->serialqueryrate = value;
14450}
14451
14452unsigned int
14453dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
14454	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14455
14456	return (zmgr->serialqueryrate);
14457}
14458
14459isc_boolean_t
14460dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
14461			isc_sockaddr_t *local, isc_time_t *now)
14462{
14463	unsigned int i;
14464	isc_rwlocktype_t locktype;
14465	isc_result_t result;
14466	isc_uint32_t seconds = isc_time_seconds(now);
14467
14468	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14469
14470	locktype = isc_rwlocktype_read;
14471	RWLOCK(&zmgr->urlock, locktype);
14472	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
14473		if (zmgr->unreachable[i].expire >= seconds &&
14474		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
14475		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
14476			result = isc_rwlock_tryupgrade(&zmgr->urlock);
14477			if (result == ISC_R_SUCCESS) {
14478				locktype = isc_rwlocktype_write;
14479				zmgr->unreachable[i].last = seconds;
14480			}
14481			break;
14482		}
14483	}
14484	RWUNLOCK(&zmgr->urlock, locktype);
14485	return (ISC_TF(i < UNREACH_CHACHE_SIZE));
14486}
14487
14488void
14489dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
14490			   isc_sockaddr_t *local)
14491{
14492	unsigned int i;
14493	isc_rwlocktype_t locktype;
14494	isc_result_t result;
14495
14496	char master[ISC_SOCKADDR_FORMATSIZE];
14497	char source[ISC_SOCKADDR_FORMATSIZE];
14498
14499	isc_sockaddr_format(remote, master, sizeof(master));
14500	isc_sockaddr_format(local, source, sizeof(source));
14501
14502	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14503
14504	locktype = isc_rwlocktype_read;
14505	RWLOCK(&zmgr->urlock, locktype);
14506	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
14507		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
14508		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
14509			result = isc_rwlock_tryupgrade(&zmgr->urlock);
14510			if (result == ISC_R_SUCCESS) {
14511				locktype = isc_rwlocktype_write;
14512				zmgr->unreachable[i].expire = 0;
14513				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14514					      DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
14515					      "master %s (source %s) deleted "
14516					      "from unreachable cache",
14517					      master, source);
14518			}
14519			break;
14520		}
14521	}
14522	RWUNLOCK(&zmgr->urlock, locktype);
14523}
14524
14525void
14526dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
14527			   isc_sockaddr_t *local, isc_time_t *now)
14528{
14529	isc_uint32_t seconds = isc_time_seconds(now);
14530	isc_uint32_t last = seconds;
14531	unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
14532
14533	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14534
14535	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
14536	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
14537		/* Existing entry? */
14538		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
14539		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
14540			break;
14541		/* Empty slot? */
14542		if (zmgr->unreachable[i].expire < seconds)
14543			slot = i;
14544		/* Least recently used slot? */
14545		if (zmgr->unreachable[i].last < last) {
14546			last = zmgr->unreachable[i].last;
14547			oldest = i;
14548		}
14549	}
14550	if (i < UNREACH_CHACHE_SIZE) {
14551		/*
14552		 * Found a existing entry.  Update the expire timer and
14553		 * last usage timestamps.
14554		 */
14555		zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
14556		zmgr->unreachable[i].last = seconds;
14557	} else if (slot != UNREACH_CHACHE_SIZE) {
14558		/*
14559		 * Found a empty slot. Add a new entry to the cache.
14560		 */
14561		zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
14562		zmgr->unreachable[slot].last = seconds;
14563		zmgr->unreachable[slot].remote = *remote;
14564		zmgr->unreachable[slot].local = *local;
14565	} else {
14566		/*
14567		 * Replace the least recently used entry in the cache.
14568		 */
14569		zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
14570		zmgr->unreachable[oldest].last = seconds;
14571		zmgr->unreachable[oldest].remote = *remote;
14572		zmgr->unreachable[oldest].local = *local;
14573	}
14574	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
14575}
14576
14577void
14578dns_zone_forcereload(dns_zone_t *zone) {
14579	REQUIRE(DNS_ZONE_VALID(zone));
14580
14581	if (zone->type == dns_zone_master ||
14582	    (zone->type == dns_zone_redirect && zone->masters == NULL))
14583		return;
14584
14585	LOCK_ZONE(zone);
14586	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
14587	UNLOCK_ZONE(zone);
14588	dns_zone_refresh(zone);
14589}
14590
14591isc_boolean_t
14592dns_zone_isforced(dns_zone_t *zone) {
14593	REQUIRE(DNS_ZONE_VALID(zone));
14594
14595	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
14596}
14597
14598isc_result_t
14599dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
14600	/*
14601	 * This function is obsoleted.
14602	 */
14603	UNUSED(zone);
14604	UNUSED(on);
14605	return (ISC_R_NOTIMPLEMENTED);
14606}
14607
14608isc_uint64_t *
14609dns_zone_getstatscounters(dns_zone_t *zone) {
14610	/*
14611	 * This function is obsoleted.
14612	 */
14613	UNUSED(zone);
14614	return (NULL);
14615}
14616
14617void
14618dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
14619	REQUIRE(DNS_ZONE_VALID(zone));
14620	REQUIRE(zone->stats == NULL);
14621
14622	LOCK_ZONE(zone);
14623	zone->stats = NULL;
14624	isc_stats_attach(stats, &zone->stats);
14625	UNLOCK_ZONE(zone);
14626}
14627
14628void
14629dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
14630	REQUIRE(DNS_ZONE_VALID(zone));
14631
14632	LOCK_ZONE(zone);
14633	if (zone->requeststats_on && stats == NULL)
14634		zone->requeststats_on = ISC_FALSE;
14635	else if (!zone->requeststats_on && stats != NULL) {
14636		if (zone->requeststats == NULL) {
14637			isc_stats_attach(stats, &zone->requeststats);
14638			zone->requeststats_on = ISC_TRUE;
14639		}
14640	}
14641	UNLOCK_ZONE(zone);
14642
14643	return;
14644}
14645
14646isc_stats_t *
14647dns_zone_getrequeststats(dns_zone_t *zone) {
14648	/*
14649	 * We don't lock zone for efficiency reason.  This is not catastrophic
14650	 * because requeststats must always be valid when requeststats_on is
14651	 * true.
14652	 * Some counters may be incremented while requeststats_on is becoming
14653	 * false, or some cannot be incremented just after the statistics are
14654	 * installed, but it shouldn't matter much in practice.
14655	 */
14656	if (zone->requeststats_on)
14657		return (zone->requeststats);
14658	else
14659		return (NULL);
14660}
14661
14662void
14663dns_zone_dialup(dns_zone_t *zone) {
14664
14665	REQUIRE(DNS_ZONE_VALID(zone));
14666
14667	zone_debuglog(zone, "dns_zone_dialup", 3,
14668		      "notify = %d, refresh = %d",
14669		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
14670		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
14671
14672	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
14673		dns_zone_notify(zone);
14674	if (zone->type != dns_zone_master && zone->masters != NULL &&
14675	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
14676		dns_zone_refresh(zone);
14677}
14678
14679void
14680dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
14681	REQUIRE(DNS_ZONE_VALID(zone));
14682
14683	LOCK_ZONE(zone);
14684	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
14685			 DNS_ZONEFLG_DIALREFRESH |
14686			 DNS_ZONEFLG_NOREFRESH);
14687	switch (dialup) {
14688	case dns_dialuptype_no:
14689		break;
14690	case dns_dialuptype_yes:
14691		DNS_ZONE_SETFLAG(zone,	(DNS_ZONEFLG_DIALNOTIFY |
14692				 DNS_ZONEFLG_DIALREFRESH |
14693				 DNS_ZONEFLG_NOREFRESH));
14694		break;
14695	case dns_dialuptype_notify:
14696		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
14697		break;
14698	case dns_dialuptype_notifypassive:
14699		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
14700		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
14701		break;
14702	case dns_dialuptype_refresh:
14703		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
14704		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
14705		break;
14706	case dns_dialuptype_passive:
14707		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
14708		break;
14709	default:
14710		INSIST(0);
14711	}
14712	UNLOCK_ZONE(zone);
14713}
14714
14715isc_result_t
14716dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
14717	isc_result_t result = ISC_R_SUCCESS;
14718
14719	REQUIRE(DNS_ZONE_VALID(zone));
14720
14721	LOCK_ZONE(zone);
14722	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
14723	UNLOCK_ZONE(zone);
14724
14725	return (result);
14726}
14727
14728const char *
14729dns_zone_getkeydirectory(dns_zone_t *zone) {
14730	REQUIRE(DNS_ZONE_VALID(zone));
14731
14732	return (zone->keydirectory);
14733}
14734
14735unsigned int
14736dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
14737	dns_zone_t *zone;
14738	unsigned int count = 0;
14739
14740	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14741
14742	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14743	switch (state) {
14744	case DNS_ZONESTATE_XFERRUNNING:
14745		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
14746		     zone != NULL;
14747		     zone = ISC_LIST_NEXT(zone, statelink))
14748			count++;
14749		break;
14750	case DNS_ZONESTATE_XFERDEFERRED:
14751		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
14752		     zone != NULL;
14753		     zone = ISC_LIST_NEXT(zone, statelink))
14754			count++;
14755		break;
14756	case DNS_ZONESTATE_SOAQUERY:
14757		for (zone = ISC_LIST_HEAD(zmgr->zones);
14758		     zone != NULL;
14759		     zone = ISC_LIST_NEXT(zone, link))
14760			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
14761				count++;
14762		break;
14763	case DNS_ZONESTATE_ANY:
14764		for (zone = ISC_LIST_HEAD(zmgr->zones);
14765		     zone != NULL;
14766		     zone = ISC_LIST_NEXT(zone, link)) {
14767			dns_view_t *view = zone->view;
14768			if (view != NULL && strcmp(view->name, "_bind") == 0)
14769				continue;
14770			count++;
14771		}
14772		break;
14773	default:
14774		INSIST(0);
14775	}
14776
14777	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14778
14779	return (count);
14780}
14781
14782isc_result_t
14783dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
14784	isc_boolean_t ok = ISC_TRUE;
14785	isc_boolean_t fail = ISC_FALSE;
14786	char namebuf[DNS_NAME_FORMATSIZE];
14787	char namebuf2[DNS_NAME_FORMATSIZE];
14788	char typebuf[DNS_RDATATYPE_FORMATSIZE];
14789	int level = ISC_LOG_WARNING;
14790	dns_name_t bad;
14791
14792	REQUIRE(DNS_ZONE_VALID(zone));
14793
14794	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
14795		return (ISC_R_SUCCESS);
14796
14797	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
14798		level = ISC_LOG_ERROR;
14799		fail = ISC_TRUE;
14800	}
14801
14802	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
14803	if (!ok) {
14804		dns_name_format(name, namebuf, sizeof(namebuf));
14805		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
14806		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
14807			     dns_result_totext(DNS_R_BADOWNERNAME));
14808		if (fail)
14809			return (DNS_R_BADOWNERNAME);
14810	}
14811
14812	dns_name_init(&bad, NULL);
14813	ok = dns_rdata_checknames(rdata, name, &bad);
14814	if (!ok) {
14815		dns_name_format(name, namebuf, sizeof(namebuf));
14816		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
14817		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
14818		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
14819			     namebuf2, dns_result_totext(DNS_R_BADNAME));
14820		if (fail)
14821			return (DNS_R_BADNAME);
14822	}
14823
14824	return (ISC_R_SUCCESS);
14825}
14826
14827void
14828dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
14829	REQUIRE(DNS_ZONE_VALID(zone));
14830	zone->checkmx = checkmx;
14831}
14832
14833void
14834dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
14835	REQUIRE(DNS_ZONE_VALID(zone));
14836	zone->checksrv = checksrv;
14837}
14838
14839void
14840dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
14841	REQUIRE(DNS_ZONE_VALID(zone));
14842	zone->checkns = checkns;
14843}
14844
14845void
14846dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
14847	REQUIRE(DNS_ZONE_VALID(zone));
14848
14849	LOCK_ZONE(zone);
14850	zone->isself = isself;
14851	zone->isselfarg = arg;
14852	UNLOCK_ZONE(zone);
14853}
14854
14855void
14856dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
14857	REQUIRE(DNS_ZONE_VALID(zone));
14858
14859	LOCK_ZONE(zone);
14860	zone->notifydelay = delay;
14861	UNLOCK_ZONE(zone);
14862}
14863
14864isc_uint32_t
14865dns_zone_getnotifydelay(dns_zone_t *zone) {
14866	REQUIRE(DNS_ZONE_VALID(zone));
14867
14868	return (zone->notifydelay);
14869}
14870
14871isc_result_t
14872dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
14873		     isc_uint16_t keyid, isc_boolean_t delete)
14874{
14875	isc_result_t result;
14876	REQUIRE(DNS_ZONE_VALID(zone));
14877
14878	dns_zone_log(zone, ISC_LOG_NOTICE,
14879		     "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
14880		     algorithm, keyid);
14881	LOCK_ZONE(zone);
14882	result = zone_signwithkey(zone, algorithm, keyid, delete);
14883	UNLOCK_ZONE(zone);
14884
14885	return (result);
14886}
14887
14888static const char *hex = "0123456789ABCDEF";
14889
14890isc_result_t
14891dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
14892	isc_result_t result;
14893	char salt[255*2+1];
14894	unsigned int i, j;
14895
14896	REQUIRE(DNS_ZONE_VALID(zone));
14897
14898	if (nsec3param->salt_length != 0) {
14899		INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
14900		for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
14901			salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
14902			salt[j++] = hex[nsec3param->salt[i] & 0xf];
14903		}
14904		salt[j] = '\0';
14905	} else
14906		strcpy(salt, "-");
14907	dns_zone_log(zone, ISC_LOG_NOTICE,
14908		     "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
14909		     nsec3param->hash, nsec3param->iterations,
14910		     salt);
14911	LOCK_ZONE(zone);
14912	result = zone_addnsec3chain(zone, nsec3param);
14913	UNLOCK_ZONE(zone);
14914
14915	return (result);
14916}
14917
14918void
14919dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
14920	REQUIRE(DNS_ZONE_VALID(zone));
14921
14922	if (nodes == 0)
14923		nodes = 1;
14924	zone->nodes = nodes;
14925}
14926
14927void
14928dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
14929	REQUIRE(DNS_ZONE_VALID(zone));
14930
14931	/*
14932	 * We treat signatures as a signed value so explicitly
14933	 * limit its range here.
14934	 */
14935	if (signatures > ISC_INT32_MAX)
14936		signatures = ISC_INT32_MAX;
14937	else if (signatures == 0)
14938		signatures = 1;
14939	zone->signatures = signatures;
14940}
14941
14942void
14943dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
14944	REQUIRE(DNS_ZONE_VALID(zone));
14945	zone->privatetype = type;
14946}
14947
14948dns_rdatatype_t
14949dns_zone_getprivatetype(dns_zone_t *zone) {
14950	REQUIRE(DNS_ZONE_VALID(zone));
14951	return (zone->privatetype);
14952}
14953
14954static isc_result_t
14955zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
14956		 isc_boolean_t delete)
14957{
14958	dns_signing_t *signing;
14959	dns_signing_t *current;
14960	isc_result_t result = ISC_R_SUCCESS;
14961	isc_time_t now;
14962
14963	signing = isc_mem_get(zone->mctx, sizeof *signing);
14964	if (signing == NULL)
14965		return (ISC_R_NOMEMORY);
14966
14967	signing->magic = 0;
14968	signing->db  = NULL;
14969	signing->dbiterator = NULL;
14970	signing->algorithm = algorithm;
14971	signing->keyid = keyid;
14972	signing->delete = delete;
14973	signing->done = ISC_FALSE;
14974
14975	TIME_NOW(&now);
14976
14977	for (current = ISC_LIST_HEAD(zone->signing);
14978	     current != NULL;
14979	     current = ISC_LIST_NEXT(current, link)) {
14980		if (current->db == zone->db &&
14981		    current->algorithm == signing->algorithm &&
14982		    current->keyid == signing->keyid) {
14983			if (current->delete != signing->delete)
14984				current->done = ISC_TRUE;
14985			else
14986				goto cleanup;
14987		}
14988	}
14989
14990	if (zone->db != NULL) {
14991		dns_db_attach(zone->db, &signing->db);
14992		result = dns_db_createiterator(signing->db, 0,
14993					       &signing->dbiterator);
14994
14995		if (result == ISC_R_SUCCESS)
14996			result = dns_dbiterator_first(signing->dbiterator);
14997		if (result == ISC_R_SUCCESS) {
14998			dns_dbiterator_pause(signing->dbiterator);
14999			ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
15000			signing = NULL;
15001			if (isc_time_isepoch(&zone->signingtime)) {
15002				zone->signingtime = now;
15003				if (zone->task != NULL)
15004					zone_settimer(zone, &now);
15005			}
15006		}
15007	} else
15008		result = ISC_R_NOTFOUND;
15009
15010 cleanup:
15011	if (signing != NULL) {
15012		if (signing->db != NULL)
15013			dns_db_detach(&signing->db);
15014		if (signing->dbiterator != NULL)
15015			dns_dbiterator_destroy(&signing->dbiterator);
15016		isc_mem_put(zone->mctx, signing, sizeof *signing);
15017	}
15018	return (result);
15019}
15020
15021static void
15022logmsg(const char *format, ...) {
15023	va_list args;
15024	va_start(args, format);
15025	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
15026		       ISC_LOG_DEBUG(1), format, args);
15027	va_end(args);
15028}
15029
15030static void
15031clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
15032	dns_dnsseckey_t *key;
15033	while (!ISC_LIST_EMPTY(*list)) {
15034		key = ISC_LIST_HEAD(*list);
15035		ISC_LIST_UNLINK(*list, key, link);
15036		dns_dnsseckey_destroy(mctx, &key);
15037	}
15038}
15039
15040/* Called once; *timep should be set to the current time. */
15041static isc_result_t
15042next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
15043	isc_result_t result;
15044	isc_stdtime_t now, then = 0, event;
15045	int i;
15046
15047	now = *timep;
15048
15049	for (i = 0; i <= DST_MAX_TIMES; i++) {
15050		result = dst_key_gettime(key, i, &event);
15051		if (result == ISC_R_SUCCESS && event > now &&
15052		    (then == 0 || event < then))
15053			then = event;
15054	}
15055
15056	if (then != 0) {
15057		*timep = then;
15058		return (ISC_R_SUCCESS);
15059	}
15060
15061	return (ISC_R_NOTFOUND);
15062}
15063
15064static isc_result_t
15065rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
15066	  const dns_rdata_t *rdata, isc_boolean_t *flag)
15067{
15068	dns_rdataset_t rdataset;
15069	dns_dbnode_t *node = NULL;
15070	isc_result_t result;
15071
15072	dns_rdataset_init(&rdataset);
15073	if (rdata->type == dns_rdatatype_nsec3)
15074		CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
15075	else
15076		CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
15077	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
15078				     (isc_stdtime_t) 0, &rdataset, NULL);
15079	if (result == ISC_R_NOTFOUND) {
15080		*flag = ISC_FALSE;
15081		result = ISC_R_SUCCESS;
15082		goto failure;
15083	}
15084
15085	for (result = dns_rdataset_first(&rdataset);
15086	     result == ISC_R_SUCCESS;
15087	     result = dns_rdataset_next(&rdataset)) {
15088		dns_rdata_t myrdata = DNS_RDATA_INIT;
15089		dns_rdataset_current(&rdataset, &myrdata);
15090		if (!dns_rdata_compare(&myrdata, rdata))
15091			break;
15092	}
15093	dns_rdataset_disassociate(&rdataset);
15094	if (result == ISC_R_SUCCESS) {
15095		*flag = ISC_TRUE;
15096	} else if (result == ISC_R_NOMORE) {
15097		*flag = ISC_FALSE;
15098		result = ISC_R_SUCCESS;
15099	}
15100
15101 failure:
15102	if (node != NULL)
15103		dns_db_detachnode(db, &node);
15104	return (result);
15105}
15106
15107/*
15108 * Add records to signal the state of signing or of key removal.
15109 */
15110static isc_result_t
15111add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
15112		    dns_dbversion_t *ver, dns_diff_t *diff,
15113		    isc_boolean_t sign_all)
15114{
15115	dns_difftuple_t *tuple, *newtuple = NULL;
15116	dns_rdata_dnskey_t dnskey;
15117	dns_rdata_t rdata = DNS_RDATA_INIT;
15118	isc_boolean_t flag;
15119	isc_region_t r;
15120	isc_result_t result = ISC_R_SUCCESS;
15121	isc_uint16_t keyid;
15122	unsigned char buf[5];
15123	dns_name_t *name = dns_db_origin(db);
15124
15125	for (tuple = ISC_LIST_HEAD(diff->tuples);
15126	     tuple != NULL;
15127	     tuple = ISC_LIST_NEXT(tuple, link)) {
15128		if (tuple->rdata.type != dns_rdatatype_dnskey)
15129			continue;
15130
15131		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
15132		RUNTIME_CHECK(result == ISC_R_SUCCESS);
15133		if ((dnskey.flags &
15134		     (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
15135			 != DNS_KEYOWNER_ZONE)
15136			continue;
15137
15138		dns_rdata_toregion(&tuple->rdata, &r);
15139
15140		keyid = dst_region_computeid(&r, dnskey.algorithm);
15141
15142		buf[0] = dnskey.algorithm;
15143		buf[1] = (keyid & 0xff00) >> 8;
15144		buf[2] = (keyid & 0xff);
15145		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
15146		buf[4] = 0;
15147		rdata.data = buf;
15148		rdata.length = sizeof(buf);
15149		rdata.type = privatetype;
15150		rdata.rdclass = tuple->rdata.rdclass;
15151
15152		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
15153			CHECK(rr_exists(db, ver, name, &rdata, &flag));
15154			if (flag)
15155				continue;
15156			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
15157						   name, 0, &rdata, &newtuple));
15158			CHECK(do_one_tuple(&newtuple, db, ver, diff));
15159			INSIST(newtuple == NULL);
15160		}
15161
15162		/*
15163		 * Remove any record which says this operation has already
15164		 * completed.
15165		 */
15166		buf[4] = 1;
15167		CHECK(rr_exists(db, ver, name, &rdata, &flag));
15168		if (flag) {
15169			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
15170						   name, 0, &rdata, &newtuple));
15171			CHECK(do_one_tuple(&newtuple, db, ver, diff));
15172			INSIST(newtuple == NULL);
15173		}
15174	}
15175 failure:
15176	return (result);
15177}
15178
15179static isc_result_t
15180sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
15181	  dns_diff_t *diff, dns_diff_t *sig_diff)
15182{
15183	isc_result_t result;
15184	isc_stdtime_t now, inception, soaexpire;
15185	isc_boolean_t check_ksk, keyset_kskonly;
15186	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
15187	unsigned int nkeys = 0, i;
15188	dns_difftuple_t *tuple;
15189
15190	result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
15191				zone_keys, &nkeys);
15192	if (result != ISC_R_SUCCESS) {
15193		dns_zone_log(zone, ISC_LOG_ERROR,
15194			     "sign_apex:find_zone_keys -> %s",
15195			     dns_result_totext(result));
15196		return (result);
15197	}
15198
15199	isc_stdtime_get(&now);
15200	inception = now - 3600;	/* Allow for clock skew. */
15201	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
15202
15203	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
15204	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
15205
15206	/*
15207	 * See if update_sigs will update DNSKEY signature and if not
15208	 * cause them to sign so that so that newly activated keys
15209	 * are used.
15210	 */
15211	for (tuple = ISC_LIST_HEAD(diff->tuples);
15212	     tuple != NULL;
15213	     tuple = ISC_LIST_NEXT(tuple, link)) {
15214		if (tuple->rdata.type == dns_rdatatype_dnskey &&
15215		    dns_name_equal(&tuple->name, &zone->origin))
15216			break;
15217	}
15218
15219	if (tuple == NULL) {
15220		result = del_sigs(zone, db, ver, &zone->origin,
15221				  dns_rdatatype_dnskey, sig_diff,
15222				  zone_keys, nkeys, now, ISC_FALSE);
15223		if (result != ISC_R_SUCCESS) {
15224			dns_zone_log(zone, ISC_LOG_ERROR,
15225				     "sign_apex:del_sigs -> %s",
15226				     dns_result_totext(result));
15227			goto failure;
15228		}
15229		result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
15230				  sig_diff, zone_keys, nkeys, zone->mctx,
15231				  inception, soaexpire, check_ksk,
15232				  keyset_kskonly);
15233		if (result != ISC_R_SUCCESS) {
15234			dns_zone_log(zone, ISC_LOG_ERROR,
15235				     "sign_apex:add_sigs -> %s",
15236				     dns_result_totext(result));
15237			goto failure;
15238		}
15239	}
15240
15241	result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
15242			     inception, soaexpire, now, check_ksk,
15243			     keyset_kskonly, sig_diff);
15244
15245	if (result != ISC_R_SUCCESS) {
15246		dns_zone_log(zone, ISC_LOG_ERROR,
15247			     "sign_apex:update_sigs -> %s",
15248			     dns_result_totext(result));
15249		goto failure;
15250	}
15251
15252 failure:
15253	for (i = 0; i < nkeys; i++)
15254		dst_key_free(&zone_keys[i]);
15255	return (result);
15256}
15257
15258/*
15259 * Prevent the zone entering a inconsistent state where
15260 * NSEC only DNSKEYs are present with NSEC3 chains.
15261 * See update.c:check_dnssec()
15262 */
15263static isc_boolean_t
15264dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
15265	    dns_diff_t *diff)
15266{
15267	isc_result_t result;
15268	dns_difftuple_t *tuple;
15269	isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
15270	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
15271
15272	/* Scan the tuples for an NSEC-only DNSKEY */
15273	for (tuple = ISC_LIST_HEAD(diff->tuples);
15274	     tuple != NULL;
15275	     tuple = ISC_LIST_NEXT(tuple, link)) {
15276		isc_uint8_t alg;
15277		if (tuple->rdata.type != dns_rdatatype_dnskey ||
15278		    tuple->op != DNS_DIFFOP_ADD)
15279			continue;
15280
15281		alg = tuple->rdata.data[3];
15282		if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
15283		    alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
15284			nseconly = ISC_TRUE;
15285			break;
15286		}
15287	}
15288
15289	/* Check existing DB for NSEC-only DNSKEY */
15290	if (!nseconly) {
15291		result = dns_nsec_nseconly(db, ver, &nseconly);
15292		if (result == ISC_R_NOTFOUND)
15293			result = ISC_R_SUCCESS;
15294		CHECK(result);
15295	}
15296
15297	/* Check existing DB for NSEC3 */
15298	if (!nsec3)
15299		CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
15300					privatetype, &nsec3));
15301
15302	/* Refuse to allow NSEC3 with NSEC-only keys */
15303	if (nseconly && nsec3) {
15304		dns_zone_log(zone, ISC_LOG_ERROR,
15305			   "NSEC only DNSKEYs and NSEC3 chains not allowed");
15306		goto failure;
15307	}
15308
15309	return (ISC_TRUE);
15310
15311 failure:
15312	return (ISC_FALSE);
15313}
15314
15315static isc_result_t
15316clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
15317		 dns_diff_t *diff)
15318{
15319	isc_result_t result;
15320	dns_dbnode_t *node = NULL;
15321	dns_rdataset_t rdataset;
15322
15323	dns_rdataset_init(&rdataset);
15324	CHECK(dns_db_getoriginnode(db, &node));
15325
15326	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
15327				     dns_rdatatype_none, 0, &rdataset, NULL);
15328	if (dns_rdataset_isassociated(&rdataset))
15329		dns_rdataset_disassociate(&rdataset);
15330	if (result != ISC_R_NOTFOUND)
15331		goto failure;
15332
15333	result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
15334
15335 failure:
15336	if (node != NULL)
15337		dns_db_detachnode(db, &node);
15338	return (result);
15339}
15340
15341/*
15342 * Given an RRSIG rdataset and an algorithm, determine whether there
15343 * are any signatures using that algorithm.
15344 */
15345static isc_boolean_t
15346signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
15347	dns_rdata_t rdata = DNS_RDATA_INIT;
15348	dns_rdata_rrsig_t rrsig;
15349	isc_result_t result;
15350
15351	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
15352	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
15353		return (ISC_FALSE);
15354	}
15355
15356	for (result = dns_rdataset_first(rdataset);
15357	     result == ISC_R_SUCCESS;
15358	     result = dns_rdataset_next(rdataset))
15359	{
15360		dns_rdataset_current(rdataset, &rdata);
15361		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
15362		RUNTIME_CHECK(result == ISC_R_SUCCESS);
15363		dns_rdata_reset(&rdata);
15364		if (rrsig.algorithm == alg)
15365			return (ISC_TRUE);
15366	}
15367
15368	return (ISC_FALSE);
15369}
15370
15371static isc_result_t
15372add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
15373	   dns_diff_t *diff)
15374{
15375	dns_name_t *origin;
15376	isc_boolean_t build_nsec3;
15377	isc_result_t result;
15378
15379	origin = dns_db_origin(db);
15380	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
15381				 &build_nsec3));
15382	if (build_nsec3)
15383		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
15384					   ISC_FALSE, zone->privatetype, diff));
15385	CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
15386
15387 failure:
15388	return (result);
15389}
15390
15391static void
15392zone_rekey(dns_zone_t *zone) {
15393	isc_result_t result;
15394	dns_db_t *db = NULL;
15395	dns_dbnode_t *node = NULL;
15396	dns_dbversion_t *ver = NULL;
15397	dns_rdataset_t soaset, soasigs, keyset, keysigs;
15398	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
15399	dns_dnsseckey_t *key;
15400	dns_diff_t diff, sig_diff;
15401	isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
15402	isc_boolean_t newalg = ISC_FALSE;
15403	isc_boolean_t fullsign;
15404	dns_ttl_t ttl = 3600;
15405	const char *dir;
15406	isc_mem_t *mctx;
15407	isc_stdtime_t now;
15408	isc_time_t timenow;
15409	isc_interval_t ival;
15410	char timebuf[80];
15411
15412	REQUIRE(DNS_ZONE_VALID(zone));
15413
15414	ISC_LIST_INIT(dnskeys);
15415	ISC_LIST_INIT(keys);
15416	ISC_LIST_INIT(rmkeys);
15417	dns_rdataset_init(&soaset);
15418	dns_rdataset_init(&soasigs);
15419	dns_rdataset_init(&keyset);
15420	dns_rdataset_init(&keysigs);
15421	dir = dns_zone_getkeydirectory(zone);
15422	mctx = zone->mctx;
15423	dns_diff_init(mctx, &diff);
15424	dns_diff_init(mctx, &sig_diff);
15425	sig_diff.resign = zone->sigresigninginterval;
15426
15427	CHECK(dns_zone_getdb(zone, &db));
15428	CHECK(dns_db_newversion(db, &ver));
15429	CHECK(dns_db_getoriginnode(db, &node));
15430
15431	TIME_NOW(&timenow);
15432	now = isc_time_seconds(&timenow);
15433
15434	dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
15435
15436	/* Get the SOA record's TTL */
15437	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
15438				  dns_rdatatype_none, 0, &soaset, &soasigs));
15439	ttl = soaset.ttl;
15440	dns_rdataset_disassociate(&soaset);
15441
15442	/* Get the DNSKEY rdataset */
15443	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
15444				     dns_rdatatype_none, 0, &keyset, &keysigs);
15445	if (result == ISC_R_SUCCESS) {
15446		ttl = keyset.ttl;
15447		CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
15448						     mctx, &keyset,
15449						     &keysigs, &soasigs,
15450						     ISC_FALSE, ISC_FALSE,
15451						     &dnskeys));
15452	} else if (result != ISC_R_NOTFOUND)
15453		goto failure;
15454
15455	/*
15456	 * True when called from "rndc sign".  Indicates the zone should be
15457	 * fully signed now.
15458	 */
15459	fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
15460
15461	result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
15462	if (result == ISC_R_SUCCESS) {
15463		isc_boolean_t check_ksk;
15464		check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
15465
15466		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
15467					       &zone->origin, ttl, &diff,
15468					       ISC_TF(!check_ksk),
15469					       mctx, logmsg);
15470
15471		/* Keys couldn't be updated for some reason;
15472		 * try again later. */
15473		if (result != ISC_R_SUCCESS) {
15474			dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
15475				     "couldn't update zone keys: %s",
15476				     isc_result_totext(result));
15477			goto failure;
15478		}
15479
15480		/*
15481		 * See if any pre-existing keys have newly become active;
15482		 * also, see if any new key is for a new algorithm, as in that
15483		 * event, we need to sign the zone fully.  (If there's a new
15484		 * key, but it's for an already-existing algorithm, then
15485		 * the zone signing can be handled incrementally.)
15486		 */
15487		for (key = ISC_LIST_HEAD(dnskeys);
15488		     key != NULL;
15489		     key = ISC_LIST_NEXT(key, link)) {
15490			if (!key->first_sign)
15491				continue;
15492
15493			newactive = ISC_TRUE;
15494
15495			if (!dns_rdataset_isassociated(&keysigs)) {
15496				newalg = ISC_TRUE;
15497				break;
15498			}
15499
15500			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
15501				/*
15502				 * This isn't a new algorithm; clear
15503				 * first_sign so we won't sign the
15504				 * whole zone with this key later
15505				 */
15506				key->first_sign = ISC_FALSE;
15507			} else {
15508				newalg = ISC_TRUE;
15509				break;
15510			}
15511		}
15512
15513		if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
15514		    dnskey_sane(zone, db, ver, &diff)) {
15515			CHECK(dns_diff_apply(&diff, db, ver));
15516			CHECK(clean_nsec3param(zone, db, ver, &diff));
15517			CHECK(add_signing_records(db, zone->privatetype,
15518						  ver, &diff,
15519						  ISC_TF(newalg || fullsign)));
15520			CHECK(update_soa_serial(db, ver, &diff, mctx,
15521						zone->updatemethod));
15522			CHECK(add_chains(zone, db, ver, &diff));
15523			CHECK(sign_apex(zone, db, ver, &diff, &sig_diff));
15524			CHECK(zone_journal(zone, &sig_diff, NULL,
15525					   "zone_rekey"));
15526			commit = ISC_TRUE;
15527		}
15528	}
15529
15530	dns_db_closeversion(db, &ver, commit);
15531
15532	if (commit) {
15533		dns_difftuple_t *tuple;
15534
15535		LOCK_ZONE(zone);
15536		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
15537
15538		zone_needdump(zone, DNS_DUMP_DELAY);
15539
15540		zone_settimer(zone, &timenow);
15541
15542		/* Remove any signatures from removed keys.  */
15543		if (!ISC_LIST_EMPTY(rmkeys)) {
15544			for (key = ISC_LIST_HEAD(rmkeys);
15545			     key != NULL;
15546			     key = ISC_LIST_NEXT(key, link)) {
15547				result = zone_signwithkey(zone,
15548							  dst_key_alg(key->key),
15549							  dst_key_id(key->key),
15550							  ISC_TRUE);
15551				if (result != ISC_R_SUCCESS) {
15552					dns_zone_log(zone, ISC_LOG_ERROR,
15553					     "zone_signwithkey failed: %s",
15554					     dns_result_totext(result));
15555				}
15556			}
15557		}
15558
15559		if (fullsign) {
15560			/*
15561			 * "rndc sign" was called, so we now sign the zone
15562			 * with all active keys, whether they're new or not.
15563			 */
15564			for (key = ISC_LIST_HEAD(dnskeys);
15565			     key != NULL;
15566			     key = ISC_LIST_NEXT(key, link)) {
15567				if (!key->force_sign && !key->hint_sign)
15568					continue;
15569
15570				result = zone_signwithkey(zone,
15571							  dst_key_alg(key->key),
15572							  dst_key_id(key->key),
15573							  ISC_FALSE);
15574				if (result != ISC_R_SUCCESS) {
15575					dns_zone_log(zone, ISC_LOG_ERROR,
15576					     "zone_signwithkey failed: %s",
15577					     dns_result_totext(result));
15578				}
15579			}
15580		} else if (newalg) {
15581			/*
15582			 * We haven't been told to sign fully, but a new
15583			 * algorithm was added to the DNSKEY.  We sign
15584			 * the full zone, but only with newly active
15585			 * keys.
15586			 */
15587			for (key = ISC_LIST_HEAD(dnskeys);
15588			     key != NULL;
15589			     key = ISC_LIST_NEXT(key, link)) {
15590				if (!key->first_sign)
15591					continue;
15592
15593				result = zone_signwithkey(zone,
15594							  dst_key_alg(key->key),
15595							  dst_key_id(key->key),
15596							  ISC_FALSE);
15597				if (result != ISC_R_SUCCESS) {
15598					dns_zone_log(zone, ISC_LOG_ERROR,
15599					     "zone_signwithkey failed: %s",
15600					     dns_result_totext(result));
15601				}
15602			}
15603		}
15604
15605		/*
15606		 * Clear fullsign flag, if it was set, so we don't do
15607		 * another full signing next time
15608		 */
15609		zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
15610
15611		/*
15612		 * Cause the zone to add/delete NSEC3 chains for the
15613		 * deferred NSEC3PARAM changes.
15614		 */
15615		for (tuple = ISC_LIST_HEAD(sig_diff.tuples);
15616		     tuple != NULL;
15617		     tuple = ISC_LIST_NEXT(tuple, link)) {
15618			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
15619			dns_rdata_t rdata = DNS_RDATA_INIT;
15620			dns_rdata_nsec3param_t nsec3param;
15621
15622			if (tuple->rdata.type != zone->privatetype ||
15623			    tuple->op != DNS_DIFFOP_ADD)
15624				continue;
15625
15626			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
15627							buf, sizeof(buf)))
15628				continue;
15629			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
15630			RUNTIME_CHECK(result == ISC_R_SUCCESS);
15631			if (nsec3param.flags == 0)
15632				continue;
15633
15634			result = zone_addnsec3chain(zone, &nsec3param);
15635			if (result != ISC_R_SUCCESS) {
15636				dns_zone_log(zone, ISC_LOG_ERROR,
15637					     "zone_addnsec3chain failed: %s",
15638					     dns_result_totext(result));
15639			}
15640		}
15641
15642		/*
15643		 * Activate any NSEC3 chain updates that may have
15644		 * been scheduled before this rekey.
15645		 */
15646		if (fullsign || newalg)
15647			resume_addnsec3chain(zone);
15648
15649		/*
15650		 * Schedule the next resigning event
15651		 */
15652		set_resigntime(zone);
15653		UNLOCK_ZONE(zone);
15654	}
15655
15656	isc_time_settoepoch(&zone->refreshkeytime);
15657
15658	/*
15659	 * If we're doing key maintenance, set the key refresh timer to
15660	 * the next scheduled key event or to 'dnssec-loadkeys-interval'
15661	 * seconds in the future, whichever is sooner.
15662	 */
15663	if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
15664		isc_time_t timethen;
15665		isc_stdtime_t then;
15666
15667		LOCK_ZONE(zone);
15668		DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
15669				  &timethen);
15670		zone->refreshkeytime = timethen;
15671		UNLOCK_ZONE(zone);
15672
15673		for (key = ISC_LIST_HEAD(dnskeys);
15674		     key != NULL;
15675		     key = ISC_LIST_NEXT(key, link)) {
15676			then = now;
15677			result = next_keyevent(key->key, &then);
15678			if (result != ISC_R_SUCCESS)
15679				continue;
15680
15681			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
15682			LOCK_ZONE(zone);
15683			if (isc_time_compare(&timethen,
15684					     &zone->refreshkeytime) < 0) {
15685				zone->refreshkeytime = timethen;
15686			}
15687			UNLOCK_ZONE(zone);
15688		}
15689
15690		zone_settimer(zone, &timenow);
15691
15692		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
15693		dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
15694	}
15695
15696 done:
15697	dns_diff_clear(&diff);
15698	dns_diff_clear(&sig_diff);
15699
15700	clear_keylist(&dnskeys, mctx);
15701	clear_keylist(&keys, mctx);
15702	clear_keylist(&rmkeys, mctx);
15703
15704	if (ver != NULL)
15705		dns_db_closeversion(db, &ver, ISC_FALSE);
15706	if (dns_rdataset_isassociated(&keyset))
15707		dns_rdataset_disassociate(&keyset);
15708	if (dns_rdataset_isassociated(&keysigs))
15709		dns_rdataset_disassociate(&keysigs);
15710	if (dns_rdataset_isassociated(&soasigs))
15711		dns_rdataset_disassociate(&soasigs);
15712	if (node != NULL)
15713		dns_db_detachnode(db, &node);
15714	if (db != NULL)
15715		dns_db_detach(&db);
15716	return;
15717
15718 failure:
15719	/*
15720	 * Something went wrong; try again in ten minutes or
15721	 * after a key refresh interval, whichever is shorter.
15722	 */
15723	isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
15724	isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
15725	goto done;
15726}
15727
15728void
15729dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
15730	isc_time_t now;
15731
15732	if (zone->type == dns_zone_master && zone->task != NULL) {
15733		LOCK_ZONE(zone);
15734
15735		if (fullsign)
15736			zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
15737
15738		TIME_NOW(&now);
15739		zone->refreshkeytime = now;
15740		zone_settimer(zone, &now);
15741
15742		UNLOCK_ZONE(zone);
15743	}
15744}
15745
15746isc_result_t
15747dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
15748		 unsigned int *errors)
15749{
15750	isc_result_t result;
15751	dns_dbnode_t *node = NULL;
15752
15753	REQUIRE(DNS_ZONE_VALID(zone));
15754	REQUIRE(errors != NULL);
15755
15756	result = dns_db_getoriginnode(db, &node);
15757	if (result != ISC_R_SUCCESS)
15758		return (result);
15759	result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
15760				  ISC_FALSE);
15761	dns_db_detachnode(db, &node);
15762	return (result);
15763}
15764
15765void
15766dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
15767	REQUIRE(DNS_ZONE_VALID(zone));
15768	LOCK_ZONE(zone);
15769	zone->added = added;
15770	UNLOCK_ZONE(zone);
15771}
15772
15773isc_boolean_t
15774dns_zone_getadded(dns_zone_t *zone) {
15775	REQUIRE(DNS_ZONE_VALID(zone));
15776	return (zone->added);
15777}
15778
15779isc_result_t
15780dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
15781{
15782	isc_time_t loadtime;
15783	isc_result_t result;
15784	TIME_NOW(&loadtime);
15785
15786	/*
15787	 * Lock hierachy zmgr, raw, zone.
15788	 */
15789	if (inline_secure(zone))
15790		LOCK_ZONE(zone->raw);
15791	LOCK_ZONE(zone);
15792	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
15793	UNLOCK_ZONE(zone);
15794	if (inline_secure(zone))
15795		UNLOCK_ZONE(zone->raw);
15796	return result;
15797}
15798
15799isc_result_t
15800dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
15801	REQUIRE(DNS_ZONE_VALID(zone));
15802	if (interval == 0)
15803		return (ISC_R_RANGE);
15804	/* Maximum value: 24 hours (3600 minutes) */
15805	if (interval > (24 * 60))
15806		interval = (24 * 60);
15807	/* Multiply by 60 for seconds */
15808	zone->refreshkeyinterval = interval * 60;
15809	return (ISC_R_SUCCESS);
15810}
15811
15812void
15813dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t b) {
15814	REQUIRE(DNS_ZONE_VALID(zone));
15815	zone->requestixfr = b;
15816}
15817
15818isc_boolean_t
15819dns_zone_getrequestixfr(dns_zone_t *zone) {
15820	REQUIRE(DNS_ZONE_VALID(zone));
15821	return (zone->requestixfr);
15822}
15823
15824void
15825dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
15826	REQUIRE(DNS_ZONE_VALID(zone));
15827	zone->updatemethod = method;
15828}
15829
15830dns_updatemethod_t
15831dns_zone_getserialupdatemethod(dns_zone_t *zone) {
15832	REQUIRE(DNS_ZONE_VALID(zone));
15833	return(zone->updatemethod);
15834}
15835
15836/*
15837 * Lock hierachy zmgr, raw, zone.
15838 */
15839isc_result_t
15840dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
15841	isc_result_t result;
15842	dns_zonemgr_t *zmgr;
15843
15844	REQUIRE(DNS_ZONE_VALID(zone));
15845	REQUIRE(zone->zmgr != NULL);
15846	REQUIRE(zone->task != NULL);
15847	REQUIRE(zone->loadtask != NULL);
15848	REQUIRE(zone->raw == NULL);
15849
15850	REQUIRE(DNS_ZONE_VALID(raw));
15851	REQUIRE(raw->zmgr == NULL);
15852	REQUIRE(raw->task == NULL);
15853	REQUIRE(raw->loadtask == NULL);
15854	REQUIRE(raw->secure == NULL);
15855
15856	zmgr = zone->zmgr;
15857	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15858	LOCK_ZONE(raw);
15859	LOCK_ZONE(zone);
15860
15861	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
15862				  NULL, NULL, zone->task, zone_timer, raw,
15863				  &raw->timer);
15864	if (result != ISC_R_SUCCESS)
15865		goto unlock;
15866
15867	/*
15868	 * The timer "holds" a iref.
15869	 */
15870	raw->irefs++;
15871	INSIST(raw->irefs != 0);
15872
15873
15874	/* dns_zone_attach(raw, &zone->raw); */
15875	isc_refcount_increment(&raw->erefs, NULL);
15876	zone->raw = raw;
15877
15878	/* dns_zone_iattach(zone,  &raw->secure); */
15879	zone_iattach(zone, &raw->secure);
15880
15881	isc_task_attach(zone->task, &raw->task);
15882	isc_task_attach(zone->loadtask, &raw->loadtask);
15883
15884	ISC_LIST_APPEND(zmgr->zones, raw, link);
15885	raw->zmgr = zmgr;
15886	zmgr->refs++;
15887
15888 unlock:
15889	UNLOCK_ZONE(zone);
15890	UNLOCK_ZONE(raw);
15891	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15892	return (result);
15893}
15894
15895void
15896dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
15897	REQUIRE(DNS_ZONE_VALID(zone));
15898	REQUIRE(raw != NULL && *raw == NULL);
15899
15900	LOCK(&zone->lock);
15901	if (zone->raw != NULL)
15902		dns_zone_attach(zone->raw, raw);
15903	UNLOCK(&zone->lock);
15904}
15905
15906struct keydone {
15907	isc_event_t event;
15908	isc_boolean_t all;
15909	unsigned char data[5];
15910};
15911
15912#define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
15913
15914static void
15915keydone(isc_task_t *task, isc_event_t *event) {
15916	const char *me = "keydone";
15917	isc_boolean_t commit = ISC_FALSE;
15918	isc_result_t result;
15919	dns_rdata_t rdata = DNS_RDATA_INIT;
15920	dns_dbversion_t *oldver = NULL, *newver = NULL;
15921	dns_zone_t *zone;
15922	dns_db_t *db = NULL;
15923	dns_dbnode_t *node = NULL;
15924	dns_rdataset_t rdataset;
15925	dns_diff_t diff;
15926	struct keydone *keydone = (struct keydone *)event;
15927	dns_update_log_t log = { update_log_cb, NULL };
15928	isc_boolean_t clear_pending = ISC_FALSE;
15929
15930	UNUSED(task);
15931
15932	zone = event->ev_arg;
15933	INSIST(DNS_ZONE_VALID(zone));
15934
15935	ENTER;
15936
15937	dns_rdataset_init(&rdataset);
15938	dns_diff_init(zone->mctx, &diff);
15939
15940	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15941	if (zone->db != NULL) {
15942		dns_db_attach(zone->db, &db);
15943		dns_db_currentversion(db, &oldver);
15944		result = dns_db_newversion(db, &newver);
15945		if (result != ISC_R_SUCCESS) {
15946			dns_zone_log(zone, ISC_LOG_ERROR,
15947				     "keydone:dns_db_newversion -> %s",
15948				     dns_result_totext(result));
15949			goto failure;
15950		}
15951	}
15952	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15953	if (db == NULL)
15954		goto failure;
15955
15956	result = dns_db_getoriginnode(db, &node);
15957	if (result != ISC_R_SUCCESS)
15958		goto failure;
15959
15960	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
15961				     dns_rdatatype_none, 0, &rdataset, NULL);
15962	if (result == ISC_R_NOTFOUND) {
15963		INSIST(!dns_rdataset_isassociated(&rdataset));
15964		goto failure;
15965	}
15966	if (result != ISC_R_SUCCESS) {
15967		INSIST(!dns_rdataset_isassociated(&rdataset));
15968		goto failure;
15969	}
15970
15971	for (result = dns_rdataset_first(&rdataset);
15972	     result == ISC_R_SUCCESS;
15973	     result = dns_rdataset_next(&rdataset)) {
15974		isc_boolean_t found = ISC_FALSE;
15975
15976		dns_rdataset_current(&rdataset, &rdata);
15977
15978		if (keydone->all) {
15979			if (rdata.length == 5 && rdata.data[0] != 0 &&
15980			       rdata.data[3] == 0 && rdata.data[4] == 1)
15981				found = ISC_TRUE;
15982			else if (rdata.data[0] == 0 &&
15983				 (rdata.data[2] & PENDINGFLAGS) != 0) {
15984				found = ISC_TRUE;
15985				clear_pending = ISC_TRUE;
15986			}
15987		} else if (rdata.length == 5 &&
15988			   memcmp(rdata.data, keydone->data, 5) == 0)
15989			found = ISC_TRUE;
15990
15991		if (found)
15992			CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
15993					    &zone->origin, rdataset.ttl,
15994					    &rdata));
15995		dns_rdata_reset(&rdata);
15996	}
15997
15998	if (!ISC_LIST_EMPTY(diff.tuples)) {
15999		/* Write changes to journal file. */
16000		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
16001					zone->updatemethod));
16002
16003		result = dns_update_signatures(&log, zone, db,
16004					       oldver, newver, &diff,
16005					       zone->sigvalidityinterval);
16006		if (!clear_pending)
16007			CHECK(result);
16008
16009		CHECK(zone_journal(zone, &diff, NULL, "keydone"));
16010		commit = ISC_TRUE;
16011
16012		LOCK_ZONE(zone);
16013		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
16014		zone_needdump(zone, 30);
16015		UNLOCK_ZONE(zone);
16016	}
16017
16018 failure:
16019	if (dns_rdataset_isassociated(&rdataset))
16020		dns_rdataset_disassociate(&rdataset);
16021	if (db != NULL) {
16022		if (node != NULL)
16023			dns_db_detachnode(db, &node);
16024		if (oldver != NULL)
16025			dns_db_closeversion(db, &oldver, ISC_FALSE);
16026		if (newver != NULL)
16027			dns_db_closeversion(db, &newver, commit);
16028		dns_db_detach(&db);
16029	}
16030	dns_diff_clear(&diff);
16031	isc_event_free(&event);
16032	dns_zone_idetach(&zone);
16033}
16034
16035isc_result_t
16036dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
16037	isc_result_t result = ISC_R_SUCCESS;
16038	isc_event_t *e;
16039	isc_buffer_t b;
16040	dns_zone_t *dummy = NULL;
16041	struct keydone *kd;
16042
16043	REQUIRE(DNS_ZONE_VALID(zone));
16044
16045	LOCK_ZONE(zone);
16046
16047	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
16048			       zone, sizeof(struct keydone));
16049	if (e == NULL) {
16050		result = ISC_R_NOMEMORY;
16051		goto failure;
16052	}
16053
16054	kd = (struct keydone *) e;
16055	if (strcasecmp(keystr, "all") == 0)
16056		kd->all = ISC_TRUE;
16057	else {
16058		isc_textregion_t r;
16059		char *algstr;
16060		dns_keytag_t keyid;
16061		dns_secalg_t alg;
16062		size_t n;
16063
16064		kd->all = ISC_FALSE;
16065
16066		n = sscanf(keystr, "%hd/", &keyid);
16067		if (n == 0U)
16068			CHECK(ISC_R_FAILURE);
16069
16070		algstr = strchr(keystr, '/');
16071		if (algstr != NULL)
16072			algstr++;
16073		else
16074			CHECK(ISC_R_FAILURE);
16075
16076		n = sscanf(algstr, "%hhd", &alg);
16077		if (n == 0U) {
16078			DE_CONST(algstr, r.base);
16079			r.length = strlen(algstr);
16080			CHECK(dns_secalg_fromtext(&alg, &r));
16081		}
16082
16083		/* construct a private-type rdata */
16084		isc_buffer_init(&b, kd->data, sizeof(kd->data));
16085		isc_buffer_putuint8(&b, alg);
16086		isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
16087		isc_buffer_putuint8(&b, (keyid & 0xff));
16088		isc_buffer_putuint8(&b, 0);
16089		isc_buffer_putuint8(&b, 1);
16090	}
16091
16092	zone_iattach(zone, &dummy);
16093	isc_task_send(zone->task, &e);
16094
16095 failure:
16096	if (e != NULL)
16097		isc_event_free(&e);
16098	UNLOCK_ZONE(zone);
16099	return (result);
16100}
16101
16102struct nsec3param {
16103	isc_event_t event;
16104	unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
16105	unsigned int length;
16106	isc_boolean_t nsec;
16107	isc_boolean_t replace;
16108};
16109
16110static void
16111setnsec3param(isc_task_t *task, isc_event_t *event) {
16112	const char *me = "setnsec3param";
16113	isc_boolean_t commit = ISC_FALSE;
16114	isc_result_t result;
16115	dns_dbversion_t *oldver = NULL, *newver = NULL;
16116	dns_zone_t *zone;
16117	dns_db_t *db = NULL;
16118	dns_dbnode_t *node = NULL;
16119	dns_rdataset_t prdataset, nrdataset;
16120	dns_diff_t diff;
16121	struct nsec3param *np = (struct nsec3param *)event;
16122	dns_update_log_t log = { update_log_cb, NULL };
16123	dns_rdata_t rdata;
16124	isc_boolean_t nseconly;
16125	isc_boolean_t exists = ISC_FALSE;
16126
16127	UNUSED(task);
16128
16129	zone = event->ev_arg;
16130	INSIST(DNS_ZONE_VALID(zone));
16131
16132	ENTER;
16133
16134	dns_rdataset_init(&prdataset);
16135	dns_rdataset_init(&nrdataset);
16136	dns_diff_init(zone->mctx, &diff);
16137
16138	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16139	if (zone->db != NULL) {
16140		dns_db_attach(zone->db, &db);
16141		dns_db_currentversion(db, &oldver);
16142		result = dns_db_newversion(db, &newver);
16143		if (result != ISC_R_SUCCESS) {
16144			dns_zone_log(zone, ISC_LOG_ERROR,
16145				     "setnsec3param:dns_db_newversion -> %s",
16146				     dns_result_totext(result));
16147			goto failure;
16148		}
16149	}
16150	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16151	if (db == NULL)
16152		goto failure;
16153
16154	CHECK(dns_db_getoriginnode(db, &node));
16155
16156	/*
16157	 * Does a private-type record already exist for this chain?
16158	 */
16159	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
16160				     dns_rdatatype_none, 0, &prdataset, NULL);
16161	if (result == ISC_R_SUCCESS) {
16162		for (result = dns_rdataset_first(&prdataset);
16163		     result == ISC_R_SUCCESS;
16164		     result = dns_rdataset_next(&prdataset)) {
16165			dns_rdata_init(&rdata);
16166			dns_rdataset_current(&prdataset, &rdata);
16167
16168			if (np->length == rdata.length &&
16169			    memcmp(rdata.data, np->data, np->length) == 0) {
16170				exists = ISC_TRUE;
16171				break;
16172			}
16173		}
16174	} else if (result != ISC_R_NOTFOUND) {
16175		INSIST(!dns_rdataset_isassociated(&prdataset));
16176		goto failure;
16177	}
16178
16179	/*
16180	 * Does the chain already exist?
16181	 */
16182	result = dns_db_findrdataset(db, node, newver,
16183				     dns_rdatatype_nsec3param,
16184				     dns_rdatatype_none, 0, &nrdataset, NULL);
16185	if (result == ISC_R_SUCCESS) {
16186		for (result = dns_rdataset_first(&nrdataset);
16187		     result == ISC_R_SUCCESS;
16188		     result = dns_rdataset_next(&nrdataset)) {
16189			dns_rdata_init(&rdata);
16190			dns_rdataset_current(&nrdataset, &rdata);
16191
16192			if (np->length == (rdata.length + 1) &&
16193			    memcmp(rdata.data, np->data + 1,
16194				   np->length - 1) == 0)
16195			{
16196				exists = ISC_TRUE;
16197				break;
16198			}
16199		}
16200	} else if (result != ISC_R_NOTFOUND) {
16201		INSIST(!dns_rdataset_isassociated(&nrdataset));
16202		goto failure;
16203	}
16204
16205
16206	/*
16207	 * We need to remove any existing NSEC3 chains.
16208	 */
16209	if (!exists && np->replace && (np->length != 0 || np->nsec))
16210		CHECK(dns_nsec3param_deletechains(db, newver, zone,
16211						  !np->nsec, &diff));
16212
16213	if (!exists && np->length != 0) {
16214		/*
16215		 * We're creating an NSEC3 chain.
16216		 *
16217		 * If the zone is not currently capable of supporting
16218		 * an NSEC3 chain, add the INITIAL flag, so these
16219		 * parameters can be used later when NSEC3 becomes
16220		 * available.
16221		 */
16222		dns_rdata_init(&rdata);
16223
16224		np->data[2] |= DNS_NSEC3FLAG_CREATE;
16225		result = dns_nsec_nseconly(db, newver, &nseconly);
16226		if (result == ISC_R_NOTFOUND || nseconly)
16227			np->data[2] |= DNS_NSEC3FLAG_INITIAL;
16228
16229		rdata.length = np->length;
16230		rdata.data = np->data;
16231		rdata.type = zone->privatetype;
16232		rdata.rdclass = zone->rdclass;
16233		CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
16234				    &zone->origin, 0, &rdata));
16235	}
16236
16237	if (!ISC_LIST_EMPTY(diff.tuples)) {
16238		/* Write changes to journal file. */
16239		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
16240					zone->updatemethod));
16241		result = dns_update_signatures(&log, zone, db,
16242					       oldver, newver, &diff,
16243					       zone->sigvalidityinterval);
16244		if (result != ISC_R_NOTFOUND)
16245			CHECK(result);
16246		CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
16247		commit = ISC_TRUE;
16248
16249		LOCK_ZONE(zone);
16250		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
16251		zone_needdump(zone, 30);
16252		UNLOCK_ZONE(zone);
16253	}
16254
16255 failure:
16256	if (dns_rdataset_isassociated(&prdataset))
16257		dns_rdataset_disassociate(&prdataset);
16258	if (dns_rdataset_isassociated(&nrdataset))
16259		dns_rdataset_disassociate(&nrdataset);
16260	if (node != NULL)
16261		dns_db_detachnode(db, &node);
16262	if (oldver != NULL)
16263		dns_db_closeversion(db, &oldver, ISC_FALSE);
16264	if (newver != NULL)
16265		dns_db_closeversion(db, &newver, commit);
16266	if (db != NULL)
16267		dns_db_detach(&db);
16268	if (commit)
16269		resume_addnsec3chain(zone);
16270	dns_diff_clear(&diff);
16271	isc_event_free(&event);
16272	dns_zone_idetach(&zone);
16273}
16274
16275isc_result_t
16276dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
16277		       isc_uint8_t iter, isc_uint8_t saltlen,
16278		       unsigned char *salt, isc_boolean_t replace)
16279{
16280	isc_result_t result = ISC_R_SUCCESS;
16281	dns_rdata_nsec3param_t param;
16282	dns_rdata_t nrdata = DNS_RDATA_INIT;
16283	dns_rdata_t prdata = DNS_RDATA_INIT;
16284	unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
16285	struct nsec3param *np;
16286	dns_zone_t *dummy = NULL;
16287	isc_buffer_t b;
16288	isc_event_t *e;
16289
16290	REQUIRE(DNS_ZONE_VALID(zone));
16291	REQUIRE(salt != NULL);
16292
16293	LOCK_ZONE(zone);
16294
16295	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
16296			       setnsec3param, zone, sizeof(struct nsec3param));
16297	if (e == NULL) {
16298		result = ISC_R_NOMEMORY;
16299		goto failure;
16300	}
16301
16302	np = (struct nsec3param *) e;
16303	np->replace = replace;
16304	if (hash == 0) {
16305		np->length = 0;
16306		np->nsec = ISC_TRUE;
16307	} else {
16308		param.common.rdclass = zone->rdclass;
16309		param.common.rdtype = dns_rdatatype_nsec3param;
16310		ISC_LINK_INIT(&param.common, link);
16311		param.mctx = NULL;
16312		param.hash = hash;
16313		param.flags = flags;
16314		param.iterations = iter;
16315		param.salt_length = saltlen;
16316		param.salt = salt;
16317		isc_buffer_init(&b, nbuf, sizeof(nbuf));
16318		CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
16319					   dns_rdatatype_nsec3param,
16320					   &param, &b));
16321		dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
16322					 np->data, sizeof(np->data));
16323		np->length = prdata.length;
16324	}
16325
16326	zone_iattach(zone, &dummy);
16327	isc_task_send(zone->task, &e);
16328
16329 failure:
16330	if (e != NULL)
16331		isc_event_free(&e);
16332	UNLOCK_ZONE(zone);
16333	return (result);
16334}
16335