1/*	$NetBSD: zone.c,v 1.1 2024/02/18 20:57:34 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16/*! \file */
17
18#include <errno.h>
19#include <inttypes.h>
20#include <stdbool.h>
21
22#include <isc/atomic.h>
23#include <isc/file.h>
24#include <isc/hex.h>
25#include <isc/md.h>
26#include <isc/mutex.h>
27#include <isc/pool.h>
28#include <isc/print.h>
29#include <isc/random.h>
30#include <isc/ratelimiter.h>
31#include <isc/refcount.h>
32#include <isc/rwlock.h>
33#include <isc/serial.h>
34#include <isc/stats.h>
35#include <isc/stdtime.h>
36#include <isc/strerr.h>
37#include <isc/string.h>
38#include <isc/taskpool.h>
39#include <isc/thread.h>
40#include <isc/timer.h>
41#include <isc/util.h>
42
43#include <dns/acl.h>
44#include <dns/adb.h>
45#include <dns/callbacks.h>
46#include <dns/catz.h>
47#include <dns/db.h>
48#include <dns/dbiterator.h>
49#include <dns/dlz.h>
50#include <dns/dnssec.h>
51#include <dns/events.h>
52#include <dns/journal.h>
53#include <dns/kasp.h>
54#include <dns/keydata.h>
55#include <dns/keymgr.h>
56#include <dns/keytable.h>
57#include <dns/keyvalues.h>
58#include <dns/log.h>
59#include <dns/master.h>
60#include <dns/masterdump.h>
61#include <dns/message.h>
62#include <dns/name.h>
63#include <dns/nsec.h>
64#include <dns/nsec3.h>
65#include <dns/opcode.h>
66#include <dns/peer.h>
67#include <dns/private.h>
68#include <dns/rcode.h>
69#include <dns/rdata.h>
70#include <dns/rdataclass.h>
71#include <dns/rdatalist.h>
72#include <dns/rdataset.h>
73#include <dns/rdatasetiter.h>
74#include <dns/rdatastruct.h>
75#include <dns/rdatatype.h>
76#include <dns/request.h>
77#include <dns/resolver.h>
78#include <dns/result.h>
79#include <dns/rriterator.h>
80#include <dns/soa.h>
81#include <dns/ssu.h>
82#include <dns/stats.h>
83#include <dns/time.h>
84#include <dns/tsig.h>
85#include <dns/update.h>
86#include <dns/xfrin.h>
87#include <dns/zone.h>
88#include <dns/zoneverify.h>
89#include <dns/zt.h>
90
91#include <dst/dst.h>
92
93#include "zone_p.h"
94
95#define ZONE_MAGIC	     ISC_MAGIC('Z', 'O', 'N', 'E')
96#define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
97
98#define NOTIFY_MAGIC		 ISC_MAGIC('N', 't', 'f', 'y')
99#define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
100
101#define CHECKDS_MAGIC		   ISC_MAGIC('C', 'h', 'D', 'S')
102#define DNS_CHECKDS_VALID(checkds) ISC_MAGIC_VALID(checkds, CHECKDS_MAGIC)
103
104#define STUB_MAGIC	     ISC_MAGIC('S', 't', 'u', 'b')
105#define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
106
107#define ZONEMGR_MAGIC		ISC_MAGIC('Z', 'm', 'g', 'r')
108#define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
109
110#define LOAD_MAGIC	     ISC_MAGIC('L', 'o', 'a', 'd')
111#define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
112
113#define FORWARD_MAGIC		ISC_MAGIC('F', 'o', 'r', 'w')
114#define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
115
116#define IO_MAGIC	   ISC_MAGIC('Z', 'm', 'I', 'O')
117#define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
118
119#define KEYMGMT_MAGIC		ISC_MAGIC('M', 'g', 'm', 't')
120#define DNS_KEYMGMT_VALID(load) ISC_MAGIC_VALID(load, KEYMGMT_MAGIC)
121
122#define KEYFILEIO_MAGIC		  ISC_MAGIC('K', 'y', 'I', 'O')
123#define DNS_KEYFILEIO_VALID(kfio) ISC_MAGIC_VALID(kfio, KEYFILEIO_MAGIC)
124
125/*%
126 * Ensure 'a' is at least 'min' but not more than 'max'.
127 */
128#define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
129
130#define NSEC3REMOVE(x) (((x)&DNS_NSEC3FLAG_REMOVE) != 0)
131
132/*%
133 * Key flags
134 */
135#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
136#define KSK(x)	  ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
137#define ID(x)	  dst_key_id(x)
138#define ALG(x)	  dst_key_alg(x)
139
140/*%
141 * KASP flags
142 */
143#define KASP_LOCK(k)                  \
144	if ((k) != NULL) {            \
145		LOCK((&((k)->lock))); \
146	}
147
148#define KASP_UNLOCK(k)                  \
149	if ((k) != NULL) {              \
150		UNLOCK((&((k)->lock))); \
151	}
152
153/*
154 * Default values.
155 */
156#define DNS_DEFAULT_IDLEIN  3600       /*%< 1 hour */
157#define DNS_DEFAULT_IDLEOUT 3600       /*%< 1 hour */
158#define MAX_XFER_TIME	    (2 * 3600) /*%< Documented default is 2 hours */
159#define RESIGN_DELAY	    3600       /*%< 1 hour */
160
161#ifndef DNS_MAX_EXPIRE
162#define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
163#endif				/* ifndef DNS_MAX_EXPIRE */
164
165#ifndef DNS_DUMP_DELAY
166#define DNS_DUMP_DELAY 900 /*%< 15 minutes */
167#endif			   /* ifndef DNS_DUMP_DELAY */
168
169typedef struct dns_notify dns_notify_t;
170typedef struct dns_checkds dns_checkds_t;
171typedef struct dns_stub dns_stub_t;
172typedef struct dns_load dns_load_t;
173typedef struct dns_forward dns_forward_t;
174typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
175typedef struct dns_io dns_io_t;
176typedef ISC_LIST(dns_io_t) dns_iolist_t;
177typedef struct dns_keymgmt dns_keymgmt_t;
178typedef struct dns_signing dns_signing_t;
179typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
180typedef struct dns_nsec3chain dns_nsec3chain_t;
181typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
182typedef struct dns_keyfetch dns_keyfetch_t;
183typedef struct dns_asyncload dns_asyncload_t;
184typedef struct dns_include dns_include_t;
185
186#define DNS_ZONE_CHECKLOCK
187#ifdef DNS_ZONE_CHECKLOCK
188#define LOCK_ZONE(z)                  \
189	do {                          \
190		LOCK(&(z)->lock);     \
191		INSIST(!(z)->locked); \
192		(z)->locked = true;   \
193	} while (0)
194#define UNLOCK_ZONE(z)               \
195	do {                         \
196		(z)->locked = false; \
197		UNLOCK(&(z)->lock);  \
198	} while (0)
199#define LOCKED_ZONE(z) ((z)->locked)
200#define TRYLOCK_ZONE(result, z)                         \
201	do {                                            \
202		result = isc_mutex_trylock(&(z)->lock); \
203		if (result == ISC_R_SUCCESS) {          \
204			INSIST(!(z)->locked);           \
205			(z)->locked = true;             \
206		}                                       \
207	} while (0)
208#else /* ifdef DNS_ZONE_CHECKLOCK */
209#define LOCK_ZONE(z)   LOCK(&(z)->lock)
210#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
211#define LOCKED_ZONE(z) true
212#define TRYLOCK_ZONE(result, z)                         \
213	do {                                            \
214		result = isc_mutex_trylock(&(z)->lock); \
215	} while (0)
216#endif /* ifdef DNS_ZONE_CHECKLOCK */
217
218#define ZONEDB_INITLOCK(l)    isc_rwlock_init((l), 0, 0)
219#define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
220#define ZONEDB_LOCK(l, t)     RWLOCK((l), (t))
221#define ZONEDB_UNLOCK(l, t)   RWUNLOCK((l), (t))
222
223#ifdef ENABLE_AFL
224extern bool dns_fuzzing_resolver;
225#endif /* ifdef ENABLE_AFL */
226
227/*%
228 *	Hold key file IO locks.
229 */
230typedef struct dns_keyfileio {
231	unsigned int magic;
232	struct dns_keyfileio *next;
233	uint32_t hashval;
234	dns_fixedname_t fname;
235	dns_name_t *name;
236	isc_refcount_t references;
237	isc_mutex_t lock;
238} dns_keyfileio_t;
239
240struct dns_keymgmt {
241	unsigned int magic;
242	isc_rwlock_t lock;
243	isc_mem_t *mctx;
244
245	dns_keyfileio_t **table;
246
247	atomic_uint_fast32_t count;
248
249	uint32_t bits;
250};
251
252struct dns_zone {
253	/* Unlocked */
254	unsigned int magic;
255	isc_mutex_t lock;
256#ifdef DNS_ZONE_CHECKLOCK
257	bool locked;
258#endif /* ifdef DNS_ZONE_CHECKLOCK */
259	isc_mem_t *mctx;
260	isc_refcount_t erefs;
261
262	isc_rwlock_t dblock;
263	dns_db_t *db; /* Locked by dblock */
264
265	/* Locked */
266	dns_zonemgr_t *zmgr;
267	ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
268	isc_timer_t *timer;
269	isc_refcount_t irefs;
270	dns_name_t origin;
271	char *masterfile;
272	ISC_LIST(dns_include_t) includes;    /* Include files */
273	ISC_LIST(dns_include_t) newincludes; /* Loading */
274	unsigned int nincludes;
275	dns_masterformat_t masterformat;
276	const dns_master_style_t *masterstyle;
277	char *journal;
278	int32_t journalsize;
279	dns_rdataclass_t rdclass;
280	dns_zonetype_t type;
281#ifdef __NetBSD__
282	atomic_uint_fast32_t flags;
283	atomic_uint_fast32_t options;
284#else
285	atomic_uint_fast64_t flags;
286	atomic_uint_fast64_t options;
287#endif
288	unsigned int db_argc;
289	char **db_argv;
290	isc_time_t expiretime;
291	isc_time_t refreshtime;
292	isc_time_t dumptime;
293	isc_time_t loadtime;
294	isc_time_t notifytime;
295	isc_time_t resigntime;
296	isc_time_t keywarntime;
297	isc_time_t signingtime;
298	isc_time_t nsec3chaintime;
299	isc_time_t refreshkeytime;
300	uint32_t refreshkeyinterval;
301	uint32_t refreshkeycount;
302	uint32_t refresh;
303	uint32_t retry;
304	uint32_t expire;
305	uint32_t minimum;
306	isc_stdtime_t key_expiry;
307	isc_stdtime_t log_key_expired_timer;
308	char *keydirectory;
309	dns_keyfileio_t *kfio;
310
311	uint32_t maxrefresh;
312	uint32_t minrefresh;
313	uint32_t maxretry;
314	uint32_t minretry;
315
316	uint32_t maxrecords;
317
318	isc_sockaddr_t *masters;
319	isc_dscp_t *masterdscps;
320	dns_name_t **masterkeynames;
321	bool *mastersok;
322	unsigned int masterscnt;
323	unsigned int curmaster;
324	isc_sockaddr_t masteraddr;
325
326	isc_sockaddr_t *parentals;
327	isc_dscp_t *parentaldscps;
328	dns_name_t **parentalkeynames;
329	dns_dnsseckeylist_t checkds_ok;
330	unsigned int parentalscnt;
331	isc_sockaddr_t parentaladdr;
332
333	dns_notifytype_t notifytype;
334	isc_sockaddr_t *notify;
335	dns_name_t **notifykeynames;
336	isc_dscp_t *notifydscp;
337	unsigned int notifycnt;
338	isc_sockaddr_t notifyfrom;
339	isc_task_t *task;
340	isc_task_t *loadtask;
341	isc_sockaddr_t notifysrc4;
342	isc_sockaddr_t notifysrc6;
343	isc_sockaddr_t parentalsrc4;
344	isc_sockaddr_t parentalsrc6;
345	isc_sockaddr_t xfrsource4;
346	isc_sockaddr_t xfrsource6;
347	isc_sockaddr_t altxfrsource4;
348	isc_sockaddr_t altxfrsource6;
349	isc_sockaddr_t sourceaddr;
350	isc_dscp_t notifysrc4dscp;
351	isc_dscp_t notifysrc6dscp;
352	isc_dscp_t parentalsrc4dscp;
353	isc_dscp_t parentalsrc6dscp;
354	isc_dscp_t xfrsource4dscp;
355	isc_dscp_t xfrsource6dscp;
356	isc_dscp_t altxfrsource4dscp;
357	isc_dscp_t altxfrsource6dscp;
358	dns_xfrin_ctx_t *xfr;	/* task locked */
359	dns_tsigkey_t *tsigkey; /* key used for xfr */
360	/* Access Control Lists */
361	dns_acl_t *update_acl;
362	dns_acl_t *forward_acl;
363	dns_acl_t *notify_acl;
364	dns_acl_t *query_acl;
365	dns_acl_t *queryon_acl;
366	dns_acl_t *xfr_acl;
367	bool update_disabled;
368	bool zero_no_soa_ttl;
369	dns_severity_t check_names;
370	ISC_LIST(dns_notify_t) notifies;
371	ISC_LIST(dns_checkds_t) checkds_requests;
372	dns_request_t *request;
373	dns_loadctx_t *lctx;
374	dns_io_t *readio;
375	dns_dumpctx_t *dctx;
376	dns_io_t *writeio;
377	uint32_t maxxfrin;
378	uint32_t maxxfrout;
379	uint32_t idlein;
380	uint32_t idleout;
381	isc_event_t ctlevent;
382	dns_ssutable_t *ssutable;
383	uint32_t sigvalidityinterval;
384	uint32_t keyvalidityinterval;
385	uint32_t sigresigninginterval;
386	dns_view_t *view;
387	dns_view_t *prev_view;
388	dns_kasp_t *kasp;
389	dns_checkmxfunc_t checkmx;
390	dns_checksrvfunc_t checksrv;
391	dns_checknsfunc_t checkns;
392	/*%
393	 * Zones in certain states such as "waiting for zone transfer"
394	 * or "zone transfer in progress" are kept on per-state linked lists
395	 * in the zone manager using the 'statelink' field.  The 'statelist'
396	 * field points at the list the zone is currently on.  It the zone
397	 * is not on any such list, statelist is NULL.
398	 */
399	ISC_LINK(dns_zone_t) statelink;
400	dns_zonelist_t *statelist;
401	/*%
402	 * Statistics counters about zone management.
403	 */
404	isc_stats_t *stats;
405	/*%
406	 * Optional per-zone statistics counters.  Counted outside of this
407	 * module.
408	 */
409	dns_zonestat_level_t statlevel;
410	bool requeststats_on;
411	isc_stats_t *requeststats;
412	dns_stats_t *rcvquerystats;
413	dns_stats_t *dnssecsignstats;
414	uint32_t notifydelay;
415	dns_isselffunc_t isself;
416	void *isselfarg;
417
418	char *strnamerd;
419	char *strname;
420	char *strrdclass;
421	char *strviewname;
422
423	/*%
424	 * Serial number for deferred journal compaction.
425	 */
426	uint32_t compact_serial;
427	/*%
428	 * Keys that are signing the zone for the first time.
429	 */
430	dns_signinglist_t signing;
431	dns_nsec3chainlist_t nsec3chain;
432	/*%
433	 * List of outstanding NSEC3PARAM change requests.
434	 */
435	isc_eventlist_t setnsec3param_queue;
436	/*%
437	 * Signing / re-signing quantum stopping parameters.
438	 */
439	uint32_t signatures;
440	uint32_t nodes;
441	dns_rdatatype_t privatetype;
442
443	/*%
444	 * Autosigning/key-maintenance options
445	 */
446#ifdef __NetBSD__
447	atomic_uint_fast32_t keyopts;
448#else
449	atomic_uint_fast64_t keyopts;
450#endif
451
452	/*%
453	 * True if added by "rndc addzone"
454	 */
455	bool added;
456
457	/*%
458	 * True if added by automatically by named.
459	 */
460	bool automatic;
461
462	/*%
463	 * response policy data to be relayed to the database
464	 */
465	dns_rpz_zones_t *rpzs;
466	dns_rpz_num_t rpz_num;
467
468	/*%
469	 * catalog zone data
470	 */
471	dns_catz_zones_t *catzs;
472
473	/*%
474	 * parent catalog zone
475	 */
476	dns_catz_zone_t *parentcatz;
477
478	/*%
479	 * Serial number update method.
480	 */
481	dns_updatemethod_t updatemethod;
482
483	/*%
484	 * whether ixfr is requested
485	 */
486	bool requestixfr;
487	uint32_t ixfr_ratio;
488
489	/*%
490	 * whether EDNS EXPIRE is requested
491	 */
492	bool requestexpire;
493
494	/*%
495	 * Outstanding forwarded UPDATE requests.
496	 */
497	dns_forwardlist_t forwards;
498
499	dns_zone_t *raw;
500	dns_zone_t *secure;
501
502	bool sourceserialset;
503	uint32_t sourceserial;
504
505	/*%
506	 * soa and maximum zone ttl
507	 */
508	dns_ttl_t soattl;
509	dns_ttl_t maxttl;
510
511	/*
512	 * Inline zone signing state.
513	 */
514	dns_diff_t rss_diff;
515	isc_eventlist_t rss_events;
516	isc_eventlist_t rss_post;
517	dns_dbversion_t *rss_newver;
518	dns_dbversion_t *rss_oldver;
519	dns_db_t *rss_db;
520	dns_zone_t *rss_raw;
521	isc_event_t *rss_event;
522	dns_update_state_t *rss_state;
523
524	isc_stats_t *gluecachestats;
525};
526
527#define zonediff_init(z, d)                \
528	do {                               \
529		dns__zonediff_t *_z = (z); \
530		(_z)->diff = (d);          \
531		(_z)->offline = false;     \
532	} while (0)
533
534#define DNS_ZONE_FLAG(z, f)    ((atomic_load_relaxed(&(z)->flags) & (f)) != 0)
535#define DNS_ZONE_SETFLAG(z, f) atomic_fetch_or(&(z)->flags, (f))
536#define DNS_ZONE_CLRFLAG(z, f) atomic_fetch_and(&(z)->flags, ~(f))
537typedef enum {
538	DNS_ZONEFLG_REFRESH = 0x00000001U,     /*%< refresh check in progress */
539	DNS_ZONEFLG_NEEDDUMP = 0x00000002U,    /*%< zone need consolidation */
540	DNS_ZONEFLG_USEVC = 0x00000004U,       /*%< use tcp for refresh query */
541	DNS_ZONEFLG_DUMPING = 0x00000008U,     /*%< a dump is in progress */
542	DNS_ZONEFLG_HASINCLUDE = 0x00000010U,  /*%< $INCLUDE in zone file */
543	DNS_ZONEFLG_LOADED = 0x00000020U,      /*%< database has loaded */
544	DNS_ZONEFLG_EXITING = 0x00000040U,     /*%< zone is being destroyed */
545	DNS_ZONEFLG_EXPIRED = 0x00000080U,     /*%< zone has expired */
546	DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
547	DNS_ZONEFLG_UPTODATE = 0x00000200U,    /*%< zone contents are
548						* up-to-date */
549	DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U,  /*%< need to send out notify
550						* messages */
551	DNS_ZONEFLG_FIXJOURNAL = 0x00000800U,  /*%< journal file had
552						* recoverable error,
553						* needs rewriting */
554	DNS_ZONEFLG_NOMASTERS = 0x00001000U,   /*%< an attempt to refresh a
555						* zone with no primaries
556						* occurred */
557	DNS_ZONEFLG_LOADING = 0x00002000U,     /*%< load from disk in progress*/
558	DNS_ZONEFLG_HAVETIMERS = 0x00004000U,  /*%< timer values have been set
559						* from SOA (if not set, we
560						* are still using
561						* default timer values) */
562	DNS_ZONEFLG_FORCEXFER = 0x00008000U,   /*%< Force a zone xfer */
563	DNS_ZONEFLG_NOREFRESH = 0x00010000U,
564	DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
565	DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
566	DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
567	DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
568	DNS_ZONEFLG_FLUSH = 0x00200000U,
569	DNS_ZONEFLG_NOEDNS = 0x00400000U,
570	DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U,
571	DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
572	DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
573	DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
574	DNS_ZONEFLG_THAW = 0x08000000U,
575	DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
576	DNS_ZONEFLG_NODELAY = 0x20000000U,
577	DNS_ZONEFLG_SENDSECURE = 0x40000000U,
578	DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
579						      * notify due to the zone
580						      * just being loaded for
581						      * the first time. */
582#ifndef __NetBSD__
583	/*
584	 * DO NOT add any new zone flags here until all platforms
585	 * support 64-bit enum values. Currently they fail on
586	 * Windows.
587	 */
588	DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
589#endif
590} dns_zoneflg_t;
591
592#define DNS_ZONE_OPTION(z, o)	 ((atomic_load_relaxed(&(z)->options) & (o)) != 0)
593#define DNS_ZONE_SETOPTION(z, o) atomic_fetch_or(&(z)->options, (o))
594#define DNS_ZONE_CLROPTION(z, o) atomic_fetch_and(&(z)->options, ~(o))
595
596#define DNS_ZONEKEY_OPTION(z, o) \
597	((atomic_load_relaxed(&(z)->keyopts) & (o)) != 0)
598#define DNS_ZONEKEY_SETOPTION(z, o) atomic_fetch_or(&(z)->keyopts, (o))
599#define DNS_ZONEKEY_CLROPTION(z, o) atomic_fetch_and(&(z)->keyopts, ~(o))
600
601/* Flags for zone_load() */
602typedef enum {
603	DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
604	DNS_ZONELOADFLAG_THAW = 0x00000002U,   /* Thaw the zone on successful
605						* load. */
606} dns_zoneloadflag_t;
607
608#define UNREACH_CACHE_SIZE 10U
609#define UNREACH_HOLD_TIME  600 /* 10 minutes */
610
611#define CHECK(op)                            \
612	do {                                 \
613		result = (op);               \
614		if (result != ISC_R_SUCCESS) \
615			goto failure;        \
616	} while (0)
617
618struct dns_unreachable {
619	isc_sockaddr_t remote;
620	isc_sockaddr_t local;
621	atomic_uint_fast32_t expire;
622	atomic_uint_fast32_t last;
623	uint32_t count;
624};
625
626struct dns_zonemgr {
627	unsigned int magic;
628	isc_mem_t *mctx;
629	isc_refcount_t refs;
630	isc_taskmgr_t *taskmgr;
631	isc_timermgr_t *timermgr;
632	isc_socketmgr_t *socketmgr;
633	isc_taskpool_t *zonetasks;
634	isc_taskpool_t *loadtasks;
635	isc_task_t *task;
636	isc_pool_t *mctxpool;
637	isc_ratelimiter_t *checkdsrl;
638	isc_ratelimiter_t *notifyrl;
639	isc_ratelimiter_t *refreshrl;
640	isc_ratelimiter_t *startupnotifyrl;
641	isc_ratelimiter_t *startuprefreshrl;
642	isc_rwlock_t rwlock;
643	isc_mutex_t iolock;
644	isc_rwlock_t urlock;
645
646	/* Locked by rwlock. */
647	dns_zonelist_t zones;
648	dns_zonelist_t waiting_for_xfrin;
649	dns_zonelist_t xfrin_in_progress;
650
651	/* Configuration data. */
652	uint32_t transfersin;
653	uint32_t transfersperns;
654	unsigned int checkdsrate;
655	unsigned int notifyrate;
656	unsigned int startupnotifyrate;
657	unsigned int serialqueryrate;
658	unsigned int startupserialqueryrate;
659
660	/* Locked by iolock */
661	uint32_t iolimit;
662	uint32_t ioactive;
663	dns_iolist_t high;
664	dns_iolist_t low;
665
666	/* Locked by urlock. */
667	/* LRU cache */
668	struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
669
670	dns_keymgmt_t *keymgmt;
671};
672
673/*%
674 * Hold notify state.
675 */
676struct dns_notify {
677	unsigned int magic;
678	unsigned int flags;
679	isc_mem_t *mctx;
680	dns_zone_t *zone;
681	dns_adbfind_t *find;
682	dns_request_t *request;
683	dns_name_t ns;
684	isc_sockaddr_t dst;
685	dns_tsigkey_t *key;
686	isc_dscp_t dscp;
687	ISC_LINK(dns_notify_t) link;
688	isc_event_t *event;
689};
690
691#define DNS_NOTIFY_NOSOA   0x0001U
692#define DNS_NOTIFY_STARTUP 0x0002U
693
694/*%
695 * Hold checkds state.
696 */
697struct dns_checkds {
698	unsigned int magic;
699	unsigned int flags;
700	isc_mem_t *mctx;
701	dns_zone_t *zone;
702	dns_request_t *request;
703	isc_sockaddr_t dst;
704	dns_tsigkey_t *key;
705	isc_dscp_t dscp;
706	ISC_LINK(dns_checkds_t) link;
707	isc_event_t *event;
708};
709
710/*%
711 *	dns_stub holds state while performing a 'stub' transfer.
712 *	'db' is the zone's 'db' or a new one if this is the initial
713 *	transfer.
714 */
715
716struct dns_stub {
717	unsigned int magic;
718	isc_mem_t *mctx;
719	dns_zone_t *zone;
720	dns_db_t *db;
721	dns_dbversion_t *version;
722	atomic_uint_fast32_t pending_requests;
723};
724
725/*%
726 *	Hold load state.
727 */
728struct dns_load {
729	unsigned int magic;
730	isc_mem_t *mctx;
731	dns_zone_t *zone;
732	dns_db_t *db;
733	isc_time_t loadtime;
734	dns_rdatacallbacks_t callbacks;
735};
736
737/*%
738 *	Hold forward state.
739 */
740struct dns_forward {
741	unsigned int magic;
742	isc_mem_t *mctx;
743	dns_zone_t *zone;
744	isc_buffer_t *msgbuf;
745	dns_request_t *request;
746	uint32_t which;
747	isc_sockaddr_t addr;
748	dns_updatecallback_t callback;
749	void *callback_arg;
750	unsigned int options;
751	ISC_LINK(dns_forward_t) link;
752};
753
754/*%
755 *	Hold IO request state.
756 */
757struct dns_io {
758	unsigned int magic;
759	dns_zonemgr_t *zmgr;
760	bool high;
761	isc_task_t *task;
762	ISC_LINK(dns_io_t) link;
763	isc_event_t *event;
764};
765
766/*%
767 *	Hold state for when we are signing a zone with a new
768 *	DNSKEY as result of an update.
769 */
770struct dns_signing {
771	unsigned int magic;
772	dns_db_t *db;
773	dns_dbiterator_t *dbiterator;
774	dns_secalg_t algorithm;
775	uint16_t keyid;
776	bool deleteit;
777	bool done;
778	ISC_LINK(dns_signing_t) link;
779};
780
781struct dns_nsec3chain {
782	unsigned int magic;
783	dns_db_t *db;
784	dns_dbiterator_t *dbiterator;
785	dns_rdata_nsec3param_t nsec3param;
786	unsigned char salt[255];
787	bool done;
788	bool seen_nsec;
789	bool delete_nsec;
790	bool save_delete_nsec;
791	ISC_LINK(dns_nsec3chain_t) link;
792};
793
794/*%<
795 * 'dbiterator' contains a iterator for the database.  If we are creating
796 * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
797 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
798 * iterated.
799 *
800 * 'nsec3param' contains the parameters of the NSEC3 chain being created
801 * or removed.
802 *
803 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
804 *
805 * 'seen_nsec' will be set to true if, while iterating the zone to create a
806 * NSEC3 chain, a NSEC record is seen.
807 *
808 * 'delete_nsec' will be set to true if, at the completion of the creation
809 * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
810 * are in the process of deleting the NSEC chain.
811 *
812 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
813 * so it can be recovered in the event of a error.
814 */
815
816struct dns_keyfetch {
817	isc_mem_t *mctx;
818	dns_fixedname_t name;
819	dns_rdataset_t keydataset;
820	dns_rdataset_t dnskeyset;
821	dns_rdataset_t dnskeysigset;
822	dns_zone_t *zone;
823	dns_db_t *db;
824	dns_fetch_t *fetch;
825};
826
827/*%
828 * Hold state for an asynchronous load
829 */
830struct dns_asyncload {
831	dns_zone_t *zone;
832	unsigned int flags;
833	dns_zt_zoneloaded_t loaded;
834	void *loaded_arg;
835};
836
837/*%
838 * Reference to an include file encountered during loading
839 */
840struct dns_include {
841	char *name;
842	isc_time_t filetime;
843	ISC_LINK(dns_include_t) link;
844};
845
846/*
847 * These can be overridden by the -T mkeytimers option on the command
848 * line, so that we can test with shorter periods than specified in
849 * RFC 5011.
850 */
851#define HOUR  3600
852#define DAY   (24 * HOUR)
853#define MONTH (30 * DAY)
854LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_hour = HOUR;
855LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_day = DAY;
856LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_month = MONTH;
857
858#define SEND_BUFFER_SIZE 2048
859
860static void
861zone_settimer(dns_zone_t *, isc_time_t *);
862static void
863cancel_refresh(dns_zone_t *);
864static void
865zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
866	      ...) ISC_FORMAT_PRINTF(4, 5);
867static void
868notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
869	ISC_FORMAT_PRINTF(3, 4);
870static void
871dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
872	ISC_FORMAT_PRINTF(3, 4);
873static void
874queue_xfrin(dns_zone_t *zone);
875static isc_result_t
876update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
877	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
878	      dns_rdata_t *rdata);
879static void
880zone_unload(dns_zone_t *zone);
881static void
882zone_expire(dns_zone_t *zone);
883static void
884zone_iattach(dns_zone_t *source, dns_zone_t **target);
885static void
886zone_idetach(dns_zone_t **zonep);
887static isc_result_t
888zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
889static void
890zone_attachdb(dns_zone_t *zone, dns_db_t *db);
891static void
892zone_detachdb(dns_zone_t *zone);
893static void
894zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs);
895static void
896zone_catz_disable(dns_zone_t *zone);
897static isc_result_t
898default_journal(dns_zone_t *zone);
899static void
900zone_xfrdone(dns_zone_t *zone, isc_result_t result);
901static isc_result_t
902zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
903	      isc_result_t result);
904static void
905zone_needdump(dns_zone_t *zone, unsigned int delay);
906static void
907zone_shutdown(isc_task_t *, isc_event_t *);
908static void
909zone_loaddone(void *arg, isc_result_t result);
910static isc_result_t
911zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);
912static void
913zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
914static void
915zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
916static void
917zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
918static void
919zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
920static isc_result_t
921zone_send_secureserial(dns_zone_t *zone, uint32_t serial);
922static void
923refresh_callback(isc_task_t *, isc_event_t *);
924static void
925stub_callback(isc_task_t *, isc_event_t *);
926static void
927queue_soa_query(dns_zone_t *zone);
928static void
929soa_query(isc_task_t *, isc_event_t *);
930static void
931ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
932static int
933message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);
934static void
935checkds_cancel(dns_zone_t *zone);
936static void
937checkds_send(dns_zone_t *zone);
938static isc_result_t
939checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep);
940static void
941checkds_done(isc_task_t *task, isc_event_t *event);
942static void
943checkds_send_toaddr(isc_task_t *task, isc_event_t *event);
944static void
945notify_cancel(dns_zone_t *zone);
946static void
947notify_find_address(dns_notify_t *notify);
948static void
949notify_send(dns_notify_t *notify);
950static isc_result_t
951notify_createmessage(dns_zone_t *zone, unsigned int flags,
952		     dns_message_t **messagep);
953static void
954notify_done(isc_task_t *task, isc_event_t *event);
955static void
956notify_send_toaddr(isc_task_t *task, isc_event_t *event);
957static isc_result_t
958zone_dump(dns_zone_t *, bool);
959static void
960got_transfer_quota(isc_task_t *task, isc_event_t *event);
961static isc_result_t
962zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);
963static void
964zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
965static void
966zonemgr_free(dns_zonemgr_t *zmgr);
967static isc_result_t
968zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
969	      isc_taskaction_t action, void *arg, dns_io_t **iop);
970static void
971zonemgr_putio(dns_io_t **iop);
972static void
973zonemgr_cancelio(dns_io_t *io);
974static void
975rss_post(dns_zone_t *, isc_event_t *);
976
977static isc_result_t
978zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
979		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
980		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
981		 uint32_t *minimum, unsigned int *errors);
982
983static void
984zone_freedbargs(dns_zone_t *zone);
985static void
986forward_callback(isc_task_t *task, isc_event_t *event);
987static void
988zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);
989static void
990zone_maintenance(dns_zone_t *zone);
991static void
992zone_notify(dns_zone_t *zone, isc_time_t *now);
993static void
994dump_done(void *arg, isc_result_t result);
995static isc_result_t
996zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
997		 bool deleteit);
998static isc_result_t
999delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
1000	    dns_name_t *name, dns_diff_t *diff);
1001static void
1002zone_rekey(dns_zone_t *zone);
1003static isc_result_t
1004zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
1005static dns_ttl_t
1006zone_nsecttl(dns_zone_t *zone);
1007static void
1008setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value);
1009static void
1010zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial);
1011static isc_result_t
1012zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
1013			 bool *fixjournal);
1014
1015#define ENTER zone_debuglog(zone, me, 1, "enter")
1016
1017static const unsigned int dbargc_default = 1;
1018static const char *dbargv_default[] = { "rbt" };
1019
1020#define DNS_ZONE_JITTER_ADD(a, b, c)                                         \
1021	do {                                                                 \
1022		isc_interval_t _i;                                           \
1023		uint32_t _j;                                                 \
1024		_j = (b)-isc_random_uniform((b) / 4);                        \
1025		isc_interval_set(&_i, _j, 0);                                \
1026		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
1027			dns_zone_log(zone, ISC_LOG_WARNING,                  \
1028				     "epoch approaching: upgrade required: " \
1029				     "now + %s failed",                      \
1030				     #b);                                    \
1031			isc_interval_set(&_i, _j / 2, 0);                    \
1032			(void)isc_time_add((a), &_i, (c));                   \
1033		}                                                            \
1034	} while (0)
1035
1036#define DNS_ZONE_TIME_ADD(a, b, c)                                           \
1037	do {                                                                 \
1038		isc_interval_t _i;                                           \
1039		isc_interval_set(&_i, (b), 0);                               \
1040		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
1041			dns_zone_log(zone, ISC_LOG_WARNING,                  \
1042				     "epoch approaching: upgrade required: " \
1043				     "now + %s failed",                      \
1044				     #b);                                    \
1045			isc_interval_set(&_i, (b) / 2, 0);                   \
1046			(void)isc_time_add((a), &_i, (c));                   \
1047		}                                                            \
1048	} while (0)
1049
1050typedef struct nsec3param nsec3param_t;
1051struct nsec3param {
1052	dns_rdata_nsec3param_t rdata;
1053	unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
1054	unsigned int length;
1055	bool nsec;
1056	bool replace;
1057	bool resalt;
1058	bool lookup;
1059	ISC_LINK(nsec3param_t) link;
1060};
1061typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
1062struct np3event {
1063	isc_event_t event;
1064	nsec3param_t params;
1065};
1066
1067struct ssevent {
1068	isc_event_t event;
1069	uint32_t serial;
1070};
1071
1072struct stub_cb_args {
1073	dns_stub_t *stub;
1074	dns_tsigkey_t *tsig_key;
1075	isc_dscp_t dscp;
1076	uint16_t udpsize;
1077	int timeout;
1078	bool reqnsid;
1079};
1080
1081struct stub_glue_request {
1082	dns_request_t *request;
1083	dns_name_t name;
1084	struct stub_cb_args *args;
1085	bool ipv4;
1086};
1087
1088/*%
1089 * Increment resolver-related statistics counters.  Zone must be locked.
1090 */
1091static void
1092inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
1093	if (zone->stats != NULL) {
1094		isc_stats_increment(zone->stats, counter);
1095	}
1096}
1097
1098/***
1099 ***	Public functions.
1100 ***/
1101
1102isc_result_t
1103dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
1104	isc_result_t result;
1105	isc_time_t now;
1106	dns_zone_t *zone = NULL;
1107	dns_zone_t z = { .masterformat = dns_masterformat_none,
1108			 .journalsize = -1,
1109			 .rdclass = dns_rdataclass_none,
1110			 .type = dns_zone_none,
1111			 .refresh = DNS_ZONE_DEFAULTREFRESH,
1112			 .retry = DNS_ZONE_DEFAULTRETRY,
1113			 .maxrefresh = DNS_ZONE_MAXREFRESH,
1114			 .minrefresh = DNS_ZONE_MINREFRESH,
1115			 .maxretry = DNS_ZONE_MAXRETRY,
1116			 .minretry = DNS_ZONE_MINRETRY,
1117			 .notifytype = dns_notifytype_yes,
1118			 .zero_no_soa_ttl = true,
1119			 .check_names = dns_severity_ignore,
1120			 .idlein = DNS_DEFAULT_IDLEIN,
1121			 .idleout = DNS_DEFAULT_IDLEOUT,
1122			 .notifysrc4dscp = -1,
1123			 .notifysrc6dscp = -1,
1124			 .parentalsrc4dscp = -1,
1125			 .parentalsrc6dscp = -1,
1126			 .xfrsource4dscp = -1,
1127			 .xfrsource6dscp = -1,
1128			 .altxfrsource4dscp = -1,
1129			 .altxfrsource6dscp = -1,
1130			 .maxxfrin = MAX_XFER_TIME,
1131			 .maxxfrout = MAX_XFER_TIME,
1132			 .sigvalidityinterval = 30 * 24 * 3600,
1133			 .sigresigninginterval = 7 * 24 * 3600,
1134			 .statlevel = dns_zonestat_none,
1135			 .notifydelay = 5,
1136			 .signatures = 10,
1137			 .nodes = 100,
1138			 .privatetype = (dns_rdatatype_t)0xffffU,
1139			 .rpz_num = DNS_RPZ_INVALID_NUM,
1140			 .requestixfr = true,
1141			 .ixfr_ratio = 100,
1142			 .requestexpire = true,
1143			 .updatemethod = dns_updatemethod_increment,
1144			 .magic = ZONE_MAGIC };
1145
1146	REQUIRE(zonep != NULL && *zonep == NULL);
1147	REQUIRE(mctx != NULL);
1148
1149	TIME_NOW(&now);
1150	zone = isc_mem_get(mctx, sizeof(*zone));
1151	*zone = z;
1152
1153	zone->mctx = NULL;
1154	isc_mem_attach(mctx, &zone->mctx);
1155	isc_mutex_init(&zone->lock);
1156	ZONEDB_INITLOCK(&zone->dblock);
1157	/* XXX MPA check that all elements are initialised */
1158#ifdef DNS_ZONE_CHECKLOCK
1159	zone->locked = false;
1160#endif /* ifdef DNS_ZONE_CHECKLOCK */
1161
1162	zone->notifytime = now;
1163
1164	ISC_LINK_INIT(zone, link);
1165	isc_refcount_init(&zone->erefs, 1);
1166	isc_refcount_init(&zone->irefs, 0);
1167	dns_name_init(&zone->origin, NULL);
1168	ISC_LIST_INIT(zone->includes);
1169	ISC_LIST_INIT(zone->newincludes);
1170	atomic_init(&zone->flags, 0);
1171	atomic_init(&zone->options, 0);
1172	atomic_init(&zone->keyopts, 0);
1173	isc_time_settoepoch(&zone->expiretime);
1174	isc_time_settoepoch(&zone->refreshtime);
1175	isc_time_settoepoch(&zone->dumptime);
1176	isc_time_settoepoch(&zone->loadtime);
1177	isc_time_settoepoch(&zone->resigntime);
1178	isc_time_settoepoch(&zone->keywarntime);
1179	isc_time_settoepoch(&zone->signingtime);
1180	isc_time_settoepoch(&zone->nsec3chaintime);
1181	isc_time_settoepoch(&zone->refreshkeytime);
1182	ISC_LIST_INIT(zone->notifies);
1183	ISC_LIST_INIT(zone->checkds_requests);
1184	isc_sockaddr_any(&zone->notifysrc4);
1185	isc_sockaddr_any6(&zone->notifysrc6);
1186	isc_sockaddr_any(&zone->parentalsrc4);
1187	isc_sockaddr_any6(&zone->parentalsrc6);
1188	isc_sockaddr_any(&zone->xfrsource4);
1189	isc_sockaddr_any6(&zone->xfrsource6);
1190	isc_sockaddr_any(&zone->altxfrsource4);
1191	isc_sockaddr_any6(&zone->altxfrsource6);
1192	ISC_LINK_INIT(zone, statelink);
1193	ISC_LIST_INIT(zone->signing);
1194	ISC_LIST_INIT(zone->nsec3chain);
1195	ISC_LIST_INIT(zone->setnsec3param_queue);
1196	ISC_LIST_INIT(zone->forwards);
1197	ISC_LIST_INIT(zone->rss_events);
1198	ISC_LIST_INIT(zone->rss_post);
1199
1200	result = isc_stats_create(mctx, &zone->gluecachestats,
1201				  dns_gluecachestatscounter_max);
1202	if (result != ISC_R_SUCCESS) {
1203		goto free_refs;
1204	}
1205
1206	/* Must be after magic is set. */
1207	dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1208
1209	ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1210		       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone, NULL,
1211		       NULL);
1212	*zonep = zone;
1213	return (ISC_R_SUCCESS);
1214
1215free_refs:
1216	isc_refcount_decrement0(&zone->erefs);
1217	isc_refcount_destroy(&zone->erefs);
1218	isc_refcount_destroy(&zone->irefs);
1219	ZONEDB_DESTROYLOCK(&zone->dblock);
1220	isc_mutex_destroy(&zone->lock);
1221	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1222	return (result);
1223}
1224
1225static void
1226clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
1227	dns_dnsseckey_t *key;
1228	while (!ISC_LIST_EMPTY(*list)) {
1229		key = ISC_LIST_HEAD(*list);
1230		ISC_LIST_UNLINK(*list, key, link);
1231		dns_dnsseckey_destroy(mctx, &key);
1232	}
1233}
1234
1235/*
1236 * Free a zone.  Because we require that there be no more
1237 * outstanding events or references, no locking is necessary.
1238 */
1239static void
1240zone_free(dns_zone_t *zone) {
1241	dns_signing_t *signing;
1242	dns_nsec3chain_t *nsec3chain;
1243	isc_event_t *event;
1244	dns_include_t *include;
1245
1246	REQUIRE(DNS_ZONE_VALID(zone));
1247	isc_refcount_destroy(&zone->erefs);
1248	isc_refcount_destroy(&zone->irefs);
1249	REQUIRE(!LOCKED_ZONE(zone));
1250	REQUIRE(zone->timer == NULL);
1251	REQUIRE(zone->zmgr == NULL);
1252
1253	/*
1254	 * Managed objects.  Order is important.
1255	 */
1256	if (zone->request != NULL) {
1257		dns_request_destroy(&zone->request); /* XXXMPA */
1258	}
1259	INSIST(zone->readio == NULL);
1260	INSIST(zone->statelist == NULL);
1261	INSIST(zone->writeio == NULL);
1262	INSIST(zone->view == NULL);
1263	INSIST(zone->prev_view == NULL);
1264
1265	if (zone->task != NULL) {
1266		isc_task_detach(&zone->task);
1267	}
1268	if (zone->loadtask != NULL) {
1269		isc_task_detach(&zone->loadtask);
1270	}
1271
1272	/* Unmanaged objects */
1273	while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
1274		event = ISC_LIST_HEAD(zone->setnsec3param_queue);
1275		ISC_LIST_UNLINK(zone->setnsec3param_queue, event, ev_link);
1276		isc_event_free(&event);
1277	}
1278	while (!ISC_LIST_EMPTY(zone->rss_post)) {
1279		event = ISC_LIST_HEAD(zone->rss_post);
1280		ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
1281		isc_event_free(&event);
1282	}
1283	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
1284	     signing = ISC_LIST_HEAD(zone->signing))
1285	{
1286		ISC_LIST_UNLINK(zone->signing, signing, link);
1287		dns_db_detach(&signing->db);
1288		dns_dbiterator_destroy(&signing->dbiterator);
1289		isc_mem_put(zone->mctx, signing, sizeof *signing);
1290	}
1291	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
1292	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
1293	{
1294		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1295		dns_db_detach(&nsec3chain->db);
1296		dns_dbiterator_destroy(&nsec3chain->dbiterator);
1297		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1298	}
1299	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1300	     include = ISC_LIST_HEAD(zone->includes))
1301	{
1302		ISC_LIST_UNLINK(zone->includes, include, link);
1303		isc_mem_free(zone->mctx, include->name);
1304		isc_mem_put(zone->mctx, include, sizeof *include);
1305	}
1306	for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
1307	     include = ISC_LIST_HEAD(zone->newincludes))
1308	{
1309		ISC_LIST_UNLINK(zone->newincludes, include, link);
1310		isc_mem_free(zone->mctx, include->name);
1311		isc_mem_put(zone->mctx, include, sizeof *include);
1312	}
1313	if (zone->masterfile != NULL) {
1314		isc_mem_free(zone->mctx, zone->masterfile);
1315	}
1316	zone->masterfile = NULL;
1317	if (zone->keydirectory != NULL) {
1318		isc_mem_free(zone->mctx, zone->keydirectory);
1319	}
1320	zone->keydirectory = NULL;
1321	if (zone->kasp != NULL) {
1322		dns_kasp_detach(&zone->kasp);
1323	}
1324	if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
1325		clear_keylist(&zone->checkds_ok, zone->mctx);
1326	}
1327
1328	zone->journalsize = -1;
1329	if (zone->journal != NULL) {
1330		isc_mem_free(zone->mctx, zone->journal);
1331	}
1332	zone->journal = NULL;
1333	if (zone->stats != NULL) {
1334		isc_stats_detach(&zone->stats);
1335	}
1336	if (zone->requeststats != NULL) {
1337		isc_stats_detach(&zone->requeststats);
1338	}
1339	if (zone->rcvquerystats != NULL) {
1340		dns_stats_detach(&zone->rcvquerystats);
1341	}
1342	if (zone->dnssecsignstats != NULL) {
1343		dns_stats_detach(&zone->dnssecsignstats);
1344	}
1345	if (zone->db != NULL) {
1346		zone_detachdb(zone);
1347	}
1348	if (zone->rpzs != NULL) {
1349		REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1350		dns_rpz_detach_rpzs(&zone->rpzs);
1351		zone->rpz_num = DNS_RPZ_INVALID_NUM;
1352	}
1353	if (zone->catzs != NULL) {
1354		dns_catz_catzs_detach(&zone->catzs);
1355	}
1356	zone_freedbargs(zone);
1357
1358	RUNTIME_CHECK(dns_zone_setparentals(zone, NULL, NULL, 0) ==
1359		      ISC_R_SUCCESS);
1360	RUNTIME_CHECK(dns_zone_setprimarieswithkeys(zone, NULL, NULL, 0) ==
1361		      ISC_R_SUCCESS);
1362	RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
1363	zone->check_names = dns_severity_ignore;
1364	if (zone->update_acl != NULL) {
1365		dns_acl_detach(&zone->update_acl);
1366	}
1367	if (zone->forward_acl != NULL) {
1368		dns_acl_detach(&zone->forward_acl);
1369	}
1370	if (zone->notify_acl != NULL) {
1371		dns_acl_detach(&zone->notify_acl);
1372	}
1373	if (zone->query_acl != NULL) {
1374		dns_acl_detach(&zone->query_acl);
1375	}
1376	if (zone->queryon_acl != NULL) {
1377		dns_acl_detach(&zone->queryon_acl);
1378	}
1379	if (zone->xfr_acl != NULL) {
1380		dns_acl_detach(&zone->xfr_acl);
1381	}
1382	if (dns_name_dynamic(&zone->origin)) {
1383		dns_name_free(&zone->origin, zone->mctx);
1384	}
1385	if (zone->strnamerd != NULL) {
1386		isc_mem_free(zone->mctx, zone->strnamerd);
1387	}
1388	if (zone->strname != NULL) {
1389		isc_mem_free(zone->mctx, zone->strname);
1390	}
1391	if (zone->strrdclass != NULL) {
1392		isc_mem_free(zone->mctx, zone->strrdclass);
1393	}
1394	if (zone->strviewname != NULL) {
1395		isc_mem_free(zone->mctx, zone->strviewname);
1396	}
1397	if (zone->ssutable != NULL) {
1398		dns_ssutable_detach(&zone->ssutable);
1399	}
1400	if (zone->gluecachestats != NULL) {
1401		isc_stats_detach(&zone->gluecachestats);
1402	}
1403
1404	/* last stuff */
1405	ZONEDB_DESTROYLOCK(&zone->dblock);
1406	isc_mutex_destroy(&zone->lock);
1407	zone->magic = 0;
1408	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1409}
1410
1411/*
1412 * Returns true iff this the signed side of an inline-signing zone.
1413 * Caller should hold zone lock.
1414 */
1415static bool
1416inline_secure(dns_zone_t *zone) {
1417	REQUIRE(DNS_ZONE_VALID(zone));
1418	if (zone->raw != NULL) {
1419		return (true);
1420	}
1421	return (false);
1422}
1423
1424/*
1425 * Returns true iff this the unsigned side of an inline-signing zone
1426 * Caller should hold zone lock.
1427 */
1428static bool
1429inline_raw(dns_zone_t *zone) {
1430	REQUIRE(DNS_ZONE_VALID(zone));
1431	if (zone->secure != NULL) {
1432		return (true);
1433	}
1434	return (false);
1435}
1436
1437/*
1438 *	Single shot.
1439 */
1440void
1441dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1442	char namebuf[1024];
1443
1444	REQUIRE(DNS_ZONE_VALID(zone));
1445	REQUIRE(rdclass != dns_rdataclass_none);
1446
1447	/*
1448	 * Test and set.
1449	 */
1450	LOCK_ZONE(zone);
1451	INSIST(zone != zone->raw);
1452	REQUIRE(zone->rdclass == dns_rdataclass_none ||
1453		zone->rdclass == rdclass);
1454	zone->rdclass = rdclass;
1455
1456	if (zone->strnamerd != NULL) {
1457		isc_mem_free(zone->mctx, zone->strnamerd);
1458	}
1459	if (zone->strrdclass != NULL) {
1460		isc_mem_free(zone->mctx, zone->strrdclass);
1461	}
1462
1463	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1464	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1465	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1466	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1467
1468	if (inline_secure(zone)) {
1469		dns_zone_setclass(zone->raw, rdclass);
1470	}
1471	UNLOCK_ZONE(zone);
1472}
1473
1474dns_rdataclass_t
1475dns_zone_getclass(dns_zone_t *zone) {
1476	REQUIRE(DNS_ZONE_VALID(zone));
1477
1478	return (zone->rdclass);
1479}
1480
1481void
1482dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1483	REQUIRE(DNS_ZONE_VALID(zone));
1484
1485	LOCK_ZONE(zone);
1486	zone->notifytype = notifytype;
1487	UNLOCK_ZONE(zone);
1488}
1489
1490isc_result_t
1491dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1492	isc_result_t result;
1493	unsigned int soacount;
1494
1495	REQUIRE(DNS_ZONE_VALID(zone));
1496	REQUIRE(serialp != NULL);
1497
1498	LOCK_ZONE(zone);
1499	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1500	if (zone->db != NULL) {
1501		result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
1502					  serialp, NULL, NULL, NULL, NULL,
1503					  NULL);
1504		if (result == ISC_R_SUCCESS && soacount == 0) {
1505			result = ISC_R_FAILURE;
1506		}
1507	} else {
1508		result = DNS_R_NOTLOADED;
1509	}
1510	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1511	UNLOCK_ZONE(zone);
1512
1513	return (result);
1514}
1515
1516/*
1517 *	Single shot.
1518 */
1519void
1520dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1521	char namebuf[1024];
1522
1523	REQUIRE(DNS_ZONE_VALID(zone));
1524	REQUIRE(type != dns_zone_none);
1525
1526	/*
1527	 * Test and set.
1528	 */
1529	LOCK_ZONE(zone);
1530	REQUIRE(zone->type == dns_zone_none || zone->type == type);
1531	zone->type = type;
1532
1533	if (zone->strnamerd != NULL) {
1534		isc_mem_free(zone->mctx, zone->strnamerd);
1535	}
1536
1537	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1538	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1539	UNLOCK_ZONE(zone);
1540}
1541
1542static void
1543zone_freedbargs(dns_zone_t *zone) {
1544	unsigned int i;
1545
1546	/* Free the old database argument list. */
1547	if (zone->db_argv != NULL) {
1548		for (i = 0; i < zone->db_argc; i++) {
1549			isc_mem_free(zone->mctx, zone->db_argv[i]);
1550		}
1551		isc_mem_put(zone->mctx, zone->db_argv,
1552			    zone->db_argc * sizeof(*zone->db_argv));
1553	}
1554	zone->db_argc = 0;
1555	zone->db_argv = NULL;
1556}
1557
1558isc_result_t
1559dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1560	size_t size = 0;
1561	unsigned int i;
1562	isc_result_t result = ISC_R_SUCCESS;
1563	void *mem;
1564	char **tmp, *tmp2, *base;
1565
1566	REQUIRE(DNS_ZONE_VALID(zone));
1567	REQUIRE(argv != NULL && *argv == NULL);
1568
1569	LOCK_ZONE(zone);
1570	size = (zone->db_argc + 1) * sizeof(char *);
1571	for (i = 0; i < zone->db_argc; i++) {
1572		size += strlen(zone->db_argv[i]) + 1;
1573	}
1574	mem = isc_mem_allocate(mctx, size);
1575	{
1576		tmp = mem;
1577		tmp2 = mem;
1578		base = mem;
1579		tmp2 += (zone->db_argc + 1) * sizeof(char *);
1580		for (i = 0; i < zone->db_argc; i++) {
1581			*tmp++ = tmp2;
1582			strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1583			tmp2 += strlen(tmp2) + 1;
1584		}
1585		*tmp = NULL;
1586	}
1587	UNLOCK_ZONE(zone);
1588	*argv = mem;
1589	return (result);
1590}
1591
1592void
1593dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
1594		   const char *const *dbargv) {
1595	char **argv = NULL;
1596	unsigned int i;
1597
1598	REQUIRE(DNS_ZONE_VALID(zone));
1599	REQUIRE(dbargc >= 1);
1600	REQUIRE(dbargv != NULL);
1601
1602	LOCK_ZONE(zone);
1603
1604	/* Set up a new database argument list. */
1605	argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1606	for (i = 0; i < dbargc; i++) {
1607		argv[i] = NULL;
1608	}
1609	for (i = 0; i < dbargc; i++) {
1610		argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1611	}
1612
1613	/* Free the old list. */
1614	zone_freedbargs(zone);
1615
1616	zone->db_argc = dbargc;
1617	zone->db_argv = argv;
1618
1619	UNLOCK_ZONE(zone);
1620}
1621
1622static void
1623dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1624	char namebuf[1024];
1625
1626	if (zone->prev_view == NULL && zone->view != NULL) {
1627		dns_view_weakattach(zone->view, &zone->prev_view);
1628	}
1629
1630	INSIST(zone != zone->raw);
1631	if (zone->view != NULL) {
1632		dns_view_weakdetach(&zone->view);
1633	}
1634	dns_view_weakattach(view, &zone->view);
1635
1636	if (zone->strviewname != NULL) {
1637		isc_mem_free(zone->mctx, zone->strviewname);
1638	}
1639	if (zone->strnamerd != NULL) {
1640		isc_mem_free(zone->mctx, zone->strnamerd);
1641	}
1642
1643	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1644	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1645	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1646	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1647
1648	if (inline_secure(zone)) {
1649		dns_zone_setview(zone->raw, view);
1650	}
1651}
1652
1653void
1654dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1655	REQUIRE(DNS_ZONE_VALID(zone));
1656
1657	LOCK_ZONE(zone);
1658	dns_zone_setview_helper(zone, view);
1659	UNLOCK_ZONE(zone);
1660}
1661
1662dns_view_t *
1663dns_zone_getview(dns_zone_t *zone) {
1664	REQUIRE(DNS_ZONE_VALID(zone));
1665
1666	return (zone->view);
1667}
1668
1669void
1670dns_zone_setviewcommit(dns_zone_t *zone) {
1671	REQUIRE(DNS_ZONE_VALID(zone));
1672
1673	LOCK_ZONE(zone);
1674	if (zone->prev_view != NULL) {
1675		dns_view_weakdetach(&zone->prev_view);
1676	}
1677	if (inline_secure(zone)) {
1678		dns_zone_setviewcommit(zone->raw);
1679	}
1680	UNLOCK_ZONE(zone);
1681}
1682
1683void
1684dns_zone_setviewrevert(dns_zone_t *zone) {
1685	REQUIRE(DNS_ZONE_VALID(zone));
1686
1687	LOCK_ZONE(zone);
1688	if (zone->prev_view != NULL) {
1689		dns_zone_setview_helper(zone, zone->prev_view);
1690		dns_view_weakdetach(&zone->prev_view);
1691	}
1692	if (zone->catzs != NULL) {
1693		zone_catz_enable(zone, zone->catzs);
1694	}
1695	if (inline_secure(zone)) {
1696		dns_zone_setviewrevert(zone->raw);
1697	}
1698	UNLOCK_ZONE(zone);
1699}
1700
1701isc_result_t
1702dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1703	isc_result_t result = ISC_R_SUCCESS;
1704	char namebuf[1024];
1705
1706	REQUIRE(DNS_ZONE_VALID(zone));
1707	REQUIRE(origin != NULL);
1708
1709	LOCK_ZONE(zone);
1710	INSIST(zone != zone->raw);
1711	if (dns_name_dynamic(&zone->origin)) {
1712		dns_name_free(&zone->origin, zone->mctx);
1713		dns_name_init(&zone->origin, NULL);
1714	}
1715	dns_name_dup(origin, zone->mctx, &zone->origin);
1716
1717	if (zone->strnamerd != NULL) {
1718		isc_mem_free(zone->mctx, zone->strnamerd);
1719	}
1720	if (zone->strname != NULL) {
1721		isc_mem_free(zone->mctx, zone->strname);
1722	}
1723
1724	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1725	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1726	zone_name_tostr(zone, namebuf, sizeof namebuf);
1727	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1728
1729	if (inline_secure(zone)) {
1730		result = dns_zone_setorigin(zone->raw, origin);
1731	}
1732	UNLOCK_ZONE(zone);
1733	return (result);
1734}
1735
1736static isc_result_t
1737dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1738	char *copy;
1739
1740	if (value != NULL) {
1741		copy = isc_mem_strdup(zone->mctx, value);
1742	} else {
1743		copy = NULL;
1744	}
1745
1746	if (*field != NULL) {
1747		isc_mem_free(zone->mctx, *field);
1748	}
1749
1750	*field = copy;
1751	return (ISC_R_SUCCESS);
1752}
1753
1754isc_result_t
1755dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
1756		 const dns_master_style_t *style) {
1757	isc_result_t result = ISC_R_SUCCESS;
1758
1759	REQUIRE(DNS_ZONE_VALID(zone));
1760
1761	LOCK_ZONE(zone);
1762	result = dns_zone_setstring(zone, &zone->masterfile, file);
1763	if (result == ISC_R_SUCCESS) {
1764		zone->masterformat = format;
1765		if (format == dns_masterformat_text) {
1766			zone->masterstyle = style;
1767		}
1768		result = default_journal(zone);
1769	}
1770	UNLOCK_ZONE(zone);
1771
1772	return (result);
1773}
1774
1775const char *
1776dns_zone_getfile(dns_zone_t *zone) {
1777	REQUIRE(DNS_ZONE_VALID(zone));
1778
1779	return (zone->masterfile);
1780}
1781
1782dns_ttl_t
1783dns_zone_getmaxttl(dns_zone_t *zone) {
1784	REQUIRE(DNS_ZONE_VALID(zone));
1785
1786	return (zone->maxttl);
1787}
1788
1789void
1790dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1791	REQUIRE(DNS_ZONE_VALID(zone));
1792
1793	LOCK_ZONE(zone);
1794	if (maxttl != 0) {
1795		DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
1796	} else {
1797		DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
1798	}
1799	zone->maxttl = maxttl;
1800	UNLOCK_ZONE(zone);
1801
1802	return;
1803}
1804
1805static isc_result_t
1806default_journal(dns_zone_t *zone) {
1807	isc_result_t result;
1808	char *journal;
1809
1810	REQUIRE(DNS_ZONE_VALID(zone));
1811	REQUIRE(LOCKED_ZONE(zone));
1812
1813	if (zone->masterfile != NULL) {
1814		/* Calculate string length including '\0'. */
1815		int len = strlen(zone->masterfile) + sizeof(".jnl");
1816		journal = isc_mem_allocate(zone->mctx, len);
1817		strlcpy(journal, zone->masterfile, len);
1818		strlcat(journal, ".jnl", len);
1819	} else {
1820		journal = NULL;
1821	}
1822	result = dns_zone_setstring(zone, &zone->journal, journal);
1823	if (journal != NULL) {
1824		isc_mem_free(zone->mctx, journal);
1825	}
1826	return (result);
1827}
1828
1829isc_result_t
1830dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1831	isc_result_t result = ISC_R_SUCCESS;
1832
1833	REQUIRE(DNS_ZONE_VALID(zone));
1834
1835	LOCK_ZONE(zone);
1836	result = dns_zone_setstring(zone, &zone->journal, myjournal);
1837	UNLOCK_ZONE(zone);
1838
1839	return (result);
1840}
1841
1842char *
1843dns_zone_getjournal(dns_zone_t *zone) {
1844	REQUIRE(DNS_ZONE_VALID(zone));
1845
1846	return (zone->journal);
1847}
1848
1849/*
1850 * Return true iff the zone is "dynamic", in the sense that the zone's
1851 * master file (if any) is written by the server, rather than being
1852 * updated manually and read by the server.
1853 *
1854 * This is true for slave zones, mirror zones, stub zones, key zones,
1855 * and zones that allow dynamic updates either by having an update
1856 * policy ("ssutable") or an "allow-update" ACL with a value other than
1857 * exactly "{ none; }".
1858 */
1859bool
1860dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1861	REQUIRE(DNS_ZONE_VALID(zone));
1862
1863	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
1864	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1865	    (zone->type == dns_zone_redirect && zone->masters != NULL))
1866	{
1867		return (true);
1868	}
1869
1870	/* Inline zones are always dynamic. */
1871	if (zone->type == dns_zone_primary && zone->raw != NULL) {
1872		return (true);
1873	}
1874
1875	/* If !ignore_freeze, we need check whether updates are disabled.  */
1876	if (zone->type == dns_zone_primary &&
1877	    (!zone->update_disabled || ignore_freeze) &&
1878	    ((zone->ssutable != NULL) ||
1879	     (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1880	{
1881		return (true);
1882	}
1883
1884	return (false);
1885}
1886
1887/*
1888 * Set the response policy index and information for a zone.
1889 */
1890isc_result_t
1891dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1892		    dns_rpz_num_t rpz_num) {
1893	/*
1894	 * Only RBTDB zones can be used for response policy zones,
1895	 * because only they have the code to create the summary data.
1896	 * Only zones that are loaded instead of mmap()ed create the
1897	 * summary data and so can be policy zones.
1898	 */
1899	if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1900	    strcmp(zone->db_argv[0], "rbt64") != 0)
1901	{
1902		return (ISC_R_NOTIMPLEMENTED);
1903	}
1904	if (zone->masterformat == dns_masterformat_map) {
1905		return (ISC_R_NOTIMPLEMENTED);
1906	}
1907
1908	/*
1909	 * This must happen only once or be redundant.
1910	 */
1911	LOCK_ZONE(zone);
1912	if (zone->rpzs != NULL) {
1913		REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1914	} else {
1915		REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1916		dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1917		zone->rpz_num = rpz_num;
1918	}
1919	rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1920	UNLOCK_ZONE(zone);
1921
1922	return (ISC_R_SUCCESS);
1923}
1924
1925dns_rpz_num_t
1926dns_zone_get_rpz_num(dns_zone_t *zone) {
1927	return (zone->rpz_num);
1928}
1929
1930/*
1931 * If a zone is a response policy zone, mark its new database.
1932 */
1933void
1934dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1935	isc_result_t result;
1936	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1937		return;
1938	}
1939	REQUIRE(zone->rpzs != NULL);
1940	result = dns_db_updatenotify_register(db, dns_rpz_dbupdate_callback,
1941					      zone->rpzs->zones[zone->rpz_num]);
1942	REQUIRE(result == ISC_R_SUCCESS);
1943}
1944
1945static void
1946dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1947	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1948		return;
1949	}
1950	REQUIRE(zone->rpzs != NULL);
1951	(void)dns_db_updatenotify_unregister(db, dns_rpz_dbupdate_callback,
1952					     zone->rpzs->zones[zone->rpz_num]);
1953}
1954
1955/*
1956 * If a zone is a catalog zone, attach it to update notification in database.
1957 */
1958void
1959dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1960	REQUIRE(DNS_ZONE_VALID(zone));
1961	REQUIRE(db != NULL);
1962
1963	if (zone->catzs != NULL) {
1964		dns_db_updatenotify_register(db, dns_catz_dbupdate_callback,
1965					     zone->catzs);
1966	}
1967}
1968
1969static void
1970dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1971	REQUIRE(DNS_ZONE_VALID(zone));
1972	REQUIRE(db != NULL);
1973
1974	if (zone->catzs != NULL) {
1975		dns_db_updatenotify_unregister(db, dns_catz_dbupdate_callback,
1976					       zone->catzs);
1977	}
1978}
1979
1980static void
1981zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1982	REQUIRE(DNS_ZONE_VALID(zone));
1983	REQUIRE(catzs != NULL);
1984
1985	INSIST(zone->catzs == NULL || zone->catzs == catzs);
1986	dns_catz_catzs_set_view(catzs, zone->view);
1987	if (zone->catzs == NULL) {
1988		dns_catz_catzs_attach(catzs, &zone->catzs);
1989	}
1990}
1991
1992void
1993dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1994	REQUIRE(DNS_ZONE_VALID(zone));
1995
1996	LOCK_ZONE(zone);
1997	zone_catz_enable(zone, catzs);
1998	UNLOCK_ZONE(zone);
1999}
2000
2001static void
2002zone_catz_disable(dns_zone_t *zone) {
2003	REQUIRE(DNS_ZONE_VALID(zone));
2004
2005	if (zone->catzs != NULL) {
2006		if (zone->db != NULL) {
2007			dns_zone_catz_disable_db(zone, zone->db);
2008		}
2009		dns_catz_catzs_detach(&zone->catzs);
2010	}
2011}
2012
2013void
2014dns_zone_catz_disable(dns_zone_t *zone) {
2015	REQUIRE(DNS_ZONE_VALID(zone));
2016
2017	LOCK_ZONE(zone);
2018	zone_catz_disable(zone);
2019	UNLOCK_ZONE(zone);
2020}
2021
2022bool
2023dns_zone_catz_is_enabled(dns_zone_t *zone) {
2024	REQUIRE(DNS_ZONE_VALID(zone));
2025
2026	return (zone->catzs != NULL);
2027}
2028
2029/*
2030 * Set catalog zone ownership of the zone
2031 */
2032void
2033dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
2034	REQUIRE(DNS_ZONE_VALID(zone));
2035	REQUIRE(catz != NULL);
2036	LOCK_ZONE(zone);
2037	INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
2038	zone->parentcatz = catz;
2039	UNLOCK_ZONE(zone);
2040}
2041
2042dns_catz_zone_t *
2043dns_zone_get_parentcatz(const dns_zone_t *zone) {
2044	REQUIRE(DNS_ZONE_VALID(zone));
2045	return (zone->parentcatz);
2046}
2047
2048static bool
2049zone_touched(dns_zone_t *zone) {
2050	isc_result_t result;
2051	isc_time_t modtime;
2052	dns_include_t *include;
2053
2054	REQUIRE(DNS_ZONE_VALID(zone));
2055
2056	result = isc_file_getmodtime(zone->masterfile, &modtime);
2057	if (result != ISC_R_SUCCESS ||
2058	    isc_time_compare(&modtime, &zone->loadtime) > 0)
2059	{
2060		return (true);
2061	}
2062
2063	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
2064	     include = ISC_LIST_NEXT(include, link))
2065	{
2066		result = isc_file_getmodtime(include->name, &modtime);
2067		if (result != ISC_R_SUCCESS ||
2068		    isc_time_compare(&modtime, &include->filetime) > 0)
2069		{
2070			return (true);
2071		}
2072	}
2073
2074	return (false);
2075}
2076
2077/*
2078 * Note: when dealing with inline-signed zones, external callers will always
2079 * call zone_load() for the secure zone; zone_load() calls itself recursively
2080 * in order to load the raw zone.
2081 */
2082static isc_result_t
2083zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
2084	isc_result_t result;
2085	isc_time_t now;
2086	isc_time_t loadtime;
2087	dns_db_t *db = NULL;
2088	bool rbt, hasraw, is_dynamic;
2089
2090	REQUIRE(DNS_ZONE_VALID(zone));
2091
2092	if (!locked) {
2093		LOCK_ZONE(zone);
2094	}
2095
2096	INSIST(zone != zone->raw);
2097	hasraw = inline_secure(zone);
2098	if (hasraw) {
2099		/*
2100		 * We are trying to load an inline-signed zone.  First call
2101		 * self recursively to try loading the raw version of the zone.
2102		 * Assuming the raw zone file is readable, there are two
2103		 * possibilities:
2104		 *
2105		 *  a) the raw zone was not yet loaded and thus it will be
2106		 *     loaded now, synchronously; if this succeeds, a
2107		 *     subsequent attempt to load the signed zone file will
2108		 *     take place and thus zone_postload() will be called
2109		 *     twice: first for the raw zone and then for the secure
2110		 *     zone; the latter call will take care of syncing the raw
2111		 *     version with the secure version,
2112		 *
2113		 *  b) the raw zone was already loaded and we are trying to
2114		 *     reload it, which will happen asynchronously; this means
2115		 *     zone_postload() will only be called for the raw zone
2116		 *     because "result" returned by the zone_load() call below
2117		 *     will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
2118		 *     zone_postload() called for the raw zone will take care
2119		 *     of syncing the raw version with the secure version.
2120		 */
2121		result = zone_load(zone->raw, flags, false);
2122		if (result != ISC_R_SUCCESS) {
2123			if (!locked) {
2124				UNLOCK_ZONE(zone);
2125			}
2126			return (result);
2127		}
2128		LOCK_ZONE(zone->raw);
2129	}
2130
2131	TIME_NOW(&now);
2132
2133	INSIST(zone->type != dns_zone_none);
2134
2135	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
2136		if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2137			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2138		}
2139		result = DNS_R_CONTINUE;
2140		goto cleanup;
2141	}
2142
2143	INSIST(zone->db_argc >= 1);
2144
2145	rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
2146	      strcmp(zone->db_argv[0], "rbt64") == 0;
2147
2148	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
2149		/*
2150		 * The zone has no master file configured.
2151		 */
2152		result = ISC_R_SUCCESS;
2153		goto cleanup;
2154	}
2155
2156	is_dynamic = dns_zone_isdynamic(zone, false);
2157	if (zone->db != NULL && is_dynamic) {
2158		/*
2159		 * This is a slave, stub, or dynamically updated zone being
2160		 * reloaded.  Do nothing - the database we already
2161		 * have is guaranteed to be up-to-date.
2162		 */
2163		if (zone->type == dns_zone_primary && !hasraw) {
2164			result = DNS_R_DYNAMIC;
2165		} else {
2166			result = ISC_R_SUCCESS;
2167		}
2168		goto cleanup;
2169	}
2170
2171	/*
2172	 * Store the current time before the zone is loaded, so that if the
2173	 * file changes between the time of the load and the time that
2174	 * zone->loadtime is set, then the file will still be reloaded
2175	 * the next time dns_zone_load is called.
2176	 */
2177	TIME_NOW(&loadtime);
2178
2179	/*
2180	 * Don't do the load if the file that stores the zone is older
2181	 * than the last time the zone was loaded.  If the zone has not
2182	 * been loaded yet, zone->loadtime will be the epoch.
2183	 */
2184	if (zone->masterfile != NULL) {
2185		isc_time_t filetime;
2186
2187		/*
2188		 * The file is already loaded.	If we are just doing a
2189		 * "rndc reconfig", we are done.
2190		 */
2191		if (!isc_time_isepoch(&zone->loadtime) &&
2192		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
2193		{
2194			result = ISC_R_SUCCESS;
2195			goto cleanup;
2196		}
2197
2198		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2199		    !zone_touched(zone))
2200		{
2201			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2202				      ISC_LOG_DEBUG(1),
2203				      "skipping load: master file "
2204				      "older than last load");
2205			result = DNS_R_UPTODATE;
2206			goto cleanup;
2207		}
2208
2209		/*
2210		 * If the file modification time is in the past
2211		 * set loadtime to that value.
2212		 */
2213		result = isc_file_getmodtime(zone->masterfile, &filetime);
2214		if (result == ISC_R_SUCCESS &&
2215		    isc_time_compare(&loadtime, &filetime) > 0)
2216		{
2217			loadtime = filetime;
2218		}
2219	}
2220
2221	/*
2222	 * Built in zones (with the exception of empty zones) don't need
2223	 * to be reloaded.
2224	 */
2225	if (zone->type == dns_zone_primary &&
2226	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
2227	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2228	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2229	{
2230		result = ISC_R_SUCCESS;
2231		goto cleanup;
2232	}
2233
2234	/*
2235	 * Zones associated with a DLZ don't need to be loaded either,
2236	 * but we need to associate the database with the zone object.
2237	 */
2238	if (strcmp(zone->db_argv[0], "dlz") == 0) {
2239		dns_dlzdb_t *dlzdb;
2240		dns_dlzfindzone_t findzone;
2241
2242		for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2243		     dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
2244		{
2245			INSIST(DNS_DLZ_VALID(dlzdb));
2246			if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
2247				break;
2248			}
2249		}
2250
2251		if (dlzdb == NULL) {
2252			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2253				      ISC_LOG_ERROR,
2254				      "DLZ %s does not exist or is set "
2255				      "to 'search yes;'",
2256				      zone->db_argv[1]);
2257			result = ISC_R_NOTFOUND;
2258			goto cleanup;
2259		}
2260
2261		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2262		/* ask SDLZ driver if the zone is supported */
2263		findzone = dlzdb->implementation->methods->findzone;
2264		result = (*findzone)(dlzdb->implementation->driverarg,
2265				     dlzdb->dbdata, dlzdb->mctx,
2266				     zone->view->rdclass, &zone->origin, NULL,
2267				     NULL, &db);
2268		if (result != ISC_R_NOTFOUND) {
2269			if (zone->db != NULL) {
2270				zone_detachdb(zone);
2271			}
2272			zone_attachdb(zone, db);
2273			dns_db_detach(&db);
2274			result = ISC_R_SUCCESS;
2275		}
2276		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2277
2278		if (result == ISC_R_SUCCESS) {
2279			if (dlzdb->configure_callback == NULL) {
2280				goto cleanup;
2281			}
2282
2283			result = (*dlzdb->configure_callback)(zone->view, dlzdb,
2284							      zone);
2285			if (result != ISC_R_SUCCESS) {
2286				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2287					      ISC_LOG_ERROR,
2288					      "DLZ configuration callback: %s",
2289					      isc_result_totext(result));
2290			}
2291		}
2292		goto cleanup;
2293	}
2294
2295	if ((zone->type == dns_zone_secondary ||
2296	     zone->type == dns_zone_mirror || zone->type == dns_zone_stub ||
2297	     (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
2298	    rbt)
2299	{
2300		if (zone->masterfile == NULL ||
2301		    !isc_file_exists(zone->masterfile))
2302		{
2303			if (zone->masterfile != NULL) {
2304				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2305					      ISC_LOG_DEBUG(1),
2306					      "no master file");
2307			}
2308			zone->refreshtime = now;
2309			if (zone->task != NULL) {
2310				zone_settimer(zone, &now);
2311			}
2312			result = ISC_R_SUCCESS;
2313			goto cleanup;
2314		}
2315	}
2316
2317	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
2318		      "starting load");
2319
2320	result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
2321			       (zone->type == dns_zone_stub) ? dns_dbtype_stub
2322							     : dns_dbtype_zone,
2323			       zone->rdclass, zone->db_argc - 1,
2324			       zone->db_argv + 1, &db);
2325
2326	if (result != ISC_R_SUCCESS) {
2327		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2328			      "loading zone: creating database: %s",
2329			      isc_result_totext(result));
2330		goto cleanup;
2331	}
2332	dns_db_settask(db, zone->task);
2333
2334	if (zone->type == dns_zone_primary ||
2335	    zone->type == dns_zone_secondary || zone->type == dns_zone_mirror)
2336	{
2337		result = dns_db_setgluecachestats(db, zone->gluecachestats);
2338		if (result == ISC_R_NOTIMPLEMENTED) {
2339			result = ISC_R_SUCCESS;
2340		}
2341		if (result != ISC_R_SUCCESS) {
2342			goto cleanup;
2343		}
2344	}
2345
2346	if (!dns_db_ispersistent(db)) {
2347		if (zone->masterfile != NULL) {
2348			result = zone_startload(db, zone, loadtime);
2349		} else {
2350			result = DNS_R_NOMASTERFILE;
2351			if (zone->type == dns_zone_primary ||
2352			    (zone->type == dns_zone_redirect &&
2353			     zone->masters == NULL))
2354			{
2355				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2356					      ISC_LOG_ERROR,
2357					      "loading zone: "
2358					      "no master file configured");
2359				goto cleanup;
2360			}
2361			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2362				      ISC_LOG_INFO,
2363				      "loading zone: "
2364				      "no master file configured: continuing");
2365		}
2366	}
2367
2368	if (result == DNS_R_CONTINUE) {
2369		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2370		if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2371			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2372		}
2373		goto cleanup;
2374	}
2375
2376	result = zone_postload(zone, db, loadtime, result);
2377
2378cleanup:
2379	if (hasraw) {
2380		UNLOCK_ZONE(zone->raw);
2381	}
2382	if (!locked) {
2383		UNLOCK_ZONE(zone);
2384	}
2385	if (db != NULL) {
2386		dns_db_detach(&db);
2387	}
2388	return (result);
2389}
2390
2391isc_result_t
2392dns_zone_load(dns_zone_t *zone, bool newonly) {
2393	return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2394}
2395
2396static void
2397zone_asyncload(isc_task_t *task, isc_event_t *event) {
2398	dns_asyncload_t *asl = event->ev_arg;
2399	dns_zone_t *zone = asl->zone;
2400	isc_result_t result;
2401
2402	UNUSED(task);
2403
2404	REQUIRE(DNS_ZONE_VALID(zone));
2405
2406	isc_event_free(&event);
2407
2408	LOCK_ZONE(zone);
2409	result = zone_load(zone, asl->flags, true);
2410	if (result != DNS_R_CONTINUE) {
2411		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2412	}
2413	UNLOCK_ZONE(zone);
2414
2415	/* Inform the zone table we've finished loading */
2416	if (asl->loaded != NULL) {
2417		(asl->loaded)(asl->loaded_arg, zone, task);
2418	}
2419
2420	/* Reduce the quantum */
2421	isc_task_setquantum(zone->loadtask, 1);
2422
2423	isc_mem_put(zone->mctx, asl, sizeof(*asl));
2424	dns_zone_idetach(&zone);
2425}
2426
2427isc_result_t
2428dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_zoneloaded_t done,
2429		   void *arg) {
2430	isc_event_t *e;
2431	dns_asyncload_t *asl = NULL;
2432
2433	REQUIRE(DNS_ZONE_VALID(zone));
2434
2435	if (zone->zmgr == NULL) {
2436		return (ISC_R_FAILURE);
2437	}
2438
2439	/* If we already have a load pending, stop now */
2440	LOCK_ZONE(zone);
2441	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2442		UNLOCK_ZONE(zone);
2443		return (ISC_R_ALREADYRUNNING);
2444	}
2445
2446	asl = isc_mem_get(zone->mctx, sizeof(*asl));
2447
2448	asl->zone = NULL;
2449	asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2450	asl->loaded = done;
2451	asl->loaded_arg = arg;
2452
2453	e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr, DNS_EVENT_ZONELOAD,
2454			       zone_asyncload, asl, sizeof(isc_event_t));
2455
2456	zone_iattach(zone, &asl->zone);
2457	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2458	isc_task_send(zone->loadtask, &e);
2459	UNLOCK_ZONE(zone);
2460
2461	return (ISC_R_SUCCESS);
2462}
2463
2464bool
2465dns__zone_loadpending(dns_zone_t *zone) {
2466	REQUIRE(DNS_ZONE_VALID(zone));
2467
2468	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2469}
2470
2471isc_result_t
2472dns_zone_loadandthaw(dns_zone_t *zone) {
2473	isc_result_t result;
2474
2475	if (inline_raw(zone)) {
2476		result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
2477	} else {
2478		/*
2479		 * When thawing a zone, we don't know what changes
2480		 * have been made. If we do DNSSEC maintenance on this
2481		 * zone, schedule a full sign for this zone.
2482		 */
2483		if (zone->type == dns_zone_primary &&
2484		    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
2485		{
2486			DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
2487		}
2488		result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2489	}
2490
2491	switch (result) {
2492	case DNS_R_CONTINUE:
2493		/* Deferred thaw. */
2494		break;
2495	case DNS_R_UPTODATE:
2496	case ISC_R_SUCCESS:
2497	case DNS_R_SEENINCLUDE:
2498		zone->update_disabled = false;
2499		break;
2500	case DNS_R_NOMASTERFILE:
2501		zone->update_disabled = false;
2502		break;
2503	default:
2504		/* Error, remain in disabled state. */
2505		break;
2506	}
2507	return (result);
2508}
2509
2510static unsigned int
2511get_master_options(dns_zone_t *zone) {
2512	unsigned int options;
2513
2514	options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2515	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
2516	    (zone->type == dns_zone_redirect && zone->masters == NULL))
2517	{
2518		options |= DNS_MASTER_SLAVE;
2519	}
2520	if (zone->type == dns_zone_key) {
2521		options |= DNS_MASTER_KEY;
2522	}
2523	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2524		options |= DNS_MASTER_CHECKNS;
2525	}
2526	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2527		options |= DNS_MASTER_FATALNS;
2528	}
2529	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2530		options |= DNS_MASTER_CHECKNAMES;
2531	}
2532	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2533		options |= DNS_MASTER_CHECKNAMESFAIL;
2534	}
2535	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2536		options |= DNS_MASTER_CHECKMX;
2537	}
2538	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2539		options |= DNS_MASTER_CHECKMXFAIL;
2540	}
2541	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2542		options |= DNS_MASTER_CHECKWILDCARD;
2543	}
2544	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2545		options |= DNS_MASTER_CHECKTTL;
2546	}
2547
2548	return (options);
2549}
2550
2551static void
2552zone_registerinclude(const char *filename, void *arg) {
2553	isc_result_t result;
2554	dns_zone_t *zone = (dns_zone_t *)arg;
2555	dns_include_t *inc = NULL;
2556
2557	REQUIRE(DNS_ZONE_VALID(zone));
2558
2559	if (filename == NULL) {
2560		return;
2561	}
2562
2563	/*
2564	 * Suppress duplicates.
2565	 */
2566	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
2567	     inc = ISC_LIST_NEXT(inc, link))
2568	{
2569		if (strcmp(filename, inc->name) == 0) {
2570			return;
2571		}
2572	}
2573
2574	inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2575	inc->name = isc_mem_strdup(zone->mctx, filename);
2576	ISC_LINK_INIT(inc, link);
2577
2578	result = isc_file_getmodtime(filename, &inc->filetime);
2579	if (result != ISC_R_SUCCESS) {
2580		isc_time_settoepoch(&inc->filetime);
2581	}
2582
2583	ISC_LIST_APPEND(zone->newincludes, inc, link);
2584}
2585
2586static void
2587zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2588	dns_load_t *load = event->ev_arg;
2589	isc_result_t result = ISC_R_SUCCESS;
2590	unsigned int options;
2591
2592	REQUIRE(DNS_LOAD_VALID(load));
2593
2594	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2595		result = ISC_R_CANCELED;
2596	}
2597	isc_event_free(&event);
2598	if (result == ISC_R_CANCELED) {
2599		goto fail;
2600	}
2601
2602	options = get_master_options(load->zone);
2603
2604	result = dns_master_loadfileinc(
2605		load->zone->masterfile, dns_db_origin(load->db),
2606		dns_db_origin(load->db), load->zone->rdclass, options, 0,
2607		&load->callbacks, task, zone_loaddone, load, &load->zone->lctx,
2608		zone_registerinclude, load->zone, load->zone->mctx,
2609		load->zone->masterformat, load->zone->maxttl);
2610	if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2611	    result != DNS_R_SEENINCLUDE)
2612	{
2613		goto fail;
2614	}
2615	return;
2616
2617fail:
2618	zone_loaddone(load, result);
2619}
2620
2621static void
2622get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2623	isc_result_t result;
2624	unsigned int soacount;
2625
2626	LOCK(&raw->lock);
2627	if (raw->db != NULL) {
2628		result = zone_get_from_db(raw, raw->db, NULL, &soacount, NULL,
2629					  &rawdata->sourceserial, NULL, NULL,
2630					  NULL, NULL, NULL);
2631		if (result == ISC_R_SUCCESS && soacount > 0U) {
2632			rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2633		}
2634	}
2635	UNLOCK(&raw->lock);
2636}
2637
2638static void
2639zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2640	const char me[] = "zone_gotwritehandle";
2641	dns_zone_t *zone = event->ev_arg;
2642	isc_result_t result = ISC_R_SUCCESS;
2643	dns_dbversion_t *version = NULL;
2644	dns_masterrawheader_t rawdata;
2645	dns_db_t *db = NULL;
2646
2647	REQUIRE(DNS_ZONE_VALID(zone));
2648	INSIST(task == zone->task);
2649	ENTER;
2650
2651	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2652		result = ISC_R_CANCELED;
2653	}
2654	isc_event_free(&event);
2655	if (result == ISC_R_CANCELED) {
2656		goto fail;
2657	}
2658
2659	LOCK_ZONE(zone);
2660	INSIST(zone != zone->raw);
2661	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2662	if (zone->db != NULL) {
2663		dns_db_attach(zone->db, &db);
2664	}
2665	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2666	if (db != NULL) {
2667		const dns_master_style_t *output_style;
2668		dns_db_currentversion(db, &version);
2669		dns_master_initrawheader(&rawdata);
2670		if (inline_secure(zone)) {
2671			get_raw_serial(zone->raw, &rawdata);
2672		}
2673		if (zone->type == dns_zone_key) {
2674			output_style = &dns_master_style_keyzone;
2675		} else if (zone->masterstyle != NULL) {
2676			output_style = zone->masterstyle;
2677		} else {
2678			output_style = &dns_master_style_default;
2679		}
2680		result = dns_master_dumpasync(
2681			zone->mctx, db, version, output_style, zone->masterfile,
2682			zone->task, dump_done, zone, &zone->dctx,
2683			zone->masterformat, &rawdata);
2684		dns_db_closeversion(db, &version, false);
2685	} else {
2686		result = ISC_R_CANCELED;
2687	}
2688	if (db != NULL) {
2689		dns_db_detach(&db);
2690	}
2691	UNLOCK_ZONE(zone);
2692	if (result != DNS_R_CONTINUE) {
2693		goto fail;
2694	}
2695	return;
2696
2697fail:
2698	dump_done(zone, result);
2699}
2700
2701/*
2702 * Save the raw serial number for inline-signing zones.
2703 * (XXX: Other information from the header will be used
2704 * for other purposes in the future, but for now this is
2705 * all we're interested in.)
2706 */
2707static void
2708zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2709	if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
2710		return;
2711	}
2712
2713	zone->sourceserial = header->sourceserial;
2714	zone->sourceserialset = true;
2715}
2716
2717void
2718dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2719	if (zone == NULL) {
2720		return;
2721	}
2722
2723	LOCK_ZONE(zone);
2724	zone_setrawdata(zone, header);
2725	UNLOCK_ZONE(zone);
2726}
2727
2728static isc_result_t
2729zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2730	const char me[] = "zone_startload";
2731	dns_load_t *load;
2732	isc_result_t result;
2733	isc_result_t tresult;
2734	unsigned int options;
2735
2736	ENTER;
2737
2738	dns_zone_rpz_enable_db(zone, db);
2739	dns_zone_catz_enable_db(zone, db);
2740
2741	options = get_master_options(zone);
2742	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2743		options |= DNS_MASTER_MANYERRORS;
2744	}
2745
2746	if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2747		load = isc_mem_get(zone->mctx, sizeof(*load));
2748
2749		load->mctx = NULL;
2750		load->zone = NULL;
2751		load->db = NULL;
2752		load->loadtime = loadtime;
2753		load->magic = LOAD_MAGIC;
2754
2755		isc_mem_attach(zone->mctx, &load->mctx);
2756		zone_iattach(zone, &load->zone);
2757		dns_db_attach(db, &load->db);
2758		dns_rdatacallbacks_init(&load->callbacks);
2759		load->callbacks.rawdata = zone_setrawdata;
2760		zone_iattach(zone, &load->callbacks.zone);
2761		result = dns_db_beginload(db, &load->callbacks);
2762		if (result != ISC_R_SUCCESS) {
2763			goto cleanup;
2764		}
2765		result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
2766				       zone_gotreadhandle, load, &zone->readio);
2767		if (result != ISC_R_SUCCESS) {
2768			/*
2769			 * We can't report multiple errors so ignore
2770			 * the result of dns_db_endload().
2771			 */
2772			(void)dns_db_endload(load->db, &load->callbacks);
2773			goto cleanup;
2774		} else {
2775			result = DNS_R_CONTINUE;
2776		}
2777	} else {
2778		dns_rdatacallbacks_t callbacks;
2779
2780		dns_rdatacallbacks_init(&callbacks);
2781		callbacks.rawdata = zone_setrawdata;
2782		zone_iattach(zone, &callbacks.zone);
2783		result = dns_db_beginload(db, &callbacks);
2784		if (result != ISC_R_SUCCESS) {
2785			zone_idetach(&callbacks.zone);
2786			return (result);
2787		}
2788		result = dns_master_loadfile(
2789			zone->masterfile, &zone->origin, &zone->origin,
2790			zone->rdclass, options, 0, &callbacks,
2791			zone_registerinclude, zone, zone->mctx,
2792			zone->masterformat, zone->maxttl);
2793		tresult = dns_db_endload(db, &callbacks);
2794		if (result == ISC_R_SUCCESS) {
2795			result = tresult;
2796		}
2797		zone_idetach(&callbacks.zone);
2798	}
2799
2800	return (result);
2801
2802cleanup:
2803	load->magic = 0;
2804	dns_db_detach(&load->db);
2805	zone_idetach(&load->zone);
2806	zone_idetach(&load->callbacks.zone);
2807	isc_mem_detach(&load->mctx);
2808	isc_mem_put(zone->mctx, load, sizeof(*load));
2809	return (result);
2810}
2811
2812static bool
2813zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2814	      dns_name_t *owner) {
2815	isc_result_t result;
2816	char ownerbuf[DNS_NAME_FORMATSIZE];
2817	char namebuf[DNS_NAME_FORMATSIZE];
2818	char altbuf[DNS_NAME_FORMATSIZE];
2819	dns_fixedname_t fixed;
2820	dns_name_t *foundname;
2821	int level;
2822
2823	/*
2824	 * "." means the services does not exist.
2825	 */
2826	if (dns_name_equal(name, dns_rootname)) {
2827		return (true);
2828	}
2829
2830	/*
2831	 * Outside of zone.
2832	 */
2833	if (!dns_name_issubdomain(name, &zone->origin)) {
2834		if (zone->checkmx != NULL) {
2835			return ((zone->checkmx)(zone, name, owner));
2836		}
2837		return (true);
2838	}
2839
2840	if (zone->type == dns_zone_primary) {
2841		level = ISC_LOG_ERROR;
2842	} else {
2843		level = ISC_LOG_WARNING;
2844	}
2845
2846	foundname = dns_fixedname_initname(&fixed);
2847
2848	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2849			     foundname, NULL, NULL);
2850	if (result == ISC_R_SUCCESS) {
2851		return (true);
2852	}
2853
2854	if (result == DNS_R_NXRRSET) {
2855		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2856				     NULL, foundname, NULL, NULL);
2857		if (result == ISC_R_SUCCESS) {
2858			return (true);
2859		}
2860	}
2861
2862	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2863	dns_name_format(name, namebuf, sizeof namebuf);
2864	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2865	    result == DNS_R_EMPTYNAME)
2866	{
2867		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2868			level = ISC_LOG_WARNING;
2869		}
2870		dns_zone_log(zone, level,
2871			     "%s/MX '%s' has no address records (A or AAAA)",
2872			     ownerbuf, namebuf);
2873		return ((level == ISC_LOG_WARNING) ? true : false);
2874	}
2875
2876	if (result == DNS_R_CNAME) {
2877		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2878		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2879		{
2880			level = ISC_LOG_WARNING;
2881		}
2882		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2883			dns_zone_log(zone, level,
2884				     "%s/MX '%s' is a CNAME (illegal)",
2885				     ownerbuf, namebuf);
2886		}
2887		return ((level == ISC_LOG_WARNING) ? true : false);
2888	}
2889
2890	if (result == DNS_R_DNAME) {
2891		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2892		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2893		{
2894			level = ISC_LOG_WARNING;
2895		}
2896		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2897			dns_name_format(foundname, altbuf, sizeof altbuf);
2898			dns_zone_log(zone, level,
2899				     "%s/MX '%s' is below a DNAME"
2900				     " '%s' (illegal)",
2901				     ownerbuf, namebuf, altbuf);
2902		}
2903		return ((level == ISC_LOG_WARNING) ? true : false);
2904	}
2905
2906	if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
2907		return ((zone->checkmx)(zone, name, owner));
2908	}
2909
2910	return (true);
2911}
2912
2913static bool
2914zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2915	       dns_name_t *owner) {
2916	isc_result_t result;
2917	char ownerbuf[DNS_NAME_FORMATSIZE];
2918	char namebuf[DNS_NAME_FORMATSIZE];
2919	char altbuf[DNS_NAME_FORMATSIZE];
2920	dns_fixedname_t fixed;
2921	dns_name_t *foundname;
2922	int level;
2923
2924	/*
2925	 * "." means the services does not exist.
2926	 */
2927	if (dns_name_equal(name, dns_rootname)) {
2928		return (true);
2929	}
2930
2931	/*
2932	 * Outside of zone.
2933	 */
2934	if (!dns_name_issubdomain(name, &zone->origin)) {
2935		if (zone->checksrv != NULL) {
2936			return ((zone->checksrv)(zone, name, owner));
2937		}
2938		return (true);
2939	}
2940
2941	if (zone->type == dns_zone_primary) {
2942		level = ISC_LOG_ERROR;
2943	} else {
2944		level = ISC_LOG_WARNING;
2945	}
2946
2947	foundname = dns_fixedname_initname(&fixed);
2948
2949	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2950			     foundname, NULL, NULL);
2951	if (result == ISC_R_SUCCESS) {
2952		return (true);
2953	}
2954
2955	if (result == DNS_R_NXRRSET) {
2956		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2957				     NULL, foundname, NULL, NULL);
2958		if (result == ISC_R_SUCCESS) {
2959			return (true);
2960		}
2961	}
2962
2963	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2964	dns_name_format(name, namebuf, sizeof namebuf);
2965	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2966	    result == DNS_R_EMPTYNAME)
2967	{
2968		dns_zone_log(zone, level,
2969			     "%s/SRV '%s' has no address records (A or AAAA)",
2970			     ownerbuf, namebuf);
2971		/* XXX950 make fatal for 9.5.0. */
2972		return (true);
2973	}
2974
2975	if (result == DNS_R_CNAME) {
2976		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2977		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2978		{
2979			level = ISC_LOG_WARNING;
2980		}
2981		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2982			dns_zone_log(zone, level,
2983				     "%s/SRV '%s' is a CNAME (illegal)",
2984				     ownerbuf, namebuf);
2985		}
2986		return ((level == ISC_LOG_WARNING) ? true : false);
2987	}
2988
2989	if (result == DNS_R_DNAME) {
2990		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2991		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2992		{
2993			level = ISC_LOG_WARNING;
2994		}
2995		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2996			dns_name_format(foundname, altbuf, sizeof altbuf);
2997			dns_zone_log(zone, level,
2998				     "%s/SRV '%s' is below a "
2999				     "DNAME '%s' (illegal)",
3000				     ownerbuf, namebuf, altbuf);
3001		}
3002		return ((level == ISC_LOG_WARNING) ? true : false);
3003	}
3004
3005	if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
3006		return ((zone->checksrv)(zone, name, owner));
3007	}
3008
3009	return (true);
3010}
3011
3012static bool
3013zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
3014		dns_name_t *owner) {
3015	bool answer = true;
3016	isc_result_t result, tresult;
3017	char ownerbuf[DNS_NAME_FORMATSIZE];
3018	char namebuf[DNS_NAME_FORMATSIZE];
3019	char altbuf[DNS_NAME_FORMATSIZE];
3020	dns_fixedname_t fixed;
3021	dns_name_t *foundname;
3022	dns_rdataset_t a;
3023	dns_rdataset_t aaaa;
3024	int level;
3025
3026	/*
3027	 * Outside of zone.
3028	 */
3029	if (!dns_name_issubdomain(name, &zone->origin)) {
3030		if (zone->checkns != NULL) {
3031			return ((zone->checkns)(zone, name, owner, NULL, NULL));
3032		}
3033		return (true);
3034	}
3035
3036	if (zone->type == dns_zone_primary) {
3037		level = ISC_LOG_ERROR;
3038	} else {
3039		level = ISC_LOG_WARNING;
3040	}
3041
3042	foundname = dns_fixedname_initname(&fixed);
3043	dns_rdataset_init(&a);
3044	dns_rdataset_init(&aaaa);
3045
3046	/*
3047	 * Perform a regular lookup to catch DNAME records then look
3048	 * for glue.
3049	 */
3050	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
3051			     foundname, &a, NULL);
3052	switch (result) {
3053	case ISC_R_SUCCESS:
3054	case DNS_R_DNAME:
3055	case DNS_R_CNAME:
3056		break;
3057	default:
3058		if (dns_rdataset_isassociated(&a)) {
3059			dns_rdataset_disassociate(&a);
3060		}
3061		result = dns_db_find(db, name, NULL, dns_rdatatype_a,
3062				     DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
3063				     NULL);
3064	}
3065	if (result == ISC_R_SUCCESS) {
3066		dns_rdataset_disassociate(&a);
3067		return (true);
3068	} else if (result == DNS_R_DELEGATION) {
3069		dns_rdataset_disassociate(&a);
3070	}
3071
3072	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
3073	    result == DNS_R_GLUE)
3074	{
3075		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
3076				      DNS_DBFIND_GLUEOK, 0, NULL, foundname,
3077				      &aaaa, NULL);
3078		if (tresult == ISC_R_SUCCESS) {
3079			if (dns_rdataset_isassociated(&a)) {
3080				dns_rdataset_disassociate(&a);
3081			}
3082			dns_rdataset_disassociate(&aaaa);
3083			return (true);
3084		}
3085		if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
3086			dns_rdataset_disassociate(&aaaa);
3087		}
3088		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
3089			/*
3090			 * Check glue against child zone.
3091			 */
3092			if (zone->checkns != NULL) {
3093				answer = (zone->checkns)(zone, name, owner, &a,
3094							 &aaaa);
3095			}
3096			if (dns_rdataset_isassociated(&a)) {
3097				dns_rdataset_disassociate(&a);
3098			}
3099			if (dns_rdataset_isassociated(&aaaa)) {
3100				dns_rdataset_disassociate(&aaaa);
3101			}
3102			return (answer);
3103		}
3104	}
3105
3106	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
3107	dns_name_format(name, namebuf, sizeof namebuf);
3108	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3109	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
3110	{
3111		const char *what;
3112		bool required = false;
3113		if (dns_name_issubdomain(name, owner)) {
3114			what = "REQUIRED GLUE ";
3115			required = true;
3116		} else if (result == DNS_R_DELEGATION) {
3117			what = "SIBLING GLUE ";
3118		} else {
3119			what = "";
3120		}
3121
3122		if (result != DNS_R_DELEGATION || required ||
3123		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
3124		{
3125			dns_zone_log(zone, level,
3126				     "%s/NS '%s' has no %s"
3127				     "address records (A or AAAA)",
3128				     ownerbuf, namebuf, what);
3129			/*
3130			 * Log missing address record.
3131			 */
3132			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
3133			{
3134				(void)(zone->checkns)(zone, name, owner, &a,
3135						      &aaaa);
3136			}
3137			/* XXX950 make fatal for 9.5.0. */
3138			/* answer = false; */
3139		}
3140	} else if (result == DNS_R_CNAME) {
3141		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
3142			     ownerbuf, namebuf);
3143		/* XXX950 make fatal for 9.5.0. */
3144		/* answer = false; */
3145	} else if (result == DNS_R_DNAME) {
3146		dns_name_format(foundname, altbuf, sizeof altbuf);
3147		dns_zone_log(zone, level,
3148			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
3149			     ownerbuf, namebuf, altbuf);
3150		/* XXX950 make fatal for 9.5.0. */
3151		/* answer = false; */
3152	}
3153
3154	if (dns_rdataset_isassociated(&a)) {
3155		dns_rdataset_disassociate(&a);
3156	}
3157	if (dns_rdataset_isassociated(&aaaa)) {
3158		dns_rdataset_disassociate(&aaaa);
3159	}
3160	return (answer);
3161}
3162
3163static bool
3164zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
3165		     dns_rdataset_t *rdataset) {
3166	dns_rdataset_t tmprdataset;
3167	isc_result_t result;
3168	bool answer = true;
3169	bool format = true;
3170	int level = ISC_LOG_WARNING;
3171	char ownerbuf[DNS_NAME_FORMATSIZE];
3172	char typebuf[DNS_RDATATYPE_FORMATSIZE];
3173	unsigned int count1 = 0;
3174
3175	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
3176		level = ISC_LOG_ERROR;
3177	}
3178
3179	dns_rdataset_init(&tmprdataset);
3180	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
3181	     result = dns_rdataset_next(rdataset))
3182	{
3183		dns_rdata_t rdata1 = DNS_RDATA_INIT;
3184		unsigned int count2 = 0;
3185
3186		count1++;
3187		dns_rdataset_current(rdataset, &rdata1);
3188		dns_rdataset_clone(rdataset, &tmprdataset);
3189		for (result = dns_rdataset_first(&tmprdataset);
3190		     result == ISC_R_SUCCESS;
3191		     result = dns_rdataset_next(&tmprdataset))
3192		{
3193			dns_rdata_t rdata2 = DNS_RDATA_INIT;
3194			count2++;
3195			if (count1 >= count2) {
3196				continue;
3197			}
3198			dns_rdataset_current(&tmprdataset, &rdata2);
3199			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
3200				if (format) {
3201					dns_name_format(owner, ownerbuf,
3202							sizeof ownerbuf);
3203					dns_rdatatype_format(rdata1.type,
3204							     typebuf,
3205							     sizeof(typebuf));
3206					format = false;
3207				}
3208				dns_zone_log(zone, level,
3209					     "%s/%s has "
3210					     "semantically identical records",
3211					     ownerbuf, typebuf);
3212				if (level == ISC_LOG_ERROR) {
3213					answer = false;
3214				}
3215				break;
3216			}
3217		}
3218		dns_rdataset_disassociate(&tmprdataset);
3219		if (!format) {
3220			break;
3221		}
3222	}
3223	return (answer);
3224}
3225
3226static bool
3227zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
3228	dns_dbiterator_t *dbiterator = NULL;
3229	dns_dbnode_t *node = NULL;
3230	dns_fixedname_t fixed;
3231	dns_name_t *name;
3232	dns_rdataset_t rdataset;
3233	dns_rdatasetiter_t *rdsit = NULL;
3234	bool ok = true;
3235	isc_result_t result;
3236
3237	name = dns_fixedname_initname(&fixed);
3238	dns_rdataset_init(&rdataset);
3239
3240	result = dns_db_createiterator(db, 0, &dbiterator);
3241	if (result != ISC_R_SUCCESS) {
3242		return (true);
3243	}
3244
3245	for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
3246	     result = dns_dbiterator_next(dbiterator))
3247	{
3248		result = dns_dbiterator_current(dbiterator, &node, name);
3249		if (result != ISC_R_SUCCESS) {
3250			continue;
3251		}
3252
3253		result = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsit);
3254		if (result != ISC_R_SUCCESS) {
3255			continue;
3256		}
3257
3258		for (result = dns_rdatasetiter_first(rdsit);
3259		     result == ISC_R_SUCCESS;
3260		     result = dns_rdatasetiter_next(rdsit))
3261		{
3262			dns_rdatasetiter_current(rdsit, &rdataset);
3263			if (!zone_rrset_check_dup(zone, name, &rdataset)) {
3264				ok = false;
3265			}
3266			dns_rdataset_disassociate(&rdataset);
3267		}
3268		dns_rdatasetiter_destroy(&rdsit);
3269		dns_db_detachnode(db, &node);
3270	}
3271
3272	if (node != NULL) {
3273		dns_db_detachnode(db, &node);
3274	}
3275	dns_dbiterator_destroy(&dbiterator);
3276
3277	return (ok);
3278}
3279
3280static bool
3281isspf(const dns_rdata_t *rdata) {
3282	char buf[1024];
3283	const unsigned char *data = rdata->data;
3284	unsigned int rdl = rdata->length, i = 0, tl, len;
3285
3286	while (rdl > 0U) {
3287		len = tl = *data;
3288		++data;
3289		--rdl;
3290		INSIST(tl <= rdl);
3291		if (len > sizeof(buf) - i - 1) {
3292			len = sizeof(buf) - i - 1;
3293		}
3294		memmove(buf + i, data, len);
3295		i += len;
3296		data += tl;
3297		rdl -= tl;
3298	}
3299
3300	if (i < 6U) {
3301		return (false);
3302	}
3303
3304	buf[i] = 0;
3305	if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
3306		return (true);
3307	}
3308	return (false);
3309}
3310
3311static bool
3312integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3313	dns_dbiterator_t *dbiterator = NULL;
3314	dns_dbnode_t *node = NULL;
3315	dns_rdataset_t rdataset;
3316	dns_fixedname_t fixed;
3317	dns_fixedname_t fixedbottom;
3318	dns_rdata_mx_t mx;
3319	dns_rdata_ns_t ns;
3320	dns_rdata_in_srv_t srv;
3321	dns_rdata_t rdata;
3322	dns_name_t *name;
3323	dns_name_t *bottom;
3324	isc_result_t result;
3325	bool ok = true, have_spf, have_txt;
3326
3327	name = dns_fixedname_initname(&fixed);
3328	bottom = dns_fixedname_initname(&fixedbottom);
3329	dns_rdataset_init(&rdataset);
3330	dns_rdata_init(&rdata);
3331
3332	result = dns_db_createiterator(db, 0, &dbiterator);
3333	if (result != ISC_R_SUCCESS) {
3334		return (true);
3335	}
3336
3337	result = dns_dbiterator_first(dbiterator);
3338	while (result == ISC_R_SUCCESS) {
3339		result = dns_dbiterator_current(dbiterator, &node, name);
3340		if (result != ISC_R_SUCCESS) {
3341			goto cleanup;
3342		}
3343
3344		/*
3345		 * Is this name visible in the zone?
3346		 */
3347		if (!dns_name_issubdomain(name, &zone->origin) ||
3348		    (dns_name_countlabels(bottom) > 0 &&
3349		     dns_name_issubdomain(name, bottom)))
3350		{
3351			goto next;
3352		}
3353
3354		dns_dbiterator_pause(dbiterator);
3355
3356		/*
3357		 * Don't check the NS records at the origin.
3358		 */
3359		if (dns_name_equal(name, &zone->origin)) {
3360			goto checkfordname;
3361		}
3362
3363		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3364					     0, 0, &rdataset, NULL);
3365		if (result != ISC_R_SUCCESS) {
3366			goto checkfordname;
3367		}
3368		/*
3369		 * Remember bottom of zone due to NS.
3370		 */
3371		dns_name_copynf(name, bottom);
3372
3373		result = dns_rdataset_first(&rdataset);
3374		while (result == ISC_R_SUCCESS) {
3375			dns_rdataset_current(&rdataset, &rdata);
3376			result = dns_rdata_tostruct(&rdata, &ns, NULL);
3377			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3378			if (!zone_check_glue(zone, db, &ns.name, name)) {
3379				ok = false;
3380			}
3381			dns_rdata_reset(&rdata);
3382			result = dns_rdataset_next(&rdataset);
3383		}
3384		dns_rdataset_disassociate(&rdataset);
3385		goto next;
3386
3387	checkfordname:
3388		result = dns_db_findrdataset(db, node, NULL,
3389					     dns_rdatatype_dname, 0, 0,
3390					     &rdataset, NULL);
3391		if (result == ISC_R_SUCCESS) {
3392			/*
3393			 * Remember bottom of zone due to DNAME.
3394			 */
3395			dns_name_copynf(name, bottom);
3396			dns_rdataset_disassociate(&rdataset);
3397		}
3398
3399		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3400					     0, 0, &rdataset, NULL);
3401		if (result != ISC_R_SUCCESS) {
3402			goto checksrv;
3403		}
3404		result = dns_rdataset_first(&rdataset);
3405		while (result == ISC_R_SUCCESS) {
3406			dns_rdataset_current(&rdataset, &rdata);
3407			result = dns_rdata_tostruct(&rdata, &mx, NULL);
3408			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3409			if (!zone_check_mx(zone, db, &mx.mx, name)) {
3410				ok = false;
3411			}
3412			dns_rdata_reset(&rdata);
3413			result = dns_rdataset_next(&rdataset);
3414		}
3415		dns_rdataset_disassociate(&rdataset);
3416
3417	checksrv:
3418		if (zone->rdclass != dns_rdataclass_in) {
3419			goto next;
3420		}
3421		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3422					     0, 0, &rdataset, NULL);
3423		if (result != ISC_R_SUCCESS) {
3424			goto checkspf;
3425		}
3426		result = dns_rdataset_first(&rdataset);
3427		while (result == ISC_R_SUCCESS) {
3428			dns_rdataset_current(&rdataset, &rdata);
3429			result = dns_rdata_tostruct(&rdata, &srv, NULL);
3430			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3431			if (!zone_check_srv(zone, db, &srv.target, name)) {
3432				ok = false;
3433			}
3434			dns_rdata_reset(&rdata);
3435			result = dns_rdataset_next(&rdataset);
3436		}
3437		dns_rdataset_disassociate(&rdataset);
3438
3439	checkspf:
3440		/*
3441		 * Check if there is a type SPF record without an
3442		 * SPF-formatted type TXT record also being present.
3443		 */
3444		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
3445			goto next;
3446		}
3447		if (zone->rdclass != dns_rdataclass_in) {
3448			goto next;
3449		}
3450		have_spf = have_txt = false;
3451		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3452					     0, 0, &rdataset, NULL);
3453		if (result == ISC_R_SUCCESS) {
3454			dns_rdataset_disassociate(&rdataset);
3455			have_spf = true;
3456		}
3457		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3458					     0, 0, &rdataset, NULL);
3459		if (result != ISC_R_SUCCESS) {
3460			goto notxt;
3461		}
3462		result = dns_rdataset_first(&rdataset);
3463		while (result == ISC_R_SUCCESS) {
3464			dns_rdataset_current(&rdataset, &rdata);
3465			have_txt = isspf(&rdata);
3466			dns_rdata_reset(&rdata);
3467			if (have_txt) {
3468				break;
3469			}
3470			result = dns_rdataset_next(&rdataset);
3471		}
3472		dns_rdataset_disassociate(&rdataset);
3473
3474	notxt:
3475		if (have_spf && !have_txt) {
3476			char namebuf[DNS_NAME_FORMATSIZE];
3477
3478			dns_name_format(name, namebuf, sizeof(namebuf));
3479			dns_zone_log(zone, ISC_LOG_WARNING,
3480				     "'%s' found type "
3481				     "SPF record but no SPF TXT record found, "
3482				     "add matching type TXT record",
3483				     namebuf);
3484		}
3485
3486	next:
3487		dns_db_detachnode(db, &node);
3488		result = dns_dbiterator_next(dbiterator);
3489	}
3490
3491cleanup:
3492	if (node != NULL) {
3493		dns_db_detachnode(db, &node);
3494	}
3495	dns_dbiterator_destroy(&dbiterator);
3496
3497	return (ok);
3498}
3499
3500/*
3501 * OpenSSL verification of RSA keys with exponent 3 is known to be
3502 * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
3503 * if they are in use.
3504 */
3505static void
3506zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3507	dns_dbnode_t *node = NULL;
3508	dns_dbversion_t *version = NULL;
3509	dns_rdata_dnskey_t dnskey;
3510	dns_rdata_t rdata = DNS_RDATA_INIT;
3511	dns_rdataset_t rdataset;
3512	isc_result_t result;
3513
3514	result = dns_db_findnode(db, &zone->origin, false, &node);
3515	if (result != ISC_R_SUCCESS) {
3516		goto cleanup;
3517	}
3518
3519	dns_db_currentversion(db, &version);
3520	dns_rdataset_init(&rdataset);
3521	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3522				     dns_rdatatype_none, 0, &rdataset, NULL);
3523	if (result != ISC_R_SUCCESS) {
3524		goto cleanup;
3525	}
3526
3527	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3528	     result = dns_rdataset_next(&rdataset))
3529	{
3530		dns_rdataset_current(&rdataset, &rdata);
3531		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3532		INSIST(result == ISC_R_SUCCESS);
3533
3534		/*
3535		 * RFC 3110, section 4: Performance Considerations:
3536		 *
3537		 * A public exponent of 3 minimizes the effort needed to verify
3538		 * a signature.  Use of 3 as the public exponent is weak for
3539		 * confidentiality uses since, if the same data can be collected
3540		 * encrypted under three different keys with an exponent of 3
3541		 * then, using the Chinese Remainder Theorem [NETSEC], the
3542		 * original plain text can be easily recovered.  If a key is
3543		 * known to be used only for authentication, as is the case with
3544		 * DNSSEC, then an exponent of 3 is acceptable.  However other
3545		 * applications in the future may wish to leverage DNS
3546		 * distributed keys for applications that do require
3547		 * confidentiality.  For keys which might have such other uses,
3548		 * a more conservative choice would be 65537 (F4, the fourth
3549		 * fermat number).
3550		 */
3551		if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3552		    dnskey.data[1] == 3 &&
3553		    (dnskey.algorithm == DNS_KEYALG_RSAMD5 ||
3554		     dnskey.algorithm == DNS_KEYALG_RSASHA1 ||
3555		     dnskey.algorithm == DNS_KEYALG_NSEC3RSASHA1 ||
3556		     dnskey.algorithm == DNS_KEYALG_RSASHA256 ||
3557		     dnskey.algorithm == DNS_KEYALG_RSASHA512))
3558		{
3559			char algorithm[DNS_SECALG_FORMATSIZE];
3560			isc_region_t r;
3561
3562			dns_rdata_toregion(&rdata, &r);
3563			dns_secalg_format(dnskey.algorithm, algorithm,
3564					  sizeof(algorithm));
3565
3566			dnssec_log(zone, ISC_LOG_WARNING,
3567				   "weak %s (%u) key found (exponent=3, id=%u)",
3568				   algorithm, dnskey.algorithm,
3569				   dst_region_computeid(&r));
3570		}
3571		dns_rdata_reset(&rdata);
3572	}
3573	dns_rdataset_disassociate(&rdataset);
3574
3575cleanup:
3576	if (node != NULL) {
3577		dns_db_detachnode(db, &node);
3578	}
3579	if (version != NULL) {
3580		dns_db_closeversion(db, &version, false);
3581	}
3582}
3583
3584static void
3585resume_signingwithkey(dns_zone_t *zone) {
3586	dns_dbnode_t *node = NULL;
3587	dns_dbversion_t *version = NULL;
3588	dns_rdata_t rdata = DNS_RDATA_INIT;
3589	dns_rdataset_t rdataset;
3590	isc_result_t result;
3591	dns_db_t *db = NULL;
3592
3593	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3594	if (zone->db != NULL) {
3595		dns_db_attach(zone->db, &db);
3596	}
3597	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3598	if (db == NULL) {
3599		goto cleanup;
3600	}
3601
3602	result = dns_db_findnode(db, &zone->origin, false, &node);
3603	if (result != ISC_R_SUCCESS) {
3604		goto cleanup;
3605	}
3606
3607	dns_db_currentversion(db, &version);
3608	dns_rdataset_init(&rdataset);
3609	result = dns_db_findrdataset(db, node, version, zone->privatetype,
3610				     dns_rdatatype_none, 0, &rdataset, NULL);
3611	if (result != ISC_R_SUCCESS) {
3612		INSIST(!dns_rdataset_isassociated(&rdataset));
3613		goto cleanup;
3614	}
3615
3616	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3617	     result = dns_rdataset_next(&rdataset))
3618	{
3619		dns_rdataset_current(&rdataset, &rdata);
3620		if (rdata.length != 5 || rdata.data[0] == 0 ||
3621		    rdata.data[4] != 0)
3622		{
3623			dns_rdata_reset(&rdata);
3624			continue;
3625		}
3626
3627		result = zone_signwithkey(zone, rdata.data[0],
3628					  (rdata.data[1] << 8) | rdata.data[2],
3629					  rdata.data[3]);
3630		if (result != ISC_R_SUCCESS) {
3631			dnssec_log(zone, ISC_LOG_ERROR,
3632				   "zone_signwithkey failed: %s",
3633				   dns_result_totext(result));
3634		}
3635		dns_rdata_reset(&rdata);
3636	}
3637	dns_rdataset_disassociate(&rdataset);
3638
3639cleanup:
3640	if (db != NULL) {
3641		if (node != NULL) {
3642			dns_db_detachnode(db, &node);
3643		}
3644		if (version != NULL) {
3645			dns_db_closeversion(db, &version, false);
3646		}
3647		dns_db_detach(&db);
3648	}
3649}
3650
3651/*
3652 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3653 * supplied NSEC3PARAM RDATA.
3654 *
3655 * Zone must be locked by caller.
3656 */
3657static isc_result_t
3658zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3659	dns_nsec3chain_t *nsec3chain, *current;
3660	dns_dbversion_t *version = NULL;
3661	bool nseconly = false, nsec3ok = false;
3662	isc_result_t result;
3663	isc_time_t now;
3664	unsigned int options = 0;
3665	char saltbuf[255 * 2 + 1];
3666	char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3667	dns_db_t *db = NULL;
3668
3669	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3670	if (zone->db != NULL) {
3671		dns_db_attach(zone->db, &db);
3672	}
3673	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3674
3675	if (db == NULL) {
3676		result = ISC_R_SUCCESS;
3677		goto cleanup;
3678	}
3679
3680	/*
3681	 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3682	 * chain from it is pointless as it would not be possible for the
3683	 * latter to exist in the first place.
3684	 */
3685	dns_db_currentversion(db, &version);
3686	result = dns_nsec_nseconly(db, version, &nseconly);
3687	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3688	dns_db_closeversion(db, &version, false);
3689	if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3690		result = ISC_R_SUCCESS;
3691		goto cleanup;
3692	}
3693
3694	/*
3695	 * Allocate and initialize structure preserving state of
3696	 * adding/removing records belonging to this NSEC3 chain between
3697	 * separate zone_nsec3chain() calls.
3698	 */
3699	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3700
3701	nsec3chain->magic = 0;
3702	nsec3chain->done = false;
3703	nsec3chain->db = NULL;
3704	nsec3chain->dbiterator = NULL;
3705	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3706	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3707	nsec3chain->nsec3param.hash = nsec3param->hash;
3708	nsec3chain->nsec3param.iterations = nsec3param->iterations;
3709	nsec3chain->nsec3param.flags = nsec3param->flags;
3710	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3711	memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3712	nsec3chain->nsec3param.salt = nsec3chain->salt;
3713	nsec3chain->seen_nsec = false;
3714	nsec3chain->delete_nsec = false;
3715	nsec3chain->save_delete_nsec = false;
3716
3717	/*
3718	 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3719	 */
3720	if (nsec3param->flags == 0) {
3721		strlcpy(flags, "NONE", sizeof(flags));
3722	} else {
3723		flags[0] = '\0';
3724		if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3725			strlcat(flags, "REMOVE", sizeof(flags));
3726		}
3727		if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3728			if (flags[0] == '\0') {
3729				strlcpy(flags, "INITIAL", sizeof(flags));
3730			} else {
3731				strlcat(flags, "|INITIAL", sizeof(flags));
3732			}
3733		}
3734		if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3735			if (flags[0] == '\0') {
3736				strlcpy(flags, "CREATE", sizeof(flags));
3737			} else {
3738				strlcat(flags, "|CREATE", sizeof(flags));
3739			}
3740		}
3741		if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3742			if (flags[0] == '\0') {
3743				strlcpy(flags, "NONSEC", sizeof(flags));
3744			} else {
3745				strlcat(flags, "|NONSEC", sizeof(flags));
3746			}
3747		}
3748		if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3749			if (flags[0] == '\0') {
3750				strlcpy(flags, "OPTOUT", sizeof(flags));
3751			} else {
3752				strlcat(flags, "|OPTOUT", sizeof(flags));
3753			}
3754		}
3755	}
3756	result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3757					   sizeof(saltbuf));
3758	RUNTIME_CHECK(result == ISC_R_SUCCESS);
3759	dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3760		   nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3761
3762	/*
3763	 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3764	 * currently being processed, interrupt its processing to avoid
3765	 * simultaneously adding and removing records for the same NSEC3 chain.
3766	 */
3767	for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
3768	     current = ISC_LIST_NEXT(current, link))
3769	{
3770		if ((current->db == db) &&
3771		    (current->nsec3param.hash == nsec3param->hash) &&
3772		    (current->nsec3param.iterations ==
3773		     nsec3param->iterations) &&
3774		    (current->nsec3param.salt_length ==
3775		     nsec3param->salt_length) &&
3776		    memcmp(current->nsec3param.salt, nsec3param->salt,
3777			   nsec3param->salt_length) == 0)
3778		{
3779			current->done = true;
3780		}
3781	}
3782
3783	/*
3784	 * Attach zone database to the structure initialized above and create
3785	 * an iterator for it with appropriate options in order to avoid
3786	 * creating NSEC3 records for NSEC3 records.
3787	 */
3788	dns_db_attach(db, &nsec3chain->db);
3789	if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3790		options = DNS_DB_NONSEC3;
3791	}
3792	result = dns_db_createiterator(nsec3chain->db, options,
3793				       &nsec3chain->dbiterator);
3794	if (result == ISC_R_SUCCESS) {
3795		result = dns_dbiterator_first(nsec3chain->dbiterator);
3796	}
3797	if (result == ISC_R_SUCCESS) {
3798		/*
3799		 * Database iterator initialization succeeded.  We are now
3800		 * ready to kick off adding/removing records belonging to this
3801		 * NSEC3 chain.  Append the structure initialized above to the
3802		 * "nsec3chain" list for the zone and set the appropriate zone
3803		 * timer so that zone_nsec3chain() is called as soon as
3804		 * possible.
3805		 */
3806		dns_dbiterator_pause(nsec3chain->dbiterator);
3807		ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
3808		nsec3chain = NULL;
3809		if (isc_time_isepoch(&zone->nsec3chaintime)) {
3810			TIME_NOW(&now);
3811			zone->nsec3chaintime = now;
3812			if (zone->task != NULL) {
3813				zone_settimer(zone, &now);
3814			}
3815		}
3816	}
3817
3818	if (nsec3chain != NULL) {
3819		if (nsec3chain->db != NULL) {
3820			dns_db_detach(&nsec3chain->db);
3821		}
3822		if (nsec3chain->dbiterator != NULL) {
3823			dns_dbiterator_destroy(&nsec3chain->dbiterator);
3824		}
3825		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3826	}
3827
3828cleanup:
3829	if (db != NULL) {
3830		dns_db_detach(&db);
3831	}
3832	return (result);
3833}
3834
3835/*
3836 * Find private-type records at the zone apex which signal that an NSEC3 chain
3837 * should be added or removed.  For each such record, extract NSEC3PARAM RDATA
3838 * and pass it to zone_addnsec3chain().
3839 *
3840 * Zone must be locked by caller.
3841 */
3842static void
3843resume_addnsec3chain(dns_zone_t *zone) {
3844	dns_dbnode_t *node = NULL;
3845	dns_dbversion_t *version = NULL;
3846	dns_rdataset_t rdataset;
3847	isc_result_t result;
3848	dns_rdata_nsec3param_t nsec3param;
3849	bool nseconly = false, nsec3ok = false;
3850	dns_db_t *db = NULL;
3851
3852	INSIST(LOCKED_ZONE(zone));
3853
3854	if (zone->privatetype == 0) {
3855		return;
3856	}
3857
3858	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3859	if (zone->db != NULL) {
3860		dns_db_attach(zone->db, &db);
3861	}
3862	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3863	if (db == NULL) {
3864		goto cleanup;
3865	}
3866
3867	result = dns_db_findnode(db, &zone->origin, false, &node);
3868	if (result != ISC_R_SUCCESS) {
3869		goto cleanup;
3870	}
3871
3872	dns_db_currentversion(db, &version);
3873
3874	/*
3875	 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3876	 * apex to exist and contain no keys using NSEC-only algorithms.
3877	 */
3878	result = dns_nsec_nseconly(db, version, &nseconly);
3879	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3880
3881	/*
3882	 * Get the RRset containing all private-type records at the zone apex.
3883	 */
3884	dns_rdataset_init(&rdataset);
3885	result = dns_db_findrdataset(db, node, version, zone->privatetype,
3886				     dns_rdatatype_none, 0, &rdataset, NULL);
3887	if (result != ISC_R_SUCCESS) {
3888		INSIST(!dns_rdataset_isassociated(&rdataset));
3889		goto cleanup;
3890	}
3891
3892	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3893	     result = dns_rdataset_next(&rdataset))
3894	{
3895		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3896		dns_rdata_t rdata = DNS_RDATA_INIT;
3897		dns_rdata_t private = DNS_RDATA_INIT;
3898
3899		dns_rdataset_current(&rdataset, &private);
3900		/*
3901		 * Try extracting NSEC3PARAM RDATA from this private-type
3902		 * record.  Failure means this private-type record does not
3903		 * represent an NSEC3PARAM record, so skip it.
3904		 */
3905		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3906						sizeof(buf)))
3907		{
3908			continue;
3909		}
3910		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3911		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3912		if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3913		    ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3914		{
3915			/*
3916			 * Pass the NSEC3PARAM RDATA contained in this
3917			 * private-type record to zone_addnsec3chain() so that
3918			 * it can kick off adding or removing NSEC3 records.
3919			 */
3920			result = zone_addnsec3chain(zone, &nsec3param);
3921			if (result != ISC_R_SUCCESS) {
3922				dnssec_log(zone, ISC_LOG_ERROR,
3923					   "zone_addnsec3chain failed: %s",
3924					   dns_result_totext(result));
3925			}
3926		}
3927	}
3928	dns_rdataset_disassociate(&rdataset);
3929
3930cleanup:
3931	if (db != NULL) {
3932		if (node != NULL) {
3933			dns_db_detachnode(db, &node);
3934		}
3935		if (version != NULL) {
3936			dns_db_closeversion(db, &version, false);
3937		}
3938		dns_db_detach(&db);
3939	}
3940}
3941
3942static void
3943set_resigntime(dns_zone_t *zone) {
3944	dns_rdataset_t rdataset;
3945	dns_fixedname_t fixed;
3946	unsigned int resign;
3947	isc_result_t result;
3948	uint32_t nanosecs;
3949	dns_db_t *db = NULL;
3950
3951	INSIST(LOCKED_ZONE(zone));
3952
3953	/* We only re-sign zones that can be dynamically updated */
3954	if (zone->update_disabled) {
3955		return;
3956	}
3957
3958	if (!inline_secure(zone) &&
3959	    (zone->type != dns_zone_primary ||
3960	     (zone->ssutable == NULL &&
3961	      (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
3962	{
3963		return;
3964	}
3965
3966	dns_rdataset_init(&rdataset);
3967	dns_fixedname_init(&fixed);
3968
3969	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3970	if (zone->db != NULL) {
3971		dns_db_attach(zone->db, &db);
3972	}
3973	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3974	if (db == NULL) {
3975		isc_time_settoepoch(&zone->resigntime);
3976		return;
3977	}
3978
3979	result = dns_db_getsigningtime(db, &rdataset,
3980				       dns_fixedname_name(&fixed));
3981	if (result != ISC_R_SUCCESS) {
3982		isc_time_settoepoch(&zone->resigntime);
3983		goto cleanup;
3984	}
3985
3986	resign = rdataset.resign - dns_zone_getsigresigninginterval(zone);
3987	dns_rdataset_disassociate(&rdataset);
3988	nanosecs = isc_random_uniform(1000000000);
3989	isc_time_set(&zone->resigntime, resign, nanosecs);
3990
3991cleanup:
3992	dns_db_detach(&db);
3993	return;
3994}
3995
3996static isc_result_t
3997check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3998	bool ok = false;
3999	dns_dbnode_t *node = NULL;
4000	dns_dbversion_t *version = NULL;
4001	dns_rdata_nsec3param_t nsec3param;
4002	dns_rdataset_t rdataset;
4003	isc_result_t result;
4004	bool dynamic = (zone->type == dns_zone_primary)
4005			       ? dns_zone_isdynamic(zone, false)
4006			       : false;
4007
4008	dns_rdataset_init(&rdataset);
4009	result = dns_db_findnode(db, &zone->origin, false, &node);
4010	if (result != ISC_R_SUCCESS) {
4011		dns_zone_log(zone, ISC_LOG_ERROR,
4012			     "nsec3param lookup failure: %s",
4013			     dns_result_totext(result));
4014		return (result);
4015	}
4016	dns_db_currentversion(db, &version);
4017
4018	result = dns_db_findrdataset(db, node, version,
4019				     dns_rdatatype_nsec3param,
4020				     dns_rdatatype_none, 0, &rdataset, NULL);
4021	if (result == ISC_R_NOTFOUND) {
4022		INSIST(!dns_rdataset_isassociated(&rdataset));
4023		result = ISC_R_SUCCESS;
4024		goto cleanup;
4025	}
4026	if (result != ISC_R_SUCCESS) {
4027		INSIST(!dns_rdataset_isassociated(&rdataset));
4028		dns_zone_log(zone, ISC_LOG_ERROR,
4029			     "nsec3param lookup failure: %s",
4030			     dns_result_totext(result));
4031		goto cleanup;
4032	}
4033
4034	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
4035	     result = dns_rdataset_next(&rdataset))
4036	{
4037		dns_rdata_t rdata = DNS_RDATA_INIT;
4038
4039		dns_rdataset_current(&rdataset, &rdata);
4040		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
4041		RUNTIME_CHECK(result == ISC_R_SUCCESS);
4042
4043		/*
4044		 * For dynamic zones we must support every algorithm so we
4045		 * can regenerate all the NSEC3 chains.
4046		 * For non-dynamic zones we only need to find a supported
4047		 * algorithm.
4048		 */
4049		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
4050		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
4051		{
4052			dns_zone_log(zone, ISC_LOG_WARNING,
4053				     "nsec3 test \"unknown\" hash algorithm "
4054				     "found: %u",
4055				     nsec3param.hash);
4056			ok = true;
4057		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
4058			if (dynamic) {
4059				dns_zone_log(zone, ISC_LOG_ERROR,
4060					     "unsupported nsec3 hash algorithm"
4061					     " in dynamic zone: %u",
4062					     nsec3param.hash);
4063				result = DNS_R_BADZONE;
4064				/* Stop second error message. */
4065				ok = true;
4066				break;
4067			} else {
4068				dns_zone_log(zone, ISC_LOG_WARNING,
4069					     "unsupported nsec3 hash "
4070					     "algorithm: %u",
4071					     nsec3param.hash);
4072			}
4073		} else {
4074			ok = true;
4075		}
4076
4077		/*
4078		 * Warn if the zone has excessive NSEC3 iterations.
4079		 */
4080		if (nsec3param.iterations > dns_nsec3_maxiterations()) {
4081			dnssec_log(zone, ISC_LOG_WARNING,
4082				   "excessive NSEC3PARAM iterations %u > %u",
4083				   nsec3param.iterations,
4084				   dns_nsec3_maxiterations());
4085		}
4086	}
4087	if (result == ISC_R_NOMORE) {
4088		result = ISC_R_SUCCESS;
4089	}
4090
4091	if (!ok) {
4092		result = DNS_R_BADZONE;
4093		dns_zone_log(zone, ISC_LOG_ERROR,
4094			     "no supported nsec3 hash algorithm");
4095	}
4096
4097cleanup:
4098	if (dns_rdataset_isassociated(&rdataset)) {
4099		dns_rdataset_disassociate(&rdataset);
4100	}
4101	dns_db_closeversion(db, &version, false);
4102	dns_db_detachnode(db, &node);
4103	return (result);
4104}
4105
4106/*
4107 * Set the timer for refreshing the key zone to the soonest future time
4108 * of the set (current timer, keydata->refresh, keydata->addhd,
4109 * keydata->removehd).
4110 */
4111static void
4112set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
4113		    isc_stdtime_t now, bool force) {
4114	const char me[] = "set_refreshkeytimer";
4115	isc_stdtime_t then;
4116	isc_time_t timenow, timethen;
4117	char timebuf[80];
4118
4119	ENTER;
4120	then = key->refresh;
4121	if (force) {
4122		then = now;
4123	}
4124	if (key->addhd > now && key->addhd < then) {
4125		then = key->addhd;
4126	}
4127	if (key->removehd > now && key->removehd < then) {
4128		then = key->removehd;
4129	}
4130
4131	TIME_NOW(&timenow);
4132	if (then > now) {
4133		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
4134	} else {
4135		timethen = timenow;
4136	}
4137	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
4138	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
4139	{
4140		zone->refreshkeytime = timethen;
4141	}
4142
4143	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4144	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
4145	zone_settimer(zone, &timenow);
4146}
4147
4148/*
4149 * If keynode references a key or a DS rdataset, and if the key
4150 * zone does not contain a KEYDATA record for the corresponding name,
4151 * then create an empty KEYDATA and push it into the zone as a placeholder,
4152 * then schedule a key refresh immediately. This new KEYDATA record will be
4153 * updated during the refresh.
4154 *
4155 * If the key zone is changed, set '*changed' to true.
4156 */
4157static isc_result_t
4158create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4159	       dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
4160	       bool *changed) {
4161	const char me[] = "create_keydata";
4162	isc_result_t result = ISC_R_SUCCESS;
4163	dns_rdata_t rdata = DNS_RDATA_INIT;
4164	dns_rdata_keydata_t kd;
4165	unsigned char rrdata[4096];
4166	isc_buffer_t rrdatabuf;
4167	isc_stdtime_t now;
4168
4169	REQUIRE(keynode != NULL);
4170
4171	ENTER;
4172	isc_stdtime_get(&now);
4173
4174	/*
4175	 * If the keynode has no trust anchor set, we shouldn't be here.
4176	 */
4177	if (!dns_keynode_dsset(keynode, NULL)) {
4178		return (ISC_R_FAILURE);
4179	}
4180
4181	memset(&kd, 0, sizeof(kd));
4182	kd.common.rdclass = zone->rdclass;
4183	kd.common.rdtype = dns_rdatatype_keydata;
4184	ISC_LINK_INIT(&kd.common, link);
4185
4186	isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
4187
4188	CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
4189				   &kd, &rrdatabuf));
4190	/* Add rdata to zone. */
4191	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
4192	*changed = true;
4193
4194	/* Refresh new keys from the zone apex as soon as possible. */
4195	set_refreshkeytimer(zone, &kd, now, true);
4196	return (ISC_R_SUCCESS);
4197
4198failure:
4199	return (result);
4200}
4201
4202/*
4203 * Remove from the key zone all the KEYDATA records found in rdataset.
4204 */
4205static isc_result_t
4206delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4207	       dns_name_t *name, dns_rdataset_t *rdataset) {
4208	dns_rdata_t rdata = DNS_RDATA_INIT;
4209	isc_result_t result, uresult;
4210
4211	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4212	     result = dns_rdataset_next(rdataset))
4213	{
4214		dns_rdata_reset(&rdata);
4215		dns_rdataset_current(rdataset, &rdata);
4216		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
4217					&rdata);
4218		if (uresult != ISC_R_SUCCESS) {
4219			return (uresult);
4220		}
4221	}
4222	if (result == ISC_R_NOMORE) {
4223		result = ISC_R_SUCCESS;
4224	}
4225	return (result);
4226}
4227
4228/*
4229 * Compute the DNSSEC key ID for a DNSKEY record.
4230 */
4231static isc_result_t
4232compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
4233	    dns_keytag_t *tag) {
4234	isc_result_t result;
4235	dns_rdata_t rdata = DNS_RDATA_INIT;
4236	unsigned char data[4096];
4237	isc_buffer_t buffer;
4238	dst_key_t *dstkey = NULL;
4239
4240	isc_buffer_init(&buffer, data, sizeof(data));
4241	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4242			     dns_rdatatype_dnskey, dnskey, &buffer);
4243
4244	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
4245	if (result == ISC_R_SUCCESS) {
4246		*tag = dst_key_id(dstkey);
4247		dst_key_free(&dstkey);
4248	}
4249
4250	return (result);
4251}
4252
4253/*
4254 * Add key to the security roots.
4255 */
4256static void
4257trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
4258	  bool initial) {
4259	isc_result_t result;
4260	dns_rdata_t rdata = DNS_RDATA_INIT;
4261	unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
4262	isc_buffer_t buffer;
4263	dns_keytable_t *sr = NULL;
4264	dns_rdata_ds_t ds;
4265
4266	result = dns_view_getsecroots(zone->view, &sr);
4267	if (result != ISC_R_SUCCESS) {
4268		return;
4269	}
4270
4271	/* Build DS record for key. */
4272	isc_buffer_init(&buffer, data, sizeof(data));
4273	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4274			     dns_rdatatype_dnskey, dnskey, &buffer);
4275	CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
4276				  &ds));
4277	CHECK(dns_keytable_add(sr, true, initial, keyname, &ds));
4278
4279	dns_keytable_detach(&sr);
4280
4281failure:
4282	if (sr != NULL) {
4283		dns_keytable_detach(&sr);
4284	}
4285	return;
4286}
4287
4288/*
4289 * Add a null key to the security roots for so that all queries
4290 * to the zone will fail.
4291 */
4292static void
4293fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4294	isc_result_t result;
4295	dns_keytable_t *sr = NULL;
4296
4297	result = dns_view_getsecroots(zone->view, &sr);
4298	if (result == ISC_R_SUCCESS) {
4299		dns_keytable_marksecure(sr, keyname);
4300		dns_keytable_detach(&sr);
4301	}
4302}
4303
4304/*
4305 * Scan a set of KEYDATA records from the key zone.  The ones that are
4306 * valid (i.e., the add holddown timer has expired) become trusted keys.
4307 */
4308static void
4309load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4310	isc_result_t result;
4311	dns_rdata_t rdata = DNS_RDATA_INIT;
4312	dns_rdata_keydata_t keydata;
4313	dns_rdata_dnskey_t dnskey;
4314	int trusted = 0, revoked = 0, pending = 0;
4315	isc_stdtime_t now;
4316	dns_keytable_t *sr = NULL;
4317
4318	isc_stdtime_get(&now);
4319
4320	result = dns_view_getsecroots(zone->view, &sr);
4321	if (result == ISC_R_SUCCESS) {
4322		dns_keytable_delete(sr, name);
4323		dns_keytable_detach(&sr);
4324	}
4325
4326	/* Now insert all the accepted trust anchors from this keydata set. */
4327	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4328	     result = dns_rdataset_next(rdataset))
4329	{
4330		dns_rdata_reset(&rdata);
4331		dns_rdataset_current(rdataset, &rdata);
4332
4333		/* Convert rdata to keydata. */
4334		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4335		if (result == ISC_R_UNEXPECTEDEND) {
4336			continue;
4337		}
4338		RUNTIME_CHECK(result == ISC_R_SUCCESS);
4339
4340		/* Set the key refresh timer to force a fast refresh. */
4341		set_refreshkeytimer(zone, &keydata, now, true);
4342
4343		/* If the removal timer is nonzero, this key was revoked. */
4344		if (keydata.removehd != 0) {
4345			revoked++;
4346			continue;
4347		}
4348
4349		/*
4350		 * If the add timer is still pending, this key is not
4351		 * trusted yet.
4352		 */
4353		if (now < keydata.addhd) {
4354			pending++;
4355			continue;
4356		}
4357
4358		/* Convert keydata to dnskey. */
4359		dns_keydata_todnskey(&keydata, &dnskey, NULL);
4360
4361		/* Add to keytables. */
4362		trusted++;
4363		trust_key(zone, name, &dnskey, (keydata.addhd == 0));
4364	}
4365
4366	if (trusted == 0 && pending != 0) {
4367		char namebuf[DNS_NAME_FORMATSIZE];
4368		dns_name_format(name, namebuf, sizeof namebuf);
4369		dnssec_log(zone, ISC_LOG_ERROR,
4370			   "No valid trust anchors for '%s'!", namebuf);
4371		dnssec_log(zone, ISC_LOG_ERROR,
4372			   "%d key(s) revoked, %d still pending", revoked,
4373			   pending);
4374		dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
4375			   namebuf);
4376		fail_secure(zone, name);
4377	}
4378}
4379
4380static isc_result_t
4381do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4382	     dns_diff_t *diff) {
4383	dns_diff_t temp_diff;
4384	isc_result_t result;
4385
4386	/*
4387	 * Create a singleton diff.
4388	 */
4389	dns_diff_init(diff->mctx, &temp_diff);
4390	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4391
4392	/*
4393	 * Apply it to the database.
4394	 */
4395	result = dns_diff_apply(&temp_diff, db, ver);
4396	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4397	if (result != ISC_R_SUCCESS) {
4398		dns_difftuple_free(tuple);
4399		return (result);
4400	}
4401
4402	/*
4403	 * Merge it into the current pending journal entry.
4404	 */
4405	dns_diff_appendminimal(diff, tuple);
4406
4407	/*
4408	 * Do not clear temp_diff.
4409	 */
4410	return (ISC_R_SUCCESS);
4411}
4412
4413static isc_result_t
4414update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4415	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4416	      dns_rdata_t *rdata) {
4417	dns_difftuple_t *tuple = NULL;
4418	isc_result_t result;
4419	result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
4420	if (result != ISC_R_SUCCESS) {
4421		return (result);
4422	}
4423	return (do_one_tuple(&tuple, db, ver, diff));
4424}
4425
4426static isc_result_t
4427update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4428		  dns_diff_t *diff, isc_mem_t *mctx,
4429		  dns_updatemethod_t method) {
4430	dns_difftuple_t *deltuple = NULL;
4431	dns_difftuple_t *addtuple = NULL;
4432	uint32_t serial;
4433	isc_result_t result;
4434	dns_updatemethod_t used = dns_updatemethod_none;
4435
4436	INSIST(method != dns_updatemethod_none);
4437
4438	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4439	CHECK(dns_difftuple_copy(deltuple, &addtuple));
4440	addtuple->op = DNS_DIFFOP_ADD;
4441
4442	serial = dns_soa_getserial(&addtuple->rdata);
4443	serial = dns_update_soaserial(serial, method, &used);
4444	if (method != used) {
4445		dns_zone_log(zone, ISC_LOG_WARNING,
4446			     "update_soa_serial:new serial would be lower than "
4447			     "old serial, using increment method instead");
4448	}
4449	dns_soa_setserial(serial, &addtuple->rdata);
4450	CHECK(do_one_tuple(&deltuple, db, ver, diff));
4451	CHECK(do_one_tuple(&addtuple, db, ver, diff));
4452	result = ISC_R_SUCCESS;
4453
4454failure:
4455	if (addtuple != NULL) {
4456		dns_difftuple_free(&addtuple);
4457	}
4458	if (deltuple != NULL) {
4459		dns_difftuple_free(&deltuple);
4460	}
4461	return (result);
4462}
4463
4464/*
4465 * Write all transactions in 'diff' to the zone journal file.
4466 */
4467static isc_result_t
4468zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4469	     const char *caller) {
4470	const char me[] = "zone_journal";
4471	const char *journalfile;
4472	isc_result_t result = ISC_R_SUCCESS;
4473	dns_journal_t *journal = NULL;
4474	unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
4475
4476	ENTER;
4477	journalfile = dns_zone_getjournal(zone);
4478	if (journalfile != NULL) {
4479		result = dns_journal_open(zone->mctx, journalfile, mode,
4480					  &journal);
4481		if (result != ISC_R_SUCCESS) {
4482			dns_zone_log(zone, ISC_LOG_ERROR,
4483				     "%s:dns_journal_open -> %s", caller,
4484				     dns_result_totext(result));
4485			return (result);
4486		}
4487
4488		if (sourceserial != NULL) {
4489			dns_journal_set_sourceserial(journal, *sourceserial);
4490		}
4491
4492		result = dns_journal_write_transaction(journal, diff);
4493		if (result != ISC_R_SUCCESS) {
4494			dns_zone_log(zone, ISC_LOG_ERROR,
4495				     "%s:dns_journal_write_transaction -> %s",
4496				     caller, dns_result_totext(result));
4497		}
4498		dns_journal_destroy(&journal);
4499	}
4500
4501	return (result);
4502}
4503
4504/*
4505 * Create an SOA record for a newly-created zone
4506 */
4507static isc_result_t
4508add_soa(dns_zone_t *zone, dns_db_t *db) {
4509	isc_result_t result;
4510	dns_rdata_t rdata = DNS_RDATA_INIT;
4511	unsigned char buf[DNS_SOA_BUFFERSIZE];
4512	dns_dbversion_t *ver = NULL;
4513	dns_diff_t diff;
4514
4515	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4516
4517	dns_diff_init(zone->mctx, &diff);
4518	result = dns_db_newversion(db, &ver);
4519	if (result != ISC_R_SUCCESS) {
4520		dns_zone_log(zone, ISC_LOG_ERROR,
4521			     "add_soa:dns_db_newversion -> %s",
4522			     dns_result_totext(result));
4523		goto failure;
4524	}
4525
4526	/* Build SOA record */
4527	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4528				    0, 0, 0, 0, 0, buf, &rdata);
4529	if (result != ISC_R_SUCCESS) {
4530		dns_zone_log(zone, ISC_LOG_ERROR,
4531			     "add_soa:dns_soa_buildrdata -> %s",
4532			     dns_result_totext(result));
4533		goto failure;
4534	}
4535
4536	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
4537			       &rdata);
4538
4539failure:
4540	dns_diff_clear(&diff);
4541	if (ver != NULL) {
4542		dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4543	}
4544
4545	INSIST(ver == NULL);
4546
4547	return (result);
4548}
4549
4550struct addifmissing_arg {
4551	dns_db_t *db;
4552	dns_dbversion_t *ver;
4553	dns_diff_t *diff;
4554	dns_zone_t *zone;
4555	bool *changed;
4556	isc_result_t result;
4557};
4558
4559static void
4560addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
4561	     dns_name_t *keyname, void *arg) {
4562	dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4563	dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4564	dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4565	dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4566	bool *changed = ((struct addifmissing_arg *)arg)->changed;
4567	isc_result_t result;
4568	dns_fixedname_t fname;
4569
4570	UNUSED(keytable);
4571
4572	if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
4573		return;
4574	}
4575
4576	if (!dns_keynode_managed(keynode)) {
4577		return;
4578	}
4579
4580	/*
4581	 * If the keynode has no trust anchor set, return.
4582	 */
4583	if (!dns_keynode_dsset(keynode, NULL)) {
4584		return;
4585	}
4586
4587	/*
4588	 * Check whether there's already a KEYDATA entry for this name;
4589	 * if so, we don't need to add another.
4590	 */
4591	dns_fixedname_init(&fname);
4592	result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
4593			     DNS_DBFIND_NOWILD, 0, NULL,
4594			     dns_fixedname_name(&fname), NULL, NULL);
4595	if (result == ISC_R_SUCCESS) {
4596		return;
4597	}
4598
4599	/*
4600	 * Create the keydata.
4601	 */
4602	result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
4603	if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
4604		((struct addifmissing_arg *)arg)->result = result;
4605	}
4606}
4607
4608/*
4609 * Synchronize the set of initializing keys found in managed-keys {}
4610 * statements with the set of trust anchors found in the managed-keys.bind
4611 * zone.  If a domain is no longer named in managed-keys, delete all keys
4612 * from that domain from the key zone.	If a domain is configured as an
4613 * initial-key in trust-anchors, but there are no references to it in the
4614 * key zone, load the key zone with the initializing key(s) for that
4615 * domain and schedule a key refresh. If a domain is configured as
4616 * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
4617 * zone with the matching key, and schedule a key refresh.
4618 */
4619static isc_result_t
4620sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4621	isc_result_t result = ISC_R_SUCCESS;
4622	bool changed = false;
4623	bool commit = false;
4624	dns_keynode_t *keynode = NULL;
4625	dns_view_t *view = zone->view;
4626	dns_keytable_t *sr = NULL;
4627	dns_dbversion_t *ver = NULL;
4628	dns_diff_t diff;
4629	dns_rriterator_t rrit;
4630	struct addifmissing_arg arg;
4631
4632	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4633
4634	dns_diff_init(zone->mctx, &diff);
4635
4636	CHECK(dns_view_getsecroots(view, &sr));
4637
4638	result = dns_db_newversion(db, &ver);
4639	if (result != ISC_R_SUCCESS) {
4640		dnssec_log(zone, ISC_LOG_ERROR,
4641			   "sync_keyzone:dns_db_newversion -> %s",
4642			   dns_result_totext(result));
4643		goto failure;
4644	}
4645
4646	/*
4647	 * Walk the zone DB.  If we find any keys whose names are no longer
4648	 * in trust-anchors, or which have been changed from initial to static,
4649	 * (meaning they are permanent and not RFC5011-maintained), delete
4650	 * them from the zone.  Otherwise call load_secroots(), which
4651	 * loads keys into secroots as appropriate.
4652	 */
4653	dns_rriterator_init(&rrit, db, ver, 0);
4654	for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
4655	     result = dns_rriterator_nextrrset(&rrit))
4656	{
4657		dns_rdataset_t *rdataset = NULL;
4658		dns_rdata_t rdata = DNS_RDATA_INIT;
4659		dns_rdata_keydata_t keydata;
4660		isc_stdtime_t now;
4661		bool load = true;
4662		dns_name_t *rrname = NULL;
4663		uint32_t ttl;
4664
4665		isc_stdtime_get(&now);
4666
4667		dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4668		if (!dns_rdataset_isassociated(rdataset)) {
4669			dns_rriterator_destroy(&rrit);
4670			goto failure;
4671		}
4672
4673		if (rdataset->type != dns_rdatatype_keydata) {
4674			continue;
4675		}
4676
4677		/*
4678		 * The managed-keys zone can contain a placeholder instead of
4679		 * legitimate data, in which case we will not use it, and we
4680		 * will try to refresh it.
4681		 */
4682		for (result = dns_rdataset_first(rdataset);
4683		     result == ISC_R_SUCCESS;
4684		     result = dns_rdataset_next(rdataset))
4685		{
4686			isc_result_t iresult;
4687
4688			dns_rdata_reset(&rdata);
4689			dns_rdataset_current(rdataset, &rdata);
4690
4691			iresult = dns_rdata_tostruct(&rdata, &keydata, NULL);
4692			/* Do we have a valid placeholder KEYDATA record? */
4693			if (iresult == ISC_R_SUCCESS && keydata.flags == 0 &&
4694			    keydata.protocol == 0 && keydata.algorithm == 0)
4695			{
4696				set_refreshkeytimer(zone, &keydata, now, true);
4697				load = false;
4698			}
4699		}
4700
4701		/*
4702		 * Release db wrlock to prevent LOR reports against
4703		 * dns_keytable_forall() call below.
4704		 */
4705		dns_rriterator_pause(&rrit);
4706		result = dns_keytable_find(sr, rrname, &keynode);
4707		if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
4708			CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
4709			changed = true;
4710		} else if (load) {
4711			load_secroots(zone, rrname, rdataset);
4712		}
4713
4714		if (keynode != NULL) {
4715			dns_keytable_detachkeynode(sr, &keynode);
4716		}
4717	}
4718	dns_rriterator_destroy(&rrit);
4719
4720	/*
4721	 * Walk secroots to find any initial keys that aren't in
4722	 * the zone.  If we find any, add them to the zone directly.
4723	 * If any DS-style initial keys are found, refresh the key
4724	 * zone so that they'll be looked up.
4725	 */
4726	arg.db = db;
4727	arg.ver = ver;
4728	arg.result = ISC_R_SUCCESS;
4729	arg.diff = &diff;
4730	arg.zone = zone;
4731	arg.changed = &changed;
4732	dns_keytable_forall(sr, addifmissing, &arg);
4733	result = arg.result;
4734	if (changed) {
4735		/* Write changes to journal file. */
4736		CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
4737					zone->updatemethod));
4738		CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4739
4740		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4741		zone_needdump(zone, 30);
4742		commit = true;
4743	}
4744
4745failure:
4746	if (result != ISC_R_SUCCESS) {
4747		dnssec_log(zone, ISC_LOG_ERROR,
4748			   "unable to synchronize managed keys: %s",
4749			   dns_result_totext(result));
4750		isc_time_settoepoch(&zone->refreshkeytime);
4751	}
4752	if (keynode != NULL) {
4753		dns_keytable_detachkeynode(sr, &keynode);
4754	}
4755	if (sr != NULL) {
4756		dns_keytable_detach(&sr);
4757	}
4758	if (ver != NULL) {
4759		dns_db_closeversion(db, &ver, commit);
4760	}
4761	dns_diff_clear(&diff);
4762
4763	INSIST(ver == NULL);
4764
4765	return (result);
4766}
4767
4768isc_result_t
4769dns_zone_synckeyzone(dns_zone_t *zone) {
4770	isc_result_t result;
4771	dns_db_t *db = NULL;
4772
4773	if (zone->type != dns_zone_key) {
4774		return (DNS_R_BADZONE);
4775	}
4776
4777	CHECK(dns_zone_getdb(zone, &db));
4778
4779	LOCK_ZONE(zone);
4780	result = sync_keyzone(zone, db);
4781	UNLOCK_ZONE(zone);
4782
4783failure:
4784	if (db != NULL) {
4785		dns_db_detach(&db);
4786	}
4787	return (result);
4788}
4789
4790static void
4791maybe_send_secure(dns_zone_t *zone) {
4792	isc_result_t result;
4793
4794	/*
4795	 * We've finished loading, or else failed to load, an inline-signing
4796	 * 'secure' zone.  We now need information about the status of the
4797	 * 'raw' zone.  If we failed to load, then we need it to send a
4798	 * copy of its database; if we succeeded, we need it to send its
4799	 * serial number so that we can sync with it.  If it has not yet
4800	 * loaded, we set a flag so that it will send the necessary
4801	 * information when it has finished loading.
4802	 */
4803	if (zone->raw->db != NULL) {
4804		if (zone->db != NULL) {
4805			uint32_t serial;
4806			unsigned int soacount;
4807
4808			result = zone_get_from_db(
4809				zone->raw, zone->raw->db, NULL, &soacount, NULL,
4810				&serial, NULL, NULL, NULL, NULL, NULL);
4811			if (result == ISC_R_SUCCESS && soacount > 0U) {
4812				zone_send_secureserial(zone->raw, serial);
4813			}
4814		} else {
4815			zone_send_securedb(zone->raw, zone->raw->db);
4816		}
4817	} else {
4818		DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4819	}
4820}
4821
4822static bool
4823zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4824	isc_result_t result;
4825	bool answer = false;
4826	dns_diff_t diff;
4827
4828	dns_diff_init(mctx, &diff);
4829	result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4830	if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
4831		answer = true;
4832	}
4833	dns_diff_clear(&diff);
4834	return (answer);
4835}
4836
4837/*
4838 * The zone is presumed to be locked.
4839 * If this is a inline_raw zone the secure version is also locked.
4840 */
4841static isc_result_t
4842zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4843	      isc_result_t result) {
4844	unsigned int soacount = 0;
4845	unsigned int nscount = 0;
4846	unsigned int errors = 0;
4847	uint32_t serial, oldserial, refresh, retry, expire, minimum, soattl;
4848	isc_time_t now;
4849	bool needdump = false;
4850	bool fixjournal = false;
4851	bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4852	bool nomaster = false;
4853	bool had_db = false;
4854	dns_include_t *inc;
4855	bool is_dynamic = false;
4856
4857	INSIST(LOCKED_ZONE(zone));
4858	if (inline_raw(zone)) {
4859		INSIST(LOCKED_ZONE(zone->secure));
4860	}
4861
4862	TIME_NOW(&now);
4863
4864	/*
4865	 * Initiate zone transfer?  We may need a error code that
4866	 * indicates that the "permanent" form does not exist.
4867	 * XXX better error feedback to log.
4868	 */
4869	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4870		if (zone->type == dns_zone_secondary ||
4871		    zone->type == dns_zone_mirror ||
4872		    zone->type == dns_zone_stub ||
4873		    (zone->type == dns_zone_redirect && zone->masters == NULL))
4874		{
4875			if (result == ISC_R_FILENOTFOUND) {
4876				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4877					      ISC_LOG_DEBUG(1),
4878					      "no master file");
4879			} else if (result != DNS_R_NOMASTERFILE) {
4880				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4881					      ISC_LOG_ERROR,
4882					      "loading from master file %s "
4883					      "failed: %s",
4884					      zone->masterfile,
4885					      dns_result_totext(result));
4886			}
4887		} else if (zone->type == dns_zone_primary &&
4888			   inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4889		{
4890			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4891				      ISC_LOG_DEBUG(1),
4892				      "no master file, requesting db");
4893			maybe_send_secure(zone);
4894		} else {
4895			int level = ISC_LOG_ERROR;
4896			if (zone->type == dns_zone_key &&
4897			    result == ISC_R_FILENOTFOUND)
4898			{
4899				level = ISC_LOG_DEBUG(1);
4900			}
4901			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4902				      "loading from master file %s failed: %s",
4903				      zone->masterfile,
4904				      dns_result_totext(result));
4905			nomaster = true;
4906		}
4907
4908		if (zone->type != dns_zone_key) {
4909			goto cleanup;
4910		}
4911	}
4912
4913	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4914		      "number of nodes in database: %u", dns_db_nodecount(db));
4915
4916	if (result == DNS_R_SEENINCLUDE) {
4917		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4918	} else {
4919		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4920	}
4921
4922	/*
4923	 * If there's no master file for a key zone, then the zone is new:
4924	 * create an SOA record.  (We do this now, instead of later, so that
4925	 * if there happens to be a journal file, we can roll forward from
4926	 * a sane starting point.)
4927	 */
4928	if (nomaster && zone->type == dns_zone_key) {
4929		result = add_soa(zone, db);
4930		if (result != ISC_R_SUCCESS) {
4931			goto cleanup;
4932		}
4933	}
4934
4935	/*
4936	 * Apply update log, if any, on initial load.
4937	 */
4938	if (zone->journal != NULL &&
4939	    !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4940	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4941	{
4942		result = zone_journal_rollforward(zone, db, &needdump,
4943						  &fixjournal);
4944		if (result != ISC_R_SUCCESS) {
4945			goto cleanup;
4946		}
4947	}
4948
4949	/*
4950	 * Obtain ns, soa and cname counts for top of zone.
4951	 */
4952	INSIST(db != NULL);
4953	result = zone_get_from_db(zone, db, &nscount, &soacount, &soattl,
4954				  &serial, &refresh, &retry, &expire, &minimum,
4955				  &errors);
4956	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4957		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
4958			      "could not find NS and/or SOA records");
4959	}
4960
4961	/*
4962	 * Process any queued NSEC3PARAM change requests. Only for dynamic
4963	 * zones, an inline-signing zone will perform this action when
4964	 * receiving the secure db (receive_secure_db).
4965	 */
4966	is_dynamic = dns_zone_isdynamic(zone, true);
4967	if (is_dynamic) {
4968		isc_event_t *setnsec3param_event;
4969		dns_zone_t *dummy;
4970
4971		while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
4972			setnsec3param_event =
4973				ISC_LIST_HEAD(zone->setnsec3param_queue);
4974			ISC_LIST_UNLINK(zone->setnsec3param_queue,
4975					setnsec3param_event, ev_link);
4976			dummy = NULL;
4977			zone_iattach(zone, &dummy);
4978			isc_task_send(zone->task, &setnsec3param_event);
4979		}
4980	}
4981
4982	/*
4983	 * Check to make sure the journal is up to date, and remove the
4984	 * journal file if it isn't, as we wouldn't be able to apply
4985	 * updates otherwise.
4986	 */
4987	if (zone->journal != NULL && is_dynamic &&
4988	    !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
4989	{
4990		uint32_t jserial;
4991		dns_journal_t *journal = NULL;
4992		bool empty = false;
4993
4994		result = dns_journal_open(zone->mctx, zone->journal,
4995					  DNS_JOURNAL_READ, &journal);
4996		if (result == ISC_R_SUCCESS) {
4997			jserial = dns_journal_last_serial(journal);
4998			empty = dns_journal_empty(journal);
4999			dns_journal_destroy(&journal);
5000		} else {
5001			jserial = serial;
5002			result = ISC_R_SUCCESS;
5003		}
5004
5005		if (jserial != serial) {
5006			if (!empty) {
5007				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5008					      ISC_LOG_INFO,
5009					      "journal file is out of date: "
5010					      "removing journal file");
5011			}
5012			if (remove(zone->journal) < 0 && errno != ENOENT) {
5013				char strbuf[ISC_STRERRORSIZE];
5014				strerror_r(errno, strbuf, sizeof(strbuf));
5015				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5016					      DNS_LOGMODULE_ZONE,
5017					      ISC_LOG_WARNING,
5018					      "unable to remove journal "
5019					      "'%s': '%s'",
5020					      zone->journal, strbuf);
5021			}
5022		}
5023	}
5024
5025	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
5026		      "loaded; checking validity");
5027
5028	/*
5029	 * Master / Slave / Mirror / Stub zones require both NS and SOA records
5030	 * at the top of the zone.
5031	 */
5032
5033	switch (zone->type) {
5034	case dns_zone_dlz:
5035	case dns_zone_primary:
5036	case dns_zone_secondary:
5037	case dns_zone_mirror:
5038	case dns_zone_stub:
5039	case dns_zone_redirect:
5040		if (soacount != 1) {
5041			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5042				      ISC_LOG_ERROR, "has %d SOA records",
5043				      soacount);
5044			result = DNS_R_BADZONE;
5045		}
5046		if (nscount == 0) {
5047			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5048				      ISC_LOG_ERROR, "has no NS records");
5049			result = DNS_R_BADZONE;
5050		}
5051		if (result != ISC_R_SUCCESS) {
5052			goto cleanup;
5053		}
5054		if (zone->type == dns_zone_primary && errors != 0) {
5055			result = DNS_R_BADZONE;
5056			goto cleanup;
5057		}
5058		if (zone->type != dns_zone_stub &&
5059		    zone->type != dns_zone_redirect)
5060		{
5061			result = check_nsec3param(zone, db);
5062			if (result != ISC_R_SUCCESS) {
5063				goto cleanup;
5064			}
5065		}
5066		if (zone->type == dns_zone_primary &&
5067		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
5068		    !integrity_checks(zone, db))
5069		{
5070			result = DNS_R_BADZONE;
5071			goto cleanup;
5072		}
5073		if (zone->type == dns_zone_primary &&
5074		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
5075		    !zone_check_dup(zone, db))
5076		{
5077			result = DNS_R_BADZONE;
5078			goto cleanup;
5079		}
5080
5081		if (zone->type == dns_zone_primary) {
5082			result = dns_zone_cdscheck(zone, db, NULL);
5083			if (result != ISC_R_SUCCESS) {
5084				dns_zone_log(zone, ISC_LOG_ERROR,
5085					     "CDS/CDNSKEY consistency checks "
5086					     "failed");
5087				goto cleanup;
5088			}
5089		}
5090
5091		result = dns_zone_verifydb(zone, db, NULL);
5092		if (result != ISC_R_SUCCESS) {
5093			goto cleanup;
5094		}
5095
5096		if (zone->db != NULL) {
5097			unsigned int oldsoacount;
5098
5099			/*
5100			 * This is checked in zone_replacedb() for slave zones
5101			 * as they don't reload from disk.
5102			 */
5103			result = zone_get_from_db(
5104				zone, zone->db, NULL, &oldsoacount, NULL,
5105				&oldserial, NULL, NULL, NULL, NULL, NULL);
5106			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5107			RUNTIME_CHECK(oldsoacount > 0U);
5108			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
5109			    !isc_serial_gt(serial, oldserial))
5110			{
5111				uint32_t serialmin, serialmax;
5112
5113				INSIST(zone->type == dns_zone_primary);
5114				INSIST(zone->raw == NULL);
5115
5116				if (serial == oldserial &&
5117				    zone_unchanged(zone->db, db, zone->mctx))
5118				{
5119					dns_zone_logc(zone,
5120						      DNS_LOGCATEGORY_ZONELOAD,
5121						      ISC_LOG_INFO,
5122						      "ixfr-from-differences: "
5123						      "unchanged");
5124					zone->loadtime = loadtime;
5125					goto done;
5126				}
5127
5128				serialmin = (oldserial + 1) & 0xffffffffU;
5129				serialmax = (oldserial + 0x7fffffffU) &
5130					    0xffffffffU;
5131				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5132					      ISC_LOG_ERROR,
5133					      "ixfr-from-differences: "
5134					      "new serial (%u) out of range "
5135					      "[%u - %u]",
5136					      serial, serialmin, serialmax);
5137				result = DNS_R_BADZONE;
5138				goto cleanup;
5139			} else if (!isc_serial_ge(serial, oldserial)) {
5140				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5141					      ISC_LOG_ERROR,
5142					      "zone serial (%u/%u) has gone "
5143					      "backwards",
5144					      serial, oldserial);
5145			} else if (serial == oldserial && !hasinclude &&
5146				   strcmp(zone->db_argv[0], "_builtin") != 0)
5147			{
5148				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5149					      ISC_LOG_ERROR,
5150					      "zone serial (%u) unchanged. "
5151					      "zone may fail to transfer "
5152					      "to slaves.",
5153					      serial);
5154			}
5155		}
5156
5157		if (zone->type == dns_zone_primary &&
5158		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
5159		    dns_zone_getsigresigninginterval(zone) < (3 * refresh) &&
5160		    dns_db_issecure(db))
5161		{
5162			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5163				      ISC_LOG_WARNING,
5164				      "sig-re-signing-interval less than "
5165				      "3 * refresh.");
5166		}
5167
5168		zone->refresh = RANGE(refresh, zone->minrefresh,
5169				      zone->maxrefresh);
5170		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
5171		zone->expire = RANGE(expire, zone->refresh + zone->retry,
5172				     DNS_MAX_EXPIRE);
5173		zone->soattl = soattl;
5174		zone->minimum = minimum;
5175		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5176
5177		if (zone->type == dns_zone_secondary ||
5178		    zone->type == dns_zone_mirror ||
5179		    zone->type == dns_zone_stub ||
5180		    (zone->type == dns_zone_redirect && zone->masters != NULL))
5181		{
5182			isc_time_t t;
5183			uint32_t delay;
5184
5185			result = isc_file_getmodtime(zone->journal, &t);
5186			if (result != ISC_R_SUCCESS) {
5187				result = isc_file_getmodtime(zone->masterfile,
5188							     &t);
5189			}
5190			if (result == ISC_R_SUCCESS) {
5191				DNS_ZONE_TIME_ADD(&t, zone->expire,
5192						  &zone->expiretime);
5193			} else {
5194				DNS_ZONE_TIME_ADD(&now, zone->retry,
5195						  &zone->expiretime);
5196			}
5197
5198			delay = (zone->retry -
5199				 isc_random_uniform((zone->retry * 3) / 4));
5200			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
5201			if (isc_time_compare(&zone->refreshtime,
5202					     &zone->expiretime) >= 0)
5203			{
5204				zone->refreshtime = now;
5205			}
5206		}
5207
5208		break;
5209
5210	case dns_zone_key:
5211		/* Nothing needs to be done now */
5212		break;
5213
5214	default:
5215		UNEXPECTED_ERROR(__FILE__, __LINE__, "unexpected zone type %d",
5216				 zone->type);
5217		result = ISC_R_UNEXPECTED;
5218		goto cleanup;
5219	}
5220
5221	/*
5222	 * Check for weak DNSKEY's.
5223	 */
5224	if (zone->type == dns_zone_primary) {
5225		zone_check_dnskeys(zone, db);
5226	}
5227
5228	/*
5229	 * Schedule DNSSEC key refresh.
5230	 */
5231	if (zone->type == dns_zone_primary &&
5232	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
5233	{
5234		zone->refreshkeytime = now;
5235	}
5236
5237	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5238	if (zone->db != NULL) {
5239		had_db = true;
5240		result = zone_replacedb(zone, db, false);
5241		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5242		if (result != ISC_R_SUCCESS) {
5243			goto cleanup;
5244		}
5245	} else {
5246		zone_attachdb(zone, db);
5247		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5248		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED |
5249					       DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
5250		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
5251		    inline_raw(zone))
5252		{
5253			if (zone->secure->db == NULL) {
5254				zone_send_securedb(zone, db);
5255			} else {
5256				zone_send_secureserial(zone, serial);
5257			}
5258		}
5259	}
5260
5261	/*
5262	 * Finished loading inline-signing zone; need to get status
5263	 * from the raw side now.
5264	 */
5265	if (zone->type == dns_zone_primary && inline_secure(zone)) {
5266		maybe_send_secure(zone);
5267	}
5268
5269	result = ISC_R_SUCCESS;
5270
5271	if (fixjournal) {
5272		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
5273		zone_journal_compact(zone, zone->db, 0);
5274	}
5275	if (needdump) {
5276		if (zone->type == dns_zone_key) {
5277			zone_needdump(zone, 30);
5278		} else {
5279			zone_needdump(zone, DNS_DUMP_DELAY);
5280		}
5281	}
5282
5283	if (zone->task != NULL) {
5284		if (zone->type == dns_zone_primary) {
5285			set_resigntime(zone);
5286			resume_signingwithkey(zone);
5287			resume_addnsec3chain(zone);
5288		}
5289
5290		is_dynamic = dns_zone_isdynamic(zone, false);
5291		if (zone->type == dns_zone_primary &&
5292		    !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
5293		    is_dynamic && dns_db_issecure(db))
5294		{
5295			dns_name_t *name;
5296			dns_fixedname_t fixed;
5297			dns_rdataset_t next;
5298
5299			dns_rdataset_init(&next);
5300			name = dns_fixedname_initname(&fixed);
5301
5302			result = dns_db_getsigningtime(db, &next, name);
5303			if (result == ISC_R_SUCCESS) {
5304				isc_stdtime_t timenow;
5305				char namebuf[DNS_NAME_FORMATSIZE];
5306				char typebuf[DNS_RDATATYPE_FORMATSIZE];
5307
5308				isc_stdtime_get(&timenow);
5309				dns_name_format(name, namebuf, sizeof(namebuf));
5310				dns_rdatatype_format(next.covers, typebuf,
5311						     sizeof(typebuf));
5312				dnssec_log(
5313					zone, ISC_LOG_DEBUG(3),
5314					"next resign: %s/%s "
5315					"in %d seconds",
5316					namebuf, typebuf,
5317					next.resign - timenow -
5318						dns_zone_getsigresigninginterval(
5319							zone));
5320				dns_rdataset_disassociate(&next);
5321			} else {
5322				dnssec_log(zone, ISC_LOG_WARNING,
5323					   "signed dynamic zone has no "
5324					   "resign event scheduled");
5325			}
5326		}
5327
5328		zone_settimer(zone, &now);
5329	}
5330
5331	/*
5332	 * Clear old include list.
5333	 */
5334	for (inc = ISC_LIST_HEAD(zone->includes); inc != NULL;
5335	     inc = ISC_LIST_HEAD(zone->includes))
5336	{
5337		ISC_LIST_UNLINK(zone->includes, inc, link);
5338		isc_mem_free(zone->mctx, inc->name);
5339		isc_mem_put(zone->mctx, inc, sizeof(*inc));
5340	}
5341	zone->nincludes = 0;
5342
5343	/*
5344	 * Transfer new include list.
5345	 */
5346	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5347	     inc = ISC_LIST_HEAD(zone->newincludes))
5348	{
5349		ISC_LIST_UNLINK(zone->newincludes, inc, link);
5350		ISC_LIST_APPEND(zone->includes, inc, link);
5351		zone->nincludes++;
5352	}
5353
5354	if (!dns_db_ispersistent(db)) {
5355		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5356			      "loaded serial %u%s", serial,
5357			      dns_db_issecure(db) ? " (DNSSEC signed)" : "");
5358	}
5359
5360	if (!had_db && zone->type == dns_zone_mirror) {
5361		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5362			      "mirror zone is now in use");
5363	}
5364
5365	zone->loadtime = loadtime;
5366	goto done;
5367
5368cleanup:
5369	if (result != ISC_R_SUCCESS) {
5370		dns_zone_rpz_disable_db(zone, db);
5371		dns_zone_catz_disable_db(zone, db);
5372	}
5373
5374	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5375	     inc = ISC_LIST_HEAD(zone->newincludes))
5376	{
5377		ISC_LIST_UNLINK(zone->newincludes, inc, link);
5378		isc_mem_free(zone->mctx, inc->name);
5379		isc_mem_put(zone->mctx, inc, sizeof(*inc));
5380	}
5381	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
5382	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
5383	    (zone->type == dns_zone_redirect && zone->masters != NULL))
5384	{
5385		if (result != ISC_R_NOMEMORY) {
5386			if (zone->journal != NULL) {
5387				zone_saveunique(zone, zone->journal,
5388						"jn-XXXXXXXX");
5389			}
5390			if (zone->masterfile != NULL) {
5391				zone_saveunique(zone, zone->masterfile,
5392						"db-XXXXXXXX");
5393			}
5394		}
5395
5396		/* Mark the zone for immediate refresh. */
5397		zone->refreshtime = now;
5398		if (zone->task != NULL) {
5399			zone_settimer(zone, &now);
5400		}
5401		result = ISC_R_SUCCESS;
5402	} else if (zone->type == dns_zone_primary ||
5403		   zone->type == dns_zone_redirect)
5404	{
5405		if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5406			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5407				      ISC_LOG_ERROR,
5408				      "not loaded due to errors.");
5409		} else if (zone->type == dns_zone_primary) {
5410			result = ISC_R_SUCCESS;
5411		}
5412	}
5413
5414done:
5415	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5416	/*
5417	 * If this is an inline-signed zone and we were called for the raw
5418	 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5419	 * as well, but only if this is a reload, not an initial zone load: in
5420	 * the former case, zone_postload() will not be run for the secure
5421	 * zone; in the latter case, it will be.  Check which case we are
5422	 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5423	 * secure zone: if it is set, this must be a reload.
5424	 */
5425	if (inline_raw(zone) && DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5426	{
5427		DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5428		/*
5429		 * Re-start zone maintenance if it had been stalled
5430		 * due to DNS_ZONEFLG_LOADPENDING being set when
5431		 * zone_maintenance was called.
5432		 */
5433		if (zone->secure->task != NULL) {
5434			zone_settimer(zone->secure, &now);
5435		}
5436	}
5437
5438	zone_debuglog(zone, "zone_postload", 99, "done");
5439
5440	return (result);
5441}
5442
5443static bool
5444exit_check(dns_zone_t *zone) {
5445	REQUIRE(LOCKED_ZONE(zone));
5446
5447	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
5448	    isc_refcount_current(&zone->irefs) == 0)
5449	{
5450		/*
5451		 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
5452		 */
5453		INSIST(isc_refcount_current(&zone->erefs) == 0);
5454		return (true);
5455	}
5456	return (false);
5457}
5458
5459static bool
5460zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5461	      dns_name_t *name, bool logit) {
5462	isc_result_t result;
5463	char namebuf[DNS_NAME_FORMATSIZE];
5464	char altbuf[DNS_NAME_FORMATSIZE];
5465	dns_fixedname_t fixed;
5466	dns_name_t *foundname;
5467	int level;
5468
5469	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) {
5470		return (true);
5471	}
5472
5473	if (zone->type == dns_zone_primary) {
5474		level = ISC_LOG_ERROR;
5475	} else {
5476		level = ISC_LOG_WARNING;
5477	}
5478
5479	foundname = dns_fixedname_initname(&fixed);
5480
5481	result = dns_db_find(db, name, version, dns_rdatatype_a, 0, 0, NULL,
5482			     foundname, NULL, NULL);
5483	if (result == ISC_R_SUCCESS) {
5484		return (true);
5485	}
5486
5487	if (result == DNS_R_NXRRSET) {
5488		result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0,
5489				     0, NULL, foundname, NULL, NULL);
5490		if (result == ISC_R_SUCCESS) {
5491			return (true);
5492		}
5493	}
5494
5495	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5496	    result == DNS_R_EMPTYNAME)
5497	{
5498		if (logit) {
5499			dns_name_format(name, namebuf, sizeof namebuf);
5500			dns_zone_log(zone, level,
5501				     "NS '%s' has no address "
5502				     "records (A or AAAA)",
5503				     namebuf);
5504		}
5505		return (false);
5506	}
5507
5508	if (result == DNS_R_CNAME) {
5509		if (logit) {
5510			dns_name_format(name, namebuf, sizeof namebuf);
5511			dns_zone_log(zone, level,
5512				     "NS '%s' is a CNAME "
5513				     "(illegal)",
5514				     namebuf);
5515		}
5516		return (false);
5517	}
5518
5519	if (result == DNS_R_DNAME) {
5520		if (logit) {
5521			dns_name_format(name, namebuf, sizeof namebuf);
5522			dns_name_format(foundname, altbuf, sizeof altbuf);
5523			dns_zone_log(zone, level,
5524				     "NS '%s' is below a DNAME "
5525				     "'%s' (illegal)",
5526				     namebuf, altbuf);
5527		}
5528		return (false);
5529	}
5530
5531	return (true);
5532}
5533
5534static isc_result_t
5535zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5536		 dns_dbversion_t *version, unsigned int *nscount,
5537		 unsigned int *errors, bool logit) {
5538	isc_result_t result;
5539	unsigned int count = 0;
5540	unsigned int ecount = 0;
5541	dns_rdataset_t rdataset;
5542	dns_rdata_t rdata;
5543	dns_rdata_ns_t ns;
5544
5545	dns_rdataset_init(&rdataset);
5546	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5547				     dns_rdatatype_none, 0, &rdataset, NULL);
5548	if (result == ISC_R_NOTFOUND) {
5549		INSIST(!dns_rdataset_isassociated(&rdataset));
5550		goto success;
5551	}
5552	if (result != ISC_R_SUCCESS) {
5553		INSIST(!dns_rdataset_isassociated(&rdataset));
5554		goto invalidate_rdataset;
5555	}
5556
5557	result = dns_rdataset_first(&rdataset);
5558	while (result == ISC_R_SUCCESS) {
5559		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5560		    (zone->type == dns_zone_primary ||
5561		     zone->type == dns_zone_secondary ||
5562		     zone->type == dns_zone_mirror))
5563		{
5564			dns_rdata_init(&rdata);
5565			dns_rdataset_current(&rdataset, &rdata);
5566			result = dns_rdata_tostruct(&rdata, &ns, NULL);
5567			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5568			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5569			    !zone_check_ns(zone, db, version, &ns.name, logit))
5570			{
5571				ecount++;
5572			}
5573		}
5574		count++;
5575		result = dns_rdataset_next(&rdataset);
5576	}
5577	dns_rdataset_disassociate(&rdataset);
5578
5579success:
5580	if (nscount != NULL) {
5581		*nscount = count;
5582	}
5583	if (errors != NULL) {
5584		*errors = ecount;
5585	}
5586
5587	result = ISC_R_SUCCESS;
5588
5589invalidate_rdataset:
5590	dns_rdataset_invalidate(&rdataset);
5591
5592	return (result);
5593}
5594
5595#define SET_IF_NOT_NULL(obj, val) \
5596	if (obj != NULL) {        \
5597		*obj = val;       \
5598	}
5599
5600#define SET_SOA_VALUES(soattl_v, serial_v, refresh_v, retry_v, expire_v, \
5601		       minimum_v)                                        \
5602	{                                                                \
5603		SET_IF_NOT_NULL(soattl, soattl_v);                       \
5604		SET_IF_NOT_NULL(serial, serial_v);                       \
5605		SET_IF_NOT_NULL(refresh, refresh_v);                     \
5606		SET_IF_NOT_NULL(retry, retry_v);                         \
5607		SET_IF_NOT_NULL(expire, expire_v);                       \
5608		SET_IF_NOT_NULL(minimum, minimum_v);                     \
5609	}
5610
5611#define CLR_SOA_VALUES()                          \
5612	{                                         \
5613		SET_SOA_VALUES(0, 0, 0, 0, 0, 0); \
5614	}
5615
5616static isc_result_t
5617zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5618		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5619		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5620		 uint32_t *minimum) {
5621	isc_result_t result;
5622	unsigned int count = 0;
5623	dns_rdataset_t rdataset;
5624	dns_rdata_t rdata = DNS_RDATA_INIT;
5625
5626	dns_rdataset_init(&rdataset);
5627	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5628				     dns_rdatatype_none, 0, &rdataset, NULL);
5629	if (result == ISC_R_NOTFOUND) {
5630		INSIST(!dns_rdataset_isassociated(&rdataset));
5631		result = ISC_R_SUCCESS;
5632		goto invalidate_rdataset;
5633	}
5634	if (result != ISC_R_SUCCESS) {
5635		INSIST(!dns_rdataset_isassociated(&rdataset));
5636		goto invalidate_rdataset;
5637	}
5638
5639	result = dns_rdataset_first(&rdataset);
5640	while (result == ISC_R_SUCCESS) {
5641		dns_rdata_init(&rdata);
5642		dns_rdataset_current(&rdataset, &rdata);
5643		count++;
5644		if (count == 1) {
5645			dns_rdata_soa_t soa;
5646			result = dns_rdata_tostruct(&rdata, &soa, NULL);
5647			SET_SOA_VALUES(rdataset.ttl, soa.serial, soa.refresh,
5648				       soa.retry, soa.expire, soa.minimum);
5649			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5650		}
5651
5652		result = dns_rdataset_next(&rdataset);
5653		dns_rdata_reset(&rdata);
5654	}
5655	dns_rdataset_disassociate(&rdataset);
5656
5657	result = ISC_R_SUCCESS;
5658
5659invalidate_rdataset:
5660	SET_IF_NOT_NULL(soacount, count);
5661	if (count == 0) {
5662		CLR_SOA_VALUES();
5663	}
5664
5665	dns_rdataset_invalidate(&rdataset);
5666
5667	return (result);
5668}
5669
5670/*
5671 * zone must be locked.
5672 */
5673static isc_result_t
5674zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5675		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5676		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5677		 uint32_t *minimum, unsigned int *errors) {
5678	isc_result_t result;
5679	isc_result_t answer = ISC_R_SUCCESS;
5680	dns_dbversion_t *version = NULL;
5681	dns_dbnode_t *node;
5682
5683	REQUIRE(db != NULL);
5684	REQUIRE(zone != NULL);
5685
5686	dns_db_currentversion(db, &version);
5687
5688	SET_IF_NOT_NULL(nscount, 0);
5689	SET_IF_NOT_NULL(soacount, 0);
5690	SET_IF_NOT_NULL(errors, 0);
5691	CLR_SOA_VALUES();
5692
5693	node = NULL;
5694	result = dns_db_findnode(db, &zone->origin, false, &node);
5695	if (result != ISC_R_SUCCESS) {
5696		answer = result;
5697		goto closeversion;
5698	}
5699
5700	if (nscount != NULL || errors != NULL) {
5701		result = zone_count_ns_rr(zone, db, node, version, nscount,
5702					  errors, true);
5703		if (result != ISC_R_SUCCESS) {
5704			answer = result;
5705		}
5706	}
5707
5708	if (soacount != NULL || soattl != NULL || serial != NULL ||
5709	    refresh != NULL || retry != NULL || expire != NULL ||
5710	    minimum != NULL)
5711	{
5712		result = zone_load_soa_rr(db, node, version, soacount, soattl,
5713					  serial, refresh, retry, expire,
5714					  minimum);
5715		if (result != ISC_R_SUCCESS) {
5716			answer = result;
5717		}
5718	}
5719
5720	dns_db_detachnode(db, &node);
5721closeversion:
5722	dns_db_closeversion(db, &version, false);
5723
5724	return (answer);
5725}
5726
5727void
5728dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5729	REQUIRE(DNS_ZONE_VALID(source));
5730	REQUIRE(target != NULL && *target == NULL);
5731	isc_refcount_increment(&source->erefs);
5732	*target = source;
5733}
5734
5735void
5736dns_zone_detach(dns_zone_t **zonep) {
5737	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5738
5739	dns_zone_t *zone = *zonep;
5740	*zonep = NULL;
5741
5742	if (isc_refcount_decrement(&zone->erefs) == 1) {
5743		isc_event_t *ev = &zone->ctlevent;
5744
5745		isc_refcount_destroy(&zone->erefs);
5746
5747		/*
5748		 * Stop things being restarted after we cancel them below.
5749		 */
5750		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
5751		dns_zone_log(zone, ISC_LOG_DEBUG(1),
5752			     "final reference detached");
5753		if (zone->task != NULL) {
5754			/*
5755			 * This zone has a task; it can clean
5756			 * itself up asynchronously.
5757			 */
5758			isc_task_send(zone->task, &ev);
5759			return;
5760		}
5761
5762		/*
5763		 * This zone is unmanaged; we're probably running in
5764		 * named-checkzone or a unit test. There's no task,
5765		 * so we need to free it immediately.
5766		 *
5767		 * Unmanaged zones must not have null views; we have no way
5768		 * of detaching from the view here without causing deadlock
5769		 * because this code is called with the view already
5770		 * locked.
5771		 */
5772		INSIST(zone->view == NULL);
5773
5774		zone_shutdown(zone->task, ev);
5775		ev = NULL;
5776	}
5777}
5778
5779void
5780dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5781	REQUIRE(DNS_ZONE_VALID(source));
5782
5783	LOCK_ZONE(source);
5784	zone_iattach(source, target);
5785	UNLOCK_ZONE(source);
5786}
5787
5788static void
5789zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5790	REQUIRE(DNS_ZONE_VALID(source));
5791	REQUIRE(LOCKED_ZONE(source));
5792	REQUIRE(target != NULL && *target == NULL);
5793	INSIST(isc_refcount_increment0(&source->irefs) +
5794		       isc_refcount_current(&source->erefs) >
5795	       0);
5796	*target = source;
5797}
5798
5799static void
5800zone_idetach(dns_zone_t **zonep) {
5801	dns_zone_t *zone;
5802
5803	/*
5804	 * 'zone' locked by caller.
5805	 */
5806	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5807	REQUIRE(LOCKED_ZONE(*zonep));
5808
5809	zone = *zonep;
5810	*zonep = NULL;
5811
5812	INSIST(isc_refcount_decrement(&zone->irefs) - 1 +
5813		       isc_refcount_current(&zone->erefs) >
5814	       0);
5815}
5816
5817void
5818dns_zone_idetach(dns_zone_t **zonep) {
5819	dns_zone_t *zone;
5820
5821	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5822
5823	zone = *zonep;
5824	*zonep = NULL;
5825
5826	if (isc_refcount_decrement(&zone->irefs) == 1) {
5827		bool free_needed;
5828		LOCK_ZONE(zone);
5829		free_needed = exit_check(zone);
5830		UNLOCK_ZONE(zone);
5831		if (free_needed) {
5832			zone_free(zone);
5833		}
5834	}
5835}
5836
5837isc_mem_t *
5838dns_zone_getmctx(dns_zone_t *zone) {
5839	REQUIRE(DNS_ZONE_VALID(zone));
5840
5841	return (zone->mctx);
5842}
5843
5844dns_zonemgr_t *
5845dns_zone_getmgr(dns_zone_t *zone) {
5846	REQUIRE(DNS_ZONE_VALID(zone));
5847
5848	return (zone->zmgr);
5849}
5850
5851void
5852dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
5853	REQUIRE(DNS_ZONE_VALID(zone));
5854
5855	LOCK_ZONE(zone);
5856	if (zone->kasp != NULL) {
5857		dns_kasp_detach(&zone->kasp);
5858	}
5859	if (kasp != NULL) {
5860		dns_kasp_attach(kasp, &zone->kasp);
5861	}
5862	UNLOCK_ZONE(zone);
5863}
5864
5865dns_kasp_t *
5866dns_zone_getkasp(dns_zone_t *zone) {
5867	REQUIRE(DNS_ZONE_VALID(zone));
5868
5869	return (zone->kasp);
5870}
5871
5872void
5873dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
5874	REQUIRE(DNS_ZONE_VALID(zone));
5875
5876	if (value) {
5877		DNS_ZONE_SETOPTION(zone, option);
5878	} else {
5879		DNS_ZONE_CLROPTION(zone, option);
5880	}
5881}
5882
5883dns_zoneopt_t
5884dns_zone_getoptions(dns_zone_t *zone) {
5885	REQUIRE(DNS_ZONE_VALID(zone));
5886
5887	return (atomic_load_relaxed(&zone->options));
5888}
5889
5890void
5891dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value) {
5892	REQUIRE(DNS_ZONE_VALID(zone));
5893
5894	if (value) {
5895		DNS_ZONEKEY_SETOPTION(zone, keyopt);
5896	} else {
5897		DNS_ZONEKEY_CLROPTION(zone, keyopt);
5898	}
5899}
5900
5901unsigned int
5902dns_zone_getkeyopts(dns_zone_t *zone) {
5903	REQUIRE(DNS_ZONE_VALID(zone));
5904
5905	return (atomic_load_relaxed(&zone->keyopts));
5906}
5907
5908isc_result_t
5909dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5910	REQUIRE(DNS_ZONE_VALID(zone));
5911
5912	LOCK_ZONE(zone);
5913	zone->xfrsource4 = *xfrsource;
5914	UNLOCK_ZONE(zone);
5915
5916	return (ISC_R_SUCCESS);
5917}
5918
5919isc_sockaddr_t *
5920dns_zone_getxfrsource4(dns_zone_t *zone) {
5921	REQUIRE(DNS_ZONE_VALID(zone));
5922	return (&zone->xfrsource4);
5923}
5924
5925isc_result_t
5926dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5927	REQUIRE(DNS_ZONE_VALID(zone));
5928
5929	LOCK_ZONE(zone);
5930	zone->xfrsource4dscp = dscp;
5931	UNLOCK_ZONE(zone);
5932
5933	return (ISC_R_SUCCESS);
5934}
5935
5936isc_dscp_t
5937dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
5938	REQUIRE(DNS_ZONE_VALID(zone));
5939	return (zone->xfrsource4dscp);
5940}
5941
5942isc_result_t
5943dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5944	REQUIRE(DNS_ZONE_VALID(zone));
5945
5946	LOCK_ZONE(zone);
5947	zone->xfrsource6 = *xfrsource;
5948	UNLOCK_ZONE(zone);
5949
5950	return (ISC_R_SUCCESS);
5951}
5952
5953isc_sockaddr_t *
5954dns_zone_getxfrsource6(dns_zone_t *zone) {
5955	REQUIRE(DNS_ZONE_VALID(zone));
5956	return (&zone->xfrsource6);
5957}
5958
5959isc_dscp_t
5960dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
5961	REQUIRE(DNS_ZONE_VALID(zone));
5962	return (zone->xfrsource6dscp);
5963}
5964
5965isc_result_t
5966dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5967	REQUIRE(DNS_ZONE_VALID(zone));
5968
5969	LOCK_ZONE(zone);
5970	zone->xfrsource6dscp = dscp;
5971	UNLOCK_ZONE(zone);
5972
5973	return (ISC_R_SUCCESS);
5974}
5975
5976isc_result_t
5977dns_zone_setaltxfrsource4(dns_zone_t *zone,
5978			  const isc_sockaddr_t *altxfrsource) {
5979	REQUIRE(DNS_ZONE_VALID(zone));
5980
5981	LOCK_ZONE(zone);
5982	zone->altxfrsource4 = *altxfrsource;
5983	UNLOCK_ZONE(zone);
5984
5985	return (ISC_R_SUCCESS);
5986}
5987
5988isc_sockaddr_t *
5989dns_zone_getaltxfrsource4(dns_zone_t *zone) {
5990	REQUIRE(DNS_ZONE_VALID(zone));
5991	return (&zone->altxfrsource4);
5992}
5993
5994isc_result_t
5995dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5996	REQUIRE(DNS_ZONE_VALID(zone));
5997
5998	LOCK_ZONE(zone);
5999	zone->altxfrsource4dscp = dscp;
6000	UNLOCK_ZONE(zone);
6001
6002	return (ISC_R_SUCCESS);
6003}
6004
6005isc_dscp_t
6006dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
6007	REQUIRE(DNS_ZONE_VALID(zone));
6008	return (zone->altxfrsource4dscp);
6009}
6010
6011isc_result_t
6012dns_zone_setaltxfrsource6(dns_zone_t *zone,
6013			  const isc_sockaddr_t *altxfrsource) {
6014	REQUIRE(DNS_ZONE_VALID(zone));
6015
6016	LOCK_ZONE(zone);
6017	zone->altxfrsource6 = *altxfrsource;
6018	UNLOCK_ZONE(zone);
6019
6020	return (ISC_R_SUCCESS);
6021}
6022
6023isc_sockaddr_t *
6024dns_zone_getaltxfrsource6(dns_zone_t *zone) {
6025	REQUIRE(DNS_ZONE_VALID(zone));
6026	return (&zone->altxfrsource6);
6027}
6028
6029isc_result_t
6030dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6031	REQUIRE(DNS_ZONE_VALID(zone));
6032
6033	LOCK_ZONE(zone);
6034	zone->altxfrsource6dscp = dscp;
6035	UNLOCK_ZONE(zone);
6036
6037	return (ISC_R_SUCCESS);
6038}
6039
6040isc_dscp_t
6041dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
6042	REQUIRE(DNS_ZONE_VALID(zone));
6043	return (zone->altxfrsource6dscp);
6044}
6045
6046isc_result_t
6047dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6048	REQUIRE(DNS_ZONE_VALID(zone));
6049
6050	LOCK_ZONE(zone);
6051	zone->parentalsrc4 = *parentalsrc;
6052	UNLOCK_ZONE(zone);
6053
6054	return (ISC_R_SUCCESS);
6055}
6056
6057isc_sockaddr_t *
6058dns_zone_getparentalsrc4(dns_zone_t *zone) {
6059	REQUIRE(DNS_ZONE_VALID(zone));
6060	return (&zone->parentalsrc4);
6061}
6062
6063isc_result_t
6064dns_zone_setparentalsrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6065	REQUIRE(DNS_ZONE_VALID(zone));
6066
6067	LOCK_ZONE(zone);
6068	zone->parentalsrc4dscp = dscp;
6069	UNLOCK_ZONE(zone);
6070
6071	return (ISC_R_SUCCESS);
6072}
6073
6074isc_dscp_t
6075dns_zone_getparentalsrc4dscp(dns_zone_t *zone) {
6076	REQUIRE(DNS_ZONE_VALID(zone));
6077	return (zone->parentalsrc4dscp);
6078}
6079
6080isc_result_t
6081dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6082	REQUIRE(DNS_ZONE_VALID(zone));
6083
6084	LOCK_ZONE(zone);
6085	zone->parentalsrc6 = *parentalsrc;
6086	UNLOCK_ZONE(zone);
6087
6088	return (ISC_R_SUCCESS);
6089}
6090
6091isc_sockaddr_t *
6092dns_zone_getparentalsrc6(dns_zone_t *zone) {
6093	REQUIRE(DNS_ZONE_VALID(zone));
6094	return (&zone->parentalsrc6);
6095}
6096
6097isc_result_t
6098dns_zone_setparentalsrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6099	REQUIRE(DNS_ZONE_VALID(zone));
6100
6101	LOCK_ZONE(zone);
6102	zone->parentalsrc6dscp = dscp;
6103	UNLOCK_ZONE(zone);
6104
6105	return (ISC_R_SUCCESS);
6106}
6107
6108isc_dscp_t
6109dns_zone_getparentalsrc6dscp(dns_zone_t *zone) {
6110	REQUIRE(DNS_ZONE_VALID(zone));
6111	return (zone->parentalsrc6dscp);
6112}
6113
6114isc_result_t
6115dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6116	REQUIRE(DNS_ZONE_VALID(zone));
6117
6118	LOCK_ZONE(zone);
6119	zone->notifysrc4 = *notifysrc;
6120	UNLOCK_ZONE(zone);
6121
6122	return (ISC_R_SUCCESS);
6123}
6124
6125isc_sockaddr_t *
6126dns_zone_getnotifysrc4(dns_zone_t *zone) {
6127	REQUIRE(DNS_ZONE_VALID(zone));
6128	return (&zone->notifysrc4);
6129}
6130
6131isc_result_t
6132dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6133	REQUIRE(DNS_ZONE_VALID(zone));
6134
6135	LOCK_ZONE(zone);
6136	zone->notifysrc4dscp = dscp;
6137	UNLOCK_ZONE(zone);
6138
6139	return (ISC_R_SUCCESS);
6140}
6141
6142isc_dscp_t
6143dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
6144	REQUIRE(DNS_ZONE_VALID(zone));
6145	return (zone->notifysrc4dscp);
6146}
6147
6148isc_result_t
6149dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6150	REQUIRE(DNS_ZONE_VALID(zone));
6151
6152	LOCK_ZONE(zone);
6153	zone->notifysrc6 = *notifysrc;
6154	UNLOCK_ZONE(zone);
6155
6156	return (ISC_R_SUCCESS);
6157}
6158
6159isc_sockaddr_t *
6160dns_zone_getnotifysrc6(dns_zone_t *zone) {
6161	REQUIRE(DNS_ZONE_VALID(zone));
6162	return (&zone->notifysrc6);
6163}
6164
6165isc_result_t
6166dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6167	REQUIRE(DNS_ZONE_VALID(zone));
6168
6169	LOCK_ZONE(zone);
6170	zone->notifysrc6dscp = dscp;
6171	UNLOCK_ZONE(zone);
6172
6173	return (ISC_R_SUCCESS);
6174}
6175
6176isc_dscp_t
6177dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
6178	REQUIRE(DNS_ZONE_VALID(zone));
6179	return (zone->notifysrc6dscp);
6180}
6181
6182static bool
6183same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
6184	   uint32_t count) {
6185	unsigned int i;
6186
6187	for (i = 0; i < count; i++) {
6188		if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) {
6189			return (false);
6190		}
6191	}
6192	return (true);
6193}
6194
6195static bool
6196same_keynames(dns_name_t *const *oldlist, dns_name_t *const *newlist,
6197	      uint32_t count) {
6198	unsigned int i;
6199
6200	if (oldlist == NULL && newlist == NULL) {
6201		return (true);
6202	}
6203	if (oldlist == NULL || newlist == NULL) {
6204		return (false);
6205	}
6206
6207	for (i = 0; i < count; i++) {
6208		if (oldlist[i] == NULL && newlist[i] == NULL) {
6209			continue;
6210		}
6211		if (oldlist[i] == NULL || newlist[i] == NULL ||
6212		    !dns_name_equal(oldlist[i], newlist[i]))
6213		{
6214			return (false);
6215		}
6216	}
6217	return (true);
6218}
6219
6220static void
6221clear_serverslist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
6222		  dns_name_t ***keynamesp, unsigned int *countp,
6223		  isc_mem_t *mctx) {
6224	unsigned int count;
6225	isc_sockaddr_t *addrs;
6226	isc_dscp_t *dscps;
6227	dns_name_t **keynames;
6228
6229	REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
6230		keynamesp != NULL);
6231
6232	count = *countp;
6233	*countp = 0;
6234	addrs = *addrsp;
6235	*addrsp = NULL;
6236	dscps = *dscpsp;
6237	*dscpsp = NULL;
6238	keynames = *keynamesp;
6239	*keynamesp = NULL;
6240
6241	if (addrs != NULL) {
6242		isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
6243	}
6244
6245	if (dscps != NULL) {
6246		isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
6247	}
6248
6249	if (keynames != NULL) {
6250		unsigned int i;
6251		for (i = 0; i < count; i++) {
6252			if (keynames[i] != NULL) {
6253				dns_name_free(keynames[i], mctx);
6254				isc_mem_put(mctx, keynames[i],
6255					    sizeof(dns_name_t));
6256				keynames[i] = NULL;
6257			}
6258		}
6259		isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
6260	}
6261}
6262
6263static isc_result_t
6264set_serverslist(unsigned int count, const isc_sockaddr_t *addrs,
6265		isc_sockaddr_t **newaddrsp, const isc_dscp_t *dscp,
6266		isc_dscp_t **newdscpp, dns_name_t **names,
6267		dns_name_t ***newnamesp, isc_mem_t *mctx) {
6268	isc_sockaddr_t *newaddrs = NULL;
6269	isc_dscp_t *newdscp = NULL;
6270	dns_name_t **newnames = NULL;
6271	unsigned int i;
6272
6273	REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
6274	REQUIRE(newdscpp != NULL && *newdscpp == NULL);
6275	REQUIRE(newnamesp != NULL && *newnamesp == NULL);
6276
6277	newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
6278	memmove(newaddrs, addrs, count * sizeof(*newaddrs));
6279
6280	if (dscp != NULL) {
6281		newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
6282		memmove(newdscp, dscp, count * sizeof(*newdscp));
6283	} else {
6284		newdscp = NULL;
6285	}
6286
6287	if (names != NULL) {
6288		newnames = isc_mem_get(mctx, count * sizeof(*newnames));
6289		for (i = 0; i < count; i++) {
6290			newnames[i] = NULL;
6291		}
6292		for (i = 0; i < count; i++) {
6293			if (names[i] != NULL) {
6294				newnames[i] = isc_mem_get(mctx,
6295							  sizeof(dns_name_t));
6296				dns_name_init(newnames[i], NULL);
6297				dns_name_dup(names[i], mctx, newnames[i]);
6298			}
6299		}
6300	} else {
6301		newnames = NULL;
6302	}
6303
6304	*newdscpp = newdscp;
6305	*newaddrsp = newaddrs;
6306	*newnamesp = newnames;
6307	return (ISC_R_SUCCESS);
6308}
6309
6310isc_result_t
6311dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
6312		       uint32_t count) {
6313	return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
6314					       count));
6315}
6316
6317isc_result_t
6318dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6319			       dns_name_t **keynames, uint32_t count) {
6320	return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
6321					       count));
6322}
6323
6324isc_result_t
6325dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6326			       const isc_dscp_t *dscps, dns_name_t **keynames,
6327			       uint32_t count) {
6328	isc_result_t result;
6329	isc_sockaddr_t *newaddrs = NULL;
6330	isc_dscp_t *newdscps = NULL;
6331	dns_name_t **newnames = NULL;
6332
6333	REQUIRE(DNS_ZONE_VALID(zone));
6334	REQUIRE(count == 0 || notify != NULL);
6335	if (keynames != NULL) {
6336		REQUIRE(count != 0);
6337	}
6338
6339	LOCK_ZONE(zone);
6340
6341	if (count == zone->notifycnt &&
6342	    same_addrs(zone->notify, notify, count) &&
6343	    same_keynames(zone->notifykeynames, keynames, count))
6344	{
6345		goto unlock;
6346	}
6347
6348	clear_serverslist(&zone->notify, &zone->notifydscp,
6349			  &zone->notifykeynames, &zone->notifycnt, zone->mctx);
6350
6351	if (count == 0) {
6352		goto unlock;
6353	}
6354
6355	/*
6356	 * Set up the notify and notifykey lists
6357	 */
6358	result = set_serverslist(count, notify, &newaddrs, dscps, &newdscps,
6359				 keynames, &newnames, zone->mctx);
6360	if (result != ISC_R_SUCCESS) {
6361		goto unlock;
6362	}
6363
6364	/*
6365	 * Everything is ok so attach to the zone.
6366	 */
6367	zone->notify = newaddrs;
6368	zone->notifydscp = newdscps;
6369	zone->notifykeynames = newnames;
6370	zone->notifycnt = count;
6371unlock:
6372	UNLOCK_ZONE(zone);
6373	return (ISC_R_SUCCESS);
6374}
6375
6376isc_result_t
6377dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *masters,
6378		      uint32_t count) {
6379	isc_result_t result;
6380
6381	result = dns_zone_setprimarieswithkeys(zone, masters, NULL, count);
6382	return (result);
6383}
6384
6385isc_result_t
6386dns_zone_setprimarieswithkeys(dns_zone_t *zone, const isc_sockaddr_t *masters,
6387			      dns_name_t **keynames, uint32_t count) {
6388	isc_result_t result = ISC_R_SUCCESS;
6389	isc_sockaddr_t *newaddrs = NULL;
6390	isc_dscp_t *newdscps = NULL;
6391	dns_name_t **newnames = NULL;
6392	bool *newok;
6393	unsigned int i;
6394
6395	REQUIRE(DNS_ZONE_VALID(zone));
6396	REQUIRE(count == 0 || masters != NULL);
6397	if (keynames != NULL) {
6398		REQUIRE(count != 0);
6399	}
6400
6401	LOCK_ZONE(zone);
6402	/*
6403	 * The refresh code assumes that 'primaries' wouldn't change under it.
6404	 * If it will change then kill off any current refresh in progress
6405	 * and update the primaries info.  If it won't change then we can just
6406	 * unlock and exit.
6407	 */
6408	if (count != zone->masterscnt ||
6409	    !same_addrs(zone->masters, masters, count) ||
6410	    !same_keynames(zone->masterkeynames, keynames, count))
6411	{
6412		if (zone->request != NULL) {
6413			dns_request_cancel(zone->request);
6414		}
6415	} else {
6416		goto unlock;
6417	}
6418
6419	/*
6420	 * This needs to happen before clear_addresskeylist() sets
6421	 * zone->masterscnt to 0:
6422	 */
6423	if (zone->mastersok != NULL) {
6424		isc_mem_put(zone->mctx, zone->mastersok,
6425			    zone->masterscnt * sizeof(bool));
6426		zone->mastersok = NULL;
6427	}
6428	clear_serverslist(&zone->masters, &zone->masterdscps,
6429			  &zone->masterkeynames, &zone->masterscnt, zone->mctx);
6430	/*
6431	 * If count == 0, don't allocate any space for masters, mastersok or
6432	 * keynames so internally, those pointers are NULL if count == 0
6433	 */
6434	if (count == 0) {
6435		goto unlock;
6436	}
6437
6438	/*
6439	 * mastersok must contain count elements
6440	 */
6441	newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
6442	for (i = 0; i < count; i++) {
6443		newok[i] = false;
6444	}
6445
6446	/*
6447	 * Now set up the primaries and primary key lists
6448	 */
6449	result = set_serverslist(count, masters, &newaddrs, NULL, &newdscps,
6450				 keynames, &newnames, zone->mctx);
6451	INSIST(newdscps == NULL);
6452	if (result != ISC_R_SUCCESS) {
6453		isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
6454		goto unlock;
6455	}
6456
6457	/*
6458	 * Everything is ok so attach to the zone.
6459	 */
6460	zone->curmaster = 0;
6461	zone->mastersok = newok;
6462	zone->masters = newaddrs;
6463	zone->masterdscps = newdscps;
6464	zone->masterkeynames = newnames;
6465	zone->masterscnt = count;
6466	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
6467
6468unlock:
6469	UNLOCK_ZONE(zone);
6470	return (result);
6471}
6472
6473isc_result_t
6474dns_zone_setparentals(dns_zone_t *zone, const isc_sockaddr_t *parentals,
6475		      dns_name_t **keynames, uint32_t count) {
6476	isc_result_t result = ISC_R_SUCCESS;
6477	isc_sockaddr_t *newaddrs = NULL;
6478	isc_dscp_t *newdscps = NULL;
6479	dns_name_t **newkeynames = NULL;
6480
6481	REQUIRE(DNS_ZONE_VALID(zone));
6482	REQUIRE(count == 0 || parentals != NULL);
6483	if (keynames != NULL) {
6484		REQUIRE(count != 0);
6485	}
6486
6487	LOCK_ZONE(zone);
6488
6489	clear_serverslist(&zone->parentals, &zone->parentaldscps,
6490			  &zone->parentalkeynames, &zone->parentalscnt,
6491			  zone->mctx);
6492	/*
6493	 * If count == 0, don't allocate any space for parentals, or keynames
6494	 * so internally, those pointers are NULL if count == 0
6495	 */
6496	if (count == 0) {
6497		goto unlock;
6498	}
6499
6500	/*
6501	 * Now set up the parentals and parental key lists
6502	 */
6503	result = set_serverslist(count, parentals, &newaddrs, NULL, &newdscps,
6504				 keynames, &newkeynames, zone->mctx);
6505	INSIST(newdscps == NULL);
6506	if (result != ISC_R_SUCCESS) {
6507		goto unlock;
6508	}
6509
6510	/*
6511	 * Everything is ok so attach to the zone.
6512	 */
6513	zone->parentals = newaddrs;
6514	zone->parentaldscps = newdscps;
6515	zone->parentalkeynames = newkeynames;
6516	zone->parentalscnt = count;
6517
6518	dns_zone_log(zone, ISC_LOG_NOTICE, "checkds: set %u parentals", count);
6519
6520unlock:
6521	UNLOCK_ZONE(zone);
6522	return (result);
6523}
6524
6525isc_result_t
6526dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6527	isc_result_t result = ISC_R_SUCCESS;
6528
6529	REQUIRE(DNS_ZONE_VALID(zone));
6530
6531	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6532	if (zone->db == NULL) {
6533		result = DNS_R_NOTLOADED;
6534	} else {
6535		dns_db_attach(zone->db, dpb);
6536	}
6537	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6538
6539	return (result);
6540}
6541
6542void
6543dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6544	REQUIRE(DNS_ZONE_VALID(zone));
6545	REQUIRE(zone->type == dns_zone_staticstub);
6546
6547	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6548	REQUIRE(zone->db == NULL);
6549	dns_db_attach(db, &zone->db);
6550	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6551}
6552
6553/*
6554 * Coordinates the starting of routine jobs.
6555 */
6556void
6557dns_zone_maintenance(dns_zone_t *zone) {
6558	const char me[] = "dns_zone_maintenance";
6559	isc_time_t now;
6560
6561	REQUIRE(DNS_ZONE_VALID(zone));
6562	ENTER;
6563
6564	LOCK_ZONE(zone);
6565	TIME_NOW(&now);
6566	zone_settimer(zone, &now);
6567	UNLOCK_ZONE(zone);
6568}
6569
6570static bool
6571was_dumping(dns_zone_t *zone) {
6572	REQUIRE(LOCKED_ZONE(zone));
6573
6574	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
6575		return (true);
6576	}
6577
6578	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6579	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6580	isc_time_settoepoch(&zone->dumptime);
6581	return (false);
6582}
6583
6584/*%
6585 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6586 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6587 * Only load the public part of a given key if it is not active at timestamp
6588 * 'now'.  Store the number of keys found in 'nkeys'.
6589 */
6590isc_result_t
6591dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6592		   isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6593		   dst_key_t **keys, unsigned int *nkeys) {
6594	isc_result_t result;
6595	dns_dbnode_t *node = NULL;
6596	const char *directory = dns_zone_getkeydirectory(zone);
6597
6598	CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6599	memset(keys, 0, sizeof(*keys) * maxkeys);
6600
6601	dns_zone_lock_keyfiles(zone);
6602
6603	result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
6604					 directory, now, mctx, maxkeys, keys,
6605					 nkeys);
6606
6607	dns_zone_unlock_keyfiles(zone);
6608
6609	if (result == ISC_R_NOTFOUND) {
6610		result = ISC_R_SUCCESS;
6611	}
6612
6613failure:
6614
6615	if (node != NULL) {
6616		dns_db_detachnode(db, &node);
6617	}
6618	return (result);
6619}
6620
6621/*%
6622 * Find DNSSEC keys used for signing zone with dnssec-policy. Load these keys
6623 * into 'keys'. Requires KASP to be locked.
6624 */
6625isc_result_t
6626dns_zone_getdnsseckeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6627		       isc_stdtime_t now, dns_dnsseckeylist_t *keys) {
6628	isc_result_t result;
6629	const char *dir = dns_zone_getkeydirectory(zone);
6630	dns_dbnode_t *node = NULL;
6631	dns_dnsseckey_t *key, *key_next;
6632	dns_dnsseckeylist_t dnskeys;
6633	dns_name_t *origin = dns_zone_getorigin(zone);
6634	dns_kasp_t *kasp = dns_zone_getkasp(zone);
6635	dns_rdataset_t keyset;
6636
6637	REQUIRE(DNS_ZONE_VALID(zone));
6638	REQUIRE(kasp != NULL);
6639
6640	ISC_LIST_INIT(dnskeys);
6641
6642	dns_rdataset_init(&keyset);
6643
6644	CHECK(dns_db_findnode(db, origin, false, &node));
6645
6646	/* Get keys from private key files. */
6647	dns_zone_lock_keyfiles(zone);
6648	result = dns_dnssec_findmatchingkeys(origin, dir, now,
6649					     dns_zone_getmctx(zone), keys);
6650	dns_zone_unlock_keyfiles(zone);
6651
6652	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6653		goto failure;
6654	}
6655
6656	/* Get public keys (dnskeys). */
6657	dns_rdataset_init(&keyset);
6658	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
6659				     dns_rdatatype_none, 0, &keyset, NULL);
6660	if (result == ISC_R_SUCCESS) {
6661		CHECK(dns_dnssec_keylistfromrdataset(
6662			origin, dir, dns_zone_getmctx(zone), &keyset, NULL,
6663			NULL, false, false, &dnskeys));
6664	} else if (result != ISC_R_NOTFOUND) {
6665		CHECK(result);
6666	}
6667
6668	/* Add new 'dnskeys' to 'keys'. */
6669	for (dns_dnsseckey_t *k1 = ISC_LIST_HEAD(dnskeys); k1 != NULL;
6670	     k1 = key_next)
6671	{
6672		dns_dnsseckey_t *k2 = NULL;
6673		key_next = ISC_LIST_NEXT(k1, link);
6674
6675		for (k2 = ISC_LIST_HEAD(*keys); k2 != NULL;
6676		     k2 = ISC_LIST_NEXT(k2, link))
6677		{
6678			if (dst_key_compare(k1->key, k2->key)) {
6679				break;
6680			}
6681		}
6682		/* No match found, add the new key. */
6683		if (k2 == NULL) {
6684			ISC_LIST_UNLINK(dnskeys, k1, link);
6685			ISC_LIST_APPEND(*keys, k1, link);
6686		}
6687	}
6688
6689failure:
6690	if (dns_rdataset_isassociated(&keyset)) {
6691		dns_rdataset_disassociate(&keyset);
6692	}
6693	if (node != NULL) {
6694		dns_db_detachnode(db, &node);
6695	}
6696	while (!ISC_LIST_EMPTY(dnskeys)) {
6697		key = ISC_LIST_HEAD(dnskeys);
6698		ISC_LIST_UNLINK(dnskeys, key, link);
6699		dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
6700	}
6701	return (result);
6702}
6703
6704static isc_result_t
6705offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6706	dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
6707	isc_result_t result;
6708
6709	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) {
6710		return (ISC_R_SUCCESS);
6711	}
6712	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6713			       name, ttl, rdata);
6714	if (result != ISC_R_SUCCESS) {
6715		return (result);
6716	}
6717	rdata->flags |= DNS_RDATA_OFFLINE;
6718	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6719			       name, ttl, rdata);
6720	zonediff->offline = true;
6721	return (result);
6722}
6723
6724static void
6725set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
6726		       isc_stdtime_t now) {
6727	unsigned int delta;
6728	char timebuf[80];
6729
6730	LOCK_ZONE(zone);
6731	zone->key_expiry = when;
6732	if (when <= now) {
6733		dns_zone_log(zone, ISC_LOG_ERROR,
6734			     "DNSKEY RRSIG(s) have expired");
6735		isc_time_settoepoch(&zone->keywarntime);
6736	} else if (when < now + 7 * 24 * 3600) {
6737		isc_time_t t;
6738		isc_time_set(&t, when, 0);
6739		isc_time_formattimestamp(&t, timebuf, 80);
6740		dns_zone_log(zone, ISC_LOG_WARNING,
6741			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
6742			     timebuf);
6743		delta = when - now;
6744		delta--;	    /* loop prevention */
6745		delta /= 24 * 3600; /* to whole days */
6746		delta *= 24 * 3600; /* to seconds */
6747		isc_time_set(&zone->keywarntime, when - delta, 0);
6748	} else {
6749		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6750		isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6751		dns_zone_log(zone, ISC_LOG_NOTICE, "setting keywarntime to %s",
6752			     timebuf);
6753	}
6754	UNLOCK_ZONE(zone);
6755}
6756
6757/*
6758 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6759 * have no new key.
6760 */
6761static bool
6762delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6763	  bool kasp, bool *warn) {
6764	unsigned int i = 0;
6765	isc_result_t ret;
6766	bool have_ksk = false, have_zsk = false;
6767	bool have_pksk = false, have_pzsk = false;
6768
6769	for (i = 0; i < nkeys; i++) {
6770		bool ksk, zsk;
6771
6772		if (have_pksk && have_ksk && have_pzsk && have_zsk) {
6773			break;
6774		}
6775
6776		if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
6777			continue;
6778		}
6779
6780		ret = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
6781		if (ret != ISC_R_SUCCESS) {
6782			ksk = KSK(keys[i]);
6783		}
6784		ret = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
6785		if (ret != ISC_R_SUCCESS) {
6786			zsk = !KSK(keys[i]);
6787		}
6788
6789		if (ksk) {
6790			have_ksk = true;
6791			if (dst_key_isprivate(keys[i])) {
6792				have_pksk = true;
6793			}
6794		}
6795		if (zsk) {
6796			have_zsk = true;
6797			if (dst_key_isprivate(keys[i])) {
6798				have_pzsk = true;
6799			}
6800		}
6801	}
6802
6803	if (have_zsk && have_ksk && !have_pzsk) {
6804		*warn = true;
6805	}
6806
6807	if (have_pksk && have_pzsk) {
6808		return (true);
6809	}
6810
6811	/*
6812	 * Deleting the SOA RRSIG is always okay.
6813	 */
6814	if (rrsig_ptr->covered == dns_rdatatype_soa) {
6815		return (true);
6816	}
6817
6818	/*
6819	 * It's okay to delete a signature if there is an active key with the
6820	 * same algorithm to replace it, unless that violates the DNSSEC
6821	 * policy.
6822	 */
6823	if (have_pksk || have_pzsk) {
6824		if (kasp && have_pzsk) {
6825			return (true);
6826		}
6827		return (!kasp);
6828	}
6829
6830	/*
6831	 * Failing that, it is *not* okay to delete a signature
6832	 * if the associated public key is still in the DNSKEY RRset
6833	 */
6834	for (i = 0; i < nkeys; i++) {
6835		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6836		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
6837		{
6838			return (false);
6839		}
6840	}
6841
6842	/*
6843	 * But if the key is gone, then go ahead.
6844	 */
6845	return (true);
6846}
6847
6848/*
6849 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6850 * See also update.c:del_keysigs().
6851 */
6852static isc_result_t
6853del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6854	 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6855	 unsigned int nkeys, isc_stdtime_t now, bool incremental) {
6856	isc_result_t result;
6857	dns_dbnode_t *node = NULL;
6858	dns_rdataset_t rdataset;
6859	unsigned int i;
6860	dns_rdata_rrsig_t rrsig;
6861	bool kasp = (dns_zone_getkasp(zone) != NULL);
6862	bool found;
6863	int64_t timewarn = 0, timemaybe = 0;
6864
6865	dns_rdataset_init(&rdataset);
6866
6867	if (type == dns_rdatatype_nsec3) {
6868		result = dns_db_findnsec3node(db, name, false, &node);
6869	} else {
6870		result = dns_db_findnode(db, name, false, &node);
6871	}
6872	if (result == ISC_R_NOTFOUND) {
6873		return (ISC_R_SUCCESS);
6874	}
6875	if (result != ISC_R_SUCCESS) {
6876		goto failure;
6877	}
6878	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6879				     (isc_stdtime_t)0, &rdataset, NULL);
6880	dns_db_detachnode(db, &node);
6881
6882	if (result == ISC_R_NOTFOUND) {
6883		INSIST(!dns_rdataset_isassociated(&rdataset));
6884		return (ISC_R_SUCCESS);
6885	}
6886	if (result != ISC_R_SUCCESS) {
6887		INSIST(!dns_rdataset_isassociated(&rdataset));
6888		goto failure;
6889	}
6890
6891	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
6892	     result = dns_rdataset_next(&rdataset))
6893	{
6894		dns_rdata_t rdata = DNS_RDATA_INIT;
6895
6896		dns_rdataset_current(&rdataset, &rdata);
6897		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6898		RUNTIME_CHECK(result == ISC_R_SUCCESS);
6899
6900		if (type != dns_rdatatype_dnskey && type != dns_rdatatype_cds &&
6901		    type != dns_rdatatype_cdnskey)
6902		{
6903			bool warn = false, deleted = false;
6904			if (delsig_ok(&rrsig, keys, nkeys, kasp, &warn)) {
6905				result = update_one_rr(db, ver, zonediff->diff,
6906						       DNS_DIFFOP_DELRESIGN,
6907						       name, rdataset.ttl,
6908						       &rdata);
6909				if (result != ISC_R_SUCCESS) {
6910					break;
6911				}
6912				deleted = true;
6913			}
6914			if (warn && !deleted) {
6915				/*
6916				 * At this point, we've got an RRSIG,
6917				 * which is signed by an inactive key.
6918				 * An administrator needs to provide a new
6919				 * key/alg, but until that time, we want to
6920				 * keep the old RRSIG.  Marking the key as
6921				 * offline will prevent us spinning waiting
6922				 * for the private part.
6923				 */
6924				if (incremental) {
6925					result = offline(db, ver, zonediff,
6926							 name, rdataset.ttl,
6927							 &rdata);
6928					if (result != ISC_R_SUCCESS) {
6929						break;
6930					}
6931				}
6932
6933				/*
6934				 * Log the key id and algorithm of
6935				 * the inactive key with no replacement
6936				 */
6937				if (zone->log_key_expired_timer <= now) {
6938					char origin[DNS_NAME_FORMATSIZE];
6939					char algbuf[DNS_NAME_FORMATSIZE];
6940					dns_name_format(&zone->origin, origin,
6941							sizeof(origin));
6942					dns_secalg_format(rrsig.algorithm,
6943							  algbuf,
6944							  sizeof(algbuf));
6945					dns_zone_log(zone, ISC_LOG_WARNING,
6946						     "Key %s/%s/%d "
6947						     "missing or inactive "
6948						     "and has no replacement: "
6949						     "retaining signatures.",
6950						     origin, algbuf,
6951						     rrsig.keyid);
6952					zone->log_key_expired_timer = now +
6953								      3600;
6954				}
6955			}
6956			continue;
6957		}
6958
6959		/*
6960		 * KSK RRSIGs requires special processing.
6961		 */
6962		found = false;
6963		for (i = 0; i < nkeys; i++) {
6964			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6965			    rrsig.keyid == dst_key_id(keys[i]))
6966			{
6967				found = true;
6968				/*
6969				 * Mark offline DNSKEY.
6970				 * We want the earliest offline expire time
6971				 * iff there is a new offline signature.
6972				 */
6973				if (!dst_key_inactive(keys[i]) &&
6974				    !dst_key_isprivate(keys[i]))
6975				{
6976					int64_t timeexpire = dns_time64_from32(
6977						rrsig.timeexpire);
6978					if (timewarn != 0 &&
6979					    timewarn > timeexpire)
6980					{
6981						timewarn = timeexpire;
6982					}
6983					if (rdata.flags & DNS_RDATA_OFFLINE) {
6984						if (timemaybe == 0 ||
6985						    timemaybe > timeexpire)
6986						{
6987							timemaybe = timeexpire;
6988						}
6989						break;
6990					}
6991					if (timewarn == 0) {
6992						timewarn = timemaybe;
6993					}
6994					if (timewarn == 0 ||
6995					    timewarn > timeexpire)
6996					{
6997						timewarn = timeexpire;
6998					}
6999					result = offline(db, ver, zonediff,
7000							 name, rdataset.ttl,
7001							 &rdata);
7002					break;
7003				}
7004				result = update_one_rr(db, ver, zonediff->diff,
7005						       DNS_DIFFOP_DELRESIGN,
7006						       name, rdataset.ttl,
7007						       &rdata);
7008				break;
7009			}
7010		}
7011
7012		/*
7013		 * If there is not a matching DNSKEY then
7014		 * delete the RRSIG.
7015		 */
7016		if (!found) {
7017			result = update_one_rr(db, ver, zonediff->diff,
7018					       DNS_DIFFOP_DELRESIGN, name,
7019					       rdataset.ttl, &rdata);
7020		}
7021		if (result != ISC_R_SUCCESS) {
7022			break;
7023		}
7024	}
7025
7026	dns_rdataset_disassociate(&rdataset);
7027	if (result == ISC_R_NOMORE) {
7028		result = ISC_R_SUCCESS;
7029	}
7030	if (timewarn > 0) {
7031		isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
7032		if (timewarn == stdwarn) {
7033			set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
7034					       now);
7035		} else {
7036			dns_zone_log(zone, ISC_LOG_ERROR,
7037				     "key expiry warning time out of range");
7038		}
7039	}
7040failure:
7041	if (node != NULL) {
7042		dns_db_detachnode(db, &node);
7043	}
7044	return (result);
7045}
7046
7047static isc_result_t
7048add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
7049	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
7050	 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
7051	 isc_stdtime_t expire, bool check_ksk, bool keyset_kskonly) {
7052	isc_result_t result;
7053	dns_dbnode_t *node = NULL;
7054	dns_stats_t *dnssecsignstats;
7055	dns_rdataset_t rdataset;
7056	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
7057	unsigned char data[1024]; /* XXX */
7058	isc_buffer_t buffer;
7059	unsigned int i, j;
7060	bool use_kasp = false;
7061
7062	if (dns_zone_getkasp(zone) != NULL) {
7063		check_ksk = false;
7064		keyset_kskonly = true;
7065		use_kasp = true;
7066	}
7067
7068	dns_rdataset_init(&rdataset);
7069	isc_buffer_init(&buffer, data, sizeof(data));
7070
7071	if (type == dns_rdatatype_nsec3) {
7072		result = dns_db_findnsec3node(db, name, false, &node);
7073	} else {
7074		result = dns_db_findnode(db, name, false, &node);
7075	}
7076	if (result == ISC_R_NOTFOUND) {
7077		return (ISC_R_SUCCESS);
7078	}
7079	if (result != ISC_R_SUCCESS) {
7080		goto failure;
7081	}
7082	result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
7083				     &rdataset, NULL);
7084	dns_db_detachnode(db, &node);
7085	if (result == ISC_R_NOTFOUND) {
7086		INSIST(!dns_rdataset_isassociated(&rdataset));
7087		return (ISC_R_SUCCESS);
7088	}
7089	if (result != ISC_R_SUCCESS) {
7090		INSIST(!dns_rdataset_isassociated(&rdataset));
7091		goto failure;
7092	}
7093
7094	for (i = 0; i < nkeys; i++) {
7095		bool both = false;
7096
7097		/* Don't add signatures for offline or inactive keys */
7098		if (!dst_key_isprivate(keys[i])) {
7099			continue;
7100		}
7101		if (dst_key_inactive(keys[i])) {
7102			continue;
7103		}
7104
7105		if (check_ksk && !REVOKE(keys[i])) {
7106			bool have_ksk, have_nonksk;
7107			if (KSK(keys[i])) {
7108				have_ksk = true;
7109				have_nonksk = false;
7110			} else {
7111				have_ksk = false;
7112				have_nonksk = true;
7113			}
7114
7115			for (j = 0; j < nkeys; j++) {
7116				if (j == i || ALG(keys[i]) != ALG(keys[j])) {
7117					continue;
7118				}
7119
7120				/*
7121				 * Don't consider inactive keys, however
7122				 * the KSK may be temporary offline, so do
7123				 * consider keys which private key files are
7124				 * unavailable.
7125				 */
7126				if (dst_key_inactive(keys[j])) {
7127					continue;
7128				}
7129
7130				if (REVOKE(keys[j])) {
7131					continue;
7132				}
7133				if (KSK(keys[j])) {
7134					have_ksk = true;
7135				} else if (dst_key_isprivate(keys[j])) {
7136					have_nonksk = true;
7137				}
7138				both = have_ksk && have_nonksk;
7139				if (both) {
7140					break;
7141				}
7142			}
7143		}
7144		if (use_kasp) {
7145			/*
7146			 * A dnssec-policy is found. Check what RRsets this
7147			 * key should sign.
7148			 */
7149			isc_result_t kresult;
7150			isc_stdtime_t when;
7151			bool ksk = false;
7152			bool zsk = false;
7153			bool have_ksk = false;
7154			bool have_zsk = false;
7155
7156			kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
7157			if (kresult != ISC_R_SUCCESS) {
7158				if (KSK(keys[i])) {
7159					ksk = true;
7160				}
7161			}
7162			kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
7163			if (kresult != ISC_R_SUCCESS) {
7164				if (!KSK(keys[i])) {
7165					zsk = true;
7166				}
7167			}
7168
7169			have_ksk = ksk;
7170			have_zsk = zsk;
7171			both = have_ksk && have_zsk;
7172
7173			for (j = 0; j < nkeys; j++) {
7174				if (both) {
7175					break;
7176				}
7177
7178				if (j == i || ALG(keys[i]) != ALG(keys[j])) {
7179					continue;
7180				}
7181
7182				/*
7183				 * Don't consider inactive keys or offline keys.
7184				 */
7185				if (!dst_key_isprivate(keys[j])) {
7186					continue;
7187				}
7188				if (dst_key_inactive(keys[j])) {
7189					continue;
7190				}
7191
7192				if (REVOKE(keys[j])) {
7193					continue;
7194				}
7195
7196				if (!have_ksk) {
7197					kresult = dst_key_getbool(keys[j],
7198								  DST_BOOL_KSK,
7199								  &have_ksk);
7200					if (kresult != ISC_R_SUCCESS) {
7201						if (KSK(keys[j])) {
7202							have_ksk = true;
7203						}
7204					}
7205				}
7206				if (!have_zsk) {
7207					kresult = dst_key_getbool(keys[j],
7208								  DST_BOOL_ZSK,
7209								  &have_zsk);
7210					if (kresult != ISC_R_SUCCESS) {
7211						if (!KSK(keys[j])) {
7212							have_zsk = true;
7213						}
7214					}
7215				}
7216				both = have_ksk && have_zsk;
7217			}
7218
7219			if (type == dns_rdatatype_dnskey ||
7220			    type == dns_rdatatype_cdnskey ||
7221			    type == dns_rdatatype_cds)
7222			{
7223				/*
7224				 * DNSKEY RRset is signed with KSK.
7225				 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
7226				 */
7227				if (!ksk) {
7228					continue;
7229				}
7230			} else if (!zsk) {
7231				/*
7232				 * Other RRsets are signed with ZSK.
7233				 */
7234				if (type != dns_rdatatype_soa &&
7235				    type != zone->privatetype)
7236				{
7237					continue;
7238				}
7239				if (have_zsk) {
7240					continue;
7241				}
7242			} else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
7243						       inception, &when))
7244			{
7245				/*
7246				 * This key is not active for zone-signing.
7247				 */
7248				continue;
7249			}
7250
7251			/*
7252			 * If this key is revoked, it may only sign the
7253			 * DNSKEY RRset.
7254			 */
7255			if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7256				continue;
7257			}
7258		} else if (both) {
7259			/*
7260			 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
7261			 */
7262			if (type == dns_rdatatype_dnskey ||
7263			    type == dns_rdatatype_cdnskey ||
7264			    type == dns_rdatatype_cds)
7265			{
7266				if (!KSK(keys[i]) && keyset_kskonly) {
7267					continue;
7268				}
7269			} else if (KSK(keys[i])) {
7270				continue;
7271			}
7272		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7273			continue;
7274		}
7275
7276		/* Calculate the signature, creating a RRSIG RDATA. */
7277		isc_buffer_clear(&buffer);
7278		CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
7279				      &expire, mctx, &buffer, &sig_rdata));
7280
7281		/* Update the database and journal with the RRSIG. */
7282		/* XXX inefficient - will cause dataset merging */
7283		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
7284				    rdataset.ttl, &sig_rdata));
7285		dns_rdata_reset(&sig_rdata);
7286		isc_buffer_init(&buffer, data, sizeof(data));
7287
7288		/* Update DNSSEC sign statistics. */
7289		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7290		if (dnssecsignstats != NULL) {
7291			/* Generated a new signature. */
7292			dns_dnssecsignstats_increment(dnssecsignstats,
7293						      ID(keys[i]),
7294						      (uint8_t)ALG(keys[i]),
7295						      dns_dnssecsignstats_sign);
7296			/* This is a refresh. */
7297			dns_dnssecsignstats_increment(
7298				dnssecsignstats, ID(keys[i]),
7299				(uint8_t)ALG(keys[i]),
7300				dns_dnssecsignstats_refresh);
7301		}
7302	}
7303
7304failure:
7305	if (dns_rdataset_isassociated(&rdataset)) {
7306		dns_rdataset_disassociate(&rdataset);
7307	}
7308	if (node != NULL) {
7309		dns_db_detachnode(db, &node);
7310	}
7311	return (result);
7312}
7313
7314static void
7315zone_resigninc(dns_zone_t *zone) {
7316	const char *me = "zone_resigninc";
7317	dns_db_t *db = NULL;
7318	dns_dbversion_t *version = NULL;
7319	dns_diff_t _sig_diff;
7320	dns__zonediff_t zonediff;
7321	dns_fixedname_t fixed;
7322	dns_name_t *name;
7323	dns_rdataset_t rdataset;
7324	dns_rdatatype_t covers;
7325	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7326	bool check_ksk, keyset_kskonly = false;
7327	isc_result_t result;
7328	isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
7329	uint32_t sigvalidityinterval, expiryinterval;
7330	unsigned int i;
7331	unsigned int nkeys = 0;
7332	unsigned int resign;
7333
7334	ENTER;
7335
7336	dns_rdataset_init(&rdataset);
7337	dns_diff_init(zone->mctx, &_sig_diff);
7338	zonediff_init(&zonediff, &_sig_diff);
7339
7340	/*
7341	 * Zone is frozen or automatic resigning is disabled.
7342	 * Pause for 5 minutes.
7343	 */
7344	if (zone->update_disabled ||
7345	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
7346	{
7347		result = ISC_R_FAILURE;
7348		goto failure;
7349	}
7350
7351	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7352	if (zone->db != NULL) {
7353		dns_db_attach(zone->db, &db);
7354	}
7355	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7356	if (db == NULL) {
7357		result = ISC_R_FAILURE;
7358		goto failure;
7359	}
7360
7361	result = dns_db_newversion(db, &version);
7362	if (result != ISC_R_SUCCESS) {
7363		dns_zone_log(zone, ISC_LOG_ERROR,
7364			     "zone_resigninc:dns_db_newversion -> %s",
7365			     dns_result_totext(result));
7366		goto failure;
7367	}
7368
7369	isc_stdtime_get(&now);
7370
7371	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7372				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
7373	if (result != ISC_R_SUCCESS) {
7374		dns_zone_log(zone, ISC_LOG_ERROR,
7375			     "zone_resigninc:dns__zone_findkeys -> %s",
7376			     dns_result_totext(result));
7377		goto failure;
7378	}
7379
7380	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7381	inception = now - 3600; /* Allow for clock skew. */
7382	soaexpire = now + sigvalidityinterval;
7383	expiryinterval = dns_zone_getsigresigninginterval(zone);
7384	if (expiryinterval > sigvalidityinterval) {
7385		expiryinterval = sigvalidityinterval;
7386	} else {
7387		expiryinterval = sigvalidityinterval - expiryinterval;
7388	}
7389
7390	/*
7391	 * Spread out signatures over time if they happen to be
7392	 * clumped.  We don't do this for each add_sigs() call as
7393	 * we still want some clustering to occur.  In normal operations
7394	 * the records should be re-signed as they fall due and they should
7395	 * already be spread out.  However if the server is off for a
7396	 * period we need to ensure that the clusters don't become
7397	 * synchronised by using the full jitter range.
7398	 */
7399	if (sigvalidityinterval >= 3600U) {
7400		uint32_t normaljitter, fulljitter;
7401		if (sigvalidityinterval > 7200U) {
7402			normaljitter = isc_random_uniform(3600);
7403			fulljitter = isc_random_uniform(expiryinterval);
7404		} else {
7405			normaljitter = fulljitter = isc_random_uniform(1200);
7406		}
7407		expire = soaexpire - normaljitter - 1;
7408		fullexpire = soaexpire - fulljitter - 1;
7409	} else {
7410		expire = fullexpire = soaexpire - 1;
7411	}
7412	stop = now + 5;
7413
7414	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7415	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7416
7417	name = dns_fixedname_initname(&fixed);
7418	result = dns_db_getsigningtime(db, &rdataset, name);
7419	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
7420		dns_zone_log(zone, ISC_LOG_ERROR,
7421			     "zone_resigninc:dns_db_getsigningtime -> %s",
7422			     dns_result_totext(result));
7423	}
7424
7425	i = 0;
7426	while (result == ISC_R_SUCCESS) {
7427		resign = rdataset.resign -
7428			 dns_zone_getsigresigninginterval(zone);
7429		covers = rdataset.covers;
7430		dns_rdataset_disassociate(&rdataset);
7431
7432		/*
7433		 * Stop if we hit the SOA as that means we have walked the
7434		 * entire zone.  The SOA record should always be the most
7435		 * recent signature.
7436		 */
7437		/* XXXMPA increase number of RRsets signed pre call */
7438		if ((covers == dns_rdatatype_soa &&
7439		     dns_name_equal(name, &zone->origin)) ||
7440		    i++ > zone->signatures || resign > stop)
7441		{
7442			break;
7443		}
7444
7445		result = del_sigs(zone, db, version, name, covers, &zonediff,
7446				  zone_keys, nkeys, now, true);
7447		if (result != ISC_R_SUCCESS) {
7448			dns_zone_log(zone, ISC_LOG_ERROR,
7449				     "zone_resigninc:del_sigs -> %s",
7450				     dns_result_totext(result));
7451			break;
7452		}
7453
7454		/*
7455		 * If re-signing is over 5 minutes late use 'fullexpire'
7456		 * to redistribute the signature over the complete
7457		 * re-signing window, otherwise only add a small amount
7458		 * of jitter.
7459		 */
7460		result = add_sigs(db, version, name, zone, covers,
7461				  zonediff.diff, zone_keys, nkeys, zone->mctx,
7462				  inception,
7463				  resign > (now - 300) ? expire : fullexpire,
7464				  check_ksk, keyset_kskonly);
7465		if (result != ISC_R_SUCCESS) {
7466			dns_zone_log(zone, ISC_LOG_ERROR,
7467				     "zone_resigninc:add_sigs -> %s",
7468				     dns_result_totext(result));
7469			break;
7470		}
7471		result = dns_db_getsigningtime(db, &rdataset, name);
7472		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
7473			result = ISC_R_SUCCESS;
7474			break;
7475		}
7476		if (result != ISC_R_SUCCESS) {
7477			dns_zone_log(zone, ISC_LOG_ERROR,
7478				     "zone_resigninc:dns_db_getsigningtime -> "
7479				     "%s",
7480				     dns_result_totext(result));
7481		}
7482	}
7483
7484	if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS) {
7485		goto failure;
7486	}
7487
7488	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7489			  &zonediff, zone_keys, nkeys, now, true);
7490	if (result != ISC_R_SUCCESS) {
7491		dns_zone_log(zone, ISC_LOG_ERROR,
7492			     "zone_resigninc:del_sigs -> %s",
7493			     dns_result_totext(result));
7494		goto failure;
7495	}
7496
7497	/*
7498	 * Did we change anything in the zone?
7499	 */
7500	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7501		/*
7502		 * Commit the changes if any key has been marked as offline.
7503		 */
7504		if (zonediff.offline) {
7505			dns_db_closeversion(db, &version, true);
7506		}
7507		goto failure;
7508	}
7509
7510	/* Increment SOA serial if we have made changes */
7511	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
7512				   zone->updatemethod);
7513	if (result != ISC_R_SUCCESS) {
7514		dns_zone_log(zone, ISC_LOG_ERROR,
7515			     "zone_resigninc:update_soa_serial -> %s",
7516			     dns_result_totext(result));
7517		goto failure;
7518	}
7519
7520	/*
7521	 * Generate maximum life time signatures so that the above loop
7522	 * termination is sensible.
7523	 */
7524	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
7525			  zonediff.diff, zone_keys, nkeys, zone->mctx,
7526			  inception, soaexpire, check_ksk, keyset_kskonly);
7527	if (result != ISC_R_SUCCESS) {
7528		dns_zone_log(zone, ISC_LOG_ERROR,
7529			     "zone_resigninc:add_sigs -> %s",
7530			     dns_result_totext(result));
7531		goto failure;
7532	}
7533
7534	/* Write changes to journal file. */
7535	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
7536
7537	/* Everything has succeeded. Commit the changes. */
7538	dns_db_closeversion(db, &version, true);
7539
7540failure:
7541	dns_diff_clear(&_sig_diff);
7542	for (i = 0; i < nkeys; i++) {
7543		dst_key_free(&zone_keys[i]);
7544	}
7545	if (version != NULL) {
7546		dns_db_closeversion(db, &version, false);
7547		dns_db_detach(&db);
7548	} else if (db != NULL) {
7549		dns_db_detach(&db);
7550	}
7551
7552	LOCK_ZONE(zone);
7553	if (result == ISC_R_SUCCESS) {
7554		set_resigntime(zone);
7555		zone_needdump(zone, DNS_DUMP_DELAY);
7556		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7557	} else {
7558		/*
7559		 * Something failed.  Retry in 5 minutes.
7560		 */
7561		isc_interval_t ival;
7562		isc_interval_set(&ival, 300, 0);
7563		isc_time_nowplusinterval(&zone->resigntime, &ival);
7564	}
7565	UNLOCK_ZONE(zone);
7566
7567	INSIST(version == NULL);
7568}
7569
7570static isc_result_t
7571next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
7572	    dns_name_t *newname, bool bottom) {
7573	isc_result_t result;
7574	dns_dbiterator_t *dbit = NULL;
7575	dns_rdatasetiter_t *rdsit = NULL;
7576	dns_dbnode_t *node = NULL;
7577
7578	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
7579	CHECK(dns_dbiterator_seek(dbit, oldname));
7580	do {
7581		result = dns_dbiterator_next(dbit);
7582		if (result == ISC_R_NOMORE) {
7583			CHECK(dns_dbiterator_first(dbit));
7584		}
7585		CHECK(dns_dbiterator_current(dbit, &node, newname));
7586		if (bottom && dns_name_issubdomain(newname, oldname) &&
7587		    !dns_name_equal(newname, oldname))
7588		{
7589			dns_db_detachnode(db, &node);
7590			continue;
7591		}
7592		/*
7593		 * Is this node empty?
7594		 */
7595		CHECK(dns_db_allrdatasets(db, node, version, 0, 0, &rdsit));
7596		result = dns_rdatasetiter_first(rdsit);
7597		dns_db_detachnode(db, &node);
7598		dns_rdatasetiter_destroy(&rdsit);
7599		if (result != ISC_R_NOMORE) {
7600			break;
7601		}
7602	} while (1);
7603failure:
7604	if (node != NULL) {
7605		dns_db_detachnode(db, &node);
7606	}
7607	if (dbit != NULL) {
7608		dns_dbiterator_destroy(&dbit);
7609	}
7610	return (result);
7611}
7612
7613static bool
7614signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
7615		     dns_dbversion_t *version, dns_rdatatype_t type,
7616		     dst_key_t *key) {
7617	isc_result_t result;
7618	dns_rdataset_t rdataset;
7619	dns_rdata_t rdata = DNS_RDATA_INIT;
7620	dns_rdata_rrsig_t rrsig;
7621	int count = 0;
7622	dns_kasp_t *kasp = dns_zone_getkasp(zone);
7623
7624	dns_rdataset_init(&rdataset);
7625	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
7626				     type, 0, &rdataset, NULL);
7627	if (result != ISC_R_SUCCESS) {
7628		INSIST(!dns_rdataset_isassociated(&rdataset));
7629		return (false);
7630	}
7631	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7632	     result = dns_rdataset_next(&rdataset))
7633	{
7634		dns_rdataset_current(&rdataset, &rdata);
7635		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
7636		INSIST(result == ISC_R_SUCCESS);
7637		if (rrsig.algorithm == dst_key_alg(key) &&
7638		    rrsig.keyid == dst_key_id(key))
7639		{
7640			dns_rdataset_disassociate(&rdataset);
7641			return (true);
7642		}
7643		if (rrsig.algorithm == dst_key_alg(key)) {
7644			count++;
7645		}
7646		dns_rdata_reset(&rdata);
7647	}
7648
7649	if (dns_zone_getkasp(zone) != NULL) {
7650		dns_kasp_key_t *kkey;
7651		int zsk_count = 0;
7652		bool approved;
7653
7654		KASP_LOCK(kasp);
7655		for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
7656		     kkey = ISC_LIST_NEXT(kkey, link))
7657		{
7658			if (dns_kasp_key_algorithm(kkey) != dst_key_alg(key)) {
7659				continue;
7660			}
7661			if (dns_kasp_key_zsk(kkey)) {
7662				zsk_count++;
7663			}
7664		}
7665		KASP_UNLOCK(kasp);
7666
7667		if (type == dns_rdatatype_dnskey ||
7668		    type == dns_rdatatype_cdnskey || type == dns_rdatatype_cds)
7669		{
7670			/*
7671			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7672			 * (RFC 7344, section 4.1 specifies that they must
7673			 * be signed with a key in the current DS RRset,
7674			 * which would only include KSK's.)
7675			 */
7676			approved = false;
7677		} else {
7678			approved = (zsk_count == count);
7679		}
7680
7681		dns_rdataset_disassociate(&rdataset);
7682		return (approved);
7683	}
7684
7685	dns_rdataset_disassociate(&rdataset);
7686	return (false);
7687}
7688
7689static isc_result_t
7690add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7691	 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom, dns_diff_t *diff) {
7692	dns_fixedname_t fixed;
7693	dns_name_t *next;
7694	dns_rdata_t rdata = DNS_RDATA_INIT;
7695	isc_result_t result;
7696	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
7697
7698	next = dns_fixedname_initname(&fixed);
7699
7700	CHECK(next_active(db, version, name, next, bottom));
7701	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata));
7702	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
7703			    &rdata));
7704failure:
7705	return (result);
7706}
7707
7708static isc_result_t
7709check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
7710			dns_dbversion_t *version, bool *is_bottom_of_zone) {
7711	isc_result_t result;
7712	dns_rdatasetiter_t *iterator = NULL;
7713	dns_rdataset_t rdataset;
7714	bool seen_soa = false, seen_ns = false, seen_dname = false;
7715
7716	REQUIRE(is_bottom_of_zone != NULL);
7717
7718	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7719	if (result != ISC_R_SUCCESS) {
7720		if (result == ISC_R_NOTFOUND) {
7721			result = ISC_R_SUCCESS;
7722		}
7723		return (result);
7724	}
7725
7726	dns_rdataset_init(&rdataset);
7727	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7728	     result = dns_rdatasetiter_next(iterator))
7729	{
7730		dns_rdatasetiter_current(iterator, &rdataset);
7731		switch (rdataset.type) {
7732		case dns_rdatatype_soa:
7733			seen_soa = true;
7734			break;
7735		case dns_rdatatype_ns:
7736			seen_ns = true;
7737			break;
7738		case dns_rdatatype_dname:
7739			seen_dname = true;
7740			break;
7741		}
7742		dns_rdataset_disassociate(&rdataset);
7743	}
7744	if (result != ISC_R_NOMORE) {
7745		goto failure;
7746	}
7747	if ((seen_ns && !seen_soa) || seen_dname) {
7748		*is_bottom_of_zone = true;
7749	}
7750	result = ISC_R_SUCCESS;
7751
7752failure:
7753	dns_rdatasetiter_destroy(&iterator);
7754
7755	return (result);
7756}
7757
7758static isc_result_t
7759sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
7760	    dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3,
7761	    bool build_nsec, dst_key_t *key, isc_stdtime_t inception,
7762	    isc_stdtime_t expire, dns_ttl_t nsecttl, bool is_ksk, bool is_zsk,
7763	    bool keyset_kskonly, bool is_bottom_of_zone, dns_diff_t *diff,
7764	    int32_t *signatures, isc_mem_t *mctx) {
7765	isc_result_t result;
7766	dns_rdatasetiter_t *iterator = NULL;
7767	dns_rdataset_t rdataset;
7768	dns_rdata_t rdata = DNS_RDATA_INIT;
7769	dns_stats_t *dnssecsignstats;
7770
7771	isc_buffer_t buffer;
7772	unsigned char data[1024];
7773	bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
7774
7775	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7776	if (result != ISC_R_SUCCESS) {
7777		if (result == ISC_R_NOTFOUND) {
7778			result = ISC_R_SUCCESS;
7779		}
7780		return (result);
7781	}
7782
7783	dns_rdataset_init(&rdataset);
7784	isc_buffer_init(&buffer, data, sizeof(data));
7785	seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
7786	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7787	     result = dns_rdatasetiter_next(iterator))
7788	{
7789		dns_rdatasetiter_current(iterator, &rdataset);
7790		if (rdataset.type == dns_rdatatype_soa) {
7791			seen_soa = true;
7792		} else if (rdataset.type == dns_rdatatype_ns) {
7793			seen_ns = true;
7794		} else if (rdataset.type == dns_rdatatype_ds) {
7795			seen_ds = true;
7796		} else if (rdataset.type == dns_rdatatype_nsec) {
7797			seen_nsec = true;
7798		} else if (rdataset.type == dns_rdatatype_nsec3) {
7799			seen_nsec3 = true;
7800		}
7801		if (rdataset.type != dns_rdatatype_rrsig) {
7802			seen_rr = true;
7803		}
7804		dns_rdataset_disassociate(&rdataset);
7805	}
7806	if (result != ISC_R_NOMORE) {
7807		goto failure;
7808	}
7809	/*
7810	 * Going from insecure to NSEC3.
7811	 * Don't generate NSEC3 records for NSEC3 records.
7812	 */
7813	if (build_nsec3 && !seen_nsec3 && seen_rr) {
7814		bool unsecure = !seen_ds && seen_ns && !seen_soa;
7815		CHECK(dns_nsec3_addnsec3s(db, version, name, nsecttl, unsecure,
7816					  diff));
7817		(*signatures)--;
7818	}
7819	/*
7820	 * Going from insecure to NSEC.
7821	 * Don't generate NSEC records for NSEC3 records.
7822	 */
7823	if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
7824		/*
7825		 * Build a NSEC record except at the origin.
7826		 */
7827		if (!dns_name_equal(name, dns_db_origin(db))) {
7828			CHECK(add_nsec(db, version, name, node, nsecttl,
7829				       is_bottom_of_zone, diff));
7830			/* Count a NSEC generation as a signature generation. */
7831			(*signatures)--;
7832		}
7833	}
7834	result = dns_rdatasetiter_first(iterator);
7835	while (result == ISC_R_SUCCESS) {
7836		isc_stdtime_t when;
7837
7838		dns_rdatasetiter_current(iterator, &rdataset);
7839		if (rdataset.type == dns_rdatatype_soa ||
7840		    rdataset.type == dns_rdatatype_rrsig)
7841		{
7842			goto next_rdataset;
7843		}
7844		if (rdataset.type == dns_rdatatype_dnskey ||
7845		    rdataset.type == dns_rdatatype_cdnskey ||
7846		    rdataset.type == dns_rdatatype_cds)
7847		{
7848			/*
7849			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7850			 * (RFC 7344, section 4.1 specifies that they must
7851			 * be signed with a key in the current DS RRset,
7852			 * which would only include KSK's.)
7853			 */
7854			if (!is_ksk && keyset_kskonly) {
7855				goto next_rdataset;
7856			}
7857		} else if (!is_zsk) {
7858			goto next_rdataset;
7859		} else if (is_zsk && !dst_key_is_signing(key, DST_BOOL_ZSK,
7860							 inception, &when))
7861		{
7862			/* Only applies to dnssec-policy. */
7863			if (dns_zone_getkasp(zone) != NULL) {
7864				goto next_rdataset;
7865			}
7866		}
7867
7868		if (seen_ns && !seen_soa && rdataset.type != dns_rdatatype_ds &&
7869		    rdataset.type != dns_rdatatype_nsec)
7870		{
7871			goto next_rdataset;
7872		}
7873		if (signed_with_good_key(zone, db, node, version, rdataset.type,
7874					 key))
7875		{
7876			goto next_rdataset;
7877		}
7878
7879		/* Calculate the signature, creating a RRSIG RDATA. */
7880		isc_buffer_clear(&buffer);
7881		CHECK(dns_dnssec_sign(name, &rdataset, key, &inception, &expire,
7882				      mctx, &buffer, &rdata));
7883		/* Update the database and journal with the RRSIG. */
7884		/* XXX inefficient - will cause dataset merging */
7885		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7886				    name, rdataset.ttl, &rdata));
7887		dns_rdata_reset(&rdata);
7888
7889		/* Update DNSSEC sign statistics. */
7890		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7891		if (dnssecsignstats != NULL) {
7892			/* Generated a new signature. */
7893			dns_dnssecsignstats_increment(dnssecsignstats, ID(key),
7894						      ALG(key),
7895						      dns_dnssecsignstats_sign);
7896			/* This is a refresh. */
7897			dns_dnssecsignstats_increment(
7898				dnssecsignstats, ID(key), ALG(key),
7899				dns_dnssecsignstats_refresh);
7900		}
7901
7902		(*signatures)--;
7903	next_rdataset:
7904		dns_rdataset_disassociate(&rdataset);
7905		result = dns_rdatasetiter_next(iterator);
7906	}
7907	if (result == ISC_R_NOMORE) {
7908		result = ISC_R_SUCCESS;
7909	}
7910failure:
7911	if (dns_rdataset_isassociated(&rdataset)) {
7912		dns_rdataset_disassociate(&rdataset);
7913	}
7914	if (iterator != NULL) {
7915		dns_rdatasetiter_destroy(&iterator);
7916	}
7917	return (result);
7918}
7919
7920/*
7921 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7922 */
7923static isc_result_t
7924updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7925	     dns_ttl_t nsecttl, bool update_only, dns_diff_t *diff) {
7926	isc_result_t result;
7927	dns_rdataset_t rdataset;
7928	dns_dbnode_t *node = NULL;
7929
7930	CHECK(dns_db_getoriginnode(db, &node));
7931	if (update_only) {
7932		dns_rdataset_init(&rdataset);
7933		result = dns_db_findrdataset(
7934			db, node, version, dns_rdatatype_nsec,
7935			dns_rdatatype_none, 0, &rdataset, NULL);
7936		if (dns_rdataset_isassociated(&rdataset)) {
7937			dns_rdataset_disassociate(&rdataset);
7938		}
7939		if (result == ISC_R_NOTFOUND) {
7940			goto success;
7941		}
7942		if (result != ISC_R_SUCCESS) {
7943			goto failure;
7944		}
7945	}
7946	CHECK(delete_nsec(db, version, node, name, diff));
7947	CHECK(add_nsec(db, version, name, node, nsecttl, false, diff));
7948success:
7949	result = ISC_R_SUCCESS;
7950failure:
7951	if (node != NULL) {
7952		dns_db_detachnode(db, &node);
7953	}
7954	return (result);
7955}
7956
7957static isc_result_t
7958updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7959		  dns_dbversion_t *version, bool build_nsec3, dns_ttl_t nsecttl,
7960		  dns_diff_t *diff) {
7961	isc_result_t result;
7962	dns_dbnode_t *node = NULL;
7963	dns_rdataset_t rdataset;
7964	dns_rdata_t rdata = DNS_RDATA_INIT;
7965	unsigned char data[5];
7966	bool seen_done = false;
7967	bool have_rr = false;
7968
7969	dns_rdataset_init(&rdataset);
7970	result = dns_db_getoriginnode(signing->db, &node);
7971	if (result != ISC_R_SUCCESS) {
7972		goto failure;
7973	}
7974
7975	result = dns_db_findrdataset(signing->db, node, version,
7976				     zone->privatetype, dns_rdatatype_none, 0,
7977				     &rdataset, NULL);
7978	if (result == ISC_R_NOTFOUND) {
7979		INSIST(!dns_rdataset_isassociated(&rdataset));
7980		result = ISC_R_SUCCESS;
7981		goto failure;
7982	}
7983	if (result != ISC_R_SUCCESS) {
7984		INSIST(!dns_rdataset_isassociated(&rdataset));
7985		goto failure;
7986	}
7987	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7988	     result = dns_rdataset_next(&rdataset))
7989	{
7990		dns_rdataset_current(&rdataset, &rdata);
7991		/*
7992		 * If we don't match the algorithm or keyid skip the record.
7993		 */
7994		if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
7995		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7996		    rdata.data[2] != (signing->keyid & 0xff))
7997		{
7998			have_rr = true;
7999			dns_rdata_reset(&rdata);
8000			continue;
8001		}
8002		/*
8003		 * We have a match.  If we were signing (!signing->deleteit)
8004		 * and we already have a record indicating that we have
8005		 * finished signing (rdata.data[4] != 0) then keep it.
8006		 * Otherwise it needs to be deleted as we have removed all
8007		 * the signatures (signing->deleteit), so any record indicating
8008		 * completion is now out of date, or we have finished signing
8009		 * with the new record so we no longer need to remember that
8010		 * we need to sign the zone with the matching key across a
8011		 * nameserver re-start.
8012		 */
8013		if (!signing->deleteit && rdata.data[4] != 0) {
8014			seen_done = true;
8015			have_rr = true;
8016		} else {
8017			CHECK(update_one_rr(signing->db, version, diff,
8018					    DNS_DIFFOP_DEL, &zone->origin,
8019					    rdataset.ttl, &rdata));
8020		}
8021		dns_rdata_reset(&rdata);
8022	}
8023	if (result == ISC_R_NOMORE) {
8024		result = ISC_R_SUCCESS;
8025	}
8026	if (!signing->deleteit && !seen_done) {
8027		/*
8028		 * If we were signing then we need to indicate that we have
8029		 * finished signing the zone with this key.  If it is already
8030		 * there we don't need to add it a second time.
8031		 */
8032		data[0] = signing->algorithm;
8033		data[1] = (signing->keyid >> 8) & 0xff;
8034		data[2] = signing->keyid & 0xff;
8035		data[3] = 0;
8036		data[4] = 1;
8037		rdata.length = sizeof(data);
8038		rdata.data = data;
8039		rdata.type = zone->privatetype;
8040		rdata.rdclass = dns_db_class(signing->db);
8041		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
8042				    &zone->origin, rdataset.ttl, &rdata));
8043	} else if (!have_rr) {
8044		dns_name_t *origin = dns_db_origin(signing->db);
8045		/*
8046		 * Rebuild the NSEC/NSEC3 record for the origin as we no
8047		 * longer have any private records.
8048		 */
8049		if (build_nsec3) {
8050			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
8051						  nsecttl, false, diff));
8052		}
8053		CHECK(updatesecure(signing->db, version, origin, nsecttl, true,
8054				   diff));
8055	}
8056
8057failure:
8058	if (dns_rdataset_isassociated(&rdataset)) {
8059		dns_rdataset_disassociate(&rdataset);
8060	}
8061	if (node != NULL) {
8062		dns_db_detachnode(signing->db, &node);
8063	}
8064	return (result);
8065}
8066
8067/*
8068 * Called from zone_nsec3chain() in order to update zone records indicating
8069 * processing status of given NSEC3 chain:
8070 *
8071 *   - If the supplied dns_nsec3chain_t structure has been fully processed
8072 *     (which is indicated by "active" being set to false):
8073 *
8074 *       - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
8075 *
8076 *       - remove all private-type records containing NSEC3PARAM RDATA matching
8077 *         the relevant NSEC3 chain.
8078 *
8079 *   - If the supplied dns_nsec3chain_t structure has not been fully processed
8080 *     (which is indicated by "active" being set to true), only remove the
8081 *     NSEC3PARAM record which matches the relevant NSEC3 chain and has the
8082 *     "flags" field set to 0.
8083 *
8084 *   - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
8085 *     in the relevant private-type record, but with the "flags" field set to
8086 *     0, indicating that this NSEC3 chain is now complete for this zone.
8087 *
8088 * Note that this function is called at different processing stages for NSEC3
8089 * chain additions vs. removals and needs to handle all cases properly.
8090 */
8091static isc_result_t
8092fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
8093		 bool active, dns_rdatatype_t privatetype, dns_diff_t *diff) {
8094	dns_dbnode_t *node = NULL;
8095	dns_name_t *name = dns_db_origin(db);
8096	dns_rdata_t rdata = DNS_RDATA_INIT;
8097	dns_rdataset_t rdataset;
8098	dns_rdata_nsec3param_t nsec3param;
8099	isc_result_t result;
8100	isc_buffer_t buffer;
8101	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
8102	dns_ttl_t ttl = 0;
8103	bool nseconly = false, nsec3ok = false;
8104
8105	dns_rdataset_init(&rdataset);
8106
8107	result = dns_db_getoriginnode(db, &node);
8108	RUNTIME_CHECK(result == ISC_R_SUCCESS);
8109	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8110				     0, &rdataset, NULL);
8111	if (result == ISC_R_NOTFOUND) {
8112		goto try_private;
8113	}
8114	if (result != ISC_R_SUCCESS) {
8115		goto failure;
8116	}
8117
8118	/*
8119	 * Preserve the existing ttl.
8120	 */
8121	ttl = rdataset.ttl;
8122
8123	/*
8124	 * Delete all NSEC3PARAM records which match that in nsec3chain.
8125	 */
8126	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8127	     result = dns_rdataset_next(&rdataset))
8128	{
8129		dns_rdataset_current(&rdataset, &rdata);
8130		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8131
8132		if (nsec3param.hash != chain->nsec3param.hash ||
8133		    (active && nsec3param.flags != 0) ||
8134		    nsec3param.iterations != chain->nsec3param.iterations ||
8135		    nsec3param.salt_length != chain->nsec3param.salt_length ||
8136		    memcmp(nsec3param.salt, chain->nsec3param.salt,
8137			   nsec3param.salt_length))
8138		{
8139			dns_rdata_reset(&rdata);
8140			continue;
8141		}
8142
8143		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8144				    rdataset.ttl, &rdata));
8145		dns_rdata_reset(&rdata);
8146	}
8147	if (result != ISC_R_NOMORE) {
8148		goto failure;
8149	}
8150
8151	dns_rdataset_disassociate(&rdataset);
8152
8153try_private:
8154
8155	if (active) {
8156		goto add;
8157	}
8158
8159	result = dns_nsec_nseconly(db, ver, &nseconly);
8160	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
8161
8162	/*
8163	 * Delete all private records which match that in nsec3chain.
8164	 */
8165	result = dns_db_findrdataset(db, node, ver, privatetype, 0, 0,
8166				     &rdataset, NULL);
8167	if (result == ISC_R_NOTFOUND) {
8168		goto add;
8169	}
8170	if (result != ISC_R_SUCCESS) {
8171		goto failure;
8172	}
8173
8174	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8175	     result = dns_rdataset_next(&rdataset))
8176	{
8177		dns_rdata_t private = DNS_RDATA_INIT;
8178		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
8179
8180		dns_rdataset_current(&rdataset, &private);
8181		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
8182						sizeof(buf)))
8183		{
8184			continue;
8185		}
8186		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8187
8188		if ((!nsec3ok &&
8189		     (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
8190		    nsec3param.hash != chain->nsec3param.hash ||
8191		    nsec3param.iterations != chain->nsec3param.iterations ||
8192		    nsec3param.salt_length != chain->nsec3param.salt_length ||
8193		    memcmp(nsec3param.salt, chain->nsec3param.salt,
8194			   nsec3param.salt_length))
8195		{
8196			dns_rdata_reset(&rdata);
8197			continue;
8198		}
8199
8200		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8201				    rdataset.ttl, &private));
8202		dns_rdata_reset(&rdata);
8203	}
8204	if (result != ISC_R_NOMORE) {
8205		goto failure;
8206	}
8207
8208add:
8209	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
8210		result = ISC_R_SUCCESS;
8211		goto failure;
8212	}
8213
8214	/*
8215	 * Add a NSEC3PARAM record which matches that in nsec3chain but
8216	 * with all flags bits cleared.
8217	 *
8218	 * Note: we do not clear chain->nsec3param.flags as this change
8219	 * may be reversed.
8220	 */
8221	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
8222	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
8223				   dns_rdatatype_nsec3param, &chain->nsec3param,
8224				   &buffer));
8225	rdata.data[1] = 0; /* Clear flag bits. */
8226	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
8227
8228failure:
8229	dns_db_detachnode(db, &node);
8230	if (dns_rdataset_isassociated(&rdataset)) {
8231		dns_rdataset_disassociate(&rdataset);
8232	}
8233	return (result);
8234}
8235
8236static isc_result_t
8237delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8238	    dns_name_t *name, dns_diff_t *diff) {
8239	dns_rdataset_t rdataset;
8240	isc_result_t result;
8241
8242	dns_rdataset_init(&rdataset);
8243
8244	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8245				     &rdataset, NULL);
8246	if (result == ISC_R_NOTFOUND) {
8247		return (ISC_R_SUCCESS);
8248	}
8249	if (result != ISC_R_SUCCESS) {
8250		return (result);
8251	}
8252	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8253	     result = dns_rdataset_next(&rdataset))
8254	{
8255		dns_rdata_t rdata = DNS_RDATA_INIT;
8256
8257		dns_rdataset_current(&rdataset, &rdata);
8258		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8259				    rdataset.ttl, &rdata));
8260	}
8261	if (result == ISC_R_NOMORE) {
8262		result = ISC_R_SUCCESS;
8263	}
8264failure:
8265	dns_rdataset_disassociate(&rdataset);
8266	return (result);
8267}
8268
8269static isc_result_t
8270deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8271		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
8272		    dns_diff_t *diff) {
8273	dns_rdataset_t rdataset;
8274	dns_rdata_nsec3_t nsec3;
8275	isc_result_t result;
8276
8277	dns_rdataset_init(&rdataset);
8278	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0,
8279				     &rdataset, NULL);
8280	if (result == ISC_R_NOTFOUND) {
8281		return (ISC_R_SUCCESS);
8282	}
8283	if (result != ISC_R_SUCCESS) {
8284		return (result);
8285	}
8286
8287	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8288	     result = dns_rdataset_next(&rdataset))
8289	{
8290		dns_rdata_t rdata = DNS_RDATA_INIT;
8291
8292		dns_rdataset_current(&rdataset, &rdata);
8293		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
8294		if (nsec3.hash != param->hash ||
8295		    nsec3.iterations != param->iterations ||
8296		    nsec3.salt_length != param->salt_length ||
8297		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
8298		{
8299			continue;
8300		}
8301		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8302				    rdataset.ttl, &rdata));
8303	}
8304	if (result == ISC_R_NOMORE) {
8305		result = ISC_R_SUCCESS;
8306	}
8307failure:
8308	dns_rdataset_disassociate(&rdataset);
8309	return (result);
8310}
8311
8312static isc_result_t
8313need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
8314		const dns_rdata_nsec3param_t *param, bool *answer) {
8315	dns_dbnode_t *node = NULL;
8316	dns_rdata_t rdata = DNS_RDATA_INIT;
8317	dns_rdata_nsec3param_t myparam;
8318	dns_rdataset_t rdataset;
8319	isc_result_t result;
8320
8321	*answer = false;
8322
8323	result = dns_db_getoriginnode(db, &node);
8324	RUNTIME_CHECK(result == ISC_R_SUCCESS);
8325
8326	dns_rdataset_init(&rdataset);
8327
8328	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8329				     &rdataset, NULL);
8330	if (result == ISC_R_SUCCESS) {
8331		dns_rdataset_disassociate(&rdataset);
8332		dns_db_detachnode(db, &node);
8333		return (result);
8334	}
8335	if (result != ISC_R_NOTFOUND) {
8336		dns_db_detachnode(db, &node);
8337		return (result);
8338	}
8339
8340	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8341				     0, &rdataset, NULL);
8342	if (result == ISC_R_NOTFOUND) {
8343		*answer = true;
8344		dns_db_detachnode(db, &node);
8345		return (ISC_R_SUCCESS);
8346	}
8347	if (result != ISC_R_SUCCESS) {
8348		dns_db_detachnode(db, &node);
8349		return (result);
8350	}
8351
8352	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8353	     result = dns_rdataset_next(&rdataset))
8354	{
8355		dns_rdataset_current(&rdataset, &rdata);
8356		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
8357		dns_rdata_reset(&rdata);
8358		/*
8359		 * Ignore any NSEC3PARAM removals.
8360		 */
8361		if (NSEC3REMOVE(myparam.flags)) {
8362			continue;
8363		}
8364		/*
8365		 * Ignore the chain that we are in the process of deleting.
8366		 */
8367		if (myparam.hash == param->hash &&
8368		    myparam.iterations == param->iterations &&
8369		    myparam.salt_length == param->salt_length &&
8370		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
8371		{
8372			continue;
8373		}
8374		/*
8375		 * Found an active NSEC3 chain.
8376		 */
8377		break;
8378	}
8379	if (result == ISC_R_NOMORE) {
8380		*answer = true;
8381		result = ISC_R_SUCCESS;
8382	}
8383
8384failure:
8385	if (dns_rdataset_isassociated(&rdataset)) {
8386		dns_rdataset_disassociate(&rdataset);
8387	}
8388	dns_db_detachnode(db, &node);
8389	return (result);
8390}
8391
8392/*%
8393 * Given a tuple which is part of a diff, return a pointer to the next tuple in
8394 * that diff which has the same name and type (or NULL if no such tuple is
8395 * found).
8396 */
8397static dns_difftuple_t *
8398find_next_matching_tuple(dns_difftuple_t *cur) {
8399	dns_difftuple_t *next = cur;
8400
8401	while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
8402		if (cur->rdata.type == next->rdata.type &&
8403		    dns_name_equal(&cur->name, &next->name))
8404		{
8405			return (next);
8406		}
8407	}
8408
8409	return (NULL);
8410}
8411
8412/*%
8413 * Remove all tuples with the same name and type as 'cur' from 'src' and append
8414 * them to 'dst'.
8415 */
8416static void
8417move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
8418	do {
8419		dns_difftuple_t *next = find_next_matching_tuple(cur);
8420		ISC_LIST_UNLINK(src->tuples, cur, link);
8421		dns_diff_appendminimal(dst, &cur);
8422		cur = next;
8423	} while (cur != NULL);
8424}
8425
8426/*%
8427 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
8428 * 'diff'.  Gradually remove tuples from 'diff' and append them to 'zonediff'
8429 * along with tuples representing relevant signature changes.
8430 */
8431isc_result_t
8432dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
8433		     dst_key_t *zone_keys[], unsigned int nkeys,
8434		     dns_zone_t *zone, isc_stdtime_t inception,
8435		     isc_stdtime_t expire, isc_stdtime_t keyexpire,
8436		     isc_stdtime_t now, bool check_ksk, bool keyset_kskonly,
8437		     dns__zonediff_t *zonediff) {
8438	dns_difftuple_t *tuple;
8439	isc_result_t result;
8440
8441	while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
8442		isc_stdtime_t exp = expire;
8443
8444		if (keyexpire != 0 &&
8445		    (tuple->rdata.type == dns_rdatatype_dnskey ||
8446		     tuple->rdata.type == dns_rdatatype_cdnskey ||
8447		     tuple->rdata.type == dns_rdatatype_cds))
8448		{
8449			exp = keyexpire;
8450		}
8451
8452		result = del_sigs(zone, db, version, &tuple->name,
8453				  tuple->rdata.type, zonediff, zone_keys, nkeys,
8454				  now, false);
8455		if (result != ISC_R_SUCCESS) {
8456			dns_zone_log(zone, ISC_LOG_ERROR,
8457				     "dns__zone_updatesigs:del_sigs -> %s",
8458				     dns_result_totext(result));
8459			return (result);
8460		}
8461		result = add_sigs(db, version, &tuple->name, zone,
8462				  tuple->rdata.type, zonediff->diff, zone_keys,
8463				  nkeys, zone->mctx, inception, exp, check_ksk,
8464				  keyset_kskonly);
8465		if (result != ISC_R_SUCCESS) {
8466			dns_zone_log(zone, ISC_LOG_ERROR,
8467				     "dns__zone_updatesigs:add_sigs -> %s",
8468				     dns_result_totext(result));
8469			return (result);
8470		}
8471
8472		/*
8473		 * Signature changes for all RRs with name tuple->name and type
8474		 * tuple->rdata.type were appended to zonediff->diff.  Now we
8475		 * remove all the "raw" changes with the same name and type
8476		 * from diff (so that they are not processed by this loop
8477		 * again) and append them to zonediff so that they get applied.
8478		 */
8479		move_matching_tuples(tuple, diff, zonediff->diff);
8480	}
8481	return (ISC_R_SUCCESS);
8482}
8483
8484/*
8485 * Incrementally build and sign a new NSEC3 chain using the parameters
8486 * requested.
8487 */
8488static void
8489zone_nsec3chain(dns_zone_t *zone) {
8490	const char *me = "zone_nsec3chain";
8491	dns_db_t *db = NULL;
8492	dns_dbnode_t *node = NULL;
8493	dns_dbversion_t *version = NULL;
8494	dns_diff_t _sig_diff;
8495	dns_diff_t nsec_diff;
8496	dns_diff_t nsec3_diff;
8497	dns_diff_t param_diff;
8498	dns__zonediff_t zonediff;
8499	dns_fixedname_t fixed;
8500	dns_fixedname_t nextfixed;
8501	dns_name_t *name, *nextname;
8502	dns_rdataset_t rdataset;
8503	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
8504	dns_nsec3chainlist_t cleanup;
8505	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8506	int32_t signatures;
8507	bool check_ksk, keyset_kskonly;
8508	bool delegation;
8509	bool first;
8510	isc_result_t result;
8511	isc_stdtime_t now, inception, soaexpire, expire;
8512	uint32_t jitter, sigvalidityinterval, expiryinterval;
8513	unsigned int i;
8514	unsigned int nkeys = 0;
8515	uint32_t nodes;
8516	bool unsecure = false;
8517	bool seen_soa, seen_ns, seen_dname, seen_ds;
8518	bool seen_nsec, seen_nsec3, seen_rr;
8519	dns_rdatasetiter_t *iterator = NULL;
8520	bool buildnsecchain;
8521	bool updatensec = false;
8522	dns_rdatatype_t privatetype = zone->privatetype;
8523
8524	ENTER;
8525
8526	dns_rdataset_init(&rdataset);
8527	name = dns_fixedname_initname(&fixed);
8528	nextname = dns_fixedname_initname(&nextfixed);
8529	dns_diff_init(zone->mctx, &param_diff);
8530	dns_diff_init(zone->mctx, &nsec3_diff);
8531	dns_diff_init(zone->mctx, &nsec_diff);
8532	dns_diff_init(zone->mctx, &_sig_diff);
8533	zonediff_init(&zonediff, &_sig_diff);
8534	ISC_LIST_INIT(cleanup);
8535
8536	/*
8537	 * Updates are disabled.  Pause for 5 minutes.
8538	 */
8539	if (zone->update_disabled) {
8540		result = ISC_R_FAILURE;
8541		goto failure;
8542	}
8543
8544	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8545	/*
8546	 * This function is called when zone timer fires, after the latter gets
8547	 * set by zone_addnsec3chain().  If the action triggering the call to
8548	 * zone_addnsec3chain() is closely followed by a zone deletion request,
8549	 * it might turn out that the timer thread will not be woken up until
8550	 * after the zone is deleted by rmzone(), which calls dns_db_detach()
8551	 * for zone->db, causing the latter to become NULL.  Return immediately
8552	 * if that happens.
8553	 */
8554	if (zone->db != NULL) {
8555		dns_db_attach(zone->db, &db);
8556	}
8557	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8558	if (db == NULL) {
8559		return;
8560	}
8561
8562	result = dns_db_newversion(db, &version);
8563	if (result != ISC_R_SUCCESS) {
8564		dnssec_log(zone, ISC_LOG_ERROR,
8565			   "zone_nsec3chain:dns_db_newversion -> %s",
8566			   dns_result_totext(result));
8567		goto failure;
8568	}
8569
8570	isc_stdtime_get(&now);
8571
8572	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8573				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
8574	if (result != ISC_R_SUCCESS) {
8575		dnssec_log(zone, ISC_LOG_ERROR,
8576			   "zone_nsec3chain:dns__zone_findkeys -> %s",
8577			   dns_result_totext(result));
8578		goto failure;
8579	}
8580
8581	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8582	inception = now - 3600; /* Allow for clock skew. */
8583	soaexpire = now + sigvalidityinterval;
8584	expiryinterval = dns_zone_getsigresigninginterval(zone);
8585	if (expiryinterval > sigvalidityinterval) {
8586		expiryinterval = sigvalidityinterval;
8587	} else {
8588		expiryinterval = sigvalidityinterval - expiryinterval;
8589	}
8590
8591	/*
8592	 * Spread out signatures over time if they happen to be
8593	 * clumped.  We don't do this for each add_sigs() call as
8594	 * we still want some clustering to occur.
8595	 */
8596	if (sigvalidityinterval >= 3600U) {
8597		if (sigvalidityinterval > 7200U) {
8598			jitter = isc_random_uniform(expiryinterval);
8599		} else {
8600			jitter = isc_random_uniform(1200);
8601		}
8602		expire = soaexpire - jitter - 1;
8603	} else {
8604		expire = soaexpire - 1;
8605	}
8606
8607	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8608	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8609
8610	/*
8611	 * We keep pulling nodes off each iterator in turn until
8612	 * we have no more nodes to pull off or we reach the limits
8613	 * for this quantum.
8614	 */
8615	nodes = zone->nodes;
8616	signatures = zone->signatures;
8617	LOCK_ZONE(zone);
8618	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8619	UNLOCK_ZONE(zone);
8620	first = true;
8621
8622	if (nsec3chain != NULL) {
8623		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8624	}
8625	/*
8626	 * Generate new NSEC3 chains first.
8627	 *
8628	 * The following while loop iterates over nodes in the zone database,
8629	 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
8630	 * them.  Once all nodes are processed, the "delete_nsec" field is
8631	 * consulted to check whether we are supposed to remove NSEC records
8632	 * from the zone database; if so, the database iterator is reset to
8633	 * point to the first node and the loop traverses all of them again,
8634	 * this time removing NSEC records.  If we hit a node which is obscured
8635	 * by a delegation or a DNAME, nodes are skipped over until we find one
8636	 * that is not obscured by the same obscuring name and then normal
8637	 * processing is resumed.
8638	 *
8639	 * The above is repeated until all requested NSEC3 chain changes are
8640	 * applied or when we reach the limits for this quantum, whichever
8641	 * happens first.
8642	 *
8643	 * Note that the "signatures" variable is only used here to limit the
8644	 * amount of work performed.  Actual DNSSEC signatures are only
8645	 * generated by dns__zone_updatesigs() calls later in this function.
8646	 */
8647	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8648		dns_dbiterator_pause(nsec3chain->dbiterator);
8649
8650		LOCK_ZONE(zone);
8651		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8652
8653		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8654		if (nsec3chain->done || nsec3chain->db != zone->db) {
8655			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
8656			ISC_LIST_APPEND(cleanup, nsec3chain, link);
8657		}
8658		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8659		UNLOCK_ZONE(zone);
8660		if (ISC_LIST_TAIL(cleanup) == nsec3chain) {
8661			goto next_addchain;
8662		}
8663
8664		/*
8665		 * Possible future db.
8666		 */
8667		if (nsec3chain->db != db) {
8668			goto next_addchain;
8669		}
8670
8671		if (NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8672			goto next_addchain;
8673		}
8674
8675		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8676
8677		if (nsec3chain->delete_nsec) {
8678			delegation = false;
8679			dns_dbiterator_pause(nsec3chain->dbiterator);
8680			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
8681			goto next_addnode;
8682		}
8683		/*
8684		 * On the first pass we need to check if the current node
8685		 * has not been obscured.
8686		 */
8687		delegation = false;
8688		unsecure = false;
8689		if (first) {
8690			dns_fixedname_t ffound;
8691			dns_name_t *found;
8692			found = dns_fixedname_initname(&ffound);
8693			result = dns_db_find(
8694				db, name, version, dns_rdatatype_soa,
8695				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8696			if ((result == DNS_R_DELEGATION ||
8697			     result == DNS_R_DNAME) &&
8698			    !dns_name_equal(name, found))
8699			{
8700				/*
8701				 * Remember the obscuring name so that
8702				 * we skip all obscured names.
8703				 */
8704				dns_name_copynf(found, name);
8705				delegation = true;
8706				goto next_addnode;
8707			}
8708		}
8709
8710		/*
8711		 * Check to see if this is a bottom of zone node.
8712		 */
8713		result = dns_db_allrdatasets(db, node, version, 0, 0,
8714					     &iterator);
8715		if (result == ISC_R_NOTFOUND) {
8716			/* Empty node? */
8717			goto next_addnode;
8718		}
8719		if (result != ISC_R_SUCCESS) {
8720			goto failure;
8721		}
8722
8723		seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
8724		for (result = dns_rdatasetiter_first(iterator);
8725		     result == ISC_R_SUCCESS;
8726		     result = dns_rdatasetiter_next(iterator))
8727		{
8728			dns_rdatasetiter_current(iterator, &rdataset);
8729			INSIST(rdataset.type != dns_rdatatype_nsec3);
8730			if (rdataset.type == dns_rdatatype_soa) {
8731				seen_soa = true;
8732			} else if (rdataset.type == dns_rdatatype_ns) {
8733				seen_ns = true;
8734			} else if (rdataset.type == dns_rdatatype_dname) {
8735				seen_dname = true;
8736			} else if (rdataset.type == dns_rdatatype_ds) {
8737				seen_ds = true;
8738			} else if (rdataset.type == dns_rdatatype_nsec) {
8739				seen_nsec = true;
8740			}
8741			dns_rdataset_disassociate(&rdataset);
8742		}
8743		dns_rdatasetiter_destroy(&iterator);
8744		/*
8745		 * Is there a NSEC chain than needs to be cleaned up?
8746		 */
8747		if (seen_nsec) {
8748			nsec3chain->seen_nsec = true;
8749		}
8750		if (seen_ns && !seen_soa && !seen_ds) {
8751			unsecure = true;
8752		}
8753		if ((seen_ns && !seen_soa) || seen_dname) {
8754			delegation = true;
8755		}
8756
8757		/*
8758		 * Process one node.
8759		 */
8760		dns_dbiterator_pause(nsec3chain->dbiterator);
8761		result = dns_nsec3_addnsec3(
8762			db, version, name, &nsec3chain->nsec3param,
8763			zone_nsecttl(zone), unsecure, &nsec3_diff);
8764		if (result != ISC_R_SUCCESS) {
8765			dnssec_log(zone, ISC_LOG_ERROR,
8766				   "zone_nsec3chain:"
8767				   "dns_nsec3_addnsec3 -> %s",
8768				   dns_result_totext(result));
8769			goto failure;
8770		}
8771
8772		/*
8773		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
8774		 * two signatures.  Additionally there will, in general, be
8775		 * two signature generated below.
8776		 *
8777		 * If we are only changing the optout flag the cost is half
8778		 * that of the cost of generating a completely new chain.
8779		 */
8780		signatures -= 4;
8781
8782		/*
8783		 * Go onto next node.
8784		 */
8785	next_addnode:
8786		first = false;
8787		dns_db_detachnode(db, &node);
8788		do {
8789			result = dns_dbiterator_next(nsec3chain->dbiterator);
8790
8791			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
8792				dns_dbiterator_pause(nsec3chain->dbiterator);
8793				CHECK(fixup_nsec3param(db, version, nsec3chain,
8794						       false, privatetype,
8795						       &param_diff));
8796				LOCK_ZONE(zone);
8797				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8798						link);
8799				UNLOCK_ZONE(zone);
8800				ISC_LIST_APPEND(cleanup, nsec3chain, link);
8801				goto next_addchain;
8802			}
8803			if (result == ISC_R_NOMORE) {
8804				dns_dbiterator_pause(nsec3chain->dbiterator);
8805				if (nsec3chain->seen_nsec) {
8806					CHECK(fixup_nsec3param(
8807						db, version, nsec3chain, true,
8808						privatetype, &param_diff));
8809					nsec3chain->delete_nsec = true;
8810					goto same_addchain;
8811				}
8812				CHECK(fixup_nsec3param(db, version, nsec3chain,
8813						       false, privatetype,
8814						       &param_diff));
8815				LOCK_ZONE(zone);
8816				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8817						link);
8818				UNLOCK_ZONE(zone);
8819				ISC_LIST_APPEND(cleanup, nsec3chain, link);
8820				goto next_addchain;
8821			} else if (result != ISC_R_SUCCESS) {
8822				dnssec_log(zone, ISC_LOG_ERROR,
8823					   "zone_nsec3chain:"
8824					   "dns_dbiterator_next -> %s",
8825					   dns_result_totext(result));
8826				goto failure;
8827			} else if (delegation) {
8828				dns_dbiterator_current(nsec3chain->dbiterator,
8829						       &node, nextname);
8830				dns_db_detachnode(db, &node);
8831				if (!dns_name_issubdomain(nextname, name)) {
8832					break;
8833				}
8834			} else {
8835				break;
8836			}
8837		} while (1);
8838		continue;
8839
8840	same_addchain:
8841		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8842		first = true;
8843		continue;
8844
8845	next_addchain:
8846		dns_dbiterator_pause(nsec3chain->dbiterator);
8847		nsec3chain = nextnsec3chain;
8848		first = true;
8849		if (nsec3chain != NULL) {
8850			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8851		}
8852	}
8853
8854	if (nsec3chain != NULL) {
8855		goto skip_removals;
8856	}
8857
8858	/*
8859	 * Process removals.
8860	 *
8861	 * This is a counterpart of the above while loop which takes care of
8862	 * removing an NSEC3 chain.  It starts with determining whether the
8863	 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
8864	 * NSEC chain by iterating over all nodes in the zone database and only
8865	 * then goes on to remove NSEC3 records be iterating over all nodes
8866	 * again and calling deletematchingnsec3() for each of them; otherwise,
8867	 * it starts removing NSEC3 records immediately.  Rules for processing
8868	 * obscured nodes and interrupting work are the same as for the while
8869	 * loop above.
8870	 */
8871	LOCK_ZONE(zone);
8872	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8873	UNLOCK_ZONE(zone);
8874	first = true;
8875	buildnsecchain = false;
8876	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8877		dns_dbiterator_pause(nsec3chain->dbiterator);
8878
8879		LOCK_ZONE(zone);
8880		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8881		UNLOCK_ZONE(zone);
8882
8883		if (nsec3chain->db != db) {
8884			goto next_removechain;
8885		}
8886
8887		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8888			goto next_removechain;
8889		}
8890
8891		/*
8892		 * Work out if we need to build a NSEC chain as a consequence
8893		 * of removing this NSEC3 chain.
8894		 */
8895		if (first && !updatensec &&
8896		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8897		{
8898			result = need_nsec_chain(db, version,
8899						 &nsec3chain->nsec3param,
8900						 &buildnsecchain);
8901			if (result != ISC_R_SUCCESS) {
8902				dnssec_log(zone, ISC_LOG_ERROR,
8903					   "zone_nsec3chain:"
8904					   "need_nsec_chain -> %s",
8905					   dns_result_totext(result));
8906				goto failure;
8907			}
8908		}
8909
8910		if (first) {
8911			dnssec_log(zone, ISC_LOG_DEBUG(3),
8912				   "zone_nsec3chain:buildnsecchain = %u\n",
8913				   buildnsecchain);
8914		}
8915
8916		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8917		dns_dbiterator_pause(nsec3chain->dbiterator);
8918		delegation = false;
8919
8920		if (!buildnsecchain) {
8921			/*
8922			 * Delete the NSEC3PARAM record matching this chain.
8923			 */
8924			if (first) {
8925				result = fixup_nsec3param(
8926					db, version, nsec3chain, true,
8927					privatetype, &param_diff);
8928				if (result != ISC_R_SUCCESS) {
8929					dnssec_log(zone, ISC_LOG_ERROR,
8930						   "zone_nsec3chain:"
8931						   "fixup_nsec3param -> %s",
8932						   dns_result_totext(result));
8933					goto failure;
8934				}
8935			}
8936
8937			/*
8938			 * Delete the NSEC3 records.
8939			 */
8940			result = deletematchingnsec3(db, version, node, name,
8941						     &nsec3chain->nsec3param,
8942						     &nsec3_diff);
8943			if (result != ISC_R_SUCCESS) {
8944				dnssec_log(zone, ISC_LOG_ERROR,
8945					   "zone_nsec3chain:"
8946					   "deletematchingnsec3 -> %s",
8947					   dns_result_totext(result));
8948				goto failure;
8949			}
8950			goto next_removenode;
8951		}
8952
8953		if (first) {
8954			dns_fixedname_t ffound;
8955			dns_name_t *found;
8956			found = dns_fixedname_initname(&ffound);
8957			result = dns_db_find(
8958				db, name, version, dns_rdatatype_soa,
8959				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8960			if ((result == DNS_R_DELEGATION ||
8961			     result == DNS_R_DNAME) &&
8962			    !dns_name_equal(name, found))
8963			{
8964				/*
8965				 * Remember the obscuring name so that
8966				 * we skip all obscured names.
8967				 */
8968				dns_name_copynf(found, name);
8969				delegation = true;
8970				goto next_removenode;
8971			}
8972		}
8973
8974		/*
8975		 * Check to see if this is a bottom of zone node.
8976		 */
8977		result = dns_db_allrdatasets(db, node, version, 0, 0,
8978					     &iterator);
8979		if (result == ISC_R_NOTFOUND) {
8980			/* Empty node? */
8981			goto next_removenode;
8982		}
8983		if (result != ISC_R_SUCCESS) {
8984			goto failure;
8985		}
8986
8987		seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
8988			seen_rr = false;
8989		for (result = dns_rdatasetiter_first(iterator);
8990		     result == ISC_R_SUCCESS;
8991		     result = dns_rdatasetiter_next(iterator))
8992		{
8993			dns_rdatasetiter_current(iterator, &rdataset);
8994			if (rdataset.type == dns_rdatatype_soa) {
8995				seen_soa = true;
8996			} else if (rdataset.type == dns_rdatatype_ns) {
8997				seen_ns = true;
8998			} else if (rdataset.type == dns_rdatatype_dname) {
8999				seen_dname = true;
9000			} else if (rdataset.type == dns_rdatatype_nsec) {
9001				seen_nsec = true;
9002			} else if (rdataset.type == dns_rdatatype_nsec3) {
9003				seen_nsec3 = true;
9004			} else if (rdataset.type != dns_rdatatype_rrsig) {
9005				seen_rr = true;
9006			}
9007			dns_rdataset_disassociate(&rdataset);
9008		}
9009		dns_rdatasetiter_destroy(&iterator);
9010
9011		if (!seen_rr || seen_nsec3 || seen_nsec) {
9012			goto next_removenode;
9013		}
9014		if ((seen_ns && !seen_soa) || seen_dname) {
9015			delegation = true;
9016		}
9017
9018		/*
9019		 * Add a NSEC record except at the origin.
9020		 */
9021		if (!dns_name_equal(name, dns_db_origin(db))) {
9022			dns_dbiterator_pause(nsec3chain->dbiterator);
9023			CHECK(add_nsec(db, version, name, node,
9024				       zone_nsecttl(zone), delegation,
9025				       &nsec_diff));
9026			signatures--;
9027		}
9028
9029	next_removenode:
9030		first = false;
9031		dns_db_detachnode(db, &node);
9032		do {
9033			result = dns_dbiterator_next(nsec3chain->dbiterator);
9034			if (result == ISC_R_NOMORE && buildnsecchain) {
9035				/*
9036				 * The NSEC chain should now be built.
9037				 * We can now remove the NSEC3 chain.
9038				 */
9039				updatensec = true;
9040				goto same_removechain;
9041			}
9042			if (result == ISC_R_NOMORE) {
9043				dns_dbiterator_pause(nsec3chain->dbiterator);
9044				LOCK_ZONE(zone);
9045				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
9046						link);
9047				UNLOCK_ZONE(zone);
9048				ISC_LIST_APPEND(cleanup, nsec3chain, link);
9049				result = fixup_nsec3param(
9050					db, version, nsec3chain, false,
9051					privatetype, &param_diff);
9052				if (result != ISC_R_SUCCESS) {
9053					dnssec_log(zone, ISC_LOG_ERROR,
9054						   "zone_nsec3chain:"
9055						   "fixup_nsec3param -> %s",
9056						   dns_result_totext(result));
9057					goto failure;
9058				}
9059				goto next_removechain;
9060			} else if (result != ISC_R_SUCCESS) {
9061				dnssec_log(zone, ISC_LOG_ERROR,
9062					   "zone_nsec3chain:"
9063					   "dns_dbiterator_next -> %s",
9064					   dns_result_totext(result));
9065				goto failure;
9066			} else if (delegation) {
9067				dns_dbiterator_current(nsec3chain->dbiterator,
9068						       &node, nextname);
9069				dns_db_detachnode(db, &node);
9070				if (!dns_name_issubdomain(nextname, name)) {
9071					break;
9072				}
9073			} else {
9074				break;
9075			}
9076		} while (1);
9077		continue;
9078
9079	same_removechain:
9080		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
9081		buildnsecchain = false;
9082		first = true;
9083		continue;
9084
9085	next_removechain:
9086		dns_dbiterator_pause(nsec3chain->dbiterator);
9087		nsec3chain = nextnsec3chain;
9088		first = true;
9089	}
9090
9091skip_removals:
9092	/*
9093	 * We may need to update the NSEC/NSEC3 records for the zone apex.
9094	 */
9095	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
9096		bool rebuild_nsec = false, rebuild_nsec3 = false;
9097		result = dns_db_getoriginnode(db, &node);
9098		RUNTIME_CHECK(result == ISC_R_SUCCESS);
9099		result = dns_db_allrdatasets(db, node, version, 0, 0,
9100					     &iterator);
9101		if (result != ISC_R_SUCCESS) {
9102			dnssec_log(zone, ISC_LOG_ERROR,
9103				   "zone_nsec3chain:dns_db_allrdatasets -> %s",
9104				   dns_result_totext(result));
9105			goto failure;
9106		}
9107		for (result = dns_rdatasetiter_first(iterator);
9108		     result == ISC_R_SUCCESS;
9109		     result = dns_rdatasetiter_next(iterator))
9110		{
9111			dns_rdatasetiter_current(iterator, &rdataset);
9112			if (rdataset.type == dns_rdatatype_nsec) {
9113				rebuild_nsec = true;
9114			} else if (rdataset.type == dns_rdatatype_nsec3param) {
9115				rebuild_nsec3 = true;
9116			}
9117			dns_rdataset_disassociate(&rdataset);
9118		}
9119		dns_rdatasetiter_destroy(&iterator);
9120		dns_db_detachnode(db, &node);
9121
9122		if (rebuild_nsec) {
9123			if (nsec3chain != NULL) {
9124				dns_dbiterator_pause(nsec3chain->dbiterator);
9125			}
9126
9127			result = updatesecure(db, version, &zone->origin,
9128					      zone_nsecttl(zone), true,
9129					      &nsec_diff);
9130			if (result != ISC_R_SUCCESS) {
9131				dnssec_log(zone, ISC_LOG_ERROR,
9132					   "zone_nsec3chain:updatesecure -> %s",
9133					   dns_result_totext(result));
9134				goto failure;
9135			}
9136		}
9137
9138		if (rebuild_nsec3) {
9139			if (nsec3chain != NULL) {
9140				dns_dbiterator_pause(nsec3chain->dbiterator);
9141			}
9142
9143			result = dns_nsec3_addnsec3s(
9144				db, version, dns_db_origin(db),
9145				zone_nsecttl(zone), false, &nsec3_diff);
9146			if (result != ISC_R_SUCCESS) {
9147				dnssec_log(zone, ISC_LOG_ERROR,
9148					   "zone_nsec3chain:"
9149					   "dns_nsec3_addnsec3s -> %s",
9150					   dns_result_totext(result));
9151				goto failure;
9152			}
9153		}
9154	}
9155
9156	/*
9157	 * Add / update signatures for the NSEC3 records.
9158	 */
9159	if (nsec3chain != NULL) {
9160		dns_dbiterator_pause(nsec3chain->dbiterator);
9161	}
9162	result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
9163				      nkeys, zone, inception, expire, 0, now,
9164				      check_ksk, keyset_kskonly, &zonediff);
9165	if (result != ISC_R_SUCCESS) {
9166		dnssec_log(zone, ISC_LOG_ERROR,
9167			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
9168			   dns_result_totext(result));
9169		goto failure;
9170	}
9171
9172	/*
9173	 * We have changed the NSEC3PARAM or private RRsets
9174	 * above so we need to update the signatures.
9175	 */
9176	result = dns__zone_updatesigs(&param_diff, db, version, zone_keys,
9177				      nkeys, zone, inception, expire, 0, now,
9178				      check_ksk, keyset_kskonly, &zonediff);
9179	if (result != ISC_R_SUCCESS) {
9180		dnssec_log(zone, ISC_LOG_ERROR,
9181			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
9182			   dns_result_totext(result));
9183		goto failure;
9184	}
9185
9186	if (updatensec) {
9187		result = updatesecure(db, version, &zone->origin,
9188				      zone_nsecttl(zone), false, &nsec_diff);
9189		if (result != ISC_R_SUCCESS) {
9190			dnssec_log(zone, ISC_LOG_ERROR,
9191				   "zone_nsec3chain:updatesecure -> %s",
9192				   dns_result_totext(result));
9193			goto failure;
9194		}
9195	}
9196
9197	result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys, nkeys,
9198				      zone, inception, expire, 0, now,
9199				      check_ksk, keyset_kskonly, &zonediff);
9200	if (result != ISC_R_SUCCESS) {
9201		dnssec_log(zone, ISC_LOG_ERROR,
9202			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
9203			   dns_result_totext(result));
9204		goto failure;
9205	}
9206
9207	/*
9208	 * If we made no effective changes to the zone then we can just
9209	 * cleanup otherwise we need to increment the serial.
9210	 */
9211	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9212		/*
9213		 * No need to call dns_db_closeversion() here as it is
9214		 * called with commit = true below.
9215		 */
9216		goto done;
9217	}
9218
9219	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9220			  &zonediff, zone_keys, nkeys, now, false);
9221	if (result != ISC_R_SUCCESS) {
9222		dnssec_log(zone, ISC_LOG_ERROR,
9223			   "zone_nsec3chain:del_sigs -> %s",
9224			   dns_result_totext(result));
9225		goto failure;
9226	}
9227
9228	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9229				   zone->updatemethod);
9230	if (result != ISC_R_SUCCESS) {
9231		dnssec_log(zone, ISC_LOG_ERROR,
9232			   "zone_nsec3chain:update_soa_serial -> %s",
9233			   dns_result_totext(result));
9234		goto failure;
9235	}
9236
9237	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9238			  zonediff.diff, zone_keys, nkeys, zone->mctx,
9239			  inception, soaexpire, check_ksk, keyset_kskonly);
9240	if (result != ISC_R_SUCCESS) {
9241		dnssec_log(zone, ISC_LOG_ERROR,
9242			   "zone_nsec3chain:add_sigs -> %s",
9243			   dns_result_totext(result));
9244		goto failure;
9245	}
9246
9247	/* Write changes to journal file. */
9248	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
9249
9250	LOCK_ZONE(zone);
9251	zone_needdump(zone, DNS_DUMP_DELAY);
9252	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9253	UNLOCK_ZONE(zone);
9254
9255done:
9256	/*
9257	 * Pause all iterators so that dns_db_closeversion() can succeed.
9258	 */
9259	LOCK_ZONE(zone);
9260	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9261	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9262	{
9263		dns_dbiterator_pause(nsec3chain->dbiterator);
9264	}
9265	UNLOCK_ZONE(zone);
9266
9267	/*
9268	 * Everything has succeeded. Commit the changes.
9269	 * Unconditionally commit as zonediff.offline not checked above.
9270	 */
9271	dns_db_closeversion(db, &version, true);
9272
9273	/*
9274	 * Everything succeeded so we can clean these up now.
9275	 */
9276	nsec3chain = ISC_LIST_HEAD(cleanup);
9277	while (nsec3chain != NULL) {
9278		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9279		dns_db_detach(&nsec3chain->db);
9280		dns_dbiterator_destroy(&nsec3chain->dbiterator);
9281		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9282		nsec3chain = ISC_LIST_HEAD(cleanup);
9283	}
9284
9285	LOCK_ZONE(zone);
9286	set_resigntime(zone);
9287	UNLOCK_ZONE(zone);
9288
9289failure:
9290	if (result != ISC_R_SUCCESS) {
9291		dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
9292			   dns_result_totext(result));
9293	}
9294
9295	/*
9296	 * On error roll back the current nsec3chain.
9297	 */
9298	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
9299		if (nsec3chain->done) {
9300			dns_db_detach(&nsec3chain->db);
9301			dns_dbiterator_destroy(&nsec3chain->dbiterator);
9302			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9303		} else {
9304			result = dns_dbiterator_first(nsec3chain->dbiterator);
9305			RUNTIME_CHECK(result == ISC_R_SUCCESS);
9306			dns_dbiterator_pause(nsec3chain->dbiterator);
9307			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9308		}
9309	}
9310
9311	/*
9312	 * Rollback the cleanup list.
9313	 */
9314	nsec3chain = ISC_LIST_TAIL(cleanup);
9315	while (nsec3chain != NULL) {
9316		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9317		if (nsec3chain->done) {
9318			dns_db_detach(&nsec3chain->db);
9319			dns_dbiterator_destroy(&nsec3chain->dbiterator);
9320			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9321		} else {
9322			LOCK_ZONE(zone);
9323			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
9324			UNLOCK_ZONE(zone);
9325			result = dns_dbiterator_first(nsec3chain->dbiterator);
9326			RUNTIME_CHECK(result == ISC_R_SUCCESS);
9327			dns_dbiterator_pause(nsec3chain->dbiterator);
9328			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9329		}
9330		nsec3chain = ISC_LIST_TAIL(cleanup);
9331	}
9332
9333	LOCK_ZONE(zone);
9334	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9335	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9336	{
9337		dns_dbiterator_pause(nsec3chain->dbiterator);
9338	}
9339	UNLOCK_ZONE(zone);
9340
9341	dns_diff_clear(&param_diff);
9342	dns_diff_clear(&nsec3_diff);
9343	dns_diff_clear(&nsec_diff);
9344	dns_diff_clear(&_sig_diff);
9345
9346	if (iterator != NULL) {
9347		dns_rdatasetiter_destroy(&iterator);
9348	}
9349
9350	for (i = 0; i < nkeys; i++) {
9351		dst_key_free(&zone_keys[i]);
9352	}
9353
9354	if (node != NULL) {
9355		dns_db_detachnode(db, &node);
9356	}
9357	if (version != NULL) {
9358		dns_db_closeversion(db, &version, false);
9359		dns_db_detach(&db);
9360	} else if (db != NULL) {
9361		dns_db_detach(&db);
9362	}
9363
9364	LOCK_ZONE(zone);
9365	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
9366		isc_interval_t interval;
9367		if (zone->update_disabled || result != ISC_R_SUCCESS) {
9368			isc_interval_set(&interval, 60, 0); /* 1 minute */
9369		} else {
9370			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9371		}
9372		isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
9373	} else {
9374		isc_time_settoepoch(&zone->nsec3chaintime);
9375	}
9376	UNLOCK_ZONE(zone);
9377
9378	INSIST(version == NULL);
9379}
9380
9381/*%
9382 * Delete all RRSIG records with the given algorithm and keyid.
9383 * Remove the NSEC record and RRSIGs if nkeys is zero.
9384 * If all remaining RRsets are signed with the given algorithm
9385 * set *has_algp to true.
9386 */
9387static isc_result_t
9388del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
9389	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
9390	uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
9391	dns_rdata_rrsig_t rrsig;
9392	dns_rdataset_t rdataset;
9393	dns_rdatasetiter_t *iterator = NULL;
9394	isc_result_t result;
9395	bool alg_missed = false;
9396	bool alg_found = false;
9397
9398	char namebuf[DNS_NAME_FORMATSIZE];
9399	dns_name_format(name, namebuf, sizeof(namebuf));
9400
9401	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
9402	if (result != ISC_R_SUCCESS) {
9403		if (result == ISC_R_NOTFOUND) {
9404			result = ISC_R_SUCCESS;
9405		}
9406		return (result);
9407	}
9408
9409	dns_rdataset_init(&rdataset);
9410	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
9411	     result = dns_rdatasetiter_next(iterator))
9412	{
9413		bool has_alg = false;
9414		dns_rdatasetiter_current(iterator, &rdataset);
9415		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
9416			for (result = dns_rdataset_first(&rdataset);
9417			     result == ISC_R_SUCCESS;
9418			     result = dns_rdataset_next(&rdataset))
9419			{
9420				dns_rdata_t rdata = DNS_RDATA_INIT;
9421				dns_rdataset_current(&rdataset, &rdata);
9422				CHECK(update_one_rr(db, version, diff,
9423						    DNS_DIFFOP_DEL, name,
9424						    rdataset.ttl, &rdata));
9425			}
9426			if (result != ISC_R_NOMORE) {
9427				goto failure;
9428			}
9429			dns_rdataset_disassociate(&rdataset);
9430			continue;
9431		}
9432		if (rdataset.type != dns_rdatatype_rrsig) {
9433			dns_rdataset_disassociate(&rdataset);
9434			continue;
9435		}
9436		for (result = dns_rdataset_first(&rdataset);
9437		     result == ISC_R_SUCCESS;
9438		     result = dns_rdataset_next(&rdataset))
9439		{
9440			dns_rdata_t rdata = DNS_RDATA_INIT;
9441			dns_rdataset_current(&rdataset, &rdata);
9442			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
9443			if (nkeys != 0 && (rrsig.algorithm != algorithm ||
9444					   rrsig.keyid != keyid))
9445			{
9446				if (rrsig.algorithm == algorithm) {
9447					has_alg = true;
9448				}
9449				continue;
9450			}
9451			CHECK(update_one_rr(db, version, diff,
9452					    DNS_DIFFOP_DELRESIGN, name,
9453					    rdataset.ttl, &rdata));
9454		}
9455		dns_rdataset_disassociate(&rdataset);
9456		if (result != ISC_R_NOMORE) {
9457			break;
9458		}
9459
9460		/*
9461		 * After deleting, if there's still a signature for
9462		 * 'algorithm', set alg_found; if not, set alg_missed.
9463		 */
9464		if (has_alg) {
9465			alg_found = true;
9466		} else {
9467			alg_missed = true;
9468		}
9469	}
9470	if (result == ISC_R_NOMORE) {
9471		result = ISC_R_SUCCESS;
9472	}
9473
9474	/*
9475	 * Set `has_algp` if the algorithm was found in every RRset:
9476	 * i.e., found in at least one, and not missing from any.
9477	 */
9478	*has_algp = (alg_found && !alg_missed);
9479failure:
9480	if (dns_rdataset_isassociated(&rdataset)) {
9481		dns_rdataset_disassociate(&rdataset);
9482	}
9483	dns_rdatasetiter_destroy(&iterator);
9484	return (result);
9485}
9486
9487/*
9488 * Incrementally sign the zone using the keys requested.
9489 * Builds the NSEC chain if required.
9490 */
9491static void
9492zone_sign(dns_zone_t *zone) {
9493	const char *me = "zone_sign";
9494	dns_db_t *db = NULL;
9495	dns_dbnode_t *node = NULL;
9496	dns_dbversion_t *version = NULL;
9497	dns_diff_t _sig_diff;
9498	dns_diff_t post_diff;
9499	dns__zonediff_t zonediff;
9500	dns_fixedname_t fixed;
9501	dns_fixedname_t nextfixed;
9502	dns_kasp_t *kasp;
9503	dns_name_t *name, *nextname;
9504	dns_rdataset_t rdataset;
9505	dns_signing_t *signing, *nextsigning;
9506	dns_signinglist_t cleanup;
9507	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
9508	int32_t signatures;
9509	bool check_ksk, keyset_kskonly, is_ksk, is_zsk;
9510	bool with_ksk, with_zsk;
9511	bool commit = false;
9512	bool is_bottom_of_zone;
9513	bool build_nsec = false;
9514	bool build_nsec3 = false;
9515	bool use_kasp = false;
9516	bool first;
9517	isc_result_t result;
9518	isc_stdtime_t now, inception, soaexpire, expire;
9519	uint32_t jitter, sigvalidityinterval, expiryinterval;
9520	unsigned int i, j;
9521	unsigned int nkeys = 0;
9522	uint32_t nodes;
9523
9524	ENTER;
9525
9526	dns_rdataset_init(&rdataset);
9527	name = dns_fixedname_initname(&fixed);
9528	nextname = dns_fixedname_initname(&nextfixed);
9529	dns_diff_init(zone->mctx, &_sig_diff);
9530	dns_diff_init(zone->mctx, &post_diff);
9531	zonediff_init(&zonediff, &_sig_diff);
9532	ISC_LIST_INIT(cleanup);
9533
9534	/*
9535	 * Updates are disabled.  Pause for 1 minute.
9536	 */
9537	if (zone->update_disabled) {
9538		result = ISC_R_FAILURE;
9539		goto cleanup;
9540	}
9541
9542	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9543	if (zone->db != NULL) {
9544		dns_db_attach(zone->db, &db);
9545	}
9546	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9547	if (db == NULL) {
9548		result = ISC_R_FAILURE;
9549		goto cleanup;
9550	}
9551
9552	result = dns_db_newversion(db, &version);
9553	if (result != ISC_R_SUCCESS) {
9554		dnssec_log(zone, ISC_LOG_ERROR,
9555			   "zone_sign:dns_db_newversion -> %s",
9556			   dns_result_totext(result));
9557		goto cleanup;
9558	}
9559
9560	isc_stdtime_get(&now);
9561
9562	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
9563				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
9564	if (result != ISC_R_SUCCESS) {
9565		dnssec_log(zone, ISC_LOG_ERROR,
9566			   "zone_sign:dns__zone_findkeys -> %s",
9567			   dns_result_totext(result));
9568		goto cleanup;
9569	}
9570
9571	kasp = dns_zone_getkasp(zone);
9572	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
9573	inception = now - 3600; /* Allow for clock skew. */
9574	soaexpire = now + sigvalidityinterval;
9575	expiryinterval = dns_zone_getsigresigninginterval(zone);
9576	if (expiryinterval > sigvalidityinterval) {
9577		expiryinterval = sigvalidityinterval;
9578	} else {
9579		expiryinterval = sigvalidityinterval - expiryinterval;
9580	}
9581
9582	/*
9583	 * Spread out signatures over time if they happen to be
9584	 * clumped.  We don't do this for each add_sigs() call as
9585	 * we still want some clustering to occur.
9586	 */
9587	if (sigvalidityinterval >= 3600U) {
9588		if (sigvalidityinterval > 7200U) {
9589			jitter = isc_random_uniform(expiryinterval);
9590		} else {
9591			jitter = isc_random_uniform(1200);
9592		}
9593		expire = soaexpire - jitter - 1;
9594	} else {
9595		expire = soaexpire - 1;
9596	}
9597
9598	/*
9599	 * We keep pulling nodes off each iterator in turn until
9600	 * we have no more nodes to pull off or we reach the limits
9601	 * for this quantum.
9602	 */
9603	nodes = zone->nodes;
9604	signatures = zone->signatures;
9605	signing = ISC_LIST_HEAD(zone->signing);
9606	first = true;
9607
9608	if (dns_zone_getkasp(zone) != NULL) {
9609		check_ksk = false;
9610		keyset_kskonly = true;
9611		use_kasp = true;
9612	} else {
9613		check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
9614		keyset_kskonly = DNS_ZONE_OPTION(zone,
9615						 DNS_ZONEOPT_DNSKEYKSKONLY);
9616	}
9617	dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
9618		   use_kasp ? "yes" : "no");
9619
9620	/* Determine which type of chain to build */
9621	CHECK(dns_private_chains(db, version, zone->privatetype, &build_nsec,
9622				 &build_nsec3));
9623	if (!build_nsec && !build_nsec3) {
9624		if (use_kasp) {
9625			build_nsec3 = dns_kasp_nsec3(kasp);
9626			build_nsec = !build_nsec3;
9627		} else {
9628			/* If neither chain is found, default to NSEC */
9629			build_nsec = true;
9630		}
9631	}
9632
9633	while (signing != NULL && nodes-- > 0 && signatures > 0) {
9634		bool has_alg = false;
9635
9636		dns_dbiterator_pause(signing->dbiterator);
9637		nextsigning = ISC_LIST_NEXT(signing, link);
9638
9639		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9640		if (signing->done || signing->db != zone->db) {
9641			/*
9642			 * The zone has been reloaded.	We will have to
9643			 * created new signings as part of the reload
9644			 * process so we can destroy this one.
9645			 */
9646			ISC_LIST_UNLINK(zone->signing, signing, link);
9647			ISC_LIST_APPEND(cleanup, signing, link);
9648			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9649			goto next_signing;
9650		}
9651		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9652
9653		if (signing->db != db) {
9654			goto next_signing;
9655		}
9656
9657		is_bottom_of_zone = false;
9658
9659		if (first && signing->deleteit) {
9660			/*
9661			 * Remove the key we are deleting from consideration.
9662			 */
9663			for (i = 0, j = 0; i < nkeys; i++) {
9664				/*
9665				 * Find the key we want to remove.
9666				 */
9667				if (ALG(zone_keys[i]) == signing->algorithm &&
9668				    dst_key_id(zone_keys[i]) == signing->keyid)
9669				{
9670					bool ksk = false;
9671					isc_result_t ret = dst_key_getbool(
9672						zone_keys[i], DST_BOOL_KSK,
9673						&ksk);
9674					if (ret != ISC_R_SUCCESS) {
9675						ksk = KSK(zone_keys[i]);
9676					}
9677					if (ksk) {
9678						dst_key_free(&zone_keys[i]);
9679					}
9680					continue;
9681				}
9682				zone_keys[j] = zone_keys[i];
9683				j++;
9684			}
9685			for (i = j; i < nkeys; i++) {
9686				zone_keys[i] = NULL;
9687			}
9688			nkeys = j;
9689		}
9690
9691		dns_dbiterator_current(signing->dbiterator, &node, name);
9692
9693		if (signing->deleteit) {
9694			dns_dbiterator_pause(signing->dbiterator);
9695			CHECK(del_sig(db, version, name, node, nkeys,
9696				      signing->algorithm, signing->keyid,
9697				      &has_alg, zonediff.diff));
9698		}
9699
9700		/*
9701		 * On the first pass we need to check if the current node
9702		 * has not been obscured.
9703		 */
9704		if (first) {
9705			dns_fixedname_t ffound;
9706			dns_name_t *found;
9707			found = dns_fixedname_initname(&ffound);
9708			result = dns_db_find(
9709				db, name, version, dns_rdatatype_soa,
9710				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
9711			if ((result == DNS_R_DELEGATION ||
9712			     result == DNS_R_DNAME) &&
9713			    !dns_name_equal(name, found))
9714			{
9715				/*
9716				 * Remember the obscuring name so that
9717				 * we skip all obscured names.
9718				 */
9719				dns_name_copynf(found, name);
9720				is_bottom_of_zone = true;
9721				goto next_node;
9722			}
9723		}
9724
9725		/*
9726		 * Process one node.
9727		 */
9728		with_ksk = false;
9729		with_zsk = false;
9730		dns_dbiterator_pause(signing->dbiterator);
9731
9732		CHECK(check_if_bottom_of_zone(db, node, version,
9733					      &is_bottom_of_zone));
9734
9735		for (i = 0; !has_alg && i < nkeys; i++) {
9736			bool both = false;
9737
9738			/*
9739			 * Find the keys we want to sign with.
9740			 */
9741			if (!dst_key_isprivate(zone_keys[i])) {
9742				continue;
9743			}
9744			if (dst_key_inactive(zone_keys[i])) {
9745				continue;
9746			}
9747
9748			/*
9749			 * When adding look for the specific key.
9750			 */
9751			if (!signing->deleteit &&
9752			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
9753			     dst_key_id(zone_keys[i]) != signing->keyid))
9754			{
9755				continue;
9756			}
9757
9758			/*
9759			 * When deleting make sure we are properly signed
9760			 * with the algorithm that was being removed.
9761			 */
9762			if (signing->deleteit &&
9763			    ALG(zone_keys[i]) != signing->algorithm)
9764			{
9765				continue;
9766			}
9767
9768			/*
9769			 * Do we do KSK processing?
9770			 */
9771			if (check_ksk && !REVOKE(zone_keys[i])) {
9772				bool have_ksk, have_nonksk;
9773				if (KSK(zone_keys[i])) {
9774					have_ksk = true;
9775					have_nonksk = false;
9776				} else {
9777					have_ksk = false;
9778					have_nonksk = true;
9779				}
9780				for (j = 0; j < nkeys; j++) {
9781					if (j == i || (ALG(zone_keys[i]) !=
9782						       ALG(zone_keys[j])))
9783					{
9784						continue;
9785					}
9786					/*
9787					 * Don't consider inactive keys, however
9788					 * the key may be temporary offline, so
9789					 * do consider KSKs which private key
9790					 * files are unavailable.
9791					 */
9792					if (dst_key_inactive(zone_keys[j])) {
9793						continue;
9794					}
9795					if (REVOKE(zone_keys[j])) {
9796						continue;
9797					}
9798					if (KSK(zone_keys[j])) {
9799						have_ksk = true;
9800					} else if (dst_key_isprivate(
9801							   zone_keys[j]))
9802					{
9803						have_nonksk = true;
9804					}
9805					both = have_ksk && have_nonksk;
9806					if (both) {
9807						break;
9808					}
9809				}
9810			}
9811			if (use_kasp) {
9812				/*
9813				 * A dnssec-policy is found. Check what
9814				 * RRsets this key can sign.
9815				 */
9816				isc_result_t kresult;
9817				is_ksk = false;
9818				kresult = dst_key_getbool(
9819					zone_keys[i], DST_BOOL_KSK, &is_ksk);
9820				if (kresult != ISC_R_SUCCESS) {
9821					if (KSK(zone_keys[i])) {
9822						is_ksk = true;
9823					}
9824				}
9825
9826				is_zsk = false;
9827				kresult = dst_key_getbool(
9828					zone_keys[i], DST_BOOL_ZSK, &is_zsk);
9829				if (kresult != ISC_R_SUCCESS) {
9830					if (!KSK(zone_keys[i])) {
9831						is_zsk = true;
9832					}
9833				}
9834				/* Treat as if we have both KSK and ZSK. */
9835				both = true;
9836			} else if (both || REVOKE(zone_keys[i])) {
9837				is_ksk = KSK(zone_keys[i]);
9838				is_zsk = !KSK(zone_keys[i]);
9839			} else {
9840				is_ksk = false;
9841				is_zsk = true;
9842			}
9843
9844			/*
9845			 * If deleting signatures, we need to ensure that
9846			 * the RRset is still signed at least once by a
9847			 * KSK and a ZSK.
9848			 */
9849			if (signing->deleteit && is_zsk && with_zsk) {
9850				continue;
9851			}
9852
9853			if (signing->deleteit && is_ksk && with_ksk) {
9854				continue;
9855			}
9856
9857			CHECK(sign_a_node(
9858				db, zone, name, node, version, build_nsec3,
9859				build_nsec, zone_keys[i], inception, expire,
9860				zone_nsecttl(zone), is_ksk, is_zsk,
9861				(both && keyset_kskonly), is_bottom_of_zone,
9862				zonediff.diff, &signatures, zone->mctx));
9863			/*
9864			 * If we are adding we are done.  Look for other keys
9865			 * of the same algorithm if deleting.
9866			 */
9867			if (!signing->deleteit) {
9868				break;
9869			}
9870			if (is_zsk) {
9871				with_zsk = true;
9872			}
9873			if (is_ksk) {
9874				with_ksk = true;
9875			}
9876		}
9877
9878		/*
9879		 * Go onto next node.
9880		 */
9881	next_node:
9882		first = false;
9883		dns_db_detachnode(db, &node);
9884		do {
9885			result = dns_dbiterator_next(signing->dbiterator);
9886			if (result == ISC_R_NOMORE) {
9887				ISC_LIST_UNLINK(zone->signing, signing, link);
9888				ISC_LIST_APPEND(cleanup, signing, link);
9889				dns_dbiterator_pause(signing->dbiterator);
9890				if (nkeys != 0 && build_nsec) {
9891					/*
9892					 * We have finished regenerating the
9893					 * zone with a zone signing key.
9894					 * The NSEC chain is now complete and
9895					 * there is a full set of signatures
9896					 * for the zone.  We can now clear the
9897					 * OPT bit from the NSEC record.
9898					 */
9899					result = updatesecure(
9900						db, version, &zone->origin,
9901						zone_nsecttl(zone), false,
9902						&post_diff);
9903					if (result != ISC_R_SUCCESS) {
9904						dnssec_log(zone, ISC_LOG_ERROR,
9905							   "updatesecure -> %s",
9906							   dns_result_totext(
9907								   result));
9908						goto cleanup;
9909					}
9910				}
9911				result = updatesignwithkey(
9912					zone, signing, version, build_nsec3,
9913					zone_nsecttl(zone), &post_diff);
9914				if (result != ISC_R_SUCCESS) {
9915					dnssec_log(zone, ISC_LOG_ERROR,
9916						   "updatesignwithkey -> %s",
9917						   dns_result_totext(result));
9918					goto cleanup;
9919				}
9920				build_nsec = false;
9921				goto next_signing;
9922			} else if (result != ISC_R_SUCCESS) {
9923				dnssec_log(zone, ISC_LOG_ERROR,
9924					   "zone_sign:"
9925					   "dns_dbiterator_next -> %s",
9926					   dns_result_totext(result));
9927				goto cleanup;
9928			} else if (is_bottom_of_zone) {
9929				dns_dbiterator_current(signing->dbiterator,
9930						       &node, nextname);
9931				dns_db_detachnode(db, &node);
9932				if (!dns_name_issubdomain(nextname, name)) {
9933					break;
9934				}
9935			} else {
9936				break;
9937			}
9938		} while (1);
9939		continue;
9940
9941	next_signing:
9942		dns_dbiterator_pause(signing->dbiterator);
9943		signing = nextsigning;
9944		first = true;
9945	}
9946
9947	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9948		result = dns__zone_updatesigs(&post_diff, db, version,
9949					      zone_keys, nkeys, zone, inception,
9950					      expire, 0, now, check_ksk,
9951					      keyset_kskonly, &zonediff);
9952		if (result != ISC_R_SUCCESS) {
9953			dnssec_log(zone, ISC_LOG_ERROR,
9954				   "zone_sign:dns__zone_updatesigs -> %s",
9955				   dns_result_totext(result));
9956			goto cleanup;
9957		}
9958	}
9959
9960	/*
9961	 * Have we changed anything?
9962	 */
9963	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9964		if (zonediff.offline) {
9965			commit = true;
9966		}
9967		result = ISC_R_SUCCESS;
9968		goto pauseall;
9969	}
9970
9971	commit = true;
9972
9973	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9974			  &zonediff, zone_keys, nkeys, now, false);
9975	if (result != ISC_R_SUCCESS) {
9976		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9977			   dns_result_totext(result));
9978		goto cleanup;
9979	}
9980
9981	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9982				   zone->updatemethod);
9983	if (result != ISC_R_SUCCESS) {
9984		dnssec_log(zone, ISC_LOG_ERROR,
9985			   "zone_sign:update_soa_serial -> %s",
9986			   dns_result_totext(result));
9987		goto cleanup;
9988	}
9989
9990	/*
9991	 * Generate maximum life time signatures so that the above loop
9992	 * termination is sensible.
9993	 */
9994	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9995			  zonediff.diff, zone_keys, nkeys, zone->mctx,
9996			  inception, soaexpire, check_ksk, keyset_kskonly);
9997	if (result != ISC_R_SUCCESS) {
9998		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
9999			   dns_result_totext(result));
10000		goto cleanup;
10001	}
10002
10003	/*
10004	 * Write changes to journal file.
10005	 */
10006	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
10007
10008pauseall:
10009	/*
10010	 * Pause all iterators so that dns_db_closeversion() can succeed.
10011	 */
10012	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10013	     signing = ISC_LIST_NEXT(signing, link))
10014	{
10015		dns_dbiterator_pause(signing->dbiterator);
10016	}
10017
10018	for (signing = ISC_LIST_HEAD(cleanup); signing != NULL;
10019	     signing = ISC_LIST_NEXT(signing, link))
10020	{
10021		dns_dbiterator_pause(signing->dbiterator);
10022	}
10023
10024	/*
10025	 * Everything has succeeded. Commit the changes.
10026	 */
10027	dns_db_closeversion(db, &version, commit);
10028
10029	/*
10030	 * Everything succeeded so we can clean these up now.
10031	 */
10032	signing = ISC_LIST_HEAD(cleanup);
10033	while (signing != NULL) {
10034		ISC_LIST_UNLINK(cleanup, signing, link);
10035		dns_db_detach(&signing->db);
10036		dns_dbiterator_destroy(&signing->dbiterator);
10037		isc_mem_put(zone->mctx, signing, sizeof *signing);
10038		signing = ISC_LIST_HEAD(cleanup);
10039	}
10040
10041	LOCK_ZONE(zone);
10042	set_resigntime(zone);
10043	if (commit) {
10044		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10045		zone_needdump(zone, DNS_DUMP_DELAY);
10046	}
10047	UNLOCK_ZONE(zone);
10048
10049failure:
10050	if (result != ISC_R_SUCCESS) {
10051		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
10052			   dns_result_totext(result));
10053	}
10054
10055cleanup:
10056	/*
10057	 * Pause all dbiterators.
10058	 */
10059	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10060	     signing = ISC_LIST_NEXT(signing, link))
10061	{
10062		dns_dbiterator_pause(signing->dbiterator);
10063	}
10064
10065	/*
10066	 * Rollback the cleanup list.
10067	 */
10068	signing = ISC_LIST_HEAD(cleanup);
10069	while (signing != NULL) {
10070		ISC_LIST_UNLINK(cleanup, signing, link);
10071		ISC_LIST_PREPEND(zone->signing, signing, link);
10072		dns_dbiterator_first(signing->dbiterator);
10073		dns_dbiterator_pause(signing->dbiterator);
10074		signing = ISC_LIST_HEAD(cleanup);
10075	}
10076
10077	dns_diff_clear(&_sig_diff);
10078
10079	for (i = 0; i < nkeys; i++) {
10080		dst_key_free(&zone_keys[i]);
10081	}
10082
10083	if (node != NULL) {
10084		dns_db_detachnode(db, &node);
10085	}
10086
10087	if (version != NULL) {
10088		dns_db_closeversion(db, &version, false);
10089		dns_db_detach(&db);
10090	} else if (db != NULL) {
10091		dns_db_detach(&db);
10092	}
10093
10094	LOCK_ZONE(zone);
10095	if (ISC_LIST_HEAD(zone->signing) != NULL) {
10096		isc_interval_t interval;
10097		if (zone->update_disabled || result != ISC_R_SUCCESS) {
10098			isc_interval_set(&interval, 60, 0); /* 1 minute */
10099		} else {
10100			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
10101		}
10102		isc_time_nowplusinterval(&zone->signingtime, &interval);
10103	} else {
10104		isc_time_settoepoch(&zone->signingtime);
10105	}
10106	UNLOCK_ZONE(zone);
10107
10108	INSIST(version == NULL);
10109}
10110
10111static isc_result_t
10112normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data,
10113	      int size) {
10114	dns_rdata_dnskey_t dnskey;
10115	dns_rdata_keydata_t keydata;
10116	isc_buffer_t buf;
10117	isc_result_t result;
10118
10119	dns_rdata_reset(target);
10120	isc_buffer_init(&buf, data, size);
10121
10122	switch (rr->type) {
10123	case dns_rdatatype_dnskey:
10124		result = dns_rdata_tostruct(rr, &dnskey, NULL);
10125		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10126		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
10127		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10128				     &dnskey, &buf);
10129		break;
10130	case dns_rdatatype_keydata:
10131		result = dns_rdata_tostruct(rr, &keydata, NULL);
10132		if (result == ISC_R_UNEXPECTEDEND) {
10133			return (result);
10134		}
10135		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10136		dns_keydata_todnskey(&keydata, &dnskey, NULL);
10137		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10138				     &dnskey, &buf);
10139		break;
10140	default:
10141		UNREACHABLE();
10142	}
10143	return (ISC_R_SUCCESS);
10144}
10145
10146/*
10147 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
10148 * a KEYDATA rdataset from the key zone.
10149 *
10150 * 'rr' contains either a DNSKEY record, or a KEYDATA record
10151 *
10152 * After normalizing keys to the same format (DNSKEY, with revoke bit
10153 * cleared), return true if a key that matches 'rr' is found in
10154 * 'rdset', or false if not.
10155 */
10156
10157static bool
10158matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
10159	unsigned char data1[4096], data2[4096];
10160	dns_rdata_t rdata, rdata1, rdata2;
10161	isc_result_t result;
10162
10163	dns_rdata_init(&rdata);
10164	dns_rdata_init(&rdata1);
10165	dns_rdata_init(&rdata2);
10166
10167	result = normalize_key(rr, &rdata1, data1, sizeof(data1));
10168	if (result != ISC_R_SUCCESS) {
10169		return (false);
10170	}
10171
10172	for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS;
10173	     result = dns_rdataset_next(rdset))
10174	{
10175		dns_rdata_reset(&rdata);
10176		dns_rdataset_current(rdset, &rdata);
10177		result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
10178		if (result != ISC_R_SUCCESS) {
10179			continue;
10180		}
10181		if (dns_rdata_compare(&rdata1, &rdata2) == 0) {
10182			return (true);
10183		}
10184	}
10185
10186	return (false);
10187}
10188
10189/*
10190 * Calculate the refresh interval for a keydata zone, per
10191 * RFC5011: MAX(1 hr,
10192 *		MIN(15 days,
10193 *		    1/2 * OrigTTL,
10194 *		    1/2 * RRSigExpirationInterval))
10195 * or for retries: MAX(1 hr,
10196 *		       MIN(1 day,
10197 *			   1/10 * OrigTTL,
10198 *			   1/10 * RRSigExpirationInterval))
10199 */
10200static isc_stdtime_t
10201refresh_time(dns_keyfetch_t *kfetch, bool retry) {
10202	isc_result_t result;
10203	uint32_t t;
10204	dns_rdataset_t *rdset;
10205	dns_rdata_t sigrr = DNS_RDATA_INIT;
10206	dns_rdata_sig_t sig;
10207	isc_stdtime_t now;
10208
10209	isc_stdtime_get(&now);
10210
10211	if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
10212		rdset = &kfetch->dnskeysigset;
10213	} else {
10214		return (now + dns_zone_mkey_hour);
10215	}
10216
10217	result = dns_rdataset_first(rdset);
10218	if (result != ISC_R_SUCCESS) {
10219		return (now + dns_zone_mkey_hour);
10220	}
10221
10222	dns_rdataset_current(rdset, &sigrr);
10223	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10224	RUNTIME_CHECK(result == ISC_R_SUCCESS);
10225
10226	if (!retry) {
10227		t = sig.originalttl / 2;
10228
10229		if (isc_serial_gt(sig.timeexpire, now)) {
10230			uint32_t exp = (sig.timeexpire - now) / 2;
10231			if (t > exp) {
10232				t = exp;
10233			}
10234		}
10235
10236		if (t > (15 * dns_zone_mkey_day)) {
10237			t = (15 * dns_zone_mkey_day);
10238		}
10239
10240		if (t < dns_zone_mkey_hour) {
10241			t = dns_zone_mkey_hour;
10242		}
10243	} else {
10244		t = sig.originalttl / 10;
10245
10246		if (isc_serial_gt(sig.timeexpire, now)) {
10247			uint32_t exp = (sig.timeexpire - now) / 10;
10248			if (t > exp) {
10249				t = exp;
10250			}
10251		}
10252
10253		if (t > dns_zone_mkey_day) {
10254			t = dns_zone_mkey_day;
10255		}
10256
10257		if (t < dns_zone_mkey_hour) {
10258			t = dns_zone_mkey_hour;
10259		}
10260	}
10261
10262	return (now + t);
10263}
10264
10265/*
10266 * This routine is called when no changes are needed in a KEYDATA
10267 * record except to simply update the refresh timer.  Caller should
10268 * hold zone lock.
10269 */
10270static isc_result_t
10271minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
10272	isc_result_t result;
10273	isc_buffer_t keyb;
10274	unsigned char key_buf[4096];
10275	dns_rdata_t rdata = DNS_RDATA_INIT;
10276	dns_rdata_keydata_t keydata;
10277	dns_name_t *name;
10278	dns_zone_t *zone = kfetch->zone;
10279	isc_stdtime_t now;
10280
10281	name = dns_fixedname_name(&kfetch->name);
10282	isc_stdtime_get(&now);
10283
10284	for (result = dns_rdataset_first(&kfetch->keydataset);
10285	     result == ISC_R_SUCCESS;
10286	     result = dns_rdataset_next(&kfetch->keydataset))
10287	{
10288		dns_rdata_reset(&rdata);
10289		dns_rdataset_current(&kfetch->keydataset, &rdata);
10290
10291		/* Delete old version */
10292		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, name,
10293				    0, &rdata));
10294
10295		/* Update refresh timer */
10296		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
10297		if (result == ISC_R_UNEXPECTEDEND) {
10298			continue;
10299		}
10300		if (result != ISC_R_SUCCESS) {
10301			goto failure;
10302		}
10303		keydata.refresh = refresh_time(kfetch, true);
10304		set_refreshkeytimer(zone, &keydata, now, false);
10305
10306		dns_rdata_reset(&rdata);
10307		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10308		CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
10309					   dns_rdatatype_keydata, &keydata,
10310					   &keyb));
10311
10312		/* Insert updated version */
10313		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, name,
10314				    0, &rdata));
10315	}
10316	result = ISC_R_SUCCESS;
10317failure:
10318	return (result);
10319}
10320
10321/*
10322 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
10323 */
10324static bool
10325revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
10326	isc_result_t result;
10327	dns_name_t *keyname;
10328	isc_mem_t *mctx;
10329	dns_rdata_t sigrr = DNS_RDATA_INIT;
10330	dns_rdata_t rr = DNS_RDATA_INIT;
10331	dns_rdata_rrsig_t sig;
10332	dns_rdata_dnskey_t dnskey;
10333	dst_key_t *dstkey = NULL;
10334	unsigned char key_buf[4096];
10335	isc_buffer_t keyb;
10336	bool answer = false;
10337
10338	REQUIRE(kfetch != NULL && keydata != NULL);
10339	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
10340
10341	keyname = dns_fixedname_name(&kfetch->name);
10342	mctx = kfetch->zone->view->mctx;
10343
10344	/* Generate a key from keydata */
10345	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10346	dns_keydata_todnskey(keydata, &dnskey, NULL);
10347	dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
10348			     &dnskey, &keyb);
10349	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
10350	if (result != ISC_R_SUCCESS) {
10351		return (false);
10352	}
10353
10354	/* See if that key generated any of the signatures */
10355	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
10356	     result == ISC_R_SUCCESS;
10357	     result = dns_rdataset_next(&kfetch->dnskeysigset))
10358	{
10359		dns_fixedname_t fixed;
10360		dns_fixedname_init(&fixed);
10361
10362		dns_rdata_reset(&sigrr);
10363		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
10364		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10365		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10366
10367		if (dst_key_alg(dstkey) == sig.algorithm &&
10368		    dst_key_rid(dstkey) == sig.keyid)
10369		{
10370			result = dns_dnssec_verify(
10371				keyname, &kfetch->dnskeyset, dstkey, false, 0,
10372				mctx, &sigrr, dns_fixedname_name(&fixed));
10373
10374			dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
10375				   "Confirm revoked DNSKEY is self-signed: %s",
10376				   dns_result_totext(result));
10377
10378			if (result == ISC_R_SUCCESS) {
10379				answer = true;
10380				break;
10381			}
10382		}
10383	}
10384
10385	dst_key_free(&dstkey);
10386	return (answer);
10387}
10388
10389/*
10390 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
10391 * anchors are being managed; scan the keyset, and update the key zone and the
10392 * local trust anchors according to RFC5011.
10393 */
10394static void
10395keyfetch_done(isc_task_t *task, isc_event_t *event) {
10396	isc_result_t result, eresult;
10397	dns_fetchevent_t *devent;
10398	dns_keyfetch_t *kfetch;
10399	dns_zone_t *zone;
10400	isc_mem_t *mctx = NULL;
10401	dns_keytable_t *secroots = NULL;
10402	dns_dbversion_t *ver = NULL;
10403	dns_diff_t diff;
10404	bool alldone = false;
10405	bool commit = false;
10406	dns_name_t *keyname = NULL;
10407	dns_rdata_t sigrr = DNS_RDATA_INIT;
10408	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
10409	dns_rdata_t keydatarr = DNS_RDATA_INIT;
10410	dns_rdata_rrsig_t sig;
10411	dns_rdata_dnskey_t dnskey;
10412	dns_rdata_keydata_t keydata;
10413	bool initializing;
10414	char namebuf[DNS_NAME_FORMATSIZE];
10415	unsigned char key_buf[4096];
10416	isc_buffer_t keyb;
10417	dst_key_t *dstkey = NULL;
10418	isc_stdtime_t now;
10419	int pending = 0;
10420	bool secure = false, initial = false;
10421	bool free_needed;
10422	dns_keynode_t *keynode = NULL;
10423	dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
10424	dns_rdataset_t *keydataset = NULL, dsset;
10425
10426	UNUSED(task);
10427	INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
10428	INSIST(event->ev_arg != NULL);
10429
10430	kfetch = event->ev_arg;
10431	zone = kfetch->zone;
10432	mctx = kfetch->mctx;
10433	keyname = dns_fixedname_name(&kfetch->name);
10434	dnskeys = &kfetch->dnskeyset;
10435	dnskeysigs = &kfetch->dnskeysigset;
10436	keydataset = &kfetch->keydataset;
10437
10438	devent = (dns_fetchevent_t *)event;
10439	eresult = devent->result;
10440
10441	/* Free resources which are not of interest */
10442	if (devent->node != NULL) {
10443		dns_db_detachnode(devent->db, &devent->node);
10444	}
10445	if (devent->db != NULL) {
10446		dns_db_detach(&devent->db);
10447	}
10448	isc_event_free(&event);
10449	dns_resolver_destroyfetch(&kfetch->fetch);
10450
10451	LOCK_ZONE(zone);
10452	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
10453		goto cleanup;
10454	}
10455
10456	isc_stdtime_get(&now);
10457	dns_name_format(keyname, namebuf, sizeof(namebuf));
10458
10459	result = dns_view_getsecroots(zone->view, &secroots);
10460	INSIST(result == ISC_R_SUCCESS);
10461
10462	dns_diff_init(mctx, &diff);
10463
10464	CHECK(dns_db_newversion(kfetch->db, &ver));
10465
10466	zone->refreshkeycount--;
10467	alldone = (zone->refreshkeycount == 0);
10468
10469	if (alldone) {
10470		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10471	}
10472
10473	dnssec_log(zone, ISC_LOG_DEBUG(3),
10474		   "Returned from key fetch in keyfetch_done() for '%s': %s",
10475		   namebuf, dns_result_totext(eresult));
10476
10477	/* Fetch failed */
10478	if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
10479		dnssec_log(zone, ISC_LOG_WARNING,
10480			   "Unable to fetch DNSKEY set '%s': %s", namebuf,
10481			   dns_result_totext(eresult));
10482		CHECK(minimal_update(kfetch, ver, &diff));
10483		goto done;
10484	}
10485
10486	/* No RRSIGs found */
10487	if (!dns_rdataset_isassociated(dnskeysigs)) {
10488		dnssec_log(zone, ISC_LOG_WARNING,
10489			   "No DNSKEY RRSIGs found for '%s': %s", namebuf,
10490			   dns_result_totext(eresult));
10491		CHECK(minimal_update(kfetch, ver, &diff));
10492		goto done;
10493	}
10494
10495	/*
10496	 * Clear any cached trust level, as we need to run validation
10497	 * over again; trusted keys might have changed.
10498	 */
10499	dnskeys->trust = dnskeysigs->trust = dns_trust_none;
10500
10501	/* Look up the trust anchor */
10502	result = dns_keytable_find(secroots, keyname, &keynode);
10503	if (result != ISC_R_SUCCESS) {
10504		goto anchors_done;
10505	}
10506
10507	/*
10508	 * If the keynode has a DS trust anchor, use it for verification.
10509	 */
10510	dns_rdataset_init(&dsset);
10511	if (dns_keynode_dsset(keynode, &dsset)) {
10512		for (result = dns_rdataset_first(dnskeysigs);
10513		     result == ISC_R_SUCCESS;
10514		     result = dns_rdataset_next(dnskeysigs))
10515		{
10516			isc_result_t tresult;
10517			dns_rdata_t keyrdata = DNS_RDATA_INIT;
10518
10519			dns_rdata_reset(&sigrr);
10520			dns_rdataset_current(dnskeysigs, &sigrr);
10521			result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10522			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10523
10524			for (tresult = dns_rdataset_first(&dsset);
10525			     tresult == ISC_R_SUCCESS;
10526			     tresult = dns_rdataset_next(&dsset))
10527			{
10528				dns_rdata_t dsrdata = DNS_RDATA_INIT;
10529				dns_rdata_ds_t ds;
10530
10531				dns_rdata_reset(&dsrdata);
10532				dns_rdataset_current(&dsset, &dsrdata);
10533				tresult = dns_rdata_tostruct(&dsrdata, &ds,
10534							     NULL);
10535				RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
10536
10537				if (ds.key_tag != sig.keyid ||
10538				    ds.algorithm != sig.algorithm)
10539				{
10540					continue;
10541				}
10542
10543				result = dns_dnssec_matchdskey(
10544					keyname, &dsrdata, dnskeys, &keyrdata);
10545				if (result == ISC_R_SUCCESS) {
10546					break;
10547				}
10548			}
10549
10550			if (tresult == ISC_R_NOMORE) {
10551				continue;
10552			}
10553
10554			result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
10555							 mctx, &dstkey);
10556			if (result != ISC_R_SUCCESS) {
10557				continue;
10558			}
10559
10560			result = dns_dnssec_verify(keyname, dnskeys, dstkey,
10561						   false, 0, mctx, &sigrr,
10562						   NULL);
10563			dst_key_free(&dstkey);
10564
10565			dnssec_log(zone, ISC_LOG_DEBUG(3),
10566				   "Verifying DNSKEY set for zone "
10567				   "'%s' using DS %d/%d: %s",
10568				   namebuf, sig.keyid, sig.algorithm,
10569				   dns_result_totext(result));
10570
10571			if (result == ISC_R_SUCCESS) {
10572				dnskeys->trust = dns_trust_secure;
10573				dnskeysigs->trust = dns_trust_secure;
10574				initial = dns_keynode_initial(keynode);
10575				dns_keynode_trust(keynode);
10576				secure = true;
10577				break;
10578			}
10579		}
10580		dns_rdataset_disassociate(&dsset);
10581	}
10582
10583anchors_done:
10584	if (keynode != NULL) {
10585		dns_keytable_detachkeynode(secroots, &keynode);
10586	}
10587
10588	/*
10589	 * If we were not able to verify the answer using the current
10590	 * trusted keys then all we can do is look at any revoked keys.
10591	 */
10592	if (!secure) {
10593		dnssec_log(zone, ISC_LOG_INFO,
10594			   "DNSKEY set for zone '%s' could not be verified "
10595			   "with current keys",
10596			   namebuf);
10597	}
10598
10599	/*
10600	 * First scan keydataset to find keys that are not in dnskeyset
10601	 *   - Missing keys which are not scheduled for removal,
10602	 *     log a warning
10603	 *   - Missing keys which are scheduled for removal and
10604	 *     the remove hold-down timer has completed should
10605	 *     be removed from the key zone
10606	 *   - Missing keys whose acceptance timers have not yet
10607	 *     completed, log a warning and reset the acceptance
10608	 *     timer to 30 days in the future
10609	 *   - All keys not being removed have their refresh timers
10610	 *     updated
10611	 */
10612	initializing = true;
10613	for (result = dns_rdataset_first(keydataset); result == ISC_R_SUCCESS;
10614	     result = dns_rdataset_next(keydataset))
10615	{
10616		dns_keytag_t keytag;
10617
10618		dns_rdata_reset(&keydatarr);
10619		dns_rdataset_current(keydataset, &keydatarr);
10620		result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10621		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10622
10623		dns_keydata_todnskey(&keydata, &dnskey, NULL);
10624		result = compute_tag(keyname, &dnskey, mctx, &keytag);
10625		if (result != ISC_R_SUCCESS) {
10626			/*
10627			 * Skip if we cannot compute the key tag.
10628			 * This may happen if the algorithm is unsupported
10629			 */
10630			dns_zone_log(zone, ISC_LOG_ERROR,
10631				     "Cannot compute tag for key in zone %s: "
10632				     "%s "
10633				     "(skipping)",
10634				     namebuf, dns_result_totext(result));
10635			continue;
10636		}
10637		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10638
10639		/*
10640		 * If any keydata record has a nonzero add holddown, then
10641		 * there was a pre-existing trust anchor for this domain;
10642		 * that means we are *not* initializing it and shouldn't
10643		 * automatically trust all the keys we find at the zone apex.
10644		 */
10645		initializing = initializing && (keydata.addhd == 0);
10646
10647		if (!matchkey(dnskeys, &keydatarr)) {
10648			bool deletekey = false;
10649
10650			if (!secure) {
10651				if (keydata.removehd != 0 &&
10652				    keydata.removehd <= now)
10653				{
10654					deletekey = true;
10655				}
10656			} else if (keydata.addhd == 0) {
10657				deletekey = true;
10658			} else if (keydata.addhd > now) {
10659				dnssec_log(zone, ISC_LOG_INFO,
10660					   "Pending key %d for zone %s "
10661					   "unexpectedly missing "
10662					   "restarting 30-day acceptance "
10663					   "timer",
10664					   keytag, namebuf);
10665				if (keydata.addhd < now + dns_zone_mkey_month) {
10666					keydata.addhd = now +
10667							dns_zone_mkey_month;
10668				}
10669				keydata.refresh = refresh_time(kfetch, false);
10670			} else if (keydata.removehd == 0) {
10671				dnssec_log(zone, ISC_LOG_INFO,
10672					   "Active key %d for zone %s "
10673					   "unexpectedly missing",
10674					   keytag, namebuf);
10675				keydata.refresh = now + dns_zone_mkey_hour;
10676			} else if (keydata.removehd <= now) {
10677				deletekey = true;
10678				dnssec_log(zone, ISC_LOG_INFO,
10679					   "Revoked key %d for zone %s "
10680					   "missing: deleting from "
10681					   "managed keys database",
10682					   keytag, namebuf);
10683			} else {
10684				keydata.refresh = refresh_time(kfetch, false);
10685			}
10686
10687			if (secure || deletekey) {
10688				/* Delete old version */
10689				CHECK(update_one_rr(kfetch->db, ver, &diff,
10690						    DNS_DIFFOP_DEL, keyname, 0,
10691						    &keydatarr));
10692			}
10693
10694			if (!secure || deletekey) {
10695				continue;
10696			}
10697
10698			dns_rdata_reset(&keydatarr);
10699			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10700			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10701					     dns_rdatatype_keydata, &keydata,
10702					     &keyb);
10703
10704			/* Insert updated version */
10705			CHECK(update_one_rr(kfetch->db, ver, &diff,
10706					    DNS_DIFFOP_ADD, keyname, 0,
10707					    &keydatarr));
10708
10709			set_refreshkeytimer(zone, &keydata, now, false);
10710		}
10711	}
10712
10713	/*
10714	 * Next scan dnskeyset:
10715	 *   - If new keys are found (i.e., lacking a match in keydataset)
10716	 *     add them to the key zone and set the acceptance timer
10717	 *     to 30 days in the future (or to immediately if we've
10718	 *     determined that we're initializing the zone for the
10719	 *     first time)
10720	 *   - Previously-known keys that have been revoked
10721	 *     must be scheduled for removal from the key zone (or,
10722	 *     if they hadn't been accepted as trust anchors yet
10723	 *     anyway, removed at once)
10724	 *   - Previously-known unrevoked keys whose acceptance timers
10725	 *     have completed are promoted to trust anchors
10726	 *   - All keys not being removed have their refresh
10727	 *     timers updated
10728	 */
10729	for (result = dns_rdataset_first(dnskeys); result == ISC_R_SUCCESS;
10730	     result = dns_rdataset_next(dnskeys))
10731	{
10732		bool revoked = false;
10733		bool newkey = false;
10734		bool updatekey = false;
10735		bool deletekey = false;
10736		bool trustkey = false;
10737		dns_keytag_t keytag;
10738
10739		dns_rdata_reset(&dnskeyrr);
10740		dns_rdataset_current(dnskeys, &dnskeyrr);
10741		result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10742		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10743
10744		/* Skip ZSK's */
10745		if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
10746			continue;
10747		}
10748
10749		result = compute_tag(keyname, &dnskey, mctx, &keytag);
10750		if (result != ISC_R_SUCCESS) {
10751			/*
10752			 * Skip if we cannot compute the key tag.
10753			 * This may happen if the algorithm is unsupported
10754			 */
10755			dns_zone_log(zone, ISC_LOG_ERROR,
10756				     "Cannot compute tag for key in zone %s: "
10757				     "%s "
10758				     "(skipping)",
10759				     namebuf, dns_result_totext(result));
10760			continue;
10761		}
10762		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10763
10764		revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
10765
10766		if (matchkey(keydataset, &dnskeyrr)) {
10767			dns_rdata_reset(&keydatarr);
10768			dns_rdataset_current(keydataset, &keydatarr);
10769			result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10770			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10771
10772			if (revoked && revocable(kfetch, &keydata)) {
10773				if (keydata.addhd > now) {
10774					/*
10775					 * Key wasn't trusted yet, and now
10776					 * it's been revoked?  Just remove it
10777					 */
10778					deletekey = true;
10779					dnssec_log(zone, ISC_LOG_INFO,
10780						   "Pending key %d for "
10781						   "zone %s is now revoked: "
10782						   "deleting from the "
10783						   "managed keys database",
10784						   keytag, namebuf);
10785				} else if (keydata.removehd == 0) {
10786					/*
10787					 * Remove key from secroots.
10788					 */
10789					dns_view_untrust(zone->view, keyname,
10790							 &dnskey);
10791
10792					/* If initializing, delete now */
10793					if (keydata.addhd == 0) {
10794						deletekey = true;
10795					} else {
10796						keydata.removehd =
10797							now +
10798							dns_zone_mkey_month;
10799						keydata.flags |=
10800							DNS_KEYFLAG_REVOKE;
10801					}
10802
10803					dnssec_log(zone, ISC_LOG_INFO,
10804						   "Trusted key %d for "
10805						   "zone %s is now revoked",
10806						   keytag, namebuf);
10807				} else if (keydata.removehd < now) {
10808					/* Scheduled for removal */
10809					deletekey = true;
10810
10811					dnssec_log(zone, ISC_LOG_INFO,
10812						   "Revoked key %d for "
10813						   "zone %s removal timer "
10814						   "complete: deleting from "
10815						   "the managed keys database",
10816						   keytag, namebuf);
10817				}
10818			} else if (revoked && keydata.removehd == 0) {
10819				dnssec_log(zone, ISC_LOG_WARNING,
10820					   "Active key %d for zone "
10821					   "%s is revoked but "
10822					   "did not self-sign; "
10823					   "ignoring",
10824					   keytag, namebuf);
10825				continue;
10826			} else if (secure) {
10827				if (keydata.removehd != 0) {
10828					/*
10829					 * Key isn't revoked--but it
10830					 * seems it used to be.
10831					 * Remove it now and add it
10832					 * back as if it were a fresh key,
10833					 * with a 30-day acceptance timer.
10834					 */
10835					deletekey = true;
10836					newkey = true;
10837					keydata.removehd = 0;
10838					keydata.addhd = now +
10839							dns_zone_mkey_month;
10840
10841					dnssec_log(zone, ISC_LOG_INFO,
10842						   "Revoked key %d for "
10843						   "zone %s has returned: "
10844						   "starting 30-day "
10845						   "acceptance timer",
10846						   keytag, namebuf);
10847				} else if (keydata.addhd > now) {
10848					pending++;
10849				} else if (keydata.addhd == 0) {
10850					keydata.addhd = now;
10851				}
10852
10853				if (keydata.addhd <= now) {
10854					trustkey = true;
10855					dnssec_log(zone, ISC_LOG_INFO,
10856						   "Key %d for zone %s "
10857						   "is now trusted (%s)",
10858						   keytag, namebuf,
10859						   initial ? "initializing key "
10860							     "verified"
10861							   : "acceptance timer "
10862							     "complete");
10863				}
10864			} else if (keydata.addhd > now) {
10865				/*
10866				 * Not secure, and key is pending:
10867				 * reset the acceptance timer
10868				 */
10869				pending++;
10870				keydata.addhd = now + dns_zone_mkey_month;
10871				dnssec_log(zone, ISC_LOG_INFO,
10872					   "Pending key %d "
10873					   "for zone %s was "
10874					   "not validated: restarting "
10875					   "30-day acceptance timer",
10876					   keytag, namebuf);
10877			}
10878
10879			if (!deletekey && !newkey) {
10880				updatekey = true;
10881			}
10882		} else if (secure) {
10883			/*
10884			 * Key wasn't in the key zone but it's
10885			 * revoked now anyway, so just skip it
10886			 */
10887			if (revoked) {
10888				continue;
10889			}
10890
10891			/* Key wasn't in the key zone: add it */
10892			newkey = true;
10893
10894			if (initializing) {
10895				dnssec_log(zone, ISC_LOG_WARNING,
10896					   "Initializing automatic trust "
10897					   "anchor management for zone '%s'; "
10898					   "DNSKEY ID %d is now trusted, "
10899					   "waiving the normal 30-day "
10900					   "waiting period.",
10901					   namebuf, keytag);
10902				trustkey = true;
10903			} else {
10904				dnssec_log(zone, ISC_LOG_INFO,
10905					   "New key %d observed "
10906					   "for zone '%s': "
10907					   "starting 30-day "
10908					   "acceptance timer",
10909					   keytag, namebuf);
10910			}
10911		} else {
10912			/*
10913			 * No previously known key, and the key is not
10914			 * secure, so skip it.
10915			 */
10916			continue;
10917		}
10918
10919		/* Delete old version */
10920		if (deletekey || !newkey) {
10921			CHECK(update_one_rr(kfetch->db, ver, &diff,
10922					    DNS_DIFFOP_DEL, keyname, 0,
10923					    &keydatarr));
10924		}
10925
10926		if (updatekey) {
10927			/* Set refresh timer */
10928			keydata.refresh = refresh_time(kfetch, false);
10929			dns_rdata_reset(&keydatarr);
10930			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10931			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10932					     dns_rdatatype_keydata, &keydata,
10933					     &keyb);
10934
10935			/* Insert updated version */
10936			CHECK(update_one_rr(kfetch->db, ver, &diff,
10937					    DNS_DIFFOP_ADD, keyname, 0,
10938					    &keydatarr));
10939		} else if (newkey) {
10940			/* Convert DNSKEY to KEYDATA */
10941			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10942			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10943			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
10944					       NULL);
10945			keydata.addhd = initializing
10946						? now
10947						: now + dns_zone_mkey_month;
10948			keydata.refresh = refresh_time(kfetch, false);
10949			dns_rdata_reset(&keydatarr);
10950			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10951			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10952					     dns_rdatatype_keydata, &keydata,
10953					     &keyb);
10954
10955			/* Insert into key zone */
10956			CHECK(update_one_rr(kfetch->db, ver, &diff,
10957					    DNS_DIFFOP_ADD, keyname, 0,
10958					    &keydatarr));
10959		}
10960
10961		if (trustkey) {
10962			/* Trust this key. */
10963			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10964			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10965			trust_key(zone, keyname, &dnskey, false);
10966		}
10967
10968		if (secure && !deletekey) {
10969			INSIST(newkey || updatekey);
10970			set_refreshkeytimer(zone, &keydata, now, false);
10971		}
10972	}
10973
10974	/*
10975	 * RFC5011 says, "A trust point that has all of its trust anchors
10976	 * revoked is considered deleted and is treated as if the trust
10977	 * point was never configured."  But if someone revoked their
10978	 * active key before the standby was trusted, that would mean the
10979	 * zone would suddenly be nonsecured.  We avoid this by checking to
10980	 * see if there's pending keydata.  If so, we put a null key in
10981	 * the security roots; then all queries to the zone will fail.
10982	 */
10983	if (pending != 0) {
10984		fail_secure(zone, keyname);
10985	}
10986
10987done:
10988	if (!ISC_LIST_EMPTY(diff.tuples)) {
10989		/* Write changes to journal file. */
10990		CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
10991					zone->updatemethod));
10992		CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10993		commit = true;
10994
10995		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10996		zone_needdump(zone, 30);
10997	} else if (result == ISC_R_NOMORE) {
10998		/*
10999		 * If "updatekey" was true for all keys found in the DNSKEY
11000		 * response and the previous update of those keys happened
11001		 * during the same second (only possible if a key refresh was
11002		 * externally triggered), it may happen that all relevant
11003		 * update_one_rr() calls will return ISC_R_SUCCESS, but
11004		 * diff.tuples will remain empty.  Reset result to
11005		 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
11006		 */
11007		result = ISC_R_SUCCESS;
11008	}
11009
11010failure:
11011	if (result != ISC_R_SUCCESS) {
11012		dnssec_log(zone, ISC_LOG_ERROR,
11013			   "error during managed-keys processing (%s): "
11014			   "DNSSEC validation may be at risk",
11015			   isc_result_totext(result));
11016	}
11017	dns_diff_clear(&diff);
11018	if (ver != NULL) {
11019		dns_db_closeversion(kfetch->db, &ver, commit);
11020	}
11021
11022cleanup:
11023	dns_db_detach(&kfetch->db);
11024
11025	/* The zone must be managed */
11026	INSIST(kfetch->zone->task != NULL);
11027	isc_refcount_decrement(&zone->irefs);
11028
11029	if (dns_rdataset_isassociated(keydataset)) {
11030		dns_rdataset_disassociate(keydataset);
11031	}
11032	if (dns_rdataset_isassociated(dnskeys)) {
11033		dns_rdataset_disassociate(dnskeys);
11034	}
11035	if (dns_rdataset_isassociated(dnskeysigs)) {
11036		dns_rdataset_disassociate(dnskeysigs);
11037	}
11038
11039	dns_name_free(keyname, mctx);
11040	isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(dns_keyfetch_t));
11041
11042	if (secroots != NULL) {
11043		dns_keytable_detach(&secroots);
11044	}
11045
11046	free_needed = exit_check(zone);
11047	UNLOCK_ZONE(zone);
11048
11049	if (free_needed) {
11050		zone_free(zone);
11051	}
11052
11053	INSIST(ver == NULL);
11054}
11055
11056static void
11057retry_keyfetch(dns_keyfetch_t *kfetch, dns_name_t *kname) {
11058	isc_time_t timenow, timethen;
11059	dns_zone_t *zone = kfetch->zone;
11060	bool free_needed;
11061	char namebuf[DNS_NAME_FORMATSIZE];
11062
11063	dns_name_format(kname, namebuf, sizeof(namebuf));
11064	dnssec_log(zone, ISC_LOG_WARNING,
11065		   "Failed to create fetch for %s DNSKEY update", namebuf);
11066
11067	/*
11068	 * Error during a key fetch; cancel and retry in an hour.
11069	 */
11070	LOCK_ZONE(zone);
11071	zone->refreshkeycount--;
11072	isc_refcount_decrement(&zone->irefs);
11073	dns_db_detach(&kfetch->db);
11074	dns_rdataset_disassociate(&kfetch->keydataset);
11075	dns_name_free(kname, zone->mctx);
11076	isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(*kfetch));
11077
11078	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11079		/* Don't really retry if we are exiting */
11080		char timebuf[80];
11081
11082		TIME_NOW(&timenow);
11083		DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
11084		zone->refreshkeytime = timethen;
11085		zone_settimer(zone, &timenow);
11086
11087		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
11088		dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
11089			   timebuf);
11090	}
11091
11092	free_needed = exit_check(zone);
11093	UNLOCK_ZONE(zone);
11094
11095	if (free_needed) {
11096		zone_free(zone);
11097	}
11098}
11099
11100static void
11101do_keyfetch(isc_task_t *task, isc_event_t *event) {
11102	isc_result_t result;
11103	dns_keyfetch_t *kfetch = (dns_keyfetch_t *)event->ev_arg;
11104	dns_name_t *kname = dns_fixedname_name(&kfetch->name);
11105	dns_zone_t *zone = kfetch->zone;
11106
11107	UNUSED(task);
11108
11109	isc_event_free(&event);
11110
11111	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11112		retry_keyfetch(kfetch, kname);
11113		return;
11114	}
11115
11116	/*
11117	 * Use of DNS_FETCHOPT_NOCACHED is essential here.  If it is not
11118	 * set and the cache still holds a non-expired, validated version
11119	 * of the RRset being queried for by the time the response is
11120	 * received, the cached RRset will be passed to keyfetch_done()
11121	 * instead of the one received in the response as the latter will
11122	 * have a lower trust level due to not being validated until
11123	 * keyfetch_done() is called.
11124	 */
11125	result = dns_resolver_createfetch(
11126		zone->view->resolver, kname, dns_rdatatype_dnskey, NULL, NULL,
11127		NULL, NULL, 0,
11128		DNS_FETCHOPT_NOVALIDATE | DNS_FETCHOPT_UNSHARED |
11129			DNS_FETCHOPT_NOCACHED,
11130		0, NULL, zone->task, keyfetch_done, kfetch, &kfetch->dnskeyset,
11131		&kfetch->dnskeysigset, &kfetch->fetch);
11132
11133	if (result != ISC_R_SUCCESS) {
11134		retry_keyfetch(kfetch, kname);
11135	}
11136}
11137
11138/*
11139 * Refresh the data in the key zone.  Initiate a fetch to look up
11140 * DNSKEY records at the trust anchor name.
11141 */
11142static void
11143zone_refreshkeys(dns_zone_t *zone) {
11144	const char me[] = "zone_refreshkeys";
11145	isc_result_t result;
11146	dns_rriterator_t rrit;
11147	dns_db_t *db = NULL;
11148	dns_dbversion_t *ver = NULL;
11149	dns_diff_t diff;
11150	dns_rdata_t rdata = DNS_RDATA_INIT;
11151	dns_rdata_keydata_t kd;
11152	isc_stdtime_t now;
11153	bool commit = false;
11154	bool fetching = false;
11155	bool timerset = false;
11156
11157	ENTER;
11158	REQUIRE(zone->db != NULL);
11159
11160	isc_stdtime_get(&now);
11161
11162	LOCK_ZONE(zone);
11163	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11164		isc_time_settoepoch(&zone->refreshkeytime);
11165		UNLOCK_ZONE(zone);
11166		return;
11167	}
11168
11169	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11170	dns_db_attach(zone->db, &db);
11171	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11172
11173	dns_diff_init(zone->mctx, &diff);
11174
11175	CHECK(dns_db_newversion(db, &ver));
11176
11177	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
11178
11179	dns_rriterator_init(&rrit, db, ver, 0);
11180	for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
11181	     result = dns_rriterator_nextrrset(&rrit))
11182	{
11183		isc_stdtime_t timer = 0xffffffff;
11184		dns_name_t *name = NULL, *kname = NULL;
11185		dns_rdataset_t *kdset = NULL;
11186		uint32_t ttl;
11187
11188		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
11189		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
11190		    !dns_rdataset_isassociated(kdset))
11191		{
11192			continue;
11193		}
11194
11195		/*
11196		 * Scan the stored keys looking for ones that need
11197		 * removal or refreshing
11198		 */
11199		for (result = dns_rdataset_first(kdset);
11200		     result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
11201		{
11202			dns_rdata_reset(&rdata);
11203			dns_rdataset_current(kdset, &rdata);
11204			result = dns_rdata_tostruct(&rdata, &kd, NULL);
11205			RUNTIME_CHECK(result == ISC_R_SUCCESS);
11206
11207			/* Removal timer expired? */
11208			if (kd.removehd != 0 && kd.removehd < now) {
11209				dns_rriterator_pause(&rrit);
11210				CHECK(update_one_rr(db, ver, &diff,
11211						    DNS_DIFFOP_DEL, name, ttl,
11212						    &rdata));
11213				continue;
11214			}
11215
11216			/* Acceptance timer expired? */
11217			if (kd.addhd <= now) {
11218				timer = kd.addhd;
11219			}
11220
11221			/* Or do we just need to refresh the keyset? */
11222			if (timer > kd.refresh) {
11223				timer = kd.refresh;
11224			}
11225
11226			dns_rriterator_pause(&rrit);
11227			set_refreshkeytimer(zone, &kd, now, false);
11228			timerset = true;
11229		}
11230
11231		if (timer > now) {
11232			continue;
11233		}
11234
11235		dns_rriterator_pause(&rrit);
11236
11237#ifdef ENABLE_AFL
11238		if (!dns_fuzzing_resolver) {
11239#endif /* ifdef ENABLE_AFL */
11240			dns_keyfetch_t *kfetch = NULL;
11241			isc_event_t *e;
11242
11243			kfetch = isc_mem_get(zone->mctx,
11244					     sizeof(dns_keyfetch_t));
11245			*kfetch = (dns_keyfetch_t){ .zone = zone };
11246			isc_mem_attach(zone->mctx, &kfetch->mctx);
11247
11248			zone->refreshkeycount++;
11249			isc_refcount_increment0(&zone->irefs);
11250			kname = dns_fixedname_initname(&kfetch->name);
11251			dns_name_dup(name, zone->mctx, kname);
11252			dns_rdataset_init(&kfetch->dnskeyset);
11253			dns_rdataset_init(&kfetch->dnskeysigset);
11254			dns_rdataset_init(&kfetch->keydataset);
11255			dns_rdataset_clone(kdset, &kfetch->keydataset);
11256			dns_db_attach(db, &kfetch->db);
11257
11258			if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
11259				char namebuf[DNS_NAME_FORMATSIZE];
11260				dns_name_format(kname, namebuf,
11261						sizeof(namebuf));
11262				dnssec_log(zone, ISC_LOG_DEBUG(3),
11263					   "Creating key fetch in "
11264					   "zone_refreshkeys() for '%s'",
11265					   namebuf);
11266			}
11267
11268			e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
11269					       do_keyfetch, kfetch,
11270					       sizeof(isc_event_t));
11271			isc_task_send(zone->task, &e);
11272			fetching = true;
11273#ifdef ENABLE_AFL
11274		}
11275#endif /* ifdef ENABLE_AFL */
11276	}
11277	if (!ISC_LIST_EMPTY(diff.tuples)) {
11278		CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
11279					zone->updatemethod));
11280		CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
11281		commit = true;
11282		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
11283		zone_needdump(zone, 30);
11284	}
11285
11286failure:
11287	if (!timerset) {
11288		isc_time_settoepoch(&zone->refreshkeytime);
11289	}
11290
11291	if (!fetching) {
11292		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
11293	}
11294
11295	dns_diff_clear(&diff);
11296	if (ver != NULL) {
11297		dns_rriterator_destroy(&rrit);
11298		dns_db_closeversion(db, &ver, commit);
11299	}
11300	dns_db_detach(&db);
11301
11302	UNLOCK_ZONE(zone);
11303
11304	INSIST(ver == NULL);
11305}
11306
11307static void
11308zone_maintenance(dns_zone_t *zone) {
11309	const char me[] = "zone_maintenance";
11310	isc_time_t now;
11311	isc_result_t result;
11312	bool dumping, load_pending, exiting, viewok;
11313	bool need_notify;
11314
11315	REQUIRE(DNS_ZONE_VALID(zone));
11316	ENTER;
11317
11318	/*
11319	 * Are we pending load/reload, exiting, or unconfigured
11320	 * (e.g. because of a syntax failure in the config file)?
11321	 * If so, don't attempt maintenance.
11322	 */
11323	LOCK_ZONE(zone);
11324	load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
11325	exiting = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING);
11326	viewok = (zone->view != NULL && zone->view->adb != NULL);
11327	UNLOCK_ZONE(zone);
11328
11329	if (load_pending || exiting || !viewok) {
11330		return;
11331	}
11332
11333	TIME_NOW(&now);
11334
11335	/*
11336	 * Expire check.
11337	 */
11338	switch (zone->type) {
11339	case dns_zone_redirect:
11340		if (zone->masters == NULL) {
11341			break;
11342		}
11343		FALLTHROUGH;
11344	case dns_zone_secondary:
11345	case dns_zone_mirror:
11346	case dns_zone_stub:
11347		LOCK_ZONE(zone);
11348		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
11349		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11350		{
11351			zone_expire(zone);
11352			zone->refreshtime = now;
11353		}
11354		UNLOCK_ZONE(zone);
11355		break;
11356	default:
11357		break;
11358	}
11359
11360	/*
11361	 * Up to date check.
11362	 */
11363	switch (zone->type) {
11364	case dns_zone_redirect:
11365		if (zone->masters == NULL) {
11366			break;
11367		}
11368		FALLTHROUGH;
11369	case dns_zone_secondary:
11370	case dns_zone_mirror:
11371	case dns_zone_stub:
11372		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
11373		    isc_time_compare(&now, &zone->refreshtime) >= 0)
11374		{
11375			dns_zone_refresh(zone);
11376		}
11377		break;
11378	default:
11379		break;
11380	}
11381
11382	/*
11383	 * Secondaries send notifies before backing up to disk,
11384	 * primaries after.
11385	 */
11386	LOCK_ZONE(zone);
11387	need_notify = (zone->type == dns_zone_secondary ||
11388		       zone->type == dns_zone_mirror) &&
11389		      (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11390		       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11391		      (isc_time_compare(&now, &zone->notifytime) >= 0);
11392	UNLOCK_ZONE(zone);
11393
11394	if (need_notify) {
11395		zone_notify(zone, &now);
11396	}
11397
11398	/*
11399	 * Do we need to consolidate the backing store?
11400	 */
11401	switch (zone->type) {
11402	case dns_zone_primary:
11403	case dns_zone_secondary:
11404	case dns_zone_mirror:
11405	case dns_zone_key:
11406	case dns_zone_redirect:
11407	case dns_zone_stub:
11408		LOCK_ZONE(zone);
11409		if (zone->masterfile != NULL &&
11410		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
11411		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11412		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
11413		{
11414			dumping = was_dumping(zone);
11415		} else {
11416			dumping = true;
11417		}
11418		UNLOCK_ZONE(zone);
11419		if (!dumping) {
11420			result = zone_dump(zone, true); /* task locked */
11421			if (result != ISC_R_SUCCESS) {
11422				dns_zone_log(zone, ISC_LOG_WARNING,
11423					     "dump failed: %s",
11424					     dns_result_totext(result));
11425			}
11426		}
11427		break;
11428	default:
11429		break;
11430	}
11431
11432	/*
11433	 * Master/redirect zones send notifies now, if needed
11434	 */
11435	switch (zone->type) {
11436	case dns_zone_primary:
11437	case dns_zone_redirect:
11438		if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11439		     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11440		    isc_time_compare(&now, &zone->notifytime) >= 0)
11441		{
11442			zone_notify(zone, &now);
11443		}
11444	default:
11445		break;
11446	}
11447
11448	/*
11449	 * Do we need to refresh keys?
11450	 */
11451	switch (zone->type) {
11452	case dns_zone_key:
11453		if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
11454			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11455			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
11456			{
11457				zone_refreshkeys(zone);
11458			}
11459		}
11460		break;
11461	case dns_zone_primary:
11462		if (!isc_time_isepoch(&zone->refreshkeytime) &&
11463		    isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
11464		    zone->rss_event == NULL)
11465		{
11466			zone_rekey(zone);
11467		}
11468	default:
11469		break;
11470	}
11471
11472	switch (zone->type) {
11473	case dns_zone_primary:
11474	case dns_zone_redirect:
11475	case dns_zone_secondary:
11476		/*
11477		 * Do we need to sign/resign some RRsets?
11478		 */
11479		if (zone->rss_event != NULL) {
11480			break;
11481		}
11482		if (!isc_time_isepoch(&zone->signingtime) &&
11483		    isc_time_compare(&now, &zone->signingtime) >= 0)
11484		{
11485			zone_sign(zone);
11486		} else if (!isc_time_isepoch(&zone->resigntime) &&
11487			   isc_time_compare(&now, &zone->resigntime) >= 0)
11488		{
11489			zone_resigninc(zone);
11490		} else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
11491			   isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
11492		{
11493			zone_nsec3chain(zone);
11494		}
11495		/*
11496		 * Do we need to issue a key expiry warning?
11497		 */
11498		if (!isc_time_isepoch(&zone->keywarntime) &&
11499		    isc_time_compare(&now, &zone->keywarntime) >= 0)
11500		{
11501			set_key_expiry_warning(zone, zone->key_expiry,
11502					       isc_time_seconds(&now));
11503		}
11504		break;
11505
11506	default:
11507		break;
11508	}
11509	LOCK_ZONE(zone);
11510	zone_settimer(zone, &now);
11511	UNLOCK_ZONE(zone);
11512}
11513
11514void
11515dns_zone_markdirty(dns_zone_t *zone) {
11516	uint32_t serial;
11517	isc_result_t result = ISC_R_SUCCESS;
11518	dns_zone_t *secure = NULL;
11519
11520	/*
11521	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
11522	 * could result in a deadlock due to a LOR so we will spin if we
11523	 * can't obtain the both locks.
11524	 */
11525again:
11526	LOCK_ZONE(zone);
11527	if (zone->type == dns_zone_primary) {
11528		if (inline_raw(zone)) {
11529			unsigned int soacount;
11530			secure = zone->secure;
11531			INSIST(secure != zone);
11532			TRYLOCK_ZONE(result, secure);
11533			if (result != ISC_R_SUCCESS) {
11534				UNLOCK_ZONE(zone);
11535				secure = NULL;
11536				isc_thread_yield();
11537				goto again;
11538			}
11539
11540			ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11541			if (zone->db != NULL) {
11542				result = zone_get_from_db(
11543					zone, zone->db, NULL, &soacount, NULL,
11544					&serial, NULL, NULL, NULL, NULL, NULL);
11545			} else {
11546				result = DNS_R_NOTLOADED;
11547			}
11548			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11549			if (result == ISC_R_SUCCESS && soacount > 0U) {
11550				zone_send_secureserial(zone, serial);
11551			}
11552		}
11553
11554		/* XXXMPA make separate call back */
11555		if (result == ISC_R_SUCCESS) {
11556			set_resigntime(zone);
11557			if (zone->task != NULL) {
11558				isc_time_t now;
11559				TIME_NOW(&now);
11560				zone_settimer(zone, &now);
11561			}
11562		}
11563	}
11564	if (secure != NULL) {
11565		UNLOCK_ZONE(secure);
11566	}
11567	zone_needdump(zone, DNS_DUMP_DELAY);
11568	UNLOCK_ZONE(zone);
11569}
11570
11571void
11572dns_zone_expire(dns_zone_t *zone) {
11573	REQUIRE(DNS_ZONE_VALID(zone));
11574
11575	LOCK_ZONE(zone);
11576	zone_expire(zone);
11577	UNLOCK_ZONE(zone);
11578}
11579
11580static void
11581zone_expire(dns_zone_t *zone) {
11582	dns_db_t *db = NULL;
11583
11584	/*
11585	 * 'zone' locked by caller.
11586	 */
11587
11588	REQUIRE(LOCKED_ZONE(zone));
11589
11590	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
11591
11592	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
11593	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11594	zone->retry = DNS_ZONE_DEFAULTRETRY;
11595	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11596
11597	/*
11598	 * An RPZ zone has expired; before unloading it, we must
11599	 * first remove it from the RPZ summary database. The
11600	 * easiest way to do this is "update" it with an empty
11601	 * database so that the update callback synchronizes
11602	 * the diff automatically.
11603	 */
11604	if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
11605		isc_result_t result;
11606		dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
11607
11608		CHECK(dns_db_create(zone->mctx, "rbt", &zone->origin,
11609				    dns_dbtype_zone, zone->rdclass, 0, NULL,
11610				    &db));
11611		CHECK(dns_rpz_dbupdate_callback(db, rpz));
11612		dns_zone_log(zone, ISC_LOG_WARNING,
11613			     "response-policy zone expired; "
11614			     "policies unloaded");
11615	}
11616
11617failure:
11618	if (db != NULL) {
11619		dns_db_detach(&db);
11620	}
11621
11622	zone_unload(zone);
11623}
11624
11625void
11626dns_zone_refresh(dns_zone_t *zone) {
11627	isc_interval_t i;
11628	uint32_t oldflags;
11629	unsigned int j;
11630	isc_result_t result;
11631
11632	REQUIRE(DNS_ZONE_VALID(zone));
11633
11634	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11635		return;
11636	}
11637
11638	/*
11639	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
11640	 * in progress at a time.
11641	 */
11642
11643	LOCK_ZONE(zone);
11644	oldflags = atomic_load(&zone->flags);
11645	if (zone->masterscnt == 0) {
11646		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
11647		if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0) {
11648			dns_zone_log(zone, ISC_LOG_ERROR,
11649				     "cannot refresh: no primaries");
11650		}
11651		goto unlock;
11652	}
11653	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11654	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11655	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11656	if ((oldflags & (DNS_ZONEFLG_REFRESH | DNS_ZONEFLG_LOADING)) != 0) {
11657		goto unlock;
11658	}
11659
11660	/*
11661	 * Set the next refresh time as if refresh check has failed.
11662	 * Setting this to the retry time will do that.  XXXMLG
11663	 * If we are successful it will be reset using zone->refresh.
11664	 */
11665	isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
11666			 0);
11667	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
11668	if (result != ISC_R_SUCCESS) {
11669		dns_zone_log(zone, ISC_LOG_WARNING,
11670			     "isc_time_nowplusinterval() failed: %s",
11671			     dns_result_totext(result));
11672	}
11673
11674	/*
11675	 * When lacking user-specified timer values from the SOA,
11676	 * do exponential backoff of the retry time up to a
11677	 * maximum of six hours.
11678	 */
11679	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) {
11680		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
11681	}
11682
11683	zone->curmaster = 0;
11684	for (j = 0; j < zone->masterscnt; j++) {
11685		zone->mastersok[j] = false;
11686	}
11687	/* initiate soa query */
11688	queue_soa_query(zone);
11689unlock:
11690	UNLOCK_ZONE(zone);
11691}
11692
11693static isc_result_t
11694zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
11695			 bool *fixjournal) {
11696	dns_journal_t *journal = NULL;
11697	unsigned int options;
11698	isc_result_t result;
11699
11700	if (zone->type == dns_zone_primary &&
11701	    (inline_secure(zone) ||
11702	     (zone->update_acl != NULL || zone->ssutable != NULL)))
11703	{
11704		options = DNS_JOURNALOPT_RESIGN;
11705	} else {
11706		options = 0;
11707	}
11708
11709	result = dns_journal_open(zone->mctx, zone->journal, DNS_JOURNAL_READ,
11710				  &journal);
11711	if (result == ISC_R_NOTFOUND) {
11712		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(3),
11713			      "no journal file, but that's OK ");
11714		return (ISC_R_SUCCESS);
11715	} else if (result != ISC_R_SUCCESS) {
11716		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11717			      "journal open failed: %s",
11718			      dns_result_totext(result));
11719		return (result);
11720	}
11721
11722	if (dns_journal_empty(journal)) {
11723		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
11724			      "journal empty");
11725		dns_journal_destroy(&journal);
11726		return (ISC_R_SUCCESS);
11727	}
11728
11729	result = dns_journal_rollforward(journal, db, options);
11730	switch (result) {
11731	case ISC_R_SUCCESS:
11732		*needdump = true;
11733		FALLTHROUGH;
11734	case DNS_R_UPTODATE:
11735		if (dns_journal_recovered(journal)) {
11736			*fixjournal = true;
11737			dns_zone_logc(
11738				zone, DNS_LOGCATEGORY_ZONELOAD,
11739				ISC_LOG_DEBUG(1),
11740				"journal rollforward completed successfully "
11741				"using old journal format: %s",
11742				dns_result_totext(result));
11743		} else {
11744			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
11745				      ISC_LOG_DEBUG(1),
11746				      "journal rollforward completed "
11747				      "successfully: %s",
11748				      dns_result_totext(result));
11749		}
11750
11751		dns_journal_destroy(&journal);
11752		return (ISC_R_SUCCESS);
11753	case ISC_R_NOTFOUND:
11754	case ISC_R_RANGE:
11755		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11756			      "journal rollforward failed: journal out of sync "
11757			      "with zone");
11758		dns_journal_destroy(&journal);
11759		return (result);
11760	default:
11761		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11762			      "journal rollforward failed: %s",
11763			      dns_result_totext(result));
11764		dns_journal_destroy(&journal);
11765		return (result);
11766	}
11767}
11768
11769static void
11770zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
11771	isc_result_t result;
11772	int32_t journalsize;
11773	dns_dbversion_t *ver = NULL;
11774	uint64_t dbsize;
11775	uint32_t options = 0;
11776
11777	INSIST(LOCKED_ZONE(zone));
11778	if (inline_raw(zone)) {
11779		INSIST(LOCKED_ZONE(zone->secure));
11780	}
11781
11782	journalsize = zone->journalsize;
11783	if (journalsize == -1) {
11784		journalsize = DNS_JOURNAL_SIZE_MAX;
11785		dns_db_currentversion(db, &ver);
11786		result = dns_db_getsize(db, ver, NULL, &dbsize);
11787		dns_db_closeversion(db, &ver, false);
11788		if (result != ISC_R_SUCCESS) {
11789			dns_zone_log(zone, ISC_LOG_ERROR,
11790				     "zone_journal_compact: "
11791				     "could not get zone size: %s",
11792				     isc_result_totext(result));
11793		} else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
11794			journalsize = (int32_t)dbsize * 2;
11795		}
11796	}
11797	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIXJOURNAL)) {
11798		options |= DNS_JOURNAL_COMPACTALL;
11799		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
11800		zone_debuglog(zone, "zone_journal_compact", 1,
11801			      "repair full journal");
11802	} else {
11803		zone_debuglog(zone, "zone_journal_compact", 1,
11804			      "target journal size %d", journalsize);
11805	}
11806	result = dns_journal_compact(zone->mctx, zone->journal, serial, options,
11807				     journalsize);
11808	switch (result) {
11809	case ISC_R_SUCCESS:
11810	case ISC_R_NOSPACE:
11811	case ISC_R_NOTFOUND:
11812		dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s",
11813			     dns_result_totext(result));
11814		break;
11815	default:
11816		dns_zone_log(zone, ISC_LOG_ERROR,
11817			     "dns_journal_compact failed: %s",
11818			     dns_result_totext(result));
11819		break;
11820	}
11821}
11822
11823isc_result_t
11824dns_zone_flush(dns_zone_t *zone) {
11825	isc_result_t result = ISC_R_SUCCESS;
11826	bool dumping;
11827
11828	REQUIRE(DNS_ZONE_VALID(zone));
11829
11830	LOCK_ZONE(zone);
11831	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
11832	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11833	    zone->masterfile != NULL)
11834	{
11835		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11836		result = ISC_R_ALREADYRUNNING;
11837		dumping = was_dumping(zone);
11838	} else {
11839		dumping = true;
11840	}
11841	UNLOCK_ZONE(zone);
11842	if (!dumping) {
11843		result = zone_dump(zone, true); /* Unknown task. */
11844	}
11845	return (result);
11846}
11847
11848isc_result_t
11849dns_zone_dump(dns_zone_t *zone) {
11850	isc_result_t result = ISC_R_ALREADYRUNNING;
11851	bool dumping;
11852
11853	REQUIRE(DNS_ZONE_VALID(zone));
11854
11855	LOCK_ZONE(zone);
11856	dumping = was_dumping(zone);
11857	UNLOCK_ZONE(zone);
11858	if (!dumping) {
11859		result = zone_dump(zone, false); /* Unknown task. */
11860	}
11861	return (result);
11862}
11863
11864static void
11865zone_needdump(dns_zone_t *zone, unsigned int delay) {
11866	const char me[] = "zone_needdump";
11867	isc_time_t dumptime;
11868	isc_time_t now;
11869
11870	/*
11871	 * 'zone' locked by caller
11872	 */
11873
11874	REQUIRE(DNS_ZONE_VALID(zone));
11875	REQUIRE(LOCKED_ZONE(zone));
11876	ENTER;
11877
11878	/*
11879	 * Do we have a place to dump to and are we loaded?
11880	 */
11881	if (zone->masterfile == NULL ||
11882	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
11883	{
11884		return;
11885	}
11886
11887	TIME_NOW(&now);
11888	/* add some noise */
11889	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
11890
11891	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11892	if (isc_time_isepoch(&zone->dumptime) ||
11893	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
11894	{
11895		zone->dumptime = dumptime;
11896	}
11897	if (zone->task != NULL) {
11898		zone_settimer(zone, &now);
11899	}
11900}
11901
11902static void
11903dump_done(void *arg, isc_result_t result) {
11904	const char me[] = "dump_done";
11905	dns_zone_t *zone = arg;
11906	dns_zone_t *secure = NULL;
11907	dns_db_t *db;
11908	dns_dbversion_t *version;
11909	bool again = false;
11910	bool compact = false;
11911	uint32_t serial;
11912	isc_result_t tresult;
11913
11914	REQUIRE(DNS_ZONE_VALID(zone));
11915
11916	ENTER;
11917
11918	if (result == ISC_R_SUCCESS && zone->journal != NULL) {
11919		/*
11920		 * We don't own these, zone->dctx must stay valid.
11921		 */
11922		db = dns_dumpctx_db(zone->dctx);
11923		version = dns_dumpctx_version(zone->dctx);
11924		tresult = dns_db_getsoaserial(db, version, &serial);
11925
11926		/*
11927		 * Handle lock order inversion.
11928		 */
11929	again:
11930		LOCK_ZONE(zone);
11931		if (inline_raw(zone)) {
11932			secure = zone->secure;
11933			INSIST(secure != zone);
11934			TRYLOCK_ZONE(result, secure);
11935			if (result != ISC_R_SUCCESS) {
11936				UNLOCK_ZONE(zone);
11937				secure = NULL;
11938				isc_thread_yield();
11939				goto again;
11940			}
11941		}
11942
11943		/*
11944		 * If there is a secure version of this zone
11945		 * use its serial if it is less than ours.
11946		 */
11947		if (tresult == ISC_R_SUCCESS && secure != NULL) {
11948			uint32_t sserial;
11949			isc_result_t mresult;
11950
11951			ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
11952			if (secure->db != NULL) {
11953				mresult = dns_db_getsoaserial(zone->secure->db,
11954							      NULL, &sserial);
11955				if (mresult == ISC_R_SUCCESS &&
11956				    isc_serial_lt(sserial, serial))
11957				{
11958					serial = sserial;
11959				}
11960			}
11961			ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
11962		}
11963		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
11964			dns_db_t *zdb = NULL;
11965			if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
11966				zone_journal_compact(zone, zdb, serial);
11967				dns_db_detach(&zdb);
11968			}
11969		} else if (tresult == ISC_R_SUCCESS) {
11970			compact = true;
11971			zone->compact_serial = serial;
11972		}
11973		if (secure != NULL) {
11974			UNLOCK_ZONE(secure);
11975		}
11976		UNLOCK_ZONE(zone);
11977	}
11978
11979	LOCK_ZONE(zone);
11980	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
11981	if (compact) {
11982		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11983	}
11984	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN)) {
11985		/*
11986		 * If DNS_ZONEFLG_SHUTDOWN is set, all external references to
11987		 * the zone are gone, which means it is in the process of being
11988		 * cleaned up, so do not reschedule dumping.
11989		 *
11990		 * Detach from the raw version of the zone in case this
11991		 * operation has been deferred in zone_shutdown().
11992		 */
11993		if (zone->raw != NULL) {
11994			dns_zone_detach(&zone->raw);
11995		}
11996		if (result == ISC_R_SUCCESS) {
11997			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
11998		}
11999	} else if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
12000		/*
12001		 * Try again in a short while.
12002		 */
12003		zone_needdump(zone, DNS_DUMP_DELAY);
12004	} else if (result == ISC_R_SUCCESS &&
12005		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12006		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12007		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12008	{
12009		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12010		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12011		isc_time_settoepoch(&zone->dumptime);
12012		again = true;
12013	} else if (result == ISC_R_SUCCESS) {
12014		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12015	}
12016
12017	if (zone->dctx != NULL) {
12018		dns_dumpctx_detach(&zone->dctx);
12019	}
12020	zonemgr_putio(&zone->writeio);
12021	UNLOCK_ZONE(zone);
12022	if (again) {
12023		(void)zone_dump(zone, false);
12024	}
12025	dns_zone_idetach(&zone);
12026}
12027
12028static isc_result_t
12029zone_dump(dns_zone_t *zone, bool compact) {
12030	const char me[] = "zone_dump";
12031	isc_result_t result;
12032	dns_dbversion_t *version = NULL;
12033	bool again;
12034	dns_db_t *db = NULL;
12035	char *masterfile = NULL;
12036	dns_masterformat_t masterformat = dns_masterformat_none;
12037
12038	/*
12039	 * 'compact' MUST only be set if we are task locked.
12040	 */
12041
12042	REQUIRE(DNS_ZONE_VALID(zone));
12043	ENTER;
12044
12045redo:
12046	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12047	if (zone->db != NULL) {
12048		dns_db_attach(zone->db, &db);
12049	}
12050	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12051	LOCK_ZONE(zone);
12052	if (zone->masterfile != NULL) {
12053		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
12054		masterformat = zone->masterformat;
12055	}
12056	UNLOCK_ZONE(zone);
12057	if (db == NULL) {
12058		result = DNS_R_NOTLOADED;
12059		goto fail;
12060	}
12061	if (masterfile == NULL) {
12062		result = DNS_R_NOMASTERFILE;
12063		goto fail;
12064	}
12065
12066	if (compact && zone->type != dns_zone_stub) {
12067		dns_zone_t *dummy = NULL;
12068		LOCK_ZONE(zone);
12069		zone_iattach(zone, &dummy);
12070		result = zonemgr_getio(zone->zmgr, false, zone->task,
12071				       zone_gotwritehandle, zone,
12072				       &zone->writeio);
12073		if (result != ISC_R_SUCCESS) {
12074			zone_idetach(&dummy);
12075		} else {
12076			result = DNS_R_CONTINUE;
12077		}
12078		UNLOCK_ZONE(zone);
12079	} else {
12080		const dns_master_style_t *output_style;
12081
12082		dns_masterrawheader_t rawdata;
12083		dns_db_currentversion(db, &version);
12084		dns_master_initrawheader(&rawdata);
12085		if (inline_secure(zone)) {
12086			get_raw_serial(zone->raw, &rawdata);
12087		}
12088		if (zone->type == dns_zone_key) {
12089			output_style = &dns_master_style_keyzone;
12090		} else {
12091			output_style = &dns_master_style_default;
12092		}
12093		result = dns_master_dump(zone->mctx, db, version, output_style,
12094					 masterfile, masterformat, &rawdata);
12095		dns_db_closeversion(db, &version, false);
12096	}
12097fail:
12098	if (db != NULL) {
12099		dns_db_detach(&db);
12100	}
12101	if (masterfile != NULL) {
12102		isc_mem_free(zone->mctx, masterfile);
12103	}
12104	masterfile = NULL;
12105
12106	if (result == DNS_R_CONTINUE) {
12107		return (ISC_R_SUCCESS); /* XXXMPA */
12108	}
12109
12110	again = false;
12111	LOCK_ZONE(zone);
12112	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
12113	if (result != ISC_R_SUCCESS) {
12114		/*
12115		 * Try again in a short while.
12116		 */
12117		zone_needdump(zone, DNS_DUMP_DELAY);
12118	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12119		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12120		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12121	{
12122		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12123		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12124		isc_time_settoepoch(&zone->dumptime);
12125		again = true;
12126	} else {
12127		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12128	}
12129	UNLOCK_ZONE(zone);
12130	if (again) {
12131		goto redo;
12132	}
12133
12134	return (result);
12135}
12136
12137static isc_result_t
12138dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
12139	     dns_masterformat_t format, const uint32_t rawversion) {
12140	isc_result_t result;
12141	dns_dbversion_t *version = NULL;
12142	dns_db_t *db = NULL;
12143	dns_masterrawheader_t rawdata;
12144
12145	REQUIRE(DNS_ZONE_VALID(zone));
12146
12147	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12148	if (zone->db != NULL) {
12149		dns_db_attach(zone->db, &db);
12150	}
12151	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12152	if (db == NULL) {
12153		return (DNS_R_NOTLOADED);
12154	}
12155
12156	dns_db_currentversion(db, &version);
12157	dns_master_initrawheader(&rawdata);
12158	if (rawversion == 0) {
12159		rawdata.flags |= DNS_MASTERRAW_COMPAT;
12160	} else if (inline_secure(zone)) {
12161		get_raw_serial(zone->raw, &rawdata);
12162	} else if (zone->sourceserialset) {
12163		rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
12164		rawdata.sourceserial = zone->sourceserial;
12165	}
12166	result = dns_master_dumptostream(zone->mctx, db, version, style, format,
12167					 &rawdata, fd);
12168	dns_db_closeversion(db, &version, false);
12169	dns_db_detach(&db);
12170	return (result);
12171}
12172
12173isc_result_t
12174dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
12175		      const dns_master_style_t *style,
12176		      const uint32_t rawversion) {
12177	return (dumptostream(zone, fd, style, format, rawversion));
12178}
12179
12180void
12181dns_zone_unload(dns_zone_t *zone) {
12182	REQUIRE(DNS_ZONE_VALID(zone));
12183
12184	LOCK_ZONE(zone);
12185	zone_unload(zone);
12186	UNLOCK_ZONE(zone);
12187}
12188
12189static void
12190notify_cancel(dns_zone_t *zone) {
12191	dns_notify_t *notify;
12192
12193	/*
12194	 * 'zone' locked by caller.
12195	 */
12196
12197	REQUIRE(LOCKED_ZONE(zone));
12198
12199	for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12200	     notify = ISC_LIST_NEXT(notify, link))
12201	{
12202		if (notify->find != NULL) {
12203			dns_adb_cancelfind(notify->find);
12204		}
12205		if (notify->request != NULL) {
12206			dns_request_cancel(notify->request);
12207		}
12208	}
12209}
12210
12211static void
12212checkds_cancel(dns_zone_t *zone) {
12213	dns_checkds_t *checkds;
12214
12215	/*
12216	 * 'zone' locked by caller.
12217	 */
12218
12219	REQUIRE(LOCKED_ZONE(zone));
12220
12221	for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
12222	     checkds = ISC_LIST_NEXT(checkds, link))
12223	{
12224		if (checkds->request != NULL) {
12225			dns_request_cancel(checkds->request);
12226		}
12227	}
12228}
12229
12230static void
12231forward_cancel(dns_zone_t *zone) {
12232	dns_forward_t *forward;
12233
12234	/*
12235	 * 'zone' locked by caller.
12236	 */
12237
12238	REQUIRE(LOCKED_ZONE(zone));
12239
12240	for (forward = ISC_LIST_HEAD(zone->forwards); forward != NULL;
12241	     forward = ISC_LIST_NEXT(forward, link))
12242	{
12243		if (forward->request != NULL) {
12244			dns_request_cancel(forward->request);
12245		}
12246	}
12247}
12248
12249static void
12250zone_unload(dns_zone_t *zone) {
12251	/*
12252	 * 'zone' locked by caller.
12253	 */
12254
12255	REQUIRE(LOCKED_ZONE(zone));
12256
12257	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
12258	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
12259	{
12260		if (zone->writeio != NULL) {
12261			zonemgr_cancelio(zone->writeio);
12262		}
12263
12264		if (zone->dctx != NULL) {
12265			dns_dumpctx_cancel(zone->dctx);
12266		}
12267	}
12268	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12269	zone_detachdb(zone);
12270	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12271	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
12272	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12273
12274	if (zone->type == dns_zone_mirror) {
12275		dns_zone_log(zone, ISC_LOG_INFO,
12276			     "mirror zone is no longer in use; "
12277			     "reverting to normal recursion");
12278	}
12279}
12280
12281void
12282dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
12283	REQUIRE(DNS_ZONE_VALID(zone));
12284	REQUIRE(val > 0);
12285
12286	zone->minrefresh = val;
12287}
12288
12289void
12290dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
12291	REQUIRE(DNS_ZONE_VALID(zone));
12292	REQUIRE(val > 0);
12293
12294	zone->maxrefresh = val;
12295}
12296
12297void
12298dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
12299	REQUIRE(DNS_ZONE_VALID(zone));
12300	REQUIRE(val > 0);
12301
12302	zone->minretry = val;
12303}
12304
12305void
12306dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
12307	REQUIRE(DNS_ZONE_VALID(zone));
12308	REQUIRE(val > 0);
12309
12310	zone->maxretry = val;
12311}
12312
12313uint32_t
12314dns_zone_getmaxrecords(dns_zone_t *zone) {
12315	REQUIRE(DNS_ZONE_VALID(zone));
12316
12317	return (zone->maxrecords);
12318}
12319
12320void
12321dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
12322	REQUIRE(DNS_ZONE_VALID(zone));
12323
12324	zone->maxrecords = val;
12325}
12326
12327static bool
12328notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
12329		isc_sockaddr_t *addr, dns_tsigkey_t *key) {
12330	dns_notify_t *notify;
12331	dns_zonemgr_t *zmgr;
12332	isc_result_t result;
12333
12334	for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12335	     notify = ISC_LIST_NEXT(notify, link))
12336	{
12337		if (notify->request != NULL) {
12338			continue;
12339		}
12340		if (name != NULL && dns_name_dynamic(&notify->ns) &&
12341		    dns_name_equal(name, &notify->ns))
12342		{
12343			goto requeue;
12344		}
12345		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
12346		    notify->key == key)
12347		{
12348			goto requeue;
12349		}
12350	}
12351	return (false);
12352
12353requeue:
12354	/*
12355	 * If we are enqueued on the startup ratelimiter and this is
12356	 * not a startup notify, re-enqueue on the normal notify
12357	 * ratelimiter.
12358	 */
12359	if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
12360	    (notify->flags & DNS_NOTIFY_STARTUP) != 0)
12361	{
12362		zmgr = notify->zone->zmgr;
12363		result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
12364						 notify->event);
12365		if (result != ISC_R_SUCCESS) {
12366			return (true);
12367		}
12368
12369		notify->flags &= ~DNS_NOTIFY_STARTUP;
12370		result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
12371						 notify->zone->task,
12372						 &notify->event);
12373		if (result != ISC_R_SUCCESS) {
12374			isc_event_free(&notify->event);
12375			return (false);
12376		}
12377	}
12378
12379	return (true);
12380}
12381
12382static bool
12383notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
12384	dns_tsigkey_t *key = NULL;
12385	isc_sockaddr_t src;
12386	isc_sockaddr_t any;
12387	bool isself;
12388	isc_netaddr_t dstaddr;
12389	isc_result_t result;
12390
12391	if (zone->view == NULL || zone->isself == NULL) {
12392		return (false);
12393	}
12394
12395	switch (isc_sockaddr_pf(dst)) {
12396	case PF_INET:
12397		src = zone->notifysrc4;
12398		isc_sockaddr_any(&any);
12399		break;
12400	case PF_INET6:
12401		src = zone->notifysrc6;
12402		isc_sockaddr_any6(&any);
12403		break;
12404	default:
12405		return (false);
12406	}
12407
12408	/*
12409	 * When sending from any the kernel will assign a source address
12410	 * that matches the destination address.
12411	 */
12412	if (isc_sockaddr_eqaddr(&any, &src)) {
12413		src = *dst;
12414	}
12415
12416	isc_netaddr_fromsockaddr(&dstaddr, dst);
12417	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
12418	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12419		return (false);
12420	}
12421	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
12422				zone->isselfarg);
12423	if (key != NULL) {
12424		dns_tsigkey_detach(&key);
12425	}
12426	return (isself);
12427}
12428
12429static void
12430notify_destroy(dns_notify_t *notify, bool locked) {
12431	isc_mem_t *mctx;
12432
12433	REQUIRE(DNS_NOTIFY_VALID(notify));
12434
12435	if (notify->zone != NULL) {
12436		if (!locked) {
12437			LOCK_ZONE(notify->zone);
12438		}
12439		REQUIRE(LOCKED_ZONE(notify->zone));
12440		if (ISC_LINK_LINKED(notify, link)) {
12441			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
12442		}
12443		if (!locked) {
12444			UNLOCK_ZONE(notify->zone);
12445		}
12446		if (locked) {
12447			zone_idetach(&notify->zone);
12448		} else {
12449			dns_zone_idetach(&notify->zone);
12450		}
12451	}
12452	if (notify->find != NULL) {
12453		dns_adb_destroyfind(&notify->find);
12454	}
12455	if (notify->request != NULL) {
12456		dns_request_destroy(&notify->request);
12457	}
12458	if (dns_name_dynamic(&notify->ns)) {
12459		dns_name_free(&notify->ns, notify->mctx);
12460	}
12461	if (notify->key != NULL) {
12462		dns_tsigkey_detach(&notify->key);
12463	}
12464	mctx = notify->mctx;
12465	isc_mem_put(notify->mctx, notify, sizeof(*notify));
12466	isc_mem_detach(&mctx);
12467}
12468
12469static isc_result_t
12470notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
12471	dns_notify_t *notify;
12472
12473	REQUIRE(notifyp != NULL && *notifyp == NULL);
12474
12475	notify = isc_mem_get(mctx, sizeof(*notify));
12476
12477	notify->mctx = NULL;
12478	isc_mem_attach(mctx, &notify->mctx);
12479	notify->flags = flags;
12480	notify->zone = NULL;
12481	notify->find = NULL;
12482	notify->request = NULL;
12483	notify->key = NULL;
12484	notify->event = NULL;
12485	isc_sockaddr_any(&notify->dst);
12486	dns_name_init(&notify->ns, NULL);
12487	ISC_LINK_INIT(notify, link);
12488	notify->magic = NOTIFY_MAGIC;
12489	*notifyp = notify;
12490	return (ISC_R_SUCCESS);
12491}
12492
12493/*
12494 * XXXAG should check for DNS_ZONEFLG_EXITING
12495 */
12496static void
12497process_adb_event(isc_task_t *task, isc_event_t *ev) {
12498	dns_notify_t *notify;
12499	isc_eventtype_t result;
12500
12501	UNUSED(task);
12502
12503	notify = ev->ev_arg;
12504	REQUIRE(DNS_NOTIFY_VALID(notify));
12505	INSIST(task == notify->zone->task);
12506	result = ev->ev_type;
12507	isc_event_free(&ev);
12508	if (result == DNS_EVENT_ADBMOREADDRESSES) {
12509		dns_adb_destroyfind(&notify->find);
12510		notify_find_address(notify);
12511		return;
12512	}
12513	if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
12514		LOCK_ZONE(notify->zone);
12515		notify_send(notify);
12516		UNLOCK_ZONE(notify->zone);
12517	}
12518	notify_destroy(notify, false);
12519}
12520
12521static void
12522notify_find_address(dns_notify_t *notify) {
12523	isc_result_t result;
12524	unsigned int options;
12525
12526	REQUIRE(DNS_NOTIFY_VALID(notify));
12527	options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET | DNS_ADBFIND_INET6 |
12528		  DNS_ADBFIND_RETURNLAME;
12529
12530	if (notify->zone->view->adb == NULL) {
12531		goto destroy;
12532	}
12533
12534	result = dns_adb_createfind(
12535		notify->zone->view->adb, notify->zone->task, process_adb_event,
12536		notify, &notify->ns, dns_rootname, 0, options, 0, NULL,
12537		notify->zone->view->dstport, 0, NULL, &notify->find);
12538
12539	/* Something failed? */
12540	if (result != ISC_R_SUCCESS) {
12541		goto destroy;
12542	}
12543
12544	/* More addresses pending? */
12545	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
12546		return;
12547	}
12548
12549	/* We have as many addresses as we can get. */
12550	LOCK_ZONE(notify->zone);
12551	notify_send(notify);
12552	UNLOCK_ZONE(notify->zone);
12553
12554destroy:
12555	notify_destroy(notify, false);
12556}
12557
12558static isc_result_t
12559notify_send_queue(dns_notify_t *notify, bool startup) {
12560	isc_event_t *e;
12561	isc_result_t result;
12562
12563	INSIST(notify->event == NULL);
12564	e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
12565			       notify_send_toaddr, notify, sizeof(isc_event_t));
12566	if (startup) {
12567		notify->event = e;
12568	}
12569	e->ev_arg = notify;
12570	e->ev_sender = NULL;
12571	result = isc_ratelimiter_enqueue(
12572		startup ? notify->zone->zmgr->startupnotifyrl
12573			: notify->zone->zmgr->notifyrl,
12574		notify->zone->task, &e);
12575	if (result != ISC_R_SUCCESS) {
12576		isc_event_free(&e);
12577		notify->event = NULL;
12578	}
12579	return (result);
12580}
12581
12582static void
12583notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
12584	dns_notify_t *notify;
12585	isc_result_t result;
12586	dns_message_t *message = NULL;
12587	isc_netaddr_t dstip;
12588	dns_tsigkey_t *key = NULL;
12589	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12590	isc_sockaddr_t src;
12591	unsigned int options, timeout;
12592	bool have_notifysource = false;
12593	bool have_notifydscp = false;
12594	isc_dscp_t dscp = -1;
12595
12596	notify = event->ev_arg;
12597	REQUIRE(DNS_NOTIFY_VALID(notify));
12598
12599	UNUSED(task);
12600
12601	LOCK_ZONE(notify->zone);
12602
12603	notify->event = NULL;
12604
12605	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
12606		result = ISC_R_CANCELED;
12607		goto cleanup;
12608	}
12609
12610	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
12611	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
12612	    notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
12613	{
12614		result = ISC_R_CANCELED;
12615		goto cleanup;
12616	}
12617
12618	/*
12619	 * The raw IPv4 address should also exist.  Don't send to the
12620	 * mapped form.
12621	 */
12622	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
12623	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr))
12624	{
12625		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12626		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12627			   "notify: ignoring IPv6 mapped IPV4 address: %s",
12628			   addrbuf);
12629		result = ISC_R_CANCELED;
12630		goto cleanup;
12631	}
12632
12633	result = notify_createmessage(notify->zone, notify->flags, &message);
12634	if (result != ISC_R_SUCCESS) {
12635		goto cleanup;
12636	}
12637
12638	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12639	if (notify->key != NULL) {
12640		/* Transfer ownership of key */
12641		key = notify->key;
12642		notify->key = NULL;
12643	} else {
12644		isc_netaddr_fromsockaddr(&dstip, &notify->dst);
12645		result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
12646		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12647			notify_log(notify->zone, ISC_LOG_ERROR,
12648				   "NOTIFY to %s not sent. "
12649				   "Peer TSIG key lookup failure.",
12650				   addrbuf);
12651			goto cleanup_message;
12652		}
12653	}
12654
12655	if (key != NULL) {
12656		char namebuf[DNS_NAME_FORMATSIZE];
12657
12658		dns_name_format(&key->name, namebuf, sizeof(namebuf));
12659		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12660			   "sending notify to %s : TSIG (%s)", addrbuf,
12661			   namebuf);
12662	} else {
12663		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12664			   "sending notify to %s", addrbuf);
12665	}
12666	options = 0;
12667	if (notify->zone->view->peers != NULL) {
12668		dns_peer_t *peer = NULL;
12669		bool usetcp = false;
12670		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
12671						 &dstip, &peer);
12672		if (result == ISC_R_SUCCESS) {
12673			result = dns_peer_getnotifysource(peer, &src);
12674			if (result == ISC_R_SUCCESS) {
12675				have_notifysource = true;
12676			}
12677			dns_peer_getnotifydscp(peer, &dscp);
12678			if (dscp != -1) {
12679				have_notifydscp = true;
12680			}
12681			result = dns_peer_getforcetcp(peer, &usetcp);
12682			if (result == ISC_R_SUCCESS && usetcp) {
12683				options |= DNS_FETCHOPT_TCP;
12684			}
12685		}
12686	}
12687	switch (isc_sockaddr_pf(&notify->dst)) {
12688	case PF_INET:
12689		if (!have_notifysource) {
12690			src = notify->zone->notifysrc4;
12691		}
12692		if (!have_notifydscp) {
12693			dscp = notify->zone->notifysrc4dscp;
12694		}
12695		break;
12696	case PF_INET6:
12697		if (!have_notifysource) {
12698			src = notify->zone->notifysrc6;
12699		}
12700		if (!have_notifydscp) {
12701			dscp = notify->zone->notifysrc6dscp;
12702		}
12703		break;
12704	default:
12705		result = ISC_R_NOTIMPLEMENTED;
12706		goto cleanup_key;
12707	}
12708	timeout = 15;
12709	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) {
12710		timeout = 30;
12711	}
12712	result = dns_request_createvia(
12713		notify->zone->view->requestmgr, message, &src, &notify->dst,
12714		dscp, options, key, timeout * 3, timeout, 0, notify->zone->task,
12715		notify_done, notify, &notify->request);
12716	if (result == ISC_R_SUCCESS) {
12717		if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
12718			inc_stats(notify->zone,
12719				  dns_zonestatscounter_notifyoutv4);
12720		} else {
12721			inc_stats(notify->zone,
12722				  dns_zonestatscounter_notifyoutv6);
12723		}
12724	}
12725
12726cleanup_key:
12727	if (key != NULL) {
12728		dns_tsigkey_detach(&key);
12729	}
12730cleanup_message:
12731	dns_message_detach(&message);
12732cleanup:
12733	UNLOCK_ZONE(notify->zone);
12734	isc_event_free(&event);
12735	if (result != ISC_R_SUCCESS) {
12736		notify_destroy(notify, false);
12737	}
12738}
12739
12740static void
12741notify_send(dns_notify_t *notify) {
12742	dns_adbaddrinfo_t *ai;
12743	isc_sockaddr_t dst;
12744	isc_result_t result;
12745	dns_notify_t *newnotify = NULL;
12746	unsigned int flags;
12747	bool startup;
12748
12749	/*
12750	 * Zone lock held by caller.
12751	 */
12752	REQUIRE(DNS_NOTIFY_VALID(notify));
12753	REQUIRE(LOCKED_ZONE(notify->zone));
12754
12755	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) {
12756		return;
12757	}
12758
12759	for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL;
12760	     ai = ISC_LIST_NEXT(ai, publink))
12761	{
12762		dst = ai->sockaddr;
12763		if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
12764				    NULL))
12765		{
12766			continue;
12767		}
12768		if (notify_isself(notify->zone, &dst)) {
12769			continue;
12770		}
12771		newnotify = NULL;
12772		flags = notify->flags & DNS_NOTIFY_NOSOA;
12773		result = notify_create(notify->mctx, flags, &newnotify);
12774		if (result != ISC_R_SUCCESS) {
12775			goto cleanup;
12776		}
12777		zone_iattach(notify->zone, &newnotify->zone);
12778		ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
12779		newnotify->dst = dst;
12780		startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
12781		result = notify_send_queue(newnotify, startup);
12782		if (result != ISC_R_SUCCESS) {
12783			goto cleanup;
12784		}
12785		newnotify = NULL;
12786	}
12787
12788cleanup:
12789	if (newnotify != NULL) {
12790		notify_destroy(newnotify, true);
12791	}
12792}
12793
12794void
12795dns_zone_notify(dns_zone_t *zone) {
12796	isc_time_t now;
12797
12798	REQUIRE(DNS_ZONE_VALID(zone));
12799
12800	LOCK_ZONE(zone);
12801	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12802
12803	TIME_NOW(&now);
12804	zone_settimer(zone, &now);
12805	UNLOCK_ZONE(zone);
12806}
12807
12808static void
12809zone_notify(dns_zone_t *zone, isc_time_t *now) {
12810	dns_dbnode_t *node = NULL;
12811	dns_db_t *zonedb = NULL;
12812	dns_dbversion_t *version = NULL;
12813	dns_name_t *origin = NULL;
12814	dns_name_t master;
12815	dns_rdata_ns_t ns;
12816	dns_rdata_soa_t soa;
12817	uint32_t serial;
12818	dns_rdata_t rdata = DNS_RDATA_INIT;
12819	dns_rdataset_t nsrdset;
12820	dns_rdataset_t soardset;
12821	isc_result_t result;
12822	unsigned int i;
12823	isc_sockaddr_t dst;
12824	bool isqueued;
12825	dns_notifytype_t notifytype;
12826	unsigned int flags = 0;
12827	bool loggednotify = false;
12828	bool startup;
12829
12830	REQUIRE(DNS_ZONE_VALID(zone));
12831
12832	LOCK_ZONE(zone);
12833	startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12834	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12835	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
12836	notifytype = zone->notifytype;
12837	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
12838	UNLOCK_ZONE(zone);
12839
12840	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12841	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12842	{
12843		return;
12844	}
12845
12846	if (notifytype == dns_notifytype_no) {
12847		return;
12848	}
12849
12850	if (notifytype == dns_notifytype_masteronly &&
12851	    zone->type != dns_zone_primary)
12852	{
12853		return;
12854	}
12855
12856	origin = &zone->origin;
12857
12858	/*
12859	 * If the zone is dialup we are done as we don't want to send
12860	 * the current soa so as to force a refresh query.
12861	 */
12862	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
12863		flags |= DNS_NOTIFY_NOSOA;
12864	}
12865
12866	/*
12867	 * Record that this was a notify due to starting up.
12868	 */
12869	if (startup) {
12870		flags |= DNS_NOTIFY_STARTUP;
12871	}
12872
12873	/*
12874	 * Get SOA RRset.
12875	 */
12876	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12877	if (zone->db != NULL) {
12878		dns_db_attach(zone->db, &zonedb);
12879	}
12880	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12881	if (zonedb == NULL) {
12882		return;
12883	}
12884	dns_db_currentversion(zonedb, &version);
12885	result = dns_db_findnode(zonedb, origin, false, &node);
12886	if (result != ISC_R_SUCCESS) {
12887		goto cleanup1;
12888	}
12889
12890	dns_rdataset_init(&soardset);
12891	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
12892				     dns_rdatatype_none, 0, &soardset, NULL);
12893	if (result != ISC_R_SUCCESS) {
12894		goto cleanup2;
12895	}
12896
12897	/*
12898	 * Find serial and master server's name.
12899	 */
12900	dns_name_init(&master, NULL);
12901	result = dns_rdataset_first(&soardset);
12902	if (result != ISC_R_SUCCESS) {
12903		goto cleanup3;
12904	}
12905	dns_rdataset_current(&soardset, &rdata);
12906	result = dns_rdata_tostruct(&rdata, &soa, NULL);
12907	RUNTIME_CHECK(result == ISC_R_SUCCESS);
12908	dns_rdata_reset(&rdata);
12909	dns_name_dup(&soa.origin, zone->mctx, &master);
12910	serial = soa.serial;
12911	dns_rdataset_disassociate(&soardset);
12912
12913	/*
12914	 * Enqueue notify requests for 'also-notify' servers.
12915	 */
12916	LOCK_ZONE(zone);
12917	for (i = 0; i < zone->notifycnt; i++) {
12918		dns_tsigkey_t *key = NULL;
12919		dns_notify_t *notify = NULL;
12920
12921		if ((zone->notifykeynames != NULL) &&
12922		    (zone->notifykeynames[i] != NULL))
12923		{
12924			dns_view_t *view = dns_zone_getview(zone);
12925			dns_name_t *keyname = zone->notifykeynames[i];
12926			(void)dns_view_gettsig(view, keyname, &key);
12927		}
12928
12929		dst = zone->notify[i];
12930		if (notify_isqueued(zone, flags, NULL, &dst, key)) {
12931			if (key != NULL) {
12932				dns_tsigkey_detach(&key);
12933			}
12934			continue;
12935		}
12936
12937		result = notify_create(zone->mctx, flags, &notify);
12938		if (result != ISC_R_SUCCESS) {
12939			if (key != NULL) {
12940				dns_tsigkey_detach(&key);
12941			}
12942			continue;
12943		}
12944
12945		zone_iattach(zone, &notify->zone);
12946		notify->dst = dst;
12947
12948		INSIST(notify->key == NULL);
12949
12950		if (key != NULL) {
12951			notify->key = key;
12952			key = NULL;
12953		}
12954
12955		ISC_LIST_APPEND(zone->notifies, notify, link);
12956		result = notify_send_queue(notify, startup);
12957		if (result != ISC_R_SUCCESS) {
12958			notify_destroy(notify, true);
12959		}
12960		if (!loggednotify) {
12961			notify_log(zone, ISC_LOG_INFO,
12962				   "sending notifies (serial %u)", serial);
12963			loggednotify = true;
12964		}
12965	}
12966	UNLOCK_ZONE(zone);
12967
12968	if (notifytype == dns_notifytype_explicit) {
12969		goto cleanup3;
12970	}
12971
12972	/*
12973	 * Process NS RRset to generate notifies.
12974	 */
12975
12976	dns_rdataset_init(&nsrdset);
12977	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
12978				     dns_rdatatype_none, 0, &nsrdset, NULL);
12979	if (result != ISC_R_SUCCESS) {
12980		goto cleanup3;
12981	}
12982
12983	result = dns_rdataset_first(&nsrdset);
12984	while (result == ISC_R_SUCCESS) {
12985		dns_notify_t *notify = NULL;
12986
12987		dns_rdataset_current(&nsrdset, &rdata);
12988		result = dns_rdata_tostruct(&rdata, &ns, NULL);
12989		RUNTIME_CHECK(result == ISC_R_SUCCESS);
12990		dns_rdata_reset(&rdata);
12991		/*
12992		 * Don't notify the master server unless explicitly
12993		 * configured to do so.
12994		 */
12995		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
12996		    dns_name_compare(&master, &ns.name) == 0)
12997		{
12998			result = dns_rdataset_next(&nsrdset);
12999			continue;
13000		}
13001
13002		if (!loggednotify) {
13003			notify_log(zone, ISC_LOG_INFO,
13004				   "sending notifies (serial %u)", serial);
13005			loggednotify = true;
13006		}
13007
13008		LOCK_ZONE(zone);
13009		isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
13010		UNLOCK_ZONE(zone);
13011		if (isqueued) {
13012			result = dns_rdataset_next(&nsrdset);
13013			continue;
13014		}
13015		result = notify_create(zone->mctx, flags, &notify);
13016		if (result != ISC_R_SUCCESS) {
13017			continue;
13018		}
13019		dns_zone_iattach(zone, &notify->zone);
13020		dns_name_dup(&ns.name, zone->mctx, &notify->ns);
13021		LOCK_ZONE(zone);
13022		ISC_LIST_APPEND(zone->notifies, notify, link);
13023		UNLOCK_ZONE(zone);
13024		notify_find_address(notify);
13025		result = dns_rdataset_next(&nsrdset);
13026	}
13027	dns_rdataset_disassociate(&nsrdset);
13028
13029cleanup3:
13030	if (dns_name_dynamic(&master)) {
13031		dns_name_free(&master, zone->mctx);
13032	}
13033cleanup2:
13034	dns_db_detachnode(zonedb, &node);
13035cleanup1:
13036	dns_db_closeversion(zonedb, &version, false);
13037	dns_db_detach(&zonedb);
13038}
13039
13040/***
13041 *** Private
13042 ***/
13043static isc_result_t
13044create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, dns_name_t *name,
13045	     dns_message_t **messagep) {
13046	dns_message_t *message = NULL;
13047	dns_name_t *qname = NULL;
13048	dns_rdataset_t *qrdataset = NULL;
13049	isc_result_t result;
13050
13051	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
13052
13053	message->opcode = dns_opcode_query;
13054	message->rdclass = zone->rdclass;
13055
13056	result = dns_message_gettempname(message, &qname);
13057	if (result != ISC_R_SUCCESS) {
13058		goto cleanup;
13059	}
13060
13061	result = dns_message_gettemprdataset(message, &qrdataset);
13062	if (result != ISC_R_SUCCESS) {
13063		goto cleanup;
13064	}
13065
13066	/*
13067	 * Make question.
13068	 */
13069	dns_name_clone(name, qname);
13070	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
13071	ISC_LIST_APPEND(qname->list, qrdataset, link);
13072	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
13073
13074	*messagep = message;
13075	return (ISC_R_SUCCESS);
13076
13077cleanup:
13078	if (qname != NULL) {
13079		dns_message_puttempname(message, &qname);
13080	}
13081	if (qrdataset != NULL) {
13082		dns_message_puttemprdataset(message, &qrdataset);
13083	}
13084	dns_message_detach(&message);
13085	return (result);
13086}
13087
13088static isc_result_t
13089add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
13090	bool reqexpire) {
13091	isc_result_t result;
13092	dns_rdataset_t *rdataset = NULL;
13093	dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
13094	int count = 0;
13095
13096	/* Set EDNS options if applicable. */
13097	if (reqnsid) {
13098		INSIST(count < DNS_EDNSOPTIONS);
13099		ednsopts[count].code = DNS_OPT_NSID;
13100		ednsopts[count].length = 0;
13101		ednsopts[count].value = NULL;
13102		count++;
13103	}
13104	if (reqexpire) {
13105		INSIST(count < DNS_EDNSOPTIONS);
13106		ednsopts[count].code = DNS_OPT_EXPIRE;
13107		ednsopts[count].length = 0;
13108		ednsopts[count].value = NULL;
13109		count++;
13110	}
13111	result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
13112				      ednsopts, count);
13113	if (result != ISC_R_SUCCESS) {
13114		return (result);
13115	}
13116
13117	return (dns_message_setopt(message, rdataset));
13118}
13119
13120/*
13121 * Called when stub zone update is finished.
13122 * Update zone refresh, retry, expire values accordingly with
13123 * SOA received from master, sync database to file, restart
13124 * zone management timer.
13125 */
13126static void
13127stub_finish_zone_update(dns_stub_t *stub, isc_time_t now) {
13128	uint32_t refresh, retry, expire;
13129	isc_result_t result;
13130	isc_interval_t i;
13131	unsigned int soacount;
13132	dns_zone_t *zone = stub->zone;
13133
13134	/*
13135	 * Tidy up.
13136	 */
13137	dns_db_closeversion(stub->db, &stub->version, true);
13138	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13139	if (zone->db == NULL) {
13140		zone_attachdb(zone, stub->db);
13141	}
13142	result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL, NULL,
13143				  &refresh, &retry, &expire, NULL, NULL);
13144	if (result == ISC_R_SUCCESS && soacount > 0U) {
13145		zone->refresh = RANGE(refresh, zone->minrefresh,
13146				      zone->maxrefresh);
13147		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
13148		zone->expire = RANGE(expire, zone->refresh + zone->retry,
13149				     DNS_MAX_EXPIRE);
13150		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13151	}
13152	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13153	dns_db_detach(&stub->db);
13154
13155	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13156	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
13157	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
13158	isc_interval_set(&i, zone->expire, 0);
13159	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
13160
13161	if (zone->masterfile != NULL) {
13162		zone_needdump(zone, 0);
13163	}
13164
13165	zone_settimer(zone, &now);
13166}
13167
13168/*
13169 * Process answers for A and AAAA queries when
13170 * resolving nameserver addresses for which glue
13171 * was missing in a previous answer for a NS query.
13172 */
13173static void
13174stub_glue_response_cb(isc_task_t *task, isc_event_t *event) {
13175	const char me[] = "stub_glue_response_cb";
13176	dns_requestevent_t *revent = (dns_requestevent_t *)event;
13177	dns_stub_t *stub = NULL;
13178	dns_message_t *msg = NULL;
13179	dns_zone_t *zone = NULL;
13180	char master[ISC_SOCKADDR_FORMATSIZE];
13181	char source[ISC_SOCKADDR_FORMATSIZE];
13182	uint32_t addr_count, cnamecnt;
13183	isc_result_t result;
13184	isc_time_t now;
13185	struct stub_glue_request *request;
13186	struct stub_cb_args *cb_args;
13187	dns_rdataset_t *addr_rdataset = NULL;
13188	dns_dbnode_t *node = NULL;
13189
13190	UNUSED(task);
13191
13192	request = revent->ev_arg;
13193	cb_args = request->args;
13194	stub = cb_args->stub;
13195	INSIST(DNS_STUB_VALID(stub));
13196
13197	zone = stub->zone;
13198
13199	ENTER;
13200
13201	TIME_NOW(&now);
13202
13203	LOCK_ZONE(zone);
13204
13205	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13206		zone_debuglog(zone, me, 1, "exiting");
13207		goto cleanup;
13208	}
13209
13210	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13211	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13212
13213	if (revent->result != ISC_R_SUCCESS) {
13214		dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
13215					   &zone->sourceaddr, &now);
13216		dns_zone_log(zone, ISC_LOG_INFO,
13217			     "could not refresh stub from master %s"
13218			     " (source %s): %s",
13219			     master, source, dns_result_totext(revent->result));
13220		goto cleanup;
13221	}
13222
13223	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13224	result = dns_request_getresponse(revent->request, msg, 0);
13225	if (result != ISC_R_SUCCESS) {
13226		dns_zone_log(zone, ISC_LOG_INFO,
13227			     "refreshing stub: unable to parse response (%s)",
13228			     isc_result_totext(result));
13229		goto cleanup;
13230	}
13231
13232	/*
13233	 * Unexpected opcode.
13234	 */
13235	if (msg->opcode != dns_opcode_query) {
13236		char opcode[128];
13237		isc_buffer_t rb;
13238
13239		isc_buffer_init(&rb, opcode, sizeof(opcode));
13240		(void)dns_opcode_totext(msg->opcode, &rb);
13241
13242		dns_zone_log(zone, ISC_LOG_INFO,
13243			     "refreshing stub: "
13244			     "unexpected opcode (%.*s) from %s (source %s)",
13245			     (int)rb.used, opcode, master, source);
13246		goto cleanup;
13247	}
13248
13249	/*
13250	 * Unexpected rcode.
13251	 */
13252	if (msg->rcode != dns_rcode_noerror) {
13253		char rcode[128];
13254		isc_buffer_t rb;
13255
13256		isc_buffer_init(&rb, rcode, sizeof(rcode));
13257		(void)dns_rcode_totext(msg->rcode, &rb);
13258
13259		dns_zone_log(zone, ISC_LOG_INFO,
13260			     "refreshing stub: "
13261			     "unexpected rcode (%.*s) from %s (source %s)",
13262			     (int)rb.used, rcode, master, source);
13263		goto cleanup;
13264	}
13265
13266	/*
13267	 * We need complete messages.
13268	 */
13269	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13270		if (dns_request_usedtcp(revent->request)) {
13271			dns_zone_log(zone, ISC_LOG_INFO,
13272				     "refreshing stub: truncated TCP "
13273				     "response from master %s (source %s)",
13274				     master, source);
13275		}
13276		goto cleanup;
13277	}
13278
13279	/*
13280	 * If non-auth log.
13281	 */
13282	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13283		dns_zone_log(zone, ISC_LOG_INFO,
13284			     "refreshing stub: "
13285			     "non-authoritative answer from "
13286			     "master %s (source %s)",
13287			     master, source);
13288		goto cleanup;
13289	}
13290
13291	/*
13292	 * Sanity checks.
13293	 */
13294	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13295	addr_count = message_count(msg, DNS_SECTION_ANSWER,
13296				   request->ipv4 ? dns_rdatatype_a
13297						 : dns_rdatatype_aaaa);
13298
13299	if (cnamecnt != 0) {
13300		dns_zone_log(zone, ISC_LOG_INFO,
13301			     "refreshing stub: unexpected CNAME response "
13302			     "from master %s (source %s)",
13303			     master, source);
13304		goto cleanup;
13305	}
13306
13307	if (addr_count == 0) {
13308		dns_zone_log(zone, ISC_LOG_INFO,
13309			     "refreshing stub: no %s records in response "
13310			     "from master %s (source %s)",
13311			     request->ipv4 ? "A" : "AAAA", master, source);
13312		goto cleanup;
13313	}
13314	/*
13315	 * Extract A or AAAA RRset from message.
13316	 */
13317	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &request->name,
13318				      request->ipv4 ? dns_rdatatype_a
13319						    : dns_rdatatype_aaaa,
13320				      dns_rdatatype_none, NULL, &addr_rdataset);
13321	if (result != ISC_R_SUCCESS) {
13322		if (result != DNS_R_NXDOMAIN && result != DNS_R_NXRRSET) {
13323			char namebuf[DNS_NAME_FORMATSIZE];
13324			dns_name_format(&request->name, namebuf,
13325					sizeof(namebuf));
13326			dns_zone_log(
13327				zone, ISC_LOG_INFO,
13328				"refreshing stub: dns_message_findname(%s/%s) "
13329				"failed (%s)",
13330				namebuf, request->ipv4 ? "A" : "AAAA",
13331				isc_result_totext(result));
13332		}
13333		goto cleanup;
13334	}
13335
13336	result = dns_db_findnode(stub->db, &request->name, true, &node);
13337	if (result != ISC_R_SUCCESS) {
13338		dns_zone_log(zone, ISC_LOG_INFO,
13339			     "refreshing stub: "
13340			     "dns_db_findnode() failed: %s",
13341			     dns_result_totext(result));
13342		goto cleanup;
13343	}
13344
13345	result = dns_db_addrdataset(stub->db, node, stub->version, 0,
13346				    addr_rdataset, 0, NULL);
13347	if (result != ISC_R_SUCCESS) {
13348		dns_zone_log(zone, ISC_LOG_INFO,
13349			     "refreshing stub: "
13350			     "dns_db_addrdataset() failed: %s",
13351			     dns_result_totext(result));
13352	}
13353	dns_db_detachnode(stub->db, &node);
13354
13355cleanup:
13356	if (msg != NULL) {
13357		dns_message_detach(&msg);
13358	}
13359	isc_event_free(&event);
13360	dns_name_free(&request->name, zone->mctx);
13361	dns_request_destroy(&request->request);
13362	isc_mem_put(zone->mctx, request, sizeof(*request));
13363
13364	/* If last request, release all related resources */
13365	if (atomic_fetch_sub_release(&stub->pending_requests, 1) == 1) {
13366		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13367		stub_finish_zone_update(stub, now);
13368		UNLOCK_ZONE(zone);
13369		stub->magic = 0;
13370		dns_zone_idetach(&stub->zone);
13371		INSIST(stub->db == NULL);
13372		INSIST(stub->version == NULL);
13373		isc_mem_put(stub->mctx, stub, sizeof(*stub));
13374	} else {
13375		UNLOCK_ZONE(zone);
13376	}
13377}
13378
13379/*
13380 * Create and send an A or AAAA query to the master
13381 * server of the stub zone given.
13382 */
13383static isc_result_t
13384stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
13385				const dns_name_t *name) {
13386	dns_message_t *message = NULL;
13387	dns_zone_t *zone;
13388	isc_result_t result;
13389	struct stub_glue_request *request;
13390
13391	zone = args->stub->zone;
13392	request = isc_mem_get(zone->mctx, sizeof(*request));
13393	request->request = NULL;
13394	request->args = args;
13395	request->name = (dns_name_t)DNS_NAME_INITEMPTY;
13396	request->ipv4 = ipv4;
13397	dns_name_dup(name, zone->mctx, &request->name);
13398
13399	result = create_query(zone, ipv4 ? dns_rdatatype_a : dns_rdatatype_aaaa,
13400			      &request->name, &message);
13401	INSIST(result == ISC_R_SUCCESS);
13402
13403	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13404		result = add_opt(message, args->udpsize, args->reqnsid, false);
13405		if (result != ISC_R_SUCCESS) {
13406			zone_debuglog(zone, "stub_send_query", 1,
13407				      "unable to add opt record: %s",
13408				      dns_result_totext(result));
13409			goto fail;
13410		}
13411	}
13412
13413	atomic_fetch_add_release(&args->stub->pending_requests, 1);
13414
13415	result = dns_request_createvia(
13416		zone->view->requestmgr, message, &zone->sourceaddr,
13417		&zone->masteraddr, args->dscp, DNS_REQUESTOPT_TCP,
13418		args->tsig_key, args->timeout * 3, args->timeout, 0, zone->task,
13419		stub_glue_response_cb, request, &request->request);
13420
13421	if (result != ISC_R_SUCCESS) {
13422		INSIST(atomic_fetch_sub_release(&args->stub->pending_requests,
13423						1) > 1);
13424		zone_debuglog(zone, "stub_send_query", 1,
13425			      "dns_request_createvia() failed: %s",
13426			      dns_result_totext(result));
13427		goto fail;
13428	}
13429
13430	dns_message_detach(&message);
13431
13432	return (ISC_R_SUCCESS);
13433
13434fail:
13435	dns_name_free(&request->name, zone->mctx);
13436	isc_mem_put(zone->mctx, request, sizeof(*request));
13437
13438	if (message != NULL) {
13439		dns_message_detach(&message);
13440	}
13441
13442	return (result);
13443}
13444
13445static isc_result_t
13446save_nsrrset(dns_message_t *message, dns_name_t *name,
13447	     struct stub_cb_args *cb_args, dns_db_t *db,
13448	     dns_dbversion_t *version) {
13449	dns_rdataset_t *nsrdataset = NULL;
13450	dns_rdataset_t *rdataset = NULL;
13451	dns_dbnode_t *node = NULL;
13452	dns_rdata_ns_t ns;
13453	isc_result_t result;
13454	dns_rdata_t rdata = DNS_RDATA_INIT;
13455	bool has_glue = false;
13456	dns_name_t *ns_name;
13457	/*
13458	 * List of NS entries in answer, keep names that will be used
13459	 * to resolve missing A/AAAA glue for each entry.
13460	 */
13461	dns_namelist_t ns_list;
13462	ISC_LIST_INIT(ns_list);
13463
13464	/*
13465	 * Extract NS RRset from message.
13466	 */
13467	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
13468				      dns_rdatatype_ns, dns_rdatatype_none,
13469				      NULL, &nsrdataset);
13470	if (result != ISC_R_SUCCESS) {
13471		goto done;
13472	}
13473
13474	/*
13475	 * Add NS rdataset.
13476	 */
13477	result = dns_db_findnode(db, name, true, &node);
13478	if (result != ISC_R_SUCCESS) {
13479		goto done;
13480	}
13481	result = dns_db_addrdataset(db, node, version, 0, nsrdataset, 0, NULL);
13482	dns_db_detachnode(db, &node);
13483	if (result != ISC_R_SUCCESS) {
13484		goto done;
13485	}
13486	/*
13487	 * Add glue rdatasets.
13488	 */
13489	for (result = dns_rdataset_first(nsrdataset); result == ISC_R_SUCCESS;
13490	     result = dns_rdataset_next(nsrdataset))
13491	{
13492		dns_rdataset_current(nsrdataset, &rdata);
13493		result = dns_rdata_tostruct(&rdata, &ns, NULL);
13494		RUNTIME_CHECK(result == ISC_R_SUCCESS);
13495		dns_rdata_reset(&rdata);
13496
13497		if (!dns_name_issubdomain(&ns.name, name)) {
13498			continue;
13499		}
13500		rdataset = NULL;
13501		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
13502					      &ns.name, dns_rdatatype_aaaa,
13503					      dns_rdatatype_none, NULL,
13504					      &rdataset);
13505		if (result == ISC_R_SUCCESS) {
13506			has_glue = true;
13507			result = dns_db_findnode(db, &ns.name, true, &node);
13508			if (result != ISC_R_SUCCESS) {
13509				goto done;
13510			}
13511			result = dns_db_addrdataset(db, node, version, 0,
13512						    rdataset, 0, NULL);
13513			dns_db_detachnode(db, &node);
13514			if (result != ISC_R_SUCCESS) {
13515				goto done;
13516			}
13517		}
13518
13519		rdataset = NULL;
13520		result = dns_message_findname(
13521			message, DNS_SECTION_ADDITIONAL, &ns.name,
13522			dns_rdatatype_a, dns_rdatatype_none, NULL, &rdataset);
13523		if (result == ISC_R_SUCCESS) {
13524			has_glue = true;
13525			result = dns_db_findnode(db, &ns.name, true, &node);
13526			if (result != ISC_R_SUCCESS) {
13527				goto done;
13528			}
13529			result = dns_db_addrdataset(db, node, version, 0,
13530						    rdataset, 0, NULL);
13531			dns_db_detachnode(db, &node);
13532			if (result != ISC_R_SUCCESS) {
13533				goto done;
13534			}
13535		}
13536
13537		/*
13538		 * If no glue is found so far, we add the name to the list to
13539		 * resolve the A/AAAA glue later. If any glue is found in any
13540		 * iteration step, this list will be discarded and only the glue
13541		 * provided in this message will be used.
13542		 */
13543		if (!has_glue && dns_name_issubdomain(&ns.name, name)) {
13544			dns_name_t *tmp_name;
13545			tmp_name = isc_mem_get(cb_args->stub->mctx,
13546					       sizeof(*tmp_name));
13547			dns_name_init(tmp_name, NULL);
13548			dns_name_dup(&ns.name, cb_args->stub->mctx, tmp_name);
13549			ISC_LIST_APPEND(ns_list, tmp_name, link);
13550		}
13551	}
13552
13553	if (result != ISC_R_NOMORE) {
13554		goto done;
13555	}
13556
13557	/*
13558	 * If no glue records were found, we attempt to resolve A/AAAA
13559	 * for each NS entry found in the answer.
13560	 */
13561	if (!has_glue) {
13562		for (ns_name = ISC_LIST_HEAD(ns_list); ns_name != NULL;
13563		     ns_name = ISC_LIST_NEXT(ns_name, link))
13564		{
13565			/*
13566			 * Resolve NS IPv4 address/A.
13567			 */
13568			result = stub_request_nameserver_address(cb_args, true,
13569								 ns_name);
13570			if (result != ISC_R_SUCCESS) {
13571				goto done;
13572			}
13573			/*
13574			 * Resolve NS IPv6 address/AAAA.
13575			 */
13576			result = stub_request_nameserver_address(cb_args, false,
13577								 ns_name);
13578			if (result != ISC_R_SUCCESS) {
13579				goto done;
13580			}
13581		}
13582	}
13583
13584	result = ISC_R_SUCCESS;
13585
13586done:
13587	while ((ns_name = ISC_LIST_HEAD(ns_list)) != NULL) {
13588		ISC_LIST_UNLINK(ns_list, ns_name, link);
13589		dns_name_free(ns_name, cb_args->stub->mctx);
13590		isc_mem_put(cb_args->stub->mctx, ns_name, sizeof(*ns_name));
13591	}
13592	return (result);
13593}
13594
13595static void
13596stub_callback(isc_task_t *task, isc_event_t *event) {
13597	const char me[] = "stub_callback";
13598	dns_requestevent_t *revent = (dns_requestevent_t *)event;
13599	dns_stub_t *stub = NULL;
13600	dns_message_t *msg = NULL;
13601	dns_zone_t *zone = NULL;
13602	char master[ISC_SOCKADDR_FORMATSIZE];
13603	char source[ISC_SOCKADDR_FORMATSIZE];
13604	uint32_t nscnt, cnamecnt;
13605	isc_result_t result;
13606	isc_time_t now;
13607	bool exiting = false;
13608	unsigned int j;
13609	struct stub_cb_args *cb_args;
13610
13611	cb_args = revent->ev_arg;
13612	stub = cb_args->stub;
13613	INSIST(DNS_STUB_VALID(stub));
13614
13615	UNUSED(task);
13616
13617	zone = stub->zone;
13618
13619	ENTER;
13620
13621	TIME_NOW(&now);
13622
13623	LOCK_ZONE(zone);
13624
13625	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13626		zone_debuglog(zone, me, 1, "exiting");
13627		exiting = true;
13628		goto next_master;
13629	}
13630
13631	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13632	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13633
13634	if (revent->result != ISC_R_SUCCESS) {
13635		if (revent->result == ISC_R_TIMEDOUT &&
13636		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS))
13637		{
13638			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13639			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13640				     "refreshing stub: timeout retrying "
13641				     " without EDNS master %s (source %s)",
13642				     master, source);
13643			goto same_master;
13644		}
13645		dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
13646					   &zone->sourceaddr, &now);
13647		dns_zone_log(zone, ISC_LOG_INFO,
13648			     "could not refresh stub from master %s"
13649			     " (source %s): %s",
13650			     master, source, dns_result_totext(revent->result));
13651		goto next_master;
13652	}
13653
13654	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13655
13656	result = dns_request_getresponse(revent->request, msg, 0);
13657	if (result != ISC_R_SUCCESS) {
13658		goto next_master;
13659	}
13660
13661	/*
13662	 * Unexpected opcode.
13663	 */
13664	if (msg->opcode != dns_opcode_query) {
13665		char opcode[128];
13666		isc_buffer_t rb;
13667
13668		isc_buffer_init(&rb, opcode, sizeof(opcode));
13669		(void)dns_opcode_totext(msg->opcode, &rb);
13670
13671		dns_zone_log(zone, ISC_LOG_INFO,
13672			     "refreshing stub: "
13673			     "unexpected opcode (%.*s) from %s (source %s)",
13674			     (int)rb.used, opcode, master, source);
13675		goto next_master;
13676	}
13677
13678	/*
13679	 * Unexpected rcode.
13680	 */
13681	if (msg->rcode != dns_rcode_noerror) {
13682		char rcode[128];
13683		isc_buffer_t rb;
13684
13685		isc_buffer_init(&rb, rcode, sizeof(rcode));
13686		(void)dns_rcode_totext(msg->rcode, &rb);
13687
13688		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13689		    (msg->rcode == dns_rcode_servfail ||
13690		     msg->rcode == dns_rcode_notimp ||
13691		     msg->rcode == dns_rcode_formerr))
13692		{
13693			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13694				     "refreshing stub: rcode (%.*s) retrying "
13695				     "without EDNS master %s (source %s)",
13696				     (int)rb.used, rcode, master, source);
13697			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13698			goto same_master;
13699		}
13700
13701		dns_zone_log(zone, ISC_LOG_INFO,
13702			     "refreshing stub: "
13703			     "unexpected rcode (%.*s) from %s (source %s)",
13704			     (int)rb.used, rcode, master, source);
13705		goto next_master;
13706	}
13707
13708	/*
13709	 * We need complete messages.
13710	 */
13711	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13712		if (dns_request_usedtcp(revent->request)) {
13713			dns_zone_log(zone, ISC_LOG_INFO,
13714				     "refreshing stub: truncated TCP "
13715				     "response from master %s (source %s)",
13716				     master, source);
13717			goto next_master;
13718		}
13719		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
13720		goto same_master;
13721	}
13722
13723	/*
13724	 * If non-auth log and next master.
13725	 */
13726	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13727		dns_zone_log(zone, ISC_LOG_INFO,
13728			     "refreshing stub: "
13729			     "non-authoritative answer from "
13730			     "master %s (source %s)",
13731			     master, source);
13732		goto next_master;
13733	}
13734
13735	/*
13736	 * Sanity checks.
13737	 */
13738	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13739	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
13740
13741	if (cnamecnt != 0) {
13742		dns_zone_log(zone, ISC_LOG_INFO,
13743			     "refreshing stub: unexpected CNAME response "
13744			     "from master %s (source %s)",
13745			     master, source);
13746		goto next_master;
13747	}
13748
13749	if (nscnt == 0) {
13750		dns_zone_log(zone, ISC_LOG_INFO,
13751			     "refreshing stub: no NS records in response "
13752			     "from master %s (source %s)",
13753			     master, source);
13754		goto next_master;
13755	}
13756
13757	atomic_fetch_add(&stub->pending_requests, 1);
13758
13759	/*
13760	 * Save answer.
13761	 */
13762	result = save_nsrrset(msg, &zone->origin, cb_args, stub->db,
13763			      stub->version);
13764	if (result != ISC_R_SUCCESS) {
13765		dns_zone_log(zone, ISC_LOG_INFO,
13766			     "refreshing stub: unable to save NS records "
13767			     "from master %s (source %s)",
13768			     master, source);
13769		goto next_master;
13770	}
13771
13772	dns_message_detach(&msg);
13773	isc_event_free(&event);
13774	dns_request_destroy(&zone->request);
13775
13776	/*
13777	 * Check to see if there are no outstanding requests and
13778	 * finish off if that is so.
13779	 */
13780	if (atomic_fetch_sub(&stub->pending_requests, 1) == 1) {
13781		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13782		stub_finish_zone_update(stub, now);
13783		goto free_stub;
13784	}
13785
13786	UNLOCK_ZONE(zone);
13787	return;
13788
13789next_master:
13790	isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13791	if (stub->version != NULL) {
13792		dns_db_closeversion(stub->db, &stub->version, false);
13793	}
13794	if (stub->db != NULL) {
13795		dns_db_detach(&stub->db);
13796	}
13797	if (msg != NULL) {
13798		dns_message_detach(&msg);
13799	}
13800	isc_event_free(&event);
13801	dns_request_destroy(&zone->request);
13802	/*
13803	 * Skip to next failed / untried master.
13804	 */
13805	do {
13806		zone->curmaster++;
13807	} while (zone->curmaster < zone->masterscnt &&
13808		 zone->mastersok[zone->curmaster]);
13809	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
13810	if (exiting || zone->curmaster >= zone->masterscnt) {
13811		bool done = true;
13812		if (!exiting &&
13813		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13814		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
13815		{
13816			/*
13817			 * Did we get a good answer from all the primaries?
13818			 */
13819			for (j = 0; j < zone->masterscnt; j++) {
13820				if (!zone->mastersok[j]) {
13821					{
13822						done = false;
13823						break;
13824					}
13825				}
13826			}
13827		} else {
13828			done = true;
13829		}
13830		if (!done) {
13831			zone->curmaster = 0;
13832			/*
13833			 * Find the next failed master.
13834			 */
13835			while (zone->curmaster < zone->masterscnt &&
13836			       zone->mastersok[zone->curmaster])
13837			{
13838				zone->curmaster++;
13839			}
13840			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13841		} else {
13842			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13843
13844			zone_settimer(zone, &now);
13845			goto free_stub;
13846		}
13847	}
13848	queue_soa_query(zone);
13849	goto free_stub;
13850
13851same_master:
13852	isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13853	if (msg != NULL) {
13854		dns_message_detach(&msg);
13855	}
13856	isc_event_free(&event);
13857	dns_request_destroy(&zone->request);
13858	ns_query(zone, NULL, stub);
13859	UNLOCK_ZONE(zone);
13860	goto done;
13861
13862free_stub:
13863	UNLOCK_ZONE(zone);
13864	stub->magic = 0;
13865	dns_zone_idetach(&stub->zone);
13866	INSIST(stub->db == NULL);
13867	INSIST(stub->version == NULL);
13868	isc_mem_put(stub->mctx, stub, sizeof(*stub));
13869
13870done:
13871	INSIST(event == NULL);
13872	return;
13873}
13874
13875/*
13876 * Get the EDNS EXPIRE option from the response and if it exists trim
13877 * expire to be not more than it.
13878 */
13879static void
13880get_edns_expire(dns_zone_t *zone, dns_message_t *message, uint32_t *expirep) {
13881	isc_result_t result;
13882	uint32_t expire;
13883	dns_rdata_t rdata = DNS_RDATA_INIT;
13884	isc_buffer_t optbuf;
13885	uint16_t optcode;
13886	uint16_t optlen;
13887
13888	REQUIRE(expirep != NULL);
13889	REQUIRE(message != NULL);
13890
13891	if (message->opt == NULL) {
13892		return;
13893	}
13894
13895	result = dns_rdataset_first(message->opt);
13896	if (result == ISC_R_SUCCESS) {
13897		dns_rdataset_current(message->opt, &rdata);
13898		isc_buffer_init(&optbuf, rdata.data, rdata.length);
13899		isc_buffer_add(&optbuf, rdata.length);
13900		while (isc_buffer_remaininglength(&optbuf) >= 4) {
13901			optcode = isc_buffer_getuint16(&optbuf);
13902			optlen = isc_buffer_getuint16(&optbuf);
13903			/*
13904			 * A EDNS EXPIRE response has a length of 4.
13905			 */
13906			if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
13907				isc_buffer_forward(&optbuf, optlen);
13908				continue;
13909			}
13910			expire = isc_buffer_getuint32(&optbuf);
13911			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13912				     "got EDNS EXPIRE of %u", expire);
13913			/*
13914			 * Trim *expirep?
13915			 */
13916			if (expire < *expirep) {
13917				*expirep = expire;
13918			}
13919			break;
13920		}
13921	}
13922}
13923
13924/*
13925 * Set the file modification time zone->expire seconds before expiretime.
13926 */
13927static void
13928setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
13929	isc_result_t result;
13930	isc_time_t when;
13931	isc_interval_t i;
13932
13933	isc_interval_set(&i, zone->expire, 0);
13934	result = isc_time_subtract(expiretime, &i, &when);
13935	if (result != ISC_R_SUCCESS) {
13936		return;
13937	}
13938
13939	result = ISC_R_FAILURE;
13940	if (zone->journal != NULL) {
13941		result = isc_file_settime(zone->journal, &when);
13942	}
13943	if (result == ISC_R_SUCCESS &&
13944	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13945	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
13946	{
13947		result = isc_file_settime(zone->masterfile, &when);
13948	} else if (result != ISC_R_SUCCESS) {
13949		result = isc_file_settime(zone->masterfile, &when);
13950	}
13951
13952	/*
13953	 * Someone removed the file from underneath us!
13954	 */
13955	if (result == ISC_R_FILENOTFOUND) {
13956		zone_needdump(zone, DNS_DUMP_DELAY);
13957	} else if (result != ISC_R_SUCCESS) {
13958		dns_zone_log(zone, ISC_LOG_ERROR,
13959			     "refresh: could not set "
13960			     "file modification time of '%s': %s",
13961			     zone->masterfile, dns_result_totext(result));
13962	}
13963}
13964
13965/*
13966 * An SOA query has finished (successfully or not).
13967 */
13968static void
13969refresh_callback(isc_task_t *task, isc_event_t *event) {
13970	const char me[] = "refresh_callback";
13971	dns_requestevent_t *revent = (dns_requestevent_t *)event;
13972	dns_zone_t *zone;
13973	dns_message_t *msg = NULL;
13974	uint32_t soacnt, cnamecnt, soacount, nscount;
13975	isc_time_t now;
13976	char master[ISC_SOCKADDR_FORMATSIZE];
13977	char source[ISC_SOCKADDR_FORMATSIZE];
13978	dns_rdataset_t *rdataset = NULL;
13979	dns_rdata_t rdata = DNS_RDATA_INIT;
13980	dns_rdata_soa_t soa;
13981	isc_result_t result;
13982	uint32_t serial, oldserial = 0;
13983	unsigned int j;
13984	bool do_queue_xfrin = false;
13985
13986	zone = revent->ev_arg;
13987	INSIST(DNS_ZONE_VALID(zone));
13988
13989	UNUSED(task);
13990
13991	ENTER;
13992
13993	TIME_NOW(&now);
13994
13995	LOCK_ZONE(zone);
13996
13997	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13998		isc_event_free(&event);
13999		dns_request_destroy(&zone->request);
14000		goto detach;
14001	}
14002
14003	/*
14004	 * if timeout log and next master;
14005	 */
14006
14007	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
14008	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14009
14010	if (revent->result != ISC_R_SUCCESS) {
14011		if (revent->result == ISC_R_TIMEDOUT &&
14012		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS))
14013		{
14014			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14015			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14016				     "refresh: timeout retrying without EDNS "
14017				     "master %s (source %s)",
14018				     master, source);
14019			goto same_master;
14020		}
14021		if (revent->result == ISC_R_TIMEDOUT &&
14022		    !dns_request_usedtcp(revent->request))
14023		{
14024			dns_zone_log(zone, ISC_LOG_INFO,
14025				     "refresh: retry limit for "
14026				     "master %s exceeded (source %s)",
14027				     master, source);
14028			/* Try with slave with TCP. */
14029			if ((zone->type == dns_zone_secondary ||
14030			     zone->type == dns_zone_mirror ||
14031			     zone->type == dns_zone_redirect) &&
14032			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
14033			{
14034				if (!dns_zonemgr_unreachable(
14035					    zone->zmgr, &zone->masteraddr,
14036					    &zone->sourceaddr, &now))
14037				{
14038					DNS_ZONE_SETFLAG(
14039						zone,
14040						DNS_ZONEFLG_SOABEFOREAXFR);
14041					goto tcp_transfer;
14042				}
14043				dns_zone_log(zone, ISC_LOG_DEBUG(1),
14044					     "refresh: skipped tcp fallback "
14045					     "as master %s (source %s) is "
14046					     "unreachable (cached)",
14047					     master, source);
14048			}
14049		} else {
14050			dns_zone_log(zone, ISC_LOG_INFO,
14051				     "refresh: failure trying master "
14052				     "%s (source %s): %s",
14053				     master, source,
14054				     dns_result_totext(revent->result));
14055		}
14056		goto next_master;
14057	}
14058
14059	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
14060	result = dns_request_getresponse(revent->request, msg, 0);
14061	if (result != ISC_R_SUCCESS) {
14062		dns_zone_log(zone, ISC_LOG_INFO,
14063			     "refresh: failure trying master "
14064			     "%s (source %s): %s",
14065			     master, source, dns_result_totext(result));
14066		goto next_master;
14067	}
14068
14069	/*
14070	 * Unexpected opcode.
14071	 */
14072	if (msg->opcode != dns_opcode_query) {
14073		char opcode[128];
14074		isc_buffer_t rb;
14075
14076		isc_buffer_init(&rb, opcode, sizeof(opcode));
14077		(void)dns_opcode_totext(msg->opcode, &rb);
14078
14079		dns_zone_log(zone, ISC_LOG_INFO,
14080			     "refresh: "
14081			     "unexpected opcode (%.*s) from %s (source %s)",
14082			     (int)rb.used, opcode, master, source);
14083		goto next_master;
14084	}
14085
14086	/*
14087	 * Unexpected rcode.
14088	 */
14089	if (msg->rcode != dns_rcode_noerror) {
14090		char rcode[128];
14091		isc_buffer_t rb;
14092
14093		isc_buffer_init(&rb, rcode, sizeof(rcode));
14094		(void)dns_rcode_totext(msg->rcode, &rb);
14095
14096		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14097		    (msg->rcode == dns_rcode_servfail ||
14098		     msg->rcode == dns_rcode_notimp ||
14099		     msg->rcode == dns_rcode_formerr))
14100		{
14101			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14102				     "refresh: rcode (%.*s) retrying without "
14103				     "EDNS master %s (source %s)",
14104				     (int)rb.used, rcode, master, source);
14105			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14106			goto same_master;
14107		}
14108		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14109		    msg->rcode == dns_rcode_badvers)
14110		{
14111			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14112				     "refresh: rcode (%.*s) retrying without "
14113				     "EDNS EXPIRE OPTION master %s (source %s)",
14114				     (int)rb.used, rcode, master, source);
14115			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14116			goto same_master;
14117		}
14118		dns_zone_log(zone, ISC_LOG_INFO,
14119			     "refresh: unexpected rcode (%.*s) from "
14120			     "master %s (source %s)",
14121			     (int)rb.used, rcode, master, source);
14122		/*
14123		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
14124		 */
14125		if (msg->rcode == dns_rcode_refused &&
14126		    (zone->type == dns_zone_secondary ||
14127		     zone->type == dns_zone_mirror ||
14128		     zone->type == dns_zone_redirect))
14129		{
14130			goto tcp_transfer;
14131		}
14132		goto next_master;
14133	}
14134
14135	/*
14136	 * If truncated punt to zone transfer which will query again.
14137	 */
14138	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
14139		if (zone->type == dns_zone_secondary ||
14140		    zone->type == dns_zone_mirror ||
14141		    zone->type == dns_zone_redirect)
14142		{
14143			dns_zone_log(zone, ISC_LOG_INFO,
14144				     "refresh: truncated UDP answer, "
14145				     "initiating TCP zone xfer "
14146				     "for master %s (source %s)",
14147				     master, source);
14148			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14149			goto tcp_transfer;
14150		} else {
14151			INSIST(zone->type == dns_zone_stub);
14152			if (dns_request_usedtcp(revent->request)) {
14153				dns_zone_log(zone, ISC_LOG_INFO,
14154					     "refresh: truncated TCP response "
14155					     "from master %s (source %s)",
14156					     master, source);
14157				goto next_master;
14158			}
14159			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
14160			goto same_master;
14161		}
14162	}
14163
14164	/*
14165	 * if non-auth log and next master;
14166	 */
14167	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
14168		dns_zone_log(zone, ISC_LOG_INFO,
14169			     "refresh: non-authoritative answer from "
14170			     "master %s (source %s)",
14171			     master, source);
14172		goto next_master;
14173	}
14174
14175	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
14176	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
14177	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
14178	soacount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_soa);
14179
14180	/*
14181	 * There should not be a CNAME record at top of zone.
14182	 */
14183	if (cnamecnt != 0) {
14184		dns_zone_log(zone, ISC_LOG_INFO,
14185			     "refresh: CNAME at top of zone "
14186			     "in master %s (source %s)",
14187			     master, source);
14188		goto next_master;
14189	}
14190
14191	/*
14192	 * if referral log and next master;
14193	 */
14194	if (soacnt == 0 && soacount == 0 && nscount != 0) {
14195		dns_zone_log(zone, ISC_LOG_INFO,
14196			     "refresh: referral response "
14197			     "from master %s (source %s)",
14198			     master, source);
14199		goto next_master;
14200	}
14201
14202	/*
14203	 * if nodata log and next master;
14204	 */
14205	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
14206		dns_zone_log(zone, ISC_LOG_INFO,
14207			     "refresh: NODATA response "
14208			     "from master %s (source %s)",
14209			     master, source);
14210		goto next_master;
14211	}
14212
14213	/*
14214	 * Only one soa at top of zone.
14215	 */
14216	if (soacnt != 1) {
14217		dns_zone_log(zone, ISC_LOG_INFO,
14218			     "refresh: answer SOA count (%d) != 1 "
14219			     "from master %s (source %s)",
14220			     soacnt, master, source);
14221		goto next_master;
14222	}
14223
14224	/*
14225	 * Extract serial
14226	 */
14227	rdataset = NULL;
14228	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
14229				      dns_rdatatype_soa, dns_rdatatype_none,
14230				      NULL, &rdataset);
14231	if (result != ISC_R_SUCCESS) {
14232		dns_zone_log(zone, ISC_LOG_INFO,
14233			     "refresh: unable to get SOA record "
14234			     "from master %s (source %s)",
14235			     master, source);
14236		goto next_master;
14237	}
14238
14239	result = dns_rdataset_first(rdataset);
14240	if (result != ISC_R_SUCCESS) {
14241		dns_zone_log(zone, ISC_LOG_INFO,
14242			     "refresh: dns_rdataset_first() failed");
14243		goto next_master;
14244	}
14245
14246	dns_rdataset_current(rdataset, &rdata);
14247	result = dns_rdata_tostruct(&rdata, &soa, NULL);
14248	RUNTIME_CHECK(result == ISC_R_SUCCESS);
14249
14250	serial = soa.serial;
14251	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
14252		unsigned int dbsoacount;
14253		result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
14254					  NULL, &oldserial, NULL, NULL, NULL,
14255					  NULL, NULL);
14256		RUNTIME_CHECK(result == ISC_R_SUCCESS);
14257		RUNTIME_CHECK(dbsoacount > 0U);
14258		zone_debuglog(zone, me, 1, "serial: new %u, old %u", serial,
14259			      oldserial);
14260	} else {
14261		zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
14262			      serial);
14263	}
14264
14265	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
14266	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
14267	    isc_serial_gt(serial, oldserial))
14268	{
14269		if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
14270					    &zone->sourceaddr, &now))
14271		{
14272			dns_zone_log(zone, ISC_LOG_INFO,
14273				     "refresh: skipping %s as master %s "
14274				     "(source %s) is unreachable (cached)",
14275				     (zone->type == dns_zone_secondary ||
14276				      zone->type == dns_zone_mirror ||
14277				      zone->type == dns_zone_redirect)
14278					     ? "zone transfer"
14279					     : "NS query",
14280				     master, source);
14281			goto next_master;
14282		}
14283	tcp_transfer:
14284		isc_event_free(&event);
14285		dns_request_destroy(&zone->request);
14286		if (zone->type == dns_zone_secondary ||
14287		    zone->type == dns_zone_mirror ||
14288		    zone->type == dns_zone_redirect)
14289		{
14290			do_queue_xfrin = true;
14291		} else {
14292			INSIST(zone->type == dns_zone_stub);
14293			ns_query(zone, rdataset, NULL);
14294		}
14295		if (msg != NULL) {
14296			dns_message_detach(&msg);
14297		}
14298	} else if (isc_serial_eq(soa.serial, oldserial)) {
14299		isc_time_t expiretime;
14300		uint32_t expire;
14301
14302		/*
14303		 * Compute the new expire time based on this response.
14304		 */
14305		expire = zone->expire;
14306		get_edns_expire(zone, msg, &expire);
14307		DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
14308
14309		/*
14310		 * Has the expire time improved?
14311		 */
14312		if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
14313			zone->expiretime = expiretime;
14314			if (zone->masterfile != NULL) {
14315				setmodtime(zone, &expiretime);
14316			}
14317		}
14318
14319		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
14320		zone->mastersok[zone->curmaster] = true;
14321		goto next_master;
14322	} else {
14323		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) {
14324			dns_zone_log(zone, ISC_LOG_INFO,
14325				     "serial number (%u) "
14326				     "received from master %s < ours (%u)",
14327				     soa.serial, master, oldserial);
14328		} else {
14329			zone_debuglog(zone, me, 1, "ahead");
14330		}
14331		zone->mastersok[zone->curmaster] = true;
14332		goto next_master;
14333	}
14334	if (msg != NULL) {
14335		dns_message_detach(&msg);
14336	}
14337	goto detach;
14338
14339next_master:
14340	if (msg != NULL) {
14341		dns_message_detach(&msg);
14342	}
14343	isc_event_free(&event);
14344	dns_request_destroy(&zone->request);
14345	/*
14346	 * Skip to next failed / untried master.
14347	 */
14348	do {
14349		zone->curmaster++;
14350	} while (zone->curmaster < zone->masterscnt &&
14351		 zone->mastersok[zone->curmaster]);
14352	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
14353	if (zone->curmaster >= zone->masterscnt) {
14354		bool done = true;
14355		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
14356		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
14357		{
14358			/*
14359			 * Did we get a good answer from all the primaries?
14360			 */
14361			for (j = 0; j < zone->masterscnt; j++) {
14362				if (!zone->mastersok[j]) {
14363					{
14364						done = false;
14365						break;
14366					}
14367				}
14368			}
14369		} else {
14370			done = true;
14371		}
14372		if (!done) {
14373			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14374			zone->curmaster = 0;
14375			/*
14376			 * Find the next failed master.
14377			 */
14378			while (zone->curmaster < zone->masterscnt &&
14379			       zone->mastersok[zone->curmaster])
14380			{
14381				zone->curmaster++;
14382			}
14383			goto requeue;
14384		}
14385		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14386		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
14387			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
14388			zone->refreshtime = now;
14389		}
14390		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14391		zone_settimer(zone, &now);
14392		goto detach;
14393	}
14394
14395requeue:
14396	queue_soa_query(zone);
14397	goto detach;
14398
14399same_master:
14400	if (msg != NULL) {
14401		dns_message_detach(&msg);
14402	}
14403	isc_event_free(&event);
14404	dns_request_destroy(&zone->request);
14405	queue_soa_query(zone);
14406
14407detach:
14408	UNLOCK_ZONE(zone);
14409	if (do_queue_xfrin) {
14410		queue_xfrin(zone);
14411	}
14412	dns_zone_idetach(&zone);
14413	return;
14414}
14415
14416static void
14417queue_soa_query(dns_zone_t *zone) {
14418	const char me[] = "queue_soa_query";
14419	isc_event_t *e;
14420	dns_zone_t *dummy = NULL;
14421	isc_result_t result;
14422
14423	ENTER;
14424	/*
14425	 * Locked by caller
14426	 */
14427	REQUIRE(LOCKED_ZONE(zone));
14428
14429	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14430		cancel_refresh(zone);
14431		return;
14432	}
14433
14434	e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE, soa_query,
14435			       zone, sizeof(isc_event_t));
14436
14437	/*
14438	 * Attach so that we won't clean up
14439	 * until the event is delivered.
14440	 */
14441	zone_iattach(zone, &dummy);
14442
14443	e->ev_arg = zone;
14444	e->ev_sender = NULL;
14445	result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
14446	if (result != ISC_R_SUCCESS) {
14447		zone_idetach(&dummy);
14448		isc_event_free(&e);
14449		cancel_refresh(zone);
14450	}
14451}
14452
14453static void
14454soa_query(isc_task_t *task, isc_event_t *event) {
14455	const char me[] = "soa_query";
14456	isc_result_t result = ISC_R_FAILURE;
14457	dns_message_t *message = NULL;
14458	dns_zone_t *zone = event->ev_arg;
14459	dns_zone_t *dummy = NULL;
14460	isc_netaddr_t masterip;
14461	dns_tsigkey_t *key = NULL;
14462	uint32_t options;
14463	bool cancel = true;
14464	int timeout;
14465	bool have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
14466	uint16_t udpsize = SEND_BUFFER_SIZE;
14467	isc_dscp_t dscp = -1;
14468
14469	REQUIRE(DNS_ZONE_VALID(zone));
14470
14471	UNUSED(task);
14472
14473	ENTER;
14474
14475	LOCK_ZONE(zone);
14476	if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
14477	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
14478	    zone->view->requestmgr == NULL)
14479	{
14480		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14481			cancel = false;
14482		}
14483		goto cleanup;
14484	}
14485
14486again:
14487	result = create_query(zone, dns_rdatatype_soa, &zone->origin, &message);
14488	if (result != ISC_R_SUCCESS) {
14489		goto cleanup;
14490	}
14491
14492	INSIST(zone->masterscnt > 0);
14493	INSIST(zone->curmaster < zone->masterscnt);
14494
14495	zone->masteraddr = zone->masters[zone->curmaster];
14496
14497	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14498	/*
14499	 * First, look for a tsig key in the master statement, then
14500	 * try for a server key.
14501	 */
14502	if ((zone->masterkeynames != NULL) &&
14503	    (zone->masterkeynames[zone->curmaster] != NULL))
14504	{
14505		dns_view_t *view = dns_zone_getview(zone);
14506		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14507		result = dns_view_gettsig(view, keyname, &key);
14508		if (result != ISC_R_SUCCESS) {
14509			char namebuf[DNS_NAME_FORMATSIZE];
14510			dns_name_format(keyname, namebuf, sizeof(namebuf));
14511			dns_zone_log(zone, ISC_LOG_ERROR,
14512				     "unable to find key: %s", namebuf);
14513			goto skip_master;
14514		}
14515	}
14516	if (key == NULL) {
14517		result = dns_view_getpeertsig(zone->view, &masterip, &key);
14518		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14519			char addrbuf[ISC_NETADDR_FORMATSIZE];
14520			isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
14521			dns_zone_log(zone, ISC_LOG_ERROR,
14522				     "unable to find TSIG key for %s", addrbuf);
14523			goto skip_master;
14524		}
14525	}
14526
14527	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? DNS_REQUESTOPT_TCP
14528							 : 0;
14529	have_xfrsource = have_xfrdscp = false;
14530	reqnsid = zone->view->requestnsid;
14531	reqexpire = zone->requestexpire;
14532	if (zone->view->peers != NULL) {
14533		dns_peer_t *peer = NULL;
14534		bool edns, usetcp;
14535		result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip,
14536						 &peer);
14537		if (result == ISC_R_SUCCESS) {
14538			result = dns_peer_getsupportedns(peer, &edns);
14539			if (result == ISC_R_SUCCESS && !edns) {
14540				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14541			}
14542			result = dns_peer_gettransfersource(peer,
14543							    &zone->sourceaddr);
14544			if (result == ISC_R_SUCCESS) {
14545				have_xfrsource = true;
14546			}
14547			(void)dns_peer_gettransferdscp(peer, &dscp);
14548			if (dscp != -1) {
14549				have_xfrdscp = true;
14550			}
14551			if (zone->view->resolver != NULL) {
14552				udpsize = dns_resolver_getudpsize(
14553					zone->view->resolver);
14554			}
14555			(void)dns_peer_getudpsize(peer, &udpsize);
14556			(void)dns_peer_getrequestnsid(peer, &reqnsid);
14557			(void)dns_peer_getrequestexpire(peer, &reqexpire);
14558			result = dns_peer_getforcetcp(peer, &usetcp);
14559			if (result == ISC_R_SUCCESS && usetcp) {
14560				options |= DNS_REQUESTOPT_TCP;
14561			}
14562		}
14563	}
14564
14565	switch (isc_sockaddr_pf(&zone->masteraddr)) {
14566	case PF_INET:
14567		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14568			if (isc_sockaddr_equal(&zone->altxfrsource4,
14569					       &zone->xfrsource4))
14570			{
14571				goto skip_master;
14572			}
14573			zone->sourceaddr = zone->altxfrsource4;
14574			if (!have_xfrdscp) {
14575				dscp = zone->altxfrsource4dscp;
14576			}
14577		} else if (!have_xfrsource) {
14578			zone->sourceaddr = zone->xfrsource4;
14579			if (!have_xfrdscp) {
14580				dscp = zone->xfrsource4dscp;
14581			}
14582		}
14583		break;
14584	case PF_INET6:
14585		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14586			if (isc_sockaddr_equal(&zone->altxfrsource6,
14587					       &zone->xfrsource6))
14588			{
14589				goto skip_master;
14590			}
14591			zone->sourceaddr = zone->altxfrsource6;
14592			if (!have_xfrdscp) {
14593				dscp = zone->altxfrsource6dscp;
14594			}
14595		} else if (!have_xfrsource) {
14596			zone->sourceaddr = zone->xfrsource6;
14597			if (!have_xfrdscp) {
14598				dscp = zone->xfrsource6dscp;
14599			}
14600		}
14601		break;
14602	default:
14603		result = ISC_R_NOTIMPLEMENTED;
14604		goto cleanup;
14605	}
14606
14607	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14608		result = add_opt(message, udpsize, reqnsid, reqexpire);
14609		if (result != ISC_R_SUCCESS) {
14610			zone_debuglog(zone, me, 1,
14611				      "unable to add opt record: %s",
14612				      dns_result_totext(result));
14613		}
14614	}
14615
14616	zone_iattach(zone, &dummy);
14617	timeout = 15;
14618	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14619		timeout = 30;
14620	}
14621	result = dns_request_createvia(
14622		zone->view->requestmgr, message, &zone->sourceaddr,
14623		&zone->masteraddr, dscp, options, key, timeout * 3, timeout, 0,
14624		zone->task, refresh_callback, zone, &zone->request);
14625	if (result != ISC_R_SUCCESS) {
14626		zone_idetach(&dummy);
14627		zone_debuglog(zone, me, 1,
14628			      "dns_request_createvia4() failed: %s",
14629			      dns_result_totext(result));
14630		goto skip_master;
14631	} else {
14632		if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET) {
14633			inc_stats(zone, dns_zonestatscounter_soaoutv4);
14634		} else {
14635			inc_stats(zone, dns_zonestatscounter_soaoutv6);
14636		}
14637	}
14638	cancel = false;
14639
14640cleanup:
14641	if (key != NULL) {
14642		dns_tsigkey_detach(&key);
14643	}
14644	if (result != ISC_R_SUCCESS) {
14645		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14646	}
14647	if (message != NULL) {
14648		dns_message_detach(&message);
14649	}
14650	if (cancel) {
14651		cancel_refresh(zone);
14652	}
14653	isc_event_free(&event);
14654	UNLOCK_ZONE(zone);
14655	dns_zone_idetach(&zone);
14656	return;
14657
14658skip_master:
14659	if (key != NULL) {
14660		dns_tsigkey_detach(&key);
14661	}
14662	dns_message_detach(&message);
14663	/*
14664	 * Skip to next failed / untried master.
14665	 */
14666	do {
14667		zone->curmaster++;
14668	} while (zone->curmaster < zone->masterscnt &&
14669		 zone->mastersok[zone->curmaster]);
14670	if (zone->curmaster < zone->masterscnt) {
14671		goto again;
14672	}
14673	zone->curmaster = 0;
14674	goto cleanup;
14675}
14676
14677static void
14678ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
14679	const char me[] = "ns_query";
14680	isc_result_t result;
14681	dns_message_t *message = NULL;
14682	isc_netaddr_t masterip;
14683	dns_tsigkey_t *key = NULL;
14684	dns_dbnode_t *node = NULL;
14685	int timeout;
14686	bool have_xfrsource = false, have_xfrdscp = false;
14687	bool reqnsid;
14688	uint16_t udpsize = SEND_BUFFER_SIZE;
14689	isc_dscp_t dscp = -1;
14690	struct stub_cb_args *cb_args;
14691
14692	REQUIRE(DNS_ZONE_VALID(zone));
14693	REQUIRE(LOCKED_ZONE(zone));
14694	REQUIRE((soardataset != NULL && stub == NULL) ||
14695		(soardataset == NULL && stub != NULL));
14696	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
14697
14698	ENTER;
14699
14700	if (stub == NULL) {
14701		stub = isc_mem_get(zone->mctx, sizeof(*stub));
14702		stub->magic = STUB_MAGIC;
14703		stub->mctx = zone->mctx;
14704		stub->zone = NULL;
14705		stub->db = NULL;
14706		stub->version = NULL;
14707		atomic_init(&stub->pending_requests, 0);
14708
14709		/*
14710		 * Attach so that the zone won't disappear from under us.
14711		 */
14712		zone_iattach(zone, &stub->zone);
14713
14714		/*
14715		 * If a db exists we will update it, otherwise we create a
14716		 * new one and attach it to the zone once we have the NS
14717		 * RRset and glue.
14718		 */
14719		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14720		if (zone->db != NULL) {
14721			dns_db_attach(zone->db, &stub->db);
14722			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14723		} else {
14724			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14725
14726			INSIST(zone->db_argc >= 1);
14727			result = dns_db_create(zone->mctx, zone->db_argv[0],
14728					       &zone->origin, dns_dbtype_stub,
14729					       zone->rdclass, zone->db_argc - 1,
14730					       zone->db_argv + 1, &stub->db);
14731			if (result != ISC_R_SUCCESS) {
14732				dns_zone_log(zone, ISC_LOG_ERROR,
14733					     "refreshing stub: "
14734					     "could not create "
14735					     "database: %s",
14736					     dns_result_totext(result));
14737				goto cleanup;
14738			}
14739			dns_db_settask(stub->db, zone->task);
14740		}
14741
14742		result = dns_db_newversion(stub->db, &stub->version);
14743		if (result != ISC_R_SUCCESS) {
14744			dns_zone_log(zone, ISC_LOG_INFO,
14745				     "refreshing stub: "
14746				     "dns_db_newversion() failed: %s",
14747				     dns_result_totext(result));
14748			goto cleanup;
14749		}
14750
14751		/*
14752		 * Update SOA record.
14753		 */
14754		result = dns_db_findnode(stub->db, &zone->origin, true, &node);
14755		if (result != ISC_R_SUCCESS) {
14756			dns_zone_log(zone, ISC_LOG_INFO,
14757				     "refreshing stub: "
14758				     "dns_db_findnode() failed: %s",
14759				     dns_result_totext(result));
14760			goto cleanup;
14761		}
14762
14763		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
14764					    soardataset, 0, NULL);
14765		dns_db_detachnode(stub->db, &node);
14766		if (result != ISC_R_SUCCESS) {
14767			dns_zone_log(zone, ISC_LOG_INFO,
14768				     "refreshing stub: "
14769				     "dns_db_addrdataset() failed: %s",
14770				     dns_result_totext(result));
14771			goto cleanup;
14772		}
14773	}
14774
14775	/*
14776	 * XXX Optimisation: Create message when zone is setup and reuse.
14777	 */
14778	result = create_query(zone, dns_rdatatype_ns, &zone->origin, &message);
14779	INSIST(result == ISC_R_SUCCESS);
14780
14781	INSIST(zone->masterscnt > 0);
14782	INSIST(zone->curmaster < zone->masterscnt);
14783	zone->masteraddr = zone->masters[zone->curmaster];
14784
14785	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14786	/*
14787	 * First, look for a tsig key in the master statement, then
14788	 * try for a server key.
14789	 */
14790	if ((zone->masterkeynames != NULL) &&
14791	    (zone->masterkeynames[zone->curmaster] != NULL))
14792	{
14793		dns_view_t *view = dns_zone_getview(zone);
14794		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14795		result = dns_view_gettsig(view, keyname, &key);
14796		if (result != ISC_R_SUCCESS) {
14797			char namebuf[DNS_NAME_FORMATSIZE];
14798			dns_name_format(keyname, namebuf, sizeof(namebuf));
14799			dns_zone_log(zone, ISC_LOG_ERROR,
14800				     "unable to find key: %s", namebuf);
14801		}
14802	}
14803	if (key == NULL) {
14804		(void)dns_view_getpeertsig(zone->view, &masterip, &key);
14805	}
14806
14807	reqnsid = zone->view->requestnsid;
14808	if (zone->view->peers != NULL) {
14809		dns_peer_t *peer = NULL;
14810		bool edns;
14811		result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip,
14812						 &peer);
14813		if (result == ISC_R_SUCCESS) {
14814			result = dns_peer_getsupportedns(peer, &edns);
14815			if (result == ISC_R_SUCCESS && !edns) {
14816				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14817			}
14818			result = dns_peer_gettransfersource(peer,
14819							    &zone->sourceaddr);
14820			if (result == ISC_R_SUCCESS) {
14821				have_xfrsource = true;
14822			}
14823			result = dns_peer_gettransferdscp(peer, &dscp);
14824			if (result == ISC_R_SUCCESS && dscp != -1) {
14825				have_xfrdscp = true;
14826			}
14827			if (zone->view->resolver != NULL) {
14828				udpsize = dns_resolver_getudpsize(
14829					zone->view->resolver);
14830			}
14831			(void)dns_peer_getudpsize(peer, &udpsize);
14832			(void)dns_peer_getrequestnsid(peer, &reqnsid);
14833		}
14834	}
14835	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14836		result = add_opt(message, udpsize, reqnsid, false);
14837		if (result != ISC_R_SUCCESS) {
14838			zone_debuglog(zone, me, 1,
14839				      "unable to add opt record: %s",
14840				      dns_result_totext(result));
14841		}
14842	}
14843
14844	/*
14845	 * Always use TCP so that we shouldn't truncate in additional section.
14846	 */
14847	switch (isc_sockaddr_pf(&zone->masteraddr)) {
14848	case PF_INET:
14849		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14850			zone->sourceaddr = zone->altxfrsource4;
14851			if (!have_xfrdscp) {
14852				dscp = zone->altxfrsource4dscp;
14853			}
14854		} else if (!have_xfrsource) {
14855			zone->sourceaddr = zone->xfrsource4;
14856			if (!have_xfrdscp) {
14857				dscp = zone->xfrsource4dscp;
14858			}
14859		}
14860		break;
14861	case PF_INET6:
14862		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14863			zone->sourceaddr = zone->altxfrsource6;
14864			if (!have_xfrdscp) {
14865				dscp = zone->altxfrsource6dscp;
14866			}
14867		} else if (!have_xfrsource) {
14868			zone->sourceaddr = zone->xfrsource6;
14869			if (!have_xfrdscp) {
14870				dscp = zone->xfrsource6dscp;
14871			}
14872		}
14873		break;
14874	default:
14875		result = ISC_R_NOTIMPLEMENTED;
14876		POST(result);
14877		goto cleanup;
14878	}
14879	timeout = 15;
14880	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14881		timeout = 30;
14882	}
14883
14884	/*
14885	 * Save request parameters so we can reuse them later on
14886	 * for resolving missing glue A/AAAA records.
14887	 */
14888	cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
14889	cb_args->stub = stub;
14890	cb_args->tsig_key = key;
14891	cb_args->dscp = dscp;
14892	cb_args->udpsize = udpsize;
14893	cb_args->timeout = timeout;
14894	cb_args->reqnsid = reqnsid;
14895
14896	result = dns_request_createvia(
14897		zone->view->requestmgr, message, &zone->sourceaddr,
14898		&zone->masteraddr, dscp, DNS_REQUESTOPT_TCP, key, timeout * 3,
14899		timeout, 0, zone->task, stub_callback, cb_args, &zone->request);
14900	if (result != ISC_R_SUCCESS) {
14901		zone_debuglog(zone, me, 1, "dns_request_createvia() failed: %s",
14902			      dns_result_totext(result));
14903		goto cleanup;
14904	}
14905	dns_message_detach(&message);
14906	goto unlock;
14907
14908cleanup:
14909	cancel_refresh(zone);
14910	stub->magic = 0;
14911	if (stub->version != NULL) {
14912		dns_db_closeversion(stub->db, &stub->version, false);
14913	}
14914	if (stub->db != NULL) {
14915		dns_db_detach(&stub->db);
14916	}
14917	if (stub->zone != NULL) {
14918		zone_idetach(&stub->zone);
14919	}
14920	isc_mem_put(stub->mctx, stub, sizeof(*stub));
14921	if (message != NULL) {
14922		dns_message_detach(&message);
14923	}
14924unlock:
14925	if (key != NULL) {
14926		dns_tsigkey_detach(&key);
14927	}
14928	return;
14929}
14930
14931/*
14932 * Shut the zone down.
14933 */
14934static void
14935zone_shutdown(isc_task_t *task, isc_event_t *event) {
14936	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
14937	bool free_needed, linked = false;
14938	dns_zone_t *raw = NULL, *secure = NULL;
14939	dns_view_t *view = NULL, *prev_view = NULL;
14940
14941	UNUSED(task);
14942	REQUIRE(DNS_ZONE_VALID(zone));
14943	INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
14944	INSIST(isc_refcount_current(&zone->erefs) == 0);
14945
14946	zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
14947
14948	/*
14949	 * If we were waiting for xfrin quota, step out of
14950	 * the queue.
14951	 * If there's no zone manager, we can't be waiting for the
14952	 * xfrin quota
14953	 */
14954	if (zone->zmgr != NULL) {
14955		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14956		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
14957			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
14958					statelink);
14959			linked = true;
14960			zone->statelist = NULL;
14961		}
14962		if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
14963			ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
14964					statelink);
14965			zone->statelist = NULL;
14966			zmgr_resume_xfrs(zone->zmgr, false);
14967		}
14968		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14969	}
14970
14971	/*
14972	 * In task context, no locking required.  See zone_xfrdone().
14973	 */
14974	if (zone->xfr != NULL) {
14975		dns_xfrin_shutdown(zone->xfr);
14976	}
14977
14978	/* Safe to release the zone now */
14979	if (zone->zmgr != NULL) {
14980		dns_zonemgr_releasezone(zone->zmgr, zone);
14981	}
14982
14983	LOCK_ZONE(zone);
14984	INSIST(zone != zone->raw);
14985
14986	/*
14987	 * Detach the views early, we don't need them anymore.  However, we need
14988	 * to detach them outside of the zone lock to break the lock loop
14989	 * between view, adb and zone locks.
14990	 */
14991	view = zone->view;
14992	zone->view = NULL;
14993	prev_view = zone->prev_view;
14994	zone->prev_view = NULL;
14995
14996	if (linked) {
14997		isc_refcount_decrement(&zone->irefs);
14998	}
14999	if (zone->request != NULL) {
15000		dns_request_cancel(zone->request);
15001	}
15002
15003	if (zone->readio != NULL) {
15004		zonemgr_cancelio(zone->readio);
15005	}
15006
15007	if (zone->lctx != NULL) {
15008		dns_loadctx_cancel(zone->lctx);
15009	}
15010
15011	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
15012	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15013	{
15014		if (zone->writeio != NULL) {
15015			zonemgr_cancelio(zone->writeio);
15016		}
15017
15018		if (zone->dctx != NULL) {
15019			dns_dumpctx_cancel(zone->dctx);
15020		}
15021	}
15022
15023	checkds_cancel(zone);
15024
15025	notify_cancel(zone);
15026
15027	forward_cancel(zone);
15028
15029	if (zone->timer != NULL) {
15030		isc_timer_destroy(&zone->timer);
15031		isc_refcount_decrement(&zone->irefs);
15032	}
15033
15034	/*
15035	 * We have now canceled everything set the flag to allow exit_check()
15036	 * to succeed.	We must not unlock between setting this flag and
15037	 * calling exit_check().
15038	 */
15039	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
15040	free_needed = exit_check(zone);
15041	/*
15042	 * If a dump is in progress for the secure zone, defer detaching from
15043	 * the raw zone as it may prevent the unsigned serial number from being
15044	 * stored in the raw-format dump of the secure zone.  In this scenario,
15045	 * dump_done() takes care of cleaning up the zone->raw reference.
15046	 */
15047	if (inline_secure(zone) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
15048		raw = zone->raw;
15049		zone->raw = NULL;
15050	}
15051	if (inline_raw(zone)) {
15052		secure = zone->secure;
15053		zone->secure = NULL;
15054	}
15055	UNLOCK_ZONE(zone);
15056
15057	if (view != NULL) {
15058		dns_view_weakdetach(&view);
15059	}
15060	if (prev_view != NULL) {
15061		dns_view_weakdetach(&prev_view);
15062	}
15063
15064	if (raw != NULL) {
15065		dns_zone_detach(&raw);
15066	}
15067	if (secure != NULL) {
15068		dns_zone_idetach(&secure);
15069	}
15070	if (free_needed) {
15071		zone_free(zone);
15072	}
15073}
15074
15075static void
15076zone_timer(isc_task_t *task, isc_event_t *event) {
15077	const char me[] = "zone_timer";
15078	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
15079
15080	UNUSED(task);
15081	REQUIRE(DNS_ZONE_VALID(zone));
15082
15083	ENTER;
15084
15085	zone_maintenance(zone);
15086
15087	isc_event_free(&event);
15088}
15089
15090static void
15091zone_settimer(dns_zone_t *zone, isc_time_t *now) {
15092	const char me[] = "zone_settimer";
15093	isc_time_t next;
15094	isc_result_t result;
15095
15096	REQUIRE(DNS_ZONE_VALID(zone));
15097	REQUIRE(LOCKED_ZONE(zone));
15098	ENTER;
15099
15100	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15101		return;
15102	}
15103
15104	isc_time_settoepoch(&next);
15105
15106	switch (zone->type) {
15107	case dns_zone_redirect:
15108		if (zone->masters != NULL) {
15109			goto treat_as_slave;
15110		}
15111		FALLTHROUGH;
15112	case dns_zone_primary:
15113		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15114		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15115		{
15116			next = zone->notifytime;
15117		}
15118		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15119		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15120		{
15121			INSIST(!isc_time_isepoch(&zone->dumptime));
15122			if (isc_time_isepoch(&next) ||
15123			    isc_time_compare(&zone->dumptime, &next) < 0)
15124			{
15125				next = zone->dumptime;
15126			}
15127		}
15128		if (zone->type == dns_zone_redirect) {
15129			break;
15130		}
15131		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
15132		    !isc_time_isepoch(&zone->refreshkeytime))
15133		{
15134			if (isc_time_isepoch(&next) ||
15135			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
15136			{
15137				next = zone->refreshkeytime;
15138			}
15139		}
15140		if (!isc_time_isepoch(&zone->resigntime)) {
15141			if (isc_time_isepoch(&next) ||
15142			    isc_time_compare(&zone->resigntime, &next) < 0)
15143			{
15144				next = zone->resigntime;
15145			}
15146		}
15147		if (!isc_time_isepoch(&zone->keywarntime)) {
15148			if (isc_time_isepoch(&next) ||
15149			    isc_time_compare(&zone->keywarntime, &next) < 0)
15150			{
15151				next = zone->keywarntime;
15152			}
15153		}
15154		if (!isc_time_isepoch(&zone->signingtime)) {
15155			if (isc_time_isepoch(&next) ||
15156			    isc_time_compare(&zone->signingtime, &next) < 0)
15157			{
15158				next = zone->signingtime;
15159			}
15160		}
15161		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
15162			if (isc_time_isepoch(&next) ||
15163			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
15164			{
15165				next = zone->nsec3chaintime;
15166			}
15167		}
15168		break;
15169
15170	case dns_zone_secondary:
15171	case dns_zone_mirror:
15172	treat_as_slave:
15173		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15174		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15175		{
15176			next = zone->notifytime;
15177		}
15178		FALLTHROUGH;
15179	case dns_zone_stub:
15180		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
15181		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
15182		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
15183		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
15184		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
15185		    !isc_time_isepoch(&zone->refreshtime) &&
15186		    (isc_time_isepoch(&next) ||
15187		     isc_time_compare(&zone->refreshtime, &next) < 0))
15188		{
15189			next = zone->refreshtime;
15190		}
15191		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15192		    !isc_time_isepoch(&zone->expiretime))
15193		{
15194			if (isc_time_isepoch(&next) ||
15195			    isc_time_compare(&zone->expiretime, &next) < 0)
15196			{
15197				next = zone->expiretime;
15198			}
15199		}
15200		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15201		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15202		{
15203			INSIST(!isc_time_isepoch(&zone->dumptime));
15204			if (isc_time_isepoch(&next) ||
15205			    isc_time_compare(&zone->dumptime, &next) < 0)
15206			{
15207				next = zone->dumptime;
15208			}
15209		}
15210		break;
15211
15212	case dns_zone_key:
15213		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15214		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15215		{
15216			INSIST(!isc_time_isepoch(&zone->dumptime));
15217			if (isc_time_isepoch(&next) ||
15218			    isc_time_compare(&zone->dumptime, &next) < 0)
15219			{
15220				next = zone->dumptime;
15221			}
15222		}
15223		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
15224			if (isc_time_isepoch(&next) ||
15225			    (!isc_time_isepoch(&zone->refreshkeytime) &&
15226			     isc_time_compare(&zone->refreshkeytime, &next) <
15227				     0))
15228			{
15229				next = zone->refreshkeytime;
15230			}
15231		}
15232		break;
15233
15234	default:
15235		break;
15236	}
15237
15238	if (isc_time_isepoch(&next)) {
15239		zone_debuglog(zone, me, 10, "settimer inactive");
15240		result = isc_timer_reset(zone->timer, isc_timertype_inactive,
15241					 NULL, NULL, true);
15242		if (result != ISC_R_SUCCESS) {
15243			dns_zone_log(zone, ISC_LOG_ERROR,
15244				     "could not deactivate zone timer: %s",
15245				     isc_result_totext(result));
15246		}
15247	} else {
15248		if (isc_time_compare(&next, now) <= 0) {
15249			next = *now;
15250		}
15251		result = isc_timer_reset(zone->timer, isc_timertype_once, &next,
15252					 NULL, true);
15253		if (result != ISC_R_SUCCESS) {
15254			dns_zone_log(zone, ISC_LOG_ERROR,
15255				     "could not reset zone timer: %s",
15256				     isc_result_totext(result));
15257		}
15258	}
15259}
15260
15261static void
15262cancel_refresh(dns_zone_t *zone) {
15263	const char me[] = "cancel_refresh";
15264	isc_time_t now;
15265
15266	/*
15267	 * 'zone' locked by caller.
15268	 */
15269
15270	REQUIRE(DNS_ZONE_VALID(zone));
15271	REQUIRE(LOCKED_ZONE(zone));
15272
15273	ENTER;
15274
15275	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
15276	TIME_NOW(&now);
15277	zone_settimer(zone, &now);
15278}
15279
15280static isc_result_t
15281notify_createmessage(dns_zone_t *zone, unsigned int flags,
15282		     dns_message_t **messagep) {
15283	dns_db_t *zonedb = NULL;
15284	dns_dbnode_t *node = NULL;
15285	dns_dbversion_t *version = NULL;
15286	dns_message_t *message = NULL;
15287	dns_rdataset_t rdataset;
15288	dns_rdata_t rdata = DNS_RDATA_INIT;
15289
15290	dns_name_t *tempname = NULL;
15291	dns_rdata_t *temprdata = NULL;
15292	dns_rdatalist_t *temprdatalist = NULL;
15293	dns_rdataset_t *temprdataset = NULL;
15294
15295	isc_result_t result;
15296	isc_region_t r;
15297	isc_buffer_t *b = NULL;
15298
15299	REQUIRE(DNS_ZONE_VALID(zone));
15300	REQUIRE(messagep != NULL && *messagep == NULL);
15301
15302	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
15303
15304	message->opcode = dns_opcode_notify;
15305	message->flags |= DNS_MESSAGEFLAG_AA;
15306	message->rdclass = zone->rdclass;
15307
15308	result = dns_message_gettempname(message, &tempname);
15309	if (result != ISC_R_SUCCESS) {
15310		goto cleanup;
15311	}
15312
15313	result = dns_message_gettemprdataset(message, &temprdataset);
15314	if (result != ISC_R_SUCCESS) {
15315		goto cleanup;
15316	}
15317
15318	/*
15319	 * Make question.
15320	 */
15321	dns_name_clone(&zone->origin, tempname);
15322	dns_rdataset_makequestion(temprdataset, zone->rdclass,
15323				  dns_rdatatype_soa);
15324	ISC_LIST_APPEND(tempname->list, temprdataset, link);
15325	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
15326	tempname = NULL;
15327	temprdataset = NULL;
15328
15329	if ((flags & DNS_NOTIFY_NOSOA) != 0) {
15330		goto done;
15331	}
15332
15333	result = dns_message_gettempname(message, &tempname);
15334	if (result != ISC_R_SUCCESS) {
15335		goto soa_cleanup;
15336	}
15337	result = dns_message_gettemprdata(message, &temprdata);
15338	if (result != ISC_R_SUCCESS) {
15339		goto soa_cleanup;
15340	}
15341	result = dns_message_gettemprdataset(message, &temprdataset);
15342	if (result != ISC_R_SUCCESS) {
15343		goto soa_cleanup;
15344	}
15345	result = dns_message_gettemprdatalist(message, &temprdatalist);
15346	if (result != ISC_R_SUCCESS) {
15347		goto soa_cleanup;
15348	}
15349
15350	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15351	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
15352	dns_db_attach(zone->db, &zonedb);
15353	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15354
15355	dns_name_clone(&zone->origin, tempname);
15356	dns_db_currentversion(zonedb, &version);
15357	result = dns_db_findnode(zonedb, tempname, false, &node);
15358	if (result != ISC_R_SUCCESS) {
15359		goto soa_cleanup;
15360	}
15361
15362	dns_rdataset_init(&rdataset);
15363	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
15364				     dns_rdatatype_none, 0, &rdataset, NULL);
15365	if (result != ISC_R_SUCCESS) {
15366		goto soa_cleanup;
15367	}
15368	result = dns_rdataset_first(&rdataset);
15369	if (result != ISC_R_SUCCESS) {
15370		goto soa_cleanup;
15371	}
15372	dns_rdataset_current(&rdataset, &rdata);
15373	dns_rdata_toregion(&rdata, &r);
15374	isc_buffer_allocate(zone->mctx, &b, r.length);
15375	isc_buffer_putmem(b, r.base, r.length);
15376	isc_buffer_usedregion(b, &r);
15377	dns_rdata_init(temprdata);
15378	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
15379	dns_message_takebuffer(message, &b);
15380	result = dns_rdataset_next(&rdataset);
15381	dns_rdataset_disassociate(&rdataset);
15382	if (result != ISC_R_NOMORE) {
15383		goto soa_cleanup;
15384	}
15385	temprdatalist->rdclass = rdata.rdclass;
15386	temprdatalist->type = rdata.type;
15387	temprdatalist->ttl = rdataset.ttl;
15388	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
15389
15390	result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
15391	if (result != ISC_R_SUCCESS) {
15392		goto soa_cleanup;
15393	}
15394
15395	ISC_LIST_APPEND(tempname->list, temprdataset, link);
15396	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
15397	temprdatalist = NULL;
15398	temprdataset = NULL;
15399	temprdata = NULL;
15400	tempname = NULL;
15401
15402soa_cleanup:
15403	if (node != NULL) {
15404		dns_db_detachnode(zonedb, &node);
15405	}
15406	if (version != NULL) {
15407		dns_db_closeversion(zonedb, &version, false);
15408	}
15409	if (zonedb != NULL) {
15410		dns_db_detach(&zonedb);
15411	}
15412	if (tempname != NULL) {
15413		dns_message_puttempname(message, &tempname);
15414	}
15415	if (temprdata != NULL) {
15416		dns_message_puttemprdata(message, &temprdata);
15417	}
15418	if (temprdataset != NULL) {
15419		dns_message_puttemprdataset(message, &temprdataset);
15420	}
15421	if (temprdatalist != NULL) {
15422		dns_message_puttemprdatalist(message, &temprdatalist);
15423	}
15424
15425done:
15426	*messagep = message;
15427	return (ISC_R_SUCCESS);
15428
15429cleanup:
15430	if (tempname != NULL) {
15431		dns_message_puttempname(message, &tempname);
15432	}
15433	if (temprdataset != NULL) {
15434		dns_message_puttemprdataset(message, &temprdataset);
15435	}
15436	dns_message_detach(&message);
15437	return (result);
15438}
15439
15440isc_result_t
15441dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
15442		       isc_sockaddr_t *to, dns_message_t *msg) {
15443	unsigned int i;
15444	dns_rdata_soa_t soa;
15445	dns_rdataset_t *rdataset = NULL;
15446	dns_rdata_t rdata = DNS_RDATA_INIT;
15447	isc_result_t result;
15448	char fromtext[ISC_SOCKADDR_FORMATSIZE];
15449	int match = 0;
15450	isc_netaddr_t netaddr;
15451	uint32_t serial = 0;
15452	bool have_serial = false;
15453	dns_tsigkey_t *tsigkey;
15454	const dns_name_t *tsig;
15455
15456	REQUIRE(DNS_ZONE_VALID(zone));
15457
15458	/*
15459	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
15460	 * ROLLOVER.
15461	 *
15462	 * SOA:	RFC1996
15463	 * Check that 'from' is a valid notify source, (zone->masters).
15464	 *	Return DNS_R_REFUSED if not.
15465	 *
15466	 * If the notify message contains a serial number check it
15467	 * against the zones serial and return if <= current serial
15468	 *
15469	 * If a refresh check is progress, if so just record the
15470	 * fact we received a NOTIFY and from where and return.
15471	 * We will perform a new refresh check when the current one
15472	 * completes. Return ISC_R_SUCCESS.
15473	 *
15474	 * Otherwise initiate a refresh check using 'from' as the
15475	 * first address to check.  Return ISC_R_SUCCESS.
15476	 */
15477
15478	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
15479
15480	/*
15481	 * Notify messages are processed by the raw zone.
15482	 */
15483	LOCK_ZONE(zone);
15484	INSIST(zone != zone->raw);
15485	if (inline_secure(zone)) {
15486		result = dns_zone_notifyreceive(zone->raw, from, to, msg);
15487		UNLOCK_ZONE(zone);
15488		return (result);
15489	}
15490	/*
15491	 *  We only handle NOTIFY (SOA) at the present.
15492	 */
15493	if (isc_sockaddr_pf(from) == PF_INET) {
15494		inc_stats(zone, dns_zonestatscounter_notifyinv4);
15495	} else {
15496		inc_stats(zone, dns_zonestatscounter_notifyinv6);
15497	}
15498	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
15499	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
15500				 dns_rdatatype_soa, dns_rdatatype_none, NULL,
15501				 NULL) != ISC_R_SUCCESS)
15502	{
15503		UNLOCK_ZONE(zone);
15504		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
15505			dns_zone_log(zone, ISC_LOG_NOTICE,
15506				     "NOTIFY with no "
15507				     "question section from: %s",
15508				     fromtext);
15509			return (DNS_R_FORMERR);
15510		}
15511		dns_zone_log(zone, ISC_LOG_NOTICE,
15512			     "NOTIFY zone does not match");
15513		return (DNS_R_NOTIMP);
15514	}
15515
15516	/*
15517	 * If we are a master zone just succeed.
15518	 */
15519	if (zone->type == dns_zone_primary) {
15520		UNLOCK_ZONE(zone);
15521		return (ISC_R_SUCCESS);
15522	}
15523
15524	isc_netaddr_fromsockaddr(&netaddr, from);
15525	for (i = 0; i < zone->masterscnt; i++) {
15526		if (isc_sockaddr_eqaddr(from, &zone->masters[i])) {
15527			break;
15528		}
15529		if (zone->view->aclenv.match_mapped &&
15530		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
15531		    isc_sockaddr_pf(&zone->masters[i]) == AF_INET)
15532		{
15533			isc_netaddr_t na1, na2;
15534			isc_netaddr_fromv4mapped(&na1, &netaddr);
15535			isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
15536			if (isc_netaddr_equal(&na1, &na2)) {
15537				break;
15538			}
15539		}
15540	}
15541
15542	/*
15543	 * Accept notify requests from non masters if they are on
15544	 * 'zone->notify_acl'.
15545	 */
15546	tsigkey = dns_message_gettsigkey(msg);
15547	tsig = dns_tsigkey_identity(tsigkey);
15548	if (i >= zone->masterscnt && zone->notify_acl != NULL &&
15549	    (dns_acl_match(&netaddr, tsig, zone->notify_acl,
15550			   &zone->view->aclenv, &match,
15551			   NULL) == ISC_R_SUCCESS) &&
15552	    match > 0)
15553	{
15554		/* Accept notify. */
15555	} else if (i >= zone->masterscnt) {
15556		UNLOCK_ZONE(zone);
15557		dns_zone_log(zone, ISC_LOG_INFO,
15558			     "refused notify from non-master: %s", fromtext);
15559		inc_stats(zone, dns_zonestatscounter_notifyrej);
15560		return (DNS_R_REFUSED);
15561	}
15562
15563	/*
15564	 * If the zone is loaded and there are answers check the serial
15565	 * to see if we need to do a refresh.  Do not worry about this
15566	 * check if we are a dialup zone as we use the notify request
15567	 * to trigger a refresh check.
15568	 */
15569	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
15570	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15571	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH))
15572	{
15573		result = dns_message_findname(
15574			msg, DNS_SECTION_ANSWER, &zone->origin,
15575			dns_rdatatype_soa, dns_rdatatype_none, NULL, &rdataset);
15576		if (result == ISC_R_SUCCESS) {
15577			result = dns_rdataset_first(rdataset);
15578		}
15579		if (result == ISC_R_SUCCESS) {
15580			uint32_t oldserial;
15581			unsigned int soacount;
15582
15583			dns_rdataset_current(rdataset, &rdata);
15584			result = dns_rdata_tostruct(&rdata, &soa, NULL);
15585			RUNTIME_CHECK(result == ISC_R_SUCCESS);
15586			serial = soa.serial;
15587			have_serial = true;
15588			/*
15589			 * The following should safely be performed without DB
15590			 * lock and succeed in this context.
15591			 */
15592			result = zone_get_from_db(zone, zone->db, NULL,
15593						  &soacount, NULL, &oldserial,
15594						  NULL, NULL, NULL, NULL, NULL);
15595			RUNTIME_CHECK(result == ISC_R_SUCCESS);
15596			RUNTIME_CHECK(soacount > 0U);
15597			if (isc_serial_le(serial, oldserial)) {
15598				dns_zone_log(zone, ISC_LOG_INFO,
15599					     "notify from %s: "
15600					     "zone is up to date",
15601					     fromtext);
15602				UNLOCK_ZONE(zone);
15603				return (ISC_R_SUCCESS);
15604			}
15605		}
15606	}
15607
15608	/*
15609	 * If we got this far and there was a refresh in progress just
15610	 * let it complete.  Record where we got the notify from so we
15611	 * can perform a refresh check when the current one completes
15612	 */
15613	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
15614		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15615		zone->notifyfrom = *from;
15616		UNLOCK_ZONE(zone);
15617		if (have_serial) {
15618			dns_zone_log(zone, ISC_LOG_INFO,
15619				     "notify from %s: serial %u: refresh in "
15620				     "progress, refresh check queued",
15621				     fromtext, serial);
15622		} else {
15623			dns_zone_log(zone, ISC_LOG_INFO,
15624				     "notify from %s: refresh in progress, "
15625				     "refresh check queued",
15626				     fromtext);
15627		}
15628		return (ISC_R_SUCCESS);
15629	}
15630	if (have_serial) {
15631		dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
15632			     fromtext, serial);
15633	} else {
15634		dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
15635			     fromtext);
15636	}
15637	zone->notifyfrom = *from;
15638	UNLOCK_ZONE(zone);
15639
15640	if (to != NULL) {
15641		dns_zonemgr_unreachabledel(zone->zmgr, from, to);
15642	}
15643	dns_zone_refresh(zone);
15644	return (ISC_R_SUCCESS);
15645}
15646
15647void
15648dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
15649	REQUIRE(DNS_ZONE_VALID(zone));
15650
15651	LOCK_ZONE(zone);
15652	if (zone->notify_acl != NULL) {
15653		dns_acl_detach(&zone->notify_acl);
15654	}
15655	dns_acl_attach(acl, &zone->notify_acl);
15656	UNLOCK_ZONE(zone);
15657}
15658
15659void
15660dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
15661	REQUIRE(DNS_ZONE_VALID(zone));
15662
15663	LOCK_ZONE(zone);
15664	if (zone->query_acl != NULL) {
15665		dns_acl_detach(&zone->query_acl);
15666	}
15667	dns_acl_attach(acl, &zone->query_acl);
15668	UNLOCK_ZONE(zone);
15669}
15670
15671void
15672dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
15673	REQUIRE(DNS_ZONE_VALID(zone));
15674
15675	LOCK_ZONE(zone);
15676	if (zone->queryon_acl != NULL) {
15677		dns_acl_detach(&zone->queryon_acl);
15678	}
15679	dns_acl_attach(acl, &zone->queryon_acl);
15680	UNLOCK_ZONE(zone);
15681}
15682
15683void
15684dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
15685	REQUIRE(DNS_ZONE_VALID(zone));
15686
15687	LOCK_ZONE(zone);
15688	if (zone->update_acl != NULL) {
15689		dns_acl_detach(&zone->update_acl);
15690	}
15691	dns_acl_attach(acl, &zone->update_acl);
15692	UNLOCK_ZONE(zone);
15693}
15694
15695void
15696dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
15697	REQUIRE(DNS_ZONE_VALID(zone));
15698
15699	LOCK_ZONE(zone);
15700	if (zone->forward_acl != NULL) {
15701		dns_acl_detach(&zone->forward_acl);
15702	}
15703	dns_acl_attach(acl, &zone->forward_acl);
15704	UNLOCK_ZONE(zone);
15705}
15706
15707void
15708dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
15709	REQUIRE(DNS_ZONE_VALID(zone));
15710
15711	LOCK_ZONE(zone);
15712	if (zone->xfr_acl != NULL) {
15713		dns_acl_detach(&zone->xfr_acl);
15714	}
15715	dns_acl_attach(acl, &zone->xfr_acl);
15716	UNLOCK_ZONE(zone);
15717}
15718
15719dns_acl_t *
15720dns_zone_getnotifyacl(dns_zone_t *zone) {
15721	REQUIRE(DNS_ZONE_VALID(zone));
15722
15723	return (zone->notify_acl);
15724}
15725
15726dns_acl_t *
15727dns_zone_getqueryacl(dns_zone_t *zone) {
15728	REQUIRE(DNS_ZONE_VALID(zone));
15729
15730	return (zone->query_acl);
15731}
15732
15733dns_acl_t *
15734dns_zone_getqueryonacl(dns_zone_t *zone) {
15735	REQUIRE(DNS_ZONE_VALID(zone));
15736
15737	return (zone->queryon_acl);
15738}
15739
15740dns_acl_t *
15741dns_zone_getupdateacl(dns_zone_t *zone) {
15742	REQUIRE(DNS_ZONE_VALID(zone));
15743
15744	return (zone->update_acl);
15745}
15746
15747dns_acl_t *
15748dns_zone_getforwardacl(dns_zone_t *zone) {
15749	REQUIRE(DNS_ZONE_VALID(zone));
15750
15751	return (zone->forward_acl);
15752}
15753
15754dns_acl_t *
15755dns_zone_getxfracl(dns_zone_t *zone) {
15756	REQUIRE(DNS_ZONE_VALID(zone));
15757
15758	return (zone->xfr_acl);
15759}
15760
15761void
15762dns_zone_clearupdateacl(dns_zone_t *zone) {
15763	REQUIRE(DNS_ZONE_VALID(zone));
15764
15765	LOCK_ZONE(zone);
15766	if (zone->update_acl != NULL) {
15767		dns_acl_detach(&zone->update_acl);
15768	}
15769	UNLOCK_ZONE(zone);
15770}
15771
15772void
15773dns_zone_clearforwardacl(dns_zone_t *zone) {
15774	REQUIRE(DNS_ZONE_VALID(zone));
15775
15776	LOCK_ZONE(zone);
15777	if (zone->forward_acl != NULL) {
15778		dns_acl_detach(&zone->forward_acl);
15779	}
15780	UNLOCK_ZONE(zone);
15781}
15782
15783void
15784dns_zone_clearnotifyacl(dns_zone_t *zone) {
15785	REQUIRE(DNS_ZONE_VALID(zone));
15786
15787	LOCK_ZONE(zone);
15788	if (zone->notify_acl != NULL) {
15789		dns_acl_detach(&zone->notify_acl);
15790	}
15791	UNLOCK_ZONE(zone);
15792}
15793
15794void
15795dns_zone_clearqueryacl(dns_zone_t *zone) {
15796	REQUIRE(DNS_ZONE_VALID(zone));
15797
15798	LOCK_ZONE(zone);
15799	if (zone->query_acl != NULL) {
15800		dns_acl_detach(&zone->query_acl);
15801	}
15802	UNLOCK_ZONE(zone);
15803}
15804
15805void
15806dns_zone_clearqueryonacl(dns_zone_t *zone) {
15807	REQUIRE(DNS_ZONE_VALID(zone));
15808
15809	LOCK_ZONE(zone);
15810	if (zone->queryon_acl != NULL) {
15811		dns_acl_detach(&zone->queryon_acl);
15812	}
15813	UNLOCK_ZONE(zone);
15814}
15815
15816void
15817dns_zone_clearxfracl(dns_zone_t *zone) {
15818	REQUIRE(DNS_ZONE_VALID(zone));
15819
15820	LOCK_ZONE(zone);
15821	if (zone->xfr_acl != NULL) {
15822		dns_acl_detach(&zone->xfr_acl);
15823	}
15824	UNLOCK_ZONE(zone);
15825}
15826
15827bool
15828dns_zone_getupdatedisabled(dns_zone_t *zone) {
15829	REQUIRE(DNS_ZONE_VALID(zone));
15830	return (zone->update_disabled);
15831}
15832
15833void
15834dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
15835	REQUIRE(DNS_ZONE_VALID(zone));
15836	zone->update_disabled = state;
15837}
15838
15839bool
15840dns_zone_getzeronosoattl(dns_zone_t *zone) {
15841	REQUIRE(DNS_ZONE_VALID(zone));
15842	return (zone->zero_no_soa_ttl);
15843}
15844
15845void
15846dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
15847	REQUIRE(DNS_ZONE_VALID(zone));
15848	zone->zero_no_soa_ttl = state;
15849}
15850
15851void
15852dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
15853	REQUIRE(DNS_ZONE_VALID(zone));
15854
15855	zone->check_names = severity;
15856}
15857
15858dns_severity_t
15859dns_zone_getchecknames(dns_zone_t *zone) {
15860	REQUIRE(DNS_ZONE_VALID(zone));
15861
15862	return (zone->check_names);
15863}
15864
15865void
15866dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
15867	REQUIRE(DNS_ZONE_VALID(zone));
15868
15869	zone->journalsize = size;
15870}
15871
15872int32_t
15873dns_zone_getjournalsize(dns_zone_t *zone) {
15874	REQUIRE(DNS_ZONE_VALID(zone));
15875
15876	return (zone->journalsize);
15877}
15878
15879static void
15880zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
15881	isc_result_t result = ISC_R_FAILURE;
15882	isc_buffer_t buffer;
15883
15884	REQUIRE(buf != NULL);
15885	REQUIRE(length > 1U);
15886
15887	/*
15888	 * Leave space for terminating '\0'.
15889	 */
15890	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15891	if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
15892		if (dns_name_dynamic(&zone->origin)) {
15893			result = dns_name_totext(&zone->origin, true, &buffer);
15894		}
15895		if (result != ISC_R_SUCCESS &&
15896		    isc_buffer_availablelength(&buffer) >=
15897			    (sizeof("<UNKNOWN>") - 1))
15898		{
15899			isc_buffer_putstr(&buffer, "<UNKNOWN>");
15900		}
15901
15902		if (isc_buffer_availablelength(&buffer) > 0) {
15903			isc_buffer_putstr(&buffer, "/");
15904		}
15905		(void)dns_rdataclass_totext(zone->rdclass, &buffer);
15906	}
15907
15908	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
15909	    strcmp(zone->view->name, "_default") != 0 &&
15910	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
15911	{
15912		isc_buffer_putstr(&buffer, "/");
15913		isc_buffer_putstr(&buffer, zone->view->name);
15914	}
15915	if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) {
15916		isc_buffer_putstr(&buffer, " (signed)");
15917	}
15918	if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) {
15919		isc_buffer_putstr(&buffer, " (unsigned)");
15920	}
15921
15922	buf[isc_buffer_usedlength(&buffer)] = '\0';
15923}
15924
15925static void
15926zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
15927	isc_result_t result = ISC_R_FAILURE;
15928	isc_buffer_t buffer;
15929
15930	REQUIRE(buf != NULL);
15931	REQUIRE(length > 1U);
15932
15933	/*
15934	 * Leave space for terminating '\0'.
15935	 */
15936	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15937	if (dns_name_dynamic(&zone->origin)) {
15938		result = dns_name_totext(&zone->origin, true, &buffer);
15939	}
15940	if (result != ISC_R_SUCCESS &&
15941	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
15942	{
15943		isc_buffer_putstr(&buffer, "<UNKNOWN>");
15944	}
15945
15946	buf[isc_buffer_usedlength(&buffer)] = '\0';
15947}
15948
15949static void
15950zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
15951	isc_buffer_t buffer;
15952
15953	REQUIRE(buf != NULL);
15954	REQUIRE(length > 1U);
15955
15956	/*
15957	 * Leave space for terminating '\0'.
15958	 */
15959	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15960	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
15961
15962	buf[isc_buffer_usedlength(&buffer)] = '\0';
15963}
15964
15965static void
15966zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
15967	isc_buffer_t buffer;
15968
15969	REQUIRE(buf != NULL);
15970	REQUIRE(length > 1U);
15971
15972	/*
15973	 * Leave space for terminating '\0'.
15974	 */
15975	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15976
15977	if (zone->view == NULL) {
15978		isc_buffer_putstr(&buffer, "_none");
15979	} else if (strlen(zone->view->name) <
15980		   isc_buffer_availablelength(&buffer))
15981	{
15982		isc_buffer_putstr(&buffer, zone->view->name);
15983	} else {
15984		isc_buffer_putstr(&buffer, "_toolong");
15985	}
15986
15987	buf[isc_buffer_usedlength(&buffer)] = '\0';
15988}
15989
15990void
15991dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
15992	REQUIRE(DNS_ZONE_VALID(zone));
15993	REQUIRE(buf != NULL);
15994
15995	LOCK_ZONE(zone);
15996	zone_namerd_tostr(zone, buf, length);
15997	UNLOCK_ZONE(zone);
15998}
15999
16000void
16001dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
16002	REQUIRE(DNS_ZONE_VALID(zone));
16003	REQUIRE(buf != NULL);
16004	zone_name_tostr(zone, buf, length);
16005}
16006
16007void
16008dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
16009	      const char *prefix, const char *fmt, va_list ap) {
16010	char message[4096];
16011	const char *zstr;
16012
16013	REQUIRE(DNS_ZONE_VALID(zone));
16014
16015	if (!isc_log_wouldlog(dns_lctx, level)) {
16016		return;
16017	}
16018
16019	vsnprintf(message, sizeof(message), fmt, ap);
16020
16021	switch (zone->type) {
16022	case dns_zone_key:
16023		zstr = "managed-keys-zone";
16024		break;
16025	case dns_zone_redirect:
16026		zstr = "redirect-zone";
16027		break;
16028	default:
16029		zstr = "zone ";
16030	}
16031
16032	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
16033		      "%s%s%s%s: %s", (prefix != NULL ? prefix : ""),
16034		      (prefix != NULL ? ": " : ""), zstr, zone->strnamerd,
16035		      message);
16036}
16037
16038static void
16039notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16040	va_list ap;
16041
16042	va_start(ap, fmt);
16043	dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
16044	va_end(ap);
16045}
16046
16047void
16048dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
16049	      const char *fmt, ...) {
16050	va_list ap;
16051
16052	va_start(ap, fmt);
16053	dns_zone_logv(zone, category, level, NULL, fmt, ap);
16054	va_end(ap);
16055}
16056
16057void
16058dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16059	va_list ap;
16060
16061	va_start(ap, fmt);
16062	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
16063	va_end(ap);
16064}
16065
16066static void
16067zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, const char *fmt,
16068	      ...) {
16069	int level = ISC_LOG_DEBUG(debuglevel);
16070	va_list ap;
16071
16072	va_start(ap, fmt);
16073	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
16074	va_end(ap);
16075}
16076
16077static void
16078dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16079	va_list ap;
16080
16081	va_start(ap, fmt);
16082	dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
16083	va_end(ap);
16084}
16085
16086static int
16087message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
16088	isc_result_t result;
16089	dns_name_t *name;
16090	dns_rdataset_t *curr;
16091	int count = 0;
16092
16093	result = dns_message_firstname(msg, section);
16094	while (result == ISC_R_SUCCESS) {
16095		name = NULL;
16096		dns_message_currentname(msg, section, &name);
16097
16098		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
16099		     curr = ISC_LIST_PREV(curr, link))
16100		{
16101			if (curr->type == type) {
16102				count++;
16103			}
16104		}
16105		result = dns_message_nextname(msg, section);
16106	}
16107
16108	return (count);
16109}
16110
16111void
16112dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
16113	REQUIRE(DNS_ZONE_VALID(zone));
16114
16115	zone->maxxfrin = maxxfrin;
16116}
16117
16118uint32_t
16119dns_zone_getmaxxfrin(dns_zone_t *zone) {
16120	REQUIRE(DNS_ZONE_VALID(zone));
16121
16122	return (zone->maxxfrin);
16123}
16124
16125void
16126dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
16127	REQUIRE(DNS_ZONE_VALID(zone));
16128	zone->maxxfrout = maxxfrout;
16129}
16130
16131uint32_t
16132dns_zone_getmaxxfrout(dns_zone_t *zone) {
16133	REQUIRE(DNS_ZONE_VALID(zone));
16134
16135	return (zone->maxxfrout);
16136}
16137
16138dns_zonetype_t
16139dns_zone_gettype(dns_zone_t *zone) {
16140	REQUIRE(DNS_ZONE_VALID(zone));
16141
16142	return (zone->type);
16143}
16144
16145const char *
16146dns_zonetype_name(dns_zonetype_t type) {
16147	switch (type) {
16148	case dns_zone_none:
16149		return ("none");
16150	case dns_zone_primary:
16151		return ("primary");
16152	case dns_zone_secondary:
16153		return ("secondary");
16154	case dns_zone_mirror:
16155		return ("mirror");
16156	case dns_zone_stub:
16157		return ("stub");
16158	case dns_zone_staticstub:
16159		return ("static-stub");
16160	case dns_zone_key:
16161		return ("key");
16162	case dns_zone_dlz:
16163		return ("dlz");
16164	case dns_zone_redirect:
16165		return ("redirect");
16166	default:
16167		return ("unknown");
16168	}
16169}
16170
16171dns_zonetype_t
16172dns_zone_getredirecttype(dns_zone_t *zone) {
16173	REQUIRE(DNS_ZONE_VALID(zone));
16174	REQUIRE(zone->type == dns_zone_redirect);
16175
16176	return (zone->masters == NULL ? dns_zone_primary : dns_zone_secondary);
16177}
16178
16179dns_name_t *
16180dns_zone_getorigin(dns_zone_t *zone) {
16181	REQUIRE(DNS_ZONE_VALID(zone));
16182
16183	return (&zone->origin);
16184}
16185
16186void
16187dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
16188	REQUIRE(DNS_ZONE_VALID(zone));
16189
16190	LOCK_ZONE(zone);
16191	if (zone->task != NULL) {
16192		isc_task_detach(&zone->task);
16193	}
16194	isc_task_attach(task, &zone->task);
16195	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16196	if (zone->db != NULL) {
16197		dns_db_settask(zone->db, zone->task);
16198	}
16199	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16200	UNLOCK_ZONE(zone);
16201}
16202
16203void
16204dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
16205	REQUIRE(DNS_ZONE_VALID(zone));
16206	isc_task_attach(zone->task, target);
16207}
16208
16209void
16210dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
16211	REQUIRE(DNS_ZONE_VALID(zone));
16212
16213	if (idlein == 0) {
16214		idlein = DNS_DEFAULT_IDLEIN;
16215	}
16216	zone->idlein = idlein;
16217}
16218
16219uint32_t
16220dns_zone_getidlein(dns_zone_t *zone) {
16221	REQUIRE(DNS_ZONE_VALID(zone));
16222
16223	return (zone->idlein);
16224}
16225
16226void
16227dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
16228	REQUIRE(DNS_ZONE_VALID(zone));
16229
16230	zone->idleout = idleout;
16231}
16232
16233uint32_t
16234dns_zone_getidleout(dns_zone_t *zone) {
16235	REQUIRE(DNS_ZONE_VALID(zone));
16236
16237	return (zone->idleout);
16238}
16239
16240static void
16241notify_done(isc_task_t *task, isc_event_t *event) {
16242	dns_requestevent_t *revent = (dns_requestevent_t *)event;
16243	dns_notify_t *notify;
16244	isc_result_t result;
16245	dns_message_t *message = NULL;
16246	isc_buffer_t buf;
16247	char rcode[128];
16248	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
16249
16250	UNUSED(task);
16251
16252	notify = event->ev_arg;
16253	REQUIRE(DNS_NOTIFY_VALID(notify));
16254	INSIST(task == notify->zone->task);
16255
16256	isc_buffer_init(&buf, rcode, sizeof(rcode));
16257	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
16258	dns_message_create(notify->zone->mctx, DNS_MESSAGE_INTENTPARSE,
16259			   &message);
16260
16261	result = revent->result;
16262	if (result == ISC_R_SUCCESS) {
16263		result =
16264			dns_request_getresponse(revent->request, message,
16265						DNS_MESSAGEPARSE_PRESERVEORDER);
16266	}
16267	if (result == ISC_R_SUCCESS) {
16268		result = dns_rcode_totext(message->rcode, &buf);
16269	}
16270	if (result == ISC_R_SUCCESS) {
16271		notify_log(notify->zone, ISC_LOG_DEBUG(3),
16272			   "notify response from %s: %.*s", addrbuf,
16273			   (int)buf.used, rcode);
16274	} else {
16275		notify_log(notify->zone, ISC_LOG_DEBUG(2),
16276			   "notify to %s failed: %s", addrbuf,
16277			   dns_result_totext(result));
16278	}
16279
16280	/*
16281	 * Old bind's return formerr if they see a soa record.	Retry w/o
16282	 * the soa if we see a formerr and had sent a SOA.
16283	 */
16284	isc_event_free(&event);
16285	if (message->rcode == dns_rcode_formerr &&
16286	    (notify->flags & DNS_NOTIFY_NOSOA) == 0)
16287	{
16288		bool startup;
16289
16290		notify->flags |= DNS_NOTIFY_NOSOA;
16291		dns_request_destroy(&notify->request);
16292		startup = (notify->flags & DNS_NOTIFY_STARTUP);
16293		result = notify_send_queue(notify, startup);
16294		if (result != ISC_R_SUCCESS) {
16295			notify_destroy(notify, false);
16296		}
16297	} else {
16298		if (result == ISC_R_TIMEDOUT) {
16299			notify_log(notify->zone, ISC_LOG_DEBUG(1),
16300				   "notify to %s: retries exceeded", addrbuf);
16301		}
16302		notify_destroy(notify, false);
16303	}
16304	dns_message_detach(&message);
16305}
16306
16307struct secure_event {
16308	isc_event_t e;
16309	dns_db_t *db;
16310	uint32_t serial;
16311};
16312
16313static void
16314update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
16315	UNUSED(arg);
16316	dns_zone_log(zone, level, "%s", message);
16317}
16318
16319static isc_result_t
16320sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
16321		    uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
16322		    dns_diff_t *diff) {
16323	isc_result_t result;
16324	dns_difftuple_t *tuple = NULL;
16325	dns_diffop_t op = DNS_DIFFOP_ADD;
16326	int n_soa = 0;
16327
16328	REQUIRE(soatuplep != NULL);
16329
16330	if (start == end) {
16331		return (DNS_R_UNCHANGED);
16332	}
16333
16334	CHECK(dns_journal_iter_init(journal, start, end, NULL));
16335	for (result = dns_journal_first_rr(journal); result == ISC_R_SUCCESS;
16336	     result = dns_journal_next_rr(journal))
16337	{
16338		dns_name_t *name = NULL;
16339		uint32_t ttl;
16340		dns_rdata_t *rdata = NULL;
16341		dns_journal_current_rr(journal, &name, &ttl, &rdata);
16342
16343		if (rdata->type == dns_rdatatype_soa) {
16344			n_soa++;
16345			if (n_soa == 2) {
16346				/*
16347				 * Save the latest raw SOA record.
16348				 */
16349				if (*soatuplep != NULL) {
16350					dns_difftuple_free(soatuplep);
16351				}
16352				CHECK(dns_difftuple_create(
16353					diff->mctx, DNS_DIFFOP_ADD, name, ttl,
16354					rdata, soatuplep));
16355			}
16356			if (n_soa == 3) {
16357				n_soa = 1;
16358			}
16359			continue;
16360		}
16361
16362		/* Sanity. */
16363		if (n_soa == 0) {
16364			dns_zone_log(raw, ISC_LOG_ERROR,
16365				     "corrupt journal file: '%s'\n",
16366				     raw->journal);
16367			return (ISC_R_FAILURE);
16368		}
16369
16370		if (zone->privatetype != 0 && rdata->type == zone->privatetype)
16371		{
16372			continue;
16373		}
16374
16375		if (rdata->type == dns_rdatatype_nsec ||
16376		    rdata->type == dns_rdatatype_rrsig ||
16377		    rdata->type == dns_rdatatype_nsec3 ||
16378		    rdata->type == dns_rdatatype_dnskey ||
16379		    rdata->type == dns_rdatatype_nsec3param)
16380		{
16381			continue;
16382		}
16383
16384		op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
16385
16386		CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
16387					   &tuple));
16388		dns_diff_appendminimal(diff, &tuple);
16389	}
16390	if (result == ISC_R_NOMORE) {
16391		result = ISC_R_SUCCESS;
16392	}
16393
16394failure:
16395	return (result);
16396}
16397
16398static isc_result_t
16399sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
16400	       dns_dbversion_t *secver, dns_difftuple_t **soatuple,
16401	       dns_diff_t *diff) {
16402	isc_result_t result;
16403	dns_db_t *rawdb = NULL;
16404	dns_dbversion_t *rawver = NULL;
16405	dns_difftuple_t *tuple = NULL, *next;
16406	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
16407	dns_rdata_soa_t oldsoa, newsoa;
16408
16409	REQUIRE(DNS_ZONE_VALID(seczone));
16410	REQUIRE(soatuple != NULL && *soatuple == NULL);
16411
16412	if (!seczone->sourceserialset) {
16413		return (DNS_R_UNCHANGED);
16414	}
16415
16416	dns_db_attach(raw->db, &rawdb);
16417	dns_db_currentversion(rawdb, &rawver);
16418	result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
16419	dns_db_closeversion(rawdb, &rawver, false);
16420	dns_db_detach(&rawdb);
16421
16422	if (result != ISC_R_SUCCESS) {
16423		return (result);
16424	}
16425
16426	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
16427		next = ISC_LIST_NEXT(tuple, link);
16428		if (tuple->rdata.type == dns_rdatatype_nsec ||
16429		    tuple->rdata.type == dns_rdatatype_rrsig ||
16430		    tuple->rdata.type == dns_rdatatype_dnskey ||
16431		    tuple->rdata.type == dns_rdatatype_nsec3 ||
16432		    tuple->rdata.type == dns_rdatatype_nsec3param)
16433		{
16434			ISC_LIST_UNLINK(diff->tuples, tuple, link);
16435			dns_difftuple_free(&tuple);
16436			continue;
16437		}
16438		if (tuple->rdata.type == dns_rdatatype_soa) {
16439			if (tuple->op == DNS_DIFFOP_DEL) {
16440				INSIST(oldtuple == NULL);
16441				oldtuple = tuple;
16442			}
16443			if (tuple->op == DNS_DIFFOP_ADD) {
16444				INSIST(newtuple == NULL);
16445				newtuple = tuple;
16446			}
16447		}
16448	}
16449
16450	if (oldtuple != NULL && newtuple != NULL) {
16451		result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
16452		RUNTIME_CHECK(result == ISC_R_SUCCESS);
16453
16454		result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
16455		RUNTIME_CHECK(result == ISC_R_SUCCESS);
16456
16457		/*
16458		 * If the SOA records are the same except for the serial
16459		 * remove them from the diff.
16460		 */
16461		if (oldtuple->ttl == newtuple->ttl &&
16462		    oldsoa.refresh == newsoa.refresh &&
16463		    oldsoa.retry == newsoa.retry &&
16464		    oldsoa.minimum == newsoa.minimum &&
16465		    oldsoa.expire == newsoa.expire &&
16466		    dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
16467		    dns_name_equal(&oldsoa.contact, &newsoa.contact))
16468		{
16469			ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16470			dns_difftuple_free(&oldtuple);
16471			ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16472			dns_difftuple_free(&newtuple);
16473		}
16474	}
16475
16476	if (ISC_LIST_EMPTY(diff->tuples)) {
16477		return (DNS_R_UNCHANGED);
16478	}
16479
16480	/*
16481	 * If there are still SOA records in the diff they can now be removed
16482	 * saving the new SOA record.
16483	 */
16484	if (oldtuple != NULL) {
16485		ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16486		dns_difftuple_free(&oldtuple);
16487	}
16488
16489	if (newtuple != NULL) {
16490		ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16491		*soatuple = newtuple;
16492	}
16493
16494	return (ISC_R_SUCCESS);
16495}
16496
16497static void
16498receive_secure_serial(isc_task_t *task, isc_event_t *event) {
16499	static char me[] = "receive_secure_serial";
16500	isc_result_t result = ISC_R_SUCCESS;
16501	dns_journal_t *rjournal = NULL;
16502	dns_journal_t *sjournal = NULL;
16503	uint32_t start, end;
16504	dns_zone_t *zone;
16505	dns_difftuple_t *tuple = NULL, *soatuple = NULL;
16506	dns_update_log_t log = { update_log_cb, NULL };
16507	uint32_t newserial = 0, desired = 0;
16508	isc_time_t timenow;
16509	int level = ISC_LOG_ERROR;
16510
16511	UNUSED(task);
16512
16513	zone = event->ev_arg;
16514	end = ((struct secure_event *)event)->serial;
16515
16516	ENTER;
16517
16518	LOCK_ZONE(zone);
16519
16520	/*
16521	 * If we are already processing a receive secure serial event
16522	 * for the zone, just queue the new one and exit.
16523	 */
16524	if (zone->rss_event != NULL && zone->rss_event != event) {
16525		ISC_LIST_APPEND(zone->rss_events, event, ev_link);
16526		UNLOCK_ZONE(zone);
16527		return;
16528	}
16529
16530nextevent:
16531	if (zone->rss_event != NULL) {
16532		INSIST(zone->rss_event == event);
16533		UNLOCK_ZONE(zone);
16534	} else {
16535		zone->rss_event = event;
16536		dns_diff_init(zone->mctx, &zone->rss_diff);
16537
16538		/*
16539		 * zone->db may be NULL, if the load from disk failed.
16540		 */
16541		result = ISC_R_SUCCESS;
16542		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16543		if (zone->db != NULL) {
16544			dns_db_attach(zone->db, &zone->rss_db);
16545		} else {
16546			result = ISC_R_FAILURE;
16547		}
16548		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16549
16550		if (result == ISC_R_SUCCESS && zone->raw != NULL) {
16551			dns_zone_attach(zone->raw, &zone->rss_raw);
16552		} else {
16553			result = ISC_R_FAILURE;
16554		}
16555
16556		UNLOCK_ZONE(zone);
16557
16558		CHECK(result);
16559
16560		/*
16561		 * We first attempt to sync the raw zone to the secure zone
16562		 * by using the raw zone's journal, applying all the deltas
16563		 * from the latest source-serial of the secure zone up to
16564		 * the current serial number of the raw zone.
16565		 *
16566		 * If that fails, then we'll fall back to a direct comparison
16567		 * between raw and secure zones.
16568		 */
16569		CHECK(dns_journal_open(zone->rss_raw->mctx,
16570				       zone->rss_raw->journal,
16571				       DNS_JOURNAL_WRITE, &rjournal));
16572
16573		result = dns_journal_open(zone->mctx, zone->journal,
16574					  DNS_JOURNAL_READ, &sjournal);
16575		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
16576			goto failure;
16577		}
16578
16579		if (!dns_journal_get_sourceserial(rjournal, &start)) {
16580			start = dns_journal_first_serial(rjournal);
16581			dns_journal_set_sourceserial(rjournal, start);
16582		}
16583		if (sjournal != NULL) {
16584			uint32_t serial;
16585			/*
16586			 * We read the secure journal first, if that
16587			 * exists use its value provided it is greater
16588			 * that from the raw journal.
16589			 */
16590			if (dns_journal_get_sourceserial(sjournal, &serial)) {
16591				if (isc_serial_gt(serial, start)) {
16592					start = serial;
16593				}
16594			}
16595			dns_journal_destroy(&sjournal);
16596		}
16597
16598		dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
16599		CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
16600
16601		/*
16602		 * Try to apply diffs from the raw zone's journal to the secure
16603		 * zone.  If that fails, we recover by syncing up the databases
16604		 * directly.
16605		 */
16606		result = sync_secure_journal(zone, zone->rss_raw, rjournal,
16607					     start, end, &soatuple,
16608					     &zone->rss_diff);
16609		if (result == DNS_R_UNCHANGED) {
16610			level = ISC_LOG_INFO;
16611			goto failure;
16612		} else if (result != ISC_R_SUCCESS) {
16613			CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
16614					     zone->rss_oldver, &soatuple,
16615					     &zone->rss_diff));
16616		}
16617
16618		CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
16619				     zone->rss_newver));
16620
16621		if (soatuple != NULL) {
16622			uint32_t oldserial;
16623
16624			CHECK(dns_db_createsoatuple(
16625				zone->rss_db, zone->rss_oldver,
16626				zone->rss_diff.mctx, DNS_DIFFOP_DEL, &tuple));
16627			oldserial = dns_soa_getserial(&tuple->rdata);
16628			newserial = desired =
16629				dns_soa_getserial(&soatuple->rdata);
16630			if (!isc_serial_gt(newserial, oldserial)) {
16631				newserial = oldserial + 1;
16632				if (newserial == 0) {
16633					newserial++;
16634				}
16635				dns_soa_setserial(newserial, &soatuple->rdata);
16636			}
16637			CHECK(do_one_tuple(&tuple, zone->rss_db,
16638					   zone->rss_newver, &zone->rss_diff));
16639			CHECK(do_one_tuple(&soatuple, zone->rss_db,
16640					   zone->rss_newver, &zone->rss_diff));
16641		} else {
16642			CHECK(update_soa_serial(zone, zone->rss_db,
16643						zone->rss_newver,
16644						&zone->rss_diff, zone->mctx,
16645						zone->updatemethod));
16646		}
16647	}
16648	result = dns_update_signaturesinc(
16649		&log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver,
16650		&zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state);
16651	if (result == DNS_R_CONTINUE) {
16652		if (rjournal != NULL) {
16653			dns_journal_destroy(&rjournal);
16654		}
16655		isc_task_send(task, &event);
16656		return;
16657	}
16658	/*
16659	 * If something went wrong while trying to update the secure zone and
16660	 * the latter was already signed before, do not apply raw zone deltas
16661	 * to it as that would break existing DNSSEC signatures.  However, if
16662	 * the secure zone was not yet signed (e.g. because no signing keys
16663	 * were created for it), commence applying raw zone deltas to it so
16664	 * that contents of the raw zone and the secure zone are kept in sync.
16665	 */
16666	if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
16667		goto failure;
16668	}
16669
16670	if (rjournal == NULL) {
16671		CHECK(dns_journal_open(zone->rss_raw->mctx,
16672				       zone->rss_raw->journal,
16673				       DNS_JOURNAL_WRITE, &rjournal));
16674	}
16675	CHECK(zone_journal(zone, &zone->rss_diff, &end,
16676			   "receive_secure_serial"));
16677
16678	dns_journal_set_sourceserial(rjournal, end);
16679	dns_journal_commit(rjournal);
16680
16681	LOCK_ZONE(zone);
16682	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16683
16684	zone->sourceserial = end;
16685	zone->sourceserialset = true;
16686	zone_needdump(zone, DNS_DUMP_DELAY);
16687
16688	/*
16689	 * Set resign time to make sure it is set to the earliest
16690	 * signature expiration.
16691	 */
16692	set_resigntime(zone);
16693	TIME_NOW(&timenow);
16694	zone_settimer(zone, &timenow);
16695	UNLOCK_ZONE(zone);
16696
16697	dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
16698	dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
16699
16700	if (newserial != 0) {
16701		dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
16702			     newserial, desired);
16703	}
16704
16705failure:
16706	isc_event_free(&zone->rss_event);
16707	event = ISC_LIST_HEAD(zone->rss_events);
16708
16709	if (zone->rss_raw != NULL) {
16710		dns_zone_detach(&zone->rss_raw);
16711	}
16712	if (result != ISC_R_SUCCESS) {
16713		LOCK_ZONE(zone);
16714		set_resigntime(zone);
16715		TIME_NOW(&timenow);
16716		zone_settimer(zone, &timenow);
16717		UNLOCK_ZONE(zone);
16718		dns_zone_log(zone, level, "receive_secure_serial: %s",
16719			     dns_result_totext(result));
16720	}
16721	if (tuple != NULL) {
16722		dns_difftuple_free(&tuple);
16723	}
16724	if (soatuple != NULL) {
16725		dns_difftuple_free(&soatuple);
16726	}
16727	if (zone->rss_db != NULL) {
16728		if (zone->rss_oldver != NULL) {
16729			dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
16730					    false);
16731		}
16732		if (zone->rss_newver != NULL) {
16733			dns_db_closeversion(zone->rss_db, &zone->rss_newver,
16734					    false);
16735		}
16736		dns_db_detach(&zone->rss_db);
16737	}
16738	INSIST(zone->rss_oldver == NULL);
16739	INSIST(zone->rss_newver == NULL);
16740	if (rjournal != NULL) {
16741		dns_journal_destroy(&rjournal);
16742	}
16743	dns_diff_clear(&zone->rss_diff);
16744
16745	if (event != NULL) {
16746		LOCK_ZONE(zone);
16747		isc_refcount_decrement(&zone->irefs);
16748		ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
16749		goto nextevent;
16750	}
16751
16752	event = ISC_LIST_HEAD(zone->rss_post);
16753	while (event != NULL) {
16754		ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
16755		rss_post(zone, event);
16756		event = ISC_LIST_HEAD(zone->rss_post);
16757	}
16758
16759	dns_zone_idetach(&zone);
16760}
16761
16762static isc_result_t
16763zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
16764	isc_event_t *e;
16765	dns_zone_t *dummy = NULL;
16766
16767	e = isc_event_allocate(zone->secure->mctx, zone,
16768			       DNS_EVENT_ZONESECURESERIAL,
16769			       receive_secure_serial, zone->secure,
16770			       sizeof(struct secure_event));
16771	((struct secure_event *)e)->serial = serial;
16772	INSIST(LOCKED_ZONE(zone->secure));
16773	zone_iattach(zone->secure, &dummy);
16774	isc_task_send(zone->secure->task, &e);
16775
16776	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
16777	return (ISC_R_SUCCESS);
16778}
16779
16780static isc_result_t
16781checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
16782	       dns_rdataset_t *rdataset, uint32_t oldserial) {
16783	dns_rdata_soa_t soa;
16784	dns_rdata_t rdata = DNS_RDATA_INIT;
16785	dns_rdatalist_t temprdatalist;
16786	dns_rdataset_t temprdataset;
16787	isc_buffer_t b;
16788	isc_result_t result;
16789	unsigned char buf[DNS_SOA_BUFFERSIZE];
16790	dns_fixedname_t fixed;
16791	dns_name_t *name;
16792
16793	result = dns_rdataset_first(rdataset);
16794	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16795	dns_rdataset_current(rdataset, &rdata);
16796	result = dns_rdata_tostruct(&rdata, &soa, NULL);
16797	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16798
16799	if (isc_serial_gt(soa.serial, oldserial)) {
16800		return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
16801					   NULL));
16802	}
16803	/*
16804	 * Always bump the serial.
16805	 */
16806	oldserial++;
16807	if (oldserial == 0) {
16808		oldserial++;
16809	}
16810	soa.serial = oldserial;
16811
16812	/*
16813	 * Construct a replacement rdataset.
16814	 */
16815	dns_rdata_reset(&rdata);
16816	isc_buffer_init(&b, buf, sizeof(buf));
16817	result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
16818				      dns_rdatatype_soa, &soa, &b);
16819	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16820	dns_rdatalist_init(&temprdatalist);
16821	temprdatalist.rdclass = rdata.rdclass;
16822	temprdatalist.type = rdata.type;
16823	temprdatalist.ttl = rdataset->ttl;
16824	ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
16825
16826	dns_rdataset_init(&temprdataset);
16827	result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
16828	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16829
16830	name = dns_fixedname_initname(&fixed);
16831	result = dns_db_nodefullname(db, node, name);
16832	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16833	dns_rdataset_getownercase(rdataset, name);
16834	dns_rdataset_setownercase(&temprdataset, name);
16835	return (dns_db_addrdataset(db, node, version, 0, &temprdataset, 0,
16836				   NULL));
16837}
16838
16839/*
16840 * This function should populate an nsec3paramlist_t with the
16841 * nsecparam_t data from a zone.
16842 */
16843static isc_result_t
16844save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
16845	isc_result_t result;
16846	dns_dbnode_t *node = NULL;
16847	dns_rdataset_t rdataset, prdataset;
16848	dns_dbversion_t *version = NULL;
16849	nsec3param_t *nsec3param = NULL;
16850	nsec3param_t *nsec3p = NULL;
16851	nsec3param_t *next;
16852	dns_db_t *db = NULL;
16853	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16854
16855	REQUIRE(DNS_ZONE_VALID(zone));
16856	REQUIRE(nsec3list != NULL);
16857	REQUIRE(ISC_LIST_EMPTY(*nsec3list));
16858
16859	dns_rdataset_init(&rdataset);
16860	dns_rdataset_init(&prdataset);
16861
16862	dns_db_attach(zone->db, &db);
16863	CHECK(dns_db_getoriginnode(db, &node));
16864
16865	dns_db_currentversion(db, &version);
16866	result = dns_db_findrdataset(db, node, version,
16867				     dns_rdatatype_nsec3param,
16868				     dns_rdatatype_none, 0, &rdataset, NULL);
16869
16870	if (result != ISC_R_SUCCESS) {
16871		goto getprivate;
16872	}
16873
16874	/*
16875	 * Walk nsec3param rdataset making a list of parameters (note that
16876	 * multiple simultaneous nsec3 chains are annoyingly legal -- this
16877	 * is why we use an nsec3list, even though we will usually only
16878	 * have one).
16879	 */
16880	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
16881	     result = dns_rdataset_next(&rdataset))
16882	{
16883		dns_rdata_t rdata = DNS_RDATA_INIT;
16884		dns_rdata_t private = DNS_RDATA_INIT;
16885
16886		dns_rdataset_current(&rdataset, &rdata);
16887		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16888			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16889			      "looping through nsec3param data");
16890		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16891		ISC_LINK_INIT(nsec3param, link);
16892
16893		/*
16894		 * now transfer the data from the rdata to
16895		 * the nsec3param
16896		 */
16897		dns_nsec3param_toprivate(&rdata, &private, zone->privatetype,
16898					 nsec3param->data,
16899					 sizeof(nsec3param->data));
16900		nsec3param->length = private.length;
16901		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16902	}
16903
16904getprivate:
16905	result = dns_db_findrdataset(db, node, version, zone->privatetype,
16906				     dns_rdatatype_none, 0, &prdataset, NULL);
16907	if (result != ISC_R_SUCCESS) {
16908		goto done;
16909	}
16910
16911	/*
16912	 * walk private type records, converting them to nsec3 parameters
16913	 * using dns_nsec3param_fromprivate(), do the right thing based on
16914	 * CREATE and REMOVE flags
16915	 */
16916	for (result = dns_rdataset_first(&prdataset); result == ISC_R_SUCCESS;
16917	     result = dns_rdataset_next(&prdataset))
16918	{
16919		dns_rdata_t rdata = DNS_RDATA_INIT;
16920		dns_rdata_t private = DNS_RDATA_INIT;
16921
16922		dns_rdataset_current(&prdataset, &private);
16923		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16924			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16925			      "looping through nsec3param private data");
16926
16927		/*
16928		 * Do we have a valid private record?
16929		 */
16930		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
16931						sizeof(buf)))
16932		{
16933			continue;
16934		}
16935
16936		/*
16937		 * Remove any NSEC3PARAM records scheduled to be removed.
16938		 */
16939		if (NSEC3REMOVE(rdata.data[1])) {
16940			/*
16941			 * Zero out the flags.
16942			 */
16943			rdata.data[1] = 0;
16944
16945			for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL;
16946			     nsec3p = next)
16947			{
16948				next = ISC_LIST_NEXT(nsec3p, link);
16949
16950				if (nsec3p->length == rdata.length + 1 &&
16951				    memcmp(rdata.data, nsec3p->data + 1,
16952					   nsec3p->length - 1) == 0)
16953				{
16954					ISC_LIST_UNLINK(*nsec3list, nsec3p,
16955							link);
16956					isc_mem_put(zone->mctx, nsec3p,
16957						    sizeof(nsec3param_t));
16958				}
16959			}
16960			continue;
16961		}
16962
16963		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16964		ISC_LINK_INIT(nsec3param, link);
16965
16966		/*
16967		 * Copy the remaining private records so the nsec/nsec3
16968		 * chain gets created.
16969		 */
16970		INSIST(private.length <= sizeof(nsec3param->data));
16971		memmove(nsec3param->data, private.data, private.length);
16972		nsec3param->length = private.length;
16973		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16974	}
16975
16976done:
16977	if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) {
16978		result = ISC_R_SUCCESS;
16979	}
16980
16981failure:
16982	if (node != NULL) {
16983		dns_db_detachnode(db, &node);
16984	}
16985	if (version != NULL) {
16986		dns_db_closeversion(db, &version, false);
16987	}
16988	if (db != NULL) {
16989		dns_db_detach(&db);
16990	}
16991	if (dns_rdataset_isassociated(&rdataset)) {
16992		dns_rdataset_disassociate(&rdataset);
16993	}
16994	if (dns_rdataset_isassociated(&prdataset)) {
16995		dns_rdataset_disassociate(&prdataset);
16996	}
16997	return (result);
16998}
16999
17000/*
17001 * Populate new zone db with private type records found by save_nsec3param().
17002 */
17003static isc_result_t
17004restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
17005		   nsec3paramlist_t *nsec3list) {
17006	isc_result_t result = ISC_R_SUCCESS;
17007	dns_diff_t diff;
17008	dns_rdata_t rdata;
17009	nsec3param_t *nsec3p = NULL;
17010	nsec3param_t *next;
17011
17012	REQUIRE(DNS_ZONE_VALID(zone));
17013	REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
17014
17015	dns_diff_init(zone->mctx, &diff);
17016
17017	/*
17018	 * Loop through the list of private-type records, set the INITIAL
17019	 * and CREATE flags, and the add the record to the apex of the tree
17020	 * in db.
17021	 */
17022	for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next)
17023	{
17024		next = ISC_LIST_NEXT(nsec3p, link);
17025		dns_rdata_init(&rdata);
17026		nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
17027		rdata.length = nsec3p->length;
17028		rdata.data = nsec3p->data;
17029		rdata.type = zone->privatetype;
17030		rdata.rdclass = zone->rdclass;
17031		result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
17032				       &zone->origin, 0, &rdata);
17033		if (result != ISC_R_SUCCESS) {
17034			break;
17035		}
17036	}
17037
17038	dns_diff_clear(&diff);
17039	return (result);
17040}
17041
17042static isc_result_t
17043copy_non_dnssec_records(dns_db_t *db, dns_db_t *version, dns_db_t *rawdb,
17044			dns_dbiterator_t *dbiterator, unsigned int *oldserial) {
17045	dns_dbnode_t *rawnode = NULL, *node = NULL;
17046	dns_fixedname_t fixed;
17047	dns_name_t *name = dns_fixedname_initname(&fixed);
17048	dns_rdataset_t rdataset;
17049	dns_rdatasetiter_t *rdsit = NULL;
17050	isc_result_t result;
17051
17052	result = dns_dbiterator_current(dbiterator, &rawnode, name);
17053	if (result != ISC_R_SUCCESS) {
17054		return (ISC_R_SUCCESS);
17055	}
17056
17057	dns_dbiterator_pause(dbiterator);
17058
17059	result = dns_db_findnode(db, name, true, &node);
17060	if (result != ISC_R_SUCCESS) {
17061		goto cleanup;
17062	}
17063
17064	result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, 0, &rdsit);
17065	if (result != ISC_R_SUCCESS) {
17066		goto cleanup;
17067	}
17068
17069	dns_rdataset_init(&rdataset);
17070
17071	for (result = dns_rdatasetiter_first(rdsit); result == ISC_R_SUCCESS;
17072	     result = dns_rdatasetiter_next(rdsit))
17073	{
17074		dns_rdatasetiter_current(rdsit, &rdataset);
17075		if (rdataset.type == dns_rdatatype_nsec ||
17076		    rdataset.type == dns_rdatatype_rrsig ||
17077		    rdataset.type == dns_rdatatype_nsec3 ||
17078		    rdataset.type == dns_rdatatype_dnskey ||
17079		    rdataset.type == dns_rdatatype_nsec3param)
17080		{
17081			dns_rdataset_disassociate(&rdataset);
17082			continue;
17083		}
17084		if (rdataset.type == dns_rdatatype_soa && oldserial != NULL) {
17085			result = checkandaddsoa(db, node, version, &rdataset,
17086						*oldserial);
17087		} else {
17088			result = dns_db_addrdataset(db, node, version, 0,
17089						    &rdataset, 0, NULL);
17090		}
17091		dns_rdataset_disassociate(&rdataset);
17092		if (result != ISC_R_SUCCESS) {
17093			goto cleanup;
17094		}
17095	}
17096	if (result == ISC_R_NOMORE) {
17097		result = ISC_R_SUCCESS;
17098	}
17099
17100cleanup:
17101	if (rdsit != NULL) {
17102		dns_rdatasetiter_destroy(&rdsit);
17103	}
17104	if (rawnode) {
17105		dns_db_detachnode(rawdb, &rawnode);
17106	}
17107	if (node) {
17108		dns_db_detachnode(db, &node);
17109	}
17110	return (result);
17111}
17112
17113static void
17114receive_secure_db(isc_task_t *task, isc_event_t *event) {
17115	isc_result_t result;
17116	dns_zone_t *zone;
17117	dns_db_t *rawdb, *db = NULL;
17118	dns_dbiterator_t *dbiterator = NULL;
17119	dns_dbversion_t *version = NULL;
17120	isc_time_t loadtime;
17121	unsigned int oldserial = 0, *oldserialp = NULL;
17122	nsec3paramlist_t nsec3list;
17123	isc_event_t *setnsec3param_event;
17124	dns_zone_t *dummy;
17125
17126	UNUSED(task);
17127
17128	ISC_LIST_INIT(nsec3list);
17129
17130	zone = event->ev_arg;
17131	rawdb = ((struct secure_event *)event)->db;
17132	isc_event_free(&event);
17133
17134	LOCK_ZONE(zone);
17135	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
17136		result = ISC_R_SHUTTINGDOWN;
17137		goto failure;
17138	}
17139
17140	TIME_NOW(&loadtime);
17141	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17142	if (zone->db != NULL) {
17143		result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
17144		if (result == ISC_R_SUCCESS) {
17145			oldserialp = &oldserial;
17146		}
17147
17148		/*
17149		 * assemble nsec3parameters from the old zone, and set a flag
17150		 * if any are found
17151		 */
17152		result = save_nsec3param(zone, &nsec3list);
17153		if (result != ISC_R_SUCCESS) {
17154			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17155			goto failure;
17156		}
17157	}
17158	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17159
17160	result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
17161			       dns_dbtype_zone, zone->rdclass,
17162			       zone->db_argc - 1, zone->db_argv + 1, &db);
17163	if (result != ISC_R_SUCCESS) {
17164		goto failure;
17165	}
17166
17167	result = dns_db_setgluecachestats(db, zone->gluecachestats);
17168	if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
17169		goto failure;
17170	}
17171
17172	result = dns_db_newversion(db, &version);
17173	if (result != ISC_R_SUCCESS) {
17174		goto failure;
17175	}
17176
17177	result = dns_db_createiterator(rawdb, 0, &dbiterator);
17178	if (result != ISC_R_SUCCESS) {
17179		goto failure;
17180	}
17181
17182	for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
17183	     result = dns_dbiterator_next(dbiterator))
17184	{
17185		result = copy_non_dnssec_records(db, version, rawdb, dbiterator,
17186						 oldserialp);
17187		if (result != ISC_R_SUCCESS) {
17188			goto failure;
17189		}
17190	}
17191	dns_dbiterator_destroy(&dbiterator);
17192	if (result != ISC_R_NOMORE) {
17193		goto failure;
17194	}
17195
17196	/*
17197	 * Call restore_nsec3param() to create private-type records from
17198	 * the old nsec3 parameters and insert them into db
17199	 */
17200	if (!ISC_LIST_EMPTY(nsec3list)) {
17201		result = restore_nsec3param(zone, db, version, &nsec3list);
17202		if (result != ISC_R_SUCCESS) {
17203			goto failure;
17204		}
17205	}
17206
17207	dns_db_closeversion(db, &version, true);
17208
17209	/*
17210	 * Lock hierarchy: zmgr, zone, raw.
17211	 */
17212	INSIST(zone != zone->raw);
17213	LOCK_ZONE(zone->raw);
17214	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17215	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
17216	zone_needdump(zone, 0); /* XXXMPA */
17217	UNLOCK_ZONE(zone->raw);
17218
17219	/*
17220	 * Process any queued NSEC3PARAM change requests.
17221	 */
17222	while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
17223		setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
17224		ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
17225				ev_link);
17226		dummy = NULL;
17227		zone_iattach(zone, &dummy);
17228		isc_task_send(zone->task, &setnsec3param_event);
17229	}
17230
17231failure:
17232	UNLOCK_ZONE(zone);
17233	if (dbiterator != NULL) {
17234		dns_dbiterator_destroy(&dbiterator);
17235	}
17236	if (result != ISC_R_SUCCESS) {
17237		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
17238			     dns_result_totext(result));
17239	}
17240
17241	while (!ISC_LIST_EMPTY(nsec3list)) {
17242		nsec3param_t *nsec3p;
17243		nsec3p = ISC_LIST_HEAD(nsec3list);
17244		ISC_LIST_UNLINK(nsec3list, nsec3p, link);
17245		isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
17246	}
17247	if (db != NULL) {
17248		if (version != NULL) {
17249			dns_db_closeversion(db, &version, false);
17250		}
17251		dns_db_detach(&db);
17252	}
17253	dns_db_detach(&rawdb);
17254	dns_zone_idetach(&zone);
17255
17256	INSIST(version == NULL);
17257}
17258
17259static isc_result_t
17260zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
17261	isc_event_t *e;
17262	dns_db_t *dummy = NULL;
17263	dns_zone_t *secure = NULL;
17264
17265	e = isc_event_allocate(zone->secure->mctx, zone, DNS_EVENT_ZONESECUREDB,
17266			       receive_secure_db, zone->secure,
17267			       sizeof(struct secure_event));
17268	dns_db_attach(db, &dummy);
17269	((struct secure_event *)e)->db = dummy;
17270	INSIST(LOCKED_ZONE(zone->secure));
17271	zone_iattach(zone->secure, &secure);
17272	isc_task_send(zone->secure->task, &e);
17273	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
17274	return (ISC_R_SUCCESS);
17275}
17276
17277isc_result_t
17278dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17279	isc_result_t result;
17280	dns_zone_t *secure = NULL;
17281
17282	REQUIRE(DNS_ZONE_VALID(zone));
17283again:
17284	LOCK_ZONE(zone);
17285	if (inline_raw(zone)) {
17286		secure = zone->secure;
17287		INSIST(secure != zone);
17288		TRYLOCK_ZONE(result, secure);
17289		if (result != ISC_R_SUCCESS) {
17290			UNLOCK_ZONE(zone);
17291			secure = NULL;
17292			isc_thread_yield();
17293			goto again;
17294		}
17295	}
17296	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
17297	result = zone_replacedb(zone, db, dump);
17298	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
17299	if (secure != NULL) {
17300		UNLOCK_ZONE(secure);
17301	}
17302	UNLOCK_ZONE(zone);
17303	return (result);
17304}
17305
17306static isc_result_t
17307zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17308	dns_dbversion_t *ver;
17309	isc_result_t result;
17310	unsigned int soacount = 0;
17311	unsigned int nscount = 0;
17312
17313	/*
17314	 * 'zone' and 'zone->db' locked by caller.
17315	 */
17316	REQUIRE(DNS_ZONE_VALID(zone));
17317	REQUIRE(LOCKED_ZONE(zone));
17318	if (inline_raw(zone)) {
17319		REQUIRE(LOCKED_ZONE(zone->secure));
17320	}
17321
17322	result = zone_get_from_db(zone, db, &nscount, &soacount, NULL, NULL,
17323				  NULL, NULL, NULL, NULL, NULL);
17324	if (result == ISC_R_SUCCESS) {
17325		if (soacount != 1) {
17326			dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records",
17327				     soacount);
17328			result = DNS_R_BADZONE;
17329		}
17330		if (nscount == 0 && zone->type != dns_zone_key) {
17331			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
17332			result = DNS_R_BADZONE;
17333		}
17334		if (result != ISC_R_SUCCESS) {
17335			return (result);
17336		}
17337	} else {
17338		dns_zone_log(zone, ISC_LOG_ERROR,
17339			     "retrieving SOA and NS records failed: %s",
17340			     dns_result_totext(result));
17341		return (result);
17342	}
17343
17344	result = check_nsec3param(zone, db);
17345	if (result != ISC_R_SUCCESS) {
17346		return (result);
17347	}
17348
17349	ver = NULL;
17350	dns_db_currentversion(db, &ver);
17351
17352	/*
17353	 * The initial version of a slave zone is always dumped;
17354	 * subsequent versions may be journaled instead if this
17355	 * is enabled in the configuration.
17356	 */
17357	if (zone->db != NULL && zone->journal != NULL &&
17358	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
17359	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
17360	{
17361		uint32_t serial, oldserial;
17362
17363		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
17364
17365		result = dns_db_getsoaserial(db, ver, &serial);
17366		if (result != ISC_R_SUCCESS) {
17367			dns_zone_log(zone, ISC_LOG_ERROR,
17368				     "ixfr-from-differences: unable to get "
17369				     "new serial");
17370			goto fail;
17371		}
17372
17373		/*
17374		 * This is checked in zone_postload() for master zones.
17375		 */
17376		result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
17377					  &oldserial, NULL, NULL, NULL, NULL,
17378					  NULL);
17379		RUNTIME_CHECK(result == ISC_R_SUCCESS);
17380		RUNTIME_CHECK(soacount > 0U);
17381		if ((zone->type == dns_zone_secondary ||
17382		     (zone->type == dns_zone_redirect &&
17383		      zone->masters != NULL)) &&
17384		    !isc_serial_gt(serial, oldserial))
17385		{
17386			uint32_t serialmin, serialmax;
17387			serialmin = (oldserial + 1) & 0xffffffffU;
17388			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
17389			dns_zone_log(zone, ISC_LOG_ERROR,
17390				     "ixfr-from-differences: failed: "
17391				     "new serial (%u) out of range [%u - %u]",
17392				     serial, serialmin, serialmax);
17393			result = ISC_R_RANGE;
17394			goto fail;
17395		}
17396
17397		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
17398				     zone->journal);
17399		if (result != ISC_R_SUCCESS) {
17400			char strbuf[ISC_STRERRORSIZE];
17401			strerror_r(errno, strbuf, sizeof(strbuf));
17402			dns_zone_log(zone, ISC_LOG_ERROR,
17403				     "ixfr-from-differences: failed: "
17404				     "%s",
17405				     strbuf);
17406			goto fallback;
17407		}
17408		if (dump) {
17409			zone_needdump(zone, DNS_DUMP_DELAY);
17410		} else {
17411			zone_journal_compact(zone, zone->db, serial);
17412		}
17413		if (zone->type == dns_zone_primary && inline_raw(zone)) {
17414			zone_send_secureserial(zone, serial);
17415		}
17416	} else {
17417	fallback:
17418		if (dump && zone->masterfile != NULL) {
17419			/*
17420			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
17421			 * to keep the old masterfile.
17422			 */
17423			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
17424			    remove(zone->masterfile) < 0 && errno != ENOENT)
17425			{
17426				char strbuf[ISC_STRERRORSIZE];
17427				strerror_r(errno, strbuf, sizeof(strbuf));
17428				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17429					      DNS_LOGMODULE_ZONE,
17430					      ISC_LOG_WARNING,
17431					      "unable to remove masterfile "
17432					      "'%s': '%s'",
17433					      zone->masterfile, strbuf);
17434			}
17435			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
17436				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
17437			} else {
17438				zone_needdump(zone, 0);
17439			}
17440		}
17441		if (dump && zone->journal != NULL) {
17442			/*
17443			 * The in-memory database just changed, and
17444			 * because 'dump' is set, it didn't change by
17445			 * being loaded from disk.  Also, we have not
17446			 * journaled diffs for this change.
17447			 * Therefore, the on-disk journal is missing
17448			 * the deltas for this change.	Since it can
17449			 * no longer be used to bring the zone
17450			 * up-to-date, it is useless and should be
17451			 * removed.
17452			 */
17453			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17454				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
17455				      "removing journal file");
17456			if (remove(zone->journal) < 0 && errno != ENOENT) {
17457				char strbuf[ISC_STRERRORSIZE];
17458				strerror_r(errno, strbuf, sizeof(strbuf));
17459				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17460					      DNS_LOGMODULE_ZONE,
17461					      ISC_LOG_WARNING,
17462					      "unable to remove journal "
17463					      "'%s': '%s'",
17464					      zone->journal, strbuf);
17465			}
17466		}
17467
17468		if (inline_raw(zone)) {
17469			zone_send_securedb(zone, db);
17470		}
17471	}
17472
17473	dns_db_closeversion(db, &ver, false);
17474
17475	dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
17476
17477	if (zone->db != NULL) {
17478		zone_detachdb(zone);
17479	}
17480	zone_attachdb(zone, db);
17481	dns_db_settask(zone->db, zone->task);
17482	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
17483	return (ISC_R_SUCCESS);
17484
17485fail:
17486	dns_db_closeversion(db, &ver, false);
17487	return (result);
17488}
17489
17490/* The caller must hold the dblock as a writer. */
17491static void
17492zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
17493	REQUIRE(zone->db == NULL && db != NULL);
17494
17495	dns_db_attach(db, &zone->db);
17496}
17497
17498/* The caller must hold the dblock as a writer. */
17499static void
17500zone_detachdb(dns_zone_t *zone) {
17501	REQUIRE(zone->db != NULL);
17502
17503	dns_zone_rpz_disable_db(zone, zone->db);
17504	dns_zone_catz_disable_db(zone, zone->db);
17505	dns_db_detach(&zone->db);
17506}
17507
17508static void
17509zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
17510	isc_time_t now;
17511	bool again = false;
17512	unsigned int soacount;
17513	unsigned int nscount;
17514	uint32_t serial, refresh, retry, expire, minimum, soattl;
17515	isc_result_t xfrresult = result;
17516	bool free_needed;
17517	dns_zone_t *secure = NULL;
17518
17519	REQUIRE(DNS_ZONE_VALID(zone));
17520
17521	dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17522		      "zone transfer finished: %s", dns_result_totext(result));
17523
17524	/*
17525	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
17526	 * could result in a deadlock due to a LOR so we will spin if we
17527	 * can't obtain the both locks.
17528	 */
17529again:
17530	LOCK_ZONE(zone);
17531	if (inline_raw(zone)) {
17532		secure = zone->secure;
17533		INSIST(secure != zone);
17534		TRYLOCK_ZONE(result, secure);
17535		if (result != ISC_R_SUCCESS) {
17536			UNLOCK_ZONE(zone);
17537			secure = NULL;
17538			isc_thread_yield();
17539			goto again;
17540		}
17541	}
17542
17543	INSIST(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH));
17544	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
17545	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
17546
17547	TIME_NOW(&now);
17548	switch (xfrresult) {
17549	case ISC_R_SUCCESS:
17550		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17551		FALLTHROUGH;
17552	case DNS_R_UPTODATE:
17553		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17554		/*
17555		 * Has the zone expired underneath us?
17556		 */
17557		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17558		if (zone->db == NULL) {
17559			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17560			goto same_master;
17561		}
17562
17563		/*
17564		 * Update the zone structure's data from the actual
17565		 * SOA received.
17566		 */
17567		nscount = 0;
17568		soacount = 0;
17569		INSIST(zone->db != NULL);
17570		result = zone_get_from_db(zone, zone->db, &nscount, &soacount,
17571					  &soattl, &serial, &refresh, &retry,
17572					  &expire, &minimum, NULL);
17573		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17574		if (result == ISC_R_SUCCESS) {
17575			if (soacount != 1) {
17576				dns_zone_log(zone, ISC_LOG_ERROR,
17577					     "transferred zone "
17578					     "has %d SOA records",
17579					     soacount);
17580				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17581				{
17582					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17583					zone->retry = DNS_ZONE_DEFAULTRETRY;
17584				}
17585				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17586				zone_unload(zone);
17587				goto next_master;
17588			}
17589			if (nscount == 0) {
17590				dns_zone_log(zone, ISC_LOG_ERROR,
17591					     "transferred zone "
17592					     "has no NS records");
17593				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17594				{
17595					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17596					zone->retry = DNS_ZONE_DEFAULTRETRY;
17597				}
17598				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17599				zone_unload(zone);
17600				goto next_master;
17601			}
17602			zone->refresh = RANGE(refresh, zone->minrefresh,
17603					      zone->maxrefresh);
17604			zone->retry = RANGE(retry, zone->minretry,
17605					    zone->maxretry);
17606			zone->expire = RANGE(expire,
17607					     zone->refresh + zone->retry,
17608					     DNS_MAX_EXPIRE);
17609			zone->soattl = soattl;
17610			zone->minimum = minimum;
17611			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17612		}
17613
17614		/*
17615		 * Set our next update/expire times.
17616		 */
17617		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
17618			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
17619			zone->refreshtime = now;
17620			DNS_ZONE_TIME_ADD(&now, zone->expire,
17621					  &zone->expiretime);
17622		} else {
17623			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
17624					    &zone->refreshtime);
17625			DNS_ZONE_TIME_ADD(&now, zone->expire,
17626					  &zone->expiretime);
17627		}
17628		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
17629			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
17630			if (zone->tsigkey != NULL) {
17631				char namebuf[DNS_NAME_FORMATSIZE];
17632				dns_name_format(&zone->tsigkey->name, namebuf,
17633						sizeof(namebuf));
17634				snprintf(buf, sizeof(buf), ": TSIG '%s'",
17635					 namebuf);
17636			} else {
17637				buf[0] = '\0';
17638			}
17639			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17640				      ISC_LOG_INFO, "transferred serial %u%s",
17641				      serial, buf);
17642			if (inline_raw(zone)) {
17643				zone_send_secureserial(zone, serial);
17644			}
17645		}
17646
17647		/*
17648		 * This is not necessary if we just performed a AXFR
17649		 * however it is necessary for an IXFR / UPTODATE and
17650		 * won't hurt with an AXFR.
17651		 */
17652		if (zone->masterfile != NULL || zone->journal != NULL) {
17653			unsigned int delay = DNS_DUMP_DELAY;
17654
17655			result = ISC_R_FAILURE;
17656			if (zone->journal != NULL) {
17657				result = isc_file_settime(zone->journal, &now);
17658			}
17659			if (result != ISC_R_SUCCESS && zone->masterfile != NULL)
17660			{
17661				result = isc_file_settime(zone->masterfile,
17662							  &now);
17663			}
17664
17665			if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
17666			    result == ISC_R_FILENOTFOUND)
17667			{
17668				delay = 0;
17669			}
17670
17671			if ((result == ISC_R_SUCCESS ||
17672			     result == ISC_R_FILENOTFOUND) &&
17673			    zone->masterfile != NULL)
17674			{
17675				zone_needdump(zone, delay);
17676			} else if (result != ISC_R_SUCCESS) {
17677				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17678					      ISC_LOG_ERROR,
17679					      "transfer: could not set file "
17680					      "modification time of '%s': %s",
17681					      zone->masterfile,
17682					      dns_result_totext(result));
17683			}
17684		}
17685		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
17686		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
17687		break;
17688
17689	case DNS_R_BADIXFR:
17690		/* Force retry with AXFR. */
17691		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOIXFR);
17692		goto same_master;
17693
17694	case DNS_R_TOOMANYRECORDS:
17695	case DNS_R_VERIFYFAILURE:
17696		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
17697		inc_stats(zone, dns_zonestatscounter_xfrfail);
17698		break;
17699
17700	default:
17701	next_master:
17702		/*
17703		 * Skip to next failed / untried master.
17704		 */
17705		do {
17706			zone->curmaster++;
17707		} while (zone->curmaster < zone->masterscnt &&
17708			 zone->mastersok[zone->curmaster]);
17709	same_master:
17710		if (zone->curmaster >= zone->masterscnt) {
17711			zone->curmaster = 0;
17712			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
17713			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
17714			{
17715				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17716				DNS_ZONE_SETFLAG(zone,
17717						 DNS_ZONEFLG_USEALTXFRSRC);
17718				while (zone->curmaster < zone->masterscnt &&
17719				       zone->mastersok[zone->curmaster])
17720				{
17721					zone->curmaster++;
17722				}
17723				again = true;
17724			} else {
17725				DNS_ZONE_CLRFLAG(zone,
17726						 DNS_ZONEFLG_USEALTXFRSRC);
17727			}
17728		} else {
17729			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17730			again = true;
17731		}
17732		inc_stats(zone, dns_zonestatscounter_xfrfail);
17733		break;
17734	}
17735	zone_settimer(zone, &now);
17736
17737	/*
17738	 * If creating the transfer object failed, zone->xfr is NULL.
17739	 * Otherwise, we are called as the done callback of a zone
17740	 * transfer object that just entered its shutting-down
17741	 * state.  Since we are no longer responsible for shutting
17742	 * it down, we can detach our reference.
17743	 */
17744	if (zone->xfr != NULL) {
17745		dns_xfrin_detach(&zone->xfr);
17746	}
17747
17748	if (zone->tsigkey != NULL) {
17749		dns_tsigkey_detach(&zone->tsigkey);
17750	}
17751
17752	/*
17753	 * Handle any deferred journal compaction.
17754	 */
17755	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
17756		dns_db_t *db = NULL;
17757		if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
17758			zone_journal_compact(zone, db, zone->compact_serial);
17759			dns_db_detach(&db);
17760			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
17761		}
17762	}
17763
17764	if (secure != NULL) {
17765		UNLOCK_ZONE(secure);
17766	}
17767	/*
17768	 * This transfer finishing freed up a transfer quota slot.
17769	 * Let any other zones waiting for quota have it.
17770	 */
17771	if (zone->zmgr != NULL &&
17772	    zone->statelist == &zone->zmgr->xfrin_in_progress)
17773	{
17774		UNLOCK_ZONE(zone);
17775		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17776		ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
17777		zone->statelist = NULL;
17778		zmgr_resume_xfrs(zone->zmgr, false);
17779		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17780		LOCK_ZONE(zone);
17781	}
17782
17783	/*
17784	 * Retry with a different server if necessary.
17785	 */
17786	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17787		queue_soa_query(zone);
17788	}
17789
17790	isc_refcount_decrement(&zone->irefs);
17791	free_needed = exit_check(zone);
17792	UNLOCK_ZONE(zone);
17793	if (free_needed) {
17794		zone_free(zone);
17795	}
17796}
17797
17798static void
17799zone_loaddone(void *arg, isc_result_t result) {
17800	static char me[] = "zone_loaddone";
17801	dns_load_t *load = arg;
17802	dns_zone_t *zone;
17803	isc_result_t tresult;
17804	dns_zone_t *secure = NULL;
17805
17806	REQUIRE(DNS_LOAD_VALID(load));
17807	zone = load->zone;
17808
17809	ENTER;
17810
17811	/*
17812	 * If zone loading failed, remove the update db callbacks prior
17813	 * to calling the list of callbacks in the zone load structure.
17814	 */
17815	if (result != ISC_R_SUCCESS) {
17816		dns_zone_rpz_disable_db(zone, load->db);
17817		dns_zone_catz_disable_db(zone, load->db);
17818	}
17819
17820	tresult = dns_db_endload(load->db, &load->callbacks);
17821	if (tresult != ISC_R_SUCCESS &&
17822	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
17823	{
17824		result = tresult;
17825	}
17826
17827	/*
17828	 * Lock hierarchy: zmgr, zone, raw.
17829	 */
17830again:
17831	LOCK_ZONE(zone);
17832	INSIST(zone != zone->raw);
17833	if (inline_secure(zone)) {
17834		LOCK_ZONE(zone->raw);
17835	} else if (inline_raw(zone)) {
17836		secure = zone->secure;
17837		TRYLOCK_ZONE(tresult, secure);
17838		if (tresult != ISC_R_SUCCESS) {
17839			UNLOCK_ZONE(zone);
17840			secure = NULL;
17841			isc_thread_yield();
17842			goto again;
17843		}
17844	}
17845	(void)zone_postload(zone, load->db, load->loadtime, result);
17846	zonemgr_putio(&zone->readio);
17847	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
17848	zone_idetach(&load->callbacks.zone);
17849	/*
17850	 * Leave the zone frozen if the reload fails.
17851	 */
17852	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
17853	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
17854	{
17855		zone->update_disabled = false;
17856	}
17857	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
17858	if (inline_secure(zone)) {
17859		UNLOCK_ZONE(zone->raw);
17860	} else if (secure != NULL) {
17861		UNLOCK_ZONE(secure);
17862	}
17863	UNLOCK_ZONE(zone);
17864
17865	load->magic = 0;
17866	dns_db_detach(&load->db);
17867	if (load->zone->lctx != NULL) {
17868		dns_loadctx_detach(&load->zone->lctx);
17869	}
17870	dns_zone_idetach(&load->zone);
17871	isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
17872}
17873
17874void
17875dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
17876	REQUIRE(DNS_ZONE_VALID(zone));
17877	REQUIRE(table != NULL);
17878	REQUIRE(*table == NULL);
17879
17880	LOCK_ZONE(zone);
17881	if (zone->ssutable != NULL) {
17882		dns_ssutable_attach(zone->ssutable, table);
17883	}
17884	UNLOCK_ZONE(zone);
17885}
17886
17887void
17888dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
17889	REQUIRE(DNS_ZONE_VALID(zone));
17890
17891	LOCK_ZONE(zone);
17892	if (zone->ssutable != NULL) {
17893		dns_ssutable_detach(&zone->ssutable);
17894	}
17895	if (table != NULL) {
17896		dns_ssutable_attach(table, &zone->ssutable);
17897	}
17898	UNLOCK_ZONE(zone);
17899}
17900
17901void
17902dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17903	REQUIRE(DNS_ZONE_VALID(zone));
17904
17905	zone->sigvalidityinterval = interval;
17906}
17907
17908uint32_t
17909dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
17910	REQUIRE(DNS_ZONE_VALID(zone));
17911
17912	return (zone->sigvalidityinterval);
17913}
17914
17915void
17916dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17917	REQUIRE(DNS_ZONE_VALID(zone));
17918
17919	zone->keyvalidityinterval = interval;
17920}
17921
17922uint32_t
17923dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
17924	REQUIRE(DNS_ZONE_VALID(zone));
17925
17926	return (zone->keyvalidityinterval);
17927}
17928
17929void
17930dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
17931	isc_time_t now;
17932
17933	REQUIRE(DNS_ZONE_VALID(zone));
17934
17935	LOCK_ZONE(zone);
17936	zone->sigresigninginterval = interval;
17937	set_resigntime(zone);
17938	if (zone->task != NULL) {
17939		TIME_NOW(&now);
17940		zone_settimer(zone, &now);
17941	}
17942	UNLOCK_ZONE(zone);
17943}
17944
17945uint32_t
17946dns_zone_getsigresigninginterval(dns_zone_t *zone) {
17947	REQUIRE(DNS_ZONE_VALID(zone));
17948
17949	return (zone->sigresigninginterval);
17950}
17951
17952static void
17953queue_xfrin(dns_zone_t *zone) {
17954	const char me[] = "queue_xfrin";
17955	isc_result_t result;
17956	dns_zonemgr_t *zmgr = zone->zmgr;
17957
17958	ENTER;
17959
17960	INSIST(zone->statelist == NULL);
17961
17962	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17963	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
17964	isc_refcount_increment0(&zone->irefs);
17965	zone->statelist = &zmgr->waiting_for_xfrin;
17966	result = zmgr_start_xfrin_ifquota(zmgr, zone);
17967	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17968
17969	if (result == ISC_R_QUOTA) {
17970		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
17971			      "zone transfer deferred due to quota");
17972	} else if (result != ISC_R_SUCCESS) {
17973		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
17974			      "starting zone transfer: %s",
17975			      isc_result_totext(result));
17976	}
17977}
17978
17979/*
17980 * This event callback is called when a zone has received
17981 * any necessary zone transfer quota.  This is the time
17982 * to go ahead and start the transfer.
17983 */
17984static void
17985got_transfer_quota(isc_task_t *task, isc_event_t *event) {
17986	isc_result_t result = ISC_R_SUCCESS;
17987	dns_peer_t *peer = NULL;
17988	char master[ISC_SOCKADDR_FORMATSIZE];
17989	char source[ISC_SOCKADDR_FORMATSIZE];
17990	dns_rdatatype_t xfrtype;
17991	dns_zone_t *zone = event->ev_arg;
17992	isc_netaddr_t masterip;
17993	isc_sockaddr_t sourceaddr;
17994	isc_sockaddr_t masteraddr;
17995	isc_time_t now;
17996	const char *soa_before = "";
17997	isc_dscp_t dscp = -1;
17998	bool loaded;
17999
18000	UNUSED(task);
18001
18002	INSIST(task == zone->task);
18003
18004	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
18005		result = ISC_R_CANCELED;
18006		goto cleanup;
18007	}
18008
18009	TIME_NOW(&now);
18010
18011	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
18012	if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
18013				    &zone->sourceaddr, &now))
18014	{
18015		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
18016		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18017			      "got_transfer_quota: skipping zone transfer as "
18018			      "master %s (source %s) is unreachable (cached)",
18019			      master, source);
18020		result = ISC_R_CANCELED;
18021		goto cleanup;
18022	}
18023
18024	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
18025	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
18026
18027	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18028		soa_before = "SOA before ";
18029	}
18030	/*
18031	 * Decide whether we should request IXFR or AXFR.
18032	 */
18033	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18034	loaded = (zone->db != NULL);
18035	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18036
18037	if (!loaded) {
18038		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18039			      "no database exists yet, requesting AXFR of "
18040			      "initial version from %s",
18041			      master);
18042		xfrtype = dns_rdatatype_axfr;
18043	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
18044		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18045			      "forced reload, requesting AXFR of "
18046			      "initial version from %s",
18047			      master);
18048		xfrtype = dns_rdatatype_axfr;
18049	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOIXFR)) {
18050		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18051			      "retrying with AXFR from %s due to "
18052			      "previous IXFR failure",
18053			      master);
18054		xfrtype = dns_rdatatype_axfr;
18055		LOCK_ZONE(zone);
18056		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOIXFR);
18057		UNLOCK_ZONE(zone);
18058	} else {
18059		bool use_ixfr = true;
18060		if (peer != NULL) {
18061			result = dns_peer_getrequestixfr(peer, &use_ixfr);
18062		}
18063		if (peer == NULL || result != ISC_R_SUCCESS) {
18064			use_ixfr = zone->requestixfr;
18065		}
18066		if (!use_ixfr) {
18067			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18068				      ISC_LOG_DEBUG(1),
18069				      "IXFR disabled, "
18070				      "requesting %sAXFR from %s",
18071				      soa_before, master);
18072			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18073				xfrtype = dns_rdatatype_soa;
18074			} else {
18075				xfrtype = dns_rdatatype_axfr;
18076			}
18077		} else {
18078			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18079				      ISC_LOG_DEBUG(1),
18080				      "requesting IXFR from %s", master);
18081			xfrtype = dns_rdatatype_ixfr;
18082		}
18083	}
18084
18085	/*
18086	 * Determine if we should attempt to sign the request with TSIG.
18087	 */
18088	result = ISC_R_NOTFOUND;
18089
18090	/*
18091	 * First, look for a tsig key in the master statement, then
18092	 * try for a server key.
18093	 */
18094	if ((zone->masterkeynames != NULL) &&
18095	    (zone->masterkeynames[zone->curmaster] != NULL))
18096	{
18097		dns_view_t *view = dns_zone_getview(zone);
18098		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
18099		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
18100	}
18101	if (zone->tsigkey == NULL) {
18102		result = dns_view_getpeertsig(zone->view, &masterip,
18103					      &zone->tsigkey);
18104	}
18105
18106	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
18107		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
18108			      "could not get TSIG key for zone transfer: %s",
18109			      isc_result_totext(result));
18110	}
18111
18112	if (zone->masterdscps != NULL) {
18113		dscp = zone->masterdscps[zone->curmaster];
18114	}
18115
18116	LOCK_ZONE(zone);
18117	masteraddr = zone->masteraddr;
18118	sourceaddr = zone->sourceaddr;
18119	switch (isc_sockaddr_pf(&masteraddr)) {
18120	case PF_INET:
18121		if (dscp == -1) {
18122			dscp = zone->xfrsource4dscp;
18123		}
18124		break;
18125	case PF_INET6:
18126		if (dscp == -1) {
18127			dscp = zone->xfrsource6dscp;
18128		}
18129		break;
18130	default:
18131		UNREACHABLE();
18132	}
18133	UNLOCK_ZONE(zone);
18134	INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
18135	result = dns_xfrin_create(zone, xfrtype, &masteraddr, &sourceaddr, dscp,
18136				  zone->tsigkey, zone->mctx,
18137				  zone->zmgr->timermgr, zone->zmgr->socketmgr,
18138				  zone->task, zone_xfrdone, &zone->xfr);
18139	if (result == ISC_R_SUCCESS) {
18140		LOCK_ZONE(zone);
18141		if (xfrtype == dns_rdatatype_axfr) {
18142			if (isc_sockaddr_pf(&masteraddr) == PF_INET) {
18143				inc_stats(zone, dns_zonestatscounter_axfrreqv4);
18144			} else {
18145				inc_stats(zone, dns_zonestatscounter_axfrreqv6);
18146			}
18147		} else if (xfrtype == dns_rdatatype_ixfr) {
18148			if (isc_sockaddr_pf(&masteraddr) == PF_INET) {
18149				inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
18150			} else {
18151				inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
18152			}
18153		}
18154		UNLOCK_ZONE(zone);
18155	}
18156cleanup:
18157	/*
18158	 * Any failure in this function is handled like a failed
18159	 * zone transfer.  This ensures that we get removed from
18160	 * zmgr->xfrin_in_progress.
18161	 */
18162	if (result != ISC_R_SUCCESS) {
18163		zone_xfrdone(zone, result);
18164	}
18165
18166	isc_event_free(&event);
18167}
18168
18169/*
18170 * Update forwarding support.
18171 */
18172
18173static void
18174forward_destroy(dns_forward_t *forward) {
18175	forward->magic = 0;
18176	if (forward->request != NULL) {
18177		dns_request_destroy(&forward->request);
18178	}
18179	if (forward->msgbuf != NULL) {
18180		isc_buffer_free(&forward->msgbuf);
18181	}
18182	if (forward->zone != NULL) {
18183		LOCK(&forward->zone->lock);
18184		if (ISC_LINK_LINKED(forward, link)) {
18185			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
18186		}
18187		UNLOCK(&forward->zone->lock);
18188		dns_zone_idetach(&forward->zone);
18189	}
18190	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
18191}
18192
18193static isc_result_t
18194sendtomaster(dns_forward_t *forward) {
18195	isc_result_t result;
18196	isc_sockaddr_t src;
18197	isc_dscp_t dscp = -1;
18198
18199	LOCK_ZONE(forward->zone);
18200
18201	if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
18202		UNLOCK_ZONE(forward->zone);
18203		return (ISC_R_CANCELED);
18204	}
18205
18206	if (forward->which >= forward->zone->masterscnt) {
18207		UNLOCK_ZONE(forward->zone);
18208		return (ISC_R_NOMORE);
18209	}
18210
18211	forward->addr = forward->zone->masters[forward->which];
18212	/*
18213	 * Always use TCP regardless of whether the original update
18214	 * used TCP.
18215	 * XXX The timeout may but a bit small if we are far down a
18216	 * transfer graph and the master has to try several masters.
18217	 */
18218	switch (isc_sockaddr_pf(&forward->addr)) {
18219	case PF_INET:
18220		src = forward->zone->xfrsource4;
18221		dscp = forward->zone->xfrsource4dscp;
18222		break;
18223	case PF_INET6:
18224		src = forward->zone->xfrsource6;
18225		dscp = forward->zone->xfrsource6dscp;
18226		break;
18227	default:
18228		result = ISC_R_NOTIMPLEMENTED;
18229		goto unlock;
18230	}
18231	result = dns_request_createraw(forward->zone->view->requestmgr,
18232				       forward->msgbuf, &src, &forward->addr,
18233				       dscp, forward->options, 15 /* XXX */, 0,
18234				       0, forward->zone->task, forward_callback,
18235				       forward, &forward->request);
18236	if (result == ISC_R_SUCCESS) {
18237		if (!ISC_LINK_LINKED(forward, link)) {
18238			ISC_LIST_APPEND(forward->zone->forwards, forward, link);
18239		}
18240	}
18241
18242unlock:
18243	UNLOCK_ZONE(forward->zone);
18244	return (result);
18245}
18246
18247static void
18248forward_callback(isc_task_t *task, isc_event_t *event) {
18249	const char me[] = "forward_callback";
18250	dns_requestevent_t *revent = (dns_requestevent_t *)event;
18251	dns_message_t *msg = NULL;
18252	char master[ISC_SOCKADDR_FORMATSIZE];
18253	isc_result_t result;
18254	dns_forward_t *forward;
18255	dns_zone_t *zone;
18256
18257	UNUSED(task);
18258
18259	forward = revent->ev_arg;
18260	INSIST(DNS_FORWARD_VALID(forward));
18261	zone = forward->zone;
18262	INSIST(DNS_ZONE_VALID(zone));
18263
18264	ENTER;
18265
18266	isc_sockaddr_format(&forward->addr, master, sizeof(master));
18267
18268	if (revent->result != ISC_R_SUCCESS) {
18269		dns_zone_log(zone, ISC_LOG_INFO,
18270			     "could not forward dynamic update to %s: %s",
18271			     master, dns_result_totext(revent->result));
18272		goto next_master;
18273	}
18274
18275	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
18276
18277	result = dns_request_getresponse(revent->request, msg,
18278					 DNS_MESSAGEPARSE_PRESERVEORDER |
18279						 DNS_MESSAGEPARSE_CLONEBUFFER);
18280	if (result != ISC_R_SUCCESS) {
18281		goto next_master;
18282	}
18283
18284	/*
18285	 * Unexpected opcode.
18286	 */
18287	if (msg->opcode != dns_opcode_update) {
18288		char opcode[128];
18289		isc_buffer_t rb;
18290
18291		isc_buffer_init(&rb, opcode, sizeof(opcode));
18292		(void)dns_opcode_totext(msg->opcode, &rb);
18293
18294		dns_zone_log(zone, ISC_LOG_INFO,
18295			     "forwarding dynamic update: "
18296			     "unexpected opcode (%.*s) from %s",
18297			     (int)rb.used, opcode, master);
18298		goto next_master;
18299	}
18300
18301	switch (msg->rcode) {
18302	/*
18303	 * Pass these rcodes back to client.
18304	 */
18305	case dns_rcode_noerror:
18306	case dns_rcode_yxdomain:
18307	case dns_rcode_yxrrset:
18308	case dns_rcode_nxrrset:
18309	case dns_rcode_refused:
18310	case dns_rcode_nxdomain: {
18311		char rcode[128];
18312		isc_buffer_t rb;
18313
18314		isc_buffer_init(&rb, rcode, sizeof(rcode));
18315		(void)dns_rcode_totext(msg->rcode, &rb);
18316		dns_zone_log(zone, ISC_LOG_INFO,
18317			     "forwarded dynamic update: "
18318			     "master %s returned: %.*s",
18319			     master, (int)rb.used, rcode);
18320		break;
18321	}
18322
18323	/* These should not occur if the primaries/zone are valid. */
18324	case dns_rcode_notzone:
18325	case dns_rcode_notauth: {
18326		char rcode[128];
18327		isc_buffer_t rb;
18328
18329		isc_buffer_init(&rb, rcode, sizeof(rcode));
18330		(void)dns_rcode_totext(msg->rcode, &rb);
18331		dns_zone_log(zone, ISC_LOG_WARNING,
18332			     "forwarding dynamic update: "
18333			     "unexpected response: master %s returned: %.*s",
18334			     master, (int)rb.used, rcode);
18335		goto next_master;
18336	}
18337
18338	/* Try another server for these rcodes. */
18339	case dns_rcode_formerr:
18340	case dns_rcode_servfail:
18341	case dns_rcode_notimp:
18342	case dns_rcode_badvers:
18343	default:
18344		goto next_master;
18345	}
18346
18347	/* call callback */
18348	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
18349	msg = NULL;
18350	dns_request_destroy(&forward->request);
18351	forward_destroy(forward);
18352	isc_event_free(&event);
18353	return;
18354
18355next_master:
18356	if (msg != NULL) {
18357		dns_message_detach(&msg);
18358	}
18359	isc_event_free(&event);
18360	forward->which++;
18361	dns_request_destroy(&forward->request);
18362	result = sendtomaster(forward);
18363	if (result != ISC_R_SUCCESS) {
18364		/* call callback */
18365		dns_zone_log(zone, ISC_LOG_DEBUG(3),
18366			     "exhausted dynamic update forwarder list");
18367		(forward->callback)(forward->callback_arg, result, NULL);
18368		forward_destroy(forward);
18369	}
18370}
18371
18372isc_result_t
18373dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
18374		       dns_updatecallback_t callback, void *callback_arg) {
18375	dns_forward_t *forward;
18376	isc_result_t result;
18377	isc_region_t *mr;
18378
18379	REQUIRE(DNS_ZONE_VALID(zone));
18380	REQUIRE(msg != NULL);
18381	REQUIRE(callback != NULL);
18382
18383	forward = isc_mem_get(zone->mctx, sizeof(*forward));
18384
18385	forward->request = NULL;
18386	forward->zone = NULL;
18387	forward->msgbuf = NULL;
18388	forward->which = 0;
18389	forward->mctx = 0;
18390	forward->callback = callback;
18391	forward->callback_arg = callback_arg;
18392	ISC_LINK_INIT(forward, link);
18393	forward->magic = FORWARD_MAGIC;
18394	forward->options = DNS_REQUESTOPT_TCP;
18395	/*
18396	 * If we have a SIG(0) signed message we need to preserve the
18397	 * query id as that is included in the SIG(0) computation.
18398	 */
18399	if (msg->sig0 != NULL) {
18400		forward->options |= DNS_REQUESTOPT_FIXEDID;
18401	}
18402
18403	mr = dns_message_getrawmessage(msg);
18404	if (mr == NULL) {
18405		result = ISC_R_UNEXPECTEDEND;
18406		goto cleanup;
18407	}
18408
18409	isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
18410	result = isc_buffer_copyregion(forward->msgbuf, mr);
18411	if (result != ISC_R_SUCCESS) {
18412		goto cleanup;
18413	}
18414
18415	isc_mem_attach(zone->mctx, &forward->mctx);
18416	dns_zone_iattach(zone, &forward->zone);
18417	result = sendtomaster(forward);
18418
18419cleanup:
18420	if (result != ISC_R_SUCCESS) {
18421		forward_destroy(forward);
18422	}
18423	return (result);
18424}
18425
18426isc_result_t
18427dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
18428	REQUIRE(DNS_ZONE_VALID(zone));
18429	REQUIRE(next != NULL && *next == NULL);
18430
18431	*next = ISC_LIST_NEXT(zone, link);
18432	if (*next == NULL) {
18433		return (ISC_R_NOMORE);
18434	} else {
18435		return (ISC_R_SUCCESS);
18436	}
18437}
18438
18439isc_result_t
18440dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
18441	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18442	REQUIRE(first != NULL && *first == NULL);
18443
18444	*first = ISC_LIST_HEAD(zmgr->zones);
18445	if (*first == NULL) {
18446		return (ISC_R_NOMORE);
18447	} else {
18448		return (ISC_R_SUCCESS);
18449	}
18450}
18451
18452/***
18453 ***	Zone manager.
18454 ***/
18455
18456#define KEYMGMT_OVERCOMMIT 3
18457#define KEYMGMT_BITS_MIN   2U
18458#define KEYMGMT_BITS_MAX   32U
18459
18460/*
18461 * WMM: Static hash functions copied from lib/dns/rbtdb.c. Should be moved to
18462 * lib/isc/hash.c when we refactor the hash table code.
18463 */
18464#define GOLDEN_RATIO_32 0x61C88647
18465#define HASHSIZE(bits)	(UINT64_C(1) << (bits))
18466
18467static uint32_t
18468hash_index(uint32_t val, uint32_t bits) {
18469	return (val * GOLDEN_RATIO_32 >> (32 - bits));
18470}
18471
18472static uint32_t
18473hash_bits_grow(uint32_t bits, uint32_t count) {
18474	uint32_t newbits = bits;
18475	while (count >= HASHSIZE(newbits) && newbits < KEYMGMT_BITS_MAX) {
18476		newbits++;
18477	}
18478	return (newbits);
18479}
18480
18481static uint32_t
18482hash_bits_shrink(uint32_t bits, uint32_t count) {
18483	uint32_t newbits = bits;
18484	while (count <= HASHSIZE(newbits) && newbits > KEYMGMT_BITS_MIN) {
18485		newbits--;
18486	}
18487	return (newbits);
18488}
18489
18490static void
18491zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) {
18492	dns_keymgmt_t *mgmt = isc_mem_get(zmgr->mctx, sizeof(*mgmt));
18493	uint32_t size;
18494
18495	*mgmt = (dns_keymgmt_t){
18496		.bits = KEYMGMT_BITS_MIN,
18497	};
18498	isc_mem_attach(zmgr->mctx, &mgmt->mctx);
18499	isc_rwlock_init(&mgmt->lock, 0, 0);
18500
18501	size = HASHSIZE(mgmt->bits);
18502	mgmt->table = isc_mem_get(mgmt->mctx, sizeof(*mgmt->table) * size);
18503	memset(mgmt->table, 0, size * sizeof(mgmt->table[0]));
18504
18505	atomic_init(&mgmt->count, 0);
18506	mgmt->magic = KEYMGMT_MAGIC;
18507
18508	zmgr->keymgmt = mgmt;
18509}
18510
18511static void
18512zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) {
18513	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18514	uint32_t size;
18515
18516	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18517
18518	size = HASHSIZE(mgmt->bits);
18519
18520	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18521	INSIST(mgmt->count == 0);
18522	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18523
18524	mgmt->magic = 0;
18525	isc_rwlock_destroy(&mgmt->lock);
18526	isc_mem_put(mgmt->mctx, mgmt->table, size * sizeof(mgmt->table[0]));
18527	isc_mem_putanddetach(&mgmt->mctx, mgmt, sizeof(dns_keymgmt_t));
18528}
18529
18530static void
18531zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) {
18532	dns_keyfileio_t **newtable;
18533	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18534	uint32_t bits, newbits, count, size, newsize;
18535	bool grow;
18536
18537	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18538
18539	RWLOCK(&mgmt->lock, isc_rwlocktype_read);
18540	count = atomic_load_relaxed(&mgmt->count);
18541	bits = mgmt->bits;
18542	RWUNLOCK(&mgmt->lock, isc_rwlocktype_read);
18543
18544	size = HASHSIZE(bits);
18545	INSIST(size > 0);
18546
18547	if (count >= (size * KEYMGMT_OVERCOMMIT)) {
18548		grow = true;
18549	} else if (count < (size / 2)) {
18550		grow = false;
18551	} else {
18552		/* No need to resize. */
18553		return;
18554	}
18555
18556	if (grow) {
18557		newbits = hash_bits_grow(bits, count);
18558	} else {
18559		newbits = hash_bits_shrink(bits, count);
18560	}
18561
18562	if (newbits == bits) {
18563		/*
18564		 * Bit values may stay the same if maximum or minimum is
18565		 * reached.
18566		 */
18567		return;
18568	}
18569
18570	newsize = HASHSIZE(newbits);
18571	INSIST(newsize > 0);
18572
18573	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18574
18575	newtable = isc_mem_get(mgmt->mctx, sizeof(dns_keyfileio_t *) * newsize);
18576	memset(newtable, 0, sizeof(dns_keyfileio_t *) * newsize);
18577
18578	for (unsigned int i = 0; i < size; i++) {
18579		dns_keyfileio_t *kfio, *next;
18580		for (kfio = mgmt->table[i]; kfio != NULL; kfio = next) {
18581			uint32_t hash = hash_index(kfio->hashval, newbits);
18582			next = kfio->next;
18583			kfio->next = newtable[hash];
18584			newtable[hash] = kfio;
18585		}
18586		mgmt->table[i] = NULL;
18587	}
18588
18589	isc_mem_put(mgmt->mctx, mgmt->table, sizeof(*mgmt->table) * size);
18590	mgmt->bits = newbits;
18591	mgmt->table = newtable;
18592
18593	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18594}
18595
18596static void
18597zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
18598		    dns_keyfileio_t **added) {
18599	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18600	uint32_t hashval, hash;
18601	dns_keyfileio_t *kfio, *next;
18602
18603	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18604	REQUIRE(added != NULL && *added == NULL);
18605
18606	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18607
18608	hashval = dns_name_hash(&zone->origin, false);
18609	hash = hash_index(hashval, mgmt->bits);
18610
18611	for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
18612		next = kfio->next;
18613		if (dns_name_equal(kfio->name, &zone->origin)) {
18614			/* Already in table, increment the counter. */
18615			isc_refcount_increment(&kfio->references);
18616			break;
18617		}
18618	}
18619
18620	if (kfio == NULL) {
18621		/* No entry found, add it. */
18622		kfio = isc_mem_get(mgmt->mctx, sizeof(*kfio));
18623		*kfio = (dns_keyfileio_t){
18624			.hashval = hashval,
18625			.next = mgmt->table[hash],
18626			.magic = KEYFILEIO_MAGIC,
18627		};
18628
18629		isc_refcount_init(&kfio->references, 1);
18630
18631		kfio->name = dns_fixedname_initname(&kfio->fname);
18632		dns_name_copynf(&zone->origin, kfio->name);
18633
18634		isc_mutex_init(&kfio->lock);
18635
18636		mgmt->table[hash] = kfio;
18637
18638		atomic_fetch_add_relaxed(&mgmt->count, 1);
18639	}
18640
18641	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18642
18643	*added = kfio;
18644
18645	/*
18646	 * Call resize, that function will also check if resize is necessary.
18647	 */
18648	zonemgr_keymgmt_resize(zmgr);
18649}
18650
18651static void
18652zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_zone_t *zone,
18653		       dns_keyfileio_t **deleted) {
18654	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18655	uint32_t hashval, hash;
18656	dns_keyfileio_t *kfio, *prev, *next;
18657
18658	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18659	REQUIRE(deleted != NULL && DNS_KEYFILEIO_VALID(*deleted));
18660
18661	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18662
18663	hashval = dns_name_hash(&zone->origin, false);
18664	hash = hash_index(hashval, mgmt->bits);
18665
18666	prev = NULL;
18667	for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
18668		next = kfio->next;
18669		if (dns_name_equal(kfio->name, &zone->origin)) {
18670			INSIST(kfio == *deleted);
18671			*deleted = NULL;
18672
18673			if (isc_refcount_decrement(&kfio->references) == 1) {
18674				if (prev == NULL) {
18675					mgmt->table[hash] = kfio->next;
18676				} else {
18677					prev->next = kfio->next;
18678				}
18679
18680				isc_refcount_destroy(&kfio->references);
18681				isc_mutex_destroy(&kfio->lock);
18682				isc_mem_put(mgmt->mctx, kfio, sizeof(*kfio));
18683
18684				atomic_fetch_sub_relaxed(&mgmt->count, 1);
18685			}
18686			break;
18687		}
18688
18689		prev = kfio;
18690	}
18691
18692	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18693
18694	/*
18695	 * Call resize, that function will also check if resize is necessary.
18696	 */
18697	zonemgr_keymgmt_resize(zmgr);
18698}
18699
18700isc_result_t
18701dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
18702		   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
18703		   dns_zonemgr_t **zmgrp) {
18704	dns_zonemgr_t *zmgr;
18705	isc_result_t result;
18706
18707	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
18708	zmgr->mctx = NULL;
18709	isc_refcount_init(&zmgr->refs, 1);
18710	isc_mem_attach(mctx, &zmgr->mctx);
18711	zmgr->taskmgr = taskmgr;
18712	zmgr->timermgr = timermgr;
18713	zmgr->socketmgr = socketmgr;
18714	zmgr->zonetasks = NULL;
18715	zmgr->loadtasks = NULL;
18716	zmgr->mctxpool = NULL;
18717	zmgr->task = NULL;
18718	zmgr->checkdsrl = NULL;
18719	zmgr->notifyrl = NULL;
18720	zmgr->refreshrl = NULL;
18721	zmgr->startupnotifyrl = NULL;
18722	zmgr->startuprefreshrl = NULL;
18723	ISC_LIST_INIT(zmgr->zones);
18724	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
18725	ISC_LIST_INIT(zmgr->xfrin_in_progress);
18726	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
18727	for (size_t i = 0; i < UNREACH_CACHE_SIZE; i++) {
18728		atomic_init(&zmgr->unreachable[i].expire, 0);
18729	}
18730	isc_rwlock_init(&zmgr->rwlock, 0, 0);
18731
18732	zmgr->transfersin = 10;
18733	zmgr->transfersperns = 2;
18734
18735	/* Unreachable lock. */
18736	isc_rwlock_init(&zmgr->urlock, 0, 0);
18737
18738	/* Create a single task for queueing of SOA queries. */
18739	result = isc_task_create(taskmgr, 1, &zmgr->task);
18740	if (result != ISC_R_SUCCESS) {
18741		goto free_urlock;
18742	}
18743
18744	isc_task_setname(zmgr->task, "zmgr", zmgr);
18745	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18746					&zmgr->checkdsrl);
18747	if (result != ISC_R_SUCCESS) {
18748		goto free_task;
18749	}
18750
18751	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18752					&zmgr->notifyrl);
18753	if (result != ISC_R_SUCCESS) {
18754		goto free_checkdsrl;
18755	}
18756
18757	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18758					&zmgr->refreshrl);
18759	if (result != ISC_R_SUCCESS) {
18760		goto free_notifyrl;
18761	}
18762
18763	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18764					&zmgr->startupnotifyrl);
18765	if (result != ISC_R_SUCCESS) {
18766		goto free_refreshrl;
18767	}
18768
18769	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18770					&zmgr->startuprefreshrl);
18771	if (result != ISC_R_SUCCESS) {
18772		goto free_startupnotifyrl;
18773	}
18774
18775	/* Key file I/O locks. */
18776	zonemgr_keymgmt_init(zmgr);
18777
18778	/* Default to 20 refresh queries / notifies / checkds per second. */
18779	setrl(zmgr->checkdsrl, &zmgr->checkdsrate, 20);
18780	setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
18781	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
18782	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
18783	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
18784	isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
18785	isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
18786
18787	zmgr->iolimit = 1;
18788	zmgr->ioactive = 0;
18789	ISC_LIST_INIT(zmgr->high);
18790	ISC_LIST_INIT(zmgr->low);
18791
18792	isc_mutex_init(&zmgr->iolock);
18793
18794	zmgr->magic = ZONEMGR_MAGIC;
18795
18796	*zmgrp = zmgr;
18797	return (ISC_R_SUCCESS);
18798
18799#if 0
18800 free_iolock:
18801	isc_mutex_destroy(&zmgr->iolock);
18802#endif /* if 0 */
18803free_startupnotifyrl:
18804	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
18805free_refreshrl:
18806	isc_ratelimiter_detach(&zmgr->refreshrl);
18807free_notifyrl:
18808	isc_ratelimiter_detach(&zmgr->notifyrl);
18809free_checkdsrl:
18810	isc_ratelimiter_detach(&zmgr->checkdsrl);
18811free_task:
18812	isc_task_detach(&zmgr->task);
18813free_urlock:
18814	isc_rwlock_destroy(&zmgr->urlock);
18815	isc_rwlock_destroy(&zmgr->rwlock);
18816	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
18817	isc_mem_detach(&mctx);
18818	return (result);
18819}
18820
18821isc_result_t
18822dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
18823	isc_result_t result;
18824	isc_mem_t *mctx = NULL;
18825	dns_zone_t *zone = NULL;
18826	void *item;
18827
18828	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18829	REQUIRE(zonep != NULL && *zonep == NULL);
18830
18831	if (zmgr->mctxpool == NULL) {
18832		return (ISC_R_FAILURE);
18833	}
18834
18835	item = isc_pool_get(zmgr->mctxpool);
18836	if (item == NULL) {
18837		return (ISC_R_FAILURE);
18838	}
18839
18840	isc_mem_attach((isc_mem_t *)item, &mctx);
18841	result = dns_zone_create(&zone, mctx);
18842	isc_mem_detach(&mctx);
18843
18844	if (result == ISC_R_SUCCESS) {
18845		*zonep = zone;
18846	}
18847
18848	return (result);
18849}
18850
18851isc_result_t
18852dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18853	isc_result_t result;
18854
18855	REQUIRE(DNS_ZONE_VALID(zone));
18856	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18857
18858	if (zmgr->zonetasks == NULL) {
18859		return (ISC_R_FAILURE);
18860	}
18861
18862	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18863	LOCK_ZONE(zone);
18864	REQUIRE(zone->task == NULL);
18865	REQUIRE(zone->timer == NULL);
18866	REQUIRE(zone->zmgr == NULL);
18867
18868	isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
18869	isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
18870
18871	/*
18872	 * Set the task name.  The tag will arbitrarily point to one
18873	 * of the zones sharing the task (in practice, the one
18874	 * to be managed last).
18875	 */
18876	isc_task_setname(zone->task, "zone", zone);
18877	isc_task_setname(zone->loadtask, "loadzone", zone);
18878
18879	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
18880				  NULL, zone->task, zone_timer, zone,
18881				  &zone->timer);
18882
18883	if (result != ISC_R_SUCCESS) {
18884		goto cleanup_tasks;
18885	}
18886
18887	/*
18888	 * The timer "holds" a iref.
18889	 */
18890	isc_refcount_increment0(&zone->irefs);
18891
18892	zonemgr_keymgmt_add(zmgr, zone, &zone->kfio);
18893	INSIST(zone->kfio != NULL);
18894
18895	ISC_LIST_APPEND(zmgr->zones, zone, link);
18896	zone->zmgr = zmgr;
18897	isc_refcount_increment(&zmgr->refs);
18898
18899	goto unlock;
18900
18901cleanup_tasks:
18902	isc_task_detach(&zone->loadtask);
18903	isc_task_detach(&zone->task);
18904
18905unlock:
18906	UNLOCK_ZONE(zone);
18907	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18908	return (result);
18909}
18910
18911void
18912dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18913	REQUIRE(DNS_ZONE_VALID(zone));
18914	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18915	REQUIRE(zone->zmgr == zmgr);
18916
18917	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18918	LOCK_ZONE(zone);
18919
18920	ISC_LIST_UNLINK(zmgr->zones, zone, link);
18921
18922	if (zone->kfio != NULL) {
18923		zonemgr_keymgmt_delete(zmgr, zone, &zone->kfio);
18924		ENSURE(zone->kfio == NULL);
18925	}
18926
18927	/* Detach below, outside of the write lock. */
18928	zone->zmgr = NULL;
18929
18930	UNLOCK_ZONE(zone);
18931	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18932
18933	dns_zonemgr_detach(&zmgr);
18934}
18935
18936void
18937dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
18938	REQUIRE(DNS_ZONEMGR_VALID(source));
18939	REQUIRE(target != NULL && *target == NULL);
18940
18941	isc_refcount_increment(&source->refs);
18942
18943	*target = source;
18944}
18945
18946void
18947dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
18948	dns_zonemgr_t *zmgr;
18949
18950	REQUIRE(zmgrp != NULL);
18951	zmgr = *zmgrp;
18952	*zmgrp = NULL;
18953	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18954
18955	if (isc_refcount_decrement(&zmgr->refs) == 1) {
18956		zonemgr_free(zmgr);
18957	}
18958}
18959
18960isc_result_t
18961dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
18962	dns_zone_t *p;
18963
18964	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18965
18966	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18967	for (p = ISC_LIST_HEAD(zmgr->zones); p != NULL;
18968	     p = ISC_LIST_NEXT(p, link))
18969	{
18970		dns_zone_maintenance(p);
18971	}
18972	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18973
18974	/*
18975	 * Recent configuration changes may have increased the
18976	 * amount of available transfers quota.  Make sure any
18977	 * transfers currently blocked on quota get started if
18978	 * possible.
18979	 */
18980	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18981	zmgr_resume_xfrs(zmgr, true);
18982	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18983	return (ISC_R_SUCCESS);
18984}
18985
18986void
18987dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
18988	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18989
18990	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18991	zmgr_resume_xfrs(zmgr, true);
18992	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18993}
18994
18995void
18996dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
18997	dns_zone_t *zone;
18998
18999	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19000
19001	isc_ratelimiter_shutdown(zmgr->checkdsrl);
19002	isc_ratelimiter_shutdown(zmgr->notifyrl);
19003	isc_ratelimiter_shutdown(zmgr->refreshrl);
19004	isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
19005	isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
19006
19007	if (zmgr->task != NULL) {
19008		isc_task_destroy(&zmgr->task);
19009	}
19010	if (zmgr->zonetasks != NULL) {
19011		isc_taskpool_destroy(&zmgr->zonetasks);
19012	}
19013	if (zmgr->loadtasks != NULL) {
19014		isc_taskpool_destroy(&zmgr->loadtasks);
19015	}
19016	if (zmgr->mctxpool != NULL) {
19017		isc_pool_destroy(&zmgr->mctxpool);
19018	}
19019
19020	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19021	for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19022	     zone = ISC_LIST_NEXT(zone, link))
19023	{
19024		LOCK_ZONE(zone);
19025		forward_cancel(zone);
19026		UNLOCK_ZONE(zone);
19027	}
19028	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19029}
19030
19031static isc_result_t
19032mctxinit(void **target, void *arg) {
19033	isc_mem_t *mctx = NULL;
19034
19035	UNUSED(arg);
19036
19037	REQUIRE(target != NULL && *target == NULL);
19038
19039	isc_mem_create(&mctx);
19040	isc_mem_setname(mctx, "zonemgr-pool", NULL);
19041
19042	*target = mctx;
19043	return (ISC_R_SUCCESS);
19044}
19045
19046static void
19047mctxfree(void **target) {
19048	isc_mem_t *mctx = *(isc_mem_t **)target;
19049	isc_mem_detach(&mctx);
19050	*target = NULL;
19051}
19052
19053#define ZONES_PER_TASK 100
19054#define ZONES_PER_MCTX 1000
19055
19056isc_result_t
19057dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
19058	isc_result_t result;
19059	int ntasks = num_zones / ZONES_PER_TASK;
19060	int nmctx = num_zones / ZONES_PER_MCTX;
19061	isc_taskpool_t *pool = NULL;
19062	isc_pool_t *mctxpool = NULL;
19063
19064	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19065
19066	/*
19067	 * For anything fewer than 1000 zones we use 10 tasks in
19068	 * the task pools.  More than that, and we'll scale at one
19069	 * task per 100 zones.  Similarly, for anything smaller than
19070	 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
19071	 */
19072	if (ntasks < 10) {
19073		ntasks = 10;
19074	}
19075	if (nmctx < 2) {
19076		nmctx = 2;
19077	}
19078
19079	/* Create or resize the zone task pools. */
19080	if (zmgr->zonetasks == NULL) {
19081		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
19082					     2, false, &pool);
19083	} else {
19084		result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, false,
19085					     &pool);
19086	}
19087
19088	if (result == ISC_R_SUCCESS) {
19089		zmgr->zonetasks = pool;
19090	}
19091
19092	pool = NULL;
19093	if (zmgr->loadtasks == NULL) {
19094		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
19095					     UINT_MAX, true, &pool);
19096	} else {
19097		result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, true,
19098					     &pool);
19099	}
19100
19101	if (result == ISC_R_SUCCESS) {
19102		zmgr->loadtasks = pool;
19103	}
19104
19105	/* Create or resize the zone memory context pool. */
19106	if (zmgr->mctxpool == NULL) {
19107		result = isc_pool_create(zmgr->mctx, nmctx, mctxfree, mctxinit,
19108					 NULL, &mctxpool);
19109	} else {
19110		result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
19111	}
19112
19113	if (result == ISC_R_SUCCESS) {
19114		zmgr->mctxpool = mctxpool;
19115	}
19116
19117	return (result);
19118}
19119
19120static void
19121zonemgr_free(dns_zonemgr_t *zmgr) {
19122	isc_mem_t *mctx;
19123
19124	INSIST(ISC_LIST_EMPTY(zmgr->zones));
19125
19126	zmgr->magic = 0;
19127
19128	isc_refcount_destroy(&zmgr->refs);
19129	isc_mutex_destroy(&zmgr->iolock);
19130	isc_ratelimiter_detach(&zmgr->checkdsrl);
19131	isc_ratelimiter_detach(&zmgr->notifyrl);
19132	isc_ratelimiter_detach(&zmgr->refreshrl);
19133	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
19134	isc_ratelimiter_detach(&zmgr->startuprefreshrl);
19135
19136	isc_rwlock_destroy(&zmgr->urlock);
19137	isc_rwlock_destroy(&zmgr->rwlock);
19138
19139	zonemgr_keymgmt_destroy(zmgr);
19140
19141	mctx = zmgr->mctx;
19142	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
19143	isc_mem_detach(&mctx);
19144}
19145
19146void
19147dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
19148	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19149
19150	zmgr->transfersin = value;
19151}
19152
19153uint32_t
19154dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
19155	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19156
19157	return (zmgr->transfersin);
19158}
19159
19160void
19161dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
19162	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19163
19164	zmgr->transfersperns = value;
19165}
19166
19167uint32_t
19168dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
19169	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19170
19171	return (zmgr->transfersperns);
19172}
19173
19174isc_taskmgr_t *
19175dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr) {
19176	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19177
19178	return (zmgr->taskmgr);
19179}
19180
19181/*
19182 * Try to start a new incoming zone transfer to fill a quota
19183 * slot that was just vacated.
19184 *
19185 * Requires:
19186 *	The zone manager is locked by the caller.
19187 */
19188static void
19189zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
19190	dns_zone_t *zone;
19191	dns_zone_t *next;
19192
19193	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); zone != NULL;
19194	     zone = next)
19195	{
19196		isc_result_t result;
19197		next = ISC_LIST_NEXT(zone, statelink);
19198		result = zmgr_start_xfrin_ifquota(zmgr, zone);
19199		if (result == ISC_R_SUCCESS) {
19200			if (multi) {
19201				continue;
19202			}
19203			/*
19204			 * We successfully filled the slot.  We're done.
19205			 */
19206			break;
19207		} else if (result == ISC_R_QUOTA) {
19208			/*
19209			 * Not enough quota.  This is probably the per-server
19210			 * quota, because we usually get called when a unit of
19211			 * global quota has just been freed.  Try the next
19212			 * zone, it may succeed if it uses another master.
19213			 */
19214			continue;
19215		} else {
19216			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
19217				      ISC_LOG_DEBUG(1),
19218				      "starting zone transfer: %s",
19219				      isc_result_totext(result));
19220			break;
19221		}
19222	}
19223}
19224
19225/*
19226 * Try to start an incoming zone transfer for 'zone', quota permitting.
19227 *
19228 * Requires:
19229 *	The zone manager is locked by the caller.
19230 *
19231 * Returns:
19232 *	ISC_R_SUCCESS	There was enough quota and we attempted to
19233 *			start a transfer.  zone_xfrdone() has been or will
19234 *			be called.
19235 *	ISC_R_QUOTA	Not enough quota.
19236 *	Others		Failure.
19237 */
19238static isc_result_t
19239zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
19240	dns_peer_t *peer = NULL;
19241	isc_netaddr_t masterip;
19242	uint32_t nxfrsin, nxfrsperns;
19243	dns_zone_t *x;
19244	uint32_t maxtransfersin, maxtransfersperns;
19245	isc_event_t *e;
19246
19247	/*
19248	 * If we are exiting just pretend we got quota so the zone will
19249	 * be cleaned up in the zone's task context.
19250	 */
19251	LOCK_ZONE(zone);
19252	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
19253		UNLOCK_ZONE(zone);
19254		goto gotquota;
19255	}
19256
19257	/*
19258	 * Find any configured information about the server we'd
19259	 * like to transfer this zone from.
19260	 */
19261	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
19262	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
19263	UNLOCK_ZONE(zone);
19264
19265	/*
19266	 * Determine the total maximum number of simultaneous
19267	 * transfers allowed, and the maximum for this specific
19268	 * master.
19269	 */
19270	maxtransfersin = zmgr->transfersin;
19271	maxtransfersperns = zmgr->transfersperns;
19272	if (peer != NULL) {
19273		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
19274	}
19275
19276	/*
19277	 * Count the total number of transfers that are in progress,
19278	 * and the number of transfers in progress from this master.
19279	 * We linearly scan a list of all transfers; if this turns
19280	 * out to be too slow, we could hash on the master address.
19281	 */
19282	nxfrsin = nxfrsperns = 0;
19283	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); x != NULL;
19284	     x = ISC_LIST_NEXT(x, statelink))
19285	{
19286		isc_netaddr_t xip;
19287
19288		LOCK_ZONE(x);
19289		isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
19290		UNLOCK_ZONE(x);
19291
19292		nxfrsin++;
19293		if (isc_netaddr_equal(&xip, &masterip)) {
19294			nxfrsperns++;
19295		}
19296	}
19297
19298	/* Enforce quota. */
19299	if (nxfrsin >= maxtransfersin) {
19300		return (ISC_R_QUOTA);
19301	}
19302
19303	if (nxfrsperns >= maxtransfersperns) {
19304		return (ISC_R_QUOTA);
19305	}
19306
19307gotquota:
19308	/*
19309	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
19310	 * list and send it an event to let it start the actual transfer in the
19311	 * context of its own task.
19312	 */
19313	e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
19314			       got_transfer_quota, zone, sizeof(isc_event_t));
19315
19316	LOCK_ZONE(zone);
19317	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
19318	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
19319	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
19320	zone->statelist = &zmgr->xfrin_in_progress;
19321	isc_task_send(zone->task, &e);
19322	dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
19323		      "Transfer started.");
19324	UNLOCK_ZONE(zone);
19325
19326	return (ISC_R_SUCCESS);
19327}
19328
19329void
19330dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
19331	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19332	REQUIRE(iolimit > 0);
19333
19334	zmgr->iolimit = iolimit;
19335}
19336
19337uint32_t
19338dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
19339	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19340
19341	return (zmgr->iolimit);
19342}
19343
19344/*
19345 * Get permission to request a file handle from the OS.
19346 * An event will be sent to action when one is available.
19347 * There are two queues available (high and low), the high
19348 * queue will be serviced before the low one.
19349 *
19350 * zonemgr_putio() must be called after the event is delivered to
19351 * 'action'.
19352 */
19353
19354static isc_result_t
19355zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
19356	      isc_taskaction_t action, void *arg, dns_io_t **iop) {
19357	dns_io_t *io;
19358	bool queue;
19359
19360	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19361	REQUIRE(iop != NULL && *iop == NULL);
19362
19363	io = isc_mem_get(zmgr->mctx, sizeof(*io));
19364
19365	io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
19366				       action, arg, sizeof(*io->event));
19367
19368	io->zmgr = zmgr;
19369	io->high = high;
19370	io->task = NULL;
19371	isc_task_attach(task, &io->task);
19372	ISC_LINK_INIT(io, link);
19373	io->magic = IO_MAGIC;
19374
19375	LOCK(&zmgr->iolock);
19376	zmgr->ioactive++;
19377	queue = (zmgr->ioactive > zmgr->iolimit);
19378	if (queue) {
19379		if (io->high) {
19380			ISC_LIST_APPEND(zmgr->high, io, link);
19381		} else {
19382			ISC_LIST_APPEND(zmgr->low, io, link);
19383		}
19384	}
19385	UNLOCK(&zmgr->iolock);
19386	*iop = io;
19387
19388	if (!queue) {
19389		isc_task_send(io->task, &io->event);
19390	}
19391	return (ISC_R_SUCCESS);
19392}
19393
19394static void
19395zonemgr_putio(dns_io_t **iop) {
19396	dns_io_t *io;
19397	dns_io_t *next;
19398	dns_zonemgr_t *zmgr;
19399
19400	REQUIRE(iop != NULL);
19401	io = *iop;
19402	*iop = NULL;
19403	REQUIRE(DNS_IO_VALID(io));
19404
19405	INSIST(!ISC_LINK_LINKED(io, link));
19406	INSIST(io->event == NULL);
19407
19408	zmgr = io->zmgr;
19409	isc_task_detach(&io->task);
19410	io->magic = 0;
19411	isc_mem_put(zmgr->mctx, io, sizeof(*io));
19412
19413	LOCK(&zmgr->iolock);
19414	INSIST(zmgr->ioactive > 0);
19415	zmgr->ioactive--;
19416	next = HEAD(zmgr->high);
19417	if (next == NULL) {
19418		next = HEAD(zmgr->low);
19419	}
19420	if (next != NULL) {
19421		if (next->high) {
19422			ISC_LIST_UNLINK(zmgr->high, next, link);
19423		} else {
19424			ISC_LIST_UNLINK(zmgr->low, next, link);
19425		}
19426		INSIST(next->event != NULL);
19427	}
19428	UNLOCK(&zmgr->iolock);
19429	if (next != NULL) {
19430		isc_task_send(next->task, &next->event);
19431	}
19432}
19433
19434static void
19435zonemgr_cancelio(dns_io_t *io) {
19436	bool send_event = false;
19437
19438	REQUIRE(DNS_IO_VALID(io));
19439
19440	/*
19441	 * If we are queued to be run then dequeue.
19442	 */
19443	LOCK(&io->zmgr->iolock);
19444	if (ISC_LINK_LINKED(io, link)) {
19445		if (io->high) {
19446			ISC_LIST_UNLINK(io->zmgr->high, io, link);
19447		} else {
19448			ISC_LIST_UNLINK(io->zmgr->low, io, link);
19449		}
19450
19451		send_event = true;
19452		INSIST(io->event != NULL);
19453	}
19454	UNLOCK(&io->zmgr->iolock);
19455	if (send_event) {
19456		io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
19457		isc_task_send(io->task, &io->event);
19458	}
19459}
19460
19461static void
19462zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
19463	char *buf;
19464	int buflen;
19465	isc_result_t result;
19466
19467	buflen = strlen(path) + strlen(templat) + 2;
19468
19469	buf = isc_mem_get(zone->mctx, buflen);
19470
19471	result = isc_file_template(path, templat, buf, buflen);
19472	if (result != ISC_R_SUCCESS) {
19473		goto cleanup;
19474	}
19475
19476	result = isc_file_renameunique(path, buf);
19477	if (result != ISC_R_SUCCESS) {
19478		goto cleanup;
19479	}
19480
19481	dns_zone_log(zone, ISC_LOG_WARNING,
19482		     "unable to load from '%s'; "
19483		     "renaming file to '%s' for failure analysis and "
19484		     "retransferring.",
19485		     path, buf);
19486
19487cleanup:
19488	isc_mem_put(zone->mctx, buf, buflen);
19489}
19490
19491static void
19492setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
19493	isc_interval_t interval;
19494	uint32_t s, ns;
19495	uint32_t pertic;
19496	isc_result_t result;
19497
19498	if (value == 0) {
19499		value = 1;
19500	}
19501
19502	if (value == 1) {
19503		s = 1;
19504		ns = 0;
19505		pertic = 1;
19506	} else if (value <= 10) {
19507		s = 0;
19508		ns = 1000000000 / value;
19509		pertic = 1;
19510	} else {
19511		s = 0;
19512		ns = (1000000000 / value) * 10;
19513		pertic = 10;
19514	}
19515
19516	isc_interval_set(&interval, s, ns);
19517
19518	result = isc_ratelimiter_setinterval(rl, &interval);
19519	RUNTIME_CHECK(result == ISC_R_SUCCESS);
19520	isc_ratelimiter_setpertic(rl, pertic);
19521
19522	*rate = value;
19523}
19524
19525void
19526dns_zonemgr_setcheckdsrate(dns_zonemgr_t *zmgr, unsigned int value) {
19527	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19528
19529	setrl(zmgr->checkdsrl, &zmgr->checkdsrate, value);
19530}
19531
19532void
19533dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19534	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19535
19536	setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
19537}
19538
19539void
19540dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19541	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19542
19543	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
19544}
19545
19546void
19547dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
19548	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19549
19550	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
19551	/* XXXMPA separate out once we have the code to support this. */
19552	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
19553}
19554
19555unsigned int
19556dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
19557	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19558
19559	return (zmgr->notifyrate);
19560}
19561
19562unsigned int
19563dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
19564	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19565
19566	return (zmgr->startupnotifyrate);
19567}
19568
19569unsigned int
19570dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
19571	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19572
19573	return (zmgr->serialqueryrate);
19574}
19575
19576bool
19577dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19578			isc_sockaddr_t *local, isc_time_t *now) {
19579	unsigned int i;
19580	uint32_t seconds = isc_time_seconds(now);
19581	uint32_t count = 0;
19582
19583	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19584
19585	RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19586	for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19587		if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
19588		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19589		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19590		{
19591			atomic_store_relaxed(&zmgr->unreachable[i].last,
19592					     seconds);
19593			count = zmgr->unreachable[i].count;
19594			break;
19595		}
19596	}
19597	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19598	return (i < UNREACH_CACHE_SIZE && count > 1U);
19599}
19600
19601void
19602dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19603			   isc_sockaddr_t *local) {
19604	unsigned int i;
19605	char master[ISC_SOCKADDR_FORMATSIZE];
19606	char source[ISC_SOCKADDR_FORMATSIZE];
19607
19608	isc_sockaddr_format(remote, master, sizeof(master));
19609	isc_sockaddr_format(local, source, sizeof(source));
19610
19611	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19612
19613	RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19614	for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19615		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19616		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19617		{
19618			atomic_store_relaxed(&zmgr->unreachable[i].expire, 0);
19619			break;
19620		}
19621	}
19622	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19623}
19624
19625void
19626dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19627			   isc_sockaddr_t *local, isc_time_t *now) {
19628	uint32_t seconds = isc_time_seconds(now);
19629	uint32_t expire = 0, last = seconds;
19630	unsigned int slot = UNREACH_CACHE_SIZE, oldest = 0;
19631	bool update_entry = true;
19632	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19633
19634	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
19635	for (unsigned int i = 0; i < UNREACH_CACHE_SIZE; i++) {
19636		/* Existing entry? */
19637		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19638		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19639		{
19640			update_entry = false;
19641			slot = i;
19642			expire = atomic_load_relaxed(
19643				&zmgr->unreachable[i].expire);
19644			break;
19645		}
19646		/* Pick first empty slot? */
19647		if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds)
19648		{
19649			slot = i;
19650			break;
19651		}
19652		/* The worst case, least recently used slot? */
19653		if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
19654			last = atomic_load_relaxed(&zmgr->unreachable[i].last);
19655			oldest = i;
19656		}
19657	}
19658
19659	/* We haven't found any existing or free slots, use the oldest */
19660	if (slot == UNREACH_CACHE_SIZE) {
19661		slot = oldest;
19662	}
19663
19664	if (expire < seconds) {
19665		/* Expired or new entry, reset count to 1 */
19666		zmgr->unreachable[slot].count = 1;
19667	} else {
19668		zmgr->unreachable[slot].count++;
19669	}
19670	atomic_store_relaxed(&zmgr->unreachable[slot].expire,
19671			     seconds + UNREACH_HOLD_TIME);
19672	atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
19673	if (update_entry) {
19674		zmgr->unreachable[slot].remote = *remote;
19675		zmgr->unreachable[slot].local = *local;
19676	}
19677
19678	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
19679}
19680
19681void
19682dns_zone_forcereload(dns_zone_t *zone) {
19683	REQUIRE(DNS_ZONE_VALID(zone));
19684
19685	if (zone->type == dns_zone_primary ||
19686	    (zone->type == dns_zone_redirect && zone->masters == NULL))
19687	{
19688		return;
19689	}
19690
19691	LOCK_ZONE(zone);
19692	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
19693	UNLOCK_ZONE(zone);
19694	dns_zone_refresh(zone);
19695}
19696
19697bool
19698dns_zone_isforced(dns_zone_t *zone) {
19699	REQUIRE(DNS_ZONE_VALID(zone));
19700
19701	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
19702}
19703
19704isc_result_t
19705dns_zone_setstatistics(dns_zone_t *zone, bool on) {
19706	/*
19707	 * This function is obsoleted.
19708	 */
19709	UNUSED(zone);
19710	UNUSED(on);
19711	return (ISC_R_NOTIMPLEMENTED);
19712}
19713
19714uint64_t *
19715dns_zone_getstatscounters(dns_zone_t *zone) {
19716	/*
19717	 * This function is obsoleted.
19718	 */
19719	UNUSED(zone);
19720	return (NULL);
19721}
19722
19723void
19724dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
19725	REQUIRE(DNS_ZONE_VALID(zone));
19726	REQUIRE(zone->stats == NULL);
19727
19728	LOCK_ZONE(zone);
19729	zone->stats = NULL;
19730	isc_stats_attach(stats, &zone->stats);
19731	UNLOCK_ZONE(zone);
19732}
19733
19734void
19735dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
19736	REQUIRE(DNS_ZONE_VALID(zone));
19737
19738	LOCK_ZONE(zone);
19739	if (zone->requeststats_on && stats == NULL) {
19740		zone->requeststats_on = false;
19741	} else if (!zone->requeststats_on && stats != NULL) {
19742		if (zone->requeststats == NULL) {
19743			isc_stats_attach(stats, &zone->requeststats);
19744		}
19745		zone->requeststats_on = true;
19746	}
19747	UNLOCK_ZONE(zone);
19748}
19749
19750void
19751dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
19752	REQUIRE(DNS_ZONE_VALID(zone));
19753
19754	LOCK_ZONE(zone);
19755	if (zone->requeststats_on && stats != NULL) {
19756		if (zone->rcvquerystats == NULL) {
19757			dns_stats_attach(stats, &zone->rcvquerystats);
19758			zone->requeststats_on = true;
19759		}
19760	}
19761	UNLOCK_ZONE(zone);
19762}
19763
19764void
19765dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
19766	REQUIRE(DNS_ZONE_VALID(zone));
19767
19768	LOCK_ZONE(zone);
19769	if (stats != NULL && zone->dnssecsignstats == NULL) {
19770		dns_stats_attach(stats, &zone->dnssecsignstats);
19771	}
19772	UNLOCK_ZONE(zone);
19773}
19774
19775dns_stats_t *
19776dns_zone_getdnssecsignstats(dns_zone_t *zone) {
19777	REQUIRE(DNS_ZONE_VALID(zone));
19778
19779	return (zone->dnssecsignstats);
19780}
19781
19782isc_stats_t *
19783dns_zone_getrequeststats(dns_zone_t *zone) {
19784	/*
19785	 * We don't lock zone for efficiency reason.  This is not catastrophic
19786	 * because requeststats must always be valid when requeststats_on is
19787	 * true.
19788	 * Some counters may be incremented while requeststats_on is becoming
19789	 * false, or some cannot be incremented just after the statistics are
19790	 * installed, but it shouldn't matter much in practice.
19791	 */
19792	if (zone->requeststats_on) {
19793		return (zone->requeststats);
19794	} else {
19795		return (NULL);
19796	}
19797}
19798
19799/*
19800 * Return the received query stats bucket
19801 * see note from dns_zone_getrequeststats()
19802 */
19803dns_stats_t *
19804dns_zone_getrcvquerystats(dns_zone_t *zone) {
19805	if (zone->requeststats_on) {
19806		return (zone->rcvquerystats);
19807	} else {
19808		return (NULL);
19809	}
19810}
19811
19812void
19813dns_zone_dialup(dns_zone_t *zone) {
19814	REQUIRE(DNS_ZONE_VALID(zone));
19815
19816	zone_debuglog(zone, "dns_zone_dialup", 3, "notify = %d, refresh = %d",
19817		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
19818		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
19819
19820	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
19821		dns_zone_notify(zone);
19822	}
19823	if (zone->type != dns_zone_primary && zone->masters != NULL &&
19824	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
19825	{
19826		dns_zone_refresh(zone);
19827	}
19828}
19829
19830void
19831dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
19832	REQUIRE(DNS_ZONE_VALID(zone));
19833
19834	LOCK_ZONE(zone);
19835	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
19836				       DNS_ZONEFLG_DIALREFRESH |
19837				       DNS_ZONEFLG_NOREFRESH);
19838	switch (dialup) {
19839	case dns_dialuptype_no:
19840		break;
19841	case dns_dialuptype_yes:
19842		DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
19843					DNS_ZONEFLG_DIALREFRESH |
19844					DNS_ZONEFLG_NOREFRESH));
19845		break;
19846	case dns_dialuptype_notify:
19847		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19848		break;
19849	case dns_dialuptype_notifypassive:
19850		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19851		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19852		break;
19853	case dns_dialuptype_refresh:
19854		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
19855		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19856		break;
19857	case dns_dialuptype_passive:
19858		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19859		break;
19860	default:
19861		UNREACHABLE();
19862	}
19863	UNLOCK_ZONE(zone);
19864}
19865
19866isc_result_t
19867dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
19868	isc_result_t result = ISC_R_SUCCESS;
19869
19870	REQUIRE(DNS_ZONE_VALID(zone));
19871
19872	LOCK_ZONE(zone);
19873	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
19874	UNLOCK_ZONE(zone);
19875
19876	return (result);
19877}
19878
19879const char *
19880dns_zone_getkeydirectory(dns_zone_t *zone) {
19881	REQUIRE(DNS_ZONE_VALID(zone));
19882
19883	return (zone->keydirectory);
19884}
19885
19886unsigned int
19887dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
19888	dns_zone_t *zone;
19889	unsigned int count = 0;
19890
19891	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19892
19893	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19894	switch (state) {
19895	case DNS_ZONESTATE_XFERRUNNING:
19896		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
19897		     zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19898		{
19899			count++;
19900		}
19901		break;
19902	case DNS_ZONESTATE_XFERDEFERRED:
19903		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
19904		     zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19905		{
19906			count++;
19907		}
19908		break;
19909	case DNS_ZONESTATE_SOAQUERY:
19910		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19911		     zone = ISC_LIST_NEXT(zone, link))
19912		{
19913			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
19914				count++;
19915			}
19916		}
19917		break;
19918	case DNS_ZONESTATE_ANY:
19919		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19920		     zone = ISC_LIST_NEXT(zone, link))
19921		{
19922			dns_view_t *view = zone->view;
19923			if (view != NULL && strcmp(view->name, "_bind") == 0) {
19924				continue;
19925			}
19926			count++;
19927		}
19928		break;
19929	case DNS_ZONESTATE_AUTOMATIC:
19930		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19931		     zone = ISC_LIST_NEXT(zone, link))
19932		{
19933			dns_view_t *view = zone->view;
19934			if (view != NULL && strcmp(view->name, "_bind") == 0) {
19935				continue;
19936			}
19937			if (zone->automatic) {
19938				count++;
19939			}
19940		}
19941		break;
19942	default:
19943		UNREACHABLE();
19944	}
19945
19946	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19947
19948	return (count);
19949}
19950
19951void
19952dns_zone_lock_keyfiles(dns_zone_t *zone) {
19953	REQUIRE(DNS_ZONE_VALID(zone));
19954
19955	if (zone->kasp == NULL) {
19956		/* No need to lock, nothing is writing key files. */
19957		return;
19958	}
19959
19960	REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
19961	isc_mutex_lock(&zone->kfio->lock);
19962}
19963
19964void
19965dns_zone_unlock_keyfiles(dns_zone_t *zone) {
19966	REQUIRE(DNS_ZONE_VALID(zone));
19967
19968	if (zone->kasp == NULL) {
19969		/* No need to lock, nothing is writing key files. */
19970		return;
19971	}
19972
19973	REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
19974	isc_mutex_unlock(&zone->kfio->lock);
19975}
19976
19977isc_result_t
19978dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
19979		    dns_rdata_t *rdata) {
19980	bool ok = true;
19981	bool fail = false;
19982	char namebuf[DNS_NAME_FORMATSIZE];
19983	char namebuf2[DNS_NAME_FORMATSIZE];
19984	char typebuf[DNS_RDATATYPE_FORMATSIZE];
19985	int level = ISC_LOG_WARNING;
19986	dns_name_t bad;
19987
19988	REQUIRE(DNS_ZONE_VALID(zone));
19989
19990	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
19991	    rdata->type != dns_rdatatype_nsec3)
19992	{
19993		return (ISC_R_SUCCESS);
19994	}
19995
19996	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
19997	    rdata->type == dns_rdatatype_nsec3)
19998	{
19999		level = ISC_LOG_ERROR;
20000		fail = true;
20001	}
20002
20003	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
20004	if (!ok) {
20005		dns_name_format(name, namebuf, sizeof(namebuf));
20006		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20007		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
20008			     dns_result_totext(DNS_R_BADOWNERNAME));
20009		if (fail) {
20010			return (DNS_R_BADOWNERNAME);
20011		}
20012	}
20013
20014	dns_name_init(&bad, NULL);
20015	ok = dns_rdata_checknames(rdata, name, &bad);
20016	if (!ok) {
20017		dns_name_format(name, namebuf, sizeof(namebuf));
20018		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
20019		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20020		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
20021			     namebuf2, dns_result_totext(DNS_R_BADNAME));
20022		if (fail) {
20023			return (DNS_R_BADNAME);
20024		}
20025	}
20026
20027	return (ISC_R_SUCCESS);
20028}
20029
20030void
20031dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
20032	REQUIRE(DNS_ZONE_VALID(zone));
20033	zone->checkmx = checkmx;
20034}
20035
20036void
20037dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
20038	REQUIRE(DNS_ZONE_VALID(zone));
20039	zone->checksrv = checksrv;
20040}
20041
20042void
20043dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
20044	REQUIRE(DNS_ZONE_VALID(zone));
20045	zone->checkns = checkns;
20046}
20047
20048void
20049dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
20050	REQUIRE(DNS_ZONE_VALID(zone));
20051
20052	LOCK_ZONE(zone);
20053	zone->isself = isself;
20054	zone->isselfarg = arg;
20055	UNLOCK_ZONE(zone);
20056}
20057
20058void
20059dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
20060	REQUIRE(DNS_ZONE_VALID(zone));
20061
20062	LOCK_ZONE(zone);
20063	zone->notifydelay = delay;
20064	UNLOCK_ZONE(zone);
20065}
20066
20067uint32_t
20068dns_zone_getnotifydelay(dns_zone_t *zone) {
20069	REQUIRE(DNS_ZONE_VALID(zone));
20070
20071	return (zone->notifydelay);
20072}
20073
20074isc_result_t
20075dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20076		     bool deleteit) {
20077	isc_result_t result;
20078	REQUIRE(DNS_ZONE_VALID(zone));
20079
20080	dnssec_log(zone, ISC_LOG_NOTICE,
20081		   "dns_zone_signwithkey(algorithm=%u, keyid=%u)", algorithm,
20082		   keyid);
20083	LOCK_ZONE(zone);
20084	result = zone_signwithkey(zone, algorithm, keyid, deleteit);
20085	UNLOCK_ZONE(zone);
20086
20087	return (result);
20088}
20089
20090/*
20091 * Called when a dynamic update for an NSEC3PARAM record is received.
20092 *
20093 * If set, transform the NSEC3 salt into human-readable form so that it can be
20094 * logged.  Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
20095 */
20096isc_result_t
20097dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
20098	isc_result_t result;
20099	char salt[255 * 2 + 1];
20100
20101	REQUIRE(DNS_ZONE_VALID(zone));
20102
20103	result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
20104	RUNTIME_CHECK(result == ISC_R_SUCCESS);
20105	dnssec_log(zone, ISC_LOG_NOTICE,
20106		   "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
20107		   nsec3param->hash, nsec3param->iterations, salt);
20108	LOCK_ZONE(zone);
20109	result = zone_addnsec3chain(zone, nsec3param);
20110	UNLOCK_ZONE(zone);
20111
20112	return (result);
20113}
20114
20115void
20116dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
20117	REQUIRE(DNS_ZONE_VALID(zone));
20118
20119	if (nodes == 0) {
20120		nodes = 1;
20121	}
20122	zone->nodes = nodes;
20123}
20124
20125void
20126dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
20127	REQUIRE(DNS_ZONE_VALID(zone));
20128
20129	/*
20130	 * We treat signatures as a signed value so explicitly
20131	 * limit its range here.
20132	 */
20133	if (signatures > INT32_MAX) {
20134		signatures = INT32_MAX;
20135	} else if (signatures == 0) {
20136		signatures = 1;
20137	}
20138	zone->signatures = signatures;
20139}
20140
20141uint32_t
20142dns_zone_getsignatures(dns_zone_t *zone) {
20143	REQUIRE(DNS_ZONE_VALID(zone));
20144	return (zone->signatures);
20145}
20146
20147void
20148dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
20149	REQUIRE(DNS_ZONE_VALID(zone));
20150	zone->privatetype = type;
20151}
20152
20153dns_rdatatype_t
20154dns_zone_getprivatetype(dns_zone_t *zone) {
20155	REQUIRE(DNS_ZONE_VALID(zone));
20156	return (zone->privatetype);
20157}
20158
20159static isc_result_t
20160zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20161		 bool deleteit) {
20162	dns_signing_t *signing;
20163	dns_signing_t *current;
20164	isc_result_t result = ISC_R_SUCCESS;
20165	isc_time_t now;
20166	dns_db_t *db = NULL;
20167
20168	signing = isc_mem_get(zone->mctx, sizeof *signing);
20169
20170	signing->magic = 0;
20171	signing->db = NULL;
20172	signing->dbiterator = NULL;
20173	signing->algorithm = algorithm;
20174	signing->keyid = keyid;
20175	signing->deleteit = deleteit;
20176	signing->done = false;
20177
20178	TIME_NOW(&now);
20179
20180	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
20181	if (zone->db != NULL) {
20182		dns_db_attach(zone->db, &db);
20183	}
20184	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
20185
20186	if (db == NULL) {
20187		result = ISC_R_NOTFOUND;
20188		goto cleanup;
20189	}
20190
20191	dns_db_attach(db, &signing->db);
20192
20193	for (current = ISC_LIST_HEAD(zone->signing); current != NULL;
20194	     current = ISC_LIST_NEXT(current, link))
20195	{
20196		if (current->db == signing->db &&
20197		    current->algorithm == signing->algorithm &&
20198		    current->keyid == signing->keyid)
20199		{
20200			if (current->deleteit != signing->deleteit) {
20201				current->done = true;
20202			} else {
20203				goto cleanup;
20204			}
20205		}
20206	}
20207
20208	result = dns_db_createiterator(signing->db, 0, &signing->dbiterator);
20209
20210	if (result == ISC_R_SUCCESS) {
20211		result = dns_dbiterator_first(signing->dbiterator);
20212	}
20213	if (result == ISC_R_SUCCESS) {
20214		dns_dbiterator_pause(signing->dbiterator);
20215		ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
20216		signing = NULL;
20217		if (isc_time_isepoch(&zone->signingtime)) {
20218			zone->signingtime = now;
20219			if (zone->task != NULL) {
20220				zone_settimer(zone, &now);
20221			}
20222		}
20223	}
20224
20225cleanup:
20226	if (signing != NULL) {
20227		if (signing->db != NULL) {
20228			dns_db_detach(&signing->db);
20229		}
20230		if (signing->dbiterator != NULL) {
20231			dns_dbiterator_destroy(&signing->dbiterator);
20232		}
20233		isc_mem_put(zone->mctx, signing, sizeof *signing);
20234	}
20235	if (db != NULL) {
20236		dns_db_detach(&db);
20237	}
20238	return (result);
20239}
20240
20241/* Called once; *timep should be set to the current time. */
20242static isc_result_t
20243next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
20244	isc_result_t result;
20245	isc_stdtime_t now, then = 0, event;
20246	int i;
20247
20248	now = *timep;
20249
20250	for (i = 0; i <= DST_MAX_TIMES; i++) {
20251		result = dst_key_gettime(key, i, &event);
20252		if (result == ISC_R_SUCCESS && event > now &&
20253		    (then == 0 || event < then))
20254		{
20255			then = event;
20256		}
20257	}
20258
20259	if (then != 0) {
20260		*timep = then;
20261		return (ISC_R_SUCCESS);
20262	}
20263
20264	return (ISC_R_NOTFOUND);
20265}
20266
20267static isc_result_t
20268rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
20269	  const dns_rdata_t *rdata, bool *flag) {
20270	dns_rdataset_t rdataset;
20271	dns_dbnode_t *node = NULL;
20272	isc_result_t result;
20273
20274	dns_rdataset_init(&rdataset);
20275	if (rdata->type == dns_rdatatype_nsec3) {
20276		CHECK(dns_db_findnsec3node(db, name, false, &node));
20277	} else {
20278		CHECK(dns_db_findnode(db, name, false, &node));
20279	}
20280	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
20281				     (isc_stdtime_t)0, &rdataset, NULL);
20282	if (result == ISC_R_NOTFOUND) {
20283		*flag = false;
20284		result = ISC_R_SUCCESS;
20285		goto failure;
20286	}
20287
20288	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
20289	     result = dns_rdataset_next(&rdataset))
20290	{
20291		dns_rdata_t myrdata = DNS_RDATA_INIT;
20292		dns_rdataset_current(&rdataset, &myrdata);
20293		if (!dns_rdata_compare(&myrdata, rdata)) {
20294			break;
20295		}
20296	}
20297	dns_rdataset_disassociate(&rdataset);
20298	if (result == ISC_R_SUCCESS) {
20299		*flag = true;
20300	} else if (result == ISC_R_NOMORE) {
20301		*flag = false;
20302		result = ISC_R_SUCCESS;
20303	}
20304
20305failure:
20306	if (node != NULL) {
20307		dns_db_detachnode(db, &node);
20308	}
20309	return (result);
20310}
20311
20312/*
20313 * Add records to signal the state of signing or of key removal.
20314 */
20315static isc_result_t
20316add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
20317		    dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
20318	dns_difftuple_t *tuple, *newtuple = NULL;
20319	dns_rdata_dnskey_t dnskey;
20320	dns_rdata_t rdata = DNS_RDATA_INIT;
20321	bool flag;
20322	isc_region_t r;
20323	isc_result_t result = ISC_R_SUCCESS;
20324	uint16_t keyid;
20325	unsigned char buf[5];
20326	dns_name_t *name = dns_db_origin(db);
20327
20328	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20329	     tuple = ISC_LIST_NEXT(tuple, link))
20330	{
20331		if (tuple->rdata.type != dns_rdatatype_dnskey) {
20332			continue;
20333		}
20334
20335		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
20336		RUNTIME_CHECK(result == ISC_R_SUCCESS);
20337		if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK |
20338				     DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE)
20339		{
20340			continue;
20341		}
20342
20343		dns_rdata_toregion(&tuple->rdata, &r);
20344
20345		keyid = dst_region_computeid(&r);
20346
20347		buf[0] = dnskey.algorithm;
20348		buf[1] = (keyid & 0xff00) >> 8;
20349		buf[2] = (keyid & 0xff);
20350		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
20351		buf[4] = 0;
20352		rdata.data = buf;
20353		rdata.length = sizeof(buf);
20354		rdata.type = privatetype;
20355		rdata.rdclass = tuple->rdata.rdclass;
20356
20357		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
20358			CHECK(rr_exists(db, ver, name, &rdata, &flag));
20359			if (flag) {
20360				continue;
20361			}
20362
20363			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
20364						   name, 0, &rdata, &newtuple));
20365			CHECK(do_one_tuple(&newtuple, db, ver, diff));
20366			INSIST(newtuple == NULL);
20367		}
20368
20369		/*
20370		 * Remove any record which says this operation has already
20371		 * completed.
20372		 */
20373		buf[4] = 1;
20374		CHECK(rr_exists(db, ver, name, &rdata, &flag));
20375		if (flag) {
20376			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
20377						   name, 0, &rdata, &newtuple));
20378			CHECK(do_one_tuple(&newtuple, db, ver, diff));
20379			INSIST(newtuple == NULL);
20380		}
20381	}
20382failure:
20383	return (result);
20384}
20385
20386/*
20387 * See if dns__zone_updatesigs() will update signature for RRset 'rrtype' at
20388 * the apex, and if not tickle them and cause to sign so that newly activated
20389 * keys are used.
20390 */
20391static isc_result_t
20392tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db,
20393		  dns_dbversion_t *ver, isc_stdtime_t now, dns_diff_t *diff,
20394		  dns__zonediff_t *zonediff, dst_key_t **keys,
20395		  unsigned int nkeys, isc_stdtime_t inception,
20396		  isc_stdtime_t keyexpire, bool check_ksk,
20397		  bool keyset_kskonly) {
20398	dns_difftuple_t *tuple;
20399	isc_result_t result;
20400
20401	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20402	     tuple = ISC_LIST_NEXT(tuple, link))
20403	{
20404		if (tuple->rdata.type == rrtype &&
20405		    dns_name_equal(&tuple->name, &zone->origin))
20406		{
20407			break;
20408		}
20409	}
20410
20411	if (tuple == NULL) {
20412		result = del_sigs(zone, db, ver, &zone->origin, rrtype,
20413				  zonediff, keys, nkeys, now, false);
20414		if (result != ISC_R_SUCCESS) {
20415			dnssec_log(zone, ISC_LOG_ERROR,
20416				   "sign_apex:del_sigs -> %s",
20417				   dns_result_totext(result));
20418			return (result);
20419		}
20420		result = add_sigs(db, ver, &zone->origin, zone, rrtype,
20421				  zonediff->diff, keys, nkeys, zone->mctx,
20422				  inception, keyexpire, check_ksk,
20423				  keyset_kskonly);
20424		if (result != ISC_R_SUCCESS) {
20425			dnssec_log(zone, ISC_LOG_ERROR,
20426				   "sign_apex:add_sigs -> %s",
20427				   dns_result_totext(result));
20428			return (result);
20429		}
20430	}
20431
20432	return (ISC_R_SUCCESS);
20433}
20434
20435static isc_result_t
20436sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20437	  isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff) {
20438	isc_result_t result;
20439	isc_stdtime_t inception, soaexpire, keyexpire;
20440	bool check_ksk, keyset_kskonly;
20441	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
20442	unsigned int nkeys = 0, i;
20443
20444	result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
20445				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
20446	if (result != ISC_R_SUCCESS) {
20447		dnssec_log(zone, ISC_LOG_ERROR,
20448			   "sign_apex:dns__zone_findkeys -> %s",
20449			   dns_result_totext(result));
20450		return (result);
20451	}
20452
20453	inception = now - 3600; /* Allow for clock skew. */
20454	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
20455
20456	keyexpire = dns_zone_getkeyvalidityinterval(zone);
20457	if (keyexpire == 0) {
20458		keyexpire = soaexpire - 1;
20459	} else {
20460		keyexpire += now;
20461	}
20462
20463	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
20464	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
20465
20466	/*
20467	 * See if dns__zone_updatesigs() will update DNSKEY/CDS/CDNSKEY
20468	 * signature and if not cause them to sign so that newly activated
20469	 * keys are used.
20470	 */
20471	result = tickle_apex_rrset(dns_rdatatype_dnskey, zone, db, ver, now,
20472				   diff, zonediff, zone_keys, nkeys, inception,
20473				   keyexpire, check_ksk, keyset_kskonly);
20474	if (result != ISC_R_SUCCESS) {
20475		goto failure;
20476	}
20477	result = tickle_apex_rrset(dns_rdatatype_cds, zone, db, ver, now, diff,
20478				   zonediff, zone_keys, nkeys, inception,
20479				   keyexpire, check_ksk, keyset_kskonly);
20480	if (result != ISC_R_SUCCESS) {
20481		goto failure;
20482	}
20483	result = tickle_apex_rrset(dns_rdatatype_cdnskey, zone, db, ver, now,
20484				   diff, zonediff, zone_keys, nkeys, inception,
20485				   keyexpire, check_ksk, keyset_kskonly);
20486	if (result != ISC_R_SUCCESS) {
20487		goto failure;
20488	}
20489
20490	result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
20491				      inception, soaexpire, keyexpire, now,
20492				      check_ksk, keyset_kskonly, zonediff);
20493
20494	if (result != ISC_R_SUCCESS) {
20495		dnssec_log(zone, ISC_LOG_ERROR,
20496			   "sign_apex:dns__zone_updatesigs -> %s",
20497			   dns_result_totext(result));
20498		goto failure;
20499	}
20500
20501failure:
20502	for (i = 0; i < nkeys; i++) {
20503		dst_key_free(&zone_keys[i]);
20504	}
20505	return (result);
20506}
20507
20508/*
20509 * Prevent the zone entering a inconsistent state where
20510 * NSEC only DNSKEYs are present with NSEC3 chains.
20511 * See update.c:check_dnssec()
20512 */
20513static bool
20514dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20515	    dns_diff_t *diff) {
20516	isc_result_t result;
20517	dns_difftuple_t *tuple;
20518	bool nseconly = false, nsec3 = false;
20519	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
20520
20521	/* Scan the tuples for an NSEC-only DNSKEY */
20522	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20523	     tuple = ISC_LIST_NEXT(tuple, link))
20524	{
20525		uint8_t alg;
20526		if (tuple->rdata.type != dns_rdatatype_dnskey ||
20527		    tuple->op != DNS_DIFFOP_ADD)
20528		{
20529			continue;
20530		}
20531
20532		alg = tuple->rdata.data[3];
20533		if (alg == DST_ALG_RSASHA1) {
20534			nseconly = true;
20535			break;
20536		}
20537	}
20538
20539	/* Check existing DB for NSEC-only DNSKEY */
20540	if (!nseconly) {
20541		result = dns_nsec_nseconly(db, ver, &nseconly);
20542		if (result == ISC_R_NOTFOUND) {
20543			result = ISC_R_SUCCESS;
20544		}
20545		CHECK(result);
20546	}
20547
20548	/* Check existing DB for NSEC3 */
20549	if (!nsec3) {
20550		CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3));
20551	}
20552
20553	/* Refuse to allow NSEC3 with NSEC-only keys */
20554	if (nseconly && nsec3) {
20555		dnssec_log(zone, ISC_LOG_ERROR,
20556			   "NSEC only DNSKEYs and NSEC3 chains not allowed");
20557		goto failure;
20558	}
20559
20560	return (true);
20561
20562failure:
20563	return (false);
20564}
20565
20566static isc_result_t
20567clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20568		 dns_diff_t *diff) {
20569	isc_result_t result;
20570	dns_dbnode_t *node = NULL;
20571	dns_rdataset_t rdataset;
20572
20573	dns_rdataset_init(&rdataset);
20574	CHECK(dns_db_getoriginnode(db, &node));
20575
20576	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
20577				     dns_rdatatype_none, 0, &rdataset, NULL);
20578	if (dns_rdataset_isassociated(&rdataset)) {
20579		dns_rdataset_disassociate(&rdataset);
20580	}
20581	if (result != ISC_R_NOTFOUND) {
20582		goto failure;
20583	}
20584
20585	result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
20586
20587failure:
20588	if (node != NULL) {
20589		dns_db_detachnode(db, &node);
20590	}
20591	return (result);
20592}
20593
20594/*
20595 * Given an RRSIG rdataset and an algorithm, determine whether there
20596 * are any signatures using that algorithm.
20597 */
20598static bool
20599signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
20600	dns_rdata_t rdata = DNS_RDATA_INIT;
20601	dns_rdata_rrsig_t rrsig;
20602	isc_result_t result;
20603
20604	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
20605	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
20606		return (false);
20607	}
20608
20609	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
20610	     result = dns_rdataset_next(rdataset))
20611	{
20612		dns_rdataset_current(rdataset, &rdata);
20613		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
20614		RUNTIME_CHECK(result == ISC_R_SUCCESS);
20615		dns_rdata_reset(&rdata);
20616		if (rrsig.algorithm == alg) {
20617			return (true);
20618		}
20619	}
20620
20621	return (false);
20622}
20623
20624static isc_result_t
20625add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20626	   dns_diff_t *diff) {
20627	dns_name_t *origin;
20628	bool build_nsec3;
20629	isc_result_t result;
20630
20631	origin = dns_db_origin(db);
20632	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
20633				 &build_nsec3));
20634	if (build_nsec3) {
20635		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone_nsecttl(zone),
20636					   false, zone->privatetype, diff));
20637	}
20638	CHECK(updatesecure(db, ver, origin, zone_nsecttl(zone), true, diff));
20639
20640failure:
20641	return (result);
20642}
20643
20644static void
20645dnssec_report(const char *format, ...) {
20646	va_list args;
20647	va_start(args, format);
20648	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
20649		       ISC_LOG_INFO, format, args);
20650	va_end(args);
20651}
20652
20653static void
20654checkds_destroy(dns_checkds_t *checkds, bool locked) {
20655	isc_mem_t *mctx;
20656
20657	REQUIRE(DNS_CHECKDS_VALID(checkds));
20658
20659	dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
20660		     "checkds: destroy DS query");
20661
20662	if (checkds->zone != NULL) {
20663		if (!locked) {
20664			LOCK_ZONE(checkds->zone);
20665		}
20666		REQUIRE(LOCKED_ZONE(checkds->zone));
20667		if (ISC_LINK_LINKED(checkds, link)) {
20668			ISC_LIST_UNLINK(checkds->zone->checkds_requests,
20669					checkds, link);
20670		}
20671		if (!locked) {
20672			UNLOCK_ZONE(checkds->zone);
20673		}
20674		if (locked) {
20675			zone_idetach(&checkds->zone);
20676		} else {
20677			dns_zone_idetach(&checkds->zone);
20678		}
20679	}
20680	if (checkds->request != NULL) {
20681		dns_request_destroy(&checkds->request);
20682	}
20683	if (checkds->key != NULL) {
20684		dns_tsigkey_detach(&checkds->key);
20685	}
20686	mctx = checkds->mctx;
20687	isc_mem_put(checkds->mctx, checkds, sizeof(*checkds));
20688	isc_mem_detach(&mctx);
20689}
20690
20691static isc_result_t
20692make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
20693	    dns_rdata_t *target) {
20694	isc_result_t result;
20695	isc_buffer_t b;
20696	isc_region_t r;
20697
20698	isc_buffer_init(&b, buf, bufsize);
20699	result = dst_key_todns(key, &b);
20700	if (result != ISC_R_SUCCESS) {
20701		return (result);
20702	}
20703
20704	dns_rdata_reset(target);
20705	isc_buffer_usedregion(&b, &r);
20706	dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey,
20707			     &r);
20708	return (ISC_R_SUCCESS);
20709}
20710
20711static bool
20712do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now,
20713	   bool dspublish) {
20714	dns_kasp_t *kasp = dns_zone_getkasp(zone);
20715	const char *dir = dns_zone_getkeydirectory(zone);
20716	isc_result_t result;
20717	uint32_t count = 0;
20718
20719	if (dspublish) {
20720		(void)dst_key_getnum(key, DST_NUM_DSPUBCOUNT, &count);
20721		count += 1;
20722		dst_key_setnum(key, DST_NUM_DSPUBCOUNT, count);
20723		dns_zone_log(zone, ISC_LOG_DEBUG(3),
20724			     "checkds: %u DS published "
20725			     "for key %u",
20726			     count, dst_key_id(key));
20727
20728		if (count != zone->parentalscnt) {
20729			return false;
20730		}
20731	} else {
20732		(void)dst_key_getnum(key, DST_NUM_DSDELCOUNT, &count);
20733		count += 1;
20734		dst_key_setnum(key, DST_NUM_DSDELCOUNT, count);
20735		dns_zone_log(zone, ISC_LOG_DEBUG(3),
20736			     "checkds: %u DS withdrawn "
20737			     "for key %u",
20738			     count, dst_key_id(key));
20739
20740		if (count != zone->parentalscnt) {
20741			return false;
20742		}
20743	}
20744
20745	dns_zone_log(zone, ISC_LOG_DEBUG(3),
20746		     "checkds: checkds %s for key "
20747		     "%u",
20748		     dspublish ? "published" : "withdrawn", dst_key_id(key));
20749
20750	dns_zone_lock_keyfiles(zone);
20751	result = dns_keymgr_checkds_id(kasp, &zone->checkds_ok, dir, now, now,
20752				       dspublish, dst_key_id(key),
20753				       dst_key_alg(key));
20754	dns_zone_unlock_keyfiles(zone);
20755
20756	if (result != ISC_R_SUCCESS) {
20757		dns_zone_log(zone, ISC_LOG_WARNING,
20758			     "checkds: checkds for key %u failed: %s",
20759			     dst_key_id(key), isc_result_totext(result));
20760		return false;
20761	}
20762
20763	return true;
20764}
20765
20766static isc_result_t
20767validate_ds(dns_zone_t *zone, dns_message_t *message) {
20768	UNUSED(zone);
20769	UNUSED(message);
20770
20771	/* Get closest trust anchor */
20772
20773	/* Check that trust anchor is (grand)parent of zone. */
20774
20775	/* Find the DNSKEY signing the message. */
20776
20777	/* Check that DNSKEY is in chain of trust. */
20778
20779	/* Validate DS RRset. */
20780
20781	return (ISC_R_SUCCESS);
20782}
20783
20784static void
20785checkds_done(isc_task_t *task, isc_event_t *event) {
20786	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
20787	char rcode[128];
20788	dns_checkds_t *checkds;
20789	dns_zone_t *zone;
20790	dns_db_t *db = NULL;
20791	dns_dbversion_t *version = NULL;
20792	dns_dnsseckey_t *key;
20793	dns_dnsseckeylist_t keys;
20794	dns_kasp_t *kasp = NULL;
20795	dns_message_t *message = NULL;
20796	dns_rdataset_t *ds_rrset = NULL;
20797	dns_requestevent_t *revent = (dns_requestevent_t *)event;
20798	isc_buffer_t buf;
20799	isc_result_t result;
20800	isc_stdtime_t now;
20801	isc_time_t timenow;
20802	bool rekey = false;
20803	bool empty = false;
20804
20805	UNUSED(task);
20806
20807	checkds = event->ev_arg;
20808	REQUIRE(DNS_CHECKDS_VALID(checkds));
20809
20810	zone = checkds->zone;
20811	INSIST(task == zone->task);
20812
20813	ISC_LIST_INIT(keys);
20814
20815	kasp = zone->kasp;
20816	INSIST(kasp != NULL);
20817
20818	isc_buffer_init(&buf, rcode, sizeof(rcode));
20819	isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
20820
20821	dns_zone_log(zone, ISC_LOG_DEBUG(1), "checkds: DS query to %s: done",
20822		     addrbuf);
20823
20824	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &message);
20825	INSIST(message != NULL);
20826
20827	CHECK(revent->result);
20828	CHECK(dns_request_getresponse(revent->request, message,
20829				      DNS_MESSAGEPARSE_PRESERVEORDER));
20830	CHECK(dns_rcode_totext(message->rcode, &buf));
20831
20832	dns_zone_log(zone, ISC_LOG_DEBUG(3),
20833		     "checkds: DS response from %s: %.*s", addrbuf,
20834		     (int)buf.used, rcode);
20835
20836	/* Validate response. */
20837	CHECK(validate_ds(zone, message));
20838
20839	if (message->rcode != dns_rcode_noerror) {
20840		dns_zone_log(zone, ISC_LOG_NOTICE,
20841			     "checkds: bad DS response from %s: %.*s", addrbuf,
20842			     (int)buf.used, rcode);
20843		goto failure;
20844	}
20845
20846	/* Lookup DS RRset. */
20847	result = dns_message_firstname(message, DNS_SECTION_ANSWER);
20848	while (result == ISC_R_SUCCESS) {
20849		dns_name_t *name = NULL;
20850		dns_rdataset_t *rdataset;
20851
20852		dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
20853		if (dns_name_compare(&zone->origin, name) != 0) {
20854			goto next;
20855		}
20856
20857		for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
20858		     rdataset = ISC_LIST_NEXT(rdataset, link))
20859		{
20860			if (rdataset->type != dns_rdatatype_ds) {
20861				goto next;
20862			}
20863
20864			ds_rrset = rdataset;
20865			break;
20866		}
20867
20868		if (ds_rrset != NULL) {
20869			break;
20870		}
20871
20872	next:
20873		result = dns_message_nextname(message, DNS_SECTION_ANSWER);
20874	}
20875
20876	if (ds_rrset == NULL) {
20877		empty = true;
20878		dns_zone_log(zone, ISC_LOG_NOTICE,
20879			     "checkds: empty DS response from %s", addrbuf);
20880	}
20881
20882	TIME_NOW(&timenow);
20883	now = isc_time_seconds(&timenow);
20884
20885	CHECK(dns_zone_getdb(zone, &db));
20886	dns_db_currentversion(db, &version);
20887
20888	KASP_LOCK(kasp);
20889	LOCK_ZONE(zone);
20890	for (key = ISC_LIST_HEAD(zone->checkds_ok); key != NULL;
20891	     key = ISC_LIST_NEXT(key, link))
20892	{
20893		bool alldone = false, found = false;
20894		bool checkdspub = false, checkdsdel = false, ksk = false;
20895		dst_key_state_t ds_state = DST_KEY_STATE_NA;
20896		isc_stdtime_t published = 0, withdrawn = 0;
20897		isc_result_t ret = ISC_R_SUCCESS;
20898
20899		/* Is this key have the KSK role? */
20900		(void)dst_key_role(key->key, &ksk, NULL);
20901		if (!ksk) {
20902			continue;
20903		}
20904
20905		/* Do we need to check the DS RRset for this key? */
20906		(void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
20907		(void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
20908		(void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
20909
20910		if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
20911			checkdspub = true;
20912		} else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
20913			   withdrawn == 0)
20914		{
20915			checkdsdel = true;
20916		}
20917		if (!checkdspub && !checkdsdel) {
20918			continue;
20919		}
20920
20921		if (empty) {
20922			goto dswithdrawn;
20923		}
20924
20925		/* Find the appropriate DS record. */
20926		ret = dns_rdataset_first(ds_rrset);
20927		while (ret == ISC_R_SUCCESS) {
20928			dns_rdata_ds_t ds;
20929			dns_rdata_t dnskey = DNS_RDATA_INIT;
20930			dns_rdata_t dsrdata = DNS_RDATA_INIT;
20931			dns_rdata_t rdata = DNS_RDATA_INIT;
20932			isc_result_t r;
20933			unsigned char dsbuf[DNS_DS_BUFFERSIZE];
20934			unsigned char keybuf[DST_KEY_MAXSIZE];
20935
20936			dns_rdataset_current(ds_rrset, &rdata);
20937			r = dns_rdata_tostruct(&rdata, &ds, NULL);
20938			if (r != ISC_R_SUCCESS) {
20939				goto nextds;
20940			}
20941			/* Check key tag and algorithm. */
20942			if (dst_key_id(key->key) != ds.key_tag) {
20943				goto nextds;
20944			}
20945			if (dst_key_alg(key->key) != ds.algorithm) {
20946				goto nextds;
20947			}
20948			/* Derive DS from DNSKEY, see if the rdata is equal. */
20949			make_dnskey(key->key, keybuf, sizeof(keybuf), &dnskey);
20950			r = dns_ds_buildrdata(&zone->origin, &dnskey,
20951					      ds.digest_type, dsbuf, &dsrdata);
20952			if (r != ISC_R_SUCCESS) {
20953				goto nextds;
20954			}
20955			if (dns_rdata_compare(&rdata, &dsrdata) == 0) {
20956				found = true;
20957				if (checkdspub) {
20958					/* DS Published. */
20959					alldone = do_checkds(zone, key->key,
20960							     now, true);
20961					if (alldone) {
20962						rekey = true;
20963					}
20964				}
20965			}
20966
20967		nextds:
20968			ret = dns_rdataset_next(ds_rrset);
20969		}
20970
20971	dswithdrawn:
20972		/* DS withdrawn. */
20973		if (checkdsdel && !found) {
20974			alldone = do_checkds(zone, key->key, now, false);
20975			if (alldone) {
20976				rekey = true;
20977			}
20978		}
20979	}
20980	UNLOCK_ZONE(zone);
20981	KASP_UNLOCK(kasp);
20982
20983	/* Rekey after checkds. */
20984	if (rekey) {
20985		dns_zone_rekey(zone, false);
20986	}
20987
20988failure:
20989	if (result != ISC_R_SUCCESS) {
20990		dns_zone_log(zone, ISC_LOG_DEBUG(3),
20991			     "checkds: DS request failed: %s",
20992			     isc_result_totext(result));
20993	}
20994
20995	if (version != NULL) {
20996		dns_db_closeversion(db, &version, false);
20997	}
20998	if (db != NULL) {
20999		dns_db_detach(&db);
21000	}
21001
21002	while (!ISC_LIST_EMPTY(keys)) {
21003		key = ISC_LIST_HEAD(keys);
21004		ISC_LIST_UNLINK(keys, key, link);
21005		dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
21006	}
21007
21008	isc_event_free(&event);
21009	checkds_destroy(checkds, false);
21010	dns_message_detach(&message);
21011}
21012
21013static bool
21014checkds_isqueued(dns_zone_t *zone, isc_sockaddr_t *addr, dns_tsigkey_t *key) {
21015	dns_checkds_t *checkds;
21016
21017	for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
21018	     checkds = ISC_LIST_NEXT(checkds, link))
21019	{
21020		if (checkds->request != NULL) {
21021			continue;
21022		}
21023		if (addr != NULL && isc_sockaddr_equal(addr, &checkds->dst) &&
21024		    checkds->key == key)
21025		{
21026			return (true);
21027		}
21028	}
21029	return (false);
21030}
21031
21032static isc_result_t
21033checkds_create(isc_mem_t *mctx, unsigned int flags, dns_checkds_t **checkdsp) {
21034	dns_checkds_t *checkds;
21035
21036	REQUIRE(checkdsp != NULL && *checkdsp == NULL);
21037
21038	checkds = isc_mem_get(mctx, sizeof(*checkds));
21039	*checkds = (dns_checkds_t){
21040		.flags = flags,
21041	};
21042
21043	isc_mem_attach(mctx, &checkds->mctx);
21044	isc_sockaddr_any(&checkds->dst);
21045	ISC_LINK_INIT(checkds, link);
21046	checkds->magic = CHECKDS_MAGIC;
21047	*checkdsp = checkds;
21048	return (ISC_R_SUCCESS);
21049}
21050
21051static isc_result_t
21052checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep) {
21053	dns_message_t *message = NULL;
21054
21055	dns_name_t *tempname = NULL;
21056	dns_rdataset_t *temprdataset = NULL;
21057
21058	isc_result_t result;
21059
21060	REQUIRE(DNS_ZONE_VALID(zone));
21061	REQUIRE(messagep != NULL && *messagep == NULL);
21062
21063	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
21064
21065	message->opcode = dns_opcode_query;
21066	message->rdclass = zone->rdclass;
21067
21068	result = dns_message_gettempname(message, &tempname);
21069	if (result != ISC_R_SUCCESS) {
21070		goto cleanup;
21071	}
21072
21073	result = dns_message_gettemprdataset(message, &temprdataset);
21074	if (result != ISC_R_SUCCESS) {
21075		goto cleanup;
21076	}
21077
21078	/*
21079	 * Make question.
21080	 */
21081	dns_name_init(tempname, NULL);
21082	dns_name_clone(&zone->origin, tempname);
21083	dns_rdataset_makequestion(temprdataset, zone->rdclass,
21084				  dns_rdatatype_ds);
21085	ISC_LIST_APPEND(tempname->list, temprdataset, link);
21086	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
21087	tempname = NULL;
21088	temprdataset = NULL;
21089
21090	*messagep = message;
21091	return (ISC_R_SUCCESS);
21092
21093cleanup:
21094	if (tempname != NULL) {
21095		dns_message_puttempname(message, &tempname);
21096	}
21097	if (temprdataset != NULL) {
21098		dns_message_puttemprdataset(message, &temprdataset);
21099	}
21100	dns_message_detach(&message);
21101	return (result);
21102}
21103
21104static void
21105checkds_send_toaddr(isc_task_t *task, isc_event_t *event) {
21106	dns_checkds_t *checkds;
21107	isc_result_t result;
21108	dns_message_t *message = NULL;
21109	isc_netaddr_t dstip;
21110	dns_tsigkey_t *key = NULL;
21111	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
21112	isc_sockaddr_t src;
21113	unsigned int options, timeout;
21114	bool have_checkdssource = false;
21115	bool have_checkdsdscp = false;
21116	isc_dscp_t dscp = -1;
21117
21118	checkds = event->ev_arg;
21119	REQUIRE(DNS_CHECKDS_VALID(checkds));
21120
21121	UNUSED(task);
21122
21123	LOCK_ZONE(checkds->zone);
21124
21125	checkds->event = NULL;
21126
21127	if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_LOADED) == 0) {
21128		result = ISC_R_CANCELED;
21129		goto cleanup;
21130	}
21131
21132	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
21133	    DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING) ||
21134	    checkds->zone->view->requestmgr == NULL ||
21135	    checkds->zone->db == NULL)
21136	{
21137		result = ISC_R_CANCELED;
21138		goto cleanup;
21139	}
21140
21141	/*
21142	 * The raw IPv4 address should also exist.  Don't send to the
21143	 * mapped form.
21144	 */
21145	if (isc_sockaddr_pf(&checkds->dst) == PF_INET6 &&
21146	    IN6_IS_ADDR_V4MAPPED(&checkds->dst.type.sin6.sin6_addr))
21147	{
21148		isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21149		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21150			     "checkds: ignoring IPv6 mapped IPV4 address: %s",
21151			     addrbuf);
21152		result = ISC_R_CANCELED;
21153		goto cleanup;
21154	}
21155
21156	result = checkds_createmessage(checkds->zone, &message);
21157	if (result != ISC_R_SUCCESS) {
21158		goto cleanup;
21159	}
21160
21161	isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21162	if (checkds->key != NULL) {
21163		/* Transfer ownership of key */
21164		key = checkds->key;
21165		checkds->key = NULL;
21166	} else {
21167		isc_netaddr_fromsockaddr(&dstip, &checkds->dst);
21168		result = dns_view_getpeertsig(checkds->zone->view, &dstip,
21169					      &key);
21170		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
21171			dns_zone_log(checkds->zone, ISC_LOG_ERROR,
21172				     "checkds: DS query to %s not sent. "
21173				     "Peer TSIG key lookup failure.",
21174				     addrbuf);
21175			goto cleanup_message;
21176		}
21177	}
21178
21179	if (key != NULL) {
21180		char namebuf[DNS_NAME_FORMATSIZE];
21181
21182		dns_name_format(&key->name, namebuf, sizeof(namebuf));
21183		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21184			     "checkds: sending DS query to %s : TSIG (%s)",
21185			     addrbuf, namebuf);
21186	} else {
21187		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21188			     "checkds: sending DS query to %s", addrbuf);
21189	}
21190	options = 0;
21191	if (checkds->zone->view->peers != NULL) {
21192		dns_peer_t *peer = NULL;
21193		bool usetcp = false;
21194		result = dns_peerlist_peerbyaddr(checkds->zone->view->peers,
21195						 &dstip, &peer);
21196		if (result == ISC_R_SUCCESS) {
21197			result = dns_peer_getquerysource(peer, &src);
21198			if (result == ISC_R_SUCCESS) {
21199				have_checkdssource = true;
21200			}
21201			dns_peer_getquerydscp(peer, &dscp);
21202			if (dscp != -1) {
21203				have_checkdsdscp = true;
21204			}
21205			result = dns_peer_getforcetcp(peer, &usetcp);
21206			if (result == ISC_R_SUCCESS && usetcp) {
21207				options |= DNS_FETCHOPT_TCP;
21208			}
21209		}
21210	}
21211	switch (isc_sockaddr_pf(&checkds->dst)) {
21212	case PF_INET:
21213		if (!have_checkdssource) {
21214			src = checkds->zone->parentalsrc4;
21215		}
21216		if (!have_checkdsdscp) {
21217			dscp = checkds->zone->parentalsrc4dscp;
21218		}
21219		break;
21220	case PF_INET6:
21221		if (!have_checkdssource) {
21222			src = checkds->zone->parentalsrc6;
21223		}
21224		if (!have_checkdsdscp) {
21225			dscp = checkds->zone->parentalsrc6dscp;
21226		}
21227		break;
21228	default:
21229		result = ISC_R_NOTIMPLEMENTED;
21230		goto cleanup_key;
21231	}
21232
21233	dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21234		     "checkds: create request for DS query to %s", addrbuf);
21235
21236	timeout = 15;
21237	options |= DNS_REQUESTOPT_TCP;
21238	result = dns_request_createvia(
21239		checkds->zone->view->requestmgr, message, &src, &checkds->dst,
21240		dscp, options, key, timeout * 3, timeout, 0,
21241		checkds->zone->task, checkds_done, checkds, &checkds->request);
21242	if (result != ISC_R_SUCCESS) {
21243		dns_zone_log(
21244			checkds->zone, ISC_LOG_DEBUG(3),
21245			"checkds: dns_request_createvia() to %s failed: %s",
21246			addrbuf, dns_result_totext(result));
21247	}
21248
21249cleanup_key:
21250	if (key != NULL) {
21251		dns_tsigkey_detach(&key);
21252	}
21253cleanup_message:
21254	dns_message_detach(&message);
21255cleanup:
21256	UNLOCK_ZONE(checkds->zone);
21257	isc_event_free(&event);
21258	if (result != ISC_R_SUCCESS) {
21259		checkds_destroy(checkds, false);
21260	}
21261}
21262
21263static isc_result_t
21264checkds_send_queue(dns_checkds_t *checkds) {
21265	isc_event_t *e;
21266	isc_result_t result;
21267
21268	INSIST(checkds->event == NULL);
21269	e = isc_event_allocate(checkds->mctx, NULL, DNS_EVENT_CHECKDSSENDTOADDR,
21270			       checkds_send_toaddr, checkds,
21271			       sizeof(isc_event_t));
21272	e->ev_arg = checkds;
21273	e->ev_sender = NULL;
21274	result = isc_ratelimiter_enqueue(checkds->zone->zmgr->checkdsrl,
21275					 checkds->zone->task, &e);
21276	if (result != ISC_R_SUCCESS) {
21277		isc_event_free(&e);
21278		checkds->event = NULL;
21279	}
21280	return (result);
21281}
21282
21283static void
21284checkds_send(dns_zone_t *zone) {
21285	dns_view_t *view = dns_zone_getview(zone);
21286	isc_result_t result;
21287	unsigned int flags = 0;
21288
21289	/*
21290	 * Zone lock held by caller.
21291	 */
21292	REQUIRE(LOCKED_ZONE(zone));
21293
21294	dns_zone_log(zone, ISC_LOG_DEBUG(3),
21295		     "checkds: start sending DS queries to %u parentals",
21296		     zone->parentalscnt);
21297
21298	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
21299		dns_zone_log(zone, ISC_LOG_DEBUG(3),
21300			     "checkds: abort, named exiting");
21301		return;
21302	}
21303
21304	for (unsigned int i = 0; i < zone->parentalscnt; i++) {
21305		dns_tsigkey_t *key = NULL;
21306		isc_sockaddr_t dst;
21307		dns_checkds_t *checkds = NULL;
21308
21309		if ((zone->parentalkeynames != NULL) &&
21310		    (zone->parentalkeynames[i] != NULL))
21311		{
21312			dns_name_t *keyname = zone->parentalkeynames[i];
21313			(void)dns_view_gettsig(view, keyname, &key);
21314		}
21315
21316		dst = zone->parentals[i];
21317
21318		if (checkds_isqueued(zone, &dst, key)) {
21319			dns_zone_log(zone, ISC_LOG_DEBUG(3),
21320				     "checkds: DS query to parent "
21321				     "%d is queued",
21322				     i);
21323			if (key != NULL) {
21324				dns_tsigkey_detach(&key);
21325			}
21326			continue;
21327		}
21328
21329		dns_zone_log(zone, ISC_LOG_DEBUG(3),
21330			     "checkds: create DS query for "
21331			     "parent %d",
21332			     i);
21333
21334		result = checkds_create(zone->mctx, flags, &checkds);
21335		if (result != ISC_R_SUCCESS) {
21336			dns_zone_log(zone, ISC_LOG_DEBUG(3),
21337				     "checkds: create DS query for "
21338				     "parent %d failed",
21339				     i);
21340			continue;
21341		}
21342		zone_iattach(zone, &checkds->zone);
21343		checkds->dst = dst;
21344
21345		INSIST(checkds->key == NULL);
21346		if (key != NULL) {
21347			checkds->key = key;
21348			key = NULL;
21349		}
21350
21351		ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
21352		result = checkds_send_queue(checkds);
21353		if (result != ISC_R_SUCCESS) {
21354			dns_zone_log(zone, ISC_LOG_DEBUG(3),
21355				     "checkds: send DS query to "
21356				     "parent %d failed",
21357				     i);
21358			checkds_destroy(checkds, true);
21359		}
21360	}
21361}
21362
21363static void
21364zone_checkds(dns_zone_t *zone) {
21365	bool cdscheck = false;
21366
21367	for (dns_dnsseckey_t *key = ISC_LIST_HEAD(zone->checkds_ok);
21368	     key != NULL; key = ISC_LIST_NEXT(key, link))
21369	{
21370		dst_key_state_t ds_state = DST_KEY_STATE_NA;
21371		bool ksk = false;
21372		isc_stdtime_t published = 0, withdrawn = 0;
21373
21374		/* Is this key have the KSK role? */
21375		(void)dst_key_role(key->key, &ksk, NULL);
21376		if (!ksk) {
21377			continue;
21378		}
21379
21380		/* Do we need to check the DS RRset? */
21381		(void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
21382		(void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
21383		(void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
21384
21385		if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
21386			dst_key_setnum(key->key, DST_NUM_DSPUBCOUNT, 0);
21387			cdscheck = true;
21388		} else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
21389			   withdrawn == 0)
21390		{
21391			dst_key_setnum(key->key, DST_NUM_DSDELCOUNT, 0);
21392			cdscheck = true;
21393		}
21394	}
21395
21396	if (cdscheck) {
21397		/* Request the DS RRset. */
21398		LOCK_ZONE(zone);
21399		checkds_send(zone);
21400		UNLOCK_ZONE(zone);
21401	}
21402}
21403
21404static void
21405zone_rekey(dns_zone_t *zone) {
21406	isc_result_t result;
21407	dns_db_t *db = NULL;
21408	dns_dbnode_t *node = NULL;
21409	dns_dbversion_t *ver = NULL;
21410	dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
21411	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
21412	dns_dnsseckey_t *key = NULL;
21413	dns_diff_t diff, _sig_diff;
21414	dns_kasp_t *kasp;
21415	dns__zonediff_t zonediff;
21416	bool commit = false, newactive = false;
21417	bool newalg = false;
21418	bool fullsign;
21419	dns_ttl_t ttl = 3600;
21420	const char *dir = NULL;
21421	isc_mem_t *mctx = NULL;
21422	isc_stdtime_t now, nexttime = 0;
21423	isc_time_t timenow;
21424	isc_interval_t ival;
21425	char timebuf[80];
21426
21427	REQUIRE(DNS_ZONE_VALID(zone));
21428
21429	ISC_LIST_INIT(dnskeys);
21430	ISC_LIST_INIT(keys);
21431	ISC_LIST_INIT(rmkeys);
21432	dns_rdataset_init(&soaset);
21433	dns_rdataset_init(&soasigs);
21434	dns_rdataset_init(&keyset);
21435	dns_rdataset_init(&keysigs);
21436	dns_rdataset_init(&cdsset);
21437	dns_rdataset_init(&cdnskeyset);
21438	dir = dns_zone_getkeydirectory(zone);
21439	mctx = zone->mctx;
21440	dns_diff_init(mctx, &diff);
21441	dns_diff_init(mctx, &_sig_diff);
21442	zonediff_init(&zonediff, &_sig_diff);
21443
21444	CHECK(dns_zone_getdb(zone, &db));
21445	CHECK(dns_db_newversion(db, &ver));
21446	CHECK(dns_db_getoriginnode(db, &node));
21447
21448	TIME_NOW(&timenow);
21449	now = isc_time_seconds(&timenow);
21450
21451	kasp = dns_zone_getkasp(zone);
21452
21453	dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
21454
21455	/* Get the SOA record's TTL */
21456	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
21457				  dns_rdatatype_none, 0, &soaset, &soasigs));
21458	ttl = soaset.ttl;
21459	dns_rdataset_disassociate(&soaset);
21460
21461	/* Get the DNSKEY rdataset */
21462	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
21463				     dns_rdatatype_none, 0, &keyset, &keysigs);
21464	if (result == ISC_R_SUCCESS) {
21465		ttl = keyset.ttl;
21466
21467		dns_zone_lock_keyfiles(zone);
21468
21469		result = dns_dnssec_keylistfromrdataset(
21470			&zone->origin, dir, mctx, &keyset, &keysigs, &soasigs,
21471			false, false, &dnskeys);
21472
21473		dns_zone_unlock_keyfiles(zone);
21474
21475		if (result != ISC_R_SUCCESS) {
21476			goto failure;
21477		}
21478	} else if (result != ISC_R_NOTFOUND) {
21479		goto failure;
21480	}
21481
21482	/* Get the CDS rdataset */
21483	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
21484				     dns_rdatatype_none, 0, &cdsset, NULL);
21485	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
21486		dns_rdataset_disassociate(&cdsset);
21487	}
21488
21489	/* Get the CDNSKEY rdataset */
21490	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
21491				     dns_rdatatype_none, 0, &cdnskeyset, NULL);
21492	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
21493		dns_rdataset_disassociate(&cdnskeyset);
21494	}
21495
21496	/*
21497	 * True when called from "rndc sign".  Indicates the zone should be
21498	 * fully signed now.
21499	 */
21500	fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
21501
21502	KASP_LOCK(kasp);
21503
21504	dns_zone_lock_keyfiles(zone);
21505	result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
21506					     &keys);
21507	dns_zone_unlock_keyfiles(zone);
21508
21509	if (result != ISC_R_SUCCESS) {
21510		dnssec_log(zone, ISC_LOG_DEBUG(1),
21511			   "zone_rekey:dns_dnssec_findmatchingkeys failed: %s",
21512			   isc_result_totext(result));
21513	}
21514
21515	if (kasp != NULL) {
21516		/*
21517		 * Check DS at parental agents. Clear ongoing checks.
21518		 */
21519		LOCK_ZONE(zone);
21520		checkds_cancel(zone);
21521		clear_keylist(&zone->checkds_ok, zone->mctx);
21522		ISC_LIST_INIT(zone->checkds_ok);
21523		UNLOCK_ZONE(zone);
21524
21525		result = dns_zone_getdnsseckeys(zone, db, ver, now,
21526						&zone->checkds_ok);
21527
21528		if (result == ISC_R_SUCCESS) {
21529			zone_checkds(zone);
21530		} else {
21531			dnssec_log(zone,
21532				   (result == ISC_R_NOTFOUND) ? ISC_LOG_DEBUG(1)
21533							      : ISC_LOG_ERROR,
21534				   "zone_rekey:dns_zone_getdnsseckeys failed: "
21535				   "%s",
21536				   isc_result_totext(result));
21537		}
21538
21539		if (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND) {
21540			dns_zone_lock_keyfiles(zone);
21541			result = dns_keymgr_run(&zone->origin, zone->rdclass,
21542						dir, mctx, &keys, &dnskeys,
21543						kasp, now, &nexttime);
21544			dns_zone_unlock_keyfiles(zone);
21545
21546			if (result != ISC_R_SUCCESS) {
21547				dnssec_log(zone, ISC_LOG_ERROR,
21548					   "zone_rekey:dns_dnssec_keymgr "
21549					   "failed: %s",
21550					   isc_result_totext(result));
21551				KASP_UNLOCK(kasp);
21552				goto failure;
21553			}
21554		}
21555	}
21556
21557	KASP_UNLOCK(kasp);
21558
21559	if (result == ISC_R_SUCCESS) {
21560		bool cdsdel = false;
21561		bool cdnskeydel = false;
21562		isc_stdtime_t when;
21563
21564		/*
21565		 * Publish CDS/CDNSKEY DELETE records if the zone is
21566		 * transitioning from secure to insecure.
21567		 */
21568		if (kasp != NULL) {
21569			if (strcmp(dns_kasp_getname(kasp), "insecure") == 0) {
21570				cdsdel = true;
21571				cdnskeydel = true;
21572			}
21573		} else {
21574			/* Check if there is a CDS DELETE record. */
21575			if (dns_rdataset_isassociated(&cdsset)) {
21576				for (result = dns_rdataset_first(&cdsset);
21577				     result == ISC_R_SUCCESS;
21578				     result = dns_rdataset_next(&cdsset))
21579				{
21580					dns_rdata_t crdata = DNS_RDATA_INIT;
21581					dns_rdataset_current(&cdsset, &crdata);
21582					/*
21583					 * CDS deletion record has this form
21584					 * "0 0 0 00" which is 5 zero octets.
21585					 */
21586					if (crdata.length == 5U &&
21587					    memcmp(crdata.data,
21588						   (unsigned char[5]){ 0, 0, 0,
21589								       0, 0 },
21590						   5) == 0)
21591					{
21592						cdsdel = true;
21593						break;
21594					}
21595				}
21596			}
21597
21598			/* Check if there is a CDNSKEY DELETE record. */
21599			if (dns_rdataset_isassociated(&cdnskeyset)) {
21600				for (result = dns_rdataset_first(&cdnskeyset);
21601				     result == ISC_R_SUCCESS;
21602				     result = dns_rdataset_next(&cdnskeyset))
21603				{
21604					dns_rdata_t crdata = DNS_RDATA_INIT;
21605					dns_rdataset_current(&cdnskeyset,
21606							     &crdata);
21607					/*
21608					 * CDNSKEY deletion record has this form
21609					 * "0 3 0 AA==" which is 2 zero octets,
21610					 * a 3, and 2 zero octets.
21611					 */
21612					if (crdata.length == 5U &&
21613					    memcmp(crdata.data,
21614						   (unsigned char[5]){ 0, 0, 3,
21615								       0, 0 },
21616						   5) == 0)
21617					{
21618						cdnskeydel = true;
21619						break;
21620					}
21621				}
21622			}
21623		}
21624
21625		/*
21626		 * Only update DNSKEY TTL if we have a policy.
21627		 */
21628		if (kasp != NULL) {
21629			ttl = dns_kasp_dnskeyttl(kasp);
21630		}
21631
21632		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
21633					       &zone->origin, ttl, &diff, mctx,
21634					       dnssec_report);
21635		/*
21636		 * Keys couldn't be updated for some reason;
21637		 * try again later.
21638		 */
21639		if (result != ISC_R_SUCCESS) {
21640			dnssec_log(zone, ISC_LOG_ERROR,
21641				   "zone_rekey:couldn't update zone keys: %s",
21642				   isc_result_totext(result));
21643			goto failure;
21644		}
21645
21646		/*
21647		 * Update CDS / CDNSKEY records.
21648		 */
21649		result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
21650					       &cdnskeyset, now, ttl, &diff,
21651					       mctx);
21652		if (result != ISC_R_SUCCESS) {
21653			dnssec_log(zone, ISC_LOG_ERROR,
21654				   "zone_rekey:couldn't update CDS/CDNSKEY: %s",
21655				   isc_result_totext(result));
21656			goto failure;
21657		}
21658
21659		if (cdsdel || cdnskeydel) {
21660			/*
21661			 * Only publish CDS/CDNSKEY DELETE records if there is
21662			 * a KSK that can be used to verify the RRset. This
21663			 * means there must be a key with the KSK role that is
21664			 * published and is used for signing.
21665			 */
21666			bool allow = false;
21667			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21668			     key = ISC_LIST_NEXT(key, link))
21669			{
21670				dst_key_t *dstk = key->key;
21671
21672				if (dst_key_is_published(dstk, now, &when) &&
21673				    dst_key_is_signing(dstk, DST_BOOL_KSK, now,
21674						       &when))
21675				{
21676					allow = true;
21677					break;
21678				}
21679			}
21680			if (cdsdel) {
21681				cdsdel = allow;
21682			}
21683			if (cdnskeydel) {
21684				cdnskeydel = allow;
21685			}
21686		}
21687		result = dns_dnssec_syncdelete(
21688			&cdsset, &cdnskeyset, &zone->origin, zone->rdclass, ttl,
21689			&diff, mctx, cdsdel, cdnskeydel);
21690		if (result != ISC_R_SUCCESS) {
21691			dnssec_log(zone, ISC_LOG_ERROR,
21692				   "zone_rekey:couldn't update CDS/CDNSKEY "
21693				   "DELETE records: %s",
21694				   isc_result_totext(result));
21695			goto failure;
21696		}
21697
21698		/*
21699		 * See if any pre-existing keys have newly become active;
21700		 * also, see if any new key is for a new algorithm, as in that
21701		 * event, we need to sign the zone fully.  (If there's a new
21702		 * key, but it's for an already-existing algorithm, then
21703		 * the zone signing can be handled incrementally.)
21704		 */
21705		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21706		     key = ISC_LIST_NEXT(key, link))
21707		{
21708			if (!key->first_sign) {
21709				continue;
21710			}
21711
21712			newactive = true;
21713
21714			if (!dns_rdataset_isassociated(&keysigs)) {
21715				newalg = true;
21716				break;
21717			}
21718
21719			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
21720				/*
21721				 * This isn't a new algorithm; clear
21722				 * first_sign so we won't sign the
21723				 * whole zone with this key later.
21724				 */
21725				key->first_sign = false;
21726			} else {
21727				newalg = true;
21728				break;
21729			}
21730		}
21731
21732		if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
21733		    dnskey_sane(zone, db, ver, &diff))
21734		{
21735			CHECK(dns_diff_apply(&diff, db, ver));
21736			CHECK(clean_nsec3param(zone, db, ver, &diff));
21737			CHECK(add_signing_records(db, zone->privatetype, ver,
21738						  &diff, (newalg || fullsign)));
21739			CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
21740						zone->updatemethod));
21741			CHECK(add_chains(zone, db, ver, &diff));
21742			CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
21743			CHECK(zone_journal(zone, zonediff.diff, NULL,
21744					   "zone_rekey"));
21745			commit = true;
21746		}
21747	}
21748
21749	dns_db_closeversion(db, &ver, true);
21750
21751	LOCK_ZONE(zone);
21752
21753	if (commit) {
21754		dns_difftuple_t *tuple;
21755		dns_stats_t *dnssecsignstats =
21756			dns_zone_getdnssecsignstats(zone);
21757
21758		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
21759
21760		zone_needdump(zone, DNS_DUMP_DELAY);
21761
21762		zone_settimer(zone, &timenow);
21763
21764		/* Remove any signatures from removed keys.  */
21765		if (!ISC_LIST_EMPTY(rmkeys)) {
21766			for (key = ISC_LIST_HEAD(rmkeys); key != NULL;
21767			     key = ISC_LIST_NEXT(key, link))
21768			{
21769				result = zone_signwithkey(
21770					zone, dst_key_alg(key->key),
21771					dst_key_id(key->key), true);
21772				if (result != ISC_R_SUCCESS) {
21773					dnssec_log(zone, ISC_LOG_ERROR,
21774						   "zone_signwithkey failed: "
21775						   "%s",
21776						   dns_result_totext(result));
21777				}
21778
21779				/* Clear DNSSEC sign statistics. */
21780				if (dnssecsignstats != NULL) {
21781					dns_dnssecsignstats_clear(
21782						dnssecsignstats,
21783						dst_key_id(key->key),
21784						dst_key_alg(key->key));
21785					/*
21786					 * Also clear the dnssec-sign
21787					 * statistics of the revoked key id.
21788					 */
21789					dns_dnssecsignstats_clear(
21790						dnssecsignstats,
21791						dst_key_rid(key->key),
21792						dst_key_alg(key->key));
21793				}
21794			}
21795		}
21796
21797		if (fullsign) {
21798			/*
21799			 * "rndc sign" was called, so we now sign the zone
21800			 * with all active keys, whether they're new or not.
21801			 */
21802			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21803			     key = ISC_LIST_NEXT(key, link))
21804			{
21805				if (!key->force_sign && !key->hint_sign) {
21806					continue;
21807				}
21808
21809				result = zone_signwithkey(
21810					zone, dst_key_alg(key->key),
21811					dst_key_id(key->key), false);
21812				if (result != ISC_R_SUCCESS) {
21813					dnssec_log(zone, ISC_LOG_ERROR,
21814						   "zone_signwithkey failed: "
21815						   "%s",
21816						   dns_result_totext(result));
21817				}
21818			}
21819		} else if (newalg) {
21820			/*
21821			 * We haven't been told to sign fully, but a new
21822			 * algorithm was added to the DNSKEY.  We sign
21823			 * the full zone, but only with newly active
21824			 * keys.
21825			 */
21826			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21827			     key = ISC_LIST_NEXT(key, link))
21828			{
21829				if (!key->first_sign) {
21830					continue;
21831				}
21832
21833				result = zone_signwithkey(
21834					zone, dst_key_alg(key->key),
21835					dst_key_id(key->key), false);
21836				if (result != ISC_R_SUCCESS) {
21837					dnssec_log(zone, ISC_LOG_ERROR,
21838						   "zone_signwithkey failed: "
21839						   "%s",
21840						   dns_result_totext(result));
21841				}
21842			}
21843		}
21844
21845		/*
21846		 * Clear fullsign flag, if it was set, so we don't do
21847		 * another full signing next time.
21848		 */
21849		DNS_ZONEKEY_CLROPTION(zone, DNS_ZONEKEY_FULLSIGN);
21850
21851		/*
21852		 * Cause the zone to add/delete NSEC3 chains for the
21853		 * deferred NSEC3PARAM changes.
21854		 */
21855		for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
21856		     tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
21857		{
21858			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
21859			dns_rdata_t rdata = DNS_RDATA_INIT;
21860			dns_rdata_nsec3param_t nsec3param;
21861
21862			if (tuple->rdata.type != zone->privatetype ||
21863			    tuple->op != DNS_DIFFOP_ADD)
21864			{
21865				continue;
21866			}
21867
21868			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
21869							buf, sizeof(buf)))
21870			{
21871				continue;
21872			}
21873
21874			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
21875			RUNTIME_CHECK(result == ISC_R_SUCCESS);
21876			if (nsec3param.flags == 0) {
21877				continue;
21878			}
21879
21880			result = zone_addnsec3chain(zone, &nsec3param);
21881			if (result != ISC_R_SUCCESS) {
21882				dnssec_log(zone, ISC_LOG_ERROR,
21883					   "zone_addnsec3chain failed: %s",
21884					   dns_result_totext(result));
21885			}
21886		}
21887
21888		/*
21889		 * Activate any NSEC3 chain updates that may have
21890		 * been scheduled before this rekey.
21891		 */
21892		if (fullsign || newalg) {
21893			resume_addnsec3chain(zone);
21894		}
21895
21896		/*
21897		 * Schedule the next resigning event
21898		 */
21899		set_resigntime(zone);
21900	}
21901
21902	isc_time_settoepoch(&zone->refreshkeytime);
21903
21904	/*
21905	 * If keymgr provided a next time, use the calculated next rekey time.
21906	 */
21907	if (kasp != NULL) {
21908		isc_time_t timenext;
21909		uint32_t nexttime_seconds;
21910
21911		/*
21912		 * Set the key refresh timer to the next scheduled key event
21913		 * or to 'dnssec-loadkeys-interval' seconds in the future
21914		 * if no next key event is scheduled (nexttime == 0).
21915		 */
21916		if (nexttime > 0) {
21917			nexttime_seconds = nexttime - now;
21918		} else {
21919			nexttime_seconds = zone->refreshkeyinterval;
21920		}
21921
21922		DNS_ZONE_TIME_ADD(&timenow, nexttime_seconds, &timenext);
21923		zone->refreshkeytime = timenext;
21924		zone_settimer(zone, &timenow);
21925		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
21926
21927		dnssec_log(zone, ISC_LOG_DEBUG(3),
21928			   "next key event in %u seconds", nexttime_seconds);
21929		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
21930	}
21931	/*
21932	 * If we're doing key maintenance, set the key refresh timer to
21933	 * the next scheduled key event or to 'dnssec-loadkeys-interval'
21934	 * seconds in the future, whichever is sooner.
21935	 */
21936	else if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
21937	{
21938		isc_time_t timethen;
21939		isc_stdtime_t then;
21940
21941		DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
21942				  &timethen);
21943		zone->refreshkeytime = timethen;
21944
21945		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21946		     key = ISC_LIST_NEXT(key, link))
21947		{
21948			then = now;
21949			result = next_keyevent(key->key, &then);
21950			if (result != ISC_R_SUCCESS) {
21951				continue;
21952			}
21953
21954			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
21955			if (isc_time_compare(&timethen, &zone->refreshkeytime) <
21956			    0)
21957			{
21958				zone->refreshkeytime = timethen;
21959			}
21960		}
21961
21962		zone_settimer(zone, &timenow);
21963
21964		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
21965		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
21966	}
21967	UNLOCK_ZONE(zone);
21968
21969	if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
21970		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21971		     key = ISC_LIST_NEXT(key, link))
21972		{
21973			/* This debug log is used in the kasp system test */
21974			char algbuf[DNS_SECALG_FORMATSIZE];
21975			dns_secalg_format(dst_key_alg(key->key), algbuf,
21976					  sizeof(algbuf));
21977			dnssec_log(zone, ISC_LOG_DEBUG(3),
21978				   "zone_rekey done: key %d/%s",
21979				   dst_key_id(key->key), algbuf);
21980		}
21981	}
21982
21983	result = ISC_R_SUCCESS;
21984
21985failure:
21986	LOCK_ZONE(zone);
21987	if (result != ISC_R_SUCCESS) {
21988		/*
21989		 * Something went wrong; try again in ten minutes or
21990		 * after a key refresh interval, whichever is shorter.
21991		 */
21992		dnssec_log(zone, ISC_LOG_DEBUG(3),
21993			   "zone_rekey failure: %s (retry in %u seconds)",
21994			   isc_result_totext(result),
21995			   ISC_MIN(zone->refreshkeyinterval, 600));
21996		isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600),
21997				 0);
21998		isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
21999	}
22000	UNLOCK_ZONE(zone);
22001
22002	dns_diff_clear(&diff);
22003	dns_diff_clear(&_sig_diff);
22004
22005	clear_keylist(&dnskeys, mctx);
22006	clear_keylist(&keys, mctx);
22007	clear_keylist(&rmkeys, mctx);
22008
22009	if (ver != NULL) {
22010		dns_db_closeversion(db, &ver, false);
22011	}
22012	if (dns_rdataset_isassociated(&cdsset)) {
22013		dns_rdataset_disassociate(&cdsset);
22014	}
22015	if (dns_rdataset_isassociated(&keyset)) {
22016		dns_rdataset_disassociate(&keyset);
22017	}
22018	if (dns_rdataset_isassociated(&keysigs)) {
22019		dns_rdataset_disassociate(&keysigs);
22020	}
22021	if (dns_rdataset_isassociated(&soasigs)) {
22022		dns_rdataset_disassociate(&soasigs);
22023	}
22024	if (dns_rdataset_isassociated(&cdnskeyset)) {
22025		dns_rdataset_disassociate(&cdnskeyset);
22026	}
22027	if (node != NULL) {
22028		dns_db_detachnode(db, &node);
22029	}
22030	if (db != NULL) {
22031		dns_db_detach(&db);
22032	}
22033
22034	INSIST(ver == NULL);
22035}
22036
22037void
22038dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
22039	isc_time_t now;
22040
22041	if (zone->type == dns_zone_primary && zone->task != NULL) {
22042		LOCK_ZONE(zone);
22043
22044		if (fullsign) {
22045			DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
22046		}
22047
22048		TIME_NOW(&now);
22049		zone->refreshkeytime = now;
22050		zone_settimer(zone, &now);
22051
22052		UNLOCK_ZONE(zone);
22053	}
22054}
22055
22056isc_result_t
22057dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
22058		 unsigned int *errors) {
22059	isc_result_t result;
22060	dns_dbnode_t *node = NULL;
22061
22062	REQUIRE(DNS_ZONE_VALID(zone));
22063	REQUIRE(errors != NULL);
22064
22065	result = dns_db_getoriginnode(db, &node);
22066	if (result != ISC_R_SUCCESS) {
22067		return (result);
22068	}
22069	result = zone_count_ns_rr(zone, db, node, version, NULL, errors, false);
22070	dns_db_detachnode(db, &node);
22071	return (result);
22072}
22073
22074isc_result_t
22075dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
22076	isc_result_t result;
22077	dns_dbnode_t *node = NULL;
22078	dns_rdataset_t dnskey, cds, cdnskey;
22079	unsigned char algorithms[256];
22080	unsigned int i;
22081	bool empty = false;
22082
22083	enum { notexpected = 0, expected = 1, found = 2 };
22084
22085	REQUIRE(DNS_ZONE_VALID(zone));
22086
22087	result = dns_db_getoriginnode(db, &node);
22088	if (result != ISC_R_SUCCESS) {
22089		return (result);
22090	}
22091
22092	dns_rdataset_init(&cds);
22093	dns_rdataset_init(&dnskey);
22094	dns_rdataset_init(&cdnskey);
22095
22096	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
22097				     dns_rdatatype_none, 0, &cds, NULL);
22098	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
22099		goto failure;
22100	}
22101
22102	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
22103				     dns_rdatatype_none, 0, &cdnskey, NULL);
22104	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
22105		goto failure;
22106	}
22107
22108	if (!dns_rdataset_isassociated(&cds) &&
22109	    !dns_rdataset_isassociated(&cdnskey))
22110	{
22111		result = ISC_R_SUCCESS;
22112		goto failure;
22113	}
22114
22115	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
22116				     dns_rdatatype_none, 0, &dnskey, NULL);
22117	if (result == ISC_R_NOTFOUND) {
22118		empty = true;
22119	} else if (result != ISC_R_SUCCESS) {
22120		goto failure;
22121	}
22122
22123	/*
22124	 * For each DNSSEC algorithm in the CDS RRset there must be
22125	 * a matching DNSKEY record with the exception of a CDS deletion
22126	 * record which must be by itself.
22127	 */
22128	if (dns_rdataset_isassociated(&cds)) {
22129		bool delete = false;
22130		memset(algorithms, notexpected, sizeof(algorithms));
22131		for (result = dns_rdataset_first(&cds); result == ISC_R_SUCCESS;
22132		     result = dns_rdataset_next(&cds))
22133		{
22134			dns_rdata_t crdata = DNS_RDATA_INIT;
22135			dns_rdata_cds_t structcds;
22136
22137			dns_rdataset_current(&cds, &crdata);
22138			/*
22139			 * CDS deletion record has this form "0 0 0 00" which
22140			 * is 5 zero octets.
22141			 */
22142			if (crdata.length == 5U &&
22143			    memcmp(crdata.data,
22144				   (unsigned char[5]){ 0, 0, 0, 0, 0 }, 5) == 0)
22145			{
22146				delete = true;
22147				continue;
22148			}
22149
22150			if (empty) {
22151				result = DNS_R_BADCDS;
22152				goto failure;
22153			}
22154
22155			CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
22156			if (algorithms[structcds.algorithm] == 0) {
22157				algorithms[structcds.algorithm] = expected;
22158			}
22159			for (result = dns_rdataset_first(&dnskey);
22160			     result == ISC_R_SUCCESS;
22161			     result = dns_rdataset_next(&dnskey))
22162			{
22163				dns_rdata_t rdata = DNS_RDATA_INIT;
22164				dns_rdata_dnskey_t structdnskey;
22165
22166				dns_rdataset_current(&dnskey, &rdata);
22167				CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
22168							 NULL));
22169
22170				if (structdnskey.algorithm ==
22171				    structcds.algorithm)
22172				{
22173					algorithms[structcds.algorithm] = found;
22174				}
22175			}
22176			if (result != ISC_R_NOMORE) {
22177				goto failure;
22178			}
22179		}
22180		for (i = 0; i < sizeof(algorithms); i++) {
22181			if (delete) {
22182				if (algorithms[i] != notexpected) {
22183					result = DNS_R_BADCDS;
22184					goto failure;
22185				}
22186			} else if (algorithms[i] == expected) {
22187				result = DNS_R_BADCDS;
22188				goto failure;
22189			}
22190		}
22191	}
22192
22193	/*
22194	 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
22195	 * a matching DNSKEY record with the exception of a CDNSKEY deletion
22196	 * record which must be by itself.
22197	 */
22198	if (dns_rdataset_isassociated(&cdnskey)) {
22199		bool delete = false;
22200		memset(algorithms, notexpected, sizeof(algorithms));
22201		for (result = dns_rdataset_first(&cdnskey);
22202		     result == ISC_R_SUCCESS;
22203		     result = dns_rdataset_next(&cdnskey))
22204		{
22205			dns_rdata_t crdata = DNS_RDATA_INIT;
22206			dns_rdata_cdnskey_t structcdnskey;
22207
22208			dns_rdataset_current(&cdnskey, &crdata);
22209			/*
22210			 * CDNSKEY deletion record has this form
22211			 * "0 3 0 AA==" which is 2 zero octets, a 3,
22212			 * and 2 zero octets.
22213			 */
22214			if (crdata.length == 5U &&
22215			    memcmp(crdata.data,
22216				   (unsigned char[5]){ 0, 0, 3, 0, 0 }, 5) == 0)
22217			{
22218				delete = true;
22219				continue;
22220			}
22221
22222			if (empty) {
22223				result = DNS_R_BADCDNSKEY;
22224				goto failure;
22225			}
22226
22227			CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
22228						 NULL));
22229			if (algorithms[structcdnskey.algorithm] == 0) {
22230				algorithms[structcdnskey.algorithm] = expected;
22231			}
22232			for (result = dns_rdataset_first(&dnskey);
22233			     result == ISC_R_SUCCESS;
22234			     result = dns_rdataset_next(&dnskey))
22235			{
22236				dns_rdata_t rdata = DNS_RDATA_INIT;
22237				dns_rdata_dnskey_t structdnskey;
22238
22239				dns_rdataset_current(&dnskey, &rdata);
22240				CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
22241							 NULL));
22242
22243				if (structdnskey.algorithm ==
22244				    structcdnskey.algorithm)
22245				{
22246					algorithms[structcdnskey.algorithm] =
22247						found;
22248				}
22249			}
22250			if (result != ISC_R_NOMORE) {
22251				goto failure;
22252			}
22253		}
22254		for (i = 0; i < sizeof(algorithms); i++) {
22255			if (delete) {
22256				if (algorithms[i] != notexpected) {
22257					result = DNS_R_BADCDNSKEY;
22258					goto failure;
22259				}
22260			} else if (algorithms[i] == expected) {
22261				result = DNS_R_BADCDNSKEY;
22262				goto failure;
22263			}
22264		}
22265	}
22266	result = ISC_R_SUCCESS;
22267
22268failure:
22269	if (dns_rdataset_isassociated(&cds)) {
22270		dns_rdataset_disassociate(&cds);
22271	}
22272	if (dns_rdataset_isassociated(&dnskey)) {
22273		dns_rdataset_disassociate(&dnskey);
22274	}
22275	if (dns_rdataset_isassociated(&cdnskey)) {
22276		dns_rdataset_disassociate(&cdnskey);
22277	}
22278	dns_db_detachnode(db, &node);
22279	return (result);
22280}
22281
22282void
22283dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
22284	REQUIRE(DNS_ZONE_VALID(zone));
22285
22286	LOCK_ZONE(zone);
22287	zone->automatic = automatic;
22288	UNLOCK_ZONE(zone);
22289}
22290
22291bool
22292dns_zone_getautomatic(dns_zone_t *zone) {
22293	REQUIRE(DNS_ZONE_VALID(zone));
22294	return (zone->automatic);
22295}
22296
22297void
22298dns_zone_setadded(dns_zone_t *zone, bool added) {
22299	REQUIRE(DNS_ZONE_VALID(zone));
22300
22301	LOCK_ZONE(zone);
22302	zone->added = added;
22303	UNLOCK_ZONE(zone);
22304}
22305
22306bool
22307dns_zone_getadded(dns_zone_t *zone) {
22308	REQUIRE(DNS_ZONE_VALID(zone));
22309	return (zone->added);
22310}
22311
22312isc_result_t
22313dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) {
22314	isc_time_t loadtime;
22315	isc_result_t result;
22316	dns_zone_t *secure = NULL;
22317
22318	TIME_NOW(&loadtime);
22319
22320	/*
22321	 * Lock hierarchy: zmgr, zone, raw.
22322	 */
22323again:
22324	LOCK_ZONE(zone);
22325	INSIST(zone != zone->raw);
22326	if (inline_secure(zone)) {
22327		LOCK_ZONE(zone->raw);
22328	} else if (inline_raw(zone)) {
22329		secure = zone->secure;
22330		TRYLOCK_ZONE(result, secure);
22331		if (result != ISC_R_SUCCESS) {
22332			UNLOCK_ZONE(zone);
22333			secure = NULL;
22334			isc_thread_yield();
22335			goto again;
22336		}
22337	}
22338	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
22339	if (inline_secure(zone)) {
22340		UNLOCK_ZONE(zone->raw);
22341	} else if (secure != NULL) {
22342		UNLOCK_ZONE(secure);
22343	}
22344	UNLOCK_ZONE(zone);
22345	return (result);
22346}
22347
22348isc_result_t
22349dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
22350	REQUIRE(DNS_ZONE_VALID(zone));
22351	if (interval == 0) {
22352		return (ISC_R_RANGE);
22353	}
22354	/* Maximum value: 24 hours (3600 minutes) */
22355	if (interval > (24 * 60)) {
22356		interval = (24 * 60);
22357	}
22358	/* Multiply by 60 for seconds */
22359	zone->refreshkeyinterval = interval * 60;
22360	return (ISC_R_SUCCESS);
22361}
22362
22363void
22364dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
22365	REQUIRE(DNS_ZONE_VALID(zone));
22366	zone->requestixfr = flag;
22367}
22368
22369bool
22370dns_zone_getrequestixfr(dns_zone_t *zone) {
22371	REQUIRE(DNS_ZONE_VALID(zone));
22372	return (zone->requestixfr);
22373}
22374
22375void
22376dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
22377	REQUIRE(DNS_ZONE_VALID(zone));
22378	zone->ixfr_ratio = ratio;
22379}
22380
22381uint32_t
22382dns_zone_getixfrratio(dns_zone_t *zone) {
22383	REQUIRE(DNS_ZONE_VALID(zone));
22384	return (zone->ixfr_ratio);
22385}
22386
22387void
22388dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
22389	REQUIRE(DNS_ZONE_VALID(zone));
22390	zone->requestexpire = flag;
22391}
22392
22393bool
22394dns_zone_getrequestexpire(dns_zone_t *zone) {
22395	REQUIRE(DNS_ZONE_VALID(zone));
22396	return (zone->requestexpire);
22397}
22398
22399void
22400dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
22401	REQUIRE(DNS_ZONE_VALID(zone));
22402	zone->updatemethod = method;
22403}
22404
22405dns_updatemethod_t
22406dns_zone_getserialupdatemethod(dns_zone_t *zone) {
22407	REQUIRE(DNS_ZONE_VALID(zone));
22408	return (zone->updatemethod);
22409}
22410
22411/*
22412 * Lock hierarchy: zmgr, zone, raw.
22413 */
22414isc_result_t
22415dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
22416	isc_result_t result;
22417	dns_zonemgr_t *zmgr;
22418
22419	REQUIRE(DNS_ZONE_VALID(zone));
22420	REQUIRE(zone->zmgr != NULL);
22421	REQUIRE(zone->task != NULL);
22422	REQUIRE(zone->loadtask != NULL);
22423	REQUIRE(zone->raw == NULL);
22424
22425	REQUIRE(DNS_ZONE_VALID(raw));
22426	REQUIRE(raw->zmgr == NULL);
22427	REQUIRE(raw->task == NULL);
22428	REQUIRE(raw->loadtask == NULL);
22429	REQUIRE(raw->secure == NULL);
22430
22431	REQUIRE(zone != raw);
22432
22433	/*
22434	 * Lock hierarchy: zmgr, zone, raw.
22435	 */
22436	zmgr = zone->zmgr;
22437	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
22438	LOCK_ZONE(zone);
22439	LOCK_ZONE(raw);
22440
22441	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
22442				  NULL, zone->task, zone_timer, raw,
22443				  &raw->timer);
22444	if (result != ISC_R_SUCCESS) {
22445		goto unlock;
22446	}
22447
22448	/*
22449	 * The timer "holds" a iref.
22450	 */
22451	isc_refcount_increment0(&raw->irefs);
22452
22453	/* dns_zone_attach(raw, &zone->raw); */
22454	isc_refcount_increment(&raw->erefs);
22455	zone->raw = raw;
22456
22457	/* dns_zone_iattach(zone,  &raw->secure); */
22458	zone_iattach(zone, &raw->secure);
22459
22460	isc_task_attach(zone->task, &raw->task);
22461	isc_task_attach(zone->loadtask, &raw->loadtask);
22462
22463	ISC_LIST_APPEND(zmgr->zones, raw, link);
22464	raw->zmgr = zmgr;
22465	isc_refcount_increment(&zmgr->refs);
22466
22467unlock:
22468	UNLOCK_ZONE(raw);
22469	UNLOCK_ZONE(zone);
22470	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
22471	return (result);
22472}
22473
22474void
22475dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
22476	REQUIRE(DNS_ZONE_VALID(zone));
22477	REQUIRE(raw != NULL && *raw == NULL);
22478
22479	LOCK(&zone->lock);
22480	INSIST(zone != zone->raw);
22481	if (zone->raw != NULL) {
22482		dns_zone_attach(zone->raw, raw);
22483	}
22484	UNLOCK(&zone->lock);
22485}
22486
22487struct keydone {
22488	isc_event_t event;
22489	bool all;
22490	unsigned char data[5];
22491};
22492
22493#define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL)
22494
22495static void
22496keydone(isc_task_t *task, isc_event_t *event) {
22497	const char *me = "keydone";
22498	bool commit = false;
22499	isc_result_t result;
22500	dns_rdata_t rdata = DNS_RDATA_INIT;
22501	dns_dbversion_t *oldver = NULL, *newver = NULL;
22502	dns_zone_t *zone;
22503	dns_db_t *db = NULL;
22504	dns_dbnode_t *node = NULL;
22505	dns_rdataset_t rdataset;
22506	dns_diff_t diff;
22507	struct keydone *kd = (struct keydone *)event;
22508	dns_update_log_t log = { update_log_cb, NULL };
22509	bool clear_pending = false;
22510
22511	UNUSED(task);
22512
22513	zone = event->ev_arg;
22514	INSIST(DNS_ZONE_VALID(zone));
22515
22516	ENTER;
22517
22518	dns_rdataset_init(&rdataset);
22519	dns_diff_init(zone->mctx, &diff);
22520
22521	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22522	if (zone->db != NULL) {
22523		dns_db_attach(zone->db, &db);
22524	}
22525	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22526	if (db == NULL) {
22527		goto failure;
22528	}
22529
22530	dns_db_currentversion(db, &oldver);
22531	result = dns_db_newversion(db, &newver);
22532	if (result != ISC_R_SUCCESS) {
22533		dnssec_log(zone, ISC_LOG_ERROR,
22534			   "keydone:dns_db_newversion -> %s",
22535			   dns_result_totext(result));
22536		goto failure;
22537	}
22538
22539	result = dns_db_getoriginnode(db, &node);
22540	if (result != ISC_R_SUCCESS) {
22541		goto failure;
22542	}
22543
22544	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
22545				     dns_rdatatype_none, 0, &rdataset, NULL);
22546	if (result == ISC_R_NOTFOUND) {
22547		INSIST(!dns_rdataset_isassociated(&rdataset));
22548		goto failure;
22549	}
22550	if (result != ISC_R_SUCCESS) {
22551		INSIST(!dns_rdataset_isassociated(&rdataset));
22552		goto failure;
22553	}
22554
22555	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
22556	     result = dns_rdataset_next(&rdataset))
22557	{
22558		bool found = false;
22559
22560		dns_rdataset_current(&rdataset, &rdata);
22561
22562		if (kd->all) {
22563			if (rdata.length == 5 && rdata.data[0] != 0 &&
22564			    rdata.data[3] == 0 && rdata.data[4] == 1)
22565			{
22566				found = true;
22567			} else if (rdata.data[0] == 0 &&
22568				   (rdata.data[2] & PENDINGFLAGS) != 0)
22569			{
22570				found = true;
22571				clear_pending = true;
22572			}
22573		} else if (rdata.length == 5 &&
22574			   memcmp(rdata.data, kd->data, 5) == 0)
22575		{
22576			found = true;
22577		}
22578
22579		if (found) {
22580			CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
22581					    &zone->origin, rdataset.ttl,
22582					    &rdata));
22583		}
22584		dns_rdata_reset(&rdata);
22585	}
22586
22587	if (!ISC_LIST_EMPTY(diff.tuples)) {
22588		/* Write changes to journal file. */
22589		CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
22590					zone->updatemethod));
22591
22592		result = dns_update_signatures(&log, zone, db, oldver, newver,
22593					       &diff,
22594					       zone->sigvalidityinterval);
22595		if (!clear_pending) {
22596			CHECK(result);
22597		}
22598
22599		CHECK(zone_journal(zone, &diff, NULL, "keydone"));
22600		commit = true;
22601
22602		LOCK_ZONE(zone);
22603		DNS_ZONE_SETFLAG(zone,
22604				 DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
22605		zone_needdump(zone, 30);
22606		UNLOCK_ZONE(zone);
22607	}
22608
22609failure:
22610	if (dns_rdataset_isassociated(&rdataset)) {
22611		dns_rdataset_disassociate(&rdataset);
22612	}
22613	if (db != NULL) {
22614		if (node != NULL) {
22615			dns_db_detachnode(db, &node);
22616		}
22617		if (oldver != NULL) {
22618			dns_db_closeversion(db, &oldver, false);
22619		}
22620		if (newver != NULL) {
22621			dns_db_closeversion(db, &newver, commit);
22622		}
22623		dns_db_detach(&db);
22624	}
22625	dns_diff_clear(&diff);
22626	isc_event_free(&event);
22627	dns_zone_idetach(&zone);
22628
22629	INSIST(oldver == NULL);
22630	INSIST(newver == NULL);
22631}
22632
22633isc_result_t
22634dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
22635	isc_result_t result = ISC_R_SUCCESS;
22636	isc_event_t *e;
22637	isc_buffer_t b;
22638	dns_zone_t *dummy = NULL;
22639	struct keydone *kd;
22640
22641	REQUIRE(DNS_ZONE_VALID(zone));
22642
22643	LOCK_ZONE(zone);
22644
22645	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
22646			       zone, sizeof(struct keydone));
22647
22648	kd = (struct keydone *)e;
22649	if (strcasecmp(keystr, "all") == 0) {
22650		kd->all = true;
22651	} else {
22652		isc_textregion_t r;
22653		const char *algstr;
22654		dns_keytag_t keyid;
22655		dns_secalg_t alg;
22656		size_t n;
22657
22658		kd->all = false;
22659
22660		n = sscanf(keystr, "%hu/", &keyid);
22661		if (n == 0U) {
22662			CHECK(ISC_R_FAILURE);
22663		}
22664
22665		algstr = strchr(keystr, '/');
22666		if (algstr != NULL) {
22667			algstr++;
22668		} else {
22669			CHECK(ISC_R_FAILURE);
22670		}
22671
22672		n = sscanf(algstr, "%hhu", &alg);
22673		if (n == 0U) {
22674			DE_CONST(algstr, r.base);
22675			r.length = strlen(algstr);
22676			CHECK(dns_secalg_fromtext(&alg, &r));
22677		}
22678
22679		/* construct a private-type rdata */
22680		isc_buffer_init(&b, kd->data, sizeof(kd->data));
22681		isc_buffer_putuint8(&b, alg);
22682		isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
22683		isc_buffer_putuint8(&b, (keyid & 0xff));
22684		isc_buffer_putuint8(&b, 0);
22685		isc_buffer_putuint8(&b, 1);
22686	}
22687
22688	zone_iattach(zone, &dummy);
22689	isc_task_send(zone->task, &e);
22690
22691failure:
22692	if (e != NULL) {
22693		isc_event_free(&e);
22694	}
22695	UNLOCK_ZONE(zone);
22696	return (result);
22697}
22698
22699/*
22700 * Called from the zone task's queue after the relevant event is posted by
22701 * dns_zone_setnsec3param().
22702 */
22703static void
22704setnsec3param(isc_task_t *task, isc_event_t *event) {
22705	const char *me = "setnsec3param";
22706	dns_zone_t *zone = event->ev_arg;
22707	bool loadpending;
22708
22709	INSIST(DNS_ZONE_VALID(zone));
22710
22711	UNUSED(task);
22712
22713	ENTER;
22714
22715	LOCK_ZONE(zone);
22716	loadpending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
22717	UNLOCK_ZONE(zone);
22718
22719	/*
22720	 * If receive_secure_serial is still processing or we have a
22721	 * queued event append rss_post queue.
22722	 */
22723	if (zone->rss_newver != NULL || ISC_LIST_HEAD(zone->rss_post) != NULL) {
22724		/*
22725		 * Wait for receive_secure_serial() to finish processing.
22726		 */
22727		ISC_LIST_APPEND(zone->rss_post, event, ev_link);
22728	} else {
22729		bool rescheduled = false;
22730		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22731		/*
22732		 * The zone is not yet fully loaded. Reschedule the event to
22733		 * be picked up later. This turns this function into a busy
22734		 * wait, but it only happens at startup.
22735		 */
22736		if (zone->db == NULL && loadpending) {
22737			rescheduled = true;
22738			isc_task_send(task, &event);
22739		}
22740		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22741		if (rescheduled) {
22742			return;
22743		}
22744
22745		rss_post(zone, event);
22746	}
22747	dns_zone_idetach(&zone);
22748}
22749
22750static void
22751salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
22752	  unsigned int textlen) {
22753	isc_region_t r;
22754	isc_buffer_t buf;
22755	isc_result_t result;
22756
22757	r.base = salt;
22758	r.length = (unsigned int)saltlen;
22759
22760	isc_buffer_init(&buf, text, textlen);
22761	result = isc_hex_totext(&r, 2, "", &buf);
22762	if (result == ISC_R_SUCCESS) {
22763		text[saltlen * 2] = 0;
22764	} else {
22765		text[0] = 0;
22766	}
22767}
22768
22769/*
22770 * Check whether NSEC3 chain addition or removal specified by the private-type
22771 * record passed with the event was already queued (or even fully performed).
22772 * If not, modify the relevant private-type records at the zone apex and call
22773 * resume_addnsec3chain().
22774 */
22775static void
22776rss_post(dns_zone_t *zone, isc_event_t *event) {
22777	const char *me = "rss_post";
22778	bool commit = false;
22779	isc_result_t result;
22780	dns_dbversion_t *oldver = NULL, *newver = NULL;
22781	dns_db_t *db = NULL;
22782	dns_dbnode_t *node = NULL;
22783	dns_rdataset_t prdataset, nrdataset;
22784	dns_diff_t diff;
22785	struct np3event *npe = (struct np3event *)event;
22786	nsec3param_t *np;
22787	dns_update_log_t log = { update_log_cb, NULL };
22788	dns_rdata_t rdata;
22789	bool nseconly;
22790	bool exists = false;
22791
22792	ENTER;
22793
22794	np = &npe->params;
22795
22796	dns_rdataset_init(&prdataset);
22797	dns_rdataset_init(&nrdataset);
22798	dns_diff_init(zone->mctx, &diff);
22799
22800	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22801	if (zone->db != NULL) {
22802		dns_db_attach(zone->db, &db);
22803	}
22804	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22805	if (db == NULL) {
22806		goto failure;
22807	}
22808
22809	dns_db_currentversion(db, &oldver);
22810	result = dns_db_newversion(db, &newver);
22811	if (result != ISC_R_SUCCESS) {
22812		dnssec_log(zone, ISC_LOG_ERROR,
22813			   "setnsec3param:dns_db_newversion -> %s",
22814			   dns_result_totext(result));
22815		goto failure;
22816	}
22817
22818	CHECK(dns_db_getoriginnode(db, &node));
22819
22820	/*
22821	 * Do we need to look up the NSEC3 parameters?
22822	 */
22823	if (np->lookup) {
22824		dns_rdata_nsec3param_t param;
22825		dns_rdata_t nrdata = DNS_RDATA_INIT;
22826		dns_rdata_t prdata = DNS_RDATA_INIT;
22827		unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
22828		unsigned char saltbuf[255];
22829		isc_buffer_t b;
22830
22831		param.salt = NULL;
22832		result = dns__zone_lookup_nsec3param(zone, &np->rdata, &param,
22833						     saltbuf, np->resalt);
22834		if (result == ISC_R_SUCCESS) {
22835			/*
22836			 * Success because the NSEC3PARAM already exists, but
22837			 * function returns void, so goto failure to clean up.
22838			 */
22839			goto failure;
22840		}
22841		if (result != DNS_R_NSEC3RESALT && result != ISC_R_NOTFOUND) {
22842			dnssec_log(zone, ISC_LOG_DEBUG(3),
22843				   "setnsec3param:lookup nsec3param -> %s",
22844				   isc_result_totext(result));
22845			goto failure;
22846		}
22847
22848		INSIST(param.salt != NULL);
22849
22850		/* Update NSEC3 parameters. */
22851		np->rdata.hash = param.hash;
22852		np->rdata.flags = param.flags;
22853		np->rdata.iterations = param.iterations;
22854		np->rdata.salt_length = param.salt_length;
22855		np->rdata.salt = param.salt;
22856
22857		isc_buffer_init(&b, nbuf, sizeof(nbuf));
22858		CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
22859					   dns_rdatatype_nsec3param, &np->rdata,
22860					   &b));
22861		dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
22862					 np->data, sizeof(np->data));
22863		np->length = prdata.length;
22864		np->nsec = false;
22865	}
22866
22867	/*
22868	 * Does a private-type record already exist for this chain?
22869	 */
22870	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
22871				     dns_rdatatype_none, 0, &prdataset, NULL);
22872	if (result == ISC_R_SUCCESS) {
22873		for (result = dns_rdataset_first(&prdataset);
22874		     result == ISC_R_SUCCESS;
22875		     result = dns_rdataset_next(&prdataset))
22876		{
22877			dns_rdata_init(&rdata);
22878			dns_rdataset_current(&prdataset, &rdata);
22879
22880			if (np->length == rdata.length &&
22881			    memcmp(rdata.data, np->data, np->length) == 0)
22882			{
22883				exists = true;
22884				break;
22885			}
22886		}
22887	} else if (result != ISC_R_NOTFOUND) {
22888		INSIST(!dns_rdataset_isassociated(&prdataset));
22889		goto failure;
22890	}
22891
22892	/*
22893	 * Does the chain already exist?
22894	 */
22895	result = dns_db_findrdataset(db, node, newver, dns_rdatatype_nsec3param,
22896				     dns_rdatatype_none, 0, &nrdataset, NULL);
22897	if (result == ISC_R_SUCCESS) {
22898		for (result = dns_rdataset_first(&nrdataset);
22899		     result == ISC_R_SUCCESS;
22900		     result = dns_rdataset_next(&nrdataset))
22901		{
22902			dns_rdata_init(&rdata);
22903			dns_rdataset_current(&nrdataset, &rdata);
22904
22905			if (np->length == (rdata.length + 1) &&
22906			    memcmp(rdata.data, np->data + 1, np->length - 1) ==
22907				    0)
22908			{
22909				exists = true;
22910				break;
22911			}
22912		}
22913	} else if (result != ISC_R_NOTFOUND) {
22914		INSIST(!dns_rdataset_isassociated(&nrdataset));
22915		goto failure;
22916	}
22917
22918	/*
22919	 * We need to remove any existing NSEC3 chains if the supplied NSEC3
22920	 * parameters are supposed to replace the current ones or if we are
22921	 * switching to NSEC.
22922	 */
22923	if (!exists && np->replace && (np->length != 0 || np->nsec)) {
22924		CHECK(dns_nsec3param_deletechains(db, newver, zone, !np->nsec,
22925						  &diff));
22926	}
22927
22928	if (!exists && np->length != 0) {
22929		/*
22930		 * We're creating an NSEC3 chain.  Add the private-type record
22931		 * passed in the event handler's argument to the zone apex.
22932		 *
22933		 * If the zone is not currently capable of supporting an NSEC3
22934		 * chain (due to the DNSKEY RRset at the zone apex not existing
22935		 * or containing at least one key using an NSEC-only
22936		 * algorithm), add the INITIAL flag, so these parameters can be
22937		 * used later when NSEC3 becomes available.
22938		 */
22939		dns_rdata_init(&rdata);
22940
22941		np->data[2] |= DNS_NSEC3FLAG_CREATE;
22942		result = dns_nsec_nseconly(db, newver, &nseconly);
22943		if (result == ISC_R_NOTFOUND || nseconly) {
22944			np->data[2] |= DNS_NSEC3FLAG_INITIAL;
22945		}
22946
22947		rdata.length = np->length;
22948		rdata.data = np->data;
22949		rdata.type = zone->privatetype;
22950		rdata.rdclass = zone->rdclass;
22951		CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
22952				    &zone->origin, 0, &rdata));
22953	}
22954
22955	/*
22956	 * If we changed anything in the zone, write changes to journal file
22957	 * and set commit to true so that resume_addnsec3chain() will be
22958	 * called below in order to kick off adding/removing relevant NSEC3
22959	 * records.
22960	 */
22961	if (!ISC_LIST_EMPTY(diff.tuples)) {
22962		CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
22963					zone->updatemethod));
22964		result = dns_update_signatures(&log, zone, db, oldver, newver,
22965					       &diff,
22966					       zone->sigvalidityinterval);
22967		if (result != ISC_R_NOTFOUND) {
22968			CHECK(result);
22969		}
22970		CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
22971		commit = true;
22972
22973		LOCK_ZONE(zone);
22974		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
22975		zone_needdump(zone, 30);
22976		UNLOCK_ZONE(zone);
22977	}
22978
22979failure:
22980	if (dns_rdataset_isassociated(&prdataset)) {
22981		dns_rdataset_disassociate(&prdataset);
22982	}
22983	if (dns_rdataset_isassociated(&nrdataset)) {
22984		dns_rdataset_disassociate(&nrdataset);
22985	}
22986	if (node != NULL) {
22987		dns_db_detachnode(db, &node);
22988	}
22989	if (oldver != NULL) {
22990		dns_db_closeversion(db, &oldver, false);
22991	}
22992	if (newver != NULL) {
22993		dns_db_closeversion(db, &newver, commit);
22994	}
22995	if (db != NULL) {
22996		dns_db_detach(&db);
22997	}
22998	if (commit) {
22999		LOCK_ZONE(zone);
23000		resume_addnsec3chain(zone);
23001		UNLOCK_ZONE(zone);
23002	}
23003	dns_diff_clear(&diff);
23004	isc_event_free(&event);
23005
23006	INSIST(oldver == NULL);
23007	INSIST(newver == NULL);
23008}
23009
23010/*
23011 * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
23012 *
23013 * If 'salt' is NULL, a match is found if the salt has the requested length,
23014 * otherwise the NSEC3 salt must match the requested salt value too.
23015 *
23016 * Returns  ISC_R_SUCCESS, if a match is found, or an error if no match is
23017 * found, or if the db lookup failed.
23018 */
23019isc_result_t
23020dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup,
23021			    dns_rdata_nsec3param_t *param,
23022			    unsigned char saltbuf[255], bool resalt) {
23023	isc_result_t result = ISC_R_UNEXPECTED;
23024	dns_dbnode_t *node = NULL;
23025	dns_db_t *db = NULL;
23026	dns_dbversion_t *version = NULL;
23027	dns_rdataset_t rdataset;
23028	dns_rdata_nsec3param_t nsec3param;
23029	dns_rdata_t rdata = DNS_RDATA_INIT;
23030
23031	REQUIRE(DNS_ZONE_VALID(zone));
23032
23033	dns_rdataset_init(&rdataset);
23034
23035	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23036	if (zone->db != NULL) {
23037		dns_db_attach(zone->db, &db);
23038	}
23039	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23040	if (db == NULL) {
23041		result = ISC_R_FAILURE;
23042		goto setparam;
23043	}
23044
23045	result = dns_db_findnode(db, &zone->origin, false, &node);
23046	if (result != ISC_R_SUCCESS) {
23047		dns_zone_log(zone, ISC_LOG_ERROR,
23048			     "dns__zone_lookup_nsec3param:"
23049			     "dns_db_findnode -> %s",
23050			     dns_result_totext(result));
23051		result = ISC_R_FAILURE;
23052		goto setparam;
23053	}
23054	dns_db_currentversion(db, &version);
23055
23056	result = dns_db_findrdataset(db, node, version,
23057				     dns_rdatatype_nsec3param,
23058				     dns_rdatatype_none, 0, &rdataset, NULL);
23059	if (result != ISC_R_SUCCESS) {
23060		INSIST(!dns_rdataset_isassociated(&rdataset));
23061		if (result != ISC_R_NOTFOUND) {
23062			dns_zone_log(zone, ISC_LOG_ERROR,
23063				     "dns__zone_lookup_nsec3param:"
23064				     "dns_db_findrdataset -> %s",
23065				     dns_result_totext(result));
23066		}
23067		goto setparam;
23068	}
23069
23070	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
23071	     result = dns_rdataset_next(&rdataset))
23072	{
23073		dns_rdataset_current(&rdataset, &rdata);
23074		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
23075		INSIST(result == ISC_R_SUCCESS);
23076		dns_rdata_reset(&rdata);
23077
23078		/* Check parameters. */
23079		if (nsec3param.hash != lookup->hash) {
23080			continue;
23081		}
23082		if (nsec3param.iterations != lookup->iterations) {
23083			continue;
23084		}
23085		if (nsec3param.salt_length != lookup->salt_length) {
23086			continue;
23087		}
23088		if (lookup->salt != NULL) {
23089			if (memcmp(nsec3param.salt, lookup->salt,
23090				   lookup->salt_length) != 0)
23091			{
23092				continue;
23093			}
23094		}
23095		/* Found a match. */
23096		result = ISC_R_SUCCESS;
23097		param->hash = nsec3param.hash;
23098		param->flags = nsec3param.flags;
23099		param->iterations = nsec3param.iterations;
23100		param->salt_length = nsec3param.salt_length;
23101		param->salt = nsec3param.salt;
23102		break;
23103	}
23104
23105	if (result == ISC_R_NOMORE) {
23106		result = ISC_R_NOTFOUND;
23107	}
23108
23109setparam:
23110	if (result != ISC_R_SUCCESS) {
23111		/* Found no match. */
23112		param->hash = lookup->hash;
23113		param->flags = lookup->flags;
23114		param->iterations = lookup->iterations;
23115		param->salt_length = lookup->salt_length;
23116		param->salt = lookup->salt;
23117	}
23118
23119	if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
23120		goto failure;
23121	}
23122
23123	if (param->salt_length == 0) {
23124		DE_CONST("-", param->salt);
23125	} else if (resalt || param->salt == NULL) {
23126		unsigned char *newsalt;
23127		unsigned char salttext[255 * 2 + 1];
23128		do {
23129			/* Generate a new salt. */
23130			result = dns_nsec3_generate_salt(saltbuf,
23131							 param->salt_length);
23132			if (result != ISC_R_SUCCESS) {
23133				break;
23134			}
23135			newsalt = saltbuf;
23136			salt2text(newsalt, param->salt_length, salttext,
23137				  sizeof(salttext));
23138			dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s",
23139				   salttext);
23140			/* Check for salt conflict. */
23141			if (param->salt != NULL &&
23142			    memcmp(newsalt, param->salt, param->salt_length) ==
23143				    0)
23144			{
23145				result = ISC_R_SUCCESS;
23146			} else {
23147				param->salt = newsalt;
23148				result = DNS_R_NSEC3RESALT;
23149			}
23150		} while (result == ISC_R_SUCCESS);
23151
23152		INSIST(result != ISC_R_SUCCESS);
23153	}
23154
23155failure:
23156	if (dns_rdataset_isassociated(&rdataset)) {
23157		dns_rdataset_disassociate(&rdataset);
23158	}
23159	if (node != NULL) {
23160		dns_db_detachnode(db, &node);
23161	}
23162	if (version != NULL) {
23163		dns_db_closeversion(db, &version, false);
23164	}
23165	if (db != NULL) {
23166		dns_db_detach(&db);
23167	}
23168
23169	return (result);
23170}
23171
23172/*
23173 * Called when an "rndc signing -nsec3param ..." command is received, or the
23174 * 'dnssec-policy' has changed.
23175 *
23176 * Allocate and prepare an nsec3param_t structure which holds information about
23177 * the NSEC3 changes requested for the zone:
23178 *
23179 *   - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
23180 *     field of the structure to true and the "replace" field to the value
23181 *     of the "replace" argument, leaving other fields initialized to zeros, to
23182 *     signal that the zone should be signed using NSEC instead of NSEC3,
23183 *
23184 *   - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
23185 *     the zone apex, convert it to a private-type record and store the latter
23186 *     in the "data" field of the nsec3param_t structure.
23187 *
23188 * Once the nsec3param_t structure is prepared, post an event to the zone's
23189 * task which will cause setnsec3param() to be called with the prepared
23190 * structure passed as an argument.
23191 */
23192isc_result_t
23193dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
23194		       uint16_t iter, uint8_t saltlen, unsigned char *salt,
23195		       bool replace, bool resalt) {
23196	isc_result_t result = ISC_R_SUCCESS;
23197	dns_rdata_nsec3param_t param, lookup;
23198	dns_rdata_t nrdata = DNS_RDATA_INIT;
23199	dns_rdata_t prdata = DNS_RDATA_INIT;
23200	unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
23201	unsigned char saltbuf[255];
23202	struct np3event *npe;
23203	nsec3param_t *np;
23204	dns_zone_t *dummy = NULL;
23205	isc_buffer_t b;
23206	isc_event_t *e = NULL;
23207	bool do_lookup = false;
23208
23209	REQUIRE(DNS_ZONE_VALID(zone));
23210
23211	LOCK_ZONE(zone);
23212
23213	/*
23214	 * First check if the requested NSEC3 parameters are already set,
23215	 * if so, no need to set again.
23216	 */
23217	if (hash != 0) {
23218		lookup.hash = hash;
23219		lookup.flags = flags;
23220		lookup.iterations = iter;
23221		lookup.salt_length = saltlen;
23222		lookup.salt = salt;
23223		param.salt = NULL;
23224		result = dns__zone_lookup_nsec3param(zone, &lookup, &param,
23225						     saltbuf, resalt);
23226		if (result == ISC_R_SUCCESS) {
23227			UNLOCK_ZONE(zone);
23228			return (ISC_R_SUCCESS);
23229		}
23230		/*
23231		 * Schedule lookup if lookup above failed (may happen if zone
23232		 * db is NULL for example).
23233		 */
23234		do_lookup = (param.salt == NULL) ? true : false;
23235	}
23236
23237	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
23238			       setnsec3param, zone, sizeof(struct np3event));
23239
23240	npe = (struct np3event *)e;
23241	np = &npe->params;
23242	np->replace = replace;
23243	np->resalt = resalt;
23244	np->lookup = do_lookup;
23245	if (hash == 0) {
23246		np->length = 0;
23247		np->nsec = true;
23248		dnssec_log(zone, ISC_LOG_DEBUG(3), "setnsec3param:nsec");
23249	} else {
23250		param.common.rdclass = zone->rdclass;
23251		param.common.rdtype = dns_rdatatype_nsec3param;
23252		ISC_LINK_INIT(&param.common, link);
23253		param.mctx = NULL;
23254		/* nsec3 specific param set in dns__zone_lookup_nsec3param() */
23255		isc_buffer_init(&b, nbuf, sizeof(nbuf));
23256
23257		if (param.salt != NULL) {
23258			CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
23259						   dns_rdatatype_nsec3param,
23260						   &param, &b));
23261			dns_nsec3param_toprivate(&nrdata, &prdata,
23262						 zone->privatetype, np->data,
23263						 sizeof(np->data));
23264			np->length = prdata.length;
23265		}
23266
23267		np->rdata = param;
23268		np->nsec = false;
23269
23270		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
23271			unsigned char salttext[255 * 2 + 1];
23272			if (param.salt != NULL) {
23273				salt2text(param.salt, param.salt_length,
23274					  salttext, sizeof(salttext));
23275			}
23276			dnssec_log(zone, ISC_LOG_DEBUG(3),
23277				   "setnsec3param:nsec3 %u %u %u %u:%s",
23278				   param.hash, param.flags, param.iterations,
23279				   param.salt_length,
23280				   param.salt == NULL ? "unknown"
23281						      : (char *)salttext);
23282		}
23283	}
23284
23285	/*
23286	 * setnsec3param() will silently return early if the zone does not yet
23287	 * have a database.  Prevent that by queueing the event up if zone->db
23288	 * is NULL.  All events queued here are subsequently processed by
23289	 * receive_secure_db() if it ever gets called or simply freed by
23290	 * zone_free() otherwise.
23291	 */
23292
23293	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23294	if (zone->db != NULL) {
23295		zone_iattach(zone, &dummy);
23296		isc_task_send(zone->task, &e);
23297	} else {
23298		ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
23299		e = NULL;
23300	}
23301	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23302
23303	result = ISC_R_SUCCESS;
23304
23305failure:
23306	if (e != NULL) {
23307		isc_event_free(&e);
23308	}
23309	UNLOCK_ZONE(zone);
23310	return (result);
23311}
23312
23313isc_result_t
23314dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
23315	REQUIRE(DNS_ZONE_VALID(zone));
23316	REQUIRE(loadtime != NULL);
23317
23318	LOCK_ZONE(zone);
23319	*loadtime = zone->loadtime;
23320	UNLOCK_ZONE(zone);
23321	return (ISC_R_SUCCESS);
23322}
23323
23324isc_result_t
23325dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
23326	REQUIRE(DNS_ZONE_VALID(zone));
23327	REQUIRE(expiretime != NULL);
23328
23329	LOCK_ZONE(zone);
23330	*expiretime = zone->expiretime;
23331	UNLOCK_ZONE(zone);
23332	return (ISC_R_SUCCESS);
23333}
23334
23335isc_result_t
23336dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
23337	REQUIRE(DNS_ZONE_VALID(zone));
23338	REQUIRE(refreshtime != NULL);
23339
23340	LOCK_ZONE(zone);
23341	*refreshtime = zone->refreshtime;
23342	UNLOCK_ZONE(zone);
23343	return (ISC_R_SUCCESS);
23344}
23345
23346isc_result_t
23347dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
23348	REQUIRE(DNS_ZONE_VALID(zone));
23349	REQUIRE(refreshkeytime != NULL);
23350
23351	LOCK_ZONE(zone);
23352	*refreshkeytime = zone->refreshkeytime;
23353	UNLOCK_ZONE(zone);
23354	return (ISC_R_SUCCESS);
23355}
23356
23357unsigned int
23358dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
23359	dns_include_t *include;
23360	char **array = NULL;
23361	unsigned int n = 0;
23362
23363	REQUIRE(DNS_ZONE_VALID(zone));
23364	REQUIRE(includesp != NULL && *includesp == NULL);
23365
23366	LOCK_ZONE(zone);
23367	if (zone->nincludes == 0) {
23368		goto done;
23369	}
23370
23371	array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
23372	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
23373	     include = ISC_LIST_NEXT(include, link))
23374	{
23375		INSIST(n < zone->nincludes);
23376		array[n++] = isc_mem_strdup(zone->mctx, include->name);
23377	}
23378	INSIST(n == zone->nincludes);
23379	*includesp = array;
23380
23381done:
23382	UNLOCK_ZONE(zone);
23383	return (n);
23384}
23385
23386void
23387dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
23388	REQUIRE(DNS_ZONE_VALID(zone));
23389
23390	zone->statlevel = level;
23391}
23392
23393dns_zonestat_level_t
23394dns_zone_getstatlevel(dns_zone_t *zone) {
23395	REQUIRE(DNS_ZONE_VALID(zone));
23396
23397	return (zone->statlevel);
23398}
23399
23400static void
23401setserial(isc_task_t *task, isc_event_t *event) {
23402	uint32_t oldserial, desired;
23403	const char *me = "setserial";
23404	bool commit = false;
23405	isc_result_t result;
23406	dns_dbversion_t *oldver = NULL, *newver = NULL;
23407	dns_zone_t *zone;
23408	dns_db_t *db = NULL;
23409	dns_diff_t diff;
23410	struct ssevent *sse = (struct ssevent *)event;
23411	dns_update_log_t log = { update_log_cb, NULL };
23412	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
23413
23414	UNUSED(task);
23415
23416	zone = event->ev_arg;
23417	INSIST(DNS_ZONE_VALID(zone));
23418
23419	ENTER;
23420
23421	if (zone->update_disabled) {
23422		goto disabled;
23423	}
23424
23425	desired = sse->serial;
23426
23427	dns_diff_init(zone->mctx, &diff);
23428
23429	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23430	if (zone->db != NULL) {
23431		dns_db_attach(zone->db, &db);
23432	}
23433	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23434	if (db == NULL) {
23435		goto failure;
23436	}
23437
23438	dns_db_currentversion(db, &oldver);
23439	result = dns_db_newversion(db, &newver);
23440	if (result != ISC_R_SUCCESS) {
23441		dns_zone_log(zone, ISC_LOG_ERROR,
23442			     "setserial:dns_db_newversion -> %s",
23443			     dns_result_totext(result));
23444		goto failure;
23445	}
23446
23447	CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL,
23448				    &oldtuple));
23449	CHECK(dns_difftuple_copy(oldtuple, &newtuple));
23450	newtuple->op = DNS_DIFFOP_ADD;
23451
23452	oldserial = dns_soa_getserial(&oldtuple->rdata);
23453	if (desired == 0U) {
23454		desired = 1;
23455	}
23456	if (!isc_serial_gt(desired, oldserial)) {
23457		if (desired != oldserial) {
23458			dns_zone_log(zone, ISC_LOG_INFO,
23459				     "setserial: desired serial (%u) "
23460				     "out of range (%u-%u)",
23461				     desired, oldserial + 1,
23462				     (oldserial + 0x7fffffff));
23463		}
23464		goto failure;
23465	}
23466
23467	dns_soa_setserial(desired, &newtuple->rdata);
23468	CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
23469	CHECK(do_one_tuple(&newtuple, db, newver, &diff));
23470	result = dns_update_signatures(&log, zone, db, oldver, newver, &diff,
23471				       zone->sigvalidityinterval);
23472	if (result != ISC_R_NOTFOUND) {
23473		CHECK(result);
23474	}
23475
23476	/* Write changes to journal file. */
23477	CHECK(zone_journal(zone, &diff, NULL, "setserial"));
23478	commit = true;
23479
23480	LOCK_ZONE(zone);
23481	zone_needdump(zone, 30);
23482	UNLOCK_ZONE(zone);
23483
23484failure:
23485	if (oldtuple != NULL) {
23486		dns_difftuple_free(&oldtuple);
23487	}
23488	if (newtuple != NULL) {
23489		dns_difftuple_free(&newtuple);
23490	}
23491	if (oldver != NULL) {
23492		dns_db_closeversion(db, &oldver, false);
23493	}
23494	if (newver != NULL) {
23495		dns_db_closeversion(db, &newver, commit);
23496	}
23497	if (db != NULL) {
23498		dns_db_detach(&db);
23499	}
23500	dns_diff_clear(&diff);
23501
23502disabled:
23503	isc_event_free(&event);
23504	dns_zone_idetach(&zone);
23505
23506	INSIST(oldver == NULL);
23507	INSIST(newver == NULL);
23508}
23509
23510isc_result_t
23511dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
23512	isc_result_t result = ISC_R_SUCCESS;
23513	dns_zone_t *dummy = NULL;
23514	isc_event_t *e = NULL;
23515	struct ssevent *sse;
23516
23517	REQUIRE(DNS_ZONE_VALID(zone));
23518
23519	LOCK_ZONE(zone);
23520
23521	if (!inline_secure(zone)) {
23522		if (!dns_zone_isdynamic(zone, true)) {
23523			result = DNS_R_NOTDYNAMIC;
23524			goto failure;
23525		}
23526	}
23527
23528	if (zone->update_disabled) {
23529		result = DNS_R_FROZEN;
23530		goto failure;
23531	}
23532
23533	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL, setserial,
23534			       zone, sizeof(struct ssevent));
23535
23536	sse = (struct ssevent *)e;
23537	sse->serial = serial;
23538
23539	zone_iattach(zone, &dummy);
23540	isc_task_send(zone->task, &e);
23541
23542failure:
23543	if (e != NULL) {
23544		isc_event_free(&e);
23545	}
23546	UNLOCK_ZONE(zone);
23547	return (result);
23548}
23549
23550isc_stats_t *
23551dns_zone_getgluecachestats(dns_zone_t *zone) {
23552	REQUIRE(DNS_ZONE_VALID(zone));
23553
23554	return (zone->gluecachestats);
23555}
23556
23557bool
23558dns_zone_isloaded(dns_zone_t *zone) {
23559	REQUIRE(DNS_ZONE_VALID(zone));
23560
23561	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
23562}
23563
23564isc_result_t
23565dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
23566	dns_dbversion_t *version = NULL;
23567	dns_keytable_t *secroots = NULL;
23568	isc_result_t result;
23569	dns_name_t *origin;
23570
23571	const char me[] = "dns_zone_verifydb";
23572
23573	REQUIRE(DNS_ZONE_VALID(zone));
23574	REQUIRE(db != NULL);
23575
23576	ENTER;
23577
23578	if (dns_zone_gettype(zone) != dns_zone_mirror) {
23579		return (ISC_R_SUCCESS);
23580	}
23581
23582	if (ver == NULL) {
23583		dns_db_currentversion(db, &version);
23584	} else {
23585		version = ver;
23586	}
23587
23588	if (zone->view != NULL) {
23589		result = dns_view_getsecroots(zone->view, &secroots);
23590		if (result != ISC_R_SUCCESS) {
23591			goto done;
23592		}
23593	}
23594
23595	origin = dns_db_origin(db);
23596	result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
23597				       zone->mctx, true, false, dnssec_report);
23598
23599done:
23600	if (secroots != NULL) {
23601		dns_keytable_detach(&secroots);
23602	}
23603
23604	if (ver == NULL) {
23605		dns_db_closeversion(db, &version, false);
23606	}
23607
23608	if (result != ISC_R_SUCCESS) {
23609		dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
23610			   isc_result_totext(result));
23611		result = DNS_R_VERIFYFAILURE;
23612	}
23613
23614	return (result);
23615}
23616
23617static dns_ttl_t
23618zone_nsecttl(dns_zone_t *zone) {
23619	REQUIRE(DNS_ZONE_VALID(zone));
23620
23621	return (ISC_MIN(zone->minimum, zone->soattl));
23622}
23623