1/*	$NetBSD: zone.c,v 1.19 2024/02/21 22:52:08 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/result.h>
33#include <isc/rwlock.h>
34#include <isc/serial.h>
35#include <isc/stats.h>
36#include <isc/stdtime.h>
37#include <isc/strerr.h>
38#include <isc/string.h>
39#include <isc/taskpool.h>
40#include <isc/thread.h>
41#include <isc/timer.h>
42#include <isc/tls.h>
43#include <isc/util.h>
44
45#include <dns/acl.h>
46#include <dns/adb.h>
47#include <dns/callbacks.h>
48#include <dns/catz.h>
49#include <dns/db.h>
50#include <dns/dbiterator.h>
51#include <dns/dlz.h>
52#include <dns/dnssec.h>
53#include <dns/events.h>
54#include <dns/journal.h>
55#include <dns/kasp.h>
56#include <dns/keydata.h>
57#include <dns/keymgr.h>
58#include <dns/keytable.h>
59#include <dns/keyvalues.h>
60#include <dns/log.h>
61#include <dns/master.h>
62#include <dns/masterdump.h>
63#include <dns/message.h>
64#include <dns/name.h>
65#include <dns/nsec.h>
66#include <dns/nsec3.h>
67#include <dns/opcode.h>
68#include <dns/peer.h>
69#include <dns/private.h>
70#include <dns/rcode.h>
71#include <dns/rdata.h>
72#include <dns/rdataclass.h>
73#include <dns/rdatalist.h>
74#include <dns/rdataset.h>
75#include <dns/rdatasetiter.h>
76#include <dns/rdatastruct.h>
77#include <dns/rdatatype.h>
78#include <dns/request.h>
79#include <dns/resolver.h>
80#include <dns/rriterator.h>
81#include <dns/soa.h>
82#include <dns/ssu.h>
83#include <dns/stats.h>
84#include <dns/time.h>
85#include <dns/tsig.h>
86#include <dns/update.h>
87#include <dns/xfrin.h>
88#include <dns/zone.h>
89#include <dns/zoneverify.h>
90#include <dns/zt.h>
91
92#include <dst/dst.h>
93
94#include "zone_p.h"
95
96#define ZONE_MAGIC	     ISC_MAGIC('Z', 'O', 'N', 'E')
97#define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
98
99#define NOTIFY_MAGIC		 ISC_MAGIC('N', 't', 'f', 'y')
100#define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
101
102#define CHECKDS_MAGIC		   ISC_MAGIC('C', 'h', 'D', 'S')
103#define DNS_CHECKDS_VALID(checkds) ISC_MAGIC_VALID(checkds, CHECKDS_MAGIC)
104
105#define STUB_MAGIC	     ISC_MAGIC('S', 't', 'u', 'b')
106#define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
107
108#define ZONEMGR_MAGIC		ISC_MAGIC('Z', 'm', 'g', 'r')
109#define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
110
111#define LOAD_MAGIC	     ISC_MAGIC('L', 'o', 'a', 'd')
112#define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
113
114#define FORWARD_MAGIC		ISC_MAGIC('F', 'o', 'r', 'w')
115#define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
116
117#define IO_MAGIC	   ISC_MAGIC('Z', 'm', 'I', 'O')
118#define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
119
120#define KEYMGMT_MAGIC		ISC_MAGIC('M', 'g', 'm', 't')
121#define DNS_KEYMGMT_VALID(load) ISC_MAGIC_VALID(load, KEYMGMT_MAGIC)
122
123#define KEYFILEIO_MAGIC		  ISC_MAGIC('K', 'y', 'I', 'O')
124#define DNS_KEYFILEIO_VALID(kfio) ISC_MAGIC_VALID(kfio, KEYFILEIO_MAGIC)
125
126/*%
127 * Ensure 'a' is at least 'min' but not more than 'max'.
128 */
129#define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
130
131#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
132
133/*%
134 * Key flags
135 */
136#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
137#define KSK(x)	  ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
138#define ID(x)	  dst_key_id(x)
139#define ALG(x)	  dst_key_alg(x)
140
141/*%
142 * KASP flags
143 */
144#define KASP_LOCK(k)                  \
145	if ((k) != NULL) {            \
146		LOCK((&((k)->lock))); \
147	}
148
149#define KASP_UNLOCK(k)                  \
150	if ((k) != NULL) {              \
151		UNLOCK((&((k)->lock))); \
152	}
153
154/*
155 * Default values.
156 */
157#define DNS_DEFAULT_IDLEIN  3600       /*%< 1 hour */
158#define DNS_DEFAULT_IDLEOUT 3600       /*%< 1 hour */
159#define MAX_XFER_TIME	    (2 * 3600) /*%< Documented default is 2 hours */
160#define RESIGN_DELAY	    3600       /*%< 1 hour */
161
162#ifndef DNS_MAX_EXPIRE
163#define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
164#endif				/* ifndef DNS_MAX_EXPIRE */
165
166#ifndef DNS_DUMP_DELAY
167#define DNS_DUMP_DELAY 900 /*%< 15 minutes */
168#endif			   /* ifndef DNS_DUMP_DELAY */
169
170typedef struct dns_notify dns_notify_t;
171typedef struct dns_checkds dns_checkds_t;
172typedef struct dns_stub dns_stub_t;
173typedef struct dns_load dns_load_t;
174typedef struct dns_forward dns_forward_t;
175typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
176typedef struct dns_io dns_io_t;
177typedef ISC_LIST(dns_io_t) dns_iolist_t;
178typedef struct dns_keymgmt dns_keymgmt_t;
179typedef struct dns_signing dns_signing_t;
180typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
181typedef struct dns_nsec3chain dns_nsec3chain_t;
182typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
183typedef struct dns_keyfetch dns_keyfetch_t;
184typedef struct dns_asyncload dns_asyncload_t;
185typedef struct dns_include dns_include_t;
186
187#define DNS_ZONE_CHECKLOCK
188#ifdef DNS_ZONE_CHECKLOCK
189#define LOCK_ZONE(z)                  \
190	do {                          \
191		LOCK(&(z)->lock);     \
192		INSIST(!(z)->locked); \
193		(z)->locked = true;   \
194	} while (0)
195#define UNLOCK_ZONE(z)               \
196	do {                         \
197		(z)->locked = false; \
198		UNLOCK(&(z)->lock);  \
199	} while (0)
200#define LOCKED_ZONE(z) ((z)->locked)
201#define TRYLOCK_ZONE(result, z)                         \
202	do {                                            \
203		result = isc_mutex_trylock(&(z)->lock); \
204		if (result == ISC_R_SUCCESS) {          \
205			INSIST(!(z)->locked);           \
206			(z)->locked = true;             \
207		}                                       \
208	} while (0)
209#else /* ifdef DNS_ZONE_CHECKLOCK */
210#define LOCK_ZONE(z)   LOCK(&(z)->lock)
211#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
212#define LOCKED_ZONE(z) true
213#define TRYLOCK_ZONE(result, z)                         \
214	do {                                            \
215		result = isc_mutex_trylock(&(z)->lock); \
216	} while (0)
217#endif /* ifdef DNS_ZONE_CHECKLOCK */
218
219#define ZONEDB_INITLOCK(l)    isc_rwlock_init((l), 0, 0)
220#define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
221#define ZONEDB_LOCK(l, t)     RWLOCK((l), (t))
222#define ZONEDB_UNLOCK(l, t)   RWUNLOCK((l), (t))
223
224#ifdef ENABLE_AFL
225extern bool dns_fuzzing_resolver;
226#endif /* ifdef ENABLE_AFL */
227
228/*%
229 *	Hold key file IO locks.
230 */
231typedef struct dns_keyfileio {
232	unsigned int magic;
233	struct dns_keyfileio *next;
234	uint32_t hashval;
235	dns_fixedname_t fname;
236	dns_name_t *name;
237	isc_refcount_t references;
238	isc_mutex_t lock;
239} dns_keyfileio_t;
240
241struct dns_keymgmt {
242	unsigned int magic;
243	isc_rwlock_t lock;
244	isc_mem_t *mctx;
245
246	dns_keyfileio_t **table;
247
248	atomic_uint_fast32_t count;
249
250	uint32_t bits;
251};
252
253struct dns_zone {
254	/* Unlocked */
255	unsigned int magic;
256	isc_mutex_t lock;
257#ifdef DNS_ZONE_CHECKLOCK
258	bool locked;
259#endif /* ifdef DNS_ZONE_CHECKLOCK */
260	isc_mem_t *mctx;
261	isc_refcount_t erefs;
262
263	isc_rwlock_t dblock;
264	dns_db_t *db; /* Locked by dblock */
265
266	/* Locked */
267	dns_zonemgr_t *zmgr;
268	ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
269	isc_timer_t *timer;
270	isc_refcount_t irefs;
271	dns_name_t origin;
272	char *masterfile;
273	const FILE *stream;		     /* loading from a stream? */
274	ISC_LIST(dns_include_t) includes;    /* Include files */
275	ISC_LIST(dns_include_t) newincludes; /* Loading */
276	unsigned int nincludes;
277	dns_masterformat_t masterformat;
278	const dns_master_style_t *masterstyle;
279	char *journal;
280	int32_t journalsize;
281	dns_rdataclass_t rdclass;
282	dns_zonetype_t type;
283#ifdef __NetBSD__
284	atomic_uint_fast32_t flags;
285	atomic_uint_fast32_t options;
286#else
287	atomic_uint_fast64_t flags;
288	atomic_uint_fast64_t options;
289#endif
290	unsigned int db_argc;
291	char **db_argv;
292	isc_time_t expiretime;
293	isc_time_t refreshtime;
294	isc_time_t dumptime;
295	isc_time_t loadtime;
296	isc_time_t notifytime;
297	isc_time_t resigntime;
298	isc_time_t keywarntime;
299	isc_time_t signingtime;
300	isc_time_t nsec3chaintime;
301	isc_time_t refreshkeytime;
302	uint32_t refreshkeyinterval;
303	uint32_t refreshkeycount;
304	uint32_t refresh;
305	uint32_t retry;
306	uint32_t expire;
307	uint32_t minimum;
308	isc_stdtime_t key_expiry;
309	isc_stdtime_t log_key_expired_timer;
310	char *keydirectory;
311	dns_keyfileio_t *kfio;
312
313	uint32_t maxrefresh;
314	uint32_t minrefresh;
315	uint32_t maxretry;
316	uint32_t minretry;
317
318	uint32_t maxrecords;
319
320	isc_sockaddr_t *primaries;
321	dns_name_t **primarykeynames;
322	dns_name_t **primarytlsnames;
323	bool *primariesok;
324	unsigned int primariescnt;
325	unsigned int curprimary;
326	isc_sockaddr_t primaryaddr;
327
328	isc_sockaddr_t *parentals;
329	dns_name_t **parentalkeynames;
330	dns_name_t **parentaltlsnames;
331	dns_dnsseckeylist_t checkds_ok;
332	unsigned int parentalscnt;
333	isc_sockaddr_t parentaladdr;
334
335	dns_notifytype_t notifytype;
336	isc_sockaddr_t *notify;
337	dns_name_t **notifykeynames;
338	dns_name_t **notifytlsnames;
339	unsigned int notifycnt;
340	isc_sockaddr_t notifyfrom;
341	isc_task_t *task;
342	isc_task_t *loadtask;
343	isc_sockaddr_t notifysrc4;
344	isc_sockaddr_t notifysrc6;
345	isc_sockaddr_t parentalsrc4;
346	isc_sockaddr_t parentalsrc6;
347	isc_sockaddr_t xfrsource4;
348	isc_sockaddr_t xfrsource6;
349	isc_sockaddr_t altxfrsource4;
350	isc_sockaddr_t altxfrsource6;
351	isc_sockaddr_t sourceaddr;
352	dns_xfrin_ctx_t *xfr;	    /* task locked */
353	dns_tsigkey_t *tsigkey;	    /* key used for xfr */
354	dns_transport_t *transport; /* transport used for xfr */
355	/* Access Control Lists */
356	dns_acl_t *update_acl;
357	dns_acl_t *forward_acl;
358	dns_acl_t *notify_acl;
359	dns_acl_t *query_acl;
360	dns_acl_t *queryon_acl;
361	dns_acl_t *xfr_acl;
362	bool update_disabled;
363	bool zero_no_soa_ttl;
364	dns_severity_t check_names;
365	ISC_LIST(dns_notify_t) notifies;
366	ISC_LIST(dns_checkds_t) checkds_requests;
367	dns_request_t *request;
368	dns_loadctx_t *lctx;
369	dns_io_t *readio;
370	dns_dumpctx_t *dctx;
371	dns_io_t *writeio;
372	uint32_t maxxfrin;
373	uint32_t maxxfrout;
374	uint32_t idlein;
375	uint32_t idleout;
376	isc_event_t ctlevent;
377	dns_ssutable_t *ssutable;
378	uint32_t sigvalidityinterval;
379	uint32_t keyvalidityinterval;
380	uint32_t sigresigninginterval;
381	dns_view_t *view;
382	dns_view_t *prev_view;
383	dns_kasp_t *kasp;
384	dns_checkmxfunc_t checkmx;
385	dns_checksrvfunc_t checksrv;
386	dns_checknsfunc_t checkns;
387	/*%
388	 * Zones in certain states such as "waiting for zone transfer"
389	 * or "zone transfer in progress" are kept on per-state linked lists
390	 * in the zone manager using the 'statelink' field.  The 'statelist'
391	 * field points at the list the zone is currently on.  It the zone
392	 * is not on any such list, statelist is NULL.
393	 */
394	ISC_LINK(dns_zone_t) statelink;
395	dns_zonelist_t *statelist;
396	/*%
397	 * Statistics counters about zone management.
398	 */
399	isc_stats_t *stats;
400	/*%
401	 * Optional per-zone statistics counters.  Counted outside of this
402	 * module.
403	 */
404	dns_zonestat_level_t statlevel;
405	bool requeststats_on;
406	isc_stats_t *requeststats;
407	dns_stats_t *rcvquerystats;
408	dns_stats_t *dnssecsignstats;
409	uint32_t notifydelay;
410	dns_isselffunc_t isself;
411	void *isselfarg;
412
413	char *strnamerd;
414	char *strname;
415	char *strrdclass;
416	char *strviewname;
417
418	/*%
419	 * Serial number for deferred journal compaction.
420	 */
421	uint32_t compact_serial;
422	/*%
423	 * Keys that are signing the zone for the first time.
424	 */
425	dns_signinglist_t signing;
426	dns_nsec3chainlist_t nsec3chain;
427	/*%
428	 * List of outstanding NSEC3PARAM change requests.
429	 */
430	isc_eventlist_t setnsec3param_queue;
431	/*%
432	 * Signing / re-signing quantum stopping parameters.
433	 */
434	uint32_t signatures;
435	uint32_t nodes;
436	dns_rdatatype_t privatetype;
437
438	/*%
439	 * Autosigning/key-maintenance options
440	 */
441#ifdef __NetBSD__
442	atomic_uint_fast32_t keyopts;
443#else
444	atomic_uint_fast64_t keyopts;
445#endif
446
447	/*%
448	 * True if added by "rndc addzone"
449	 */
450	bool added;
451
452	/*%
453	 * True if added by automatically by named.
454	 */
455	bool automatic;
456
457	/*%
458	 * response policy data to be relayed to the database
459	 */
460	dns_rpz_zones_t *rpzs;
461	dns_rpz_num_t rpz_num;
462
463	/*%
464	 * catalog zone data
465	 */
466	dns_catz_zones_t *catzs;
467
468	/*%
469	 * parent catalog zone
470	 */
471	dns_catz_zone_t *parentcatz;
472
473	/*%
474	 * Serial number update method.
475	 */
476	dns_updatemethod_t updatemethod;
477
478	/*%
479	 * whether ixfr is requested
480	 */
481	bool requestixfr;
482	uint32_t ixfr_ratio;
483
484	/*%
485	 * whether EDNS EXPIRE is requested
486	 */
487	bool requestexpire;
488
489	/*%
490	 * Outstanding forwarded UPDATE requests.
491	 */
492	dns_forwardlist_t forwards;
493
494	dns_zone_t *raw;
495	dns_zone_t *secure;
496
497	bool sourceserialset;
498	uint32_t sourceserial;
499
500	/*%
501	 * soa and maximum zone ttl
502	 */
503	dns_ttl_t soattl;
504	dns_ttl_t maxttl;
505
506	/*
507	 * Inline zone signing state.
508	 */
509	dns_diff_t rss_diff;
510	isc_eventlist_t rss_events;
511	isc_eventlist_t rss_post;
512	dns_dbversion_t *rss_newver;
513	dns_dbversion_t *rss_oldver;
514	dns_db_t *rss_db;
515	dns_zone_t *rss_raw;
516	isc_event_t *rss_event;
517	dns_update_state_t *rss_state;
518
519	isc_stats_t *gluecachestats;
520};
521
522#define zonediff_init(z, d)                \
523	do {                               \
524		dns__zonediff_t *_z = (z); \
525		(_z)->diff = (d);          \
526		(_z)->offline = false;     \
527	} while (0)
528
529#define DNS_ZONE_FLAG(z, f)    ((atomic_load_relaxed(&(z)->flags) & (f)) != 0)
530#define DNS_ZONE_SETFLAG(z, f) atomic_fetch_or(&(z)->flags, (f))
531#define DNS_ZONE_CLRFLAG(z, f) atomic_fetch_and(&(z)->flags, ~(f))
532typedef enum {
533	DNS_ZONEFLG_REFRESH = 0x00000001U,     /*%< refresh check in progress */
534	DNS_ZONEFLG_NEEDDUMP = 0x00000002U,    /*%< zone need consolidation */
535	DNS_ZONEFLG_USEVC = 0x00000004U,       /*%< use tcp for refresh query */
536	DNS_ZONEFLG_DUMPING = 0x00000008U,     /*%< a dump is in progress */
537	DNS_ZONEFLG_HASINCLUDE = 0x00000010U,  /*%< $INCLUDE in zone file */
538	DNS_ZONEFLG_LOADED = 0x00000020U,      /*%< database has loaded */
539	DNS_ZONEFLG_EXITING = 0x00000040U,     /*%< zone is being destroyed */
540	DNS_ZONEFLG_EXPIRED = 0x00000080U,     /*%< zone has expired */
541	DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
542	DNS_ZONEFLG_UPTODATE = 0x00000200U,    /*%< zone contents are
543						* up-to-date */
544	DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U,  /*%< need to send out notify
545						* messages */
546	DNS_ZONEFLG_FIXJOURNAL = 0x00000800U,  /*%< journal file had
547						* recoverable error,
548						* needs rewriting */
549	DNS_ZONEFLG_NOPRIMARIES = 0x00001000U, /*%< an attempt to refresh a
550						* zone with no primaries
551						* occurred */
552	DNS_ZONEFLG_LOADING = 0x00002000U,     /*%< load from disk in progress*/
553	DNS_ZONEFLG_HAVETIMERS = 0x00004000U,  /*%< timer values have been set
554						* from SOA (if not set, we
555						* are still using
556						* default timer values) */
557	DNS_ZONEFLG_FORCEXFER = 0x00008000U,   /*%< Force a zone xfer */
558	DNS_ZONEFLG_NOREFRESH = 0x00010000U,
559	DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
560	DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
561	DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
562	DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
563	DNS_ZONEFLG_FLUSH = 0x00200000U,
564	DNS_ZONEFLG_NOEDNS = 0x00400000U,
565	DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U,
566	DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
567	DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
568	DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
569	DNS_ZONEFLG_THAW = 0x08000000U,
570	DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
571	DNS_ZONEFLG_NODELAY = 0x20000000U,
572	DNS_ZONEFLG_SENDSECURE = 0x40000000U,
573	DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
574						      * notify due to the zone
575						      * just being loaded for
576						      * the first time. */
577#ifndef __NetBSD__
578	/*
579	 * DO NOT add any new zone flags here until all platforms
580	 * support 64-bit enum values. Currently they fail on
581	 * Windows.
582	 */
583	DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
584#endif
585} dns_zoneflg_t;
586
587#define DNS_ZONE_OPTION(z, o)	 ((atomic_load_relaxed(&(z)->options) & (o)) != 0)
588#define DNS_ZONE_SETOPTION(z, o) atomic_fetch_or(&(z)->options, (o))
589#define DNS_ZONE_CLROPTION(z, o) atomic_fetch_and(&(z)->options, ~(o))
590
591#define DNS_ZONEKEY_OPTION(z, o) \
592	((atomic_load_relaxed(&(z)->keyopts) & (o)) != 0)
593#define DNS_ZONEKEY_SETOPTION(z, o) atomic_fetch_or(&(z)->keyopts, (o))
594#define DNS_ZONEKEY_CLROPTION(z, o) atomic_fetch_and(&(z)->keyopts, ~(o))
595
596/* Flags for zone_load() */
597typedef enum {
598	DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
599	DNS_ZONELOADFLAG_THAW = 0x00000002U,   /* Thaw the zone on successful
600						* load. */
601} dns_zoneloadflag_t;
602
603#define UNREACH_CACHE_SIZE 10U
604#define UNREACH_HOLD_TIME  600 /* 10 minutes */
605
606#define CHECK(op)                            \
607	do {                                 \
608		result = (op);               \
609		if (result != ISC_R_SUCCESS) \
610			goto failure;        \
611	} while (0)
612
613struct dns_unreachable {
614	isc_sockaddr_t remote;
615	isc_sockaddr_t local;
616	atomic_uint_fast32_t expire;
617	atomic_uint_fast32_t last;
618	uint32_t count;
619};
620
621struct dns_zonemgr {
622	unsigned int magic;
623	isc_mem_t *mctx;
624	isc_refcount_t refs;
625	isc_taskmgr_t *taskmgr;
626	isc_timermgr_t *timermgr;
627	isc_nm_t *netmgr;
628	isc_taskpool_t *zonetasks;
629	isc_taskpool_t *loadtasks;
630	isc_task_t *task;
631	isc_pool_t *mctxpool;
632	isc_ratelimiter_t *checkdsrl;
633	isc_ratelimiter_t *notifyrl;
634	isc_ratelimiter_t *refreshrl;
635	isc_ratelimiter_t *startupnotifyrl;
636	isc_ratelimiter_t *startuprefreshrl;
637	isc_rwlock_t rwlock;
638	isc_mutex_t iolock;
639	isc_rwlock_t urlock;
640
641	/* Locked by rwlock. */
642	dns_zonelist_t zones;
643	dns_zonelist_t waiting_for_xfrin;
644	dns_zonelist_t xfrin_in_progress;
645
646	/* Configuration data. */
647	uint32_t transfersin;
648	uint32_t transfersperns;
649	unsigned int checkdsrate;
650	unsigned int notifyrate;
651	unsigned int startupnotifyrate;
652	unsigned int serialqueryrate;
653	unsigned int startupserialqueryrate;
654
655	/* Locked by iolock */
656	uint32_t iolimit;
657	uint32_t ioactive;
658	dns_iolist_t high;
659	dns_iolist_t low;
660
661	/* Locked by urlock. */
662	/* LRU cache */
663	struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
664
665	dns_keymgmt_t *keymgmt;
666
667	isc_tlsctx_cache_t *tlsctx_cache;
668	isc_rwlock_t tlsctx_cache_rwlock;
669};
670
671/*%
672 * Hold notify state.
673 */
674struct dns_notify {
675	unsigned int magic;
676	unsigned int flags;
677	isc_mem_t *mctx;
678	dns_zone_t *zone;
679	dns_adbfind_t *find;
680	dns_request_t *request;
681	dns_name_t ns;
682	isc_sockaddr_t dst;
683	dns_tsigkey_t *key;
684	dns_transport_t *transport;
685	ISC_LINK(dns_notify_t) link;
686	isc_event_t *event;
687};
688
689#define DNS_NOTIFY_NOSOA   0x0001U
690#define DNS_NOTIFY_STARTUP 0x0002U
691
692/*%
693 * Hold checkds state.
694 */
695struct dns_checkds {
696	unsigned int magic;
697	unsigned int flags;
698	isc_mem_t *mctx;
699	dns_zone_t *zone;
700	dns_request_t *request;
701	isc_sockaddr_t dst;
702	dns_tsigkey_t *key;
703	dns_transport_t *transport;
704	ISC_LINK(dns_checkds_t) link;
705	isc_event_t *event;
706};
707
708/*%
709 *	dns_stub holds state while performing a 'stub' transfer.
710 *	'db' is the zone's 'db' or a new one if this is the initial
711 *	transfer.
712 */
713
714struct dns_stub {
715	unsigned int magic;
716	isc_mem_t *mctx;
717	dns_zone_t *zone;
718	dns_db_t *db;
719	dns_dbversion_t *version;
720	atomic_uint_fast32_t pending_requests;
721};
722
723/*%
724 *	Hold load state.
725 */
726struct dns_load {
727	unsigned int magic;
728	isc_mem_t *mctx;
729	dns_zone_t *zone;
730	dns_db_t *db;
731	isc_time_t loadtime;
732	dns_rdatacallbacks_t callbacks;
733};
734
735/*%
736 *	Hold forward state.
737 */
738struct dns_forward {
739	unsigned int magic;
740	isc_mem_t *mctx;
741	dns_zone_t *zone;
742	isc_buffer_t *msgbuf;
743	dns_request_t *request;
744	uint32_t which;
745	isc_sockaddr_t addr;
746	dns_updatecallback_t callback;
747	void *callback_arg;
748	unsigned int options;
749	ISC_LINK(dns_forward_t) link;
750};
751
752/*%
753 *	Hold IO request state.
754 */
755struct dns_io {
756	unsigned int magic;
757	dns_zonemgr_t *zmgr;
758	bool high;
759	isc_task_t *task;
760	ISC_LINK(dns_io_t) link;
761	isc_event_t *event;
762};
763
764/*%
765 *	Hold state for when we are signing a zone with a new
766 *	DNSKEY as result of an update.
767 */
768struct dns_signing {
769	unsigned int magic;
770	dns_db_t *db;
771	dns_dbiterator_t *dbiterator;
772	dns_secalg_t algorithm;
773	uint16_t keyid;
774	bool deleteit;
775	bool done;
776	ISC_LINK(dns_signing_t) link;
777};
778
779struct dns_nsec3chain {
780	unsigned int magic;
781	dns_db_t *db;
782	dns_dbiterator_t *dbiterator;
783	dns_rdata_nsec3param_t nsec3param;
784	unsigned char salt[255];
785	bool done;
786	bool seen_nsec;
787	bool delete_nsec;
788	bool save_delete_nsec;
789	ISC_LINK(dns_nsec3chain_t) link;
790};
791
792/*%<
793 * 'dbiterator' contains a iterator for the database.  If we are creating
794 * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
795 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
796 * iterated.
797 *
798 * 'nsec3param' contains the parameters of the NSEC3 chain being created
799 * or removed.
800 *
801 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
802 *
803 * 'seen_nsec' will be set to true if, while iterating the zone to create a
804 * NSEC3 chain, a NSEC record is seen.
805 *
806 * 'delete_nsec' will be set to true if, at the completion of the creation
807 * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
808 * are in the process of deleting the NSEC chain.
809 *
810 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
811 * so it can be recovered in the event of a error.
812 */
813
814struct dns_keyfetch {
815	isc_mem_t *mctx;
816	dns_fixedname_t name;
817	dns_rdataset_t keydataset;
818	dns_rdataset_t dnskeyset;
819	dns_rdataset_t dnskeysigset;
820	dns_zone_t *zone;
821	dns_db_t *db;
822	dns_fetch_t *fetch;
823};
824
825/*%
826 * Hold state for an asynchronous load
827 */
828struct dns_asyncload {
829	dns_zone_t *zone;
830	unsigned int flags;
831	dns_zt_zoneloaded_t loaded;
832	void *loaded_arg;
833};
834
835/*%
836 * Reference to an include file encountered during loading
837 */
838struct dns_include {
839	char *name;
840	isc_time_t filetime;
841	ISC_LINK(dns_include_t) link;
842};
843
844/*
845 * These can be overridden by the -T mkeytimers option on the command
846 * line, so that we can test with shorter periods than specified in
847 * RFC 5011.
848 */
849#define HOUR  3600
850#define DAY   (24 * HOUR)
851#define MONTH (30 * DAY)
852unsigned int dns_zone_mkey_hour = HOUR;
853unsigned int dns_zone_mkey_day = DAY;
854unsigned int dns_zone_mkey_month = MONTH;
855
856#define SEND_BUFFER_SIZE 2048
857
858static void
859zone_settimer(dns_zone_t *, isc_time_t *);
860static void
861cancel_refresh(dns_zone_t *);
862static void
863zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
864	      ...) ISC_FORMAT_PRINTF(4, 5);
865static void
866notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
867	ISC_FORMAT_PRINTF(3, 4);
868static void
869dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
870	ISC_FORMAT_PRINTF(3, 4);
871static void
872queue_xfrin(dns_zone_t *zone);
873static isc_result_t
874update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
875	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
876	      dns_rdata_t *rdata);
877static void
878zone_unload(dns_zone_t *zone);
879static void
880zone_expire(dns_zone_t *zone);
881static void
882zone_refresh(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 void
1018zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache);
1019/*%<
1020 *	Attach to TLS client context cache used for zone transfers via
1021 *	encrypted transports (e.g. XoT).
1022 *
1023 * The obtained reference needs to be detached by a call to
1024 * 'isc_tlsctx_cache_detach()' when not needed anymore.
1025 *
1026 * Requires:
1027 *\li	'zmgr' is a valid zone manager.
1028 *\li	'ptlsctx_cache' is not 'NULL' and points to 'NULL'.
1029 */
1030
1031static const unsigned int dbargc_default = 1;
1032static const char *dbargv_default[] = { "rbt" };
1033
1034#define DNS_ZONE_JITTER_ADD(a, b, c)                                         \
1035	do {                                                                 \
1036		isc_interval_t _i;                                           \
1037		uint32_t _j;                                                 \
1038		_j = (b)-isc_random_uniform((b) / 4);                        \
1039		isc_interval_set(&_i, _j, 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, _j / 2, 0);                    \
1046			(void)isc_time_add((a), &_i, (c));                   \
1047		}                                                            \
1048	} while (0)
1049
1050#define DNS_ZONE_TIME_ADD(a, b, c)                                           \
1051	do {                                                                 \
1052		isc_interval_t _i;                                           \
1053		isc_interval_set(&_i, (b), 0);                               \
1054		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
1055			dns_zone_log(zone, ISC_LOG_WARNING,                  \
1056				     "epoch approaching: upgrade required: " \
1057				     "now + %s failed",                      \
1058				     #b);                                    \
1059			isc_interval_set(&_i, (b) / 2, 0);                   \
1060			(void)isc_time_add((a), &_i, (c));                   \
1061		}                                                            \
1062	} while (0)
1063
1064typedef struct nsec3param nsec3param_t;
1065struct nsec3param {
1066	dns_rdata_nsec3param_t rdata;
1067	unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
1068	unsigned int length;
1069	bool nsec;
1070	bool replace;
1071	bool resalt;
1072	bool lookup;
1073	ISC_LINK(nsec3param_t) link;
1074};
1075typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
1076struct np3event {
1077	isc_event_t event;
1078	nsec3param_t params;
1079};
1080
1081struct ssevent {
1082	isc_event_t event;
1083	uint32_t serial;
1084};
1085
1086struct stub_cb_args {
1087	dns_stub_t *stub;
1088	dns_tsigkey_t *tsig_key;
1089	uint16_t udpsize;
1090	int timeout;
1091	bool reqnsid;
1092};
1093
1094struct stub_glue_request {
1095	dns_request_t *request;
1096	dns_name_t name;
1097	struct stub_cb_args *args;
1098	bool ipv4;
1099};
1100
1101/*%
1102 * Increment resolver-related statistics counters.  Zone must be locked.
1103 */
1104static void
1105inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
1106	if (zone->stats != NULL) {
1107		isc_stats_increment(zone->stats, counter);
1108	}
1109}
1110
1111/***
1112 ***	Public functions.
1113 ***/
1114
1115isc_result_t
1116dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
1117	isc_result_t result;
1118	isc_time_t now;
1119	dns_zone_t *zone = NULL;
1120	dns_zone_t z = { .masterformat = dns_masterformat_none,
1121			 .journalsize = -1,
1122			 .rdclass = dns_rdataclass_none,
1123			 .type = dns_zone_none,
1124			 .refresh = DNS_ZONE_DEFAULTREFRESH,
1125			 .retry = DNS_ZONE_DEFAULTRETRY,
1126			 .maxrefresh = DNS_ZONE_MAXREFRESH,
1127			 .minrefresh = DNS_ZONE_MINREFRESH,
1128			 .maxretry = DNS_ZONE_MAXRETRY,
1129			 .minretry = DNS_ZONE_MINRETRY,
1130			 .notifytype = dns_notifytype_yes,
1131			 .zero_no_soa_ttl = true,
1132			 .check_names = dns_severity_ignore,
1133			 .idlein = DNS_DEFAULT_IDLEIN,
1134			 .idleout = DNS_DEFAULT_IDLEOUT,
1135			 .maxxfrin = MAX_XFER_TIME,
1136			 .maxxfrout = MAX_XFER_TIME,
1137			 .sigvalidityinterval = 30 * 24 * 3600,
1138			 .sigresigninginterval = 7 * 24 * 3600,
1139			 .statlevel = dns_zonestat_none,
1140			 .notifydelay = 5,
1141			 .signatures = 10,
1142			 .nodes = 100,
1143			 .privatetype = (dns_rdatatype_t)0xffffU,
1144			 .rpz_num = DNS_RPZ_INVALID_NUM,
1145			 .requestixfr = true,
1146			 .ixfr_ratio = 100,
1147			 .requestexpire = true,
1148			 .updatemethod = dns_updatemethod_increment,
1149			 .magic = ZONE_MAGIC };
1150
1151	REQUIRE(zonep != NULL && *zonep == NULL);
1152	REQUIRE(mctx != NULL);
1153
1154	TIME_NOW(&now);
1155	zone = isc_mem_get(mctx, sizeof(*zone));
1156	*zone = z;
1157
1158	zone->mctx = NULL;
1159	isc_mem_attach(mctx, &zone->mctx);
1160	isc_mutex_init(&zone->lock);
1161	ZONEDB_INITLOCK(&zone->dblock);
1162	/* XXX MPA check that all elements are initialised */
1163#ifdef DNS_ZONE_CHECKLOCK
1164	zone->locked = false;
1165#endif /* ifdef DNS_ZONE_CHECKLOCK */
1166
1167	zone->notifytime = now;
1168
1169	ISC_LINK_INIT(zone, link);
1170	isc_refcount_init(&zone->erefs, 1);
1171	isc_refcount_init(&zone->irefs, 0);
1172	dns_name_init(&zone->origin, NULL);
1173	ISC_LIST_INIT(zone->includes);
1174	ISC_LIST_INIT(zone->newincludes);
1175	atomic_init(&zone->flags, 0);
1176	atomic_init(&zone->options, 0);
1177	atomic_init(&zone->keyopts, 0);
1178	isc_time_settoepoch(&zone->expiretime);
1179	isc_time_settoepoch(&zone->refreshtime);
1180	isc_time_settoepoch(&zone->dumptime);
1181	isc_time_settoepoch(&zone->loadtime);
1182	isc_time_settoepoch(&zone->resigntime);
1183	isc_time_settoepoch(&zone->keywarntime);
1184	isc_time_settoepoch(&zone->signingtime);
1185	isc_time_settoepoch(&zone->nsec3chaintime);
1186	isc_time_settoepoch(&zone->refreshkeytime);
1187	ISC_LIST_INIT(zone->notifies);
1188	ISC_LIST_INIT(zone->checkds_requests);
1189	isc_sockaddr_any(&zone->notifysrc4);
1190	isc_sockaddr_any6(&zone->notifysrc6);
1191	isc_sockaddr_any(&zone->parentalsrc4);
1192	isc_sockaddr_any6(&zone->parentalsrc6);
1193	isc_sockaddr_any(&zone->xfrsource4);
1194	isc_sockaddr_any6(&zone->xfrsource6);
1195	isc_sockaddr_any(&zone->altxfrsource4);
1196	isc_sockaddr_any6(&zone->altxfrsource6);
1197	ISC_LINK_INIT(zone, statelink);
1198	ISC_LIST_INIT(zone->signing);
1199	ISC_LIST_INIT(zone->nsec3chain);
1200	ISC_LIST_INIT(zone->setnsec3param_queue);
1201	ISC_LIST_INIT(zone->forwards);
1202	ISC_LIST_INIT(zone->rss_events);
1203	ISC_LIST_INIT(zone->rss_post);
1204
1205	result = isc_stats_create(mctx, &zone->gluecachestats,
1206				  dns_gluecachestatscounter_max);
1207	if (result != ISC_R_SUCCESS) {
1208		goto free_refs;
1209	}
1210
1211	/* Must be after magic is set. */
1212	dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1213
1214	ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1215		       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone, NULL,
1216		       NULL);
1217	*zonep = zone;
1218	return (ISC_R_SUCCESS);
1219
1220free_refs:
1221	isc_refcount_decrement0(&zone->erefs);
1222	isc_refcount_destroy(&zone->erefs);
1223	isc_refcount_destroy(&zone->irefs);
1224	ZONEDB_DESTROYLOCK(&zone->dblock);
1225	isc_mutex_destroy(&zone->lock);
1226	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1227	return (result);
1228}
1229
1230static void
1231clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
1232	dns_dnsseckey_t *key;
1233	while (!ISC_LIST_EMPTY(*list)) {
1234		key = ISC_LIST_HEAD(*list);
1235		ISC_LIST_UNLINK(*list, key, link);
1236		dns_dnsseckey_destroy(mctx, &key);
1237	}
1238}
1239
1240/*
1241 * Free a zone.  Because we require that there be no more
1242 * outstanding events or references, no locking is necessary.
1243 */
1244static void
1245zone_free(dns_zone_t *zone) {
1246	dns_signing_t *signing;
1247	dns_nsec3chain_t *nsec3chain;
1248	isc_event_t *event;
1249	dns_include_t *include;
1250
1251	REQUIRE(DNS_ZONE_VALID(zone));
1252	isc_refcount_destroy(&zone->erefs);
1253	isc_refcount_destroy(&zone->irefs);
1254	REQUIRE(!LOCKED_ZONE(zone));
1255	REQUIRE(zone->timer == NULL);
1256	REQUIRE(zone->zmgr == NULL);
1257
1258	/*
1259	 * Managed objects.  Order is important.
1260	 */
1261	if (zone->request != NULL) {
1262		dns_request_destroy(&zone->request); /* XXXMPA */
1263	}
1264	INSIST(zone->readio == NULL);
1265	INSIST(zone->statelist == NULL);
1266	INSIST(zone->writeio == NULL);
1267	INSIST(zone->view == NULL);
1268	INSIST(zone->prev_view == NULL);
1269
1270	if (zone->task != NULL) {
1271		isc_task_detach(&zone->task);
1272	}
1273	if (zone->loadtask != NULL) {
1274		isc_task_detach(&zone->loadtask);
1275	}
1276
1277	/* Unmanaged objects */
1278	while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
1279		event = ISC_LIST_HEAD(zone->setnsec3param_queue);
1280		ISC_LIST_UNLINK(zone->setnsec3param_queue, event, ev_link);
1281		isc_event_free(&event);
1282	}
1283	while (!ISC_LIST_EMPTY(zone->rss_post)) {
1284		event = ISC_LIST_HEAD(zone->rss_post);
1285		ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
1286		isc_event_free(&event);
1287	}
1288	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
1289	     signing = ISC_LIST_HEAD(zone->signing))
1290	{
1291		ISC_LIST_UNLINK(zone->signing, signing, link);
1292		dns_db_detach(&signing->db);
1293		dns_dbiterator_destroy(&signing->dbiterator);
1294		isc_mem_put(zone->mctx, signing, sizeof *signing);
1295	}
1296	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
1297	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
1298	{
1299		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1300		dns_db_detach(&nsec3chain->db);
1301		dns_dbiterator_destroy(&nsec3chain->dbiterator);
1302		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1303	}
1304	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1305	     include = ISC_LIST_HEAD(zone->includes))
1306	{
1307		ISC_LIST_UNLINK(zone->includes, include, link);
1308		isc_mem_free(zone->mctx, include->name);
1309		isc_mem_put(zone->mctx, include, sizeof *include);
1310	}
1311	for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
1312	     include = ISC_LIST_HEAD(zone->newincludes))
1313	{
1314		ISC_LIST_UNLINK(zone->newincludes, include, link);
1315		isc_mem_free(zone->mctx, include->name);
1316		isc_mem_put(zone->mctx, include, sizeof *include);
1317	}
1318	if (zone->masterfile != NULL) {
1319		isc_mem_free(zone->mctx, zone->masterfile);
1320	}
1321	zone->masterfile = NULL;
1322	if (zone->keydirectory != NULL) {
1323		isc_mem_free(zone->mctx, zone->keydirectory);
1324	}
1325	zone->keydirectory = NULL;
1326	if (zone->kasp != NULL) {
1327		dns_kasp_detach(&zone->kasp);
1328	}
1329	if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
1330		clear_keylist(&zone->checkds_ok, zone->mctx);
1331	}
1332
1333	zone->journalsize = -1;
1334	if (zone->journal != NULL) {
1335		isc_mem_free(zone->mctx, zone->journal);
1336	}
1337	zone->journal = NULL;
1338	if (zone->stats != NULL) {
1339		isc_stats_detach(&zone->stats);
1340	}
1341	if (zone->requeststats != NULL) {
1342		isc_stats_detach(&zone->requeststats);
1343	}
1344	if (zone->rcvquerystats != NULL) {
1345		dns_stats_detach(&zone->rcvquerystats);
1346	}
1347	if (zone->dnssecsignstats != NULL) {
1348		dns_stats_detach(&zone->dnssecsignstats);
1349	}
1350	if (zone->db != NULL) {
1351		zone_detachdb(zone);
1352	}
1353	if (zone->rpzs != NULL) {
1354		REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1355		dns_rpz_detach_rpzs(&zone->rpzs);
1356		zone->rpz_num = DNS_RPZ_INVALID_NUM;
1357	}
1358	if (zone->catzs != NULL) {
1359		dns_catz_detach_catzs(&zone->catzs);
1360	}
1361	zone_freedbargs(zone);
1362	dns_zone_setparentals(zone, NULL, NULL, NULL, 0);
1363	dns_zone_setprimaries(zone, NULL, NULL, NULL, 0);
1364	dns_zone_setalsonotify(zone, NULL, NULL, NULL, 0);
1365
1366	zone->check_names = dns_severity_ignore;
1367	if (zone->update_acl != NULL) {
1368		dns_acl_detach(&zone->update_acl);
1369	}
1370	if (zone->forward_acl != NULL) {
1371		dns_acl_detach(&zone->forward_acl);
1372	}
1373	if (zone->notify_acl != NULL) {
1374		dns_acl_detach(&zone->notify_acl);
1375	}
1376	if (zone->query_acl != NULL) {
1377		dns_acl_detach(&zone->query_acl);
1378	}
1379	if (zone->queryon_acl != NULL) {
1380		dns_acl_detach(&zone->queryon_acl);
1381	}
1382	if (zone->xfr_acl != NULL) {
1383		dns_acl_detach(&zone->xfr_acl);
1384	}
1385	if (dns_name_dynamic(&zone->origin)) {
1386		dns_name_free(&zone->origin, zone->mctx);
1387	}
1388	if (zone->strnamerd != NULL) {
1389		isc_mem_free(zone->mctx, zone->strnamerd);
1390	}
1391	if (zone->strname != NULL) {
1392		isc_mem_free(zone->mctx, zone->strname);
1393	}
1394	if (zone->strrdclass != NULL) {
1395		isc_mem_free(zone->mctx, zone->strrdclass);
1396	}
1397	if (zone->strviewname != NULL) {
1398		isc_mem_free(zone->mctx, zone->strviewname);
1399	}
1400	if (zone->ssutable != NULL) {
1401		dns_ssutable_detach(&zone->ssutable);
1402	}
1403	if (zone->gluecachestats != NULL) {
1404		isc_stats_detach(&zone->gluecachestats);
1405	}
1406
1407	/* last stuff */
1408	ZONEDB_DESTROYLOCK(&zone->dblock);
1409	isc_mutex_destroy(&zone->lock);
1410	zone->magic = 0;
1411	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1412}
1413
1414/*
1415 * Returns true iff this the signed side of an inline-signing zone.
1416 * Caller should hold zone lock.
1417 */
1418static bool
1419inline_secure(dns_zone_t *zone) {
1420	REQUIRE(DNS_ZONE_VALID(zone));
1421	if (zone->raw != NULL) {
1422		return (true);
1423	}
1424	return (false);
1425}
1426
1427/*
1428 * Returns true iff this the unsigned side of an inline-signing zone
1429 * Caller should hold zone lock.
1430 */
1431static bool
1432inline_raw(dns_zone_t *zone) {
1433	REQUIRE(DNS_ZONE_VALID(zone));
1434	if (zone->secure != NULL) {
1435		return (true);
1436	}
1437	return (false);
1438}
1439
1440/*
1441 *	Single shot.
1442 */
1443void
1444dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1445	char namebuf[1024];
1446
1447	REQUIRE(DNS_ZONE_VALID(zone));
1448	REQUIRE(rdclass != dns_rdataclass_none);
1449
1450	/*
1451	 * Test and set.
1452	 */
1453	LOCK_ZONE(zone);
1454	INSIST(zone != zone->raw);
1455	REQUIRE(zone->rdclass == dns_rdataclass_none ||
1456		zone->rdclass == rdclass);
1457	zone->rdclass = rdclass;
1458
1459	if (zone->strnamerd != NULL) {
1460		isc_mem_free(zone->mctx, zone->strnamerd);
1461	}
1462	if (zone->strrdclass != NULL) {
1463		isc_mem_free(zone->mctx, zone->strrdclass);
1464	}
1465
1466	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1467	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1468	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1469	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1470
1471	if (inline_secure(zone)) {
1472		dns_zone_setclass(zone->raw, rdclass);
1473	}
1474	UNLOCK_ZONE(zone);
1475}
1476
1477dns_rdataclass_t
1478dns_zone_getclass(dns_zone_t *zone) {
1479	REQUIRE(DNS_ZONE_VALID(zone));
1480
1481	return (zone->rdclass);
1482}
1483
1484void
1485dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1486	REQUIRE(DNS_ZONE_VALID(zone));
1487
1488	LOCK_ZONE(zone);
1489	zone->notifytype = notifytype;
1490	UNLOCK_ZONE(zone);
1491}
1492
1493isc_result_t
1494dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1495	isc_result_t result;
1496	unsigned int soacount;
1497
1498	REQUIRE(DNS_ZONE_VALID(zone));
1499	REQUIRE(serialp != NULL);
1500
1501	LOCK_ZONE(zone);
1502	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1503	if (zone->db != NULL) {
1504		result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
1505					  serialp, NULL, NULL, NULL, NULL,
1506					  NULL);
1507		if (result == ISC_R_SUCCESS && soacount == 0) {
1508			result = ISC_R_FAILURE;
1509		}
1510	} else {
1511		result = DNS_R_NOTLOADED;
1512	}
1513	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1514	UNLOCK_ZONE(zone);
1515
1516	return (result);
1517}
1518
1519/*
1520 *	Single shot.
1521 */
1522void
1523dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1524	char namebuf[1024];
1525
1526	REQUIRE(DNS_ZONE_VALID(zone));
1527	REQUIRE(type != dns_zone_none);
1528
1529	/*
1530	 * Test and set.
1531	 */
1532	LOCK_ZONE(zone);
1533	REQUIRE(zone->type == dns_zone_none || zone->type == type);
1534	zone->type = type;
1535
1536	if (zone->strnamerd != NULL) {
1537		isc_mem_free(zone->mctx, zone->strnamerd);
1538	}
1539
1540	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1541	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1542	UNLOCK_ZONE(zone);
1543}
1544
1545static void
1546zone_freedbargs(dns_zone_t *zone) {
1547	unsigned int i;
1548
1549	/* Free the old database argument list. */
1550	if (zone->db_argv != NULL) {
1551		for (i = 0; i < zone->db_argc; i++) {
1552			isc_mem_free(zone->mctx, zone->db_argv[i]);
1553		}
1554		isc_mem_put(zone->mctx, zone->db_argv,
1555			    zone->db_argc * sizeof(*zone->db_argv));
1556	}
1557	zone->db_argc = 0;
1558	zone->db_argv = NULL;
1559}
1560
1561isc_result_t
1562dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1563	size_t size = 0;
1564	unsigned int i;
1565	isc_result_t result = ISC_R_SUCCESS;
1566	void *mem;
1567	char **tmp, *tmp2, *base;
1568
1569	REQUIRE(DNS_ZONE_VALID(zone));
1570	REQUIRE(argv != NULL && *argv == NULL);
1571
1572	LOCK_ZONE(zone);
1573	size = (zone->db_argc + 1) * sizeof(char *);
1574	for (i = 0; i < zone->db_argc; i++) {
1575		size += strlen(zone->db_argv[i]) + 1;
1576	}
1577	mem = isc_mem_allocate(mctx, size);
1578	{
1579		tmp = mem;
1580		tmp2 = mem;
1581		base = mem;
1582		tmp2 += (zone->db_argc + 1) * sizeof(char *);
1583		for (i = 0; i < zone->db_argc; i++) {
1584			*tmp++ = tmp2;
1585			strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1586			tmp2 += strlen(tmp2) + 1;
1587		}
1588		*tmp = NULL;
1589	}
1590	UNLOCK_ZONE(zone);
1591	*argv = mem;
1592	return (result);
1593}
1594
1595void
1596dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
1597		   const char *const *dbargv) {
1598	char **argv = NULL;
1599	unsigned int i;
1600
1601	REQUIRE(DNS_ZONE_VALID(zone));
1602	REQUIRE(dbargc >= 1);
1603	REQUIRE(dbargv != NULL);
1604
1605	LOCK_ZONE(zone);
1606
1607	/* Set up a new database argument list. */
1608	argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1609	for (i = 0; i < dbargc; i++) {
1610		argv[i] = NULL;
1611	}
1612	for (i = 0; i < dbargc; i++) {
1613		argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1614	}
1615
1616	/* Free the old list. */
1617	zone_freedbargs(zone);
1618
1619	zone->db_argc = dbargc;
1620	zone->db_argv = argv;
1621
1622	UNLOCK_ZONE(zone);
1623}
1624
1625static void
1626dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1627	char namebuf[1024];
1628
1629	if (zone->prev_view == NULL && zone->view != NULL) {
1630		dns_view_weakattach(zone->view, &zone->prev_view);
1631	}
1632
1633	INSIST(zone != zone->raw);
1634	if (zone->view != NULL) {
1635		dns_view_sfd_del(zone->view, &zone->origin);
1636		dns_view_weakdetach(&zone->view);
1637	}
1638	dns_view_weakattach(view, &zone->view);
1639	dns_view_sfd_add(view, &zone->origin);
1640
1641	if (zone->strviewname != NULL) {
1642		isc_mem_free(zone->mctx, zone->strviewname);
1643	}
1644	if (zone->strnamerd != NULL) {
1645		isc_mem_free(zone->mctx, zone->strnamerd);
1646	}
1647
1648	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1649	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1650	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1651	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1652
1653	if (inline_secure(zone)) {
1654		dns_zone_setview(zone->raw, view);
1655	}
1656}
1657
1658void
1659dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1660	REQUIRE(DNS_ZONE_VALID(zone));
1661
1662	LOCK_ZONE(zone);
1663	dns_zone_setview_helper(zone, view);
1664	UNLOCK_ZONE(zone);
1665}
1666
1667dns_view_t *
1668dns_zone_getview(dns_zone_t *zone) {
1669	REQUIRE(DNS_ZONE_VALID(zone));
1670
1671	return (zone->view);
1672}
1673
1674void
1675dns_zone_setviewcommit(dns_zone_t *zone) {
1676	REQUIRE(DNS_ZONE_VALID(zone));
1677
1678	LOCK_ZONE(zone);
1679	if (zone->prev_view != NULL) {
1680		dns_view_weakdetach(&zone->prev_view);
1681	}
1682	if (inline_secure(zone)) {
1683		dns_zone_setviewcommit(zone->raw);
1684	}
1685	UNLOCK_ZONE(zone);
1686}
1687
1688void
1689dns_zone_setviewrevert(dns_zone_t *zone) {
1690	REQUIRE(DNS_ZONE_VALID(zone));
1691
1692	LOCK_ZONE(zone);
1693	if (zone->prev_view != NULL) {
1694		dns_zone_setview_helper(zone, zone->prev_view);
1695		dns_view_weakdetach(&zone->prev_view);
1696	}
1697	if (zone->catzs != NULL) {
1698		zone_catz_enable(zone, zone->catzs);
1699	}
1700	if (inline_secure(zone)) {
1701		dns_zone_setviewrevert(zone->raw);
1702	}
1703	UNLOCK_ZONE(zone);
1704}
1705
1706isc_result_t
1707dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1708	isc_result_t result = ISC_R_SUCCESS;
1709	char namebuf[1024];
1710
1711	REQUIRE(DNS_ZONE_VALID(zone));
1712	REQUIRE(origin != NULL);
1713
1714	LOCK_ZONE(zone);
1715	INSIST(zone != zone->raw);
1716	if (dns_name_dynamic(&zone->origin)) {
1717		dns_name_free(&zone->origin, zone->mctx);
1718		dns_name_init(&zone->origin, NULL);
1719	}
1720	dns_name_dup(origin, zone->mctx, &zone->origin);
1721
1722	if (zone->strnamerd != NULL) {
1723		isc_mem_free(zone->mctx, zone->strnamerd);
1724	}
1725	if (zone->strname != NULL) {
1726		isc_mem_free(zone->mctx, zone->strname);
1727	}
1728
1729	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1730	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1731	zone_name_tostr(zone, namebuf, sizeof namebuf);
1732	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1733
1734	if (inline_secure(zone)) {
1735		result = dns_zone_setorigin(zone->raw, origin);
1736	}
1737	UNLOCK_ZONE(zone);
1738	return (result);
1739}
1740
1741static isc_result_t
1742dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1743	char *copy;
1744
1745	if (value != NULL) {
1746		copy = isc_mem_strdup(zone->mctx, value);
1747	} else {
1748		copy = NULL;
1749	}
1750
1751	if (*field != NULL) {
1752		isc_mem_free(zone->mctx, *field);
1753	}
1754
1755	*field = copy;
1756	return (ISC_R_SUCCESS);
1757}
1758
1759isc_result_t
1760dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
1761		 const dns_master_style_t *style) {
1762	isc_result_t result = ISC_R_SUCCESS;
1763
1764	REQUIRE(DNS_ZONE_VALID(zone));
1765	REQUIRE(zone->stream == NULL);
1766
1767	LOCK_ZONE(zone);
1768	result = dns_zone_setstring(zone, &zone->masterfile, file);
1769	if (result == ISC_R_SUCCESS) {
1770		zone->masterformat = format;
1771		if (format == dns_masterformat_text) {
1772			zone->masterstyle = style;
1773		}
1774		result = default_journal(zone);
1775	}
1776	UNLOCK_ZONE(zone);
1777
1778	return (result);
1779}
1780
1781const char *
1782dns_zone_getfile(dns_zone_t *zone) {
1783	REQUIRE(DNS_ZONE_VALID(zone));
1784
1785	return (zone->masterfile);
1786}
1787
1788isc_result_t
1789dns_zone_setstream(dns_zone_t *zone, const FILE *stream,
1790		   dns_masterformat_t format, const dns_master_style_t *style) {
1791	isc_result_t result = ISC_R_SUCCESS;
1792
1793	REQUIRE(DNS_ZONE_VALID(zone));
1794	REQUIRE(stream != NULL);
1795	REQUIRE(zone->masterfile == NULL);
1796
1797	LOCK_ZONE(zone);
1798	zone->stream = stream;
1799	zone->masterformat = format;
1800	if (format == dns_masterformat_text) {
1801		zone->masterstyle = style;
1802	}
1803	result = default_journal(zone);
1804	UNLOCK_ZONE(zone);
1805
1806	return (result);
1807}
1808
1809dns_ttl_t
1810dns_zone_getmaxttl(dns_zone_t *zone) {
1811	REQUIRE(DNS_ZONE_VALID(zone));
1812
1813	return (zone->maxttl);
1814}
1815
1816void
1817dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1818	REQUIRE(DNS_ZONE_VALID(zone));
1819
1820	LOCK_ZONE(zone);
1821	if (maxttl != 0) {
1822		DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
1823	} else {
1824		DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
1825	}
1826	zone->maxttl = maxttl;
1827	UNLOCK_ZONE(zone);
1828
1829	return;
1830}
1831
1832static isc_result_t
1833default_journal(dns_zone_t *zone) {
1834	isc_result_t result;
1835	char *journal;
1836
1837	REQUIRE(DNS_ZONE_VALID(zone));
1838	REQUIRE(LOCKED_ZONE(zone));
1839
1840	if (zone->masterfile != NULL) {
1841		/* Calculate string length including '\0'. */
1842		int len = strlen(zone->masterfile) + sizeof(".jnl");
1843		journal = isc_mem_allocate(zone->mctx, len);
1844		strlcpy(journal, zone->masterfile, len);
1845		strlcat(journal, ".jnl", len);
1846	} else {
1847		journal = NULL;
1848	}
1849	result = dns_zone_setstring(zone, &zone->journal, journal);
1850	if (journal != NULL) {
1851		isc_mem_free(zone->mctx, journal);
1852	}
1853	return (result);
1854}
1855
1856isc_result_t
1857dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1858	isc_result_t result = ISC_R_SUCCESS;
1859
1860	REQUIRE(DNS_ZONE_VALID(zone));
1861
1862	LOCK_ZONE(zone);
1863	result = dns_zone_setstring(zone, &zone->journal, myjournal);
1864	UNLOCK_ZONE(zone);
1865
1866	return (result);
1867}
1868
1869char *
1870dns_zone_getjournal(dns_zone_t *zone) {
1871	REQUIRE(DNS_ZONE_VALID(zone));
1872
1873	return (zone->journal);
1874}
1875
1876/*
1877 * Return true iff the zone is "dynamic", in the sense that the zone's
1878 * master file (if any) is written by the server, rather than being
1879 * updated manually and read by the server.
1880 *
1881 * This is true for secondary zones, mirror zones, stub zones, key zones,
1882 * and zones that allow dynamic updates either by having an update
1883 * policy ("ssutable") or an "allow-update" ACL with a value other than
1884 * exactly "{ none; }".
1885 */
1886bool
1887dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1888	REQUIRE(DNS_ZONE_VALID(zone));
1889
1890	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
1891	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1892	    (zone->type == dns_zone_redirect && zone->primaries != NULL))
1893	{
1894		return (true);
1895	}
1896
1897	/* Inline zones are always dynamic. */
1898	if (zone->type == dns_zone_primary && zone->raw != NULL) {
1899		return (true);
1900	}
1901
1902	/* If !ignore_freeze, we need check whether updates are disabled.  */
1903	if (zone->type == dns_zone_primary &&
1904	    (!zone->update_disabled || ignore_freeze) &&
1905	    ((zone->ssutable != NULL) ||
1906	     (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1907	{
1908		return (true);
1909	}
1910
1911	return (false);
1912}
1913
1914/*
1915 * Set the response policy index and information for a zone.
1916 */
1917isc_result_t
1918dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1919		    dns_rpz_num_t rpz_num) {
1920	/*
1921	 * Only RBTDB zones can be used for response policy zones,
1922	 * because only they have the code to create the summary data.
1923	 * Only zones that are loaded instead of mmap()ed create the
1924	 * summary data and so can be policy zones.
1925	 */
1926	if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1927	    strcmp(zone->db_argv[0], "rbt64") != 0)
1928	{
1929		return (ISC_R_NOTIMPLEMENTED);
1930	}
1931
1932	/*
1933	 * This must happen only once or be redundant.
1934	 */
1935	LOCK_ZONE(zone);
1936	if (zone->rpzs != NULL) {
1937		REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1938	} else {
1939		REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1940		dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1941		zone->rpz_num = rpz_num;
1942	}
1943	rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1944	UNLOCK_ZONE(zone);
1945
1946	return (ISC_R_SUCCESS);
1947}
1948
1949dns_rpz_num_t
1950dns_zone_get_rpz_num(dns_zone_t *zone) {
1951	return (zone->rpz_num);
1952}
1953
1954/*
1955 * If a zone is a response policy zone, mark its new database.
1956 */
1957void
1958dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1959	isc_result_t result;
1960	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1961		return;
1962	}
1963	REQUIRE(zone->rpzs != NULL);
1964	result = dns_db_updatenotify_register(db, dns_rpz_dbupdate_callback,
1965					      zone->rpzs->zones[zone->rpz_num]);
1966	REQUIRE(result == ISC_R_SUCCESS);
1967}
1968
1969static void
1970dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1971	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1972		return;
1973	}
1974	REQUIRE(zone->rpzs != NULL);
1975	(void)dns_db_updatenotify_unregister(db, dns_rpz_dbupdate_callback,
1976					     zone->rpzs->zones[zone->rpz_num]);
1977}
1978
1979/*
1980 * If a zone is a catalog zone, attach it to update notification in database.
1981 */
1982void
1983dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1984	REQUIRE(DNS_ZONE_VALID(zone));
1985	REQUIRE(db != NULL);
1986
1987	if (zone->catzs != NULL) {
1988		dns_catz_dbupdate_register(db, zone->catzs);
1989	}
1990}
1991
1992static void
1993dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1994	REQUIRE(DNS_ZONE_VALID(zone));
1995	REQUIRE(db != NULL);
1996
1997	if (zone->catzs != NULL) {
1998		dns_catz_dbupdate_unregister(db, zone->catzs);
1999	}
2000}
2001
2002static void
2003zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
2004	REQUIRE(DNS_ZONE_VALID(zone));
2005	REQUIRE(catzs != NULL);
2006
2007	INSIST(zone->catzs == NULL || zone->catzs == catzs);
2008	dns_catz_catzs_set_view(catzs, zone->view);
2009	if (zone->catzs == NULL) {
2010		dns_catz_attach_catzs(catzs, &zone->catzs);
2011	}
2012}
2013
2014void
2015dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
2016	REQUIRE(DNS_ZONE_VALID(zone));
2017
2018	LOCK_ZONE(zone);
2019	zone_catz_enable(zone, catzs);
2020	UNLOCK_ZONE(zone);
2021}
2022
2023static void
2024zone_catz_disable(dns_zone_t *zone) {
2025	REQUIRE(DNS_ZONE_VALID(zone));
2026
2027	if (zone->catzs != NULL) {
2028		if (zone->db != NULL) {
2029			dns_zone_catz_disable_db(zone, zone->db);
2030		}
2031		dns_catz_detach_catzs(&zone->catzs);
2032	}
2033}
2034
2035void
2036dns_zone_catz_disable(dns_zone_t *zone) {
2037	REQUIRE(DNS_ZONE_VALID(zone));
2038
2039	LOCK_ZONE(zone);
2040	zone_catz_disable(zone);
2041	UNLOCK_ZONE(zone);
2042}
2043
2044bool
2045dns_zone_catz_is_enabled(dns_zone_t *zone) {
2046	REQUIRE(DNS_ZONE_VALID(zone));
2047
2048	return (zone->catzs != NULL);
2049}
2050
2051/*
2052 * Set catalog zone ownership of the zone
2053 */
2054void
2055dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
2056	REQUIRE(DNS_ZONE_VALID(zone));
2057	REQUIRE(catz != NULL);
2058	LOCK_ZONE(zone);
2059	INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
2060	zone->parentcatz = catz;
2061	UNLOCK_ZONE(zone);
2062}
2063
2064dns_catz_zone_t *
2065dns_zone_get_parentcatz(const dns_zone_t *zone) {
2066	REQUIRE(DNS_ZONE_VALID(zone));
2067	return (zone->parentcatz);
2068}
2069
2070static bool
2071zone_touched(dns_zone_t *zone) {
2072	isc_result_t result;
2073	isc_time_t modtime;
2074	dns_include_t *include;
2075
2076	REQUIRE(DNS_ZONE_VALID(zone));
2077
2078	result = isc_file_getmodtime(zone->masterfile, &modtime);
2079	if (result != ISC_R_SUCCESS ||
2080	    isc_time_compare(&modtime, &zone->loadtime) > 0)
2081	{
2082		return (true);
2083	}
2084
2085	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
2086	     include = ISC_LIST_NEXT(include, link))
2087	{
2088		result = isc_file_getmodtime(include->name, &modtime);
2089		if (result != ISC_R_SUCCESS ||
2090		    isc_time_compare(&modtime, &include->filetime) > 0)
2091		{
2092			return (true);
2093		}
2094	}
2095
2096	return (false);
2097}
2098
2099/*
2100 * Note: when dealing with inline-signed zones, external callers will always
2101 * call zone_load() for the secure zone; zone_load() calls itself recursively
2102 * in order to load the raw zone.
2103 */
2104static isc_result_t
2105zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
2106	isc_result_t result;
2107	isc_time_t now;
2108	isc_time_t loadtime;
2109	dns_db_t *db = NULL;
2110	bool rbt, hasraw, is_dynamic;
2111
2112	REQUIRE(DNS_ZONE_VALID(zone));
2113
2114	if (!locked) {
2115		LOCK_ZONE(zone);
2116	}
2117
2118	INSIST(zone != zone->raw);
2119	hasraw = inline_secure(zone);
2120	if (hasraw) {
2121		/*
2122		 * We are trying to load an inline-signed zone.  First call
2123		 * self recursively to try loading the raw version of the zone.
2124		 * Assuming the raw zone file is readable, there are two
2125		 * possibilities:
2126		 *
2127		 *  a) the raw zone was not yet loaded and thus it will be
2128		 *     loaded now, synchronously; if this succeeds, a
2129		 *     subsequent attempt to load the signed zone file will
2130		 *     take place and thus zone_postload() will be called
2131		 *     twice: first for the raw zone and then for the secure
2132		 *     zone; the latter call will take care of syncing the raw
2133		 *     version with the secure version,
2134		 *
2135		 *  b) the raw zone was already loaded and we are trying to
2136		 *     reload it, which will happen asynchronously; this means
2137		 *     zone_postload() will only be called for the raw zone
2138		 *     because "result" returned by the zone_load() call below
2139		 *     will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
2140		 *     zone_postload() called for the raw zone will take care
2141		 *     of syncing the raw version with the secure version.
2142		 */
2143		result = zone_load(zone->raw, flags, false);
2144		if (result != ISC_R_SUCCESS) {
2145			if (!locked) {
2146				UNLOCK_ZONE(zone);
2147			}
2148			return (result);
2149		}
2150		LOCK_ZONE(zone->raw);
2151	}
2152
2153	TIME_NOW(&now);
2154
2155	INSIST(zone->type != dns_zone_none);
2156
2157	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
2158		if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2159			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2160		}
2161		result = DNS_R_CONTINUE;
2162		goto cleanup;
2163	}
2164
2165	INSIST(zone->db_argc >= 1);
2166
2167	rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
2168	      strcmp(zone->db_argv[0], "rbt64") == 0;
2169
2170	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
2171		/*
2172		 * The zone has no master file configured.
2173		 */
2174		result = ISC_R_SUCCESS;
2175		goto cleanup;
2176	}
2177
2178	is_dynamic = dns_zone_isdynamic(zone, false);
2179	if (zone->db != NULL && is_dynamic) {
2180		/*
2181		 * This is a secondary, stub, or dynamically updated zone
2182		 * being reloaded.  Do nothing - the database we already
2183		 * have is guaranteed to be up-to-date.
2184		 */
2185		if (zone->type == dns_zone_primary && !hasraw) {
2186			result = DNS_R_DYNAMIC;
2187		} else {
2188			result = ISC_R_SUCCESS;
2189		}
2190		goto cleanup;
2191	}
2192
2193	/*
2194	 * Store the current time before the zone is loaded, so that if the
2195	 * file changes between the time of the load and the time that
2196	 * zone->loadtime is set, then the file will still be reloaded
2197	 * the next time dns_zone_load is called.
2198	 */
2199	TIME_NOW(&loadtime);
2200
2201	/*
2202	 * Don't do the load if the file that stores the zone is older
2203	 * than the last time the zone was loaded.  If the zone has not
2204	 * been loaded yet, zone->loadtime will be the epoch.
2205	 */
2206	if (zone->masterfile != NULL) {
2207		isc_time_t filetime;
2208
2209		/*
2210		 * The file is already loaded.	If we are just doing a
2211		 * "rndc reconfig", we are done.
2212		 */
2213		if (!isc_time_isepoch(&zone->loadtime) &&
2214		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
2215		{
2216			result = ISC_R_SUCCESS;
2217			goto cleanup;
2218		}
2219
2220		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2221		    !zone_touched(zone))
2222		{
2223			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2224				      ISC_LOG_DEBUG(1),
2225				      "skipping load: master file "
2226				      "older than last load");
2227			result = DNS_R_UPTODATE;
2228			goto cleanup;
2229		}
2230
2231		/*
2232		 * If the file modification time is in the past
2233		 * set loadtime to that value.
2234		 */
2235		result = isc_file_getmodtime(zone->masterfile, &filetime);
2236		if (result == ISC_R_SUCCESS &&
2237		    isc_time_compare(&loadtime, &filetime) > 0)
2238		{
2239			loadtime = filetime;
2240		}
2241	}
2242
2243	/*
2244	 * Built in zones (with the exception of empty zones) don't need
2245	 * to be reloaded.
2246	 */
2247	if (zone->type == dns_zone_primary &&
2248	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
2249	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2250	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2251	{
2252		result = ISC_R_SUCCESS;
2253		goto cleanup;
2254	}
2255
2256	/*
2257	 * Zones associated with a DLZ don't need to be loaded either,
2258	 * but we need to associate the database with the zone object.
2259	 */
2260	if (strcmp(zone->db_argv[0], "dlz") == 0) {
2261		dns_dlzdb_t *dlzdb;
2262		dns_dlzfindzone_t findzone;
2263
2264		for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2265		     dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
2266		{
2267			INSIST(DNS_DLZ_VALID(dlzdb));
2268			if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
2269				break;
2270			}
2271		}
2272
2273		if (dlzdb == NULL) {
2274			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2275				      ISC_LOG_ERROR,
2276				      "DLZ %s does not exist or is set "
2277				      "to 'search yes;'",
2278				      zone->db_argv[1]);
2279			result = ISC_R_NOTFOUND;
2280			goto cleanup;
2281		}
2282
2283		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2284		/* ask SDLZ driver if the zone is supported */
2285		findzone = dlzdb->implementation->methods->findzone;
2286		result = (*findzone)(dlzdb->implementation->driverarg,
2287				     dlzdb->dbdata, dlzdb->mctx,
2288				     zone->view->rdclass, &zone->origin, NULL,
2289				     NULL, &db);
2290		if (result != ISC_R_NOTFOUND) {
2291			if (zone->db != NULL) {
2292				zone_detachdb(zone);
2293			}
2294			zone_attachdb(zone, db);
2295			dns_db_detach(&db);
2296			result = ISC_R_SUCCESS;
2297		}
2298		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2299
2300		if (result == ISC_R_SUCCESS) {
2301			if (dlzdb->configure_callback == NULL) {
2302				goto cleanup;
2303			}
2304
2305			result = (*dlzdb->configure_callback)(zone->view, dlzdb,
2306							      zone);
2307			if (result != ISC_R_SUCCESS) {
2308				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2309					      ISC_LOG_ERROR,
2310					      "DLZ configuration callback: %s",
2311					      isc_result_totext(result));
2312			}
2313		}
2314		goto cleanup;
2315	}
2316
2317	if ((zone->type == dns_zone_secondary ||
2318	     zone->type == dns_zone_mirror || zone->type == dns_zone_stub ||
2319	     (zone->type == dns_zone_redirect && zone->primaries != NULL)) &&
2320	    rbt)
2321	{
2322		if (zone->stream == NULL &&
2323		    (zone->masterfile == NULL ||
2324		     !isc_file_exists(zone->masterfile)))
2325		{
2326			if (zone->masterfile != NULL) {
2327				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2328					      ISC_LOG_DEBUG(1),
2329					      "no master file");
2330			}
2331			zone->refreshtime = now;
2332			if (zone->task != NULL) {
2333				zone_settimer(zone, &now);
2334			}
2335			result = ISC_R_SUCCESS;
2336			goto cleanup;
2337		}
2338	}
2339
2340	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
2341		      "starting load");
2342
2343	result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
2344			       (zone->type == dns_zone_stub) ? dns_dbtype_stub
2345							     : dns_dbtype_zone,
2346			       zone->rdclass, zone->db_argc - 1,
2347			       zone->db_argv + 1, &db);
2348
2349	if (result != ISC_R_SUCCESS) {
2350		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2351			      "loading zone: creating database: %s",
2352			      isc_result_totext(result));
2353		goto cleanup;
2354	}
2355	dns_db_settask(db, zone->task);
2356
2357	if (zone->type == dns_zone_primary ||
2358	    zone->type == dns_zone_secondary || zone->type == dns_zone_mirror)
2359	{
2360		result = dns_db_setgluecachestats(db, zone->gluecachestats);
2361		if (result == ISC_R_NOTIMPLEMENTED) {
2362			result = ISC_R_SUCCESS;
2363		}
2364		if (result != ISC_R_SUCCESS) {
2365			goto cleanup;
2366		}
2367	}
2368
2369	if (!dns_db_ispersistent(db)) {
2370		if (zone->masterfile != NULL || zone->stream != NULL) {
2371			result = zone_startload(db, zone, loadtime);
2372		} else {
2373			result = DNS_R_NOMASTERFILE;
2374			if (zone->type == dns_zone_primary ||
2375			    (zone->type == dns_zone_redirect &&
2376			     zone->primaries == NULL))
2377			{
2378				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2379					      ISC_LOG_ERROR,
2380					      "loading zone: "
2381					      "no master file configured");
2382				goto cleanup;
2383			}
2384			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2385				      ISC_LOG_INFO,
2386				      "loading zone: "
2387				      "no master file configured: continuing");
2388		}
2389	}
2390
2391	if (result == DNS_R_CONTINUE) {
2392		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2393		if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2394			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2395		}
2396		goto cleanup;
2397	}
2398
2399	result = zone_postload(zone, db, loadtime, result);
2400
2401cleanup:
2402	if (hasraw) {
2403		UNLOCK_ZONE(zone->raw);
2404	}
2405	if (!locked) {
2406		UNLOCK_ZONE(zone);
2407	}
2408	if (db != NULL) {
2409		dns_db_detach(&db);
2410	}
2411	return (result);
2412}
2413
2414isc_result_t
2415dns_zone_load(dns_zone_t *zone, bool newonly) {
2416	return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2417}
2418
2419static void
2420zone_asyncload(isc_task_t *task, isc_event_t *event) {
2421	dns_asyncload_t *asl = event->ev_arg;
2422	dns_zone_t *zone = asl->zone;
2423	isc_result_t result;
2424
2425	UNUSED(task);
2426
2427	REQUIRE(DNS_ZONE_VALID(zone));
2428
2429	isc_event_free(&event);
2430
2431	LOCK_ZONE(zone);
2432	result = zone_load(zone, asl->flags, true);
2433	if (result != DNS_R_CONTINUE) {
2434		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2435	}
2436	UNLOCK_ZONE(zone);
2437
2438	/* Inform the zone table we've finished loading */
2439	if (asl->loaded != NULL) {
2440		(asl->loaded)(asl->loaded_arg, zone, task);
2441	}
2442
2443	/* Reduce the quantum */
2444	isc_task_setquantum(zone->loadtask, 1);
2445
2446	isc_mem_put(zone->mctx, asl, sizeof(*asl));
2447	dns_zone_idetach(&zone);
2448}
2449
2450isc_result_t
2451dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_zoneloaded_t done,
2452		   void *arg) {
2453	isc_event_t *e;
2454	dns_asyncload_t *asl = NULL;
2455
2456	REQUIRE(DNS_ZONE_VALID(zone));
2457
2458	if (zone->zmgr == NULL) {
2459		return (ISC_R_FAILURE);
2460	}
2461
2462	/* If we already have a load pending, stop now */
2463	LOCK_ZONE(zone);
2464	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2465		UNLOCK_ZONE(zone);
2466		return (ISC_R_ALREADYRUNNING);
2467	}
2468
2469	asl = isc_mem_get(zone->mctx, sizeof(*asl));
2470
2471	asl->zone = NULL;
2472	asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2473	asl->loaded = done;
2474	asl->loaded_arg = arg;
2475
2476	e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr, DNS_EVENT_ZONELOAD,
2477			       zone_asyncload, asl, sizeof(isc_event_t));
2478
2479	zone_iattach(zone, &asl->zone);
2480	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2481	isc_task_send(zone->loadtask, &e);
2482	UNLOCK_ZONE(zone);
2483
2484	return (ISC_R_SUCCESS);
2485}
2486
2487bool
2488dns__zone_loadpending(dns_zone_t *zone) {
2489	REQUIRE(DNS_ZONE_VALID(zone));
2490
2491	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2492}
2493
2494isc_result_t
2495dns_zone_loadandthaw(dns_zone_t *zone) {
2496	isc_result_t result;
2497
2498	if (inline_raw(zone)) {
2499		result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
2500	} else {
2501		/*
2502		 * When thawing a zone, we don't know what changes
2503		 * have been made. If we do DNSSEC maintenance on this
2504		 * zone, schedule a full sign for this zone.
2505		 */
2506		if (zone->type == dns_zone_primary &&
2507		    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
2508		{
2509			DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
2510		}
2511		result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2512	}
2513
2514	switch (result) {
2515	case DNS_R_CONTINUE:
2516		/* Deferred thaw. */
2517		break;
2518	case DNS_R_UPTODATE:
2519	case ISC_R_SUCCESS:
2520	case DNS_R_SEENINCLUDE:
2521		zone->update_disabled = false;
2522		break;
2523	case DNS_R_NOMASTERFILE:
2524		zone->update_disabled = false;
2525		break;
2526	default:
2527		/* Error, remain in disabled state. */
2528		break;
2529	}
2530	return (result);
2531}
2532
2533static unsigned int
2534get_primary_options(dns_zone_t *zone) {
2535	unsigned int options;
2536
2537	options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2538	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
2539	    (zone->type == dns_zone_redirect && zone->primaries == NULL))
2540	{
2541		options |= DNS_MASTER_SECONDARY;
2542	}
2543	if (zone->type == dns_zone_key) {
2544		options |= DNS_MASTER_KEY;
2545	}
2546	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2547		options |= DNS_MASTER_CHECKNS;
2548	}
2549	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2550		options |= DNS_MASTER_FATALNS;
2551	}
2552	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2553		options |= DNS_MASTER_CHECKNAMES;
2554	}
2555	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2556		options |= DNS_MASTER_CHECKNAMESFAIL;
2557	}
2558	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2559		options |= DNS_MASTER_CHECKMX;
2560	}
2561	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2562		options |= DNS_MASTER_CHECKMXFAIL;
2563	}
2564	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2565		options |= DNS_MASTER_CHECKWILDCARD;
2566	}
2567	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2568		options |= DNS_MASTER_CHECKTTL;
2569	}
2570
2571	return (options);
2572}
2573
2574static void
2575zone_registerinclude(const char *filename, void *arg) {
2576	isc_result_t result;
2577	dns_zone_t *zone = (dns_zone_t *)arg;
2578	dns_include_t *inc = NULL;
2579
2580	REQUIRE(DNS_ZONE_VALID(zone));
2581
2582	if (filename == NULL) {
2583		return;
2584	}
2585
2586	/*
2587	 * Suppress duplicates.
2588	 */
2589	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
2590	     inc = ISC_LIST_NEXT(inc, link))
2591	{
2592		if (strcmp(filename, inc->name) == 0) {
2593			return;
2594		}
2595	}
2596
2597	inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2598	inc->name = isc_mem_strdup(zone->mctx, filename);
2599	ISC_LINK_INIT(inc, link);
2600
2601	result = isc_file_getmodtime(filename, &inc->filetime);
2602	if (result != ISC_R_SUCCESS) {
2603		isc_time_settoepoch(&inc->filetime);
2604	}
2605
2606	ISC_LIST_APPEND(zone->newincludes, inc, link);
2607}
2608
2609static void
2610zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2611	dns_load_t *load = event->ev_arg;
2612	isc_result_t result = ISC_R_SUCCESS;
2613	unsigned int options;
2614
2615	REQUIRE(DNS_LOAD_VALID(load));
2616
2617	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2618		result = ISC_R_CANCELED;
2619	}
2620	isc_event_free(&event);
2621	if (result == ISC_R_CANCELED) {
2622		goto fail;
2623	}
2624
2625	options = get_primary_options(load->zone);
2626
2627	result = dns_master_loadfileinc(
2628		load->zone->masterfile, dns_db_origin(load->db),
2629		dns_db_origin(load->db), load->zone->rdclass, options, 0,
2630		&load->callbacks, task, zone_loaddone, load, &load->zone->lctx,
2631		zone_registerinclude, load->zone, load->zone->mctx,
2632		load->zone->masterformat, load->zone->maxttl);
2633	if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2634	    result != DNS_R_SEENINCLUDE)
2635	{
2636		goto fail;
2637	}
2638	return;
2639
2640fail:
2641	zone_loaddone(load, result);
2642}
2643
2644static void
2645get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2646	isc_result_t result;
2647	unsigned int soacount;
2648
2649	LOCK(&raw->lock);
2650	if (raw->db != NULL) {
2651		result = zone_get_from_db(raw, raw->db, NULL, &soacount, NULL,
2652					  &rawdata->sourceserial, NULL, NULL,
2653					  NULL, NULL, NULL);
2654		if (result == ISC_R_SUCCESS && soacount > 0U) {
2655			rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2656		}
2657	}
2658	UNLOCK(&raw->lock);
2659}
2660
2661static void
2662zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2663	const char me[] = "zone_gotwritehandle";
2664	dns_zone_t *zone = event->ev_arg;
2665	isc_result_t result = ISC_R_SUCCESS;
2666	dns_dbversion_t *version = NULL;
2667	dns_masterrawheader_t rawdata;
2668	dns_db_t *db = NULL;
2669
2670	REQUIRE(DNS_ZONE_VALID(zone));
2671	INSIST(task == zone->task);
2672	ENTER;
2673
2674	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2675		result = ISC_R_CANCELED;
2676	}
2677	isc_event_free(&event);
2678	if (result == ISC_R_CANCELED) {
2679		goto fail;
2680	}
2681
2682	LOCK_ZONE(zone);
2683	INSIST(zone != zone->raw);
2684	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2685	if (zone->db != NULL) {
2686		dns_db_attach(zone->db, &db);
2687	}
2688	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2689	if (db != NULL) {
2690		const dns_master_style_t *output_style;
2691		dns_db_currentversion(db, &version);
2692		dns_master_initrawheader(&rawdata);
2693		if (inline_secure(zone)) {
2694			get_raw_serial(zone->raw, &rawdata);
2695		}
2696		if (zone->type == dns_zone_key) {
2697			output_style = &dns_master_style_keyzone;
2698		} else if (zone->masterstyle != NULL) {
2699			output_style = zone->masterstyle;
2700		} else {
2701			output_style = &dns_master_style_default;
2702		}
2703		result = dns_master_dumpasync(
2704			zone->mctx, db, version, output_style, zone->masterfile,
2705			zone->task, dump_done, zone, &zone->dctx,
2706			zone->masterformat, &rawdata);
2707		dns_db_closeversion(db, &version, false);
2708	} else {
2709		result = ISC_R_CANCELED;
2710	}
2711	if (db != NULL) {
2712		dns_db_detach(&db);
2713	}
2714	UNLOCK_ZONE(zone);
2715	if (result != DNS_R_CONTINUE) {
2716		goto fail;
2717	}
2718	return;
2719
2720fail:
2721	dump_done(zone, result);
2722}
2723
2724/*
2725 * Save the raw serial number for inline-signing zones.
2726 * (XXX: Other information from the header will be used
2727 * for other purposes in the future, but for now this is
2728 * all we're interested in.)
2729 */
2730static void
2731zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2732	if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
2733		return;
2734	}
2735
2736	zone->sourceserial = header->sourceserial;
2737	zone->sourceserialset = true;
2738}
2739
2740void
2741dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2742	if (zone == NULL) {
2743		return;
2744	}
2745
2746	LOCK_ZONE(zone);
2747	zone_setrawdata(zone, header);
2748	UNLOCK_ZONE(zone);
2749}
2750
2751static isc_result_t
2752zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2753	const char me[] = "zone_startload";
2754	dns_load_t *load;
2755	isc_result_t result;
2756	isc_result_t tresult;
2757	unsigned int options;
2758
2759	ENTER;
2760
2761	dns_zone_rpz_enable_db(zone, db);
2762	dns_zone_catz_enable_db(zone, db);
2763
2764	options = get_primary_options(zone);
2765	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2766		options |= DNS_MASTER_MANYERRORS;
2767	}
2768
2769	if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2770		load = isc_mem_get(zone->mctx, sizeof(*load));
2771
2772		load->mctx = NULL;
2773		load->zone = NULL;
2774		load->db = NULL;
2775		load->loadtime = loadtime;
2776		load->magic = LOAD_MAGIC;
2777
2778		isc_mem_attach(zone->mctx, &load->mctx);
2779		zone_iattach(zone, &load->zone);
2780		dns_db_attach(db, &load->db);
2781		dns_rdatacallbacks_init(&load->callbacks);
2782		load->callbacks.rawdata = zone_setrawdata;
2783		zone_iattach(zone, &load->callbacks.zone);
2784		result = dns_db_beginload(db, &load->callbacks);
2785		if (result != ISC_R_SUCCESS) {
2786			goto cleanup;
2787		}
2788		result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
2789				       zone_gotreadhandle, load, &zone->readio);
2790		if (result != ISC_R_SUCCESS) {
2791			/*
2792			 * We can't report multiple errors so ignore
2793			 * the result of dns_db_endload().
2794			 */
2795			(void)dns_db_endload(load->db, &load->callbacks);
2796			goto cleanup;
2797		} else {
2798			result = DNS_R_CONTINUE;
2799		}
2800	} else {
2801		dns_rdatacallbacks_t callbacks;
2802
2803		dns_rdatacallbacks_init(&callbacks);
2804		callbacks.rawdata = zone_setrawdata;
2805		zone_iattach(zone, &callbacks.zone);
2806		result = dns_db_beginload(db, &callbacks);
2807		if (result != ISC_R_SUCCESS) {
2808			zone_idetach(&callbacks.zone);
2809			return (result);
2810		}
2811
2812		if (zone->stream != NULL) {
2813			FILE *stream = NULL;
2814			DE_CONST(zone->stream, stream);
2815			result = dns_master_loadstream(
2816				stream, &zone->origin, &zone->origin,
2817				zone->rdclass, options, &callbacks, zone->mctx);
2818		} else {
2819			result = dns_master_loadfile(
2820				zone->masterfile, &zone->origin, &zone->origin,
2821				zone->rdclass, options, 0, &callbacks,
2822				zone_registerinclude, zone, zone->mctx,
2823				zone->masterformat, zone->maxttl);
2824		}
2825
2826		tresult = dns_db_endload(db, &callbacks);
2827		if (result == ISC_R_SUCCESS) {
2828			result = tresult;
2829		}
2830		zone_idetach(&callbacks.zone);
2831	}
2832
2833	return (result);
2834
2835cleanup:
2836	load->magic = 0;
2837	dns_db_detach(&load->db);
2838	zone_idetach(&load->zone);
2839	zone_idetach(&load->callbacks.zone);
2840	isc_mem_detach(&load->mctx);
2841	isc_mem_put(zone->mctx, load, sizeof(*load));
2842	return (result);
2843}
2844
2845static bool
2846zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2847	      dns_name_t *owner) {
2848	isc_result_t result;
2849	char ownerbuf[DNS_NAME_FORMATSIZE];
2850	char namebuf[DNS_NAME_FORMATSIZE];
2851	char altbuf[DNS_NAME_FORMATSIZE];
2852	dns_fixedname_t fixed;
2853	dns_name_t *foundname;
2854	int level;
2855
2856	/*
2857	 * "." means the services does not exist.
2858	 */
2859	if (dns_name_equal(name, dns_rootname)) {
2860		return (true);
2861	}
2862
2863	/*
2864	 * Outside of zone.
2865	 */
2866	if (!dns_name_issubdomain(name, &zone->origin)) {
2867		if (zone->checkmx != NULL) {
2868			return ((zone->checkmx)(zone, name, owner));
2869		}
2870		return (true);
2871	}
2872
2873	if (zone->type == dns_zone_primary) {
2874		level = ISC_LOG_ERROR;
2875	} else {
2876		level = ISC_LOG_WARNING;
2877	}
2878
2879	foundname = dns_fixedname_initname(&fixed);
2880
2881	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2882			     foundname, NULL, NULL);
2883	if (result == ISC_R_SUCCESS) {
2884		return (true);
2885	}
2886
2887	if (result == DNS_R_NXRRSET) {
2888		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2889				     NULL, foundname, NULL, NULL);
2890		if (result == ISC_R_SUCCESS) {
2891			return (true);
2892		}
2893	}
2894
2895	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2896	dns_name_format(name, namebuf, sizeof namebuf);
2897	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2898	    result == DNS_R_EMPTYNAME)
2899	{
2900		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2901			level = ISC_LOG_WARNING;
2902		}
2903		dns_zone_log(zone, level,
2904			     "%s/MX '%s' has no address records (A or AAAA)",
2905			     ownerbuf, namebuf);
2906		return ((level == ISC_LOG_WARNING) ? true : false);
2907	}
2908
2909	if (result == DNS_R_CNAME) {
2910		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2911		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2912		{
2913			level = ISC_LOG_WARNING;
2914		}
2915		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2916			dns_zone_log(zone, level,
2917				     "%s/MX '%s' is a CNAME (illegal)",
2918				     ownerbuf, namebuf);
2919		}
2920		return ((level == ISC_LOG_WARNING) ? true : false);
2921	}
2922
2923	if (result == DNS_R_DNAME) {
2924		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2925		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2926		{
2927			level = ISC_LOG_WARNING;
2928		}
2929		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2930			dns_name_format(foundname, altbuf, sizeof altbuf);
2931			dns_zone_log(zone, level,
2932				     "%s/MX '%s' is below a DNAME"
2933				     " '%s' (illegal)",
2934				     ownerbuf, namebuf, altbuf);
2935		}
2936		return ((level == ISC_LOG_WARNING) ? true : false);
2937	}
2938
2939	if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
2940		return ((zone->checkmx)(zone, name, owner));
2941	}
2942
2943	return (true);
2944}
2945
2946static bool
2947zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2948	       dns_name_t *owner) {
2949	isc_result_t result;
2950	char ownerbuf[DNS_NAME_FORMATSIZE];
2951	char namebuf[DNS_NAME_FORMATSIZE];
2952	char altbuf[DNS_NAME_FORMATSIZE];
2953	dns_fixedname_t fixed;
2954	dns_name_t *foundname;
2955	int level;
2956
2957	/*
2958	 * "." means the services does not exist.
2959	 */
2960	if (dns_name_equal(name, dns_rootname)) {
2961		return (true);
2962	}
2963
2964	/*
2965	 * Outside of zone.
2966	 */
2967	if (!dns_name_issubdomain(name, &zone->origin)) {
2968		if (zone->checksrv != NULL) {
2969			return ((zone->checksrv)(zone, name, owner));
2970		}
2971		return (true);
2972	}
2973
2974	if (zone->type == dns_zone_primary) {
2975		level = ISC_LOG_ERROR;
2976	} else {
2977		level = ISC_LOG_WARNING;
2978	}
2979
2980	foundname = dns_fixedname_initname(&fixed);
2981
2982	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2983			     foundname, NULL, NULL);
2984	if (result == ISC_R_SUCCESS) {
2985		return (true);
2986	}
2987
2988	if (result == DNS_R_NXRRSET) {
2989		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2990				     NULL, foundname, NULL, NULL);
2991		if (result == ISC_R_SUCCESS) {
2992			return (true);
2993		}
2994	}
2995
2996	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2997	dns_name_format(name, namebuf, sizeof namebuf);
2998	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2999	    result == DNS_R_EMPTYNAME)
3000	{
3001		dns_zone_log(zone, level,
3002			     "%s/SRV '%s' has no address records (A or AAAA)",
3003			     ownerbuf, namebuf);
3004		/* XXX950 make fatal for 9.5.0. */
3005		return (true);
3006	}
3007
3008	if (result == DNS_R_CNAME) {
3009		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
3010		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
3011		{
3012			level = ISC_LOG_WARNING;
3013		}
3014		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
3015			dns_zone_log(zone, level,
3016				     "%s/SRV '%s' is a CNAME (illegal)",
3017				     ownerbuf, namebuf);
3018		}
3019		return ((level == ISC_LOG_WARNING) ? true : false);
3020	}
3021
3022	if (result == DNS_R_DNAME) {
3023		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
3024		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
3025		{
3026			level = ISC_LOG_WARNING;
3027		}
3028		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
3029			dns_name_format(foundname, altbuf, sizeof altbuf);
3030			dns_zone_log(zone, level,
3031				     "%s/SRV '%s' is below a "
3032				     "DNAME '%s' (illegal)",
3033				     ownerbuf, namebuf, altbuf);
3034		}
3035		return ((level == ISC_LOG_WARNING) ? true : false);
3036	}
3037
3038	if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
3039		return ((zone->checksrv)(zone, name, owner));
3040	}
3041
3042	return (true);
3043}
3044
3045static bool
3046zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
3047		dns_name_t *owner) {
3048	bool answer = true;
3049	isc_result_t result, tresult;
3050	char ownerbuf[DNS_NAME_FORMATSIZE];
3051	char namebuf[DNS_NAME_FORMATSIZE];
3052	char altbuf[DNS_NAME_FORMATSIZE];
3053	dns_fixedname_t fixed;
3054	dns_name_t *foundname;
3055	dns_rdataset_t a;
3056	dns_rdataset_t aaaa;
3057	int level;
3058
3059	/*
3060	 * Outside of zone.
3061	 */
3062	if (!dns_name_issubdomain(name, &zone->origin)) {
3063		if (zone->checkns != NULL) {
3064			return ((zone->checkns)(zone, name, owner, NULL, NULL));
3065		}
3066		return (true);
3067	}
3068
3069	if (zone->type == dns_zone_primary) {
3070		level = ISC_LOG_ERROR;
3071	} else {
3072		level = ISC_LOG_WARNING;
3073	}
3074
3075	foundname = dns_fixedname_initname(&fixed);
3076	dns_rdataset_init(&a);
3077	dns_rdataset_init(&aaaa);
3078
3079	/*
3080	 * Perform a regular lookup to catch DNAME records then look
3081	 * for glue.
3082	 */
3083	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
3084			     foundname, &a, NULL);
3085	switch (result) {
3086	case ISC_R_SUCCESS:
3087	case DNS_R_DNAME:
3088	case DNS_R_CNAME:
3089		break;
3090	default:
3091		if (dns_rdataset_isassociated(&a)) {
3092			dns_rdataset_disassociate(&a);
3093		}
3094		result = dns_db_find(db, name, NULL, dns_rdatatype_a,
3095				     DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
3096				     NULL);
3097	}
3098	if (result == ISC_R_SUCCESS) {
3099		dns_rdataset_disassociate(&a);
3100		return (true);
3101	} else if (result == DNS_R_DELEGATION) {
3102		dns_rdataset_disassociate(&a);
3103	}
3104
3105	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
3106	    result == DNS_R_GLUE)
3107	{
3108		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
3109				      DNS_DBFIND_GLUEOK, 0, NULL, foundname,
3110				      &aaaa, NULL);
3111		if (tresult == ISC_R_SUCCESS) {
3112			if (dns_rdataset_isassociated(&a)) {
3113				dns_rdataset_disassociate(&a);
3114			}
3115			dns_rdataset_disassociate(&aaaa);
3116			return (true);
3117		}
3118		if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
3119			dns_rdataset_disassociate(&aaaa);
3120		}
3121		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
3122			/*
3123			 * Check glue against child zone.
3124			 */
3125			if (zone->checkns != NULL) {
3126				answer = (zone->checkns)(zone, name, owner, &a,
3127							 &aaaa);
3128			}
3129			if (dns_rdataset_isassociated(&a)) {
3130				dns_rdataset_disassociate(&a);
3131			}
3132			if (dns_rdataset_isassociated(&aaaa)) {
3133				dns_rdataset_disassociate(&aaaa);
3134			}
3135			return (answer);
3136		}
3137	}
3138
3139	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
3140	dns_name_format(name, namebuf, sizeof namebuf);
3141	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3142	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
3143	{
3144		const char *what;
3145		bool required = false;
3146		if (dns_name_issubdomain(name, owner)) {
3147			what = "REQUIRED GLUE ";
3148			required = true;
3149		} else if (result == DNS_R_DELEGATION) {
3150			what = "SIBLING GLUE ";
3151		} else {
3152			what = "";
3153		}
3154
3155		if (result != DNS_R_DELEGATION || required ||
3156		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
3157		{
3158			dns_zone_log(zone, level,
3159				     "%s/NS '%s' has no %s"
3160				     "address records (A or AAAA)",
3161				     ownerbuf, namebuf, what);
3162			/*
3163			 * Log missing address record.
3164			 */
3165			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
3166			{
3167				(void)(zone->checkns)(zone, name, owner, &a,
3168						      &aaaa);
3169			}
3170			/* XXX950 make fatal for 9.5.0. */
3171			/* answer = false; */
3172		}
3173	} else if (result == DNS_R_CNAME) {
3174		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
3175			     ownerbuf, namebuf);
3176		/* XXX950 make fatal for 9.5.0. */
3177		/* answer = false; */
3178	} else if (result == DNS_R_DNAME) {
3179		dns_name_format(foundname, altbuf, sizeof altbuf);
3180		dns_zone_log(zone, level,
3181			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
3182			     ownerbuf, namebuf, altbuf);
3183		/* XXX950 make fatal for 9.5.0. */
3184		/* answer = false; */
3185	}
3186
3187	if (dns_rdataset_isassociated(&a)) {
3188		dns_rdataset_disassociate(&a);
3189	}
3190	if (dns_rdataset_isassociated(&aaaa)) {
3191		dns_rdataset_disassociate(&aaaa);
3192	}
3193	return (answer);
3194}
3195
3196static bool
3197zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
3198		     dns_rdataset_t *rdataset) {
3199	dns_rdataset_t tmprdataset;
3200	isc_result_t result;
3201	bool answer = true;
3202	bool format = true;
3203	int level = ISC_LOG_WARNING;
3204	char ownerbuf[DNS_NAME_FORMATSIZE];
3205	char typebuf[DNS_RDATATYPE_FORMATSIZE];
3206	unsigned int count1 = 0;
3207
3208	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
3209		level = ISC_LOG_ERROR;
3210	}
3211
3212	dns_rdataset_init(&tmprdataset);
3213	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
3214	     result = dns_rdataset_next(rdataset))
3215	{
3216		dns_rdata_t rdata1 = DNS_RDATA_INIT;
3217		unsigned int count2 = 0;
3218
3219		count1++;
3220		dns_rdataset_current(rdataset, &rdata1);
3221		dns_rdataset_clone(rdataset, &tmprdataset);
3222		for (result = dns_rdataset_first(&tmprdataset);
3223		     result == ISC_R_SUCCESS;
3224		     result = dns_rdataset_next(&tmprdataset))
3225		{
3226			dns_rdata_t rdata2 = DNS_RDATA_INIT;
3227			count2++;
3228			if (count1 >= count2) {
3229				continue;
3230			}
3231			dns_rdataset_current(&tmprdataset, &rdata2);
3232			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
3233				if (format) {
3234					dns_name_format(owner, ownerbuf,
3235							sizeof ownerbuf);
3236					dns_rdatatype_format(rdata1.type,
3237							     typebuf,
3238							     sizeof(typebuf));
3239					format = false;
3240				}
3241				dns_zone_log(zone, level,
3242					     "%s/%s has "
3243					     "semantically identical records",
3244					     ownerbuf, typebuf);
3245				if (level == ISC_LOG_ERROR) {
3246					answer = false;
3247				}
3248				break;
3249			}
3250		}
3251		dns_rdataset_disassociate(&tmprdataset);
3252		if (!format) {
3253			break;
3254		}
3255	}
3256	return (answer);
3257}
3258
3259static bool
3260zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
3261	dns_dbiterator_t *dbiterator = NULL;
3262	dns_dbnode_t *node = NULL;
3263	dns_fixedname_t fixed;
3264	dns_name_t *name;
3265	dns_rdataset_t rdataset;
3266	dns_rdatasetiter_t *rdsit = NULL;
3267	bool ok = true;
3268	isc_result_t result;
3269
3270	name = dns_fixedname_initname(&fixed);
3271	dns_rdataset_init(&rdataset);
3272
3273	result = dns_db_createiterator(db, 0, &dbiterator);
3274	if (result != ISC_R_SUCCESS) {
3275		return (true);
3276	}
3277
3278	for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
3279	     result = dns_dbiterator_next(dbiterator))
3280	{
3281		result = dns_dbiterator_current(dbiterator, &node, name);
3282		if (result != ISC_R_SUCCESS) {
3283			continue;
3284		}
3285
3286		result = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsit);
3287		if (result != ISC_R_SUCCESS) {
3288			continue;
3289		}
3290
3291		for (result = dns_rdatasetiter_first(rdsit);
3292		     result == ISC_R_SUCCESS;
3293		     result = dns_rdatasetiter_next(rdsit))
3294		{
3295			dns_rdatasetiter_current(rdsit, &rdataset);
3296			if (!zone_rrset_check_dup(zone, name, &rdataset)) {
3297				ok = false;
3298			}
3299			dns_rdataset_disassociate(&rdataset);
3300		}
3301		dns_rdatasetiter_destroy(&rdsit);
3302		dns_db_detachnode(db, &node);
3303	}
3304
3305	if (node != NULL) {
3306		dns_db_detachnode(db, &node);
3307	}
3308	dns_dbiterator_destroy(&dbiterator);
3309
3310	return (ok);
3311}
3312
3313static bool
3314isspf(const dns_rdata_t *rdata) {
3315	char buf[1024];
3316	const unsigned char *data = rdata->data;
3317	unsigned int rdl = rdata->length, i = 0, tl, len;
3318
3319	while (rdl > 0U) {
3320		len = tl = *data;
3321		++data;
3322		--rdl;
3323		INSIST(tl <= rdl);
3324		if (len > sizeof(buf) - i - 1) {
3325			len = sizeof(buf) - i - 1;
3326		}
3327		memmove(buf + i, data, len);
3328		i += len;
3329		data += tl;
3330		rdl -= tl;
3331	}
3332
3333	if (i < 6U) {
3334		return (false);
3335	}
3336
3337	buf[i] = 0;
3338	if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
3339		return (true);
3340	}
3341	return (false);
3342}
3343
3344static bool
3345integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3346	dns_dbiterator_t *dbiterator = NULL;
3347	dns_dbnode_t *node = NULL;
3348	dns_rdataset_t rdataset;
3349	dns_fixedname_t fixed;
3350	dns_fixedname_t fixedbottom;
3351	dns_rdata_mx_t mx;
3352	dns_rdata_ns_t ns;
3353	dns_rdata_in_srv_t srv;
3354	dns_rdata_t rdata;
3355	dns_name_t *name;
3356	dns_name_t *bottom;
3357	isc_result_t result;
3358	bool ok = true, have_spf, have_txt;
3359
3360	name = dns_fixedname_initname(&fixed);
3361	bottom = dns_fixedname_initname(&fixedbottom);
3362	dns_rdataset_init(&rdataset);
3363	dns_rdata_init(&rdata);
3364
3365	result = dns_db_createiterator(db, 0, &dbiterator);
3366	if (result != ISC_R_SUCCESS) {
3367		return (true);
3368	}
3369
3370	result = dns_dbiterator_first(dbiterator);
3371	while (result == ISC_R_SUCCESS) {
3372		result = dns_dbiterator_current(dbiterator, &node, name);
3373		if (result != ISC_R_SUCCESS) {
3374			goto cleanup;
3375		}
3376
3377		/*
3378		 * Is this name visible in the zone?
3379		 */
3380		if (!dns_name_issubdomain(name, &zone->origin) ||
3381		    (dns_name_countlabels(bottom) > 0 &&
3382		     dns_name_issubdomain(name, bottom)))
3383		{
3384			goto next;
3385		}
3386
3387		dns_dbiterator_pause(dbiterator);
3388
3389		/*
3390		 * Don't check the NS records at the origin.
3391		 */
3392		if (dns_name_equal(name, &zone->origin)) {
3393			goto checkfordname;
3394		}
3395
3396		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3397					     0, 0, &rdataset, NULL);
3398		if (result != ISC_R_SUCCESS) {
3399			goto checkfordname;
3400		}
3401		/*
3402		 * Remember bottom of zone due to NS.
3403		 */
3404		dns_name_copy(name, bottom);
3405
3406		result = dns_rdataset_first(&rdataset);
3407		while (result == ISC_R_SUCCESS) {
3408			dns_rdataset_current(&rdataset, &rdata);
3409			result = dns_rdata_tostruct(&rdata, &ns, NULL);
3410			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3411			if (!zone_check_glue(zone, db, &ns.name, name)) {
3412				ok = false;
3413			}
3414			dns_rdata_reset(&rdata);
3415			result = dns_rdataset_next(&rdataset);
3416		}
3417		dns_rdataset_disassociate(&rdataset);
3418		goto next;
3419
3420	checkfordname:
3421		result = dns_db_findrdataset(db, node, NULL,
3422					     dns_rdatatype_dname, 0, 0,
3423					     &rdataset, NULL);
3424		if (result == ISC_R_SUCCESS) {
3425			/*
3426			 * Remember bottom of zone due to DNAME.
3427			 */
3428			dns_name_copy(name, bottom);
3429			dns_rdataset_disassociate(&rdataset);
3430		}
3431
3432		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3433					     0, 0, &rdataset, NULL);
3434		if (result != ISC_R_SUCCESS) {
3435			goto checksrv;
3436		}
3437		result = dns_rdataset_first(&rdataset);
3438		while (result == ISC_R_SUCCESS) {
3439			dns_rdataset_current(&rdataset, &rdata);
3440			result = dns_rdata_tostruct(&rdata, &mx, NULL);
3441			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3442			if (!zone_check_mx(zone, db, &mx.mx, name)) {
3443				ok = false;
3444			}
3445			dns_rdata_reset(&rdata);
3446			result = dns_rdataset_next(&rdataset);
3447		}
3448		dns_rdataset_disassociate(&rdataset);
3449
3450	checksrv:
3451		if (zone->rdclass != dns_rdataclass_in) {
3452			goto next;
3453		}
3454		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3455					     0, 0, &rdataset, NULL);
3456		if (result != ISC_R_SUCCESS) {
3457			goto checkspf;
3458		}
3459		result = dns_rdataset_first(&rdataset);
3460		while (result == ISC_R_SUCCESS) {
3461			dns_rdataset_current(&rdataset, &rdata);
3462			result = dns_rdata_tostruct(&rdata, &srv, NULL);
3463			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3464			if (!zone_check_srv(zone, db, &srv.target, name)) {
3465				ok = false;
3466			}
3467			dns_rdata_reset(&rdata);
3468			result = dns_rdataset_next(&rdataset);
3469		}
3470		dns_rdataset_disassociate(&rdataset);
3471
3472	checkspf:
3473		/*
3474		 * Check if there is a type SPF record without an
3475		 * SPF-formatted type TXT record also being present.
3476		 */
3477		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
3478			goto next;
3479		}
3480		if (zone->rdclass != dns_rdataclass_in) {
3481			goto next;
3482		}
3483		have_spf = have_txt = false;
3484		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3485					     0, 0, &rdataset, NULL);
3486		if (result == ISC_R_SUCCESS) {
3487			dns_rdataset_disassociate(&rdataset);
3488			have_spf = true;
3489		}
3490		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3491					     0, 0, &rdataset, NULL);
3492		if (result != ISC_R_SUCCESS) {
3493			goto notxt;
3494		}
3495		result = dns_rdataset_first(&rdataset);
3496		while (result == ISC_R_SUCCESS) {
3497			dns_rdataset_current(&rdataset, &rdata);
3498			have_txt = isspf(&rdata);
3499			dns_rdata_reset(&rdata);
3500			if (have_txt) {
3501				break;
3502			}
3503			result = dns_rdataset_next(&rdataset);
3504		}
3505		dns_rdataset_disassociate(&rdataset);
3506
3507	notxt:
3508		if (have_spf && !have_txt) {
3509			char namebuf[DNS_NAME_FORMATSIZE];
3510
3511			dns_name_format(name, namebuf, sizeof(namebuf));
3512			dns_zone_log(zone, ISC_LOG_WARNING,
3513				     "'%s' found type "
3514				     "SPF record but no SPF TXT record found, "
3515				     "add matching type TXT record",
3516				     namebuf);
3517		}
3518
3519	next:
3520		dns_db_detachnode(db, &node);
3521		result = dns_dbiterator_next(dbiterator);
3522	}
3523
3524cleanup:
3525	if (node != NULL) {
3526		dns_db_detachnode(db, &node);
3527	}
3528	dns_dbiterator_destroy(&dbiterator);
3529
3530	return (ok);
3531}
3532
3533/*
3534 * OpenSSL verification of RSA keys with exponent 3 is known to be
3535 * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
3536 * if they are in use.
3537 */
3538static void
3539zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3540	dns_dbnode_t *node = NULL;
3541	dns_dbversion_t *version = NULL;
3542	dns_rdata_dnskey_t dnskey;
3543	dns_rdata_t rdata = DNS_RDATA_INIT;
3544	dns_rdataset_t rdataset;
3545	isc_result_t result;
3546
3547	result = dns_db_findnode(db, &zone->origin, false, &node);
3548	if (result != ISC_R_SUCCESS) {
3549		goto cleanup;
3550	}
3551
3552	dns_db_currentversion(db, &version);
3553	dns_rdataset_init(&rdataset);
3554	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3555				     dns_rdatatype_none, 0, &rdataset, NULL);
3556	if (result != ISC_R_SUCCESS) {
3557		goto cleanup;
3558	}
3559
3560	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3561	     result = dns_rdataset_next(&rdataset))
3562	{
3563		dns_rdataset_current(&rdataset, &rdata);
3564		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3565		INSIST(result == ISC_R_SUCCESS);
3566
3567		/*
3568		 * RFC 3110, section 4: Performance Considerations:
3569		 *
3570		 * A public exponent of 3 minimizes the effort needed to verify
3571		 * a signature.  Use of 3 as the public exponent is weak for
3572		 * confidentiality uses since, if the same data can be collected
3573		 * encrypted under three different keys with an exponent of 3
3574		 * then, using the Chinese Remainder Theorem [NETSEC], the
3575		 * original plain text can be easily recovered.  If a key is
3576		 * known to be used only for authentication, as is the case with
3577		 * DNSSEC, then an exponent of 3 is acceptable.  However other
3578		 * applications in the future may wish to leverage DNS
3579		 * distributed keys for applications that do require
3580		 * confidentiality.  For keys which might have such other uses,
3581		 * a more conservative choice would be 65537 (F4, the fourth
3582		 * fermat number).
3583		 */
3584		if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3585		    dnskey.data[1] == 3 &&
3586		    (dnskey.algorithm == DNS_KEYALG_RSAMD5 ||
3587		     dnskey.algorithm == DNS_KEYALG_RSASHA1 ||
3588		     dnskey.algorithm == DNS_KEYALG_NSEC3RSASHA1 ||
3589		     dnskey.algorithm == DNS_KEYALG_RSASHA256 ||
3590		     dnskey.algorithm == DNS_KEYALG_RSASHA512))
3591		{
3592			char algorithm[DNS_SECALG_FORMATSIZE];
3593			isc_region_t r;
3594
3595			dns_rdata_toregion(&rdata, &r);
3596			dns_secalg_format(dnskey.algorithm, algorithm,
3597					  sizeof(algorithm));
3598
3599			dnssec_log(zone, ISC_LOG_WARNING,
3600				   "weak %s (%u) key found (exponent=3, id=%u)",
3601				   algorithm, dnskey.algorithm,
3602				   dst_region_computeid(&r));
3603		}
3604		dns_rdata_reset(&rdata);
3605	}
3606	dns_rdataset_disassociate(&rdataset);
3607
3608cleanup:
3609	if (node != NULL) {
3610		dns_db_detachnode(db, &node);
3611	}
3612	if (version != NULL) {
3613		dns_db_closeversion(db, &version, false);
3614	}
3615}
3616
3617static void
3618resume_signingwithkey(dns_zone_t *zone) {
3619	dns_dbnode_t *node = NULL;
3620	dns_dbversion_t *version = NULL;
3621	dns_rdata_t rdata = DNS_RDATA_INIT;
3622	dns_rdataset_t rdataset;
3623	isc_result_t result;
3624	dns_db_t *db = NULL;
3625
3626	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3627	if (zone->db != NULL) {
3628		dns_db_attach(zone->db, &db);
3629	}
3630	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3631	if (db == NULL) {
3632		goto cleanup;
3633	}
3634
3635	result = dns_db_findnode(db, &zone->origin, false, &node);
3636	if (result != ISC_R_SUCCESS) {
3637		goto cleanup;
3638	}
3639
3640	dns_db_currentversion(db, &version);
3641	dns_rdataset_init(&rdataset);
3642	result = dns_db_findrdataset(db, node, version, zone->privatetype,
3643				     dns_rdatatype_none, 0, &rdataset, NULL);
3644	if (result != ISC_R_SUCCESS) {
3645		INSIST(!dns_rdataset_isassociated(&rdataset));
3646		goto cleanup;
3647	}
3648
3649	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3650	     result = dns_rdataset_next(&rdataset))
3651	{
3652		dns_rdataset_current(&rdataset, &rdata);
3653		if (rdata.length != 5 || rdata.data[0] == 0 ||
3654		    rdata.data[4] != 0)
3655		{
3656			dns_rdata_reset(&rdata);
3657			continue;
3658		}
3659
3660		result = zone_signwithkey(zone, rdata.data[0],
3661					  (rdata.data[1] << 8) | rdata.data[2],
3662					  rdata.data[3]);
3663		if (result != ISC_R_SUCCESS) {
3664			dnssec_log(zone, ISC_LOG_ERROR,
3665				   "zone_signwithkey failed: %s",
3666				   isc_result_totext(result));
3667		}
3668		dns_rdata_reset(&rdata);
3669	}
3670	dns_rdataset_disassociate(&rdataset);
3671
3672cleanup:
3673	if (db != NULL) {
3674		if (node != NULL) {
3675			dns_db_detachnode(db, &node);
3676		}
3677		if (version != NULL) {
3678			dns_db_closeversion(db, &version, false);
3679		}
3680		dns_db_detach(&db);
3681	}
3682}
3683
3684/*
3685 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3686 * supplied NSEC3PARAM RDATA.
3687 *
3688 * Zone must be locked by caller.
3689 */
3690static isc_result_t
3691zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3692	dns_nsec3chain_t *nsec3chain, *current;
3693	dns_dbversion_t *version = NULL;
3694	bool nseconly = false, nsec3ok = false;
3695	isc_result_t result;
3696	isc_time_t now;
3697	unsigned int options = 0;
3698	char saltbuf[255 * 2 + 1];
3699	char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3700	dns_db_t *db = NULL;
3701
3702	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3703	if (zone->db != NULL) {
3704		dns_db_attach(zone->db, &db);
3705	}
3706	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3707
3708	if (db == NULL) {
3709		result = ISC_R_SUCCESS;
3710		goto cleanup;
3711	}
3712
3713	/*
3714	 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3715	 * chain from it is pointless as it would not be possible for the
3716	 * latter to exist in the first place.
3717	 */
3718	dns_db_currentversion(db, &version);
3719	result = dns_nsec_nseconly(db, version, NULL, &nseconly);
3720	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3721	dns_db_closeversion(db, &version, false);
3722	if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3723		result = ISC_R_SUCCESS;
3724		goto cleanup;
3725	}
3726
3727	/*
3728	 * Allocate and initialize structure preserving state of
3729	 * adding/removing records belonging to this NSEC3 chain between
3730	 * separate zone_nsec3chain() calls.
3731	 */
3732	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3733
3734	nsec3chain->magic = 0;
3735	nsec3chain->done = false;
3736	nsec3chain->db = NULL;
3737	nsec3chain->dbiterator = NULL;
3738	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3739	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3740	nsec3chain->nsec3param.hash = nsec3param->hash;
3741	nsec3chain->nsec3param.iterations = nsec3param->iterations;
3742	nsec3chain->nsec3param.flags = nsec3param->flags;
3743	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3744	memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3745	nsec3chain->nsec3param.salt = nsec3chain->salt;
3746	nsec3chain->seen_nsec = false;
3747	nsec3chain->delete_nsec = false;
3748	nsec3chain->save_delete_nsec = false;
3749
3750	/*
3751	 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3752	 */
3753	if (nsec3param->flags == 0) {
3754		strlcpy(flags, "NONE", sizeof(flags));
3755	} else {
3756		flags[0] = '\0';
3757		if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3758			strlcat(flags, "REMOVE", sizeof(flags));
3759		}
3760		if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3761			if (flags[0] == '\0') {
3762				strlcpy(flags, "INITIAL", sizeof(flags));
3763			} else {
3764				strlcat(flags, "|INITIAL", sizeof(flags));
3765			}
3766		}
3767		if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3768			if (flags[0] == '\0') {
3769				strlcpy(flags, "CREATE", sizeof(flags));
3770			} else {
3771				strlcat(flags, "|CREATE", sizeof(flags));
3772			}
3773		}
3774		if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3775			if (flags[0] == '\0') {
3776				strlcpy(flags, "NONSEC", sizeof(flags));
3777			} else {
3778				strlcat(flags, "|NONSEC", sizeof(flags));
3779			}
3780		}
3781		if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3782			if (flags[0] == '\0') {
3783				strlcpy(flags, "OPTOUT", sizeof(flags));
3784			} else {
3785				strlcat(flags, "|OPTOUT", sizeof(flags));
3786			}
3787		}
3788	}
3789	result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3790					   sizeof(saltbuf));
3791	RUNTIME_CHECK(result == ISC_R_SUCCESS);
3792	dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3793		   nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3794
3795	/*
3796	 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3797	 * currently being processed, interrupt its processing to avoid
3798	 * simultaneously adding and removing records for the same NSEC3 chain.
3799	 */
3800	for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
3801	     current = ISC_LIST_NEXT(current, link))
3802	{
3803		if ((current->db == db) &&
3804		    (current->nsec3param.hash == nsec3param->hash) &&
3805		    (current->nsec3param.iterations ==
3806		     nsec3param->iterations) &&
3807		    (current->nsec3param.salt_length ==
3808		     nsec3param->salt_length) &&
3809		    memcmp(current->nsec3param.salt, nsec3param->salt,
3810			   nsec3param->salt_length) == 0)
3811		{
3812			current->done = true;
3813		}
3814	}
3815
3816	/*
3817	 * Attach zone database to the structure initialized above and create
3818	 * an iterator for it with appropriate options in order to avoid
3819	 * creating NSEC3 records for NSEC3 records.
3820	 */
3821	dns_db_attach(db, &nsec3chain->db);
3822	if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3823		options = DNS_DB_NONSEC3;
3824	}
3825	result = dns_db_createiterator(nsec3chain->db, options,
3826				       &nsec3chain->dbiterator);
3827	if (result == ISC_R_SUCCESS) {
3828		result = dns_dbiterator_first(nsec3chain->dbiterator);
3829	}
3830	if (result == ISC_R_SUCCESS) {
3831		/*
3832		 * Database iterator initialization succeeded.  We are now
3833		 * ready to kick off adding/removing records belonging to this
3834		 * NSEC3 chain.  Append the structure initialized above to the
3835		 * "nsec3chain" list for the zone and set the appropriate zone
3836		 * timer so that zone_nsec3chain() is called as soon as
3837		 * possible.
3838		 */
3839		dns_dbiterator_pause(nsec3chain->dbiterator);
3840		ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
3841		nsec3chain = NULL;
3842		if (isc_time_isepoch(&zone->nsec3chaintime)) {
3843			TIME_NOW(&now);
3844			zone->nsec3chaintime = now;
3845			if (zone->task != NULL) {
3846				zone_settimer(zone, &now);
3847			}
3848		}
3849	}
3850
3851	if (nsec3chain != NULL) {
3852		if (nsec3chain->db != NULL) {
3853			dns_db_detach(&nsec3chain->db);
3854		}
3855		if (nsec3chain->dbiterator != NULL) {
3856			dns_dbiterator_destroy(&nsec3chain->dbiterator);
3857		}
3858		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3859	}
3860
3861cleanup:
3862	if (db != NULL) {
3863		dns_db_detach(&db);
3864	}
3865	return (result);
3866}
3867
3868/*
3869 * Find private-type records at the zone apex which signal that an NSEC3 chain
3870 * should be added or removed.  For each such record, extract NSEC3PARAM RDATA
3871 * and pass it to zone_addnsec3chain().
3872 *
3873 * Zone must be locked by caller.
3874 */
3875static void
3876resume_addnsec3chain(dns_zone_t *zone) {
3877	dns_dbnode_t *node = NULL;
3878	dns_dbversion_t *version = NULL;
3879	dns_rdataset_t rdataset;
3880	isc_result_t result;
3881	dns_rdata_nsec3param_t nsec3param;
3882	bool nseconly = false, nsec3ok = false;
3883	dns_db_t *db = NULL;
3884
3885	INSIST(LOCKED_ZONE(zone));
3886
3887	if (zone->privatetype == 0) {
3888		return;
3889	}
3890
3891	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3892	if (zone->db != NULL) {
3893		dns_db_attach(zone->db, &db);
3894	}
3895	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3896	if (db == NULL) {
3897		goto cleanup;
3898	}
3899
3900	result = dns_db_findnode(db, &zone->origin, false, &node);
3901	if (result != ISC_R_SUCCESS) {
3902		goto cleanup;
3903	}
3904
3905	dns_db_currentversion(db, &version);
3906
3907	/*
3908	 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3909	 * apex to exist and contain no keys using NSEC-only algorithms.
3910	 */
3911	result = dns_nsec_nseconly(db, version, NULL, &nseconly);
3912	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3913
3914	/*
3915	 * Get the RRset containing all private-type records at the zone apex.
3916	 */
3917	dns_rdataset_init(&rdataset);
3918	result = dns_db_findrdataset(db, node, version, zone->privatetype,
3919				     dns_rdatatype_none, 0, &rdataset, NULL);
3920	if (result != ISC_R_SUCCESS) {
3921		INSIST(!dns_rdataset_isassociated(&rdataset));
3922		goto cleanup;
3923	}
3924
3925	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3926	     result = dns_rdataset_next(&rdataset))
3927	{
3928		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3929		dns_rdata_t rdata = DNS_RDATA_INIT;
3930		dns_rdata_t private = DNS_RDATA_INIT;
3931
3932		dns_rdataset_current(&rdataset, &private);
3933		/*
3934		 * Try extracting NSEC3PARAM RDATA from this private-type
3935		 * record.  Failure means this private-type record does not
3936		 * represent an NSEC3PARAM record, so skip it.
3937		 */
3938		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3939						sizeof(buf)))
3940		{
3941			continue;
3942		}
3943		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3944		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3945		if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3946		    ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3947		{
3948			/*
3949			 * Pass the NSEC3PARAM RDATA contained in this
3950			 * private-type record to zone_addnsec3chain() so that
3951			 * it can kick off adding or removing NSEC3 records.
3952			 */
3953			result = zone_addnsec3chain(zone, &nsec3param);
3954			if (result != ISC_R_SUCCESS) {
3955				dnssec_log(zone, ISC_LOG_ERROR,
3956					   "zone_addnsec3chain failed: %s",
3957					   isc_result_totext(result));
3958			}
3959		}
3960	}
3961	dns_rdataset_disassociate(&rdataset);
3962
3963cleanup:
3964	if (db != NULL) {
3965		if (node != NULL) {
3966			dns_db_detachnode(db, &node);
3967		}
3968		if (version != NULL) {
3969			dns_db_closeversion(db, &version, false);
3970		}
3971		dns_db_detach(&db);
3972	}
3973}
3974
3975static void
3976set_resigntime(dns_zone_t *zone) {
3977	dns_rdataset_t rdataset;
3978	dns_fixedname_t fixed;
3979	unsigned int resign;
3980	isc_result_t result;
3981	uint32_t nanosecs;
3982	dns_db_t *db = NULL;
3983
3984	INSIST(LOCKED_ZONE(zone));
3985
3986	/* We only re-sign zones that can be dynamically updated */
3987	if (!dns_zone_isdynamic(zone, false)) {
3988		return;
3989	}
3990
3991	if (inline_raw(zone)) {
3992		return;
3993	}
3994
3995	dns_rdataset_init(&rdataset);
3996	dns_fixedname_init(&fixed);
3997
3998	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3999	if (zone->db != NULL) {
4000		dns_db_attach(zone->db, &db);
4001	}
4002	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4003	if (db == NULL) {
4004		isc_time_settoepoch(&zone->resigntime);
4005		return;
4006	}
4007
4008	result = dns_db_getsigningtime(db, &rdataset,
4009				       dns_fixedname_name(&fixed));
4010	if (result != ISC_R_SUCCESS) {
4011		isc_time_settoepoch(&zone->resigntime);
4012		goto cleanup;
4013	}
4014
4015	resign = rdataset.resign - dns_zone_getsigresigninginterval(zone);
4016	dns_rdataset_disassociate(&rdataset);
4017	nanosecs = isc_random_uniform(1000000000);
4018	isc_time_set(&zone->resigntime, resign, nanosecs);
4019
4020cleanup:
4021	dns_db_detach(&db);
4022	return;
4023}
4024
4025static isc_result_t
4026check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
4027	bool ok = false;
4028	dns_dbnode_t *node = NULL;
4029	dns_dbversion_t *version = NULL;
4030	dns_rdata_nsec3param_t nsec3param;
4031	dns_rdataset_t rdataset;
4032	isc_result_t result;
4033	bool dynamic = (zone->type == dns_zone_primary)
4034			       ? dns_zone_isdynamic(zone, false)
4035			       : false;
4036
4037	dns_rdataset_init(&rdataset);
4038	result = dns_db_findnode(db, &zone->origin, false, &node);
4039	if (result != ISC_R_SUCCESS) {
4040		dns_zone_log(zone, ISC_LOG_ERROR,
4041			     "nsec3param lookup failure: %s",
4042			     isc_result_totext(result));
4043		return (result);
4044	}
4045	dns_db_currentversion(db, &version);
4046
4047	result = dns_db_findrdataset(db, node, version,
4048				     dns_rdatatype_nsec3param,
4049				     dns_rdatatype_none, 0, &rdataset, NULL);
4050	if (result == ISC_R_NOTFOUND) {
4051		INSIST(!dns_rdataset_isassociated(&rdataset));
4052		result = ISC_R_SUCCESS;
4053		goto cleanup;
4054	}
4055	if (result != ISC_R_SUCCESS) {
4056		INSIST(!dns_rdataset_isassociated(&rdataset));
4057		dns_zone_log(zone, ISC_LOG_ERROR,
4058			     "nsec3param lookup failure: %s",
4059			     isc_result_totext(result));
4060		goto cleanup;
4061	}
4062
4063	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
4064	     result = dns_rdataset_next(&rdataset))
4065	{
4066		dns_rdata_t rdata = DNS_RDATA_INIT;
4067
4068		dns_rdataset_current(&rdataset, &rdata);
4069		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
4070		RUNTIME_CHECK(result == ISC_R_SUCCESS);
4071
4072		/*
4073		 * For dynamic zones we must support every algorithm so we
4074		 * can regenerate all the NSEC3 chains.
4075		 * For non-dynamic zones we only need to find a supported
4076		 * algorithm.
4077		 */
4078		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
4079		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
4080		{
4081			dns_zone_log(zone, ISC_LOG_WARNING,
4082				     "nsec3 test \"unknown\" hash algorithm "
4083				     "found: %u",
4084				     nsec3param.hash);
4085			ok = true;
4086		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
4087			if (dynamic) {
4088				dns_zone_log(zone, ISC_LOG_ERROR,
4089					     "unsupported nsec3 hash algorithm"
4090					     " in dynamic zone: %u",
4091					     nsec3param.hash);
4092				result = DNS_R_BADZONE;
4093				/* Stop second error message. */
4094				ok = true;
4095				break;
4096			} else {
4097				dns_zone_log(zone, ISC_LOG_WARNING,
4098					     "unsupported nsec3 hash "
4099					     "algorithm: %u",
4100					     nsec3param.hash);
4101			}
4102		} else {
4103			ok = true;
4104		}
4105
4106		/*
4107		 * Warn if the zone has excessive NSEC3 iterations.
4108		 */
4109		if (nsec3param.iterations > dns_nsec3_maxiterations()) {
4110			dnssec_log(zone, ISC_LOG_WARNING,
4111				   "excessive NSEC3PARAM iterations %u > %u",
4112				   nsec3param.iterations,
4113				   dns_nsec3_maxiterations());
4114		}
4115	}
4116	if (result == ISC_R_NOMORE) {
4117		result = ISC_R_SUCCESS;
4118	}
4119
4120	if (!ok) {
4121		result = DNS_R_BADZONE;
4122		dns_zone_log(zone, ISC_LOG_ERROR,
4123			     "no supported nsec3 hash algorithm");
4124	}
4125
4126cleanup:
4127	if (dns_rdataset_isassociated(&rdataset)) {
4128		dns_rdataset_disassociate(&rdataset);
4129	}
4130	dns_db_closeversion(db, &version, false);
4131	dns_db_detachnode(db, &node);
4132	return (result);
4133}
4134
4135/*
4136 * Set the timer for refreshing the key zone to the soonest future time
4137 * of the set (current timer, keydata->refresh, keydata->addhd,
4138 * keydata->removehd).
4139 */
4140static void
4141set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
4142		    isc_stdtime_t now, bool force) {
4143	const char me[] = "set_refreshkeytimer";
4144	isc_stdtime_t then;
4145	isc_time_t timenow, timethen;
4146	char timebuf[80];
4147
4148	ENTER;
4149	then = key->refresh;
4150	if (force) {
4151		then = now;
4152	}
4153	if (key->addhd > now && key->addhd < then) {
4154		then = key->addhd;
4155	}
4156	if (key->removehd > now && key->removehd < then) {
4157		then = key->removehd;
4158	}
4159
4160	TIME_NOW(&timenow);
4161	if (then > now) {
4162		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
4163	} else {
4164		timethen = timenow;
4165	}
4166	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
4167	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
4168	{
4169		zone->refreshkeytime = timethen;
4170	}
4171
4172	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4173	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
4174	zone_settimer(zone, &timenow);
4175}
4176
4177/*
4178 * If keynode references a key or a DS rdataset, and if the key
4179 * zone does not contain a KEYDATA record for the corresponding name,
4180 * then create an empty KEYDATA and push it into the zone as a placeholder,
4181 * then schedule a key refresh immediately. This new KEYDATA record will be
4182 * updated during the refresh.
4183 *
4184 * If the key zone is changed, set '*changed' to true.
4185 */
4186static isc_result_t
4187create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4188	       dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
4189	       bool *changed) {
4190	const char me[] = "create_keydata";
4191	isc_result_t result = ISC_R_SUCCESS;
4192	dns_rdata_t rdata = DNS_RDATA_INIT;
4193	dns_rdata_keydata_t kd;
4194	unsigned char rrdata[4096];
4195	isc_buffer_t rrdatabuf;
4196	isc_stdtime_t now;
4197
4198	REQUIRE(keynode != NULL);
4199
4200	ENTER;
4201	isc_stdtime_get(&now);
4202
4203	/*
4204	 * If the keynode has no trust anchor set, we shouldn't be here.
4205	 */
4206	if (!dns_keynode_dsset(keynode, NULL)) {
4207		return (ISC_R_FAILURE);
4208	}
4209
4210	memset(&kd, 0, sizeof(kd));
4211	kd.common.rdclass = zone->rdclass;
4212	kd.common.rdtype = dns_rdatatype_keydata;
4213	ISC_LINK_INIT(&kd.common, link);
4214
4215	isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
4216
4217	CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
4218				   &kd, &rrdatabuf));
4219	/* Add rdata to zone. */
4220	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
4221	*changed = true;
4222
4223	/* Refresh new keys from the zone apex as soon as possible. */
4224	set_refreshkeytimer(zone, &kd, now, true);
4225	return (ISC_R_SUCCESS);
4226
4227failure:
4228	return (result);
4229}
4230
4231/*
4232 * Remove from the key zone all the KEYDATA records found in rdataset.
4233 */
4234static isc_result_t
4235delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4236	       dns_name_t *name, dns_rdataset_t *rdataset) {
4237	dns_rdata_t rdata = DNS_RDATA_INIT;
4238	isc_result_t result, uresult;
4239
4240	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4241	     result = dns_rdataset_next(rdataset))
4242	{
4243		dns_rdata_reset(&rdata);
4244		dns_rdataset_current(rdataset, &rdata);
4245		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
4246					&rdata);
4247		if (uresult != ISC_R_SUCCESS) {
4248			return (uresult);
4249		}
4250	}
4251	if (result == ISC_R_NOMORE) {
4252		result = ISC_R_SUCCESS;
4253	}
4254	return (result);
4255}
4256
4257/*
4258 * Compute the DNSSEC key ID for a DNSKEY record.
4259 */
4260static isc_result_t
4261compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
4262	    dns_keytag_t *tag) {
4263	isc_result_t result;
4264	dns_rdata_t rdata = DNS_RDATA_INIT;
4265	unsigned char data[4096];
4266	isc_buffer_t buffer;
4267	dst_key_t *dstkey = NULL;
4268
4269	isc_buffer_init(&buffer, data, sizeof(data));
4270	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4271			     dns_rdatatype_dnskey, dnskey, &buffer);
4272
4273	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
4274	if (result == ISC_R_SUCCESS) {
4275		*tag = dst_key_id(dstkey);
4276		dst_key_free(&dstkey);
4277	}
4278
4279	return (result);
4280}
4281
4282/*
4283 * Synth-from-dnssec callbacks to add/delete names from namespace tree.
4284 */
4285static void
4286sfd_add(const dns_name_t *name, void *arg) {
4287	if (arg != NULL) {
4288		dns_view_sfd_add(arg, name);
4289	}
4290}
4291
4292static void
4293sfd_del(const dns_name_t *name, void *arg) {
4294	if (arg != NULL) {
4295		dns_view_sfd_del(arg, name);
4296	}
4297}
4298
4299/*
4300 * Add key to the security roots.
4301 */
4302static void
4303trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
4304	  bool initial) {
4305	isc_result_t result;
4306	dns_rdata_t rdata = DNS_RDATA_INIT;
4307	unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
4308	isc_buffer_t buffer;
4309	dns_keytable_t *sr = NULL;
4310	dns_rdata_ds_t ds;
4311
4312	result = dns_view_getsecroots(zone->view, &sr);
4313	if (result != ISC_R_SUCCESS) {
4314		return;
4315	}
4316
4317	/* Build DS record for key. */
4318	isc_buffer_init(&buffer, data, sizeof(data));
4319	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4320			     dns_rdatatype_dnskey, dnskey, &buffer);
4321	CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
4322				  &ds));
4323	CHECK(dns_keytable_add(sr, true, initial, keyname, &ds, sfd_add,
4324			       zone->view));
4325
4326	dns_keytable_detach(&sr);
4327
4328failure:
4329	if (sr != NULL) {
4330		dns_keytable_detach(&sr);
4331	}
4332	return;
4333}
4334
4335/*
4336 * Add a null key to the security roots for so that all queries
4337 * to the zone will fail.
4338 */
4339static void
4340fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4341	isc_result_t result;
4342	dns_keytable_t *sr = NULL;
4343
4344	result = dns_view_getsecroots(zone->view, &sr);
4345	if (result == ISC_R_SUCCESS) {
4346		dns_keytable_marksecure(sr, keyname);
4347		dns_keytable_detach(&sr);
4348	}
4349}
4350
4351/*
4352 * Scan a set of KEYDATA records from the key zone.  The ones that are
4353 * valid (i.e., the add holddown timer has expired) become trusted keys.
4354 */
4355static void
4356load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4357	isc_result_t result;
4358	dns_rdata_t rdata = DNS_RDATA_INIT;
4359	dns_rdata_keydata_t keydata;
4360	dns_rdata_dnskey_t dnskey;
4361	int trusted = 0, revoked = 0, pending = 0;
4362	isc_stdtime_t now;
4363	dns_keytable_t *sr = NULL;
4364
4365	isc_stdtime_get(&now);
4366
4367	result = dns_view_getsecroots(zone->view, &sr);
4368	if (result == ISC_R_SUCCESS) {
4369		dns_keytable_delete(sr, name, sfd_del, zone->view);
4370		dns_keytable_detach(&sr);
4371	}
4372
4373	/* Now insert all the accepted trust anchors from this keydata set. */
4374	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4375	     result = dns_rdataset_next(rdataset))
4376	{
4377		dns_rdata_reset(&rdata);
4378		dns_rdataset_current(rdataset, &rdata);
4379
4380		/* Convert rdata to keydata. */
4381		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4382		if (result == ISC_R_UNEXPECTEDEND) {
4383			continue;
4384		}
4385		RUNTIME_CHECK(result == ISC_R_SUCCESS);
4386
4387		/* Set the key refresh timer to force a fast refresh. */
4388		set_refreshkeytimer(zone, &keydata, now, true);
4389
4390		/* If the removal timer is nonzero, this key was revoked. */
4391		if (keydata.removehd != 0) {
4392			revoked++;
4393			continue;
4394		}
4395
4396		/*
4397		 * If the add timer is still pending, this key is not
4398		 * trusted yet.
4399		 */
4400		if (now < keydata.addhd) {
4401			pending++;
4402			continue;
4403		}
4404
4405		/* Convert keydata to dnskey. */
4406		dns_keydata_todnskey(&keydata, &dnskey, NULL);
4407
4408		/* Add to keytables. */
4409		trusted++;
4410		trust_key(zone, name, &dnskey, (keydata.addhd == 0));
4411	}
4412
4413	if (trusted == 0 && pending != 0) {
4414		char namebuf[DNS_NAME_FORMATSIZE];
4415		dns_name_format(name, namebuf, sizeof namebuf);
4416		dnssec_log(zone, ISC_LOG_ERROR,
4417			   "No valid trust anchors for '%s'!", namebuf);
4418		dnssec_log(zone, ISC_LOG_ERROR,
4419			   "%d key(s) revoked, %d still pending", revoked,
4420			   pending);
4421		dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
4422			   namebuf);
4423		fail_secure(zone, name);
4424	}
4425}
4426
4427static isc_result_t
4428do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4429	     dns_diff_t *diff) {
4430	dns_diff_t temp_diff;
4431	isc_result_t result;
4432
4433	/*
4434	 * Create a singleton diff.
4435	 */
4436	dns_diff_init(diff->mctx, &temp_diff);
4437	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4438
4439	/*
4440	 * Apply it to the database.
4441	 */
4442	result = dns_diff_apply(&temp_diff, db, ver);
4443	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4444	if (result != ISC_R_SUCCESS) {
4445		dns_difftuple_free(tuple);
4446		return (result);
4447	}
4448
4449	/*
4450	 * Merge it into the current pending journal entry.
4451	 */
4452	dns_diff_appendminimal(diff, tuple);
4453
4454	/*
4455	 * Do not clear temp_diff.
4456	 */
4457	return (ISC_R_SUCCESS);
4458}
4459
4460static isc_result_t
4461update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4462	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4463	      dns_rdata_t *rdata) {
4464	dns_difftuple_t *tuple = NULL;
4465	isc_result_t result;
4466	result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
4467	if (result != ISC_R_SUCCESS) {
4468		return (result);
4469	}
4470	return (do_one_tuple(&tuple, db, ver, diff));
4471}
4472
4473static isc_result_t
4474update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4475		  dns_diff_t *diff, isc_mem_t *mctx,
4476		  dns_updatemethod_t method) {
4477	dns_difftuple_t *deltuple = NULL;
4478	dns_difftuple_t *addtuple = NULL;
4479	uint32_t serial;
4480	isc_result_t result;
4481	dns_updatemethod_t used = dns_updatemethod_none;
4482
4483	INSIST(method != dns_updatemethod_none);
4484
4485	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4486	CHECK(dns_difftuple_copy(deltuple, &addtuple));
4487	addtuple->op = DNS_DIFFOP_ADD;
4488
4489	serial = dns_soa_getserial(&addtuple->rdata);
4490	serial = dns_update_soaserial(serial, method, &used);
4491	if (method != used) {
4492		dns_zone_log(zone, ISC_LOG_WARNING,
4493			     "update_soa_serial:new serial would be lower than "
4494			     "old serial, using increment method instead");
4495	}
4496	dns_soa_setserial(serial, &addtuple->rdata);
4497	CHECK(do_one_tuple(&deltuple, db, ver, diff));
4498	CHECK(do_one_tuple(&addtuple, db, ver, diff));
4499	result = ISC_R_SUCCESS;
4500
4501failure:
4502	if (addtuple != NULL) {
4503		dns_difftuple_free(&addtuple);
4504	}
4505	if (deltuple != NULL) {
4506		dns_difftuple_free(&deltuple);
4507	}
4508	return (result);
4509}
4510
4511/*
4512 * Write all transactions in 'diff' to the zone journal file.
4513 */
4514static isc_result_t
4515zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4516	     const char *caller) {
4517	const char me[] = "zone_journal";
4518	const char *journalfile;
4519	isc_result_t result = ISC_R_SUCCESS;
4520	dns_journal_t *journal = NULL;
4521	unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
4522
4523	ENTER;
4524	journalfile = dns_zone_getjournal(zone);
4525	if (journalfile != NULL) {
4526		result = dns_journal_open(zone->mctx, journalfile, mode,
4527					  &journal);
4528		if (result != ISC_R_SUCCESS) {
4529			dns_zone_log(zone, ISC_LOG_ERROR,
4530				     "%s:dns_journal_open -> %s", caller,
4531				     isc_result_totext(result));
4532			return (result);
4533		}
4534
4535		if (sourceserial != NULL) {
4536			dns_journal_set_sourceserial(journal, *sourceserial);
4537		}
4538
4539		result = dns_journal_write_transaction(journal, diff);
4540		if (result != ISC_R_SUCCESS) {
4541			dns_zone_log(zone, ISC_LOG_ERROR,
4542				     "%s:dns_journal_write_transaction -> %s",
4543				     caller, isc_result_totext(result));
4544		}
4545		dns_journal_destroy(&journal);
4546	}
4547
4548	return (result);
4549}
4550
4551/*
4552 * Create an SOA record for a newly-created zone
4553 */
4554static isc_result_t
4555add_soa(dns_zone_t *zone, dns_db_t *db) {
4556	isc_result_t result;
4557	dns_rdata_t rdata = DNS_RDATA_INIT;
4558	unsigned char buf[DNS_SOA_BUFFERSIZE];
4559	dns_dbversion_t *ver = NULL;
4560	dns_diff_t diff;
4561
4562	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4563
4564	dns_diff_init(zone->mctx, &diff);
4565	result = dns_db_newversion(db, &ver);
4566	if (result != ISC_R_SUCCESS) {
4567		dns_zone_log(zone, ISC_LOG_ERROR,
4568			     "add_soa:dns_db_newversion -> %s",
4569			     isc_result_totext(result));
4570		goto failure;
4571	}
4572
4573	/* Build SOA record */
4574	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4575				    0, 0, 0, 0, 0, buf, &rdata);
4576	if (result != ISC_R_SUCCESS) {
4577		dns_zone_log(zone, ISC_LOG_ERROR,
4578			     "add_soa:dns_soa_buildrdata -> %s",
4579			     isc_result_totext(result));
4580		goto failure;
4581	}
4582
4583	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
4584			       &rdata);
4585
4586failure:
4587	dns_diff_clear(&diff);
4588	if (ver != NULL) {
4589		dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4590	}
4591
4592	INSIST(ver == NULL);
4593
4594	return (result);
4595}
4596
4597struct addifmissing_arg {
4598	dns_db_t *db;
4599	dns_dbversion_t *ver;
4600	dns_diff_t *diff;
4601	dns_zone_t *zone;
4602	bool *changed;
4603	isc_result_t result;
4604};
4605
4606static void
4607addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
4608	     dns_name_t *keyname, void *arg) {
4609	dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4610	dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4611	dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4612	dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4613	bool *changed = ((struct addifmissing_arg *)arg)->changed;
4614	isc_result_t result;
4615	dns_fixedname_t fname;
4616
4617	UNUSED(keytable);
4618
4619	if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
4620		return;
4621	}
4622
4623	if (!dns_keynode_managed(keynode)) {
4624		return;
4625	}
4626
4627	/*
4628	 * If the keynode has no trust anchor set, return.
4629	 */
4630	if (!dns_keynode_dsset(keynode, NULL)) {
4631		return;
4632	}
4633
4634	/*
4635	 * Check whether there's already a KEYDATA entry for this name;
4636	 * if so, we don't need to add another.
4637	 */
4638	dns_fixedname_init(&fname);
4639	result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
4640			     DNS_DBFIND_NOWILD, 0, NULL,
4641			     dns_fixedname_name(&fname), NULL, NULL);
4642	if (result == ISC_R_SUCCESS) {
4643		return;
4644	}
4645
4646	/*
4647	 * Create the keydata.
4648	 */
4649	result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
4650	if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
4651		((struct addifmissing_arg *)arg)->result = result;
4652	}
4653}
4654
4655/*
4656 * Synchronize the set of initializing keys found in managed-keys {}
4657 * statements with the set of trust anchors found in the managed-keys.bind
4658 * zone.  If a domain is no longer named in managed-keys, delete all keys
4659 * from that domain from the key zone.	If a domain is configured as an
4660 * initial-key in trust-anchors, but there are no references to it in the
4661 * key zone, load the key zone with the initializing key(s) for that
4662 * domain and schedule a key refresh. If a domain is configured as
4663 * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
4664 * zone with the matching key, and schedule a key refresh.
4665 */
4666static isc_result_t
4667sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4668	isc_result_t result = ISC_R_SUCCESS;
4669	bool changed = false;
4670	bool commit = false;
4671	dns_keynode_t *keynode = NULL;
4672	dns_view_t *view = zone->view;
4673	dns_keytable_t *sr = NULL;
4674	dns_dbversion_t *ver = NULL;
4675	dns_diff_t diff;
4676	dns_rriterator_t rrit;
4677	struct addifmissing_arg arg;
4678
4679	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4680
4681	dns_diff_init(zone->mctx, &diff);
4682
4683	CHECK(dns_view_getsecroots(view, &sr));
4684
4685	result = dns_db_newversion(db, &ver);
4686	if (result != ISC_R_SUCCESS) {
4687		dnssec_log(zone, ISC_LOG_ERROR,
4688			   "sync_keyzone:dns_db_newversion -> %s",
4689			   isc_result_totext(result));
4690		goto failure;
4691	}
4692
4693	/*
4694	 * Walk the zone DB.  If we find any keys whose names are no longer
4695	 * in trust-anchors, or which have been changed from initial to static,
4696	 * (meaning they are permanent and not RFC5011-maintained), delete
4697	 * them from the zone.  Otherwise call load_secroots(), which
4698	 * loads keys into secroots as appropriate.
4699	 */
4700	dns_rriterator_init(&rrit, db, ver, 0);
4701	for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
4702	     result = dns_rriterator_nextrrset(&rrit))
4703	{
4704		dns_rdataset_t *rdataset = NULL;
4705		dns_rdata_t rdata = DNS_RDATA_INIT;
4706		dns_rdata_keydata_t keydata;
4707		isc_stdtime_t now;
4708		bool load = true;
4709		dns_name_t *rrname = NULL;
4710		uint32_t ttl;
4711
4712		isc_stdtime_get(&now);
4713
4714		dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4715		if (!dns_rdataset_isassociated(rdataset)) {
4716			dns_rriterator_destroy(&rrit);
4717			goto failure;
4718		}
4719
4720		if (rdataset->type != dns_rdatatype_keydata) {
4721			continue;
4722		}
4723
4724		/*
4725		 * The managed-keys zone can contain a placeholder instead of
4726		 * legitimate data, in which case we will not use it, and we
4727		 * will try to refresh it.
4728		 */
4729		for (result = dns_rdataset_first(rdataset);
4730		     result == ISC_R_SUCCESS;
4731		     result = dns_rdataset_next(rdataset))
4732		{
4733			isc_result_t iresult;
4734
4735			dns_rdata_reset(&rdata);
4736			dns_rdataset_current(rdataset, &rdata);
4737
4738			iresult = dns_rdata_tostruct(&rdata, &keydata, NULL);
4739			/* Do we have a valid placeholder KEYDATA record? */
4740			if (iresult == ISC_R_SUCCESS && keydata.flags == 0 &&
4741			    keydata.protocol == 0 && keydata.algorithm == 0)
4742			{
4743				set_refreshkeytimer(zone, &keydata, now, true);
4744				load = false;
4745			}
4746		}
4747
4748		/*
4749		 * Release db wrlock to prevent LOR reports against
4750		 * dns_keytable_forall() call below.
4751		 */
4752		dns_rriterator_pause(&rrit);
4753		result = dns_keytable_find(sr, rrname, &keynode);
4754		if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
4755			CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
4756			changed = true;
4757		} else if (load) {
4758			load_secroots(zone, rrname, rdataset);
4759		}
4760
4761		if (keynode != NULL) {
4762			dns_keytable_detachkeynode(sr, &keynode);
4763		}
4764	}
4765	dns_rriterator_destroy(&rrit);
4766
4767	/*
4768	 * Walk secroots to find any initial keys that aren't in
4769	 * the zone.  If we find any, add them to the zone directly.
4770	 * If any DS-style initial keys are found, refresh the key
4771	 * zone so that they'll be looked up.
4772	 */
4773	arg.db = db;
4774	arg.ver = ver;
4775	arg.result = ISC_R_SUCCESS;
4776	arg.diff = &diff;
4777	arg.zone = zone;
4778	arg.changed = &changed;
4779	dns_keytable_forall(sr, addifmissing, &arg);
4780	result = arg.result;
4781	if (changed) {
4782		/* Write changes to journal file. */
4783		CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
4784					zone->updatemethod));
4785		CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4786
4787		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4788		zone_needdump(zone, 30);
4789		commit = true;
4790	}
4791
4792failure:
4793	if (result != ISC_R_SUCCESS) {
4794		dnssec_log(zone, ISC_LOG_ERROR,
4795			   "unable to synchronize managed keys: %s",
4796			   isc_result_totext(result));
4797		isc_time_settoepoch(&zone->refreshkeytime);
4798	}
4799	if (keynode != NULL) {
4800		dns_keytable_detachkeynode(sr, &keynode);
4801	}
4802	if (sr != NULL) {
4803		dns_keytable_detach(&sr);
4804	}
4805	if (ver != NULL) {
4806		dns_db_closeversion(db, &ver, commit);
4807	}
4808	dns_diff_clear(&diff);
4809
4810	INSIST(ver == NULL);
4811
4812	return (result);
4813}
4814
4815isc_result_t
4816dns_zone_synckeyzone(dns_zone_t *zone) {
4817	isc_result_t result;
4818	dns_db_t *db = NULL;
4819
4820	if (zone->type != dns_zone_key) {
4821		return (DNS_R_BADZONE);
4822	}
4823
4824	CHECK(dns_zone_getdb(zone, &db));
4825
4826	LOCK_ZONE(zone);
4827	result = sync_keyzone(zone, db);
4828	UNLOCK_ZONE(zone);
4829
4830failure:
4831	if (db != NULL) {
4832		dns_db_detach(&db);
4833	}
4834	return (result);
4835}
4836
4837static void
4838maybe_send_secure(dns_zone_t *zone) {
4839	isc_result_t result;
4840
4841	/*
4842	 * We've finished loading, or else failed to load, an inline-signing
4843	 * 'secure' zone.  We now need information about the status of the
4844	 * 'raw' zone.  If we failed to load, then we need it to send a
4845	 * copy of its database; if we succeeded, we need it to send its
4846	 * serial number so that we can sync with it.  If it has not yet
4847	 * loaded, we set a flag so that it will send the necessary
4848	 * information when it has finished loading.
4849	 */
4850	if (zone->raw->db != NULL) {
4851		if (zone->db != NULL) {
4852			uint32_t serial;
4853			unsigned int soacount;
4854
4855			result = zone_get_from_db(
4856				zone->raw, zone->raw->db, NULL, &soacount, NULL,
4857				&serial, NULL, NULL, NULL, NULL, NULL);
4858			if (result == ISC_R_SUCCESS && soacount > 0U) {
4859				zone_send_secureserial(zone->raw, serial);
4860			}
4861		} else {
4862			zone_send_securedb(zone->raw, zone->raw->db);
4863		}
4864	} else {
4865		DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4866	}
4867}
4868
4869static bool
4870zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4871	isc_result_t result;
4872	bool answer = false;
4873	dns_diff_t diff;
4874
4875	dns_diff_init(mctx, &diff);
4876	result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4877	if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
4878		answer = true;
4879	}
4880	dns_diff_clear(&diff);
4881	return (answer);
4882}
4883
4884/*
4885 * The zone is presumed to be locked.
4886 * If this is a inline_raw zone the secure version is also locked.
4887 */
4888static isc_result_t
4889zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4890	      isc_result_t result) {
4891	unsigned int soacount = 0;
4892	unsigned int nscount = 0;
4893	unsigned int errors = 0;
4894	uint32_t serial, oldserial, refresh, retry, expire, minimum, soattl;
4895	isc_time_t now;
4896	bool needdump = false;
4897	bool fixjournal = false;
4898	bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4899	bool noprimary = false;
4900	bool had_db = false;
4901	dns_include_t *inc;
4902	bool is_dynamic = false;
4903
4904	INSIST(LOCKED_ZONE(zone));
4905	if (inline_raw(zone)) {
4906		INSIST(LOCKED_ZONE(zone->secure));
4907	}
4908
4909	TIME_NOW(&now);
4910
4911	/*
4912	 * Initiate zone transfer?  We may need a error code that
4913	 * indicates that the "permanent" form does not exist.
4914	 * XXX better error feedback to log.
4915	 */
4916	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4917		if (zone->type == dns_zone_secondary ||
4918		    zone->type == dns_zone_mirror ||
4919		    zone->type == dns_zone_stub ||
4920		    (zone->type == dns_zone_redirect &&
4921		     zone->primaries == NULL))
4922		{
4923			if (result == ISC_R_FILENOTFOUND) {
4924				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4925					      ISC_LOG_DEBUG(1),
4926					      "no master file");
4927			} else if (result != DNS_R_NOMASTERFILE) {
4928				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4929					      ISC_LOG_ERROR,
4930					      "loading from master file %s "
4931					      "failed: %s",
4932					      zone->masterfile,
4933					      isc_result_totext(result));
4934			}
4935		} else if (zone->type == dns_zone_primary &&
4936			   inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4937		{
4938			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4939				      ISC_LOG_DEBUG(1),
4940				      "no master file, requesting db");
4941			maybe_send_secure(zone);
4942		} else {
4943			int level = ISC_LOG_ERROR;
4944			if (zone->type == dns_zone_key &&
4945			    result == ISC_R_FILENOTFOUND)
4946			{
4947				level = ISC_LOG_DEBUG(1);
4948			}
4949			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4950				      "loading from master file %s failed: %s",
4951				      zone->masterfile,
4952				      isc_result_totext(result));
4953			noprimary = true;
4954		}
4955
4956		if (zone->type != dns_zone_key) {
4957			goto cleanup;
4958		}
4959	}
4960
4961	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4962		      "number of nodes in database: %u",
4963		      dns_db_nodecount(db, dns_dbtree_main));
4964
4965	if (result == DNS_R_SEENINCLUDE) {
4966		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4967	} else {
4968		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4969	}
4970
4971	/*
4972	 * If there's no master file for a key zone, then the zone is new:
4973	 * create an SOA record.  (We do this now, instead of later, so that
4974	 * if there happens to be a journal file, we can roll forward from
4975	 * a sane starting point.)
4976	 */
4977	if (noprimary && zone->type == dns_zone_key) {
4978		result = add_soa(zone, db);
4979		if (result != ISC_R_SUCCESS) {
4980			goto cleanup;
4981		}
4982	}
4983
4984	/*
4985	 * Apply update log, if any, on initial load.
4986	 */
4987	if (zone->journal != NULL &&
4988	    !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4989	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4990	{
4991		result = zone_journal_rollforward(zone, db, &needdump,
4992						  &fixjournal);
4993		if (result != ISC_R_SUCCESS) {
4994			goto cleanup;
4995		}
4996	}
4997
4998	/*
4999	 * Obtain ns, soa and cname counts for top of zone.
5000	 */
5001	INSIST(db != NULL);
5002	result = zone_get_from_db(zone, db, &nscount, &soacount, &soattl,
5003				  &serial, &refresh, &retry, &expire, &minimum,
5004				  &errors);
5005	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
5006		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
5007			      "could not find NS and/or SOA records");
5008	}
5009
5010	/*
5011	 * Process any queued NSEC3PARAM change requests. Only for dynamic
5012	 * zones, an inline-signing zone will perform this action when
5013	 * receiving the secure db (receive_secure_db).
5014	 */
5015	is_dynamic = dns_zone_isdynamic(zone, true);
5016	if (is_dynamic) {
5017		isc_event_t *setnsec3param_event;
5018		dns_zone_t *dummy;
5019
5020		while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
5021			setnsec3param_event =
5022				ISC_LIST_HEAD(zone->setnsec3param_queue);
5023			ISC_LIST_UNLINK(zone->setnsec3param_queue,
5024					setnsec3param_event, ev_link);
5025			dummy = NULL;
5026			zone_iattach(zone, &dummy);
5027			isc_task_send(zone->task, &setnsec3param_event);
5028		}
5029	}
5030
5031	/*
5032	 * Check to make sure the journal is up to date, and remove the
5033	 * journal file if it isn't, as we wouldn't be able to apply
5034	 * updates otherwise.
5035	 */
5036	if (zone->journal != NULL && is_dynamic &&
5037	    !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
5038	{
5039		uint32_t jserial;
5040		dns_journal_t *journal = NULL;
5041		bool empty = false;
5042
5043		result = dns_journal_open(zone->mctx, zone->journal,
5044					  DNS_JOURNAL_READ, &journal);
5045		if (result == ISC_R_SUCCESS) {
5046			jserial = dns_journal_last_serial(journal);
5047			empty = dns_journal_empty(journal);
5048			dns_journal_destroy(&journal);
5049		} else {
5050			jserial = serial;
5051			result = ISC_R_SUCCESS;
5052		}
5053
5054		if (jserial != serial) {
5055			if (!empty) {
5056				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5057					      ISC_LOG_INFO,
5058					      "journal file is out of date: "
5059					      "removing journal file");
5060			}
5061			if (remove(zone->journal) < 0 && errno != ENOENT) {
5062				char strbuf[ISC_STRERRORSIZE];
5063				strerror_r(errno, strbuf, sizeof(strbuf));
5064				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5065					      DNS_LOGMODULE_ZONE,
5066					      ISC_LOG_WARNING,
5067					      "unable to remove journal "
5068					      "'%s': '%s'",
5069					      zone->journal, strbuf);
5070			}
5071		}
5072	}
5073
5074	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
5075		      "loaded; checking validity");
5076
5077	/*
5078	 * Primary / Secondary / Mirror / Stub zones require both NS and SOA
5079	 * records at the top of the zone.
5080	 */
5081
5082	switch (zone->type) {
5083	case dns_zone_dlz:
5084	case dns_zone_primary:
5085	case dns_zone_secondary:
5086	case dns_zone_mirror:
5087	case dns_zone_stub:
5088	case dns_zone_redirect:
5089		if (soacount != 1) {
5090			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5091				      ISC_LOG_ERROR, "has %d SOA records",
5092				      soacount);
5093			result = DNS_R_BADZONE;
5094		}
5095		if (nscount == 0) {
5096			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5097				      ISC_LOG_ERROR, "has no NS records");
5098			result = DNS_R_BADZONE;
5099		}
5100		if (result != ISC_R_SUCCESS) {
5101			goto cleanup;
5102		}
5103		if (zone->type == dns_zone_primary && errors != 0) {
5104			result = DNS_R_BADZONE;
5105			goto cleanup;
5106		}
5107		if (zone->type != dns_zone_stub &&
5108		    zone->type != dns_zone_redirect)
5109		{
5110			result = check_nsec3param(zone, db);
5111			if (result != ISC_R_SUCCESS) {
5112				goto cleanup;
5113			}
5114		}
5115		if (zone->type == dns_zone_primary &&
5116		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
5117		    !integrity_checks(zone, db))
5118		{
5119			result = DNS_R_BADZONE;
5120			goto cleanup;
5121		}
5122		if (zone->type == dns_zone_primary &&
5123		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
5124		    !zone_check_dup(zone, db))
5125		{
5126			result = DNS_R_BADZONE;
5127			goto cleanup;
5128		}
5129
5130		if (zone->type == dns_zone_primary) {
5131			result = dns_zone_cdscheck(zone, db, NULL);
5132			if (result != ISC_R_SUCCESS) {
5133				dns_zone_log(zone, ISC_LOG_ERROR,
5134					     "CDS/CDNSKEY consistency checks "
5135					     "failed");
5136				goto cleanup;
5137			}
5138		}
5139
5140		result = dns_zone_verifydb(zone, db, NULL);
5141		if (result != ISC_R_SUCCESS) {
5142			goto cleanup;
5143		}
5144
5145		if (zone->db != NULL) {
5146			unsigned int oldsoacount;
5147
5148			/*
5149			 * This is checked in zone_replacedb() for
5150			 * secondary zones as they don't reload from disk.
5151			 */
5152			result = zone_get_from_db(
5153				zone, zone->db, NULL, &oldsoacount, NULL,
5154				&oldserial, NULL, NULL, NULL, NULL, NULL);
5155			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5156			RUNTIME_CHECK(oldsoacount > 0U);
5157			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
5158			    !isc_serial_gt(serial, oldserial))
5159			{
5160				uint32_t serialmin, serialmax;
5161
5162				INSIST(zone->type == dns_zone_primary);
5163				INSIST(zone->raw == NULL);
5164
5165				if (serial == oldserial &&
5166				    zone_unchanged(zone->db, db, zone->mctx))
5167				{
5168					dns_zone_logc(zone,
5169						      DNS_LOGCATEGORY_ZONELOAD,
5170						      ISC_LOG_INFO,
5171						      "ixfr-from-differences: "
5172						      "unchanged");
5173					zone->loadtime = loadtime;
5174					goto done;
5175				}
5176
5177				serialmin = (oldserial + 1) & 0xffffffffU;
5178				serialmax = (oldserial + 0x7fffffffU) &
5179					    0xffffffffU;
5180				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5181					      ISC_LOG_ERROR,
5182					      "ixfr-from-differences: "
5183					      "new serial (%u) out of range "
5184					      "[%u - %u]",
5185					      serial, serialmin, serialmax);
5186				result = DNS_R_BADZONE;
5187				goto cleanup;
5188			} else if (!isc_serial_ge(serial, oldserial)) {
5189				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5190					      ISC_LOG_ERROR,
5191					      "zone serial (%u/%u) has gone "
5192					      "backwards",
5193					      serial, oldserial);
5194			} else if (serial == oldserial && !hasinclude &&
5195				   strcmp(zone->db_argv[0], "_builtin") != 0)
5196			{
5197				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5198					      ISC_LOG_ERROR,
5199					      "zone serial (%u) unchanged. "
5200					      "zone may fail to transfer "
5201					      "to secondaries.",
5202					      serial);
5203			}
5204		}
5205
5206		if (zone->type == dns_zone_primary &&
5207		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
5208		    dns_zone_getsigresigninginterval(zone) < (3 * refresh) &&
5209		    dns_db_issecure(db))
5210		{
5211			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5212				      ISC_LOG_WARNING,
5213				      "sig-re-signing-interval less than "
5214				      "3 * refresh.");
5215		}
5216
5217		zone->refresh = RANGE(refresh, zone->minrefresh,
5218				      zone->maxrefresh);
5219		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
5220		zone->expire = RANGE(expire, zone->refresh + zone->retry,
5221				     DNS_MAX_EXPIRE);
5222		zone->soattl = soattl;
5223		zone->minimum = minimum;
5224		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5225
5226		if (zone->type == dns_zone_secondary ||
5227		    zone->type == dns_zone_mirror ||
5228		    zone->type == dns_zone_stub ||
5229		    (zone->type == dns_zone_redirect &&
5230		     zone->primaries != NULL))
5231		{
5232			isc_time_t t;
5233			uint32_t delay;
5234
5235			result = isc_file_getmodtime(zone->journal, &t);
5236			if (result != ISC_R_SUCCESS) {
5237				result = isc_file_getmodtime(zone->masterfile,
5238							     &t);
5239			}
5240			if (result == ISC_R_SUCCESS) {
5241				DNS_ZONE_TIME_ADD(&t, zone->expire,
5242						  &zone->expiretime);
5243			} else {
5244				DNS_ZONE_TIME_ADD(&now, zone->retry,
5245						  &zone->expiretime);
5246			}
5247
5248			delay = (zone->retry -
5249				 isc_random_uniform((zone->retry * 3) / 4));
5250			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
5251			if (isc_time_compare(&zone->refreshtime,
5252					     &zone->expiretime) >= 0)
5253			{
5254				zone->refreshtime = now;
5255			}
5256		}
5257
5258		break;
5259
5260	case dns_zone_key:
5261		/* Nothing needs to be done now */
5262		break;
5263
5264	default:
5265		UNEXPECTED_ERROR("unexpected zone type %d", zone->type);
5266		result = ISC_R_UNEXPECTED;
5267		goto cleanup;
5268	}
5269
5270	/*
5271	 * Check for weak DNSKEY's.
5272	 */
5273	if (zone->type == dns_zone_primary) {
5274		zone_check_dnskeys(zone, db);
5275	}
5276
5277	/*
5278	 * Schedule DNSSEC key refresh.
5279	 */
5280	if (zone->type == dns_zone_primary &&
5281	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
5282	{
5283		zone->refreshkeytime = now;
5284	}
5285
5286	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5287	if (zone->db != NULL) {
5288		had_db = true;
5289		result = zone_replacedb(zone, db, false);
5290		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5291		if (result != ISC_R_SUCCESS) {
5292			goto cleanup;
5293		}
5294	} else {
5295		zone_attachdb(zone, db);
5296		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5297		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED |
5298					       DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
5299		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
5300		    inline_raw(zone))
5301		{
5302			if (zone->secure->db == NULL) {
5303				zone_send_securedb(zone, db);
5304			} else {
5305				zone_send_secureserial(zone, serial);
5306			}
5307		}
5308	}
5309
5310	/*
5311	 * Finished loading inline-signing zone; need to get status
5312	 * from the raw side now.
5313	 */
5314	if (zone->type == dns_zone_primary && inline_secure(zone)) {
5315		maybe_send_secure(zone);
5316	}
5317
5318	result = ISC_R_SUCCESS;
5319
5320	if (fixjournal) {
5321		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
5322		zone_journal_compact(zone, zone->db, 0);
5323	}
5324	if (needdump) {
5325		if (zone->type == dns_zone_key) {
5326			zone_needdump(zone, 30);
5327		} else {
5328			zone_needdump(zone, DNS_DUMP_DELAY);
5329		}
5330	}
5331
5332	if (zone->task != NULL) {
5333		if (zone->type == dns_zone_primary) {
5334			set_resigntime(zone);
5335			resume_signingwithkey(zone);
5336			resume_addnsec3chain(zone);
5337		}
5338
5339		is_dynamic = dns_zone_isdynamic(zone, false);
5340		if (zone->type == dns_zone_primary &&
5341		    !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
5342		    is_dynamic && dns_db_issecure(db) && !inline_raw(zone))
5343		{
5344			dns_name_t *name;
5345			dns_fixedname_t fixed;
5346			dns_rdataset_t next;
5347
5348			dns_rdataset_init(&next);
5349			name = dns_fixedname_initname(&fixed);
5350
5351			result = dns_db_getsigningtime(db, &next, name);
5352			if (result == ISC_R_SUCCESS) {
5353				isc_stdtime_t timenow;
5354				char namebuf[DNS_NAME_FORMATSIZE];
5355				char typebuf[DNS_RDATATYPE_FORMATSIZE];
5356
5357				isc_stdtime_get(&timenow);
5358				dns_name_format(name, namebuf, sizeof(namebuf));
5359				dns_rdatatype_format(next.covers, typebuf,
5360						     sizeof(typebuf));
5361				dnssec_log(
5362					zone, ISC_LOG_DEBUG(3),
5363					"next resign: %s/%s "
5364					"in %d seconds",
5365					namebuf, typebuf,
5366					next.resign - timenow -
5367						dns_zone_getsigresigninginterval(
5368							zone));
5369				dns_rdataset_disassociate(&next);
5370			} else {
5371				dnssec_log(zone, ISC_LOG_WARNING,
5372					   "signed dynamic zone has no "
5373					   "resign event scheduled");
5374			}
5375		}
5376
5377		zone_settimer(zone, &now);
5378	}
5379
5380	/*
5381	 * Clear old include list.
5382	 */
5383	for (inc = ISC_LIST_HEAD(zone->includes); inc != NULL;
5384	     inc = ISC_LIST_HEAD(zone->includes))
5385	{
5386		ISC_LIST_UNLINK(zone->includes, inc, link);
5387		isc_mem_free(zone->mctx, inc->name);
5388		isc_mem_put(zone->mctx, inc, sizeof(*inc));
5389	}
5390	zone->nincludes = 0;
5391
5392	/*
5393	 * Transfer new include list.
5394	 */
5395	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5396	     inc = ISC_LIST_HEAD(zone->newincludes))
5397	{
5398		ISC_LIST_UNLINK(zone->newincludes, inc, link);
5399		ISC_LIST_APPEND(zone->includes, inc, link);
5400		zone->nincludes++;
5401	}
5402
5403	if (!dns_db_ispersistent(db)) {
5404		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5405			      "loaded serial %u%s", serial,
5406			      dns_db_issecure(db) ? " (DNSSEC signed)" : "");
5407	}
5408
5409	if (!had_db && zone->type == dns_zone_mirror) {
5410		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5411			      "mirror zone is now in use");
5412	}
5413
5414	zone->loadtime = loadtime;
5415	goto done;
5416
5417cleanup:
5418	if (result != ISC_R_SUCCESS) {
5419		dns_zone_rpz_disable_db(zone, db);
5420		dns_zone_catz_disable_db(zone, db);
5421	}
5422
5423	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5424	     inc = ISC_LIST_HEAD(zone->newincludes))
5425	{
5426		ISC_LIST_UNLINK(zone->newincludes, inc, link);
5427		isc_mem_free(zone->mctx, inc->name);
5428		isc_mem_put(zone->mctx, inc, sizeof(*inc));
5429	}
5430	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
5431	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
5432	    (zone->type == dns_zone_redirect && zone->primaries != NULL))
5433	{
5434		if (result != ISC_R_NOMEMORY) {
5435			if (zone->journal != NULL) {
5436				zone_saveunique(zone, zone->journal,
5437						"jn-XXXXXXXX");
5438			}
5439			if (zone->masterfile != NULL) {
5440				zone_saveunique(zone, zone->masterfile,
5441						"db-XXXXXXXX");
5442			}
5443		}
5444
5445		/* Mark the zone for immediate refresh. */
5446		zone->refreshtime = now;
5447		if (zone->task != NULL) {
5448			zone_settimer(zone, &now);
5449		}
5450		result = ISC_R_SUCCESS;
5451	} else if (zone->type == dns_zone_primary ||
5452		   zone->type == dns_zone_redirect)
5453	{
5454		if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5455			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5456				      ISC_LOG_ERROR,
5457				      "not loaded due to errors.");
5458		} else if (zone->type == dns_zone_primary) {
5459			result = ISC_R_SUCCESS;
5460		}
5461	}
5462
5463done:
5464	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5465	/*
5466	 * If this is an inline-signed zone and we were called for the raw
5467	 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5468	 * as well, but only if this is a reload, not an initial zone load: in
5469	 * the former case, zone_postload() will not be run for the secure
5470	 * zone; in the latter case, it will be.  Check which case we are
5471	 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5472	 * secure zone: if it is set, this must be a reload.
5473	 */
5474	if (inline_raw(zone) && DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5475	{
5476		DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5477		/*
5478		 * Re-start zone maintenance if it had been stalled
5479		 * due to DNS_ZONEFLG_LOADPENDING being set when
5480		 * zone_maintenance was called.
5481		 */
5482		if (zone->secure->task != NULL) {
5483			zone_settimer(zone->secure, &now);
5484		}
5485	}
5486
5487	zone_debuglog(zone, "zone_postload", 99, "done");
5488
5489	return (result);
5490}
5491
5492static bool
5493exit_check(dns_zone_t *zone) {
5494	REQUIRE(LOCKED_ZONE(zone));
5495
5496	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
5497	    isc_refcount_current(&zone->irefs) == 0)
5498	{
5499		/*
5500		 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
5501		 */
5502		INSIST(isc_refcount_current(&zone->erefs) == 0);
5503		return (true);
5504	}
5505	return (false);
5506}
5507
5508static bool
5509zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5510	      dns_name_t *name, bool logit) {
5511	isc_result_t result;
5512	char namebuf[DNS_NAME_FORMATSIZE];
5513	char altbuf[DNS_NAME_FORMATSIZE];
5514	dns_fixedname_t fixed;
5515	dns_name_t *foundname;
5516	int level;
5517
5518	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) {
5519		return (true);
5520	}
5521
5522	if (zone->type == dns_zone_primary) {
5523		level = ISC_LOG_ERROR;
5524	} else {
5525		level = ISC_LOG_WARNING;
5526	}
5527
5528	foundname = dns_fixedname_initname(&fixed);
5529
5530	result = dns_db_find(db, name, version, dns_rdatatype_a, 0, 0, NULL,
5531			     foundname, NULL, NULL);
5532	if (result == ISC_R_SUCCESS) {
5533		return (true);
5534	}
5535
5536	if (result == DNS_R_NXRRSET) {
5537		result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0,
5538				     0, NULL, foundname, NULL, NULL);
5539		if (result == ISC_R_SUCCESS) {
5540			return (true);
5541		}
5542	}
5543
5544	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5545	    result == DNS_R_EMPTYNAME)
5546	{
5547		if (logit) {
5548			dns_name_format(name, namebuf, sizeof namebuf);
5549			dns_zone_log(zone, level,
5550				     "NS '%s' has no address "
5551				     "records (A or AAAA)",
5552				     namebuf);
5553		}
5554		return (false);
5555	}
5556
5557	if (result == DNS_R_CNAME) {
5558		if (logit) {
5559			dns_name_format(name, namebuf, sizeof namebuf);
5560			dns_zone_log(zone, level,
5561				     "NS '%s' is a CNAME "
5562				     "(illegal)",
5563				     namebuf);
5564		}
5565		return (false);
5566	}
5567
5568	if (result == DNS_R_DNAME) {
5569		if (logit) {
5570			dns_name_format(name, namebuf, sizeof namebuf);
5571			dns_name_format(foundname, altbuf, sizeof altbuf);
5572			dns_zone_log(zone, level,
5573				     "NS '%s' is below a DNAME "
5574				     "'%s' (illegal)",
5575				     namebuf, altbuf);
5576		}
5577		return (false);
5578	}
5579
5580	return (true);
5581}
5582
5583static isc_result_t
5584zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5585		 dns_dbversion_t *version, unsigned int *nscount,
5586		 unsigned int *errors, bool logit) {
5587	isc_result_t result;
5588	unsigned int count = 0;
5589	unsigned int ecount = 0;
5590	dns_rdataset_t rdataset;
5591	dns_rdata_t rdata;
5592	dns_rdata_ns_t ns;
5593
5594	dns_rdataset_init(&rdataset);
5595	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5596				     dns_rdatatype_none, 0, &rdataset, NULL);
5597	if (result == ISC_R_NOTFOUND) {
5598		INSIST(!dns_rdataset_isassociated(&rdataset));
5599		goto success;
5600	}
5601	if (result != ISC_R_SUCCESS) {
5602		INSIST(!dns_rdataset_isassociated(&rdataset));
5603		goto invalidate_rdataset;
5604	}
5605
5606	result = dns_rdataset_first(&rdataset);
5607	while (result == ISC_R_SUCCESS) {
5608		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5609		    (zone->type == dns_zone_primary ||
5610		     zone->type == dns_zone_secondary ||
5611		     zone->type == dns_zone_mirror))
5612		{
5613			dns_rdata_init(&rdata);
5614			dns_rdataset_current(&rdataset, &rdata);
5615			result = dns_rdata_tostruct(&rdata, &ns, NULL);
5616			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5617			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5618			    !zone_check_ns(zone, db, version, &ns.name, logit))
5619			{
5620				ecount++;
5621			}
5622		}
5623		count++;
5624		result = dns_rdataset_next(&rdataset);
5625	}
5626	dns_rdataset_disassociate(&rdataset);
5627
5628success:
5629	if (nscount != NULL) {
5630		*nscount = count;
5631	}
5632	if (errors != NULL) {
5633		*errors = ecount;
5634	}
5635
5636	result = ISC_R_SUCCESS;
5637
5638invalidate_rdataset:
5639	dns_rdataset_invalidate(&rdataset);
5640
5641	return (result);
5642}
5643
5644#define SET_IF_NOT_NULL(obj, val) \
5645	if (obj != NULL) {        \
5646		*obj = val;       \
5647	}
5648
5649#define SET_SOA_VALUES(soattl_v, serial_v, refresh_v, retry_v, expire_v, \
5650		       minimum_v)                                        \
5651	{                                                                \
5652		SET_IF_NOT_NULL(soattl, soattl_v);                       \
5653		SET_IF_NOT_NULL(serial, serial_v);                       \
5654		SET_IF_NOT_NULL(refresh, refresh_v);                     \
5655		SET_IF_NOT_NULL(retry, retry_v);                         \
5656		SET_IF_NOT_NULL(expire, expire_v);                       \
5657		SET_IF_NOT_NULL(minimum, minimum_v);                     \
5658	}
5659
5660#define CLR_SOA_VALUES()                          \
5661	{                                         \
5662		SET_SOA_VALUES(0, 0, 0, 0, 0, 0); \
5663	}
5664
5665static isc_result_t
5666zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5667		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5668		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5669		 uint32_t *minimum) {
5670	isc_result_t result;
5671	unsigned int count = 0;
5672	dns_rdataset_t rdataset;
5673	dns_rdata_t rdata = DNS_RDATA_INIT;
5674
5675	dns_rdataset_init(&rdataset);
5676	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5677				     dns_rdatatype_none, 0, &rdataset, NULL);
5678	if (result == ISC_R_NOTFOUND) {
5679		INSIST(!dns_rdataset_isassociated(&rdataset));
5680		result = ISC_R_SUCCESS;
5681		goto invalidate_rdataset;
5682	}
5683	if (result != ISC_R_SUCCESS) {
5684		INSIST(!dns_rdataset_isassociated(&rdataset));
5685		goto invalidate_rdataset;
5686	}
5687
5688	result = dns_rdataset_first(&rdataset);
5689	while (result == ISC_R_SUCCESS) {
5690		dns_rdata_init(&rdata);
5691		dns_rdataset_current(&rdataset, &rdata);
5692		count++;
5693		if (count == 1) {
5694			dns_rdata_soa_t soa;
5695			result = dns_rdata_tostruct(&rdata, &soa, NULL);
5696			SET_SOA_VALUES(rdataset.ttl, soa.serial, soa.refresh,
5697				       soa.retry, soa.expire, soa.minimum);
5698			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5699		}
5700
5701		result = dns_rdataset_next(&rdataset);
5702		dns_rdata_reset(&rdata);
5703	}
5704	dns_rdataset_disassociate(&rdataset);
5705
5706	result = ISC_R_SUCCESS;
5707
5708invalidate_rdataset:
5709	SET_IF_NOT_NULL(soacount, count);
5710	if (count == 0) {
5711		CLR_SOA_VALUES();
5712	}
5713
5714	dns_rdataset_invalidate(&rdataset);
5715
5716	return (result);
5717}
5718
5719/*
5720 * zone must be locked.
5721 */
5722static isc_result_t
5723zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5724		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5725		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5726		 uint32_t *minimum, unsigned int *errors) {
5727	isc_result_t result;
5728	isc_result_t answer = ISC_R_SUCCESS;
5729	dns_dbversion_t *version = NULL;
5730	dns_dbnode_t *node;
5731
5732	REQUIRE(db != NULL);
5733	REQUIRE(zone != NULL);
5734
5735	dns_db_currentversion(db, &version);
5736
5737	SET_IF_NOT_NULL(nscount, 0);
5738	SET_IF_NOT_NULL(soacount, 0);
5739	SET_IF_NOT_NULL(errors, 0);
5740	CLR_SOA_VALUES();
5741
5742	node = NULL;
5743	result = dns_db_findnode(db, &zone->origin, false, &node);
5744	if (result != ISC_R_SUCCESS) {
5745		answer = result;
5746		goto closeversion;
5747	}
5748
5749	if (nscount != NULL || errors != NULL) {
5750		result = zone_count_ns_rr(zone, db, node, version, nscount,
5751					  errors, true);
5752		if (result != ISC_R_SUCCESS) {
5753			answer = result;
5754		}
5755	}
5756
5757	if (soacount != NULL || soattl != NULL || serial != NULL ||
5758	    refresh != NULL || retry != NULL || expire != NULL ||
5759	    minimum != NULL)
5760	{
5761		result = zone_load_soa_rr(db, node, version, soacount, soattl,
5762					  serial, refresh, retry, expire,
5763					  minimum);
5764		if (result != ISC_R_SUCCESS) {
5765			answer = result;
5766		}
5767	}
5768
5769	dns_db_detachnode(db, &node);
5770closeversion:
5771	dns_db_closeversion(db, &version, false);
5772
5773	return (answer);
5774}
5775
5776void
5777dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5778	REQUIRE(DNS_ZONE_VALID(source));
5779	REQUIRE(target != NULL && *target == NULL);
5780	isc_refcount_increment(&source->erefs);
5781	*target = source;
5782}
5783
5784void
5785dns_zone_detach(dns_zone_t **zonep) {
5786	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5787
5788	dns_zone_t *zone = *zonep;
5789	*zonep = NULL;
5790
5791	if (isc_refcount_decrement(&zone->erefs) == 1) {
5792		isc_event_t *ev = &zone->ctlevent;
5793
5794		isc_refcount_destroy(&zone->erefs);
5795
5796		/*
5797		 * Stop things being restarted after we cancel them below.
5798		 */
5799		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
5800		dns_zone_log(zone, ISC_LOG_DEBUG(1),
5801			     "final reference detached");
5802		if (zone->task != NULL) {
5803			/*
5804			 * This zone has a task; it can clean
5805			 * itself up asynchronously.
5806			 */
5807			isc_task_send(zone->task, &ev);
5808			return;
5809		}
5810
5811		/*
5812		 * This zone is unmanaged; we're probably running in
5813		 * named-checkzone or a unit test. There's no task,
5814		 * so we need to free it immediately.
5815		 *
5816		 * Unmanaged zones must not have null views; we have no way
5817		 * of detaching from the view here without causing deadlock
5818		 * because this code is called with the view already
5819		 * locked.
5820		 */
5821		INSIST(zone->view == NULL);
5822
5823		zone_shutdown(zone->task, ev);
5824		ev = NULL;
5825	}
5826}
5827
5828void
5829dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5830	REQUIRE(DNS_ZONE_VALID(source));
5831
5832	LOCK_ZONE(source);
5833	zone_iattach(source, target);
5834	UNLOCK_ZONE(source);
5835}
5836
5837static void
5838zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5839	REQUIRE(DNS_ZONE_VALID(source));
5840	REQUIRE(LOCKED_ZONE(source));
5841	REQUIRE(target != NULL && *target == NULL);
5842	INSIST(isc_refcount_increment0(&source->irefs) +
5843		       isc_refcount_current(&source->erefs) >
5844	       0);
5845	*target = source;
5846}
5847
5848static void
5849zone_idetach(dns_zone_t **zonep) {
5850	dns_zone_t *zone;
5851
5852	/*
5853	 * 'zone' locked by caller.
5854	 */
5855	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5856	REQUIRE(LOCKED_ZONE(*zonep));
5857
5858	zone = *zonep;
5859	*zonep = NULL;
5860
5861	INSIST(isc_refcount_decrement(&zone->irefs) - 1 +
5862		       isc_refcount_current(&zone->erefs) >
5863	       0);
5864}
5865
5866void
5867dns_zone_idetach(dns_zone_t **zonep) {
5868	dns_zone_t *zone;
5869
5870	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5871
5872	zone = *zonep;
5873	*zonep = NULL;
5874
5875	if (isc_refcount_decrement(&zone->irefs) == 1) {
5876		bool free_needed;
5877		LOCK_ZONE(zone);
5878		free_needed = exit_check(zone);
5879		UNLOCK_ZONE(zone);
5880		if (free_needed) {
5881			zone_free(zone);
5882		}
5883	}
5884}
5885
5886isc_mem_t *
5887dns_zone_getmctx(dns_zone_t *zone) {
5888	REQUIRE(DNS_ZONE_VALID(zone));
5889
5890	return (zone->mctx);
5891}
5892
5893dns_zonemgr_t *
5894dns_zone_getmgr(dns_zone_t *zone) {
5895	REQUIRE(DNS_ZONE_VALID(zone));
5896
5897	return (zone->zmgr);
5898}
5899
5900void
5901dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
5902	REQUIRE(DNS_ZONE_VALID(zone));
5903
5904	LOCK_ZONE(zone);
5905	if (zone->kasp != NULL) {
5906		dns_kasp_detach(&zone->kasp);
5907	}
5908	if (kasp != NULL) {
5909		dns_kasp_attach(kasp, &zone->kasp);
5910	}
5911	UNLOCK_ZONE(zone);
5912}
5913
5914dns_kasp_t *
5915dns_zone_getkasp(dns_zone_t *zone) {
5916	REQUIRE(DNS_ZONE_VALID(zone));
5917
5918	return (zone->kasp);
5919}
5920
5921void
5922dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
5923	REQUIRE(DNS_ZONE_VALID(zone));
5924
5925	if (value) {
5926		DNS_ZONE_SETOPTION(zone, option);
5927	} else {
5928		DNS_ZONE_CLROPTION(zone, option);
5929	}
5930}
5931
5932dns_zoneopt_t
5933dns_zone_getoptions(dns_zone_t *zone) {
5934	REQUIRE(DNS_ZONE_VALID(zone));
5935
5936	return (atomic_load_relaxed(&zone->options));
5937}
5938
5939void
5940dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value) {
5941	REQUIRE(DNS_ZONE_VALID(zone));
5942
5943	if (value) {
5944		DNS_ZONEKEY_SETOPTION(zone, keyopt);
5945	} else {
5946		DNS_ZONEKEY_CLROPTION(zone, keyopt);
5947	}
5948}
5949
5950unsigned int
5951dns_zone_getkeyopts(dns_zone_t *zone) {
5952	REQUIRE(DNS_ZONE_VALID(zone));
5953
5954	return (atomic_load_relaxed(&zone->keyopts));
5955}
5956
5957isc_result_t
5958dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5959	REQUIRE(DNS_ZONE_VALID(zone));
5960
5961	LOCK_ZONE(zone);
5962	zone->xfrsource4 = *xfrsource;
5963	UNLOCK_ZONE(zone);
5964
5965	return (ISC_R_SUCCESS);
5966}
5967
5968isc_sockaddr_t *
5969dns_zone_getxfrsource4(dns_zone_t *zone) {
5970	REQUIRE(DNS_ZONE_VALID(zone));
5971	return (&zone->xfrsource4);
5972}
5973
5974isc_result_t
5975dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5976	REQUIRE(DNS_ZONE_VALID(zone));
5977
5978	LOCK_ZONE(zone);
5979	zone->xfrsource6 = *xfrsource;
5980	UNLOCK_ZONE(zone);
5981
5982	return (ISC_R_SUCCESS);
5983}
5984
5985isc_sockaddr_t *
5986dns_zone_getxfrsource6(dns_zone_t *zone) {
5987	REQUIRE(DNS_ZONE_VALID(zone));
5988	return (&zone->xfrsource6);
5989}
5990
5991isc_result_t
5992dns_zone_setaltxfrsource4(dns_zone_t *zone,
5993			  const isc_sockaddr_t *altxfrsource) {
5994	REQUIRE(DNS_ZONE_VALID(zone));
5995
5996	LOCK_ZONE(zone);
5997	zone->altxfrsource4 = *altxfrsource;
5998	UNLOCK_ZONE(zone);
5999
6000	return (ISC_R_SUCCESS);
6001}
6002
6003isc_sockaddr_t *
6004dns_zone_getaltxfrsource4(dns_zone_t *zone) {
6005	REQUIRE(DNS_ZONE_VALID(zone));
6006	return (&zone->altxfrsource4);
6007}
6008
6009isc_result_t
6010dns_zone_setaltxfrsource6(dns_zone_t *zone,
6011			  const isc_sockaddr_t *altxfrsource) {
6012	REQUIRE(DNS_ZONE_VALID(zone));
6013
6014	LOCK_ZONE(zone);
6015	zone->altxfrsource6 = *altxfrsource;
6016	UNLOCK_ZONE(zone);
6017
6018	return (ISC_R_SUCCESS);
6019}
6020
6021isc_sockaddr_t *
6022dns_zone_getaltxfrsource6(dns_zone_t *zone) {
6023	REQUIRE(DNS_ZONE_VALID(zone));
6024	return (&zone->altxfrsource6);
6025}
6026
6027isc_result_t
6028dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6029	REQUIRE(DNS_ZONE_VALID(zone));
6030
6031	LOCK_ZONE(zone);
6032	zone->parentalsrc4 = *parentalsrc;
6033	UNLOCK_ZONE(zone);
6034
6035	return (ISC_R_SUCCESS);
6036}
6037
6038isc_sockaddr_t *
6039dns_zone_getparentalsrc4(dns_zone_t *zone) {
6040	REQUIRE(DNS_ZONE_VALID(zone));
6041	return (&zone->parentalsrc4);
6042}
6043
6044isc_result_t
6045dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6046	REQUIRE(DNS_ZONE_VALID(zone));
6047
6048	LOCK_ZONE(zone);
6049	zone->parentalsrc6 = *parentalsrc;
6050	UNLOCK_ZONE(zone);
6051
6052	return (ISC_R_SUCCESS);
6053}
6054
6055isc_sockaddr_t *
6056dns_zone_getparentalsrc6(dns_zone_t *zone) {
6057	REQUIRE(DNS_ZONE_VALID(zone));
6058	return (&zone->parentalsrc6);
6059}
6060
6061isc_result_t
6062dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6063	REQUIRE(DNS_ZONE_VALID(zone));
6064
6065	LOCK_ZONE(zone);
6066	zone->notifysrc4 = *notifysrc;
6067	UNLOCK_ZONE(zone);
6068
6069	return (ISC_R_SUCCESS);
6070}
6071
6072isc_sockaddr_t *
6073dns_zone_getnotifysrc4(dns_zone_t *zone) {
6074	REQUIRE(DNS_ZONE_VALID(zone));
6075	return (&zone->notifysrc4);
6076}
6077
6078isc_result_t
6079dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6080	REQUIRE(DNS_ZONE_VALID(zone));
6081
6082	LOCK_ZONE(zone);
6083	zone->notifysrc6 = *notifysrc;
6084	UNLOCK_ZONE(zone);
6085
6086	return (ISC_R_SUCCESS);
6087}
6088
6089isc_sockaddr_t *
6090dns_zone_getnotifysrc6(dns_zone_t *zone) {
6091	REQUIRE(DNS_ZONE_VALID(zone));
6092	return (&zone->notifysrc6);
6093}
6094
6095static bool
6096same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
6097	   uint32_t count) {
6098	unsigned int i;
6099
6100	for (i = 0; i < count; i++) {
6101		if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) {
6102			return (false);
6103		}
6104	}
6105	return (true);
6106}
6107
6108static bool
6109same_names(dns_name_t *const *oldlist, dns_name_t *const *newlist,
6110	   uint32_t count) {
6111	unsigned int i;
6112
6113	if (oldlist == NULL && newlist == NULL) {
6114		return (true);
6115	}
6116	if (oldlist == NULL || newlist == NULL) {
6117		return (false);
6118	}
6119
6120	for (i = 0; i < count; i++) {
6121		if (oldlist[i] == NULL && newlist[i] == NULL) {
6122			continue;
6123		}
6124		if (oldlist[i] == NULL || newlist[i] == NULL ||
6125		    !dns_name_equal(oldlist[i], newlist[i]))
6126		{
6127			return (false);
6128		}
6129	}
6130	return (true);
6131}
6132
6133static void
6134clear_serverslist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
6135		  dns_name_t ***tlsnamesp, unsigned int *countp,
6136		  isc_mem_t *mctx) {
6137	unsigned int count;
6138	isc_sockaddr_t *addrs;
6139	dns_name_t **keynames;
6140	dns_name_t **tlsnames;
6141
6142	REQUIRE(countp != NULL);
6143	REQUIRE(addrsp != NULL);
6144	REQUIRE(keynamesp != NULL);
6145	REQUIRE(tlsnamesp != NULL);
6146
6147	count = *countp;
6148	*countp = 0;
6149	addrs = *addrsp;
6150	*addrsp = NULL;
6151	keynames = *keynamesp;
6152	*keynamesp = NULL;
6153	tlsnames = *tlsnamesp;
6154	*tlsnamesp = NULL;
6155
6156	if (addrs != NULL) {
6157		isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
6158	}
6159
6160	if (keynames != NULL) {
6161		unsigned int i;
6162		for (i = 0; i < count; i++) {
6163			if (keynames[i] != NULL) {
6164				dns_name_free(keynames[i], mctx);
6165				isc_mem_put(mctx, keynames[i],
6166					    sizeof(dns_name_t));
6167				keynames[i] = NULL;
6168			}
6169		}
6170		isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
6171	}
6172
6173	if (tlsnames != NULL) {
6174		unsigned int i;
6175		for (i = 0; i < count; i++) {
6176			if (tlsnames[i] != NULL) {
6177				dns_name_free(tlsnames[i], mctx);
6178				isc_mem_put(mctx, tlsnames[i],
6179					    sizeof(dns_name_t));
6180				tlsnames[i] = NULL;
6181			}
6182		}
6183		isc_mem_put(mctx, tlsnames, count * sizeof(dns_name_t *));
6184	}
6185}
6186
6187static void
6188set_serverslist(unsigned int count, const isc_sockaddr_t *addrs,
6189		isc_sockaddr_t **newaddrsp, dns_name_t **keynames,
6190		dns_name_t ***newkeynamesp, dns_name_t **tlsnames,
6191		dns_name_t ***newtlsnamesp, isc_mem_t *mctx) {
6192	isc_sockaddr_t *newaddrs = NULL;
6193	dns_name_t **newkeynames = NULL;
6194	dns_name_t **newtlsnames = NULL;
6195	unsigned int i;
6196
6197	REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
6198	REQUIRE(newkeynamesp != NULL && *newkeynamesp == NULL);
6199	REQUIRE(newtlsnamesp != NULL && *newtlsnamesp == NULL);
6200
6201	newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
6202	memmove(newaddrs, addrs, count * sizeof(*newaddrs));
6203
6204	if (keynames != NULL) {
6205		newkeynames = isc_mem_get(mctx, count * sizeof(*newkeynames));
6206		for (i = 0; i < count; i++) {
6207			newkeynames[i] = NULL;
6208		}
6209		for (i = 0; i < count; i++) {
6210			if (keynames[i] != NULL) {
6211				newkeynames[i] =
6212					isc_mem_get(mctx, sizeof(dns_name_t));
6213				dns_name_init(newkeynames[i], NULL);
6214				dns_name_dup(keynames[i], mctx, newkeynames[i]);
6215			}
6216		}
6217	}
6218
6219	if (tlsnames != NULL) {
6220		newtlsnames = isc_mem_get(mctx, count * sizeof(*newtlsnames));
6221		for (i = 0; i < count; i++) {
6222			newtlsnames[i] = NULL;
6223		}
6224		for (i = 0; i < count; i++) {
6225			if (tlsnames[i] != NULL) {
6226				newtlsnames[i] =
6227					isc_mem_get(mctx, sizeof(dns_name_t));
6228				dns_name_init(newtlsnames[i], NULL);
6229				dns_name_dup(tlsnames[i], mctx, newtlsnames[i]);
6230			}
6231		}
6232	}
6233
6234	*newaddrsp = newaddrs;
6235	*newkeynamesp = newkeynames;
6236	*newtlsnamesp = newtlsnames;
6237}
6238
6239void
6240dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
6241		       dns_name_t **keynames, dns_name_t **tlsnames,
6242		       uint32_t count) {
6243	isc_sockaddr_t *newaddrs = NULL;
6244	dns_name_t **newkeynames = NULL;
6245	dns_name_t **newtlsnames = NULL;
6246
6247	REQUIRE(DNS_ZONE_VALID(zone));
6248	REQUIRE(count == 0 || notify != NULL);
6249	if (keynames != NULL) {
6250		REQUIRE(count != 0);
6251	}
6252
6253	LOCK_ZONE(zone);
6254
6255	if (count == zone->notifycnt &&
6256	    same_addrs(zone->notify, notify, count) &&
6257	    same_names(zone->notifykeynames, keynames, count) &&
6258	    same_names(zone->notifytlsnames, tlsnames, count))
6259	{
6260		goto unlock;
6261	}
6262
6263	clear_serverslist(&zone->notify, &zone->notifykeynames,
6264			  &zone->notifytlsnames, &zone->notifycnt, zone->mctx);
6265
6266	if (count == 0) {
6267		goto unlock;
6268	}
6269
6270	/*
6271	 * Set up the notify and notifykey lists
6272	 */
6273	set_serverslist(count, notify, &newaddrs, keynames, &newkeynames,
6274			tlsnames, &newtlsnames, zone->mctx);
6275
6276	/*
6277	 * Everything is ok so attach to the zone.
6278	 */
6279	zone->notify = newaddrs;
6280	zone->notifykeynames = newkeynames;
6281	zone->notifytlsnames = newtlsnames;
6282	zone->notifycnt = count;
6283unlock:
6284	UNLOCK_ZONE(zone);
6285}
6286
6287void
6288dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *primaries,
6289		      dns_name_t **keynames, dns_name_t **tlsnames,
6290		      uint32_t count) {
6291	isc_sockaddr_t *newaddrs = NULL;
6292	dns_name_t **newkeynames = NULL;
6293	dns_name_t **newtlsnames = NULL;
6294	bool *newok;
6295	unsigned int i;
6296
6297	REQUIRE(DNS_ZONE_VALID(zone));
6298	REQUIRE(count == 0 || primaries != NULL);
6299	if (keynames != NULL || tlsnames != NULL) {
6300		REQUIRE(count != 0);
6301	}
6302
6303	LOCK_ZONE(zone);
6304	/*
6305	 * The refresh code assumes that 'primaries' wouldn't change under it.
6306	 * If it will change then kill off any current refresh in progress
6307	 * and update the primaries info.  If it won't change then we can just
6308	 * unlock and exit.
6309	 */
6310	if (count != zone->primariescnt ||
6311	    !same_addrs(zone->primaries, primaries, count) ||
6312	    !same_names(zone->primarykeynames, keynames, count) ||
6313	    !same_names(zone->primarytlsnames, tlsnames, count))
6314	{
6315		if (zone->request != NULL) {
6316			dns_request_cancel(zone->request);
6317		}
6318	} else {
6319		goto unlock;
6320	}
6321
6322	/*
6323	 * This needs to happen before clear_addresskeylist() sets
6324	 * zone->primariescnt to 0:
6325	 */
6326	if (zone->primariesok != NULL) {
6327		isc_mem_put(zone->mctx, zone->primariesok,
6328			    zone->primariescnt * sizeof(bool));
6329		zone->primariesok = NULL;
6330	}
6331	clear_serverslist(&zone->primaries, &zone->primarykeynames,
6332			  &zone->primarytlsnames, &zone->primariescnt,
6333			  zone->mctx);
6334	/*
6335	 * If count == 0, don't allocate any space for primaries, primariesok or
6336	 * keynames so internally, those pointers are NULL if count == 0
6337	 */
6338	if (count == 0) {
6339		goto unlock;
6340	}
6341
6342	/*
6343	 * primariesok must contain count elements
6344	 */
6345	newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
6346	for (i = 0; i < count; i++) {
6347		newok[i] = false;
6348	}
6349
6350	/*
6351	 * Now set up the primaries and primary key lists
6352	 */
6353	set_serverslist(count, primaries, &newaddrs, keynames, &newkeynames,
6354			tlsnames, &newtlsnames, zone->mctx);
6355
6356	/*
6357	 * Everything is ok so attach to the zone.
6358	 */
6359	zone->curprimary = 0;
6360	zone->primariesok = newok;
6361	zone->primaries = newaddrs;
6362	zone->primarykeynames = newkeynames;
6363	zone->primarytlsnames = newtlsnames;
6364	zone->primariescnt = count;
6365	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
6366
6367unlock:
6368	UNLOCK_ZONE(zone);
6369}
6370
6371void
6372dns_zone_setparentals(dns_zone_t *zone, const isc_sockaddr_t *parentals,
6373		      dns_name_t **keynames, dns_name_t **tlsnames,
6374		      uint32_t count) {
6375	isc_sockaddr_t *newaddrs = NULL;
6376	dns_name_t **newkeynames = NULL;
6377	dns_name_t **newtlsnames = NULL;
6378
6379	REQUIRE(DNS_ZONE_VALID(zone));
6380	REQUIRE(count == 0 || parentals != NULL);
6381	if (keynames != NULL || tlsnames != NULL) {
6382		REQUIRE(count != 0);
6383	}
6384
6385	LOCK_ZONE(zone);
6386
6387	clear_serverslist(&zone->parentals, &zone->parentalkeynames,
6388			  &zone->parentaltlsnames, &zone->parentalscnt,
6389			  zone->mctx);
6390	/*
6391	 * If count == 0, don't allocate any space for parentals, or keynames
6392	 * so internally, those pointers are NULL if count == 0
6393	 */
6394	if (count == 0) {
6395		goto unlock;
6396	}
6397
6398	/*
6399	 * Now set up the parentals and parental key lists
6400	 */
6401	set_serverslist(count, parentals, &newaddrs, keynames, &newkeynames,
6402			tlsnames, &newtlsnames, zone->mctx);
6403
6404	/*
6405	 * Everything is ok so attach to the zone.
6406	 */
6407	zone->parentals = newaddrs;
6408	zone->parentalkeynames = newkeynames;
6409	zone->parentaltlsnames = newtlsnames;
6410	zone->parentalscnt = count;
6411
6412	dns_zone_log(zone, ISC_LOG_NOTICE, "checkds: set %u parentals", count);
6413
6414unlock:
6415	UNLOCK_ZONE(zone);
6416}
6417
6418isc_result_t
6419dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6420	isc_result_t result = ISC_R_SUCCESS;
6421
6422	REQUIRE(DNS_ZONE_VALID(zone));
6423
6424	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6425	if (zone->db == NULL) {
6426		result = DNS_R_NOTLOADED;
6427	} else {
6428		dns_db_attach(zone->db, dpb);
6429	}
6430	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6431
6432	return (result);
6433}
6434
6435void
6436dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6437	REQUIRE(DNS_ZONE_VALID(zone));
6438	REQUIRE(zone->type == dns_zone_staticstub);
6439
6440	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6441	REQUIRE(zone->db == NULL);
6442	dns_db_attach(db, &zone->db);
6443	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6444}
6445
6446/*
6447 * Coordinates the starting of routine jobs.
6448 */
6449void
6450dns_zone_maintenance(dns_zone_t *zone) {
6451	const char me[] = "dns_zone_maintenance";
6452	isc_time_t now;
6453
6454	REQUIRE(DNS_ZONE_VALID(zone));
6455	ENTER;
6456
6457	LOCK_ZONE(zone);
6458	TIME_NOW(&now);
6459	zone_settimer(zone, &now);
6460	UNLOCK_ZONE(zone);
6461}
6462
6463static bool
6464was_dumping(dns_zone_t *zone) {
6465	REQUIRE(LOCKED_ZONE(zone));
6466
6467	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
6468		return (true);
6469	}
6470
6471	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6472	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6473	isc_time_settoepoch(&zone->dumptime);
6474	return (false);
6475}
6476
6477/*%
6478 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6479 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6480 * Only load the public part of a given key if it is not active at timestamp
6481 * 'now'.  Store the number of keys found in 'nkeys'.
6482 */
6483isc_result_t
6484dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6485		   isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6486		   dst_key_t **keys, unsigned int *nkeys) {
6487	isc_result_t result;
6488	dns_dbnode_t *node = NULL;
6489	const char *directory = dns_zone_getkeydirectory(zone);
6490
6491	CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6492	memset(keys, 0, sizeof(*keys) * maxkeys);
6493
6494	dns_zone_lock_keyfiles(zone);
6495
6496	result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
6497					 directory, now, mctx, maxkeys, keys,
6498					 nkeys);
6499
6500	dns_zone_unlock_keyfiles(zone);
6501
6502	if (result == ISC_R_NOTFOUND) {
6503		result = ISC_R_SUCCESS;
6504	}
6505
6506failure:
6507
6508	if (node != NULL) {
6509		dns_db_detachnode(db, &node);
6510	}
6511	return (result);
6512}
6513
6514/*%
6515 * Find DNSSEC keys used for signing zone with dnssec-policy. Load these keys
6516 * into 'keys'. Requires KASP to be locked.
6517 */
6518isc_result_t
6519dns_zone_getdnsseckeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6520		       isc_stdtime_t now, dns_dnsseckeylist_t *keys) {
6521	isc_result_t result;
6522	const char *dir = dns_zone_getkeydirectory(zone);
6523	dns_dbnode_t *node = NULL;
6524	dns_dnsseckey_t *key, *key_next;
6525	dns_dnsseckeylist_t dnskeys;
6526	dns_name_t *origin = dns_zone_getorigin(zone);
6527	dns_kasp_t *kasp = dns_zone_getkasp(zone);
6528	dns_rdataset_t keyset;
6529
6530	REQUIRE(DNS_ZONE_VALID(zone));
6531	REQUIRE(kasp != NULL);
6532
6533	ISC_LIST_INIT(dnskeys);
6534
6535	dns_rdataset_init(&keyset);
6536
6537	CHECK(dns_db_findnode(db, origin, false, &node));
6538
6539	/* Get keys from private key files. */
6540	dns_zone_lock_keyfiles(zone);
6541	result = dns_dnssec_findmatchingkeys(origin, dir, now,
6542					     dns_zone_getmctx(zone), keys);
6543	dns_zone_unlock_keyfiles(zone);
6544
6545	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6546		goto failure;
6547	}
6548
6549	/* Get public keys (dnskeys). */
6550	dns_rdataset_init(&keyset);
6551	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
6552				     dns_rdatatype_none, 0, &keyset, NULL);
6553	if (result == ISC_R_SUCCESS) {
6554		CHECK(dns_dnssec_keylistfromrdataset(
6555			origin, dir, dns_zone_getmctx(zone), &keyset, NULL,
6556			NULL, false, false, &dnskeys));
6557	} else if (result != ISC_R_NOTFOUND) {
6558		CHECK(result);
6559	}
6560
6561	/* Add new 'dnskeys' to 'keys'. */
6562	for (dns_dnsseckey_t *k1 = ISC_LIST_HEAD(dnskeys); k1 != NULL;
6563	     k1 = key_next)
6564	{
6565		dns_dnsseckey_t *k2 = NULL;
6566		key_next = ISC_LIST_NEXT(k1, link);
6567
6568		for (k2 = ISC_LIST_HEAD(*keys); k2 != NULL;
6569		     k2 = ISC_LIST_NEXT(k2, link))
6570		{
6571			if (dst_key_compare(k1->key, k2->key)) {
6572				break;
6573			}
6574		}
6575		/* No match found, add the new key. */
6576		if (k2 == NULL) {
6577			ISC_LIST_UNLINK(dnskeys, k1, link);
6578			ISC_LIST_APPEND(*keys, k1, link);
6579		}
6580	}
6581
6582failure:
6583	if (dns_rdataset_isassociated(&keyset)) {
6584		dns_rdataset_disassociate(&keyset);
6585	}
6586	if (node != NULL) {
6587		dns_db_detachnode(db, &node);
6588	}
6589	while (!ISC_LIST_EMPTY(dnskeys)) {
6590		key = ISC_LIST_HEAD(dnskeys);
6591		ISC_LIST_UNLINK(dnskeys, key, link);
6592		dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
6593	}
6594	return (result);
6595}
6596
6597static isc_result_t
6598offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6599	dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
6600	isc_result_t result;
6601
6602	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) {
6603		return (ISC_R_SUCCESS);
6604	}
6605	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6606			       name, ttl, rdata);
6607	if (result != ISC_R_SUCCESS) {
6608		return (result);
6609	}
6610	rdata->flags |= DNS_RDATA_OFFLINE;
6611	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6612			       name, ttl, rdata);
6613	zonediff->offline = true;
6614	return (result);
6615}
6616
6617static void
6618set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
6619		       isc_stdtime_t now) {
6620	unsigned int delta;
6621	char timebuf[80];
6622
6623	LOCK_ZONE(zone);
6624	zone->key_expiry = when;
6625	if (when <= now) {
6626		dns_zone_log(zone, ISC_LOG_ERROR,
6627			     "DNSKEY RRSIG(s) have expired");
6628		isc_time_settoepoch(&zone->keywarntime);
6629	} else if (when < now + 7 * 24 * 3600) {
6630		isc_time_t t;
6631		isc_time_set(&t, when, 0);
6632		isc_time_formattimestamp(&t, timebuf, 80);
6633		dns_zone_log(zone, ISC_LOG_WARNING,
6634			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
6635			     timebuf);
6636		delta = when - now;
6637		delta--;	    /* loop prevention */
6638		delta /= 24 * 3600; /* to whole days */
6639		delta *= 24 * 3600; /* to seconds */
6640		isc_time_set(&zone->keywarntime, when - delta, 0);
6641	} else {
6642		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6643		isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6644		dns_zone_log(zone, ISC_LOG_NOTICE, "setting keywarntime to %s",
6645			     timebuf);
6646	}
6647	UNLOCK_ZONE(zone);
6648}
6649
6650/*
6651 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6652 * have no new key.
6653 */
6654static bool
6655delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6656	  bool kasp, bool *warn) {
6657	unsigned int i = 0;
6658	isc_result_t ret;
6659	bool have_ksk = false, have_zsk = false;
6660	bool have_pksk = false, have_pzsk = false;
6661
6662	for (i = 0; i < nkeys; i++) {
6663		bool ksk, zsk;
6664
6665		if (have_pksk && have_ksk && have_pzsk && have_zsk) {
6666			break;
6667		}
6668
6669		if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
6670			continue;
6671		}
6672
6673		ret = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
6674		if (ret != ISC_R_SUCCESS) {
6675			ksk = KSK(keys[i]);
6676		}
6677		ret = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
6678		if (ret != ISC_R_SUCCESS) {
6679			zsk = !KSK(keys[i]);
6680		}
6681
6682		if (ksk) {
6683			have_ksk = true;
6684			if (dst_key_isprivate(keys[i])) {
6685				have_pksk = true;
6686			}
6687		}
6688		if (zsk) {
6689			have_zsk = true;
6690			if (dst_key_isprivate(keys[i])) {
6691				have_pzsk = true;
6692			}
6693		}
6694	}
6695
6696	if (have_zsk && have_ksk && !have_pzsk) {
6697		*warn = true;
6698	}
6699
6700	if (have_pksk && have_pzsk) {
6701		return (true);
6702	}
6703
6704	/*
6705	 * Deleting the SOA RRSIG is always okay.
6706	 */
6707	if (rrsig_ptr->covered == dns_rdatatype_soa) {
6708		return (true);
6709	}
6710
6711	/*
6712	 * It's okay to delete a signature if there is an active key with the
6713	 * same algorithm to replace it, unless that violates the DNSSEC
6714	 * policy.
6715	 */
6716	if (have_pksk || have_pzsk) {
6717		if (kasp && have_pzsk) {
6718			return (true);
6719		}
6720		return (!kasp);
6721	}
6722
6723	/*
6724	 * Failing that, it is *not* okay to delete a signature
6725	 * if the associated public key is still in the DNSKEY RRset
6726	 */
6727	for (i = 0; i < nkeys; i++) {
6728		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6729		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
6730		{
6731			return (false);
6732		}
6733	}
6734
6735	/*
6736	 * But if the key is gone, then go ahead.
6737	 */
6738	return (true);
6739}
6740
6741/*
6742 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6743 * See also update.c:del_keysigs().
6744 */
6745static isc_result_t
6746del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6747	 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6748	 unsigned int nkeys, isc_stdtime_t now, bool incremental) {
6749	isc_result_t result;
6750	dns_dbnode_t *node = NULL;
6751	dns_rdataset_t rdataset;
6752	unsigned int i;
6753	dns_rdata_rrsig_t rrsig;
6754	bool kasp = (dns_zone_getkasp(zone) != NULL);
6755	bool found;
6756	int64_t timewarn = 0, timemaybe = 0;
6757
6758	dns_rdataset_init(&rdataset);
6759
6760	if (type == dns_rdatatype_nsec3) {
6761		result = dns_db_findnsec3node(db, name, false, &node);
6762	} else {
6763		result = dns_db_findnode(db, name, false, &node);
6764	}
6765	if (result == ISC_R_NOTFOUND) {
6766		return (ISC_R_SUCCESS);
6767	}
6768	if (result != ISC_R_SUCCESS) {
6769		goto failure;
6770	}
6771	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6772				     (isc_stdtime_t)0, &rdataset, NULL);
6773	dns_db_detachnode(db, &node);
6774
6775	if (result == ISC_R_NOTFOUND) {
6776		INSIST(!dns_rdataset_isassociated(&rdataset));
6777		return (ISC_R_SUCCESS);
6778	}
6779	if (result != ISC_R_SUCCESS) {
6780		INSIST(!dns_rdataset_isassociated(&rdataset));
6781		goto failure;
6782	}
6783
6784	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
6785	     result = dns_rdataset_next(&rdataset))
6786	{
6787		dns_rdata_t rdata = DNS_RDATA_INIT;
6788
6789		dns_rdataset_current(&rdataset, &rdata);
6790		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6791		RUNTIME_CHECK(result == ISC_R_SUCCESS);
6792
6793		if (type != dns_rdatatype_dnskey && type != dns_rdatatype_cds &&
6794		    type != dns_rdatatype_cdnskey)
6795		{
6796			bool warn = false, deleted = false;
6797			if (delsig_ok(&rrsig, keys, nkeys, kasp, &warn)) {
6798				result = update_one_rr(db, ver, zonediff->diff,
6799						       DNS_DIFFOP_DELRESIGN,
6800						       name, rdataset.ttl,
6801						       &rdata);
6802				if (result != ISC_R_SUCCESS) {
6803					break;
6804				}
6805				deleted = true;
6806			}
6807			if (warn && !deleted) {
6808				/*
6809				 * At this point, we've got an RRSIG,
6810				 * which is signed by an inactive key.
6811				 * An administrator needs to provide a new
6812				 * key/alg, but until that time, we want to
6813				 * keep the old RRSIG.  Marking the key as
6814				 * offline will prevent us spinning waiting
6815				 * for the private part.
6816				 */
6817				if (incremental) {
6818					result = offline(db, ver, zonediff,
6819							 name, rdataset.ttl,
6820							 &rdata);
6821					if (result != ISC_R_SUCCESS) {
6822						break;
6823					}
6824				}
6825
6826				/*
6827				 * Log the key id and algorithm of
6828				 * the inactive key with no replacement
6829				 */
6830				if (zone->log_key_expired_timer <= now) {
6831					char origin[DNS_NAME_FORMATSIZE];
6832					char algbuf[DNS_NAME_FORMATSIZE];
6833					dns_name_format(&zone->origin, origin,
6834							sizeof(origin));
6835					dns_secalg_format(rrsig.algorithm,
6836							  algbuf,
6837							  sizeof(algbuf));
6838					dns_zone_log(zone, ISC_LOG_WARNING,
6839						     "Key %s/%s/%d "
6840						     "missing or inactive "
6841						     "and has no replacement: "
6842						     "retaining signatures.",
6843						     origin, algbuf,
6844						     rrsig.keyid);
6845					zone->log_key_expired_timer = now +
6846								      3600;
6847				}
6848			}
6849			continue;
6850		}
6851
6852		/*
6853		 * KSK RRSIGs requires special processing.
6854		 */
6855		found = false;
6856		for (i = 0; i < nkeys; i++) {
6857			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6858			    rrsig.keyid == dst_key_id(keys[i]))
6859			{
6860				found = true;
6861				/*
6862				 * Mark offline DNSKEY.
6863				 * We want the earliest offline expire time
6864				 * iff there is a new offline signature.
6865				 */
6866				if (!dst_key_inactive(keys[i]) &&
6867				    !dst_key_isprivate(keys[i]))
6868				{
6869					int64_t timeexpire = dns_time64_from32(
6870						rrsig.timeexpire);
6871					if (timewarn != 0 &&
6872					    timewarn > timeexpire)
6873					{
6874						timewarn = timeexpire;
6875					}
6876					if (rdata.flags & DNS_RDATA_OFFLINE) {
6877						if (timemaybe == 0 ||
6878						    timemaybe > timeexpire)
6879						{
6880							timemaybe = timeexpire;
6881						}
6882						break;
6883					}
6884					if (timewarn == 0) {
6885						timewarn = timemaybe;
6886					}
6887					if (timewarn == 0 ||
6888					    timewarn > timeexpire)
6889					{
6890						timewarn = timeexpire;
6891					}
6892					result = offline(db, ver, zonediff,
6893							 name, rdataset.ttl,
6894							 &rdata);
6895					break;
6896				}
6897				result = update_one_rr(db, ver, zonediff->diff,
6898						       DNS_DIFFOP_DELRESIGN,
6899						       name, rdataset.ttl,
6900						       &rdata);
6901				break;
6902			}
6903		}
6904
6905		/*
6906		 * If there is not a matching DNSKEY then
6907		 * delete the RRSIG.
6908		 */
6909		if (!found) {
6910			result = update_one_rr(db, ver, zonediff->diff,
6911					       DNS_DIFFOP_DELRESIGN, name,
6912					       rdataset.ttl, &rdata);
6913		}
6914		if (result != ISC_R_SUCCESS) {
6915			break;
6916		}
6917	}
6918
6919	dns_rdataset_disassociate(&rdataset);
6920	if (result == ISC_R_NOMORE) {
6921		result = ISC_R_SUCCESS;
6922	}
6923	if (timewarn > 0) {
6924		isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
6925		if (timewarn == stdwarn) {
6926			set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
6927					       now);
6928		} else {
6929			dns_zone_log(zone, ISC_LOG_ERROR,
6930				     "key expiry warning time out of range");
6931		}
6932	}
6933failure:
6934	if (node != NULL) {
6935		dns_db_detachnode(db, &node);
6936	}
6937	return (result);
6938}
6939
6940static isc_result_t
6941add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
6942	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
6943	 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t now,
6944	 isc_stdtime_t inception, isc_stdtime_t expire, bool check_ksk,
6945	 bool keyset_kskonly) {
6946	isc_result_t result;
6947	dns_dbnode_t *node = NULL;
6948	dns_stats_t *dnssecsignstats;
6949	dns_rdataset_t rdataset;
6950	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
6951	unsigned char data[1024]; /* XXX */
6952	isc_buffer_t buffer;
6953	unsigned int i, j;
6954	bool use_kasp = false;
6955
6956	if (dns_zone_getkasp(zone) != NULL) {
6957		check_ksk = false;
6958		keyset_kskonly = true;
6959		use_kasp = true;
6960	}
6961
6962	dns_rdataset_init(&rdataset);
6963	isc_buffer_init(&buffer, data, sizeof(data));
6964
6965	if (type == dns_rdatatype_nsec3) {
6966		result = dns_db_findnsec3node(db, name, false, &node);
6967	} else {
6968		result = dns_db_findnode(db, name, false, &node);
6969	}
6970	if (result == ISC_R_NOTFOUND) {
6971		return (ISC_R_SUCCESS);
6972	}
6973	if (result != ISC_R_SUCCESS) {
6974		goto failure;
6975	}
6976	result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
6977				     &rdataset, NULL);
6978	dns_db_detachnode(db, &node);
6979	if (result == ISC_R_NOTFOUND) {
6980		INSIST(!dns_rdataset_isassociated(&rdataset));
6981		return (ISC_R_SUCCESS);
6982	}
6983	if (result != ISC_R_SUCCESS) {
6984		INSIST(!dns_rdataset_isassociated(&rdataset));
6985		goto failure;
6986	}
6987
6988	for (i = 0; i < nkeys; i++) {
6989		bool both = false;
6990
6991		/* Don't add signatures for offline or inactive keys */
6992		if (!dst_key_isprivate(keys[i])) {
6993			continue;
6994		}
6995		if (dst_key_inactive(keys[i])) {
6996			continue;
6997		}
6998
6999		if (check_ksk && !REVOKE(keys[i])) {
7000			bool have_ksk, have_nonksk;
7001			if (KSK(keys[i])) {
7002				have_ksk = true;
7003				have_nonksk = false;
7004			} else {
7005				have_ksk = false;
7006				have_nonksk = true;
7007			}
7008
7009			for (j = 0; j < nkeys; j++) {
7010				if (j == i || ALG(keys[i]) != ALG(keys[j])) {
7011					continue;
7012				}
7013
7014				/*
7015				 * Don't consider inactive keys, however
7016				 * the KSK may be temporary offline, so do
7017				 * consider keys which private key files are
7018				 * unavailable.
7019				 */
7020				if (dst_key_inactive(keys[j])) {
7021					continue;
7022				}
7023
7024				if (REVOKE(keys[j])) {
7025					continue;
7026				}
7027				if (KSK(keys[j])) {
7028					have_ksk = true;
7029				} else if (dst_key_isprivate(keys[j])) {
7030					have_nonksk = true;
7031				}
7032				both = have_ksk && have_nonksk;
7033				if (both) {
7034					break;
7035				}
7036			}
7037		}
7038		if (use_kasp) {
7039			/*
7040			 * A dnssec-policy is found. Check what RRsets this
7041			 * key should sign.
7042			 */
7043			isc_result_t kresult;
7044			isc_stdtime_t when;
7045			bool ksk = false;
7046			bool zsk = false;
7047			bool have_ksk = false;
7048			bool have_zsk = false;
7049
7050			kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
7051			if (kresult != ISC_R_SUCCESS) {
7052				if (KSK(keys[i])) {
7053					ksk = true;
7054				}
7055			}
7056			kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
7057			if (kresult != ISC_R_SUCCESS) {
7058				if (!KSK(keys[i])) {
7059					zsk = true;
7060				}
7061			}
7062
7063			have_ksk = ksk;
7064			have_zsk = zsk;
7065			both = have_ksk && have_zsk;
7066
7067			for (j = 0; j < nkeys; j++) {
7068				if (both) {
7069					break;
7070				}
7071
7072				if (j == i || ALG(keys[i]) != ALG(keys[j])) {
7073					continue;
7074				}
7075
7076				/*
7077				 * Don't consider inactive keys or offline keys.
7078				 */
7079				if (!dst_key_isprivate(keys[j])) {
7080					continue;
7081				}
7082				if (dst_key_inactive(keys[j])) {
7083					continue;
7084				}
7085
7086				if (REVOKE(keys[j])) {
7087					continue;
7088				}
7089
7090				if (!have_ksk) {
7091					kresult = dst_key_getbool(keys[j],
7092								  DST_BOOL_KSK,
7093								  &have_ksk);
7094					if (kresult != ISC_R_SUCCESS) {
7095						if (KSK(keys[j])) {
7096							have_ksk = true;
7097						}
7098					}
7099				}
7100				if (!have_zsk) {
7101					kresult = dst_key_getbool(keys[j],
7102								  DST_BOOL_ZSK,
7103								  &have_zsk);
7104					if (kresult != ISC_R_SUCCESS) {
7105						if (!KSK(keys[j])) {
7106							have_zsk = true;
7107						}
7108					}
7109				}
7110				both = have_ksk && have_zsk;
7111			}
7112
7113			if (type == dns_rdatatype_dnskey ||
7114			    type == dns_rdatatype_cdnskey ||
7115			    type == dns_rdatatype_cds)
7116			{
7117				/*
7118				 * DNSKEY RRset is signed with KSK.
7119				 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
7120				 */
7121				if (!ksk) {
7122					continue;
7123				}
7124			} else if (!zsk) {
7125				/*
7126				 * Other RRsets are signed with ZSK.
7127				 */
7128				if (type != dns_rdatatype_soa &&
7129				    type != zone->privatetype)
7130				{
7131					continue;
7132				}
7133				if (have_zsk) {
7134					continue;
7135				}
7136			} else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
7137						       now, &when))
7138			{
7139				/*
7140				 * This key is not active for zone-signing.
7141				 */
7142				continue;
7143			}
7144
7145			/*
7146			 * If this key is revoked, it may only sign the
7147			 * DNSKEY RRset.
7148			 */
7149			if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7150				continue;
7151			}
7152		} else if (both) {
7153			/*
7154			 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
7155			 */
7156			if (type == dns_rdatatype_dnskey ||
7157			    type == dns_rdatatype_cdnskey ||
7158			    type == dns_rdatatype_cds)
7159			{
7160				if (!KSK(keys[i]) && keyset_kskonly) {
7161					continue;
7162				}
7163			} else if (KSK(keys[i])) {
7164				continue;
7165			}
7166		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7167			continue;
7168		}
7169
7170		/* Calculate the signature, creating a RRSIG RDATA. */
7171		isc_buffer_clear(&buffer);
7172		CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
7173				      &expire, mctx, &buffer, &sig_rdata));
7174
7175		/* Update the database and journal with the RRSIG. */
7176		/* XXX inefficient - will cause dataset merging */
7177		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
7178				    rdataset.ttl, &sig_rdata));
7179		dns_rdata_reset(&sig_rdata);
7180		isc_buffer_init(&buffer, data, sizeof(data));
7181
7182		/* Update DNSSEC sign statistics. */
7183		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7184		if (dnssecsignstats != NULL) {
7185			/* Generated a new signature. */
7186			dns_dnssecsignstats_increment(dnssecsignstats,
7187						      ID(keys[i]),
7188						      (uint8_t)ALG(keys[i]),
7189						      dns_dnssecsignstats_sign);
7190			/* This is a refresh. */
7191			dns_dnssecsignstats_increment(
7192				dnssecsignstats, ID(keys[i]),
7193				(uint8_t)ALG(keys[i]),
7194				dns_dnssecsignstats_refresh);
7195		}
7196	}
7197
7198failure:
7199	if (dns_rdataset_isassociated(&rdataset)) {
7200		dns_rdataset_disassociate(&rdataset);
7201	}
7202	if (node != NULL) {
7203		dns_db_detachnode(db, &node);
7204	}
7205	return (result);
7206}
7207
7208static void
7209zone_resigninc(dns_zone_t *zone) {
7210	const char *me = "zone_resigninc";
7211	dns_db_t *db = NULL;
7212	dns_dbversion_t *version = NULL;
7213	dns_diff_t _sig_diff;
7214	dns__zonediff_t zonediff;
7215	dns_fixedname_t fixed;
7216	dns_name_t *name;
7217	dns_rdataset_t rdataset;
7218	dns_rdatatype_t covers;
7219	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7220	bool check_ksk, keyset_kskonly = false;
7221	isc_result_t result;
7222	isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
7223	uint32_t sigvalidityinterval, expiryinterval;
7224	unsigned int i;
7225	unsigned int nkeys = 0;
7226	unsigned int resign;
7227
7228	ENTER;
7229
7230	dns_rdataset_init(&rdataset);
7231	dns_diff_init(zone->mctx, &_sig_diff);
7232	zonediff_init(&zonediff, &_sig_diff);
7233
7234	/*
7235	 * Zone is frozen or automatic resigning is disabled.
7236	 * Pause for 5 minutes.
7237	 */
7238	if (zone->update_disabled ||
7239	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
7240	{
7241		result = ISC_R_FAILURE;
7242		goto failure;
7243	}
7244
7245	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7246	if (zone->db != NULL) {
7247		dns_db_attach(zone->db, &db);
7248	}
7249	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7250	if (db == NULL) {
7251		result = ISC_R_FAILURE;
7252		goto failure;
7253	}
7254
7255	result = dns_db_newversion(db, &version);
7256	if (result != ISC_R_SUCCESS) {
7257		dns_zone_log(zone, ISC_LOG_ERROR,
7258			     "zone_resigninc:dns_db_newversion -> %s",
7259			     isc_result_totext(result));
7260		goto failure;
7261	}
7262
7263	isc_stdtime_get(&now);
7264
7265	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7266				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
7267	if (result != ISC_R_SUCCESS) {
7268		dns_zone_log(zone, ISC_LOG_ERROR,
7269			     "zone_resigninc:dns__zone_findkeys -> %s",
7270			     isc_result_totext(result));
7271		goto failure;
7272	}
7273
7274	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7275	inception = now - 3600; /* Allow for clock skew. */
7276	soaexpire = now + sigvalidityinterval;
7277	expiryinterval = dns_zone_getsigresigninginterval(zone);
7278	if (expiryinterval > sigvalidityinterval) {
7279		expiryinterval = sigvalidityinterval;
7280	} else {
7281		expiryinterval = sigvalidityinterval - expiryinterval;
7282	}
7283
7284	/*
7285	 * Spread out signatures over time if they happen to be
7286	 * clumped.  We don't do this for each add_sigs() call as
7287	 * we still want some clustering to occur.  In normal operations
7288	 * the records should be re-signed as they fall due and they should
7289	 * already be spread out.  However if the server is off for a
7290	 * period we need to ensure that the clusters don't become
7291	 * synchronised by using the full jitter range.
7292	 */
7293	if (sigvalidityinterval >= 3600U) {
7294		uint32_t normaljitter, fulljitter;
7295		if (sigvalidityinterval > 7200U) {
7296			normaljitter = isc_random_uniform(3600);
7297			fulljitter = isc_random_uniform(expiryinterval);
7298		} else {
7299			normaljitter = fulljitter = isc_random_uniform(1200);
7300		}
7301		expire = soaexpire - normaljitter - 1;
7302		fullexpire = soaexpire - fulljitter - 1;
7303	} else {
7304		expire = fullexpire = soaexpire - 1;
7305	}
7306	stop = now + 5;
7307
7308	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7309	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7310
7311	name = dns_fixedname_initname(&fixed);
7312	result = dns_db_getsigningtime(db, &rdataset, name);
7313	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
7314		dns_zone_log(zone, ISC_LOG_ERROR,
7315			     "zone_resigninc:dns_db_getsigningtime -> %s",
7316			     isc_result_totext(result));
7317	}
7318
7319	i = 0;
7320	while (result == ISC_R_SUCCESS) {
7321		resign = rdataset.resign -
7322			 dns_zone_getsigresigninginterval(zone);
7323		covers = rdataset.covers;
7324		dns_rdataset_disassociate(&rdataset);
7325
7326		/*
7327		 * Stop if we hit the SOA as that means we have walked the
7328		 * entire zone.  The SOA record should always be the most
7329		 * recent signature.
7330		 */
7331		/* XXXMPA increase number of RRsets signed pre call */
7332		if ((covers == dns_rdatatype_soa &&
7333		     dns_name_equal(name, &zone->origin)) ||
7334		    i++ > zone->signatures || resign > stop)
7335		{
7336			break;
7337		}
7338
7339		result = del_sigs(zone, db, version, name, covers, &zonediff,
7340				  zone_keys, nkeys, now, true);
7341		if (result != ISC_R_SUCCESS) {
7342			dns_zone_log(zone, ISC_LOG_ERROR,
7343				     "zone_resigninc:del_sigs -> %s",
7344				     isc_result_totext(result));
7345			break;
7346		}
7347
7348		/*
7349		 * If re-signing is over 5 minutes late use 'fullexpire'
7350		 * to redistribute the signature over the complete
7351		 * re-signing window, otherwise only add a small amount
7352		 * of jitter.
7353		 */
7354		result = add_sigs(db, version, name, zone, covers,
7355				  zonediff.diff, zone_keys, nkeys, zone->mctx,
7356				  now, inception,
7357				  resign > (now - 300) ? expire : fullexpire,
7358				  check_ksk, keyset_kskonly);
7359		if (result != ISC_R_SUCCESS) {
7360			dns_zone_log(zone, ISC_LOG_ERROR,
7361				     "zone_resigninc:add_sigs -> %s",
7362				     isc_result_totext(result));
7363			break;
7364		}
7365		result = dns_db_getsigningtime(db, &rdataset, name);
7366		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
7367			result = ISC_R_SUCCESS;
7368			break;
7369		}
7370		if (result != ISC_R_SUCCESS) {
7371			dns_zone_log(zone, ISC_LOG_ERROR,
7372				     "zone_resigninc:dns_db_getsigningtime -> "
7373				     "%s",
7374				     isc_result_totext(result));
7375		}
7376	}
7377
7378	if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS) {
7379		goto failure;
7380	}
7381
7382	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7383			  &zonediff, zone_keys, nkeys, now, true);
7384	if (result != ISC_R_SUCCESS) {
7385		dns_zone_log(zone, ISC_LOG_ERROR,
7386			     "zone_resigninc:del_sigs -> %s",
7387			     isc_result_totext(result));
7388		goto failure;
7389	}
7390
7391	/*
7392	 * Did we change anything in the zone?
7393	 */
7394	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7395		/*
7396		 * Commit the changes if any key has been marked as offline.
7397		 */
7398		if (zonediff.offline) {
7399			dns_db_closeversion(db, &version, true);
7400		}
7401		goto failure;
7402	}
7403
7404	/* Increment SOA serial if we have made changes */
7405	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
7406				   zone->updatemethod);
7407	if (result != ISC_R_SUCCESS) {
7408		dns_zone_log(zone, ISC_LOG_ERROR,
7409			     "zone_resigninc:update_soa_serial -> %s",
7410			     isc_result_totext(result));
7411		goto failure;
7412	}
7413
7414	/*
7415	 * Generate maximum life time signatures so that the above loop
7416	 * termination is sensible.
7417	 */
7418	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
7419			  zonediff.diff, zone_keys, nkeys, zone->mctx, now,
7420			  inception, soaexpire, check_ksk, keyset_kskonly);
7421	if (result != ISC_R_SUCCESS) {
7422		dns_zone_log(zone, ISC_LOG_ERROR,
7423			     "zone_resigninc:add_sigs -> %s",
7424			     isc_result_totext(result));
7425		goto failure;
7426	}
7427
7428	/* Write changes to journal file. */
7429	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
7430
7431	/* Everything has succeeded. Commit the changes. */
7432	dns_db_closeversion(db, &version, true);
7433
7434failure:
7435	dns_diff_clear(&_sig_diff);
7436	for (i = 0; i < nkeys; i++) {
7437		dst_key_free(&zone_keys[i]);
7438	}
7439	if (version != NULL) {
7440		dns_db_closeversion(db, &version, false);
7441		dns_db_detach(&db);
7442	} else if (db != NULL) {
7443		dns_db_detach(&db);
7444	}
7445
7446	LOCK_ZONE(zone);
7447	if (result == ISC_R_SUCCESS) {
7448		set_resigntime(zone);
7449		zone_needdump(zone, DNS_DUMP_DELAY);
7450		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7451	} else {
7452		/*
7453		 * Something failed.  Retry in 5 minutes.
7454		 */
7455		isc_interval_t ival;
7456		isc_interval_set(&ival, 300, 0);
7457		isc_time_nowplusinterval(&zone->resigntime, &ival);
7458	}
7459	UNLOCK_ZONE(zone);
7460
7461	INSIST(version == NULL);
7462}
7463
7464static isc_result_t
7465next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
7466	    dns_name_t *newname, bool bottom) {
7467	isc_result_t result;
7468	dns_dbiterator_t *dbit = NULL;
7469	dns_rdatasetiter_t *rdsit = NULL;
7470	dns_dbnode_t *node = NULL;
7471
7472	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
7473	CHECK(dns_dbiterator_seek(dbit, oldname));
7474	do {
7475		result = dns_dbiterator_next(dbit);
7476		if (result == ISC_R_NOMORE) {
7477			CHECK(dns_dbiterator_first(dbit));
7478		}
7479		CHECK(dns_dbiterator_current(dbit, &node, newname));
7480		if (bottom && dns_name_issubdomain(newname, oldname) &&
7481		    !dns_name_equal(newname, oldname))
7482		{
7483			dns_db_detachnode(db, &node);
7484			continue;
7485		}
7486		/*
7487		 * Is this node empty?
7488		 */
7489		CHECK(dns_db_allrdatasets(db, node, version, 0, 0, &rdsit));
7490		result = dns_rdatasetiter_first(rdsit);
7491		dns_db_detachnode(db, &node);
7492		dns_rdatasetiter_destroy(&rdsit);
7493		if (result != ISC_R_NOMORE) {
7494			break;
7495		}
7496	} while (1);
7497failure:
7498	if (node != NULL) {
7499		dns_db_detachnode(db, &node);
7500	}
7501	if (dbit != NULL) {
7502		dns_dbiterator_destroy(&dbit);
7503	}
7504	return (result);
7505}
7506
7507static bool
7508signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
7509		     dns_dbversion_t *version, dns_rdatatype_t type,
7510		     dst_key_t *key) {
7511	isc_result_t result;
7512	dns_rdataset_t rdataset;
7513	dns_rdata_t rdata = DNS_RDATA_INIT;
7514	dns_rdata_rrsig_t rrsig;
7515	int count = 0;
7516	dns_kasp_t *kasp = dns_zone_getkasp(zone);
7517
7518	dns_rdataset_init(&rdataset);
7519	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
7520				     type, 0, &rdataset, NULL);
7521	if (result != ISC_R_SUCCESS) {
7522		INSIST(!dns_rdataset_isassociated(&rdataset));
7523		return (false);
7524	}
7525	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7526	     result = dns_rdataset_next(&rdataset))
7527	{
7528		dns_rdataset_current(&rdataset, &rdata);
7529		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
7530		INSIST(result == ISC_R_SUCCESS);
7531		if (rrsig.algorithm == dst_key_alg(key) &&
7532		    rrsig.keyid == dst_key_id(key))
7533		{
7534			dns_rdataset_disassociate(&rdataset);
7535			return (true);
7536		}
7537		if (rrsig.algorithm == dst_key_alg(key)) {
7538			count++;
7539		}
7540		dns_rdata_reset(&rdata);
7541	}
7542
7543	if (dns_zone_getkasp(zone) != NULL) {
7544		dns_kasp_key_t *kkey;
7545		int zsk_count = 0;
7546		bool approved;
7547
7548		KASP_LOCK(kasp);
7549		for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
7550		     kkey = ISC_LIST_NEXT(kkey, link))
7551		{
7552			if (dns_kasp_key_algorithm(kkey) != dst_key_alg(key)) {
7553				continue;
7554			}
7555			if (dns_kasp_key_zsk(kkey)) {
7556				zsk_count++;
7557			}
7558		}
7559		KASP_UNLOCK(kasp);
7560
7561		if (type == dns_rdatatype_dnskey ||
7562		    type == dns_rdatatype_cdnskey || type == dns_rdatatype_cds)
7563		{
7564			/*
7565			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7566			 * (RFC 7344, section 4.1 specifies that they must
7567			 * be signed with a key in the current DS RRset,
7568			 * which would only include KSK's.)
7569			 */
7570			approved = false;
7571		} else {
7572			approved = (zsk_count == count);
7573		}
7574
7575		dns_rdataset_disassociate(&rdataset);
7576		return (approved);
7577	}
7578
7579	dns_rdataset_disassociate(&rdataset);
7580	return (false);
7581}
7582
7583static isc_result_t
7584add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7585	 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom, dns_diff_t *diff) {
7586	dns_fixedname_t fixed;
7587	dns_name_t *next;
7588	dns_rdata_t rdata = DNS_RDATA_INIT;
7589	isc_result_t result;
7590	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
7591
7592	next = dns_fixedname_initname(&fixed);
7593
7594	CHECK(next_active(db, version, name, next, bottom));
7595	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata));
7596	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
7597			    &rdata));
7598failure:
7599	return (result);
7600}
7601
7602static isc_result_t
7603check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
7604			dns_dbversion_t *version, bool *is_bottom_of_zone) {
7605	isc_result_t result;
7606	dns_rdatasetiter_t *iterator = NULL;
7607	dns_rdataset_t rdataset;
7608	bool seen_soa = false, seen_ns = false, seen_dname = false;
7609
7610	REQUIRE(is_bottom_of_zone != NULL);
7611
7612	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7613	if (result != ISC_R_SUCCESS) {
7614		if (result == ISC_R_NOTFOUND) {
7615			result = ISC_R_SUCCESS;
7616		}
7617		return (result);
7618	}
7619
7620	dns_rdataset_init(&rdataset);
7621	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7622	     result = dns_rdatasetiter_next(iterator))
7623	{
7624		dns_rdatasetiter_current(iterator, &rdataset);
7625		switch (rdataset.type) {
7626		case dns_rdatatype_soa:
7627			seen_soa = true;
7628			break;
7629		case dns_rdatatype_ns:
7630			seen_ns = true;
7631			break;
7632		case dns_rdatatype_dname:
7633			seen_dname = true;
7634			break;
7635		}
7636		dns_rdataset_disassociate(&rdataset);
7637	}
7638	if (result != ISC_R_NOMORE) {
7639		goto failure;
7640	}
7641	if ((seen_ns && !seen_soa) || seen_dname) {
7642		*is_bottom_of_zone = true;
7643	}
7644	result = ISC_R_SUCCESS;
7645
7646failure:
7647	dns_rdatasetiter_destroy(&iterator);
7648
7649	return (result);
7650}
7651
7652static isc_result_t
7653sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
7654	    dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3,
7655	    bool build_nsec, dst_key_t *key, isc_stdtime_t now,
7656	    isc_stdtime_t inception, isc_stdtime_t expire, dns_ttl_t nsecttl,
7657	    bool is_ksk, bool is_zsk, bool keyset_kskonly,
7658	    bool is_bottom_of_zone, dns_diff_t *diff, int32_t *signatures,
7659	    isc_mem_t *mctx) {
7660	isc_result_t result;
7661	dns_rdatasetiter_t *iterator = NULL;
7662	dns_rdataset_t rdataset;
7663	dns_rdata_t rdata = DNS_RDATA_INIT;
7664	dns_stats_t *dnssecsignstats;
7665
7666	isc_buffer_t buffer;
7667	unsigned char data[1024];
7668	bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
7669
7670	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7671	if (result != ISC_R_SUCCESS) {
7672		if (result == ISC_R_NOTFOUND) {
7673			result = ISC_R_SUCCESS;
7674		}
7675		return (result);
7676	}
7677
7678	dns_rdataset_init(&rdataset);
7679	isc_buffer_init(&buffer, data, sizeof(data));
7680	seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
7681	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7682	     result = dns_rdatasetiter_next(iterator))
7683	{
7684		dns_rdatasetiter_current(iterator, &rdataset);
7685		if (rdataset.type == dns_rdatatype_soa) {
7686			seen_soa = true;
7687		} else if (rdataset.type == dns_rdatatype_ns) {
7688			seen_ns = true;
7689		} else if (rdataset.type == dns_rdatatype_ds) {
7690			seen_ds = true;
7691		} else if (rdataset.type == dns_rdatatype_nsec) {
7692			seen_nsec = true;
7693		} else if (rdataset.type == dns_rdatatype_nsec3) {
7694			seen_nsec3 = true;
7695		}
7696		if (rdataset.type != dns_rdatatype_rrsig) {
7697			seen_rr = true;
7698		}
7699		dns_rdataset_disassociate(&rdataset);
7700	}
7701	if (result != ISC_R_NOMORE) {
7702		goto failure;
7703	}
7704	/*
7705	 * Going from insecure to NSEC3.
7706	 * Don't generate NSEC3 records for NSEC3 records.
7707	 */
7708	if (build_nsec3 && !seen_nsec3 && seen_rr) {
7709		bool unsecure = !seen_ds && seen_ns && !seen_soa;
7710		CHECK(dns_nsec3_addnsec3s(db, version, name, nsecttl, unsecure,
7711					  diff));
7712		(*signatures)--;
7713	}
7714	/*
7715	 * Going from insecure to NSEC.
7716	 * Don't generate NSEC records for NSEC3 records.
7717	 */
7718	if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
7719		/*
7720		 * Build a NSEC record except at the origin.
7721		 */
7722		if (!dns_name_equal(name, dns_db_origin(db))) {
7723			CHECK(add_nsec(db, version, name, node, nsecttl,
7724				       is_bottom_of_zone, diff));
7725			/* Count a NSEC generation as a signature generation. */
7726			(*signatures)--;
7727		}
7728	}
7729	result = dns_rdatasetiter_first(iterator);
7730	while (result == ISC_R_SUCCESS) {
7731		isc_stdtime_t when;
7732
7733		dns_rdatasetiter_current(iterator, &rdataset);
7734		if (rdataset.type == dns_rdatatype_soa ||
7735		    rdataset.type == dns_rdatatype_rrsig)
7736		{
7737			goto next_rdataset;
7738		}
7739		if (rdataset.type == dns_rdatatype_dnskey ||
7740		    rdataset.type == dns_rdatatype_cdnskey ||
7741		    rdataset.type == dns_rdatatype_cds)
7742		{
7743			/*
7744			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7745			 * (RFC 7344, section 4.1 specifies that they must
7746			 * be signed with a key in the current DS RRset,
7747			 * which would only include KSK's.)
7748			 */
7749			if (!is_ksk && keyset_kskonly) {
7750				goto next_rdataset;
7751			}
7752		} else if (!is_zsk) {
7753			goto next_rdataset;
7754		} else if (is_zsk &&
7755			   !dst_key_is_signing(key, DST_BOOL_ZSK, now, &when))
7756		{
7757			/* Only applies to dnssec-policy. */
7758			if (dns_zone_getkasp(zone) != NULL) {
7759				goto next_rdataset;
7760			}
7761		}
7762
7763		if (seen_ns && !seen_soa && rdataset.type != dns_rdatatype_ds &&
7764		    rdataset.type != dns_rdatatype_nsec)
7765		{
7766			goto next_rdataset;
7767		}
7768		if (signed_with_good_key(zone, db, node, version, rdataset.type,
7769					 key))
7770		{
7771			goto next_rdataset;
7772		}
7773
7774		/* Calculate the signature, creating a RRSIG RDATA. */
7775		isc_buffer_clear(&buffer);
7776		CHECK(dns_dnssec_sign(name, &rdataset, key, &inception, &expire,
7777				      mctx, &buffer, &rdata));
7778		/* Update the database and journal with the RRSIG. */
7779		/* XXX inefficient - will cause dataset merging */
7780		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7781				    name, rdataset.ttl, &rdata));
7782		dns_rdata_reset(&rdata);
7783
7784		/* Update DNSSEC sign statistics. */
7785		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7786		if (dnssecsignstats != NULL) {
7787			/* Generated a new signature. */
7788			dns_dnssecsignstats_increment(dnssecsignstats, ID(key),
7789						      ALG(key),
7790						      dns_dnssecsignstats_sign);
7791			/* This is a refresh. */
7792			dns_dnssecsignstats_increment(
7793				dnssecsignstats, ID(key), ALG(key),
7794				dns_dnssecsignstats_refresh);
7795		}
7796
7797		(*signatures)--;
7798	next_rdataset:
7799		dns_rdataset_disassociate(&rdataset);
7800		result = dns_rdatasetiter_next(iterator);
7801	}
7802	if (result == ISC_R_NOMORE) {
7803		result = ISC_R_SUCCESS;
7804	}
7805failure:
7806	if (dns_rdataset_isassociated(&rdataset)) {
7807		dns_rdataset_disassociate(&rdataset);
7808	}
7809	if (iterator != NULL) {
7810		dns_rdatasetiter_destroy(&iterator);
7811	}
7812	return (result);
7813}
7814
7815/*
7816 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7817 */
7818static isc_result_t
7819updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7820	     dns_ttl_t nsecttl, bool update_only, dns_diff_t *diff) {
7821	isc_result_t result;
7822	dns_rdataset_t rdataset;
7823	dns_dbnode_t *node = NULL;
7824
7825	CHECK(dns_db_getoriginnode(db, &node));
7826	if (update_only) {
7827		dns_rdataset_init(&rdataset);
7828		result = dns_db_findrdataset(
7829			db, node, version, dns_rdatatype_nsec,
7830			dns_rdatatype_none, 0, &rdataset, NULL);
7831		if (dns_rdataset_isassociated(&rdataset)) {
7832			dns_rdataset_disassociate(&rdataset);
7833		}
7834		if (result == ISC_R_NOTFOUND) {
7835			goto success;
7836		}
7837		if (result != ISC_R_SUCCESS) {
7838			goto failure;
7839		}
7840	}
7841	CHECK(delete_nsec(db, version, node, name, diff));
7842	CHECK(add_nsec(db, version, name, node, nsecttl, false, diff));
7843success:
7844	result = ISC_R_SUCCESS;
7845failure:
7846	if (node != NULL) {
7847		dns_db_detachnode(db, &node);
7848	}
7849	return (result);
7850}
7851
7852static isc_result_t
7853updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7854		  dns_dbversion_t *version, bool build_nsec3, dns_ttl_t nsecttl,
7855		  dns_diff_t *diff) {
7856	isc_result_t result;
7857	dns_dbnode_t *node = NULL;
7858	dns_rdataset_t rdataset;
7859	dns_rdata_t rdata = DNS_RDATA_INIT;
7860	unsigned char data[5];
7861	bool seen_done = false;
7862	bool have_rr = false;
7863
7864	dns_rdataset_init(&rdataset);
7865	result = dns_db_getoriginnode(signing->db, &node);
7866	if (result != ISC_R_SUCCESS) {
7867		goto failure;
7868	}
7869
7870	result = dns_db_findrdataset(signing->db, node, version,
7871				     zone->privatetype, dns_rdatatype_none, 0,
7872				     &rdataset, NULL);
7873	if (result == ISC_R_NOTFOUND) {
7874		INSIST(!dns_rdataset_isassociated(&rdataset));
7875		result = ISC_R_SUCCESS;
7876		goto failure;
7877	}
7878	if (result != ISC_R_SUCCESS) {
7879		INSIST(!dns_rdataset_isassociated(&rdataset));
7880		goto failure;
7881	}
7882	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7883	     result = dns_rdataset_next(&rdataset))
7884	{
7885		dns_rdataset_current(&rdataset, &rdata);
7886		/*
7887		 * If we don't match the algorithm or keyid skip the record.
7888		 */
7889		if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
7890		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7891		    rdata.data[2] != (signing->keyid & 0xff))
7892		{
7893			have_rr = true;
7894			dns_rdata_reset(&rdata);
7895			continue;
7896		}
7897		/*
7898		 * We have a match.  If we were signing (!signing->deleteit)
7899		 * and we already have a record indicating that we have
7900		 * finished signing (rdata.data[4] != 0) then keep it.
7901		 * Otherwise it needs to be deleted as we have removed all
7902		 * the signatures (signing->deleteit), so any record indicating
7903		 * completion is now out of date, or we have finished signing
7904		 * with the new record so we no longer need to remember that
7905		 * we need to sign the zone with the matching key across a
7906		 * nameserver re-start.
7907		 */
7908		if (!signing->deleteit && rdata.data[4] != 0) {
7909			seen_done = true;
7910			have_rr = true;
7911		} else {
7912			CHECK(update_one_rr(signing->db, version, diff,
7913					    DNS_DIFFOP_DEL, &zone->origin,
7914					    rdataset.ttl, &rdata));
7915		}
7916		dns_rdata_reset(&rdata);
7917	}
7918	if (result == ISC_R_NOMORE) {
7919		result = ISC_R_SUCCESS;
7920	}
7921	if (!signing->deleteit && !seen_done) {
7922		/*
7923		 * If we were signing then we need to indicate that we have
7924		 * finished signing the zone with this key.  If it is already
7925		 * there we don't need to add it a second time.
7926		 */
7927		data[0] = signing->algorithm;
7928		data[1] = (signing->keyid >> 8) & 0xff;
7929		data[2] = signing->keyid & 0xff;
7930		data[3] = 0;
7931		data[4] = 1;
7932		rdata.length = sizeof(data);
7933		rdata.data = data;
7934		rdata.type = zone->privatetype;
7935		rdata.rdclass = dns_db_class(signing->db);
7936		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
7937				    &zone->origin, rdataset.ttl, &rdata));
7938	} else if (!have_rr) {
7939		dns_name_t *origin = dns_db_origin(signing->db);
7940		/*
7941		 * Rebuild the NSEC/NSEC3 record for the origin as we no
7942		 * longer have any private records.
7943		 */
7944		if (build_nsec3) {
7945			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
7946						  nsecttl, false, diff));
7947		}
7948		CHECK(updatesecure(signing->db, version, origin, nsecttl, true,
7949				   diff));
7950	}
7951
7952failure:
7953	if (dns_rdataset_isassociated(&rdataset)) {
7954		dns_rdataset_disassociate(&rdataset);
7955	}
7956	if (node != NULL) {
7957		dns_db_detachnode(signing->db, &node);
7958	}
7959	return (result);
7960}
7961
7962/*
7963 * Called from zone_nsec3chain() in order to update zone records indicating
7964 * processing status of given NSEC3 chain:
7965 *
7966 *   - If the supplied dns_nsec3chain_t structure has been fully processed
7967 *     (which is indicated by "active" being set to false):
7968 *
7969 *       - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
7970 *
7971 *       - remove all private-type records containing NSEC3PARAM RDATA matching
7972 *         the relevant NSEC3 chain.
7973 *
7974 *   - If the supplied dns_nsec3chain_t structure has not been fully processed
7975 *     (which is indicated by "active" being set to true), only remove the
7976 *     NSEC3PARAM record which matches the relevant NSEC3 chain and has the
7977 *     "flags" field set to 0.
7978 *
7979 *   - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
7980 *     in the relevant private-type record, but with the "flags" field set to
7981 *     0, indicating that this NSEC3 chain is now complete for this zone.
7982 *
7983 * Note that this function is called at different processing stages for NSEC3
7984 * chain additions vs. removals and needs to handle all cases properly.
7985 */
7986static isc_result_t
7987fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
7988		 bool active, dns_rdatatype_t privatetype, dns_diff_t *diff) {
7989	dns_dbnode_t *node = NULL;
7990	dns_name_t *name = dns_db_origin(db);
7991	dns_rdata_t rdata = DNS_RDATA_INIT;
7992	dns_rdataset_t rdataset;
7993	dns_rdata_nsec3param_t nsec3param;
7994	isc_result_t result;
7995	isc_buffer_t buffer;
7996	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
7997	dns_ttl_t ttl = 0;
7998	bool nseconly = false, nsec3ok = false;
7999
8000	dns_rdataset_init(&rdataset);
8001
8002	result = dns_db_getoriginnode(db, &node);
8003	RUNTIME_CHECK(result == ISC_R_SUCCESS);
8004	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8005				     0, &rdataset, NULL);
8006	if (result == ISC_R_NOTFOUND) {
8007		goto try_private;
8008	}
8009	if (result != ISC_R_SUCCESS) {
8010		goto failure;
8011	}
8012
8013	/*
8014	 * Preserve the existing ttl.
8015	 */
8016	ttl = rdataset.ttl;
8017
8018	/*
8019	 * Delete all NSEC3PARAM records which match that in nsec3chain.
8020	 */
8021	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8022	     result = dns_rdataset_next(&rdataset))
8023	{
8024		dns_rdataset_current(&rdataset, &rdata);
8025		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8026
8027		if (nsec3param.hash != chain->nsec3param.hash ||
8028		    (active && nsec3param.flags != 0) ||
8029		    nsec3param.iterations != chain->nsec3param.iterations ||
8030		    nsec3param.salt_length != chain->nsec3param.salt_length ||
8031		    memcmp(nsec3param.salt, chain->nsec3param.salt,
8032			   nsec3param.salt_length))
8033		{
8034			dns_rdata_reset(&rdata);
8035			continue;
8036		}
8037
8038		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8039				    rdataset.ttl, &rdata));
8040		dns_rdata_reset(&rdata);
8041	}
8042	if (result != ISC_R_NOMORE) {
8043		goto failure;
8044	}
8045
8046	dns_rdataset_disassociate(&rdataset);
8047
8048try_private:
8049
8050	if (active) {
8051		goto add;
8052	}
8053
8054	result = dns_nsec_nseconly(db, ver, diff, &nseconly);
8055	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
8056
8057	/*
8058	 * Delete all private records which match that in nsec3chain.
8059	 */
8060	result = dns_db_findrdataset(db, node, ver, privatetype, 0, 0,
8061				     &rdataset, NULL);
8062	if (result == ISC_R_NOTFOUND) {
8063		goto add;
8064	}
8065	if (result != ISC_R_SUCCESS) {
8066		goto failure;
8067	}
8068
8069	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8070	     result = dns_rdataset_next(&rdataset))
8071	{
8072		dns_rdata_t private = DNS_RDATA_INIT;
8073		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
8074
8075		dns_rdataset_current(&rdataset, &private);
8076		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
8077						sizeof(buf)))
8078		{
8079			continue;
8080		}
8081		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8082
8083		if ((!nsec3ok &&
8084		     (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
8085		    nsec3param.hash != chain->nsec3param.hash ||
8086		    nsec3param.iterations != chain->nsec3param.iterations ||
8087		    nsec3param.salt_length != chain->nsec3param.salt_length ||
8088		    memcmp(nsec3param.salt, chain->nsec3param.salt,
8089			   nsec3param.salt_length))
8090		{
8091			dns_rdata_reset(&rdata);
8092			continue;
8093		}
8094
8095		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8096				    rdataset.ttl, &private));
8097		dns_rdata_reset(&rdata);
8098	}
8099	if (result != ISC_R_NOMORE) {
8100		goto failure;
8101	}
8102
8103add:
8104	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
8105		result = ISC_R_SUCCESS;
8106		goto failure;
8107	}
8108
8109	/*
8110	 * Add a NSEC3PARAM record which matches that in nsec3chain but
8111	 * with all flags bits cleared.
8112	 *
8113	 * Note: we do not clear chain->nsec3param.flags as this change
8114	 * may be reversed.
8115	 */
8116	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
8117	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
8118				   dns_rdatatype_nsec3param, &chain->nsec3param,
8119				   &buffer));
8120	rdata.data[1] = 0; /* Clear flag bits. */
8121	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
8122
8123failure:
8124	dns_db_detachnode(db, &node);
8125	if (dns_rdataset_isassociated(&rdataset)) {
8126		dns_rdataset_disassociate(&rdataset);
8127	}
8128	return (result);
8129}
8130
8131static isc_result_t
8132delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8133	    dns_name_t *name, dns_diff_t *diff) {
8134	dns_rdataset_t rdataset;
8135	isc_result_t result;
8136
8137	dns_rdataset_init(&rdataset);
8138
8139	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8140				     &rdataset, NULL);
8141	if (result == ISC_R_NOTFOUND) {
8142		return (ISC_R_SUCCESS);
8143	}
8144	if (result != ISC_R_SUCCESS) {
8145		return (result);
8146	}
8147	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8148	     result = dns_rdataset_next(&rdataset))
8149	{
8150		dns_rdata_t rdata = DNS_RDATA_INIT;
8151
8152		dns_rdataset_current(&rdataset, &rdata);
8153		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8154				    rdataset.ttl, &rdata));
8155	}
8156	if (result == ISC_R_NOMORE) {
8157		result = ISC_R_SUCCESS;
8158	}
8159failure:
8160	dns_rdataset_disassociate(&rdataset);
8161	return (result);
8162}
8163
8164static isc_result_t
8165deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8166		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
8167		    dns_diff_t *diff) {
8168	dns_rdataset_t rdataset;
8169	dns_rdata_nsec3_t nsec3;
8170	isc_result_t result;
8171
8172	dns_rdataset_init(&rdataset);
8173	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0,
8174				     &rdataset, NULL);
8175	if (result == ISC_R_NOTFOUND) {
8176		return (ISC_R_SUCCESS);
8177	}
8178	if (result != ISC_R_SUCCESS) {
8179		return (result);
8180	}
8181
8182	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8183	     result = dns_rdataset_next(&rdataset))
8184	{
8185		dns_rdata_t rdata = DNS_RDATA_INIT;
8186
8187		dns_rdataset_current(&rdataset, &rdata);
8188		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
8189		if (nsec3.hash != param->hash ||
8190		    nsec3.iterations != param->iterations ||
8191		    nsec3.salt_length != param->salt_length ||
8192		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
8193		{
8194			continue;
8195		}
8196		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8197				    rdataset.ttl, &rdata));
8198	}
8199	if (result == ISC_R_NOMORE) {
8200		result = ISC_R_SUCCESS;
8201	}
8202failure:
8203	dns_rdataset_disassociate(&rdataset);
8204	return (result);
8205}
8206
8207static isc_result_t
8208need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
8209		const dns_rdata_nsec3param_t *param, bool *answer) {
8210	dns_dbnode_t *node = NULL;
8211	dns_rdata_t rdata = DNS_RDATA_INIT;
8212	dns_rdata_nsec3param_t myparam;
8213	dns_rdataset_t rdataset;
8214	isc_result_t result;
8215
8216	*answer = false;
8217
8218	result = dns_db_getoriginnode(db, &node);
8219	RUNTIME_CHECK(result == ISC_R_SUCCESS);
8220
8221	dns_rdataset_init(&rdataset);
8222
8223	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8224				     &rdataset, NULL);
8225	if (result == ISC_R_SUCCESS) {
8226		dns_rdataset_disassociate(&rdataset);
8227		dns_db_detachnode(db, &node);
8228		return (result);
8229	}
8230	if (result != ISC_R_NOTFOUND) {
8231		dns_db_detachnode(db, &node);
8232		return (result);
8233	}
8234
8235	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8236				     0, &rdataset, NULL);
8237	if (result == ISC_R_NOTFOUND) {
8238		*answer = true;
8239		dns_db_detachnode(db, &node);
8240		return (ISC_R_SUCCESS);
8241	}
8242	if (result != ISC_R_SUCCESS) {
8243		dns_db_detachnode(db, &node);
8244		return (result);
8245	}
8246
8247	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8248	     result = dns_rdataset_next(&rdataset))
8249	{
8250		dns_rdataset_current(&rdataset, &rdata);
8251		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
8252		dns_rdata_reset(&rdata);
8253		/*
8254		 * Ignore any NSEC3PARAM removals.
8255		 */
8256		if (NSEC3REMOVE(myparam.flags)) {
8257			continue;
8258		}
8259		/*
8260		 * Ignore the chain that we are in the process of deleting.
8261		 */
8262		if (myparam.hash == param->hash &&
8263		    myparam.iterations == param->iterations &&
8264		    myparam.salt_length == param->salt_length &&
8265		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
8266		{
8267			continue;
8268		}
8269		/*
8270		 * Found an active NSEC3 chain.
8271		 */
8272		break;
8273	}
8274	if (result == ISC_R_NOMORE) {
8275		*answer = true;
8276		result = ISC_R_SUCCESS;
8277	}
8278
8279failure:
8280	if (dns_rdataset_isassociated(&rdataset)) {
8281		dns_rdataset_disassociate(&rdataset);
8282	}
8283	dns_db_detachnode(db, &node);
8284	return (result);
8285}
8286
8287/*%
8288 * Given a tuple which is part of a diff, return a pointer to the next tuple in
8289 * that diff which has the same name and type (or NULL if no such tuple is
8290 * found).
8291 */
8292static dns_difftuple_t *
8293find_next_matching_tuple(dns_difftuple_t *cur) {
8294	dns_difftuple_t *next = cur;
8295
8296	while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
8297		if (cur->rdata.type == next->rdata.type &&
8298		    dns_name_equal(&cur->name, &next->name))
8299		{
8300			return (next);
8301		}
8302	}
8303
8304	return (NULL);
8305}
8306
8307/*%
8308 * Remove all tuples with the same name and type as 'cur' from 'src' and append
8309 * them to 'dst'.
8310 */
8311static void
8312move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
8313	do {
8314		dns_difftuple_t *next = find_next_matching_tuple(cur);
8315		ISC_LIST_UNLINK(src->tuples, cur, link);
8316		dns_diff_appendminimal(dst, &cur);
8317		cur = next;
8318	} while (cur != NULL);
8319}
8320
8321/*%
8322 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
8323 * 'diff'.  Gradually remove tuples from 'diff' and append them to 'zonediff'
8324 * along with tuples representing relevant signature changes.
8325 */
8326isc_result_t
8327dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
8328		     dst_key_t *zone_keys[], unsigned int nkeys,
8329		     dns_zone_t *zone, isc_stdtime_t inception,
8330		     isc_stdtime_t expire, isc_stdtime_t keyexpire,
8331		     isc_stdtime_t now, bool check_ksk, bool keyset_kskonly,
8332		     dns__zonediff_t *zonediff) {
8333	dns_difftuple_t *tuple;
8334	isc_result_t result;
8335
8336	while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
8337		isc_stdtime_t exp = expire;
8338
8339		if (keyexpire != 0 &&
8340		    (tuple->rdata.type == dns_rdatatype_dnskey ||
8341		     tuple->rdata.type == dns_rdatatype_cdnskey ||
8342		     tuple->rdata.type == dns_rdatatype_cds))
8343		{
8344			exp = keyexpire;
8345		}
8346
8347		result = del_sigs(zone, db, version, &tuple->name,
8348				  tuple->rdata.type, zonediff, zone_keys, nkeys,
8349				  now, false);
8350		if (result != ISC_R_SUCCESS) {
8351			dns_zone_log(zone, ISC_LOG_ERROR,
8352				     "dns__zone_updatesigs:del_sigs -> %s",
8353				     isc_result_totext(result));
8354			return (result);
8355		}
8356		result = add_sigs(db, version, &tuple->name, zone,
8357				  tuple->rdata.type, zonediff->diff, zone_keys,
8358				  nkeys, zone->mctx, now, inception, exp,
8359				  check_ksk, keyset_kskonly);
8360		if (result != ISC_R_SUCCESS) {
8361			dns_zone_log(zone, ISC_LOG_ERROR,
8362				     "dns__zone_updatesigs:add_sigs -> %s",
8363				     isc_result_totext(result));
8364			return (result);
8365		}
8366
8367		/*
8368		 * Signature changes for all RRs with name tuple->name and type
8369		 * tuple->rdata.type were appended to zonediff->diff.  Now we
8370		 * remove all the "raw" changes with the same name and type
8371		 * from diff (so that they are not processed by this loop
8372		 * again) and append them to zonediff so that they get applied.
8373		 */
8374		move_matching_tuples(tuple, diff, zonediff->diff);
8375	}
8376	return (ISC_R_SUCCESS);
8377}
8378
8379/*
8380 * Incrementally build and sign a new NSEC3 chain using the parameters
8381 * requested.
8382 */
8383static void
8384zone_nsec3chain(dns_zone_t *zone) {
8385	const char *me = "zone_nsec3chain";
8386	dns_db_t *db = NULL;
8387	dns_dbnode_t *node = NULL;
8388	dns_dbversion_t *version = NULL;
8389	dns_diff_t _sig_diff;
8390	dns_diff_t nsec_diff;
8391	dns_diff_t nsec3_diff;
8392	dns_diff_t param_diff;
8393	dns__zonediff_t zonediff;
8394	dns_fixedname_t fixed;
8395	dns_fixedname_t nextfixed;
8396	dns_name_t *name, *nextname;
8397	dns_rdataset_t rdataset;
8398	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
8399	dns_nsec3chainlist_t cleanup;
8400	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8401	int32_t signatures;
8402	bool check_ksk, keyset_kskonly;
8403	bool delegation;
8404	bool first;
8405	isc_result_t result;
8406	isc_stdtime_t now, inception, soaexpire, expire;
8407	uint32_t jitter, sigvalidityinterval, expiryinterval;
8408	unsigned int i;
8409	unsigned int nkeys = 0;
8410	uint32_t nodes;
8411	bool unsecure = false;
8412	bool seen_soa, seen_ns, seen_dname, seen_ds;
8413	bool seen_nsec, seen_nsec3, seen_rr;
8414	dns_rdatasetiter_t *iterator = NULL;
8415	bool buildnsecchain;
8416	bool updatensec = false;
8417	dns_rdatatype_t privatetype = zone->privatetype;
8418
8419	ENTER;
8420
8421	dns_rdataset_init(&rdataset);
8422	name = dns_fixedname_initname(&fixed);
8423	nextname = dns_fixedname_initname(&nextfixed);
8424	dns_diff_init(zone->mctx, &param_diff);
8425	dns_diff_init(zone->mctx, &nsec3_diff);
8426	dns_diff_init(zone->mctx, &nsec_diff);
8427	dns_diff_init(zone->mctx, &_sig_diff);
8428	zonediff_init(&zonediff, &_sig_diff);
8429	ISC_LIST_INIT(cleanup);
8430
8431	/*
8432	 * Updates are disabled.  Pause for 5 minutes.
8433	 */
8434	if (zone->update_disabled) {
8435		result = ISC_R_FAILURE;
8436		goto failure;
8437	}
8438
8439	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8440	/*
8441	 * This function is called when zone timer fires, after the latter gets
8442	 * set by zone_addnsec3chain().  If the action triggering the call to
8443	 * zone_addnsec3chain() is closely followed by a zone deletion request,
8444	 * it might turn out that the timer thread will not be woken up until
8445	 * after the zone is deleted by rmzone(), which calls dns_db_detach()
8446	 * for zone->db, causing the latter to become NULL.  Return immediately
8447	 * if that happens.
8448	 */
8449	if (zone->db != NULL) {
8450		dns_db_attach(zone->db, &db);
8451	}
8452	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8453	if (db == NULL) {
8454		return;
8455	}
8456
8457	result = dns_db_newversion(db, &version);
8458	if (result != ISC_R_SUCCESS) {
8459		dnssec_log(zone, ISC_LOG_ERROR,
8460			   "zone_nsec3chain:dns_db_newversion -> %s",
8461			   isc_result_totext(result));
8462		goto failure;
8463	}
8464
8465	isc_stdtime_get(&now);
8466
8467	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8468				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
8469	if (result != ISC_R_SUCCESS) {
8470		dnssec_log(zone, ISC_LOG_ERROR,
8471			   "zone_nsec3chain:dns__zone_findkeys -> %s",
8472			   isc_result_totext(result));
8473		goto failure;
8474	}
8475
8476	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8477	inception = now - 3600; /* Allow for clock skew. */
8478	soaexpire = now + sigvalidityinterval;
8479	expiryinterval = dns_zone_getsigresigninginterval(zone);
8480	if (expiryinterval > sigvalidityinterval) {
8481		expiryinterval = sigvalidityinterval;
8482	} else {
8483		expiryinterval = sigvalidityinterval - expiryinterval;
8484	}
8485
8486	/*
8487	 * Spread out signatures over time if they happen to be
8488	 * clumped.  We don't do this for each add_sigs() call as
8489	 * we still want some clustering to occur.
8490	 */
8491	if (sigvalidityinterval >= 3600U) {
8492		if (sigvalidityinterval > 7200U) {
8493			jitter = isc_random_uniform(expiryinterval);
8494		} else {
8495			jitter = isc_random_uniform(1200);
8496		}
8497		expire = soaexpire - jitter - 1;
8498	} else {
8499		expire = soaexpire - 1;
8500	}
8501
8502	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8503	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8504
8505	/*
8506	 * We keep pulling nodes off each iterator in turn until
8507	 * we have no more nodes to pull off or we reach the limits
8508	 * for this quantum.
8509	 */
8510	nodes = zone->nodes;
8511	signatures = zone->signatures;
8512	LOCK_ZONE(zone);
8513	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8514	UNLOCK_ZONE(zone);
8515	first = true;
8516
8517	if (nsec3chain != NULL) {
8518		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8519	}
8520	/*
8521	 * Generate new NSEC3 chains first.
8522	 *
8523	 * The following while loop iterates over nodes in the zone database,
8524	 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
8525	 * them.  Once all nodes are processed, the "delete_nsec" field is
8526	 * consulted to check whether we are supposed to remove NSEC records
8527	 * from the zone database; if so, the database iterator is reset to
8528	 * point to the first node and the loop traverses all of them again,
8529	 * this time removing NSEC records.  If we hit a node which is obscured
8530	 * by a delegation or a DNAME, nodes are skipped over until we find one
8531	 * that is not obscured by the same obscuring name and then normal
8532	 * processing is resumed.
8533	 *
8534	 * The above is repeated until all requested NSEC3 chain changes are
8535	 * applied or when we reach the limits for this quantum, whichever
8536	 * happens first.
8537	 *
8538	 * Note that the "signatures" variable is only used here to limit the
8539	 * amount of work performed.  Actual DNSSEC signatures are only
8540	 * generated by dns__zone_updatesigs() calls later in this function.
8541	 */
8542	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8543		dns_dbiterator_pause(nsec3chain->dbiterator);
8544
8545		LOCK_ZONE(zone);
8546		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8547
8548		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8549		if (nsec3chain->done || nsec3chain->db != zone->db) {
8550			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
8551			ISC_LIST_APPEND(cleanup, nsec3chain, link);
8552		}
8553		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8554		UNLOCK_ZONE(zone);
8555		if (ISC_LIST_TAIL(cleanup) == nsec3chain) {
8556			goto next_addchain;
8557		}
8558
8559		/*
8560		 * Possible future db.
8561		 */
8562		if (nsec3chain->db != db) {
8563			goto next_addchain;
8564		}
8565
8566		if (NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8567			goto next_addchain;
8568		}
8569
8570		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8571
8572		if (nsec3chain->delete_nsec) {
8573			delegation = false;
8574			dns_dbiterator_pause(nsec3chain->dbiterator);
8575			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
8576			goto next_addnode;
8577		}
8578		/*
8579		 * On the first pass we need to check if the current node
8580		 * has not been obscured.
8581		 */
8582		delegation = false;
8583		unsecure = false;
8584		if (first) {
8585			dns_fixedname_t ffound;
8586			dns_name_t *found;
8587			found = dns_fixedname_initname(&ffound);
8588			result = dns_db_find(
8589				db, name, version, dns_rdatatype_soa,
8590				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8591			if ((result == DNS_R_DELEGATION ||
8592			     result == DNS_R_DNAME) &&
8593			    !dns_name_equal(name, found))
8594			{
8595				/*
8596				 * Remember the obscuring name so that
8597				 * we skip all obscured names.
8598				 */
8599				dns_name_copy(found, name);
8600				delegation = true;
8601				goto next_addnode;
8602			}
8603		}
8604
8605		/*
8606		 * Check to see if this is a bottom of zone node.
8607		 */
8608		result = dns_db_allrdatasets(db, node, version, 0, 0,
8609					     &iterator);
8610		if (result == ISC_R_NOTFOUND) {
8611			/* Empty node? */
8612			goto next_addnode;
8613		}
8614		if (result != ISC_R_SUCCESS) {
8615			goto failure;
8616		}
8617
8618		seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
8619		for (result = dns_rdatasetiter_first(iterator);
8620		     result == ISC_R_SUCCESS;
8621		     result = dns_rdatasetiter_next(iterator))
8622		{
8623			dns_rdatasetiter_current(iterator, &rdataset);
8624			INSIST(rdataset.type != dns_rdatatype_nsec3);
8625			if (rdataset.type == dns_rdatatype_soa) {
8626				seen_soa = true;
8627			} else if (rdataset.type == dns_rdatatype_ns) {
8628				seen_ns = true;
8629			} else if (rdataset.type == dns_rdatatype_dname) {
8630				seen_dname = true;
8631			} else if (rdataset.type == dns_rdatatype_ds) {
8632				seen_ds = true;
8633			} else if (rdataset.type == dns_rdatatype_nsec) {
8634				seen_nsec = true;
8635			}
8636			dns_rdataset_disassociate(&rdataset);
8637		}
8638		dns_rdatasetiter_destroy(&iterator);
8639		/*
8640		 * Is there a NSEC chain than needs to be cleaned up?
8641		 */
8642		if (seen_nsec) {
8643			nsec3chain->seen_nsec = true;
8644		}
8645		if (seen_ns && !seen_soa && !seen_ds) {
8646			unsecure = true;
8647		}
8648		if ((seen_ns && !seen_soa) || seen_dname) {
8649			delegation = true;
8650		}
8651
8652		/*
8653		 * Process one node.
8654		 */
8655		dns_dbiterator_pause(nsec3chain->dbiterator);
8656		result = dns_nsec3_addnsec3(
8657			db, version, name, &nsec3chain->nsec3param,
8658			zone_nsecttl(zone), unsecure, &nsec3_diff);
8659		if (result != ISC_R_SUCCESS) {
8660			dnssec_log(zone, ISC_LOG_ERROR,
8661				   "zone_nsec3chain:"
8662				   "dns_nsec3_addnsec3 -> %s",
8663				   isc_result_totext(result));
8664			goto failure;
8665		}
8666
8667		/*
8668		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
8669		 * two signatures.  Additionally there will, in general, be
8670		 * two signature generated below.
8671		 *
8672		 * If we are only changing the optout flag the cost is half
8673		 * that of the cost of generating a completely new chain.
8674		 */
8675		signatures -= 4;
8676
8677		/*
8678		 * Go onto next node.
8679		 */
8680	next_addnode:
8681		first = false;
8682		dns_db_detachnode(db, &node);
8683		do {
8684			result = dns_dbiterator_next(nsec3chain->dbiterator);
8685
8686			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
8687				dns_dbiterator_pause(nsec3chain->dbiterator);
8688				CHECK(fixup_nsec3param(db, version, nsec3chain,
8689						       false, privatetype,
8690						       &param_diff));
8691				LOCK_ZONE(zone);
8692				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8693						link);
8694				UNLOCK_ZONE(zone);
8695				ISC_LIST_APPEND(cleanup, nsec3chain, link);
8696				goto next_addchain;
8697			}
8698			if (result == ISC_R_NOMORE) {
8699				dns_dbiterator_pause(nsec3chain->dbiterator);
8700				if (nsec3chain->seen_nsec) {
8701					CHECK(fixup_nsec3param(
8702						db, version, nsec3chain, true,
8703						privatetype, &param_diff));
8704					nsec3chain->delete_nsec = true;
8705					goto same_addchain;
8706				}
8707				CHECK(fixup_nsec3param(db, version, nsec3chain,
8708						       false, privatetype,
8709						       &param_diff));
8710				LOCK_ZONE(zone);
8711				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8712						link);
8713				UNLOCK_ZONE(zone);
8714				ISC_LIST_APPEND(cleanup, nsec3chain, link);
8715				goto next_addchain;
8716			} else if (result != ISC_R_SUCCESS) {
8717				dnssec_log(zone, ISC_LOG_ERROR,
8718					   "zone_nsec3chain:"
8719					   "dns_dbiterator_next -> %s",
8720					   isc_result_totext(result));
8721				goto failure;
8722			} else if (delegation) {
8723				dns_dbiterator_current(nsec3chain->dbiterator,
8724						       &node, nextname);
8725				dns_db_detachnode(db, &node);
8726				if (!dns_name_issubdomain(nextname, name)) {
8727					break;
8728				}
8729			} else {
8730				break;
8731			}
8732		} while (1);
8733		continue;
8734
8735	same_addchain:
8736		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8737		first = true;
8738		continue;
8739
8740	next_addchain:
8741		dns_dbiterator_pause(nsec3chain->dbiterator);
8742		nsec3chain = nextnsec3chain;
8743		first = true;
8744		if (nsec3chain != NULL) {
8745			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8746		}
8747	}
8748
8749	if (nsec3chain != NULL) {
8750		goto skip_removals;
8751	}
8752
8753	/*
8754	 * Process removals.
8755	 *
8756	 * This is a counterpart of the above while loop which takes care of
8757	 * removing an NSEC3 chain.  It starts with determining whether the
8758	 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
8759	 * NSEC chain by iterating over all nodes in the zone database and only
8760	 * then goes on to remove NSEC3 records be iterating over all nodes
8761	 * again and calling deletematchingnsec3() for each of them; otherwise,
8762	 * it starts removing NSEC3 records immediately.  Rules for processing
8763	 * obscured nodes and interrupting work are the same as for the while
8764	 * loop above.
8765	 */
8766	LOCK_ZONE(zone);
8767	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8768	UNLOCK_ZONE(zone);
8769	first = true;
8770	buildnsecchain = false;
8771	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8772		dns_dbiterator_pause(nsec3chain->dbiterator);
8773
8774		LOCK_ZONE(zone);
8775		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8776		UNLOCK_ZONE(zone);
8777
8778		if (nsec3chain->db != db) {
8779			goto next_removechain;
8780		}
8781
8782		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8783			goto next_removechain;
8784		}
8785
8786		/*
8787		 * Work out if we need to build a NSEC chain as a consequence
8788		 * of removing this NSEC3 chain.
8789		 */
8790		if (first && !updatensec &&
8791		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8792		{
8793			result = need_nsec_chain(db, version,
8794						 &nsec3chain->nsec3param,
8795						 &buildnsecchain);
8796			if (result != ISC_R_SUCCESS) {
8797				dnssec_log(zone, ISC_LOG_ERROR,
8798					   "zone_nsec3chain:"
8799					   "need_nsec_chain -> %s",
8800					   isc_result_totext(result));
8801				goto failure;
8802			}
8803		}
8804
8805		if (first) {
8806			dnssec_log(zone, ISC_LOG_DEBUG(3),
8807				   "zone_nsec3chain:buildnsecchain = %u\n",
8808				   buildnsecchain);
8809		}
8810
8811		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8812		dns_dbiterator_pause(nsec3chain->dbiterator);
8813		delegation = false;
8814
8815		if (!buildnsecchain) {
8816			/*
8817			 * Delete the NSEC3PARAM record matching this chain.
8818			 */
8819			if (first) {
8820				result = fixup_nsec3param(
8821					db, version, nsec3chain, true,
8822					privatetype, &param_diff);
8823				if (result != ISC_R_SUCCESS) {
8824					dnssec_log(zone, ISC_LOG_ERROR,
8825						   "zone_nsec3chain:"
8826						   "fixup_nsec3param -> %s",
8827						   isc_result_totext(result));
8828					goto failure;
8829				}
8830			}
8831
8832			/*
8833			 * Delete the NSEC3 records.
8834			 */
8835			result = deletematchingnsec3(db, version, node, name,
8836						     &nsec3chain->nsec3param,
8837						     &nsec3_diff);
8838			if (result != ISC_R_SUCCESS) {
8839				dnssec_log(zone, ISC_LOG_ERROR,
8840					   "zone_nsec3chain:"
8841					   "deletematchingnsec3 -> %s",
8842					   isc_result_totext(result));
8843				goto failure;
8844			}
8845			goto next_removenode;
8846		}
8847
8848		if (first) {
8849			dns_fixedname_t ffound;
8850			dns_name_t *found;
8851			found = dns_fixedname_initname(&ffound);
8852			result = dns_db_find(
8853				db, name, version, dns_rdatatype_soa,
8854				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8855			if ((result == DNS_R_DELEGATION ||
8856			     result == DNS_R_DNAME) &&
8857			    !dns_name_equal(name, found))
8858			{
8859				/*
8860				 * Remember the obscuring name so that
8861				 * we skip all obscured names.
8862				 */
8863				dns_name_copy(found, name);
8864				delegation = true;
8865				goto next_removenode;
8866			}
8867		}
8868
8869		/*
8870		 * Check to see if this is a bottom of zone node.
8871		 */
8872		result = dns_db_allrdatasets(db, node, version, 0, 0,
8873					     &iterator);
8874		if (result == ISC_R_NOTFOUND) {
8875			/* Empty node? */
8876			goto next_removenode;
8877		}
8878		if (result != ISC_R_SUCCESS) {
8879			goto failure;
8880		}
8881
8882		seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
8883			seen_rr = false;
8884		for (result = dns_rdatasetiter_first(iterator);
8885		     result == ISC_R_SUCCESS;
8886		     result = dns_rdatasetiter_next(iterator))
8887		{
8888			dns_rdatasetiter_current(iterator, &rdataset);
8889			if (rdataset.type == dns_rdatatype_soa) {
8890				seen_soa = true;
8891			} else if (rdataset.type == dns_rdatatype_ns) {
8892				seen_ns = true;
8893			} else if (rdataset.type == dns_rdatatype_dname) {
8894				seen_dname = true;
8895			} else if (rdataset.type == dns_rdatatype_nsec) {
8896				seen_nsec = true;
8897			} else if (rdataset.type == dns_rdatatype_nsec3) {
8898				seen_nsec3 = true;
8899			} else if (rdataset.type != dns_rdatatype_rrsig) {
8900				seen_rr = true;
8901			}
8902			dns_rdataset_disassociate(&rdataset);
8903		}
8904		dns_rdatasetiter_destroy(&iterator);
8905
8906		if (!seen_rr || seen_nsec3 || seen_nsec) {
8907			goto next_removenode;
8908		}
8909		if ((seen_ns && !seen_soa) || seen_dname) {
8910			delegation = true;
8911		}
8912
8913		/*
8914		 * Add a NSEC record except at the origin.
8915		 */
8916		if (!dns_name_equal(name, dns_db_origin(db))) {
8917			dns_dbiterator_pause(nsec3chain->dbiterator);
8918			CHECK(add_nsec(db, version, name, node,
8919				       zone_nsecttl(zone), delegation,
8920				       &nsec_diff));
8921			signatures--;
8922		}
8923
8924	next_removenode:
8925		first = false;
8926		dns_db_detachnode(db, &node);
8927		do {
8928			result = dns_dbiterator_next(nsec3chain->dbiterator);
8929			if (result == ISC_R_NOMORE && buildnsecchain) {
8930				/*
8931				 * The NSEC chain should now be built.
8932				 * We can now remove the NSEC3 chain.
8933				 */
8934				updatensec = true;
8935				goto same_removechain;
8936			}
8937			if (result == ISC_R_NOMORE) {
8938				dns_dbiterator_pause(nsec3chain->dbiterator);
8939				LOCK_ZONE(zone);
8940				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8941						link);
8942				UNLOCK_ZONE(zone);
8943				ISC_LIST_APPEND(cleanup, nsec3chain, link);
8944				result = fixup_nsec3param(
8945					db, version, nsec3chain, false,
8946					privatetype, &param_diff);
8947				if (result != ISC_R_SUCCESS) {
8948					dnssec_log(zone, ISC_LOG_ERROR,
8949						   "zone_nsec3chain:"
8950						   "fixup_nsec3param -> %s",
8951						   isc_result_totext(result));
8952					goto failure;
8953				}
8954				goto next_removechain;
8955			} else if (result != ISC_R_SUCCESS) {
8956				dnssec_log(zone, ISC_LOG_ERROR,
8957					   "zone_nsec3chain:"
8958					   "dns_dbiterator_next -> %s",
8959					   isc_result_totext(result));
8960				goto failure;
8961			} else if (delegation) {
8962				dns_dbiterator_current(nsec3chain->dbiterator,
8963						       &node, nextname);
8964				dns_db_detachnode(db, &node);
8965				if (!dns_name_issubdomain(nextname, name)) {
8966					break;
8967				}
8968			} else {
8969				break;
8970			}
8971		} while (1);
8972		continue;
8973
8974	same_removechain:
8975		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8976		buildnsecchain = false;
8977		first = true;
8978		continue;
8979
8980	next_removechain:
8981		dns_dbiterator_pause(nsec3chain->dbiterator);
8982		nsec3chain = nextnsec3chain;
8983		first = true;
8984	}
8985
8986skip_removals:
8987	/*
8988	 * We may need to update the NSEC/NSEC3 records for the zone apex.
8989	 */
8990	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
8991		bool rebuild_nsec = false, rebuild_nsec3 = false;
8992		result = dns_db_getoriginnode(db, &node);
8993		RUNTIME_CHECK(result == ISC_R_SUCCESS);
8994		result = dns_db_allrdatasets(db, node, version, 0, 0,
8995					     &iterator);
8996		if (result != ISC_R_SUCCESS) {
8997			dnssec_log(zone, ISC_LOG_ERROR,
8998				   "zone_nsec3chain:dns_db_allrdatasets -> %s",
8999				   isc_result_totext(result));
9000			goto failure;
9001		}
9002		for (result = dns_rdatasetiter_first(iterator);
9003		     result == ISC_R_SUCCESS;
9004		     result = dns_rdatasetiter_next(iterator))
9005		{
9006			dns_rdatasetiter_current(iterator, &rdataset);
9007			if (rdataset.type == dns_rdatatype_nsec) {
9008				rebuild_nsec = true;
9009			} else if (rdataset.type == dns_rdatatype_nsec3param) {
9010				rebuild_nsec3 = true;
9011			}
9012			dns_rdataset_disassociate(&rdataset);
9013		}
9014		dns_rdatasetiter_destroy(&iterator);
9015		dns_db_detachnode(db, &node);
9016
9017		if (rebuild_nsec) {
9018			if (nsec3chain != NULL) {
9019				dns_dbiterator_pause(nsec3chain->dbiterator);
9020			}
9021
9022			result = updatesecure(db, version, &zone->origin,
9023					      zone_nsecttl(zone), true,
9024					      &nsec_diff);
9025			if (result != ISC_R_SUCCESS) {
9026				dnssec_log(zone, ISC_LOG_ERROR,
9027					   "zone_nsec3chain:updatesecure -> %s",
9028					   isc_result_totext(result));
9029				goto failure;
9030			}
9031		}
9032
9033		if (rebuild_nsec3) {
9034			if (nsec3chain != NULL) {
9035				dns_dbiterator_pause(nsec3chain->dbiterator);
9036			}
9037
9038			result = dns_nsec3_addnsec3s(
9039				db, version, dns_db_origin(db),
9040				zone_nsecttl(zone), false, &nsec3_diff);
9041			if (result != ISC_R_SUCCESS) {
9042				dnssec_log(zone, ISC_LOG_ERROR,
9043					   "zone_nsec3chain:"
9044					   "dns_nsec3_addnsec3s -> %s",
9045					   isc_result_totext(result));
9046				goto failure;
9047			}
9048		}
9049	}
9050
9051	/*
9052	 * Add / update signatures for the NSEC3 records.
9053	 */
9054	if (nsec3chain != NULL) {
9055		dns_dbiterator_pause(nsec3chain->dbiterator);
9056	}
9057	result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
9058				      nkeys, zone, inception, expire, 0, now,
9059				      check_ksk, keyset_kskonly, &zonediff);
9060	if (result != ISC_R_SUCCESS) {
9061		dnssec_log(zone, ISC_LOG_ERROR,
9062			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
9063			   isc_result_totext(result));
9064		goto failure;
9065	}
9066
9067	/*
9068	 * We have changed the NSEC3PARAM or private RRsets
9069	 * above so we need to update the signatures.
9070	 */
9071	result = dns__zone_updatesigs(&param_diff, db, version, zone_keys,
9072				      nkeys, zone, inception, expire, 0, now,
9073				      check_ksk, keyset_kskonly, &zonediff);
9074	if (result != ISC_R_SUCCESS) {
9075		dnssec_log(zone, ISC_LOG_ERROR,
9076			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
9077			   isc_result_totext(result));
9078		goto failure;
9079	}
9080
9081	if (updatensec) {
9082		result = updatesecure(db, version, &zone->origin,
9083				      zone_nsecttl(zone), false, &nsec_diff);
9084		if (result != ISC_R_SUCCESS) {
9085			dnssec_log(zone, ISC_LOG_ERROR,
9086				   "zone_nsec3chain:updatesecure -> %s",
9087				   isc_result_totext(result));
9088			goto failure;
9089		}
9090	}
9091
9092	result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys, nkeys,
9093				      zone, inception, expire, 0, now,
9094				      check_ksk, keyset_kskonly, &zonediff);
9095	if (result != ISC_R_SUCCESS) {
9096		dnssec_log(zone, ISC_LOG_ERROR,
9097			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
9098			   isc_result_totext(result));
9099		goto failure;
9100	}
9101
9102	/*
9103	 * If we made no effective changes to the zone then we can just
9104	 * cleanup otherwise we need to increment the serial.
9105	 */
9106	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9107		/*
9108		 * No need to call dns_db_closeversion() here as it is
9109		 * called with commit = true below.
9110		 */
9111		goto done;
9112	}
9113
9114	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9115			  &zonediff, zone_keys, nkeys, now, false);
9116	if (result != ISC_R_SUCCESS) {
9117		dnssec_log(zone, ISC_LOG_ERROR,
9118			   "zone_nsec3chain:del_sigs -> %s",
9119			   isc_result_totext(result));
9120		goto failure;
9121	}
9122
9123	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9124				   zone->updatemethod);
9125	if (result != ISC_R_SUCCESS) {
9126		dnssec_log(zone, ISC_LOG_ERROR,
9127			   "zone_nsec3chain:update_soa_serial -> %s",
9128			   isc_result_totext(result));
9129		goto failure;
9130	}
9131
9132	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9133			  zonediff.diff, zone_keys, nkeys, zone->mctx, now,
9134			  inception, soaexpire, check_ksk, keyset_kskonly);
9135	if (result != ISC_R_SUCCESS) {
9136		dnssec_log(zone, ISC_LOG_ERROR,
9137			   "zone_nsec3chain:add_sigs -> %s",
9138			   isc_result_totext(result));
9139		goto failure;
9140	}
9141
9142	/* Write changes to journal file. */
9143	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
9144
9145	LOCK_ZONE(zone);
9146	zone_needdump(zone, DNS_DUMP_DELAY);
9147	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9148	UNLOCK_ZONE(zone);
9149
9150done:
9151	/*
9152	 * Pause all iterators so that dns_db_closeversion() can succeed.
9153	 */
9154	LOCK_ZONE(zone);
9155	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9156	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9157	{
9158		dns_dbiterator_pause(nsec3chain->dbiterator);
9159	}
9160	UNLOCK_ZONE(zone);
9161
9162	/*
9163	 * Everything has succeeded. Commit the changes.
9164	 * Unconditionally commit as zonediff.offline not checked above.
9165	 */
9166	dns_db_closeversion(db, &version, true);
9167
9168	/*
9169	 * Everything succeeded so we can clean these up now.
9170	 */
9171	nsec3chain = ISC_LIST_HEAD(cleanup);
9172	while (nsec3chain != NULL) {
9173		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9174		dns_db_detach(&nsec3chain->db);
9175		dns_dbiterator_destroy(&nsec3chain->dbiterator);
9176		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9177		nsec3chain = ISC_LIST_HEAD(cleanup);
9178	}
9179
9180	LOCK_ZONE(zone);
9181	set_resigntime(zone);
9182	UNLOCK_ZONE(zone);
9183
9184failure:
9185	if (result != ISC_R_SUCCESS) {
9186		dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
9187			   isc_result_totext(result));
9188	}
9189
9190	/*
9191	 * On error roll back the current nsec3chain.
9192	 */
9193	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
9194		if (nsec3chain->done) {
9195			dns_db_detach(&nsec3chain->db);
9196			dns_dbiterator_destroy(&nsec3chain->dbiterator);
9197			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9198		} else {
9199			result = dns_dbiterator_first(nsec3chain->dbiterator);
9200			RUNTIME_CHECK(result == ISC_R_SUCCESS);
9201			dns_dbiterator_pause(nsec3chain->dbiterator);
9202			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9203		}
9204	}
9205
9206	/*
9207	 * Rollback the cleanup list.
9208	 */
9209	nsec3chain = ISC_LIST_TAIL(cleanup);
9210	while (nsec3chain != NULL) {
9211		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9212		if (nsec3chain->done) {
9213			dns_db_detach(&nsec3chain->db);
9214			dns_dbiterator_destroy(&nsec3chain->dbiterator);
9215			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9216		} else {
9217			LOCK_ZONE(zone);
9218			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
9219			UNLOCK_ZONE(zone);
9220			result = dns_dbiterator_first(nsec3chain->dbiterator);
9221			RUNTIME_CHECK(result == ISC_R_SUCCESS);
9222			dns_dbiterator_pause(nsec3chain->dbiterator);
9223			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9224		}
9225		nsec3chain = ISC_LIST_TAIL(cleanup);
9226	}
9227
9228	LOCK_ZONE(zone);
9229	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9230	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9231	{
9232		dns_dbiterator_pause(nsec3chain->dbiterator);
9233	}
9234	UNLOCK_ZONE(zone);
9235
9236	dns_diff_clear(&param_diff);
9237	dns_diff_clear(&nsec3_diff);
9238	dns_diff_clear(&nsec_diff);
9239	dns_diff_clear(&_sig_diff);
9240
9241	if (iterator != NULL) {
9242		dns_rdatasetiter_destroy(&iterator);
9243	}
9244
9245	for (i = 0; i < nkeys; i++) {
9246		dst_key_free(&zone_keys[i]);
9247	}
9248
9249	if (node != NULL) {
9250		dns_db_detachnode(db, &node);
9251	}
9252	if (version != NULL) {
9253		dns_db_closeversion(db, &version, false);
9254		dns_db_detach(&db);
9255	} else if (db != NULL) {
9256		dns_db_detach(&db);
9257	}
9258
9259	LOCK_ZONE(zone);
9260	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
9261		isc_interval_t interval;
9262		if (zone->update_disabled || result != ISC_R_SUCCESS) {
9263			isc_interval_set(&interval, 60, 0); /* 1 minute */
9264		} else {
9265			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9266		}
9267		isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
9268	} else {
9269		isc_time_settoepoch(&zone->nsec3chaintime);
9270	}
9271	UNLOCK_ZONE(zone);
9272
9273	INSIST(version == NULL);
9274}
9275
9276/*%
9277 * Delete all RRSIG records with the given algorithm and keyid.
9278 * Remove the NSEC record and RRSIGs if nkeys is zero.
9279 * If all remaining RRsets are signed with the given algorithm
9280 * set *has_algp to true.
9281 */
9282static isc_result_t
9283del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
9284	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
9285	uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
9286	dns_rdata_rrsig_t rrsig;
9287	dns_rdataset_t rdataset;
9288	dns_rdatasetiter_t *iterator = NULL;
9289	isc_result_t result;
9290	bool alg_missed = false;
9291	bool alg_found = false;
9292
9293	char namebuf[DNS_NAME_FORMATSIZE];
9294	dns_name_format(name, namebuf, sizeof(namebuf));
9295
9296	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
9297	if (result != ISC_R_SUCCESS) {
9298		if (result == ISC_R_NOTFOUND) {
9299			result = ISC_R_SUCCESS;
9300		}
9301		return (result);
9302	}
9303
9304	dns_rdataset_init(&rdataset);
9305	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
9306	     result = dns_rdatasetiter_next(iterator))
9307	{
9308		bool has_alg = false;
9309		dns_rdatasetiter_current(iterator, &rdataset);
9310		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
9311			for (result = dns_rdataset_first(&rdataset);
9312			     result == ISC_R_SUCCESS;
9313			     result = dns_rdataset_next(&rdataset))
9314			{
9315				dns_rdata_t rdata = DNS_RDATA_INIT;
9316				dns_rdataset_current(&rdataset, &rdata);
9317				CHECK(update_one_rr(db, version, diff,
9318						    DNS_DIFFOP_DEL, name,
9319						    rdataset.ttl, &rdata));
9320			}
9321			if (result != ISC_R_NOMORE) {
9322				goto failure;
9323			}
9324			dns_rdataset_disassociate(&rdataset);
9325			continue;
9326		}
9327		if (rdataset.type != dns_rdatatype_rrsig) {
9328			dns_rdataset_disassociate(&rdataset);
9329			continue;
9330		}
9331		for (result = dns_rdataset_first(&rdataset);
9332		     result == ISC_R_SUCCESS;
9333		     result = dns_rdataset_next(&rdataset))
9334		{
9335			dns_rdata_t rdata = DNS_RDATA_INIT;
9336			dns_rdataset_current(&rdataset, &rdata);
9337			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
9338			if (nkeys != 0 && (rrsig.algorithm != algorithm ||
9339					   rrsig.keyid != keyid))
9340			{
9341				if (rrsig.algorithm == algorithm) {
9342					has_alg = true;
9343				}
9344				continue;
9345			}
9346			CHECK(update_one_rr(db, version, diff,
9347					    DNS_DIFFOP_DELRESIGN, name,
9348					    rdataset.ttl, &rdata));
9349		}
9350		dns_rdataset_disassociate(&rdataset);
9351		if (result != ISC_R_NOMORE) {
9352			break;
9353		}
9354
9355		/*
9356		 * After deleting, if there's still a signature for
9357		 * 'algorithm', set alg_found; if not, set alg_missed.
9358		 */
9359		if (has_alg) {
9360			alg_found = true;
9361		} else {
9362			alg_missed = true;
9363		}
9364	}
9365	if (result == ISC_R_NOMORE) {
9366		result = ISC_R_SUCCESS;
9367	}
9368
9369	/*
9370	 * Set `has_algp` if the algorithm was found in every RRset:
9371	 * i.e., found in at least one, and not missing from any.
9372	 */
9373	*has_algp = (alg_found && !alg_missed);
9374failure:
9375	if (dns_rdataset_isassociated(&rdataset)) {
9376		dns_rdataset_disassociate(&rdataset);
9377	}
9378	dns_rdatasetiter_destroy(&iterator);
9379	return (result);
9380}
9381
9382/*
9383 * Prevent the zone entering a inconsistent state where
9384 * NSEC only DNSKEYs are present with NSEC3 chains.
9385 */
9386bool
9387dns_zone_check_dnskey_nsec3(dns_zone_t *zone, dns_db_t *db,
9388			    dns_dbversion_t *ver, dns_diff_t *diff,
9389			    dst_key_t **keys, unsigned int numkeys) {
9390	uint8_t alg;
9391	dns_rdatatype_t privatetype;
9392	;
9393	bool nseconly = false, nsec3 = false;
9394	isc_result_t result;
9395
9396	REQUIRE(DNS_ZONE_VALID(zone));
9397	REQUIRE(db != NULL);
9398
9399	privatetype = dns_zone_getprivatetype(zone);
9400
9401	/* Scan the tuples for an NSEC-only DNSKEY */
9402	if (diff != NULL) {
9403		for (dns_difftuple_t *tuple = ISC_LIST_HEAD(diff->tuples);
9404		     tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
9405		{
9406			if (nseconly && nsec3) {
9407				break;
9408			}
9409
9410			if (tuple->op != DNS_DIFFOP_ADD) {
9411				continue;
9412			}
9413
9414			if (tuple->rdata.type == dns_rdatatype_nsec3param) {
9415				nsec3 = true;
9416			}
9417
9418			if (tuple->rdata.type != dns_rdatatype_dnskey) {
9419				continue;
9420			}
9421
9422			alg = tuple->rdata.data[3];
9423			if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DH ||
9424			    alg == DNS_KEYALG_DSA || alg == DNS_KEYALG_RSASHA1)
9425			{
9426				nseconly = true;
9427			}
9428		}
9429	}
9430	/* Scan the zone keys for an NSEC-only DNSKEY */
9431	if (keys != NULL && !nseconly) {
9432		for (unsigned int i = 0; i < numkeys; i++) {
9433			alg = dst_key_alg(keys[i]);
9434			if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DH ||
9435			    alg == DNS_KEYALG_DSA || alg == DNS_KEYALG_RSASHA1)
9436			{
9437				nseconly = true;
9438				break;
9439			}
9440		}
9441	}
9442
9443	/* Check DB for NSEC-only DNSKEY */
9444	if (!nseconly) {
9445		result = dns_nsec_nseconly(db, ver, diff, &nseconly);
9446		/*
9447		 * Adding an NSEC3PARAM record can proceed without a
9448		 * DNSKEY (it will trigger a delayed change), so we can
9449		 * ignore ISC_R_NOTFOUND here.
9450		 */
9451		if (result == ISC_R_NOTFOUND) {
9452			result = ISC_R_SUCCESS;
9453		}
9454		CHECK(result);
9455	}
9456
9457	/* Check existing DB for NSEC3 */
9458	if (!nsec3) {
9459		CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3));
9460	}
9461
9462	/* Check kasp for NSEC3PARAM settings */
9463	if (!nsec3) {
9464		dns_kasp_t *kasp = dns_zone_getkasp(zone);
9465		if (kasp != NULL) {
9466			nsec3 = dns_kasp_nsec3(kasp);
9467		}
9468	}
9469
9470	/* Refuse to allow NSEC3 with NSEC-only keys */
9471	if (nseconly && nsec3) {
9472		goto failure;
9473	}
9474
9475	return (true);
9476
9477failure:
9478	return (false);
9479}
9480
9481/*
9482 * Incrementally sign the zone using the keys requested.
9483 * Builds the NSEC chain if required.
9484 */
9485static void
9486zone_sign(dns_zone_t *zone) {
9487	const char *me = "zone_sign";
9488	dns_db_t *db = NULL;
9489	dns_dbnode_t *node = NULL;
9490	dns_dbversion_t *version = NULL;
9491	dns_diff_t _sig_diff;
9492	dns_diff_t post_diff;
9493	dns__zonediff_t zonediff;
9494	dns_fixedname_t fixed;
9495	dns_fixedname_t nextfixed;
9496	dns_kasp_t *kasp;
9497	dns_name_t *name, *nextname;
9498	dns_rdataset_t rdataset;
9499	dns_signing_t *signing, *nextsigning;
9500	dns_signinglist_t cleanup;
9501	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
9502	int32_t signatures;
9503	bool check_ksk, keyset_kskonly, is_ksk, is_zsk;
9504	bool with_ksk, with_zsk;
9505	bool commit = false;
9506	bool is_bottom_of_zone;
9507	bool build_nsec = false;
9508	bool build_nsec3 = false;
9509	bool use_kasp = false;
9510	bool first;
9511	isc_result_t result;
9512	isc_stdtime_t now, inception, soaexpire, expire;
9513	uint32_t jitter, sigvalidityinterval, expiryinterval;
9514	unsigned int i, j;
9515	unsigned int nkeys = 0;
9516	uint32_t nodes;
9517
9518	ENTER;
9519
9520	dns_rdataset_init(&rdataset);
9521	name = dns_fixedname_initname(&fixed);
9522	nextname = dns_fixedname_initname(&nextfixed);
9523	dns_diff_init(zone->mctx, &_sig_diff);
9524	dns_diff_init(zone->mctx, &post_diff);
9525	zonediff_init(&zonediff, &_sig_diff);
9526	ISC_LIST_INIT(cleanup);
9527
9528	/*
9529	 * Updates are disabled.  Pause for 1 minute.
9530	 */
9531	if (zone->update_disabled) {
9532		result = ISC_R_FAILURE;
9533		goto cleanup;
9534	}
9535
9536	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9537	if (zone->db != NULL) {
9538		dns_db_attach(zone->db, &db);
9539	}
9540	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9541	if (db == NULL) {
9542		result = ISC_R_FAILURE;
9543		goto cleanup;
9544	}
9545
9546	result = dns_db_newversion(db, &version);
9547	if (result != ISC_R_SUCCESS) {
9548		dnssec_log(zone, ISC_LOG_ERROR,
9549			   "zone_sign:dns_db_newversion -> %s",
9550			   isc_result_totext(result));
9551		goto cleanup;
9552	}
9553
9554	isc_stdtime_get(&now);
9555
9556	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
9557				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
9558	if (result != ISC_R_SUCCESS) {
9559		dnssec_log(zone, ISC_LOG_ERROR,
9560			   "zone_sign:dns__zone_findkeys -> %s",
9561			   isc_result_totext(result));
9562		goto cleanup;
9563	}
9564
9565	kasp = dns_zone_getkasp(zone);
9566	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
9567	inception = now - 3600; /* Allow for clock skew. */
9568	soaexpire = now + sigvalidityinterval;
9569	expiryinterval = dns_zone_getsigresigninginterval(zone);
9570	if (expiryinterval > sigvalidityinterval) {
9571		expiryinterval = sigvalidityinterval;
9572	} else {
9573		expiryinterval = sigvalidityinterval - expiryinterval;
9574	}
9575
9576	/*
9577	 * Spread out signatures over time if they happen to be
9578	 * clumped.  We don't do this for each add_sigs() call as
9579	 * we still want some clustering to occur.
9580	 */
9581	if (sigvalidityinterval >= 3600U) {
9582		if (sigvalidityinterval > 7200U) {
9583			jitter = isc_random_uniform(expiryinterval);
9584		} else {
9585			jitter = isc_random_uniform(1200);
9586		}
9587		expire = soaexpire - jitter - 1;
9588	} else {
9589		expire = soaexpire - 1;
9590	}
9591
9592	/*
9593	 * We keep pulling nodes off each iterator in turn until
9594	 * we have no more nodes to pull off or we reach the limits
9595	 * for this quantum.
9596	 */
9597	nodes = zone->nodes;
9598	signatures = zone->signatures;
9599	signing = ISC_LIST_HEAD(zone->signing);
9600	first = true;
9601
9602	if (dns_zone_getkasp(zone) != NULL) {
9603		check_ksk = false;
9604		keyset_kskonly = true;
9605		use_kasp = true;
9606	} else {
9607		check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
9608		keyset_kskonly = DNS_ZONE_OPTION(zone,
9609						 DNS_ZONEOPT_DNSKEYKSKONLY);
9610	}
9611	dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
9612		   use_kasp ? "yes" : "no");
9613
9614	/* Determine which type of chain to build */
9615	CHECK(dns_private_chains(db, version, zone->privatetype, &build_nsec,
9616				 &build_nsec3));
9617	if (!build_nsec && !build_nsec3) {
9618		if (use_kasp) {
9619			build_nsec3 = dns_kasp_nsec3(kasp);
9620			if (!dns_zone_check_dnskey_nsec3(
9621				    zone, db, version, NULL,
9622				    (dst_key_t **)&zone_keys, nkeys))
9623			{
9624				dnssec_log(zone, ISC_LOG_INFO,
9625					   "wait building NSEC3 chain until "
9626					   "NSEC only DNSKEYs are removed");
9627				build_nsec3 = false;
9628			}
9629			build_nsec = !build_nsec3;
9630		} else {
9631			/* If neither chain is found, default to NSEC */
9632			build_nsec = true;
9633		}
9634	}
9635
9636	while (signing != NULL && nodes-- > 0 && signatures > 0) {
9637		bool has_alg = false;
9638
9639		dns_dbiterator_pause(signing->dbiterator);
9640		nextsigning = ISC_LIST_NEXT(signing, link);
9641
9642		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9643		if (signing->done || signing->db != zone->db) {
9644			/*
9645			 * The zone has been reloaded.	We will have to
9646			 * created new signings as part of the reload
9647			 * process so we can destroy this one.
9648			 */
9649			ISC_LIST_UNLINK(zone->signing, signing, link);
9650			ISC_LIST_APPEND(cleanup, signing, link);
9651			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9652			goto next_signing;
9653		}
9654		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9655
9656		if (signing->db != db) {
9657			goto next_signing;
9658		}
9659
9660		is_bottom_of_zone = false;
9661
9662		if (first && signing->deleteit) {
9663			/*
9664			 * Remove the key we are deleting from consideration.
9665			 */
9666			for (i = 0, j = 0; i < nkeys; i++) {
9667				/*
9668				 * Find the key we want to remove.
9669				 */
9670				if (ALG(zone_keys[i]) == signing->algorithm &&
9671				    dst_key_id(zone_keys[i]) == signing->keyid)
9672				{
9673					dst_key_free(&zone_keys[i]);
9674					continue;
9675				}
9676				zone_keys[j] = zone_keys[i];
9677				j++;
9678			}
9679			for (i = j; i < nkeys; i++) {
9680				zone_keys[i] = NULL;
9681			}
9682			nkeys = j;
9683		}
9684
9685		dns_dbiterator_current(signing->dbiterator, &node, name);
9686
9687		if (signing->deleteit) {
9688			dns_dbiterator_pause(signing->dbiterator);
9689			CHECK(del_sig(db, version, name, node, nkeys,
9690				      signing->algorithm, signing->keyid,
9691				      &has_alg, zonediff.diff));
9692		}
9693
9694		/*
9695		 * On the first pass we need to check if the current node
9696		 * has not been obscured.
9697		 */
9698		if (first) {
9699			dns_fixedname_t ffound;
9700			dns_name_t *found;
9701			found = dns_fixedname_initname(&ffound);
9702			result = dns_db_find(
9703				db, name, version, dns_rdatatype_soa,
9704				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
9705			if ((result == DNS_R_DELEGATION ||
9706			     result == DNS_R_DNAME) &&
9707			    !dns_name_equal(name, found))
9708			{
9709				/*
9710				 * Remember the obscuring name so that
9711				 * we skip all obscured names.
9712				 */
9713				dns_name_copy(found, name);
9714				is_bottom_of_zone = true;
9715				goto next_node;
9716			}
9717		}
9718
9719		/*
9720		 * Process one node.
9721		 */
9722		with_ksk = false;
9723		with_zsk = false;
9724		dns_dbiterator_pause(signing->dbiterator);
9725
9726		CHECK(check_if_bottom_of_zone(db, node, version,
9727					      &is_bottom_of_zone));
9728
9729		for (i = 0; !has_alg && i < nkeys; i++) {
9730			bool both = false;
9731
9732			/*
9733			 * Find the keys we want to sign with.
9734			 */
9735			if (!dst_key_isprivate(zone_keys[i])) {
9736				continue;
9737			}
9738			if (dst_key_inactive(zone_keys[i])) {
9739				continue;
9740			}
9741
9742			/*
9743			 * When adding look for the specific key.
9744			 */
9745			if (!signing->deleteit &&
9746			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
9747			     dst_key_id(zone_keys[i]) != signing->keyid))
9748			{
9749				continue;
9750			}
9751
9752			/*
9753			 * When deleting make sure we are properly signed
9754			 * with the algorithm that was being removed.
9755			 */
9756			if (signing->deleteit &&
9757			    ALG(zone_keys[i]) != signing->algorithm)
9758			{
9759				continue;
9760			}
9761
9762			/*
9763			 * Do we do KSK processing?
9764			 */
9765			if (check_ksk && !REVOKE(zone_keys[i])) {
9766				bool have_ksk, have_nonksk;
9767				if (KSK(zone_keys[i])) {
9768					have_ksk = true;
9769					have_nonksk = false;
9770				} else {
9771					have_ksk = false;
9772					have_nonksk = true;
9773				}
9774				for (j = 0; j < nkeys; j++) {
9775					if (j == i || (ALG(zone_keys[i]) !=
9776						       ALG(zone_keys[j])))
9777					{
9778						continue;
9779					}
9780					/*
9781					 * Don't consider inactive keys, however
9782					 * the key may be temporary offline, so
9783					 * do consider KSKs which private key
9784					 * files are unavailable.
9785					 */
9786					if (dst_key_inactive(zone_keys[j])) {
9787						continue;
9788					}
9789					if (REVOKE(zone_keys[j])) {
9790						continue;
9791					}
9792					if (KSK(zone_keys[j])) {
9793						have_ksk = true;
9794					} else if (dst_key_isprivate(
9795							   zone_keys[j]))
9796					{
9797						have_nonksk = true;
9798					}
9799					both = have_ksk && have_nonksk;
9800					if (both) {
9801						break;
9802					}
9803				}
9804			}
9805			if (use_kasp) {
9806				/*
9807				 * A dnssec-policy is found. Check what
9808				 * RRsets this key can sign.
9809				 */
9810				isc_result_t kresult;
9811				is_ksk = false;
9812				kresult = dst_key_getbool(
9813					zone_keys[i], DST_BOOL_KSK, &is_ksk);
9814				if (kresult != ISC_R_SUCCESS) {
9815					if (KSK(zone_keys[i])) {
9816						is_ksk = true;
9817					}
9818				}
9819
9820				is_zsk = false;
9821				kresult = dst_key_getbool(
9822					zone_keys[i], DST_BOOL_ZSK, &is_zsk);
9823				if (kresult != ISC_R_SUCCESS) {
9824					if (!KSK(zone_keys[i])) {
9825						is_zsk = true;
9826					}
9827				}
9828				/* Treat as if we have both KSK and ZSK. */
9829				both = true;
9830			} else if (both || REVOKE(zone_keys[i])) {
9831				is_ksk = KSK(zone_keys[i]);
9832				is_zsk = !KSK(zone_keys[i]);
9833			} else {
9834				is_ksk = false;
9835				is_zsk = true;
9836			}
9837
9838			/*
9839			 * If deleting signatures, we need to ensure that
9840			 * the RRset is still signed at least once by a
9841			 * KSK and a ZSK.
9842			 */
9843			if (signing->deleteit && is_zsk && with_zsk) {
9844				continue;
9845			}
9846
9847			if (signing->deleteit && is_ksk && with_ksk) {
9848				continue;
9849			}
9850
9851			CHECK(sign_a_node(
9852				db, zone, name, node, version, build_nsec3,
9853				build_nsec, zone_keys[i], now, inception,
9854				expire, zone_nsecttl(zone), is_ksk, is_zsk,
9855				(both && keyset_kskonly), is_bottom_of_zone,
9856				zonediff.diff, &signatures, zone->mctx));
9857			/*
9858			 * If we are adding we are done.  Look for other keys
9859			 * of the same algorithm if deleting.
9860			 */
9861			if (!signing->deleteit) {
9862				break;
9863			}
9864			if (is_zsk) {
9865				with_zsk = true;
9866			}
9867			if (is_ksk) {
9868				with_ksk = true;
9869			}
9870		}
9871
9872		/*
9873		 * Go onto next node.
9874		 */
9875	next_node:
9876		first = false;
9877		dns_db_detachnode(db, &node);
9878		do {
9879			result = dns_dbiterator_next(signing->dbiterator);
9880			if (result == ISC_R_NOMORE) {
9881				ISC_LIST_UNLINK(zone->signing, signing, link);
9882				ISC_LIST_APPEND(cleanup, signing, link);
9883				dns_dbiterator_pause(signing->dbiterator);
9884				if (nkeys != 0 && build_nsec) {
9885					/*
9886					 * We have finished regenerating the
9887					 * zone with a zone signing key.
9888					 * The NSEC chain is now complete and
9889					 * there is a full set of signatures
9890					 * for the zone.  We can now clear the
9891					 * OPT bit from the NSEC record.
9892					 */
9893					result = updatesecure(
9894						db, version, &zone->origin,
9895						zone_nsecttl(zone), false,
9896						&post_diff);
9897					if (result != ISC_R_SUCCESS) {
9898						dnssec_log(zone, ISC_LOG_ERROR,
9899							   "updatesecure -> %s",
9900							   isc_result_totext(
9901								   result));
9902						goto cleanup;
9903					}
9904				}
9905				result = updatesignwithkey(
9906					zone, signing, version, build_nsec3,
9907					zone_nsecttl(zone), &post_diff);
9908				if (result != ISC_R_SUCCESS) {
9909					dnssec_log(zone, ISC_LOG_ERROR,
9910						   "updatesignwithkey -> %s",
9911						   isc_result_totext(result));
9912					goto cleanup;
9913				}
9914				build_nsec = false;
9915				goto next_signing;
9916			} else if (result != ISC_R_SUCCESS) {
9917				dnssec_log(zone, ISC_LOG_ERROR,
9918					   "zone_sign:"
9919					   "dns_dbiterator_next -> %s",
9920					   isc_result_totext(result));
9921				goto cleanup;
9922			} else if (is_bottom_of_zone) {
9923				dns_dbiterator_current(signing->dbiterator,
9924						       &node, nextname);
9925				dns_db_detachnode(db, &node);
9926				if (!dns_name_issubdomain(nextname, name)) {
9927					break;
9928				}
9929			} else {
9930				break;
9931			}
9932		} while (1);
9933		continue;
9934
9935	next_signing:
9936		dns_dbiterator_pause(signing->dbiterator);
9937		signing = nextsigning;
9938		first = true;
9939	}
9940
9941	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9942		result = dns__zone_updatesigs(&post_diff, db, version,
9943					      zone_keys, nkeys, zone, inception,
9944					      expire, 0, now, check_ksk,
9945					      keyset_kskonly, &zonediff);
9946		if (result != ISC_R_SUCCESS) {
9947			dnssec_log(zone, ISC_LOG_ERROR,
9948				   "zone_sign:dns__zone_updatesigs -> %s",
9949				   isc_result_totext(result));
9950			goto cleanup;
9951		}
9952	}
9953
9954	/*
9955	 * Have we changed anything?
9956	 */
9957	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9958		if (zonediff.offline) {
9959			commit = true;
9960		}
9961		result = ISC_R_SUCCESS;
9962		goto pauseall;
9963	}
9964
9965	commit = true;
9966
9967	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9968			  &zonediff, zone_keys, nkeys, now, false);
9969	if (result != ISC_R_SUCCESS) {
9970		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9971			   isc_result_totext(result));
9972		goto cleanup;
9973	}
9974
9975	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9976				   zone->updatemethod);
9977	if (result != ISC_R_SUCCESS) {
9978		dnssec_log(zone, ISC_LOG_ERROR,
9979			   "zone_sign:update_soa_serial -> %s",
9980			   isc_result_totext(result));
9981		goto cleanup;
9982	}
9983
9984	/*
9985	 * Generate maximum life time signatures so that the above loop
9986	 * termination is sensible.
9987	 */
9988	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9989			  zonediff.diff, zone_keys, nkeys, zone->mctx, now,
9990			  inception, soaexpire, check_ksk, keyset_kskonly);
9991	if (result != ISC_R_SUCCESS) {
9992		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
9993			   isc_result_totext(result));
9994		goto cleanup;
9995	}
9996
9997	/*
9998	 * Write changes to journal file.
9999	 */
10000	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
10001
10002pauseall:
10003	/*
10004	 * Pause all iterators so that dns_db_closeversion() can succeed.
10005	 */
10006	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10007	     signing = ISC_LIST_NEXT(signing, link))
10008	{
10009		dns_dbiterator_pause(signing->dbiterator);
10010	}
10011
10012	for (signing = ISC_LIST_HEAD(cleanup); signing != NULL;
10013	     signing = ISC_LIST_NEXT(signing, link))
10014	{
10015		dns_dbiterator_pause(signing->dbiterator);
10016	}
10017
10018	/*
10019	 * Everything has succeeded. Commit the changes.
10020	 */
10021	dns_db_closeversion(db, &version, commit);
10022
10023	/*
10024	 * Everything succeeded so we can clean these up now.
10025	 */
10026	signing = ISC_LIST_HEAD(cleanup);
10027	while (signing != NULL) {
10028		ISC_LIST_UNLINK(cleanup, signing, link);
10029		dns_db_detach(&signing->db);
10030		dns_dbiterator_destroy(&signing->dbiterator);
10031		isc_mem_put(zone->mctx, signing, sizeof *signing);
10032		signing = ISC_LIST_HEAD(cleanup);
10033	}
10034
10035	LOCK_ZONE(zone);
10036	set_resigntime(zone);
10037	if (commit) {
10038		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10039		zone_needdump(zone, DNS_DUMP_DELAY);
10040	}
10041	UNLOCK_ZONE(zone);
10042
10043failure:
10044	if (result != ISC_R_SUCCESS) {
10045		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
10046			   isc_result_totext(result));
10047	}
10048
10049cleanup:
10050	/*
10051	 * Pause all dbiterators.
10052	 */
10053	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10054	     signing = ISC_LIST_NEXT(signing, link))
10055	{
10056		dns_dbiterator_pause(signing->dbiterator);
10057	}
10058
10059	/*
10060	 * Rollback the cleanup list.
10061	 */
10062	signing = ISC_LIST_HEAD(cleanup);
10063	while (signing != NULL) {
10064		ISC_LIST_UNLINK(cleanup, signing, link);
10065		ISC_LIST_PREPEND(zone->signing, signing, link);
10066		dns_dbiterator_first(signing->dbiterator);
10067		dns_dbiterator_pause(signing->dbiterator);
10068		signing = ISC_LIST_HEAD(cleanup);
10069	}
10070
10071	dns_diff_clear(&_sig_diff);
10072
10073	for (i = 0; i < nkeys; i++) {
10074		dst_key_free(&zone_keys[i]);
10075	}
10076
10077	if (node != NULL) {
10078		dns_db_detachnode(db, &node);
10079	}
10080
10081	if (version != NULL) {
10082		dns_db_closeversion(db, &version, false);
10083		dns_db_detach(&db);
10084	} else if (db != NULL) {
10085		dns_db_detach(&db);
10086	}
10087
10088	LOCK_ZONE(zone);
10089	if (ISC_LIST_HEAD(zone->signing) != NULL) {
10090		isc_interval_t interval;
10091		if (zone->update_disabled || result != ISC_R_SUCCESS) {
10092			isc_interval_set(&interval, 60, 0); /* 1 minute */
10093		} else {
10094			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
10095		}
10096		isc_time_nowplusinterval(&zone->signingtime, &interval);
10097	} else {
10098		isc_time_settoepoch(&zone->signingtime);
10099	}
10100	UNLOCK_ZONE(zone);
10101
10102	INSIST(version == NULL);
10103}
10104
10105static isc_result_t
10106normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data,
10107	      int size) {
10108	dns_rdata_dnskey_t dnskey;
10109	dns_rdata_keydata_t keydata;
10110	isc_buffer_t buf;
10111	isc_result_t result;
10112
10113	dns_rdata_reset(target);
10114	isc_buffer_init(&buf, data, size);
10115
10116	switch (rr->type) {
10117	case dns_rdatatype_dnskey:
10118		result = dns_rdata_tostruct(rr, &dnskey, NULL);
10119		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10120		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
10121		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10122				     &dnskey, &buf);
10123		break;
10124	case dns_rdatatype_keydata:
10125		result = dns_rdata_tostruct(rr, &keydata, NULL);
10126		if (result == ISC_R_UNEXPECTEDEND) {
10127			return (result);
10128		}
10129		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10130		dns_keydata_todnskey(&keydata, &dnskey, NULL);
10131		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10132				     &dnskey, &buf);
10133		break;
10134	default:
10135		UNREACHABLE();
10136	}
10137	return (ISC_R_SUCCESS);
10138}
10139
10140/*
10141 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
10142 * a KEYDATA rdataset from the key zone.
10143 *
10144 * 'rr' contains either a DNSKEY record, or a KEYDATA record
10145 *
10146 * After normalizing keys to the same format (DNSKEY, with revoke bit
10147 * cleared), return true if a key that matches 'rr' is found in
10148 * 'rdset', or false if not.
10149 */
10150
10151static bool
10152matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
10153	unsigned char data1[4096], data2[4096];
10154	dns_rdata_t rdata, rdata1, rdata2;
10155	isc_result_t result;
10156
10157	dns_rdata_init(&rdata);
10158	dns_rdata_init(&rdata1);
10159	dns_rdata_init(&rdata2);
10160
10161	result = normalize_key(rr, &rdata1, data1, sizeof(data1));
10162	if (result != ISC_R_SUCCESS) {
10163		return (false);
10164	}
10165
10166	for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS;
10167	     result = dns_rdataset_next(rdset))
10168	{
10169		dns_rdata_reset(&rdata);
10170		dns_rdataset_current(rdset, &rdata);
10171		result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
10172		if (result != ISC_R_SUCCESS) {
10173			continue;
10174		}
10175		if (dns_rdata_compare(&rdata1, &rdata2) == 0) {
10176			return (true);
10177		}
10178	}
10179
10180	return (false);
10181}
10182
10183/*
10184 * Calculate the refresh interval for a keydata zone, per
10185 * RFC5011: MAX(1 hr,
10186 *		MIN(15 days,
10187 *		    1/2 * OrigTTL,
10188 *		    1/2 * RRSigExpirationInterval))
10189 * or for retries: MAX(1 hr,
10190 *		       MIN(1 day,
10191 *			   1/10 * OrigTTL,
10192 *			   1/10 * RRSigExpirationInterval))
10193 */
10194static isc_stdtime_t
10195refresh_time(dns_keyfetch_t *kfetch, bool retry) {
10196	isc_result_t result;
10197	uint32_t t;
10198	dns_rdataset_t *rdset;
10199	dns_rdata_t sigrr = DNS_RDATA_INIT;
10200	dns_rdata_sig_t sig;
10201	isc_stdtime_t now;
10202
10203	isc_stdtime_get(&now);
10204
10205	if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
10206		rdset = &kfetch->dnskeysigset;
10207	} else {
10208		return (now + dns_zone_mkey_hour);
10209	}
10210
10211	result = dns_rdataset_first(rdset);
10212	if (result != ISC_R_SUCCESS) {
10213		return (now + dns_zone_mkey_hour);
10214	}
10215
10216	dns_rdataset_current(rdset, &sigrr);
10217	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10218	RUNTIME_CHECK(result == ISC_R_SUCCESS);
10219
10220	if (!retry) {
10221		t = sig.originalttl / 2;
10222
10223		if (isc_serial_gt(sig.timeexpire, now)) {
10224			uint32_t exp = (sig.timeexpire - now) / 2;
10225			if (t > exp) {
10226				t = exp;
10227			}
10228		}
10229
10230		if (t > (15 * dns_zone_mkey_day)) {
10231			t = (15 * dns_zone_mkey_day);
10232		}
10233
10234		if (t < dns_zone_mkey_hour) {
10235			t = dns_zone_mkey_hour;
10236		}
10237	} else {
10238		t = sig.originalttl / 10;
10239
10240		if (isc_serial_gt(sig.timeexpire, now)) {
10241			uint32_t exp = (sig.timeexpire - now) / 10;
10242			if (t > exp) {
10243				t = exp;
10244			}
10245		}
10246
10247		if (t > dns_zone_mkey_day) {
10248			t = dns_zone_mkey_day;
10249		}
10250
10251		if (t < dns_zone_mkey_hour) {
10252			t = dns_zone_mkey_hour;
10253		}
10254	}
10255
10256	return (now + t);
10257}
10258
10259/*
10260 * This routine is called when no changes are needed in a KEYDATA
10261 * record except to simply update the refresh timer.  Caller should
10262 * hold zone lock.
10263 */
10264static isc_result_t
10265minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
10266	isc_result_t result;
10267	isc_buffer_t keyb;
10268	unsigned char key_buf[4096];
10269	dns_rdata_t rdata = DNS_RDATA_INIT;
10270	dns_rdata_keydata_t keydata;
10271	dns_name_t *name;
10272	dns_zone_t *zone = kfetch->zone;
10273	isc_stdtime_t now;
10274
10275	name = dns_fixedname_name(&kfetch->name);
10276	isc_stdtime_get(&now);
10277
10278	for (result = dns_rdataset_first(&kfetch->keydataset);
10279	     result == ISC_R_SUCCESS;
10280	     result = dns_rdataset_next(&kfetch->keydataset))
10281	{
10282		dns_rdata_reset(&rdata);
10283		dns_rdataset_current(&kfetch->keydataset, &rdata);
10284
10285		/* Delete old version */
10286		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, name,
10287				    0, &rdata));
10288
10289		/* Update refresh timer */
10290		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
10291		if (result == ISC_R_UNEXPECTEDEND) {
10292			continue;
10293		}
10294		if (result != ISC_R_SUCCESS) {
10295			goto failure;
10296		}
10297		keydata.refresh = refresh_time(kfetch, true);
10298		set_refreshkeytimer(zone, &keydata, now, false);
10299
10300		dns_rdata_reset(&rdata);
10301		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10302		CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
10303					   dns_rdatatype_keydata, &keydata,
10304					   &keyb));
10305
10306		/* Insert updated version */
10307		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, name,
10308				    0, &rdata));
10309	}
10310	result = ISC_R_SUCCESS;
10311failure:
10312	return (result);
10313}
10314
10315/*
10316 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
10317 */
10318static bool
10319revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
10320	isc_result_t result;
10321	dns_name_t *keyname;
10322	isc_mem_t *mctx;
10323	dns_rdata_t sigrr = DNS_RDATA_INIT;
10324	dns_rdata_t rr = DNS_RDATA_INIT;
10325	dns_rdata_rrsig_t sig;
10326	dns_rdata_dnskey_t dnskey;
10327	dst_key_t *dstkey = NULL;
10328	unsigned char key_buf[4096];
10329	isc_buffer_t keyb;
10330	bool answer = false;
10331
10332	REQUIRE(kfetch != NULL && keydata != NULL);
10333	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
10334
10335	keyname = dns_fixedname_name(&kfetch->name);
10336	mctx = kfetch->zone->view->mctx;
10337
10338	/* Generate a key from keydata */
10339	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10340	dns_keydata_todnskey(keydata, &dnskey, NULL);
10341	dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
10342			     &dnskey, &keyb);
10343	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
10344	if (result != ISC_R_SUCCESS) {
10345		return (false);
10346	}
10347
10348	/* See if that key generated any of the signatures */
10349	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
10350	     result == ISC_R_SUCCESS;
10351	     result = dns_rdataset_next(&kfetch->dnskeysigset))
10352	{
10353		dns_fixedname_t fixed;
10354		dns_fixedname_init(&fixed);
10355
10356		dns_rdata_reset(&sigrr);
10357		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
10358		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10359		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10360
10361		if (dst_key_alg(dstkey) == sig.algorithm &&
10362		    dst_key_rid(dstkey) == sig.keyid)
10363		{
10364			result = dns_dnssec_verify(
10365				keyname, &kfetch->dnskeyset, dstkey, false, 0,
10366				mctx, &sigrr, dns_fixedname_name(&fixed));
10367
10368			dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
10369				   "Confirm revoked DNSKEY is self-signed: %s",
10370				   isc_result_totext(result));
10371
10372			if (result == ISC_R_SUCCESS) {
10373				answer = true;
10374				break;
10375			}
10376		}
10377	}
10378
10379	dst_key_free(&dstkey);
10380	return (answer);
10381}
10382
10383/*
10384 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
10385 * anchors are being managed; scan the keyset, and update the key zone and the
10386 * local trust anchors according to RFC5011.
10387 */
10388static void
10389keyfetch_done(isc_task_t *task, isc_event_t *event) {
10390	isc_result_t result, eresult;
10391	dns_fetchevent_t *devent;
10392	dns_keyfetch_t *kfetch;
10393	dns_zone_t *zone;
10394	isc_mem_t *mctx = NULL;
10395	dns_keytable_t *secroots = NULL;
10396	dns_dbversion_t *ver = NULL;
10397	dns_diff_t diff;
10398	bool alldone = false;
10399	bool commit = false;
10400	dns_name_t *keyname = NULL;
10401	dns_rdata_t sigrr = DNS_RDATA_INIT;
10402	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
10403	dns_rdata_t keydatarr = DNS_RDATA_INIT;
10404	dns_rdata_rrsig_t sig;
10405	dns_rdata_dnskey_t dnskey;
10406	dns_rdata_keydata_t keydata;
10407	bool initializing;
10408	char namebuf[DNS_NAME_FORMATSIZE];
10409	unsigned char key_buf[4096];
10410	isc_buffer_t keyb;
10411	dst_key_t *dstkey = NULL;
10412	isc_stdtime_t now;
10413	int pending = 0;
10414	bool secure = false, initial = false;
10415	bool free_needed;
10416	dns_keynode_t *keynode = NULL;
10417	dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
10418	dns_rdataset_t *keydataset = NULL, dsset;
10419
10420	UNUSED(task);
10421	INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
10422	INSIST(event->ev_arg != NULL);
10423
10424	kfetch = event->ev_arg;
10425	zone = kfetch->zone;
10426	mctx = kfetch->mctx;
10427	keyname = dns_fixedname_name(&kfetch->name);
10428	dnskeys = &kfetch->dnskeyset;
10429	dnskeysigs = &kfetch->dnskeysigset;
10430	keydataset = &kfetch->keydataset;
10431
10432	devent = (dns_fetchevent_t *)event;
10433	eresult = devent->result;
10434
10435	/* Free resources which are not of interest */
10436	if (devent->node != NULL) {
10437		dns_db_detachnode(devent->db, &devent->node);
10438	}
10439	if (devent->db != NULL) {
10440		dns_db_detach(&devent->db);
10441	}
10442	isc_event_free(&event);
10443	dns_resolver_destroyfetch(&kfetch->fetch);
10444
10445	LOCK_ZONE(zone);
10446	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
10447		goto cleanup;
10448	}
10449
10450	isc_stdtime_get(&now);
10451	dns_name_format(keyname, namebuf, sizeof(namebuf));
10452
10453	result = dns_view_getsecroots(zone->view, &secroots);
10454	INSIST(result == ISC_R_SUCCESS);
10455
10456	dns_diff_init(mctx, &diff);
10457
10458	CHECK(dns_db_newversion(kfetch->db, &ver));
10459
10460	zone->refreshkeycount--;
10461	alldone = (zone->refreshkeycount == 0);
10462
10463	if (alldone) {
10464		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10465	}
10466
10467	dnssec_log(zone, ISC_LOG_DEBUG(3),
10468		   "Returned from key fetch in keyfetch_done() for '%s': %s",
10469		   namebuf, isc_result_totext(eresult));
10470
10471	/* Fetch failed */
10472	if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
10473		dnssec_log(zone, ISC_LOG_WARNING,
10474			   "Unable to fetch DNSKEY set '%s': %s", namebuf,
10475			   isc_result_totext(eresult));
10476		CHECK(minimal_update(kfetch, ver, &diff));
10477		goto done;
10478	}
10479
10480	/* No RRSIGs found */
10481	if (!dns_rdataset_isassociated(dnskeysigs)) {
10482		dnssec_log(zone, ISC_LOG_WARNING,
10483			   "No DNSKEY RRSIGs found for '%s': %s", namebuf,
10484			   isc_result_totext(eresult));
10485		CHECK(minimal_update(kfetch, ver, &diff));
10486		goto done;
10487	}
10488
10489	/*
10490	 * Clear any cached trust level, as we need to run validation
10491	 * over again; trusted keys might have changed.
10492	 */
10493	dnskeys->trust = dnskeysigs->trust = dns_trust_none;
10494
10495	/* Look up the trust anchor */
10496	result = dns_keytable_find(secroots, keyname, &keynode);
10497	if (result != ISC_R_SUCCESS) {
10498		goto anchors_done;
10499	}
10500
10501	/*
10502	 * If the keynode has a DS trust anchor, use it for verification.
10503	 */
10504	dns_rdataset_init(&dsset);
10505	if (dns_keynode_dsset(keynode, &dsset)) {
10506		for (result = dns_rdataset_first(dnskeysigs);
10507		     result == ISC_R_SUCCESS;
10508		     result = dns_rdataset_next(dnskeysigs))
10509		{
10510			isc_result_t tresult;
10511			dns_rdata_t keyrdata = DNS_RDATA_INIT;
10512
10513			dns_rdata_reset(&sigrr);
10514			dns_rdataset_current(dnskeysigs, &sigrr);
10515			result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10516			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10517
10518			for (tresult = dns_rdataset_first(&dsset);
10519			     tresult == ISC_R_SUCCESS;
10520			     tresult = dns_rdataset_next(&dsset))
10521			{
10522				dns_rdata_t dsrdata = DNS_RDATA_INIT;
10523				dns_rdata_ds_t ds;
10524
10525				dns_rdata_reset(&dsrdata);
10526				dns_rdataset_current(&dsset, &dsrdata);
10527				tresult = dns_rdata_tostruct(&dsrdata, &ds,
10528							     NULL);
10529				RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
10530
10531				if (ds.key_tag != sig.keyid ||
10532				    ds.algorithm != sig.algorithm)
10533				{
10534					continue;
10535				}
10536
10537				result = dns_dnssec_matchdskey(
10538					keyname, &dsrdata, dnskeys, &keyrdata);
10539				if (result == ISC_R_SUCCESS) {
10540					break;
10541				}
10542			}
10543
10544			if (tresult == ISC_R_NOMORE) {
10545				continue;
10546			}
10547
10548			result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
10549							 mctx, &dstkey);
10550			if (result != ISC_R_SUCCESS) {
10551				continue;
10552			}
10553
10554			result = dns_dnssec_verify(keyname, dnskeys, dstkey,
10555						   false, 0, mctx, &sigrr,
10556						   NULL);
10557			dst_key_free(&dstkey);
10558
10559			dnssec_log(zone, ISC_LOG_DEBUG(3),
10560				   "Verifying DNSKEY set for zone "
10561				   "'%s' using DS %d/%d: %s",
10562				   namebuf, sig.keyid, sig.algorithm,
10563				   isc_result_totext(result));
10564
10565			if (result == ISC_R_SUCCESS) {
10566				dnskeys->trust = dns_trust_secure;
10567				dnskeysigs->trust = dns_trust_secure;
10568				initial = dns_keynode_initial(keynode);
10569				dns_keynode_trust(keynode);
10570				secure = true;
10571				break;
10572			}
10573		}
10574		dns_rdataset_disassociate(&dsset);
10575	}
10576
10577anchors_done:
10578	if (keynode != NULL) {
10579		dns_keytable_detachkeynode(secroots, &keynode);
10580	}
10581
10582	/*
10583	 * If we were not able to verify the answer using the current
10584	 * trusted keys then all we can do is look at any revoked keys.
10585	 */
10586	if (!secure) {
10587		dnssec_log(zone, ISC_LOG_INFO,
10588			   "DNSKEY set for zone '%s' could not be verified "
10589			   "with current keys",
10590			   namebuf);
10591	}
10592
10593	/*
10594	 * First scan keydataset to find keys that are not in dnskeyset
10595	 *   - Missing keys which are not scheduled for removal,
10596	 *     log a warning
10597	 *   - Missing keys which are scheduled for removal and
10598	 *     the remove hold-down timer has completed should
10599	 *     be removed from the key zone
10600	 *   - Missing keys whose acceptance timers have not yet
10601	 *     completed, log a warning and reset the acceptance
10602	 *     timer to 30 days in the future
10603	 *   - All keys not being removed have their refresh timers
10604	 *     updated
10605	 */
10606	initializing = true;
10607	for (result = dns_rdataset_first(keydataset); result == ISC_R_SUCCESS;
10608	     result = dns_rdataset_next(keydataset))
10609	{
10610		dns_keytag_t keytag;
10611
10612		dns_rdata_reset(&keydatarr);
10613		dns_rdataset_current(keydataset, &keydatarr);
10614		result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10615		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10616
10617		dns_keydata_todnskey(&keydata, &dnskey, NULL);
10618		result = compute_tag(keyname, &dnskey, mctx, &keytag);
10619		if (result != ISC_R_SUCCESS) {
10620			/*
10621			 * Skip if we cannot compute the key tag.
10622			 * This may happen if the algorithm is unsupported
10623			 */
10624			dns_zone_log(zone, ISC_LOG_ERROR,
10625				     "Cannot compute tag for key in zone %s: "
10626				     "%s "
10627				     "(skipping)",
10628				     namebuf, isc_result_totext(result));
10629			continue;
10630		}
10631		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10632
10633		/*
10634		 * If any keydata record has a nonzero add holddown, then
10635		 * there was a pre-existing trust anchor for this domain;
10636		 * that means we are *not* initializing it and shouldn't
10637		 * automatically trust all the keys we find at the zone apex.
10638		 */
10639		initializing = initializing && (keydata.addhd == 0);
10640
10641		if (!matchkey(dnskeys, &keydatarr)) {
10642			bool deletekey = false;
10643
10644			if (!secure) {
10645				if (keydata.removehd != 0 &&
10646				    keydata.removehd <= now)
10647				{
10648					deletekey = true;
10649				}
10650			} else if (keydata.addhd == 0) {
10651				deletekey = true;
10652			} else if (keydata.addhd > now) {
10653				dnssec_log(zone, ISC_LOG_INFO,
10654					   "Pending key %d for zone %s "
10655					   "unexpectedly missing from DNSKEY "
10656					   "RRset: restarting 30-day "
10657					   "acceptance timer",
10658					   keytag, namebuf);
10659				if (keydata.addhd < now + dns_zone_mkey_month) {
10660					keydata.addhd = now +
10661							dns_zone_mkey_month;
10662				}
10663				keydata.refresh = refresh_time(kfetch, false);
10664			} else if (keydata.removehd == 0) {
10665				dnssec_log(zone, ISC_LOG_INFO,
10666					   "Active key %d for zone %s "
10667					   "unexpectedly missing from DNSKEY "
10668					   "RRset",
10669					   keytag, namebuf);
10670				keydata.refresh = now + dns_zone_mkey_hour;
10671			} else if (keydata.removehd <= now) {
10672				deletekey = true;
10673				dnssec_log(
10674					zone, ISC_LOG_INFO,
10675					"Revoked key %d for zone %s no longer "
10676					"present in DNSKEY RRset: deleting "
10677					"from managed keys database",
10678					keytag, namebuf);
10679			} else {
10680				keydata.refresh = refresh_time(kfetch, false);
10681			}
10682
10683			if (secure || deletekey) {
10684				/* Delete old version */
10685				CHECK(update_one_rr(kfetch->db, ver, &diff,
10686						    DNS_DIFFOP_DEL, keyname, 0,
10687						    &keydatarr));
10688			}
10689
10690			if (!secure || deletekey) {
10691				continue;
10692			}
10693
10694			dns_rdata_reset(&keydatarr);
10695			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10696			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10697					     dns_rdatatype_keydata, &keydata,
10698					     &keyb);
10699
10700			/* Insert updated version */
10701			CHECK(update_one_rr(kfetch->db, ver, &diff,
10702					    DNS_DIFFOP_ADD, keyname, 0,
10703					    &keydatarr));
10704
10705			set_refreshkeytimer(zone, &keydata, now, false);
10706		}
10707	}
10708
10709	/*
10710	 * Next scan dnskeyset:
10711	 *   - If new keys are found (i.e., lacking a match in keydataset)
10712	 *     add them to the key zone and set the acceptance timer
10713	 *     to 30 days in the future (or to immediately if we've
10714	 *     determined that we're initializing the zone for the
10715	 *     first time)
10716	 *   - Previously-known keys that have been revoked
10717	 *     must be scheduled for removal from the key zone (or,
10718	 *     if they hadn't been accepted as trust anchors yet
10719	 *     anyway, removed at once)
10720	 *   - Previously-known unrevoked keys whose acceptance timers
10721	 *     have completed are promoted to trust anchors
10722	 *   - All keys not being removed have their refresh
10723	 *     timers updated
10724	 */
10725	for (result = dns_rdataset_first(dnskeys); result == ISC_R_SUCCESS;
10726	     result = dns_rdataset_next(dnskeys))
10727	{
10728		bool revoked = false;
10729		bool newkey = false;
10730		bool updatekey = false;
10731		bool deletekey = false;
10732		bool trustkey = false;
10733		dns_keytag_t keytag;
10734
10735		dns_rdata_reset(&dnskeyrr);
10736		dns_rdataset_current(dnskeys, &dnskeyrr);
10737		result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10738		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10739
10740		/* Skip ZSK's */
10741		if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
10742			continue;
10743		}
10744
10745		result = compute_tag(keyname, &dnskey, mctx, &keytag);
10746		if (result != ISC_R_SUCCESS) {
10747			/*
10748			 * Skip if we cannot compute the key tag.
10749			 * This may happen if the algorithm is unsupported
10750			 */
10751			dns_zone_log(zone, ISC_LOG_ERROR,
10752				     "Cannot compute tag for key in zone %s: "
10753				     "%s "
10754				     "(skipping)",
10755				     namebuf, isc_result_totext(result));
10756			continue;
10757		}
10758		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10759
10760		revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
10761
10762		if (matchkey(keydataset, &dnskeyrr)) {
10763			dns_rdata_reset(&keydatarr);
10764			dns_rdataset_current(keydataset, &keydatarr);
10765			result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10766			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10767
10768			if (revoked && revocable(kfetch, &keydata)) {
10769				if (keydata.addhd > now) {
10770					/*
10771					 * Key wasn't trusted yet, and now
10772					 * it's been revoked?  Just remove it
10773					 */
10774					deletekey = true;
10775					dnssec_log(zone, ISC_LOG_INFO,
10776						   "Pending key %d for "
10777						   "zone %s is now revoked: "
10778						   "deleting from the "
10779						   "managed keys database",
10780						   keytag, namebuf);
10781				} else if (keydata.removehd == 0) {
10782					/*
10783					 * Remove key from secroots.
10784					 */
10785					dns_view_untrust(zone->view, keyname,
10786							 &dnskey);
10787
10788					/* If initializing, delete now */
10789					if (keydata.addhd == 0) {
10790						deletekey = true;
10791					} else {
10792						keydata.removehd =
10793							now +
10794							dns_zone_mkey_month;
10795						keydata.flags |=
10796							DNS_KEYFLAG_REVOKE;
10797					}
10798
10799					dnssec_log(zone, ISC_LOG_INFO,
10800						   "Trusted key %d for "
10801						   "zone %s is now revoked",
10802						   keytag, namebuf);
10803				} else if (keydata.removehd < now) {
10804					/* Scheduled for removal */
10805					deletekey = true;
10806
10807					dnssec_log(zone, ISC_LOG_INFO,
10808						   "Revoked key %d for "
10809						   "zone %s removal timer "
10810						   "complete: deleting from "
10811						   "the managed keys database",
10812						   keytag, namebuf);
10813				}
10814			} else if (revoked && keydata.removehd == 0) {
10815				dnssec_log(zone, ISC_LOG_WARNING,
10816					   "Active key %d for zone "
10817					   "%s is revoked but "
10818					   "did not self-sign; "
10819					   "ignoring",
10820					   keytag, namebuf);
10821				continue;
10822			} else if (secure) {
10823				if (keydata.removehd != 0) {
10824					/*
10825					 * Key isn't revoked--but it
10826					 * seems it used to be.
10827					 * Remove it now and add it
10828					 * back as if it were a fresh key,
10829					 * with a 30-day acceptance timer.
10830					 */
10831					deletekey = true;
10832					newkey = true;
10833					keydata.removehd = 0;
10834					keydata.addhd = now +
10835							dns_zone_mkey_month;
10836
10837					dnssec_log(zone, ISC_LOG_INFO,
10838						   "Revoked key %d for "
10839						   "zone %s has returned: "
10840						   "starting 30-day "
10841						   "acceptance timer",
10842						   keytag, namebuf);
10843				} else if (keydata.addhd > now) {
10844					pending++;
10845				} else if (keydata.addhd == 0) {
10846					keydata.addhd = now;
10847				}
10848
10849				if (keydata.addhd <= now) {
10850					trustkey = true;
10851					dnssec_log(zone, ISC_LOG_INFO,
10852						   "Key %d for zone %s "
10853						   "is now trusted (%s)",
10854						   keytag, namebuf,
10855						   initial ? "initializing key "
10856							     "verified"
10857							   : "acceptance timer "
10858							     "complete");
10859				}
10860			} else if (keydata.addhd > now) {
10861				/*
10862				 * Not secure, and key is pending:
10863				 * reset the acceptance timer
10864				 */
10865				pending++;
10866				keydata.addhd = now + dns_zone_mkey_month;
10867				dnssec_log(zone, ISC_LOG_INFO,
10868					   "Pending key %d "
10869					   "for zone %s was "
10870					   "not validated: restarting "
10871					   "30-day acceptance timer",
10872					   keytag, namebuf);
10873			}
10874
10875			if (!deletekey && !newkey) {
10876				updatekey = true;
10877			}
10878		} else if (secure) {
10879			/*
10880			 * Key wasn't in the key zone but it's
10881			 * revoked now anyway, so just skip it
10882			 */
10883			if (revoked) {
10884				continue;
10885			}
10886
10887			/* Key wasn't in the key zone: add it */
10888			newkey = true;
10889
10890			if (initializing) {
10891				dnssec_log(zone, ISC_LOG_WARNING,
10892					   "Initializing automatic trust "
10893					   "anchor management for zone '%s'; "
10894					   "DNSKEY ID %d is now trusted, "
10895					   "waiving the normal 30-day "
10896					   "waiting period.",
10897					   namebuf, keytag);
10898				trustkey = true;
10899			} else {
10900				dnssec_log(zone, ISC_LOG_INFO,
10901					   "New key %d observed "
10902					   "for zone '%s': "
10903					   "starting 30-day "
10904					   "acceptance timer",
10905					   keytag, namebuf);
10906			}
10907		} else {
10908			/*
10909			 * No previously known key, and the key is not
10910			 * secure, so skip it.
10911			 */
10912			continue;
10913		}
10914
10915		/* Delete old version */
10916		if (deletekey || !newkey) {
10917			CHECK(update_one_rr(kfetch->db, ver, &diff,
10918					    DNS_DIFFOP_DEL, keyname, 0,
10919					    &keydatarr));
10920		}
10921
10922		if (updatekey) {
10923			/* Set refresh timer */
10924			keydata.refresh = refresh_time(kfetch, false);
10925			dns_rdata_reset(&keydatarr);
10926			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10927			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10928					     dns_rdatatype_keydata, &keydata,
10929					     &keyb);
10930
10931			/* Insert updated version */
10932			CHECK(update_one_rr(kfetch->db, ver, &diff,
10933					    DNS_DIFFOP_ADD, keyname, 0,
10934					    &keydatarr));
10935		} else if (newkey) {
10936			/* Convert DNSKEY to KEYDATA */
10937			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10938			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10939			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
10940					       NULL);
10941			keydata.addhd = initializing
10942						? now
10943						: now + dns_zone_mkey_month;
10944			keydata.refresh = refresh_time(kfetch, false);
10945			dns_rdata_reset(&keydatarr);
10946			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10947			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10948					     dns_rdatatype_keydata, &keydata,
10949					     &keyb);
10950
10951			/* Insert into key zone */
10952			CHECK(update_one_rr(kfetch->db, ver, &diff,
10953					    DNS_DIFFOP_ADD, keyname, 0,
10954					    &keydatarr));
10955		}
10956
10957		if (trustkey) {
10958			/* Trust this key. */
10959			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10960			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10961			trust_key(zone, keyname, &dnskey, false);
10962		}
10963
10964		if (secure && !deletekey) {
10965			INSIST(newkey || updatekey);
10966			set_refreshkeytimer(zone, &keydata, now, false);
10967		}
10968	}
10969
10970	/*
10971	 * RFC5011 says, "A trust point that has all of its trust anchors
10972	 * revoked is considered deleted and is treated as if the trust
10973	 * point was never configured."  But if someone revoked their
10974	 * active key before the standby was trusted, that would mean the
10975	 * zone would suddenly be nonsecured.  We avoid this by checking to
10976	 * see if there's pending keydata.  If so, we put a null key in
10977	 * the security roots; then all queries to the zone will fail.
10978	 */
10979	if (pending != 0) {
10980		fail_secure(zone, keyname);
10981	}
10982
10983done:
10984	if (!ISC_LIST_EMPTY(diff.tuples)) {
10985		/* Write changes to journal file. */
10986		CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
10987					zone->updatemethod));
10988		CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10989		commit = true;
10990
10991		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10992		zone_needdump(zone, 30);
10993	} else if (result == ISC_R_NOMORE) {
10994		/*
10995		 * If "updatekey" was true for all keys found in the DNSKEY
10996		 * response and the previous update of those keys happened
10997		 * during the same second (only possible if a key refresh was
10998		 * externally triggered), it may happen that all relevant
10999		 * update_one_rr() calls will return ISC_R_SUCCESS, but
11000		 * diff.tuples will remain empty.  Reset result to
11001		 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
11002		 */
11003		result = ISC_R_SUCCESS;
11004	}
11005
11006failure:
11007	if (result != ISC_R_SUCCESS) {
11008		dnssec_log(zone, ISC_LOG_ERROR,
11009			   "error during managed-keys processing (%s): "
11010			   "DNSSEC validation may be at risk",
11011			   isc_result_totext(result));
11012	}
11013	dns_diff_clear(&diff);
11014	if (ver != NULL) {
11015		dns_db_closeversion(kfetch->db, &ver, commit);
11016	}
11017
11018cleanup:
11019	dns_db_detach(&kfetch->db);
11020
11021	/* The zone must be managed */
11022	INSIST(kfetch->zone->task != NULL);
11023	isc_refcount_decrement(&zone->irefs);
11024
11025	if (dns_rdataset_isassociated(keydataset)) {
11026		dns_rdataset_disassociate(keydataset);
11027	}
11028	if (dns_rdataset_isassociated(dnskeys)) {
11029		dns_rdataset_disassociate(dnskeys);
11030	}
11031	if (dns_rdataset_isassociated(dnskeysigs)) {
11032		dns_rdataset_disassociate(dnskeysigs);
11033	}
11034
11035	dns_name_free(keyname, mctx);
11036	isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(dns_keyfetch_t));
11037
11038	if (secroots != NULL) {
11039		dns_keytable_detach(&secroots);
11040	}
11041
11042	free_needed = exit_check(zone);
11043	UNLOCK_ZONE(zone);
11044
11045	if (free_needed) {
11046		zone_free(zone);
11047	}
11048
11049	INSIST(ver == NULL);
11050}
11051
11052static void
11053retry_keyfetch(dns_keyfetch_t *kfetch, dns_name_t *kname) {
11054	isc_time_t timenow, timethen;
11055	dns_zone_t *zone = kfetch->zone;
11056	bool free_needed;
11057	char namebuf[DNS_NAME_FORMATSIZE];
11058
11059	dns_name_format(kname, namebuf, sizeof(namebuf));
11060	dnssec_log(zone, ISC_LOG_WARNING,
11061		   "Failed to create fetch for %s DNSKEY update", namebuf);
11062
11063	/*
11064	 * Error during a key fetch; cancel and retry in an hour.
11065	 */
11066	LOCK_ZONE(zone);
11067	zone->refreshkeycount--;
11068	isc_refcount_decrement(&zone->irefs);
11069	dns_db_detach(&kfetch->db);
11070	dns_rdataset_disassociate(&kfetch->keydataset);
11071	dns_name_free(kname, zone->mctx);
11072	isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(*kfetch));
11073
11074	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11075		/* Don't really retry if we are exiting */
11076		char timebuf[80];
11077
11078		TIME_NOW(&timenow);
11079		DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
11080		zone->refreshkeytime = timethen;
11081		zone_settimer(zone, &timenow);
11082
11083		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
11084		dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
11085			   timebuf);
11086	}
11087
11088	free_needed = exit_check(zone);
11089	UNLOCK_ZONE(zone);
11090
11091	if (free_needed) {
11092		zone_free(zone);
11093	}
11094}
11095
11096static void
11097do_keyfetch(isc_task_t *task, isc_event_t *event) {
11098	isc_result_t result;
11099	dns_keyfetch_t *kfetch = (dns_keyfetch_t *)event->ev_arg;
11100	dns_name_t *kname = dns_fixedname_name(&kfetch->name);
11101	dns_zone_t *zone = kfetch->zone;
11102
11103	UNUSED(task);
11104
11105	isc_event_free(&event);
11106
11107	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11108		retry_keyfetch(kfetch, kname);
11109		return;
11110	}
11111
11112	/*
11113	 * Use of DNS_FETCHOPT_NOCACHED is essential here.  If it is not
11114	 * set and the cache still holds a non-expired, validated version
11115	 * of the RRset being queried for by the time the response is
11116	 * received, the cached RRset will be passed to keyfetch_done()
11117	 * instead of the one received in the response as the latter will
11118	 * have a lower trust level due to not being validated until
11119	 * keyfetch_done() is called.
11120	 */
11121	result = dns_resolver_createfetch(
11122		zone->view->resolver, kname, dns_rdatatype_dnskey, NULL, NULL,
11123		NULL, NULL, 0,
11124		DNS_FETCHOPT_NOVALIDATE | DNS_FETCHOPT_UNSHARED |
11125			DNS_FETCHOPT_NOCACHED,
11126		0, NULL, zone->task, keyfetch_done, kfetch, &kfetch->dnskeyset,
11127		&kfetch->dnskeysigset, &kfetch->fetch);
11128
11129	if (result != ISC_R_SUCCESS) {
11130		retry_keyfetch(kfetch, kname);
11131	}
11132}
11133
11134/*
11135 * Refresh the data in the key zone.  Initiate a fetch to look up
11136 * DNSKEY records at the trust anchor name.
11137 */
11138static void
11139zone_refreshkeys(dns_zone_t *zone) {
11140	const char me[] = "zone_refreshkeys";
11141	isc_result_t result;
11142	dns_rriterator_t rrit;
11143	dns_db_t *db = NULL;
11144	dns_dbversion_t *ver = NULL;
11145	dns_diff_t diff;
11146	dns_rdata_t rdata = DNS_RDATA_INIT;
11147	dns_rdata_keydata_t kd;
11148	isc_stdtime_t now;
11149	bool commit = false;
11150	bool fetching = false;
11151	bool timerset = false;
11152
11153	ENTER;
11154	REQUIRE(zone->db != NULL);
11155
11156	isc_stdtime_get(&now);
11157
11158	LOCK_ZONE(zone);
11159	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11160		isc_time_settoepoch(&zone->refreshkeytime);
11161		UNLOCK_ZONE(zone);
11162		return;
11163	}
11164
11165	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11166	dns_db_attach(zone->db, &db);
11167	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11168
11169	dns_diff_init(zone->mctx, &diff);
11170
11171	CHECK(dns_db_newversion(db, &ver));
11172
11173	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
11174
11175	dns_rriterator_init(&rrit, db, ver, 0);
11176	for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
11177	     result = dns_rriterator_nextrrset(&rrit))
11178	{
11179		isc_stdtime_t timer = 0xffffffff;
11180		dns_name_t *name = NULL, *kname = NULL;
11181		dns_rdataset_t *kdset = NULL;
11182		uint32_t ttl;
11183
11184		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
11185		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
11186		    !dns_rdataset_isassociated(kdset))
11187		{
11188			continue;
11189		}
11190
11191		/*
11192		 * Scan the stored keys looking for ones that need
11193		 * removal or refreshing
11194		 */
11195		for (result = dns_rdataset_first(kdset);
11196		     result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
11197		{
11198			dns_rdata_reset(&rdata);
11199			dns_rdataset_current(kdset, &rdata);
11200			result = dns_rdata_tostruct(&rdata, &kd, NULL);
11201			RUNTIME_CHECK(result == ISC_R_SUCCESS);
11202
11203			/* Removal timer expired? */
11204			if (kd.removehd != 0 && kd.removehd < now) {
11205				dns_rriterator_pause(&rrit);
11206				CHECK(update_one_rr(db, ver, &diff,
11207						    DNS_DIFFOP_DEL, name, ttl,
11208						    &rdata));
11209				continue;
11210			}
11211
11212			/* Acceptance timer expired? */
11213			if (kd.addhd <= now) {
11214				timer = kd.addhd;
11215			}
11216
11217			/* Or do we just need to refresh the keyset? */
11218			if (timer > kd.refresh) {
11219				timer = kd.refresh;
11220			}
11221
11222			dns_rriterator_pause(&rrit);
11223			set_refreshkeytimer(zone, &kd, now, false);
11224			timerset = true;
11225		}
11226
11227		if (timer > now) {
11228			continue;
11229		}
11230
11231		dns_rriterator_pause(&rrit);
11232
11233#ifdef ENABLE_AFL
11234		if (!dns_fuzzing_resolver) {
11235#endif /* ifdef ENABLE_AFL */
11236			dns_keyfetch_t *kfetch = NULL;
11237			isc_event_t *e;
11238
11239			kfetch = isc_mem_get(zone->mctx,
11240					     sizeof(dns_keyfetch_t));
11241			*kfetch = (dns_keyfetch_t){ .zone = zone };
11242			isc_mem_attach(zone->mctx, &kfetch->mctx);
11243
11244			zone->refreshkeycount++;
11245			isc_refcount_increment0(&zone->irefs);
11246			kname = dns_fixedname_initname(&kfetch->name);
11247			dns_name_dup(name, zone->mctx, kname);
11248			dns_rdataset_init(&kfetch->dnskeyset);
11249			dns_rdataset_init(&kfetch->dnskeysigset);
11250			dns_rdataset_init(&kfetch->keydataset);
11251			dns_rdataset_clone(kdset, &kfetch->keydataset);
11252			dns_db_attach(db, &kfetch->db);
11253
11254			if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
11255				char namebuf[DNS_NAME_FORMATSIZE];
11256				dns_name_format(kname, namebuf,
11257						sizeof(namebuf));
11258				dnssec_log(zone, ISC_LOG_DEBUG(3),
11259					   "Creating key fetch in "
11260					   "zone_refreshkeys() for '%s'",
11261					   namebuf);
11262			}
11263
11264			e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
11265					       do_keyfetch, kfetch,
11266					       sizeof(isc_event_t));
11267			isc_task_send(zone->task, &e);
11268			fetching = true;
11269#ifdef ENABLE_AFL
11270		}
11271#endif /* ifdef ENABLE_AFL */
11272	}
11273	if (!ISC_LIST_EMPTY(diff.tuples)) {
11274		CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
11275					zone->updatemethod));
11276		CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
11277		commit = true;
11278		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
11279		zone_needdump(zone, 30);
11280	}
11281
11282failure:
11283	if (!timerset) {
11284		isc_time_settoepoch(&zone->refreshkeytime);
11285	}
11286
11287	if (!fetching) {
11288		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
11289	}
11290
11291	dns_diff_clear(&diff);
11292	if (ver != NULL) {
11293		dns_rriterator_destroy(&rrit);
11294		dns_db_closeversion(db, &ver, commit);
11295	}
11296	dns_db_detach(&db);
11297
11298	UNLOCK_ZONE(zone);
11299
11300	INSIST(ver == NULL);
11301}
11302
11303static void
11304zone_maintenance(dns_zone_t *zone) {
11305	const char me[] = "zone_maintenance";
11306	isc_time_t now;
11307	isc_result_t result;
11308	bool load_pending, exiting, dumping, viewok, notify;
11309	bool refreshkeys, sign, resign, rekey, chain, warn_expire;
11310
11311	REQUIRE(DNS_ZONE_VALID(zone));
11312	ENTER;
11313
11314	/*
11315	 * Are we pending load/reload, exiting, or unconfigured
11316	 * (e.g. because of a syntax failure in the config file)?
11317	 * If so, don't attempt maintenance.
11318	 */
11319	LOCK_ZONE(zone);
11320	load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
11321	exiting = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING);
11322	viewok = (zone->view != NULL && zone->view->adb != NULL);
11323	UNLOCK_ZONE(zone);
11324
11325	if (load_pending || exiting || !viewok) {
11326		return;
11327	}
11328
11329	TIME_NOW(&now);
11330
11331	/*
11332	 * Expire check.
11333	 */
11334	switch (zone->type) {
11335	case dns_zone_redirect:
11336		if (zone->primaries == NULL) {
11337			break;
11338		}
11339		FALLTHROUGH;
11340	case dns_zone_secondary:
11341	case dns_zone_mirror:
11342	case dns_zone_stub:
11343		LOCK_ZONE(zone);
11344		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
11345		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11346		{
11347			zone_expire(zone);
11348			zone->refreshtime = now;
11349		}
11350		UNLOCK_ZONE(zone);
11351		break;
11352	default:
11353		break;
11354	}
11355
11356	/*
11357	 * Up to date check.
11358	 */
11359	switch (zone->type) {
11360	case dns_zone_redirect:
11361		if (zone->primaries == NULL) {
11362			break;
11363		}
11364		FALLTHROUGH;
11365	case dns_zone_secondary:
11366	case dns_zone_mirror:
11367	case dns_zone_stub:
11368		LOCK_ZONE(zone);
11369		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
11370		    isc_time_compare(&now, &zone->refreshtime) >= 0)
11371		{
11372			zone_refresh(zone);
11373		}
11374		UNLOCK_ZONE(zone);
11375		break;
11376	default:
11377		break;
11378	}
11379
11380	/*
11381	 * Secondaries send notifies before backing up to disk,
11382	 * primaries after.
11383	 */
11384	LOCK_ZONE(zone);
11385	notify = (zone->type == dns_zone_secondary ||
11386		  zone->type == dns_zone_mirror) &&
11387		 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11388		  DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11389		 isc_time_compare(&now, &zone->notifytime) >= 0;
11390	UNLOCK_ZONE(zone);
11391
11392	if (notify) {
11393		zone_notify(zone, &now);
11394	}
11395
11396	/*
11397	 * Do we need to consolidate the backing store?
11398	 */
11399	switch (zone->type) {
11400	case dns_zone_primary:
11401	case dns_zone_secondary:
11402	case dns_zone_mirror:
11403	case dns_zone_key:
11404	case dns_zone_redirect:
11405	case dns_zone_stub:
11406		LOCK_ZONE(zone);
11407		if (zone->masterfile != NULL &&
11408		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
11409		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11410		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
11411		{
11412			dumping = was_dumping(zone);
11413		} else {
11414			dumping = true;
11415		}
11416		UNLOCK_ZONE(zone);
11417		if (!dumping) {
11418			result = zone_dump(zone, true); /* task locked */
11419			if (result != ISC_R_SUCCESS) {
11420				dns_zone_log(zone, ISC_LOG_WARNING,
11421					     "dump failed: %s",
11422					     isc_result_totext(result));
11423			}
11424		}
11425		break;
11426	default:
11427		break;
11428	}
11429
11430	/*
11431	 * Primary/redirect zones send notifies now, if needed
11432	 */
11433	switch (zone->type) {
11434	case dns_zone_primary:
11435	case dns_zone_redirect:
11436		LOCK_ZONE(zone);
11437		notify = (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11438			  DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11439			 isc_time_compare(&now, &zone->notifytime) >= 0;
11440		UNLOCK_ZONE(zone);
11441		if (notify) {
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		LOCK_ZONE(zone);
11454		refreshkeys = isc_time_compare(&now, &zone->refreshkeytime) >=
11455				      0 &&
11456			      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11457			      !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING);
11458		UNLOCK_ZONE(zone);
11459		if (refreshkeys) {
11460			zone_refreshkeys(zone);
11461		}
11462		break;
11463	case dns_zone_primary:
11464		LOCK_ZONE(zone);
11465		rekey = (!isc_time_isepoch(&zone->refreshkeytime) &&
11466			 isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
11467			 zone->rss_event == NULL);
11468		UNLOCK_ZONE(zone);
11469		if (rekey) {
11470			zone_rekey(zone);
11471		}
11472	default:
11473		break;
11474	}
11475
11476	switch (zone->type) {
11477	case dns_zone_primary:
11478	case dns_zone_redirect:
11479	case dns_zone_secondary:
11480		/*
11481		 * Do we need to sign/resign some RRsets?
11482		 */
11483		LOCK_ZONE(zone);
11484		if (zone->rss_event != NULL) {
11485			UNLOCK_ZONE(zone);
11486			break;
11487		}
11488		sign = !isc_time_isepoch(&zone->signingtime) &&
11489		       isc_time_compare(&now, &zone->signingtime) >= 0;
11490		resign = !isc_time_isepoch(&zone->resigntime) &&
11491			 isc_time_compare(&now, &zone->resigntime) >= 0;
11492		chain = !isc_time_isepoch(&zone->nsec3chaintime) &&
11493			isc_time_compare(&now, &zone->nsec3chaintime) >= 0;
11494		warn_expire = !isc_time_isepoch(&zone->keywarntime) &&
11495			      isc_time_compare(&now, &zone->keywarntime) >= 0;
11496		UNLOCK_ZONE(zone);
11497
11498		if (sign) {
11499			zone_sign(zone);
11500		} else if (resign) {
11501			zone_resigninc(zone);
11502		} else if (chain) {
11503			zone_nsec3chain(zone);
11504		}
11505
11506		/*
11507		 * Do we need to issue a key expiry warning?
11508		 */
11509		if (warn_expire) {
11510			set_key_expiry_warning(zone, zone->key_expiry,
11511					       isc_time_seconds(&now));
11512		}
11513		break;
11514
11515	default:
11516		break;
11517	}
11518	LOCK_ZONE(zone);
11519	zone_settimer(zone, &now);
11520	UNLOCK_ZONE(zone);
11521}
11522
11523void
11524dns_zone_markdirty(dns_zone_t *zone) {
11525	uint32_t serial;
11526	isc_result_t result = ISC_R_SUCCESS;
11527	dns_zone_t *secure = NULL;
11528
11529	/*
11530	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
11531	 * could result in a deadlock due to a LOR so we will spin if we
11532	 * can't obtain the both locks.
11533	 */
11534again:
11535	LOCK_ZONE(zone);
11536	if (zone->type == dns_zone_primary) {
11537		if (inline_raw(zone)) {
11538			unsigned int soacount;
11539			secure = zone->secure;
11540			INSIST(secure != zone);
11541			TRYLOCK_ZONE(result, secure);
11542			if (result != ISC_R_SUCCESS) {
11543				UNLOCK_ZONE(zone);
11544				secure = NULL;
11545				isc_thread_yield();
11546				goto again;
11547			}
11548
11549			ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11550			if (zone->db != NULL) {
11551				result = zone_get_from_db(
11552					zone, zone->db, NULL, &soacount, NULL,
11553					&serial, NULL, NULL, NULL, NULL, NULL);
11554			} else {
11555				result = DNS_R_NOTLOADED;
11556			}
11557			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11558			if (result == ISC_R_SUCCESS && soacount > 0U) {
11559				zone_send_secureserial(zone, serial);
11560			}
11561		}
11562
11563		/* XXXMPA make separate call back */
11564		if (result == ISC_R_SUCCESS) {
11565			set_resigntime(zone);
11566			if (zone->task != NULL) {
11567				isc_time_t now;
11568				TIME_NOW(&now);
11569				zone_settimer(zone, &now);
11570			}
11571		}
11572	}
11573	if (secure != NULL) {
11574		UNLOCK_ZONE(secure);
11575	}
11576	zone_needdump(zone, DNS_DUMP_DELAY);
11577	UNLOCK_ZONE(zone);
11578}
11579
11580void
11581dns_zone_expire(dns_zone_t *zone) {
11582	REQUIRE(DNS_ZONE_VALID(zone));
11583
11584	LOCK_ZONE(zone);
11585	zone_expire(zone);
11586	UNLOCK_ZONE(zone);
11587}
11588
11589static void
11590zone_expire(dns_zone_t *zone) {
11591	dns_db_t *db = NULL;
11592
11593	/*
11594	 * 'zone' locked by caller.
11595	 */
11596
11597	REQUIRE(LOCKED_ZONE(zone));
11598
11599	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
11600
11601	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
11602	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11603	zone->retry = DNS_ZONE_DEFAULTRETRY;
11604	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11605
11606	/*
11607	 * An RPZ zone has expired; before unloading it, we must
11608	 * first remove it from the RPZ summary database. The
11609	 * easiest way to do this is "update" it with an empty
11610	 * database so that the update callback synchronizes
11611	 * the diff automatically.
11612	 */
11613	if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
11614		isc_result_t result;
11615		dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
11616
11617		CHECK(dns_db_create(zone->mctx, "rbt", &zone->origin,
11618				    dns_dbtype_zone, zone->rdclass, 0, NULL,
11619				    &db));
11620		CHECK(dns_rpz_dbupdate_callback(db, rpz));
11621		dns_zone_log(zone, ISC_LOG_WARNING,
11622			     "response-policy zone expired; "
11623			     "policies unloaded");
11624	}
11625
11626failure:
11627	if (db != NULL) {
11628		dns_db_detach(&db);
11629	}
11630
11631	zone_unload(zone);
11632}
11633
11634static void
11635zone_refresh(dns_zone_t *zone) {
11636	isc_interval_t i;
11637	uint32_t oldflags;
11638	unsigned int j;
11639	isc_result_t result;
11640
11641	REQUIRE(DNS_ZONE_VALID(zone));
11642	REQUIRE(LOCKED_ZONE(zone));
11643
11644	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11645		return;
11646	}
11647
11648	/*
11649	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
11650	 * in progress at a time.
11651	 */
11652
11653	oldflags = atomic_load(&zone->flags);
11654	if (zone->primariescnt == 0) {
11655		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
11656		if ((oldflags & DNS_ZONEFLG_NOPRIMARIES) == 0) {
11657			dns_zone_log(zone, ISC_LOG_ERROR,
11658				     "cannot refresh: no primaries");
11659		}
11660		return;
11661	}
11662	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11663	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11664	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11665	if ((oldflags & (DNS_ZONEFLG_REFRESH | DNS_ZONEFLG_LOADING)) != 0) {
11666		return;
11667	}
11668
11669	/*
11670	 * Set the next refresh time as if refresh check has failed.
11671	 * Setting this to the retry time will do that.  XXXMLG
11672	 * If we are successful it will be reset using zone->refresh.
11673	 */
11674	isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
11675			 0);
11676	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
11677	if (result != ISC_R_SUCCESS) {
11678		dns_zone_log(zone, ISC_LOG_WARNING,
11679			     "isc_time_nowplusinterval() failed: %s",
11680			     isc_result_totext(result));
11681	}
11682
11683	/*
11684	 * When lacking user-specified timer values from the SOA,
11685	 * do exponential backoff of the retry time up to a
11686	 * maximum of six hours.
11687	 */
11688	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) {
11689		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
11690	}
11691
11692	zone->curprimary = 0;
11693	for (j = 0; j < zone->primariescnt; j++) {
11694		zone->primariesok[j] = false;
11695	}
11696	/* initiate soa query */
11697	queue_soa_query(zone);
11698}
11699
11700void
11701dns_zone_refresh(dns_zone_t *zone) {
11702	LOCK_ZONE(zone);
11703	zone_refresh(zone);
11704	UNLOCK_ZONE(zone);
11705}
11706
11707static isc_result_t
11708zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
11709			 bool *fixjournal) {
11710	dns_journal_t *journal = NULL;
11711	unsigned int options;
11712	isc_result_t result;
11713
11714	if (zone->type == dns_zone_primary &&
11715	    (inline_secure(zone) ||
11716	     (zone->update_acl != NULL || zone->ssutable != NULL)))
11717	{
11718		options = DNS_JOURNALOPT_RESIGN;
11719	} else {
11720		options = 0;
11721	}
11722
11723	result = dns_journal_open(zone->mctx, zone->journal, DNS_JOURNAL_READ,
11724				  &journal);
11725	if (result == ISC_R_NOTFOUND) {
11726		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(3),
11727			      "no journal file, but that's OK ");
11728		return (ISC_R_SUCCESS);
11729	} else if (result != ISC_R_SUCCESS) {
11730		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11731			      "journal open failed: %s",
11732			      isc_result_totext(result));
11733		return (result);
11734	}
11735
11736	if (dns_journal_empty(journal)) {
11737		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
11738			      "journal empty");
11739		dns_journal_destroy(&journal);
11740		return (ISC_R_SUCCESS);
11741	}
11742
11743	result = dns_journal_rollforward(journal, db, options);
11744	switch (result) {
11745	case ISC_R_SUCCESS:
11746		*needdump = true;
11747		FALLTHROUGH;
11748	case DNS_R_UPTODATE:
11749		if (dns_journal_recovered(journal)) {
11750			*fixjournal = true;
11751			dns_zone_logc(
11752				zone, DNS_LOGCATEGORY_ZONELOAD,
11753				ISC_LOG_DEBUG(1),
11754				"journal rollforward completed successfully "
11755				"using old journal format: %s",
11756				isc_result_totext(result));
11757		} else {
11758			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
11759				      ISC_LOG_DEBUG(1),
11760				      "journal rollforward completed "
11761				      "successfully: %s",
11762				      isc_result_totext(result));
11763		}
11764
11765		dns_journal_destroy(&journal);
11766		return (ISC_R_SUCCESS);
11767	case ISC_R_NOTFOUND:
11768	case ISC_R_RANGE:
11769		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11770			      "journal rollforward failed: journal out of sync "
11771			      "with zone");
11772		dns_journal_destroy(&journal);
11773		return (result);
11774	default:
11775		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11776			      "journal rollforward failed: %s",
11777			      isc_result_totext(result));
11778		dns_journal_destroy(&journal);
11779		return (result);
11780	}
11781}
11782
11783static void
11784zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
11785	isc_result_t result;
11786	int32_t journalsize;
11787	dns_dbversion_t *ver = NULL;
11788	uint64_t dbsize;
11789	uint32_t options = 0;
11790
11791	INSIST(LOCKED_ZONE(zone));
11792	if (inline_raw(zone)) {
11793		INSIST(LOCKED_ZONE(zone->secure));
11794	}
11795
11796	journalsize = zone->journalsize;
11797	if (journalsize == -1) {
11798		journalsize = DNS_JOURNAL_SIZE_MAX;
11799		dns_db_currentversion(db, &ver);
11800		result = dns_db_getsize(db, ver, NULL, &dbsize);
11801		dns_db_closeversion(db, &ver, false);
11802		if (result != ISC_R_SUCCESS) {
11803			dns_zone_log(zone, ISC_LOG_ERROR,
11804				     "zone_journal_compact: "
11805				     "could not get zone size: %s",
11806				     isc_result_totext(result));
11807		} else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
11808			journalsize = (int32_t)dbsize * 2;
11809		}
11810	}
11811	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIXJOURNAL)) {
11812		options |= DNS_JOURNAL_COMPACTALL;
11813		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
11814		zone_debuglog(zone, "zone_journal_compact", 1,
11815			      "repair full journal");
11816	} else {
11817		zone_debuglog(zone, "zone_journal_compact", 1,
11818			      "target journal size %d", journalsize);
11819	}
11820	result = dns_journal_compact(zone->mctx, zone->journal, serial, options,
11821				     journalsize);
11822	switch (result) {
11823	case ISC_R_SUCCESS:
11824	case ISC_R_NOSPACE:
11825	case ISC_R_NOTFOUND:
11826		dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s",
11827			     isc_result_totext(result));
11828		break;
11829	default:
11830		dns_zone_log(zone, ISC_LOG_ERROR,
11831			     "dns_journal_compact failed: %s",
11832			     isc_result_totext(result));
11833		break;
11834	}
11835}
11836
11837isc_result_t
11838dns_zone_flush(dns_zone_t *zone) {
11839	isc_result_t result = ISC_R_SUCCESS;
11840	bool dumping;
11841
11842	REQUIRE(DNS_ZONE_VALID(zone));
11843
11844	LOCK_ZONE(zone);
11845	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
11846	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11847	    zone->masterfile != NULL)
11848	{
11849		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11850		result = ISC_R_ALREADYRUNNING;
11851		dumping = was_dumping(zone);
11852	} else {
11853		dumping = true;
11854	}
11855	UNLOCK_ZONE(zone);
11856	if (!dumping) {
11857		result = zone_dump(zone, true); /* Unknown task. */
11858	}
11859	return (result);
11860}
11861
11862isc_result_t
11863dns_zone_dump(dns_zone_t *zone) {
11864	isc_result_t result = ISC_R_ALREADYRUNNING;
11865	bool dumping;
11866
11867	REQUIRE(DNS_ZONE_VALID(zone));
11868
11869	LOCK_ZONE(zone);
11870	dumping = was_dumping(zone);
11871	UNLOCK_ZONE(zone);
11872	if (!dumping) {
11873		result = zone_dump(zone, false); /* Unknown task. */
11874	}
11875	return (result);
11876}
11877
11878static void
11879zone_needdump(dns_zone_t *zone, unsigned int delay) {
11880	const char me[] = "zone_needdump";
11881	isc_time_t dumptime;
11882	isc_time_t now;
11883
11884	/*
11885	 * 'zone' locked by caller
11886	 */
11887
11888	REQUIRE(DNS_ZONE_VALID(zone));
11889	REQUIRE(LOCKED_ZONE(zone));
11890	ENTER;
11891
11892	/*
11893	 * Do we have a place to dump to and are we loaded?
11894	 */
11895	if (zone->masterfile == NULL ||
11896	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
11897	{
11898		return;
11899	}
11900
11901	TIME_NOW(&now);
11902	/* add some noise */
11903	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
11904
11905	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11906	if (isc_time_isepoch(&zone->dumptime) ||
11907	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
11908	{
11909		zone->dumptime = dumptime;
11910	}
11911	if (zone->task != NULL) {
11912		zone_settimer(zone, &now);
11913	}
11914}
11915
11916static void
11917dump_done(void *arg, isc_result_t result) {
11918	const char me[] = "dump_done";
11919	dns_zone_t *zone = arg;
11920	dns_zone_t *secure = NULL;
11921	dns_db_t *db;
11922	dns_dbversion_t *version;
11923	bool again = false;
11924	bool compact = false;
11925	uint32_t serial;
11926	isc_result_t tresult;
11927
11928	REQUIRE(DNS_ZONE_VALID(zone));
11929
11930	ENTER;
11931
11932	if (result == ISC_R_SUCCESS && zone->journal != NULL) {
11933		/*
11934		 * We don't own these, zone->dctx must stay valid.
11935		 */
11936		db = dns_dumpctx_db(zone->dctx);
11937		version = dns_dumpctx_version(zone->dctx);
11938		tresult = dns_db_getsoaserial(db, version, &serial);
11939
11940		/*
11941		 * Handle lock order inversion.
11942		 */
11943	again:
11944		LOCK_ZONE(zone);
11945		if (inline_raw(zone)) {
11946			secure = zone->secure;
11947			INSIST(secure != zone);
11948			TRYLOCK_ZONE(result, secure);
11949			if (result != ISC_R_SUCCESS) {
11950				UNLOCK_ZONE(zone);
11951				secure = NULL;
11952				isc_thread_yield();
11953				goto again;
11954			}
11955		}
11956
11957		/*
11958		 * If there is a secure version of this zone
11959		 * use its serial if it is less than ours.
11960		 */
11961		if (tresult == ISC_R_SUCCESS && secure != NULL) {
11962			uint32_t sserial;
11963			isc_result_t mresult;
11964
11965			ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
11966			if (secure->db != NULL) {
11967				mresult = dns_db_getsoaserial(zone->secure->db,
11968							      NULL, &sserial);
11969				if (mresult == ISC_R_SUCCESS &&
11970				    isc_serial_lt(sserial, serial))
11971				{
11972					serial = sserial;
11973				}
11974			}
11975			ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
11976		}
11977		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
11978			dns_db_t *zdb = NULL;
11979			if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
11980				zone_journal_compact(zone, zdb, serial);
11981				dns_db_detach(&zdb);
11982			}
11983		} else if (tresult == ISC_R_SUCCESS) {
11984			compact = true;
11985			zone->compact_serial = serial;
11986		}
11987		if (secure != NULL) {
11988			UNLOCK_ZONE(secure);
11989		}
11990		UNLOCK_ZONE(zone);
11991	}
11992
11993	LOCK_ZONE(zone);
11994	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
11995	if (compact) {
11996		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11997	}
11998	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN)) {
11999		/*
12000		 * If DNS_ZONEFLG_SHUTDOWN is set, all external references to
12001		 * the zone are gone, which means it is in the process of being
12002		 * cleaned up, so do not reschedule dumping.
12003		 *
12004		 * Detach from the raw version of the zone in case this
12005		 * operation has been deferred in zone_shutdown().
12006		 */
12007		if (zone->raw != NULL) {
12008			dns_zone_detach(&zone->raw);
12009		}
12010		if (result == ISC_R_SUCCESS) {
12011			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12012		}
12013	} else if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
12014		/*
12015		 * Try again in a short while.
12016		 */
12017		zone_needdump(zone, DNS_DUMP_DELAY);
12018	} else if (result == ISC_R_SUCCESS &&
12019		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12020		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12021		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12022	{
12023		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12024		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12025		isc_time_settoepoch(&zone->dumptime);
12026		again = true;
12027	} else if (result == ISC_R_SUCCESS) {
12028		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12029	}
12030
12031	if (zone->dctx != NULL) {
12032		dns_dumpctx_detach(&zone->dctx);
12033	}
12034	zonemgr_putio(&zone->writeio);
12035	UNLOCK_ZONE(zone);
12036	if (again) {
12037		(void)zone_dump(zone, false);
12038	}
12039	dns_zone_idetach(&zone);
12040}
12041
12042static isc_result_t
12043zone_dump(dns_zone_t *zone, bool compact) {
12044	const char me[] = "zone_dump";
12045	isc_result_t result;
12046	dns_dbversion_t *version = NULL;
12047	bool again;
12048	dns_db_t *db = NULL;
12049	char *masterfile = NULL;
12050	dns_masterformat_t masterformat = dns_masterformat_none;
12051
12052	/*
12053	 * 'compact' MUST only be set if we are task locked.
12054	 */
12055
12056	REQUIRE(DNS_ZONE_VALID(zone));
12057	ENTER;
12058
12059redo:
12060	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12061	if (zone->db != NULL) {
12062		dns_db_attach(zone->db, &db);
12063	}
12064	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12065	LOCK_ZONE(zone);
12066	if (zone->masterfile != NULL) {
12067		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
12068		masterformat = zone->masterformat;
12069	}
12070	UNLOCK_ZONE(zone);
12071	if (db == NULL) {
12072		result = DNS_R_NOTLOADED;
12073		goto fail;
12074	}
12075	if (masterfile == NULL) {
12076		result = DNS_R_NOMASTERFILE;
12077		goto fail;
12078	}
12079
12080	if (compact && zone->type != dns_zone_stub) {
12081		dns_zone_t *dummy = NULL;
12082		LOCK_ZONE(zone);
12083		zone_iattach(zone, &dummy);
12084		result = zonemgr_getio(zone->zmgr, false, zone->task,
12085				       zone_gotwritehandle, zone,
12086				       &zone->writeio);
12087		if (result != ISC_R_SUCCESS) {
12088			zone_idetach(&dummy);
12089		} else {
12090			result = DNS_R_CONTINUE;
12091		}
12092		UNLOCK_ZONE(zone);
12093	} else {
12094		const dns_master_style_t *output_style;
12095
12096		dns_masterrawheader_t rawdata;
12097		dns_db_currentversion(db, &version);
12098		dns_master_initrawheader(&rawdata);
12099		if (inline_secure(zone)) {
12100			get_raw_serial(zone->raw, &rawdata);
12101		}
12102		if (zone->type == dns_zone_key) {
12103			output_style = &dns_master_style_keyzone;
12104		} else {
12105			output_style = &dns_master_style_default;
12106		}
12107		result = dns_master_dump(zone->mctx, db, version, output_style,
12108					 masterfile, masterformat, &rawdata);
12109		dns_db_closeversion(db, &version, false);
12110	}
12111fail:
12112	if (db != NULL) {
12113		dns_db_detach(&db);
12114	}
12115	if (masterfile != NULL) {
12116		isc_mem_free(zone->mctx, masterfile);
12117	}
12118	masterfile = NULL;
12119
12120	if (result == DNS_R_CONTINUE) {
12121		return (ISC_R_SUCCESS); /* XXXMPA */
12122	}
12123
12124	again = false;
12125	LOCK_ZONE(zone);
12126	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
12127	if (result != ISC_R_SUCCESS) {
12128		/*
12129		 * Try again in a short while.
12130		 */
12131		zone_needdump(zone, DNS_DUMP_DELAY);
12132	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12133		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12134		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12135	{
12136		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12137		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12138		isc_time_settoepoch(&zone->dumptime);
12139		again = true;
12140	} else {
12141		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12142	}
12143	UNLOCK_ZONE(zone);
12144	if (again) {
12145		goto redo;
12146	}
12147
12148	return (result);
12149}
12150
12151static isc_result_t
12152dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
12153	     dns_masterformat_t format, const uint32_t rawversion) {
12154	isc_result_t result;
12155	dns_dbversion_t *version = NULL;
12156	dns_db_t *db = NULL;
12157	dns_masterrawheader_t rawdata;
12158
12159	REQUIRE(DNS_ZONE_VALID(zone));
12160
12161	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12162	if (zone->db != NULL) {
12163		dns_db_attach(zone->db, &db);
12164	}
12165	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12166	if (db == NULL) {
12167		return (DNS_R_NOTLOADED);
12168	}
12169
12170	dns_db_currentversion(db, &version);
12171	dns_master_initrawheader(&rawdata);
12172	if (rawversion == 0) {
12173		rawdata.flags |= DNS_MASTERRAW_COMPAT;
12174	} else if (inline_secure(zone)) {
12175		get_raw_serial(zone->raw, &rawdata);
12176	} else if (zone->sourceserialset) {
12177		rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
12178		rawdata.sourceserial = zone->sourceserial;
12179	}
12180	result = dns_master_dumptostream(zone->mctx, db, version, style, format,
12181					 &rawdata, fd);
12182	dns_db_closeversion(db, &version, false);
12183	dns_db_detach(&db);
12184	return (result);
12185}
12186
12187isc_result_t
12188dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
12189		      const dns_master_style_t *style,
12190		      const uint32_t rawversion) {
12191	return (dumptostream(zone, fd, style, format, rawversion));
12192}
12193
12194void
12195dns_zone_unload(dns_zone_t *zone) {
12196	REQUIRE(DNS_ZONE_VALID(zone));
12197
12198	LOCK_ZONE(zone);
12199	zone_unload(zone);
12200	UNLOCK_ZONE(zone);
12201}
12202
12203static void
12204notify_cancel(dns_zone_t *zone) {
12205	dns_notify_t *notify;
12206
12207	/*
12208	 * 'zone' locked by caller.
12209	 */
12210
12211	REQUIRE(LOCKED_ZONE(zone));
12212
12213	for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12214	     notify = ISC_LIST_NEXT(notify, link))
12215	{
12216		if (notify->find != NULL) {
12217			dns_adb_cancelfind(notify->find);
12218		}
12219		if (notify->request != NULL) {
12220			dns_request_cancel(notify->request);
12221		}
12222	}
12223}
12224
12225static void
12226checkds_cancel(dns_zone_t *zone) {
12227	dns_checkds_t *checkds;
12228
12229	/*
12230	 * 'zone' locked by caller.
12231	 */
12232
12233	REQUIRE(LOCKED_ZONE(zone));
12234
12235	for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
12236	     checkds = ISC_LIST_NEXT(checkds, link))
12237	{
12238		if (checkds->request != NULL) {
12239			dns_request_cancel(checkds->request);
12240		}
12241	}
12242}
12243
12244static void
12245forward_cancel(dns_zone_t *zone) {
12246	dns_forward_t *forward;
12247
12248	/*
12249	 * 'zone' locked by caller.
12250	 */
12251
12252	REQUIRE(LOCKED_ZONE(zone));
12253
12254	for (forward = ISC_LIST_HEAD(zone->forwards); forward != NULL;
12255	     forward = ISC_LIST_NEXT(forward, link))
12256	{
12257		if (forward->request != NULL) {
12258			dns_request_cancel(forward->request);
12259		}
12260	}
12261}
12262
12263static void
12264zone_unload(dns_zone_t *zone) {
12265	/*
12266	 * 'zone' locked by caller.
12267	 */
12268
12269	REQUIRE(LOCKED_ZONE(zone));
12270
12271	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
12272	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
12273	{
12274		if (zone->writeio != NULL) {
12275			zonemgr_cancelio(zone->writeio);
12276		}
12277
12278		if (zone->dctx != NULL) {
12279			dns_dumpctx_cancel(zone->dctx);
12280		}
12281	}
12282	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12283	zone_detachdb(zone);
12284	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12285	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
12286	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12287
12288	if (zone->type == dns_zone_mirror) {
12289		dns_zone_log(zone, ISC_LOG_INFO,
12290			     "mirror zone is no longer in use; "
12291			     "reverting to normal recursion");
12292	}
12293}
12294
12295void
12296dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
12297	REQUIRE(DNS_ZONE_VALID(zone));
12298	REQUIRE(val > 0);
12299
12300	zone->minrefresh = val;
12301}
12302
12303void
12304dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
12305	REQUIRE(DNS_ZONE_VALID(zone));
12306	REQUIRE(val > 0);
12307
12308	zone->maxrefresh = val;
12309}
12310
12311void
12312dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
12313	REQUIRE(DNS_ZONE_VALID(zone));
12314	REQUIRE(val > 0);
12315
12316	zone->minretry = val;
12317}
12318
12319void
12320dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
12321	REQUIRE(DNS_ZONE_VALID(zone));
12322	REQUIRE(val > 0);
12323
12324	zone->maxretry = val;
12325}
12326
12327uint32_t
12328dns_zone_getmaxrecords(dns_zone_t *zone) {
12329	REQUIRE(DNS_ZONE_VALID(zone));
12330
12331	return (zone->maxrecords);
12332}
12333
12334void
12335dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
12336	REQUIRE(DNS_ZONE_VALID(zone));
12337
12338	zone->maxrecords = val;
12339}
12340
12341static bool
12342notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
12343		isc_sockaddr_t *addr, dns_tsigkey_t *key,
12344		dns_transport_t *transport) {
12345	dns_notify_t *notify;
12346	dns_zonemgr_t *zmgr;
12347	isc_result_t result;
12348
12349	for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12350	     notify = ISC_LIST_NEXT(notify, link))
12351	{
12352		if (notify->request != NULL) {
12353			continue;
12354		}
12355		if (name != NULL && dns_name_dynamic(&notify->ns) &&
12356		    dns_name_equal(name, &notify->ns))
12357		{
12358			goto requeue;
12359		}
12360		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
12361		    notify->key == key && notify->transport == transport)
12362		{
12363			goto requeue;
12364		}
12365	}
12366	return (false);
12367
12368requeue:
12369	/*
12370	 * If we are enqueued on the startup ratelimiter and this is
12371	 * not a startup notify, re-enqueue on the normal notify
12372	 * ratelimiter.
12373	 */
12374	if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
12375	    (notify->flags & DNS_NOTIFY_STARTUP) != 0)
12376	{
12377		zmgr = notify->zone->zmgr;
12378		result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
12379						 notify->event);
12380		if (result != ISC_R_SUCCESS) {
12381			return (true);
12382		}
12383
12384		notify->flags &= ~DNS_NOTIFY_STARTUP;
12385		result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
12386						 notify->zone->task,
12387						 &notify->event);
12388		if (result != ISC_R_SUCCESS) {
12389			isc_event_free(&notify->event);
12390			return (false);
12391		}
12392	}
12393
12394	return (true);
12395}
12396
12397static bool
12398notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
12399	dns_tsigkey_t *key = NULL;
12400	isc_sockaddr_t src;
12401	isc_sockaddr_t any;
12402	bool isself;
12403	isc_netaddr_t dstaddr;
12404	isc_result_t result;
12405
12406	if (zone->view == NULL || zone->isself == NULL) {
12407		return (false);
12408	}
12409
12410	switch (isc_sockaddr_pf(dst)) {
12411	case PF_INET:
12412		src = zone->notifysrc4;
12413		isc_sockaddr_any(&any);
12414		break;
12415	case PF_INET6:
12416		src = zone->notifysrc6;
12417		isc_sockaddr_any6(&any);
12418		break;
12419	default:
12420		return (false);
12421	}
12422
12423	/*
12424	 * When sending from any the kernel will assign a source address
12425	 * that matches the destination address.
12426	 */
12427	if (isc_sockaddr_eqaddr(&any, &src)) {
12428		src = *dst;
12429	}
12430
12431	isc_netaddr_fromsockaddr(&dstaddr, dst);
12432	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
12433	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12434		return (false);
12435	}
12436	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
12437				zone->isselfarg);
12438	if (key != NULL) {
12439		dns_tsigkey_detach(&key);
12440	}
12441	return (isself);
12442}
12443
12444static void
12445notify_destroy(dns_notify_t *notify, bool locked) {
12446	isc_mem_t *mctx;
12447
12448	REQUIRE(DNS_NOTIFY_VALID(notify));
12449
12450	if (notify->zone != NULL) {
12451		if (!locked) {
12452			LOCK_ZONE(notify->zone);
12453		}
12454		REQUIRE(LOCKED_ZONE(notify->zone));
12455		if (ISC_LINK_LINKED(notify, link)) {
12456			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
12457		}
12458		if (!locked) {
12459			UNLOCK_ZONE(notify->zone);
12460		}
12461		if (locked) {
12462			zone_idetach(&notify->zone);
12463		} else {
12464			dns_zone_idetach(&notify->zone);
12465		}
12466	}
12467	if (notify->find != NULL) {
12468		dns_adb_destroyfind(&notify->find);
12469	}
12470	if (notify->request != NULL) {
12471		dns_request_destroy(&notify->request);
12472	}
12473	if (dns_name_dynamic(&notify->ns)) {
12474		dns_name_free(&notify->ns, notify->mctx);
12475	}
12476	if (notify->key != NULL) {
12477		dns_tsigkey_detach(&notify->key);
12478	}
12479	if (notify->transport != NULL) {
12480		dns_transport_detach(&notify->transport);
12481	}
12482	mctx = notify->mctx;
12483	isc_mem_put(notify->mctx, notify, sizeof(*notify));
12484	isc_mem_detach(&mctx);
12485}
12486
12487static isc_result_t
12488notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
12489	dns_notify_t *notify;
12490
12491	REQUIRE(notifyp != NULL && *notifyp == NULL);
12492
12493	notify = isc_mem_get(mctx, sizeof(*notify));
12494	*notify = (dns_notify_t){
12495		.flags = flags,
12496	};
12497
12498	isc_mem_attach(mctx, &notify->mctx);
12499	isc_sockaddr_any(&notify->dst);
12500	dns_name_init(&notify->ns, NULL);
12501	ISC_LINK_INIT(notify, link);
12502	notify->magic = NOTIFY_MAGIC;
12503	*notifyp = notify;
12504	return (ISC_R_SUCCESS);
12505}
12506
12507/*
12508 * XXXAG should check for DNS_ZONEFLG_EXITING
12509 */
12510static void
12511process_adb_event(isc_task_t *task, isc_event_t *ev) {
12512	dns_notify_t *notify;
12513	isc_eventtype_t result;
12514
12515	UNUSED(task);
12516
12517	notify = ev->ev_arg;
12518	REQUIRE(DNS_NOTIFY_VALID(notify));
12519	INSIST(task == notify->zone->task);
12520	result = ev->ev_type;
12521	isc_event_free(&ev);
12522	if (result == DNS_EVENT_ADBMOREADDRESSES) {
12523		dns_adb_destroyfind(&notify->find);
12524		notify_find_address(notify);
12525		return;
12526	}
12527	if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
12528		LOCK_ZONE(notify->zone);
12529		notify_send(notify);
12530		UNLOCK_ZONE(notify->zone);
12531	}
12532	notify_destroy(notify, false);
12533}
12534
12535static void
12536notify_find_address(dns_notify_t *notify) {
12537	isc_result_t result;
12538	unsigned int options;
12539
12540	REQUIRE(DNS_NOTIFY_VALID(notify));
12541	options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET | DNS_ADBFIND_INET6 |
12542		  DNS_ADBFIND_RETURNLAME;
12543
12544	if (notify->zone->view->adb == NULL) {
12545		goto destroy;
12546	}
12547
12548	result = dns_adb_createfind(
12549		notify->zone->view->adb, notify->zone->task, process_adb_event,
12550		notify, &notify->ns, dns_rootname, 0, options, 0, NULL,
12551		notify->zone->view->dstport, 0, NULL, &notify->find);
12552
12553	/* Something failed? */
12554	if (result != ISC_R_SUCCESS) {
12555		goto destroy;
12556	}
12557
12558	/* More addresses pending? */
12559	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
12560		return;
12561	}
12562
12563	/* We have as many addresses as we can get. */
12564	LOCK_ZONE(notify->zone);
12565	notify_send(notify);
12566	UNLOCK_ZONE(notify->zone);
12567
12568destroy:
12569	notify_destroy(notify, false);
12570}
12571
12572static isc_result_t
12573notify_send_queue(dns_notify_t *notify, bool startup) {
12574	isc_event_t *e;
12575	isc_result_t result;
12576
12577	INSIST(notify->event == NULL);
12578	e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
12579			       notify_send_toaddr, notify, sizeof(isc_event_t));
12580	if (startup) {
12581		notify->event = e;
12582	}
12583	e->ev_arg = notify;
12584	e->ev_sender = NULL;
12585	result = isc_ratelimiter_enqueue(
12586		startup ? notify->zone->zmgr->startupnotifyrl
12587			: notify->zone->zmgr->notifyrl,
12588		notify->zone->task, &e);
12589	if (result != ISC_R_SUCCESS) {
12590		isc_event_free(&e);
12591		notify->event = NULL;
12592	}
12593	return (result);
12594}
12595
12596static void
12597notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
12598	dns_notify_t *notify;
12599	isc_result_t result;
12600	dns_message_t *message = NULL;
12601	isc_netaddr_t dstip;
12602	dns_tsigkey_t *key = NULL;
12603	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12604	isc_sockaddr_t src;
12605	unsigned int options, timeout;
12606	bool have_notifysource = false;
12607
12608	notify = event->ev_arg;
12609	REQUIRE(DNS_NOTIFY_VALID(notify));
12610
12611	UNUSED(task);
12612
12613	LOCK_ZONE(notify->zone);
12614
12615	notify->event = NULL;
12616
12617	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
12618		result = ISC_R_CANCELED;
12619		goto cleanup;
12620	}
12621
12622	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
12623	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
12624	    notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
12625	{
12626		result = ISC_R_CANCELED;
12627		goto cleanup;
12628	}
12629
12630	/*
12631	 * The raw IPv4 address should also exist.  Don't send to the
12632	 * mapped form.
12633	 */
12634	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
12635	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr))
12636	{
12637		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12638		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12639			   "notify: ignoring IPv6 mapped IPV4 address: %s",
12640			   addrbuf);
12641		result = ISC_R_CANCELED;
12642		goto cleanup;
12643	}
12644
12645	result = notify_createmessage(notify->zone, notify->flags, &message);
12646	if (result != ISC_R_SUCCESS) {
12647		goto cleanup;
12648	}
12649
12650	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12651	if (notify->key != NULL) {
12652		/* Transfer ownership of key */
12653		key = notify->key;
12654		notify->key = NULL;
12655	} else {
12656		isc_netaddr_fromsockaddr(&dstip, &notify->dst);
12657		result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
12658		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12659			notify_log(notify->zone, ISC_LOG_ERROR,
12660				   "NOTIFY to %s not sent. "
12661				   "Peer TSIG key lookup failure.",
12662				   addrbuf);
12663			goto cleanup_message;
12664		}
12665	}
12666
12667	if (key != NULL) {
12668		char namebuf[DNS_NAME_FORMATSIZE];
12669
12670		dns_name_format(&key->name, namebuf, sizeof(namebuf));
12671		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12672			   "sending notify to %s : TSIG (%s)", addrbuf,
12673			   namebuf);
12674	} else {
12675		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12676			   "sending notify to %s", addrbuf);
12677	}
12678	options = 0;
12679	if (notify->zone->view->peers != NULL) {
12680		dns_peer_t *peer = NULL;
12681		bool usetcp = false;
12682		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
12683						 &dstip, &peer);
12684		if (result == ISC_R_SUCCESS) {
12685			result = dns_peer_getnotifysource(peer, &src);
12686			if (result == ISC_R_SUCCESS) {
12687				have_notifysource = true;
12688			}
12689			result = dns_peer_getforcetcp(peer, &usetcp);
12690			if (result == ISC_R_SUCCESS && usetcp) {
12691				options |= DNS_FETCHOPT_TCP;
12692			}
12693		}
12694	}
12695	switch (isc_sockaddr_pf(&notify->dst)) {
12696	case PF_INET:
12697		if (!have_notifysource) {
12698			src = notify->zone->notifysrc4;
12699		}
12700		break;
12701	case PF_INET6:
12702		if (!have_notifysource) {
12703			src = notify->zone->notifysrc6;
12704		}
12705		break;
12706	default:
12707		result = ISC_R_NOTIMPLEMENTED;
12708		goto cleanup_key;
12709	}
12710	timeout = 5;
12711	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) {
12712		timeout = 30;
12713	}
12714	result = dns_request_create(
12715		notify->zone->view->requestmgr, message, &src, &notify->dst,
12716		options, key, timeout * 3 + 1, timeout, 2, notify->zone->task,
12717		notify_done, notify, &notify->request);
12718	if (result == ISC_R_SUCCESS) {
12719		if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
12720			inc_stats(notify->zone,
12721				  dns_zonestatscounter_notifyoutv4);
12722		} else {
12723			inc_stats(notify->zone,
12724				  dns_zonestatscounter_notifyoutv6);
12725		}
12726	}
12727
12728cleanup_key:
12729	if (key != NULL) {
12730		dns_tsigkey_detach(&key);
12731	}
12732cleanup_message:
12733	dns_message_detach(&message);
12734cleanup:
12735	UNLOCK_ZONE(notify->zone);
12736	isc_event_free(&event);
12737	if (result != ISC_R_SUCCESS) {
12738		notify_destroy(notify, false);
12739	}
12740}
12741
12742static void
12743notify_send(dns_notify_t *notify) {
12744	dns_adbaddrinfo_t *ai;
12745	isc_sockaddr_t dst;
12746	isc_result_t result;
12747	dns_notify_t *newnotify = NULL;
12748	unsigned int flags;
12749	bool startup;
12750
12751	/*
12752	 * Zone lock held by caller.
12753	 */
12754	REQUIRE(DNS_NOTIFY_VALID(notify));
12755	REQUIRE(LOCKED_ZONE(notify->zone));
12756
12757	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) {
12758		return;
12759	}
12760
12761	for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL;
12762	     ai = ISC_LIST_NEXT(ai, publink))
12763	{
12764		dst = ai->sockaddr;
12765		if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
12766				    NULL, NULL))
12767		{
12768			continue;
12769		}
12770		if (notify_isself(notify->zone, &dst)) {
12771			continue;
12772		}
12773		newnotify = NULL;
12774		flags = notify->flags & DNS_NOTIFY_NOSOA;
12775		result = notify_create(notify->mctx, flags, &newnotify);
12776		if (result != ISC_R_SUCCESS) {
12777			goto cleanup;
12778		}
12779		zone_iattach(notify->zone, &newnotify->zone);
12780		ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
12781		newnotify->dst = dst;
12782		startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
12783		result = notify_send_queue(newnotify, startup);
12784		if (result != ISC_R_SUCCESS) {
12785			goto cleanup;
12786		}
12787		newnotify = NULL;
12788	}
12789
12790cleanup:
12791	if (newnotify != NULL) {
12792		notify_destroy(newnotify, true);
12793	}
12794}
12795
12796void
12797dns_zone_notify(dns_zone_t *zone) {
12798	isc_time_t now;
12799
12800	REQUIRE(DNS_ZONE_VALID(zone));
12801
12802	LOCK_ZONE(zone);
12803	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12804
12805	TIME_NOW(&now);
12806	zone_settimer(zone, &now);
12807	UNLOCK_ZONE(zone);
12808}
12809
12810static void
12811zone_notify(dns_zone_t *zone, isc_time_t *now) {
12812	dns_dbnode_t *node = NULL;
12813	dns_db_t *zonedb = NULL;
12814	dns_dbversion_t *version = NULL;
12815	dns_name_t *origin = NULL;
12816	dns_name_t primary;
12817	dns_rdata_ns_t ns;
12818	dns_rdata_soa_t soa;
12819	uint32_t serial;
12820	dns_rdata_t rdata = DNS_RDATA_INIT;
12821	dns_rdataset_t nsrdset;
12822	dns_rdataset_t soardset;
12823	isc_result_t result;
12824	unsigned int i;
12825	isc_sockaddr_t dst;
12826	bool isqueued;
12827	dns_notifytype_t notifytype;
12828	unsigned int flags = 0;
12829	bool loggednotify = false;
12830	bool startup;
12831
12832	REQUIRE(DNS_ZONE_VALID(zone));
12833
12834	LOCK_ZONE(zone);
12835	startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12836	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12837	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
12838	notifytype = zone->notifytype;
12839	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
12840	UNLOCK_ZONE(zone);
12841
12842	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12843	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12844	{
12845		return;
12846	}
12847
12848	if (notifytype == dns_notifytype_no) {
12849		return;
12850	}
12851
12852	if (notifytype == dns_notifytype_masteronly &&
12853	    zone->type != dns_zone_primary)
12854	{
12855		return;
12856	}
12857
12858	origin = &zone->origin;
12859
12860	/*
12861	 * If the zone is dialup we are done as we don't want to send
12862	 * the current soa so as to force a refresh query.
12863	 */
12864	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
12865		flags |= DNS_NOTIFY_NOSOA;
12866	}
12867
12868	/*
12869	 * Record that this was a notify due to starting up.
12870	 */
12871	if (startup) {
12872		flags |= DNS_NOTIFY_STARTUP;
12873	}
12874
12875	/*
12876	 * Get SOA RRset.
12877	 */
12878	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12879	if (zone->db != NULL) {
12880		dns_db_attach(zone->db, &zonedb);
12881	}
12882	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12883	if (zonedb == NULL) {
12884		return;
12885	}
12886	dns_db_currentversion(zonedb, &version);
12887	result = dns_db_findnode(zonedb, origin, false, &node);
12888	if (result != ISC_R_SUCCESS) {
12889		goto cleanup1;
12890	}
12891
12892	dns_rdataset_init(&soardset);
12893	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
12894				     dns_rdatatype_none, 0, &soardset, NULL);
12895	if (result != ISC_R_SUCCESS) {
12896		goto cleanup2;
12897	}
12898
12899	/*
12900	 * Find serial and primary server's name.
12901	 */
12902	dns_name_init(&primary, NULL);
12903	result = dns_rdataset_first(&soardset);
12904	if (result != ISC_R_SUCCESS) {
12905		goto cleanup3;
12906	}
12907	dns_rdataset_current(&soardset, &rdata);
12908	result = dns_rdata_tostruct(&rdata, &soa, NULL);
12909	RUNTIME_CHECK(result == ISC_R_SUCCESS);
12910	dns_rdata_reset(&rdata);
12911	dns_name_dup(&soa.origin, zone->mctx, &primary);
12912	serial = soa.serial;
12913	dns_rdataset_disassociate(&soardset);
12914
12915	/*
12916	 * Enqueue notify requests for 'also-notify' servers.
12917	 */
12918	LOCK_ZONE(zone);
12919	for (i = 0; i < zone->notifycnt; i++) {
12920		dns_tsigkey_t *key = NULL;
12921		dns_transport_t *transport = NULL;
12922		dns_notify_t *notify = NULL;
12923		dns_view_t *view = dns_zone_getview(zone);
12924
12925		if ((zone->notifykeynames != NULL) &&
12926		    (zone->notifykeynames[i] != NULL))
12927		{
12928			dns_name_t *keyname = zone->notifykeynames[i];
12929			(void)dns_view_gettsig(view, keyname, &key);
12930		}
12931
12932		if ((zone->notifytlsnames != NULL) &&
12933		    (zone->notifytlsnames[i] != NULL))
12934		{
12935			dns_name_t *tlsname = zone->notifytlsnames[i];
12936			(void)dns_view_gettransport(view, DNS_TRANSPORT_TLS,
12937						    tlsname, &transport);
12938
12939			dns_zone_logc(
12940				zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
12941				"got TLS configuration for zone transfer");
12942		}
12943
12944		/* TODO: glue the transport to the notify */
12945
12946		dst = zone->notify[i];
12947		if (notify_isqueued(zone, flags, NULL, &dst, key, transport)) {
12948			if (key != NULL) {
12949				dns_tsigkey_detach(&key);
12950			}
12951			if (transport != NULL) {
12952				dns_transport_detach(&transport);
12953			}
12954			continue;
12955		}
12956
12957		result = notify_create(zone->mctx, flags, &notify);
12958		if (result != ISC_R_SUCCESS) {
12959			if (key != NULL) {
12960				dns_tsigkey_detach(&key);
12961			}
12962			if (transport != NULL) {
12963				dns_transport_detach(&transport);
12964			}
12965			continue;
12966		}
12967
12968		zone_iattach(zone, &notify->zone);
12969		notify->dst = dst;
12970
12971		INSIST(notify->key == NULL);
12972
12973		if (key != NULL) {
12974			notify->key = key;
12975			key = NULL;
12976		}
12977
12978		INSIST(notify->transport == NULL);
12979		if (transport != NULL) {
12980			notify->transport = transport;
12981			transport = NULL;
12982		}
12983
12984		ISC_LIST_APPEND(zone->notifies, notify, link);
12985		result = notify_send_queue(notify, startup);
12986		if (result != ISC_R_SUCCESS) {
12987			notify_destroy(notify, true);
12988		}
12989		if (!loggednotify) {
12990			notify_log(zone, ISC_LOG_INFO,
12991				   "sending notifies (serial %u)", serial);
12992			loggednotify = true;
12993		}
12994	}
12995	UNLOCK_ZONE(zone);
12996
12997	if (notifytype == dns_notifytype_explicit) {
12998		goto cleanup3;
12999	}
13000
13001	/*
13002	 * Process NS RRset to generate notifies.
13003	 */
13004
13005	dns_rdataset_init(&nsrdset);
13006	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
13007				     dns_rdatatype_none, 0, &nsrdset, NULL);
13008	if (result != ISC_R_SUCCESS) {
13009		goto cleanup3;
13010	}
13011
13012	result = dns_rdataset_first(&nsrdset);
13013	while (result == ISC_R_SUCCESS) {
13014		dns_notify_t *notify = NULL;
13015
13016		dns_rdataset_current(&nsrdset, &rdata);
13017		result = dns_rdata_tostruct(&rdata, &ns, NULL);
13018		RUNTIME_CHECK(result == ISC_R_SUCCESS);
13019		dns_rdata_reset(&rdata);
13020		/*
13021		 * Don't notify the primary server unless explicitly
13022		 * configured to do so.
13023		 */
13024		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
13025		    dns_name_compare(&primary, &ns.name) == 0)
13026		{
13027			result = dns_rdataset_next(&nsrdset);
13028			continue;
13029		}
13030
13031		if (!loggednotify) {
13032			notify_log(zone, ISC_LOG_INFO,
13033				   "sending notifies (serial %u)", serial);
13034			loggednotify = true;
13035		}
13036
13037		LOCK_ZONE(zone);
13038		isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL,
13039					   NULL);
13040		UNLOCK_ZONE(zone);
13041		if (isqueued) {
13042			result = dns_rdataset_next(&nsrdset);
13043			continue;
13044		}
13045		result = notify_create(zone->mctx, flags, &notify);
13046		if (result != ISC_R_SUCCESS) {
13047			continue;
13048		}
13049		dns_zone_iattach(zone, &notify->zone);
13050		dns_name_dup(&ns.name, zone->mctx, &notify->ns);
13051		LOCK_ZONE(zone);
13052		ISC_LIST_APPEND(zone->notifies, notify, link);
13053		UNLOCK_ZONE(zone);
13054		notify_find_address(notify);
13055		result = dns_rdataset_next(&nsrdset);
13056	}
13057	dns_rdataset_disassociate(&nsrdset);
13058
13059cleanup3:
13060	if (dns_name_dynamic(&primary)) {
13061		dns_name_free(&primary, zone->mctx);
13062	}
13063cleanup2:
13064	dns_db_detachnode(zonedb, &node);
13065cleanup1:
13066	dns_db_closeversion(zonedb, &version, false);
13067	dns_db_detach(&zonedb);
13068}
13069
13070/***
13071 *** Private
13072 ***/
13073static isc_result_t
13074create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, dns_name_t *name,
13075	     dns_message_t **messagep) {
13076	dns_message_t *message = NULL;
13077	dns_name_t *qname = NULL;
13078	dns_rdataset_t *qrdataset = NULL;
13079	isc_result_t result;
13080
13081	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
13082
13083	message->opcode = dns_opcode_query;
13084	message->rdclass = zone->rdclass;
13085
13086	result = dns_message_gettempname(message, &qname);
13087	if (result != ISC_R_SUCCESS) {
13088		goto cleanup;
13089	}
13090
13091	result = dns_message_gettemprdataset(message, &qrdataset);
13092	if (result != ISC_R_SUCCESS) {
13093		goto cleanup;
13094	}
13095
13096	/*
13097	 * Make question.
13098	 */
13099	dns_name_clone(name, qname);
13100	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
13101	ISC_LIST_APPEND(qname->list, qrdataset, link);
13102	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
13103
13104	*messagep = message;
13105	return (ISC_R_SUCCESS);
13106
13107cleanup:
13108	if (qname != NULL) {
13109		dns_message_puttempname(message, &qname);
13110	}
13111	if (qrdataset != NULL) {
13112		dns_message_puttemprdataset(message, &qrdataset);
13113	}
13114	dns_message_detach(&message);
13115	return (result);
13116}
13117
13118static isc_result_t
13119add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
13120	bool reqexpire) {
13121	isc_result_t result;
13122	dns_rdataset_t *rdataset = NULL;
13123	dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
13124	int count = 0;
13125
13126	/* Set EDNS options if applicable. */
13127	if (reqnsid) {
13128		INSIST(count < DNS_EDNSOPTIONS);
13129		ednsopts[count].code = DNS_OPT_NSID;
13130		ednsopts[count].length = 0;
13131		ednsopts[count].value = NULL;
13132		count++;
13133	}
13134	if (reqexpire) {
13135		INSIST(count < DNS_EDNSOPTIONS);
13136		ednsopts[count].code = DNS_OPT_EXPIRE;
13137		ednsopts[count].length = 0;
13138		ednsopts[count].value = NULL;
13139		count++;
13140	}
13141	result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
13142				      ednsopts, count);
13143	if (result != ISC_R_SUCCESS) {
13144		return (result);
13145	}
13146
13147	return (dns_message_setopt(message, rdataset));
13148}
13149
13150/*
13151 * Called when stub zone update is finished.
13152 * Update zone refresh, retry, expire values accordingly with
13153 * SOA received from primary, sync database to file, restart
13154 * zone management timer.
13155 */
13156static void
13157stub_finish_zone_update(dns_stub_t *stub, isc_time_t now) {
13158	uint32_t refresh, retry, expire;
13159	isc_result_t result;
13160	isc_interval_t i;
13161	unsigned int soacount;
13162	dns_zone_t *zone = stub->zone;
13163
13164	/*
13165	 * Tidy up.
13166	 */
13167	dns_db_closeversion(stub->db, &stub->version, true);
13168	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13169	if (zone->db == NULL) {
13170		zone_attachdb(zone, stub->db);
13171	}
13172	result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL, NULL,
13173				  &refresh, &retry, &expire, NULL, NULL);
13174	if (result == ISC_R_SUCCESS && soacount > 0U) {
13175		zone->refresh = RANGE(refresh, zone->minrefresh,
13176				      zone->maxrefresh);
13177		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
13178		zone->expire = RANGE(expire, zone->refresh + zone->retry,
13179				     DNS_MAX_EXPIRE);
13180		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13181	}
13182	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13183	dns_db_detach(&stub->db);
13184
13185	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13186	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
13187	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
13188	isc_interval_set(&i, zone->expire, 0);
13189	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
13190
13191	if (zone->masterfile != NULL) {
13192		zone_needdump(zone, 0);
13193	}
13194
13195	zone_settimer(zone, &now);
13196}
13197
13198/*
13199 * Process answers for A and AAAA queries when
13200 * resolving nameserver addresses for which glue
13201 * was missing in a previous answer for a NS query.
13202 */
13203static void
13204stub_glue_response_cb(isc_task_t *task, isc_event_t *event) {
13205	const char me[] = "stub_glue_response_cb";
13206	dns_requestevent_t *revent = (dns_requestevent_t *)event;
13207	dns_stub_t *stub = NULL;
13208	dns_message_t *msg = NULL;
13209	dns_zone_t *zone = NULL;
13210	char primary[ISC_SOCKADDR_FORMATSIZE];
13211	char source[ISC_SOCKADDR_FORMATSIZE];
13212	uint32_t addr_count, cnamecnt;
13213	isc_result_t result;
13214	isc_time_t now;
13215	struct stub_glue_request *request;
13216	struct stub_cb_args *cb_args;
13217	dns_rdataset_t *addr_rdataset = NULL;
13218	dns_dbnode_t *node = NULL;
13219
13220	UNUSED(task);
13221
13222	request = revent->ev_arg;
13223	cb_args = request->args;
13224	stub = cb_args->stub;
13225	INSIST(DNS_STUB_VALID(stub));
13226
13227	zone = stub->zone;
13228
13229	ENTER;
13230
13231	TIME_NOW(&now);
13232
13233	LOCK_ZONE(zone);
13234
13235	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13236		zone_debuglog(zone, me, 1, "exiting");
13237		goto cleanup;
13238	}
13239
13240	isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary));
13241	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13242
13243	if (revent->result != ISC_R_SUCCESS) {
13244		dns_zonemgr_unreachableadd(zone->zmgr, &zone->primaryaddr,
13245					   &zone->sourceaddr, &now);
13246		dns_zone_log(zone, ISC_LOG_INFO,
13247			     "could not refresh stub from primary %s"
13248			     " (source %s): %s",
13249			     primary, source,
13250			     isc_result_totext(revent->result));
13251		goto cleanup;
13252	}
13253
13254	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13255	result = dns_request_getresponse(revent->request, msg, 0);
13256	if (result != ISC_R_SUCCESS) {
13257		dns_zone_log(zone, ISC_LOG_INFO,
13258			     "refreshing stub: unable to parse response (%s)",
13259			     isc_result_totext(result));
13260		goto cleanup;
13261	}
13262
13263	/*
13264	 * Unexpected opcode.
13265	 */
13266	if (msg->opcode != dns_opcode_query) {
13267		char opcode[128];
13268		isc_buffer_t rb;
13269
13270		isc_buffer_init(&rb, opcode, sizeof(opcode));
13271		(void)dns_opcode_totext(msg->opcode, &rb);
13272
13273		dns_zone_log(zone, ISC_LOG_INFO,
13274			     "refreshing stub: "
13275			     "unexpected opcode (%.*s) from %s (source %s)",
13276			     (int)rb.used, opcode, primary, source);
13277		goto cleanup;
13278	}
13279
13280	/*
13281	 * Unexpected rcode.
13282	 */
13283	if (msg->rcode != dns_rcode_noerror) {
13284		char rcode[128];
13285		isc_buffer_t rb;
13286
13287		isc_buffer_init(&rb, rcode, sizeof(rcode));
13288		(void)dns_rcode_totext(msg->rcode, &rb);
13289
13290		dns_zone_log(zone, ISC_LOG_INFO,
13291			     "refreshing stub: "
13292			     "unexpected rcode (%.*s) from %s (source %s)",
13293			     (int)rb.used, rcode, primary, source);
13294		goto cleanup;
13295	}
13296
13297	/*
13298	 * We need complete messages.
13299	 */
13300	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13301		if (dns_request_usedtcp(revent->request)) {
13302			dns_zone_log(zone, ISC_LOG_INFO,
13303				     "refreshing stub: truncated TCP "
13304				     "response from primary %s (source %s)",
13305				     primary, source);
13306		}
13307		goto cleanup;
13308	}
13309
13310	/*
13311	 * If non-auth log.
13312	 */
13313	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13314		dns_zone_log(zone, ISC_LOG_INFO,
13315			     "refreshing stub: "
13316			     "non-authoritative answer from "
13317			     "primary %s (source %s)",
13318			     primary, source);
13319		goto cleanup;
13320	}
13321
13322	/*
13323	 * Sanity checks.
13324	 */
13325	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13326	addr_count = message_count(msg, DNS_SECTION_ANSWER,
13327				   request->ipv4 ? dns_rdatatype_a
13328						 : dns_rdatatype_aaaa);
13329
13330	if (cnamecnt != 0) {
13331		dns_zone_log(zone, ISC_LOG_INFO,
13332			     "refreshing stub: unexpected CNAME response "
13333			     "from primary %s (source %s)",
13334			     primary, source);
13335		goto cleanup;
13336	}
13337
13338	if (addr_count == 0) {
13339		dns_zone_log(zone, ISC_LOG_INFO,
13340			     "refreshing stub: no %s records in response "
13341			     "from primary %s (source %s)",
13342			     request->ipv4 ? "A" : "AAAA", primary, source);
13343		goto cleanup;
13344	}
13345	/*
13346	 * Extract A or AAAA RRset from message.
13347	 */
13348	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &request->name,
13349				      request->ipv4 ? dns_rdatatype_a
13350						    : dns_rdatatype_aaaa,
13351				      dns_rdatatype_none, NULL, &addr_rdataset);
13352	if (result != ISC_R_SUCCESS) {
13353		if (result != DNS_R_NXDOMAIN && result != DNS_R_NXRRSET) {
13354			char namebuf[DNS_NAME_FORMATSIZE];
13355			dns_name_format(&request->name, namebuf,
13356					sizeof(namebuf));
13357			dns_zone_log(
13358				zone, ISC_LOG_INFO,
13359				"refreshing stub: dns_message_findname(%s/%s) "
13360				"failed (%s)",
13361				namebuf, request->ipv4 ? "A" : "AAAA",
13362				isc_result_totext(result));
13363		}
13364		goto cleanup;
13365	}
13366
13367	result = dns_db_findnode(stub->db, &request->name, true, &node);
13368	if (result != ISC_R_SUCCESS) {
13369		dns_zone_log(zone, ISC_LOG_INFO,
13370			     "refreshing stub: "
13371			     "dns_db_findnode() failed: %s",
13372			     isc_result_totext(result));
13373		goto cleanup;
13374	}
13375
13376	result = dns_db_addrdataset(stub->db, node, stub->version, 0,
13377				    addr_rdataset, 0, NULL);
13378	if (result != ISC_R_SUCCESS) {
13379		dns_zone_log(zone, ISC_LOG_INFO,
13380			     "refreshing stub: "
13381			     "dns_db_addrdataset() failed: %s",
13382			     isc_result_totext(result));
13383	}
13384	dns_db_detachnode(stub->db, &node);
13385
13386cleanup:
13387	if (msg != NULL) {
13388		dns_message_detach(&msg);
13389	}
13390	isc_event_free(&event);
13391	dns_name_free(&request->name, zone->mctx);
13392	dns_request_destroy(&request->request);
13393	isc_mem_put(zone->mctx, request, sizeof(*request));
13394
13395	/* If last request, release all related resources */
13396	if (atomic_fetch_sub_release(&stub->pending_requests, 1) == 1) {
13397		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13398		stub_finish_zone_update(stub, now);
13399		UNLOCK_ZONE(zone);
13400		stub->magic = 0;
13401		dns_zone_idetach(&stub->zone);
13402		INSIST(stub->db == NULL);
13403		INSIST(stub->version == NULL);
13404		isc_mem_put(stub->mctx, stub, sizeof(*stub));
13405	} else {
13406		UNLOCK_ZONE(zone);
13407	}
13408}
13409
13410/*
13411 * Create and send an A or AAAA query to the primary
13412 * server of the stub zone given.
13413 */
13414static isc_result_t
13415stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
13416				const dns_name_t *name) {
13417	dns_message_t *message = NULL;
13418	dns_zone_t *zone;
13419	isc_result_t result;
13420	struct stub_glue_request *request;
13421
13422	zone = args->stub->zone;
13423	request = isc_mem_get(zone->mctx, sizeof(*request));
13424	request->request = NULL;
13425	request->args = args;
13426	request->name = (dns_name_t)DNS_NAME_INITEMPTY;
13427	request->ipv4 = ipv4;
13428	dns_name_dup(name, zone->mctx, &request->name);
13429
13430	result = create_query(zone, ipv4 ? dns_rdatatype_a : dns_rdatatype_aaaa,
13431			      &request->name, &message);
13432	INSIST(result == ISC_R_SUCCESS);
13433
13434	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13435		result = add_opt(message, args->udpsize, args->reqnsid, false);
13436		if (result != ISC_R_SUCCESS) {
13437			zone_debuglog(zone, "stub_send_query", 1,
13438				      "unable to add opt record: %s",
13439				      isc_result_totext(result));
13440			goto fail;
13441		}
13442	}
13443
13444	atomic_fetch_add_release(&args->stub->pending_requests, 1);
13445
13446	result = dns_request_create(
13447		zone->view->requestmgr, message, &zone->sourceaddr,
13448		&zone->primaryaddr, DNS_REQUESTOPT_TCP, args->tsig_key,
13449		args->timeout * 3, args->timeout, 2, zone->task,
13450		stub_glue_response_cb, request, &request->request);
13451
13452	if (result != ISC_R_SUCCESS) {
13453		uint_fast32_t pr;
13454		pr = atomic_fetch_sub_release(&args->stub->pending_requests, 1);
13455		INSIST(pr > 1);
13456		zone_debuglog(zone, "stub_send_query", 1,
13457			      "dns_request_create() failed: %s",
13458			      isc_result_totext(result));
13459		goto fail;
13460	}
13461
13462	dns_message_detach(&message);
13463
13464	return (ISC_R_SUCCESS);
13465
13466fail:
13467	dns_name_free(&request->name, zone->mctx);
13468	isc_mem_put(zone->mctx, request, sizeof(*request));
13469
13470	if (message != NULL) {
13471		dns_message_detach(&message);
13472	}
13473
13474	return (result);
13475}
13476
13477static isc_result_t
13478save_nsrrset(dns_message_t *message, dns_name_t *name,
13479	     struct stub_cb_args *cb_args, dns_db_t *db,
13480	     dns_dbversion_t *version) {
13481	dns_rdataset_t *nsrdataset = NULL;
13482	dns_rdataset_t *rdataset = NULL;
13483	dns_dbnode_t *node = NULL;
13484	dns_rdata_ns_t ns;
13485	isc_result_t result;
13486	dns_rdata_t rdata = DNS_RDATA_INIT;
13487	bool has_glue = false;
13488	dns_name_t *ns_name;
13489	/*
13490	 * List of NS entries in answer, keep names that will be used
13491	 * to resolve missing A/AAAA glue for each entry.
13492	 */
13493	dns_namelist_t ns_list;
13494	ISC_LIST_INIT(ns_list);
13495
13496	/*
13497	 * Extract NS RRset from message.
13498	 */
13499	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
13500				      dns_rdatatype_ns, dns_rdatatype_none,
13501				      NULL, &nsrdataset);
13502	if (result != ISC_R_SUCCESS) {
13503		goto done;
13504	}
13505
13506	/*
13507	 * Add NS rdataset.
13508	 */
13509	result = dns_db_findnode(db, name, true, &node);
13510	if (result != ISC_R_SUCCESS) {
13511		goto done;
13512	}
13513	result = dns_db_addrdataset(db, node, version, 0, nsrdataset, 0, NULL);
13514	dns_db_detachnode(db, &node);
13515	if (result != ISC_R_SUCCESS) {
13516		goto done;
13517	}
13518	/*
13519	 * Add glue rdatasets.
13520	 */
13521	for (result = dns_rdataset_first(nsrdataset); result == ISC_R_SUCCESS;
13522	     result = dns_rdataset_next(nsrdataset))
13523	{
13524		dns_rdataset_current(nsrdataset, &rdata);
13525		result = dns_rdata_tostruct(&rdata, &ns, NULL);
13526		RUNTIME_CHECK(result == ISC_R_SUCCESS);
13527		dns_rdata_reset(&rdata);
13528
13529		if (!dns_name_issubdomain(&ns.name, name)) {
13530			continue;
13531		}
13532		rdataset = NULL;
13533		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
13534					      &ns.name, dns_rdatatype_aaaa,
13535					      dns_rdatatype_none, NULL,
13536					      &rdataset);
13537		if (result == ISC_R_SUCCESS) {
13538			has_glue = true;
13539			result = dns_db_findnode(db, &ns.name, true, &node);
13540			if (result != ISC_R_SUCCESS) {
13541				goto done;
13542			}
13543			result = dns_db_addrdataset(db, node, version, 0,
13544						    rdataset, 0, NULL);
13545			dns_db_detachnode(db, &node);
13546			if (result != ISC_R_SUCCESS) {
13547				goto done;
13548			}
13549		}
13550
13551		rdataset = NULL;
13552		result = dns_message_findname(
13553			message, DNS_SECTION_ADDITIONAL, &ns.name,
13554			dns_rdatatype_a, dns_rdatatype_none, NULL, &rdataset);
13555		if (result == ISC_R_SUCCESS) {
13556			has_glue = true;
13557			result = dns_db_findnode(db, &ns.name, true, &node);
13558			if (result != ISC_R_SUCCESS) {
13559				goto done;
13560			}
13561			result = dns_db_addrdataset(db, node, version, 0,
13562						    rdataset, 0, NULL);
13563			dns_db_detachnode(db, &node);
13564			if (result != ISC_R_SUCCESS) {
13565				goto done;
13566			}
13567		}
13568
13569		/*
13570		 * If no glue is found so far, we add the name to the list to
13571		 * resolve the A/AAAA glue later. If any glue is found in any
13572		 * iteration step, this list will be discarded and only the glue
13573		 * provided in this message will be used.
13574		 */
13575		if (!has_glue && dns_name_issubdomain(&ns.name, name)) {
13576			dns_name_t *tmp_name;
13577			tmp_name = isc_mem_get(cb_args->stub->mctx,
13578					       sizeof(*tmp_name));
13579			dns_name_init(tmp_name, NULL);
13580			dns_name_dup(&ns.name, cb_args->stub->mctx, tmp_name);
13581			ISC_LIST_APPEND(ns_list, tmp_name, link);
13582		}
13583	}
13584
13585	if (result != ISC_R_NOMORE) {
13586		goto done;
13587	}
13588
13589	/*
13590	 * If no glue records were found, we attempt to resolve A/AAAA
13591	 * for each NS entry found in the answer.
13592	 */
13593	if (!has_glue) {
13594		for (ns_name = ISC_LIST_HEAD(ns_list); ns_name != NULL;
13595		     ns_name = ISC_LIST_NEXT(ns_name, link))
13596		{
13597			/*
13598			 * Resolve NS IPv4 address/A.
13599			 */
13600			result = stub_request_nameserver_address(cb_args, true,
13601								 ns_name);
13602			if (result != ISC_R_SUCCESS) {
13603				goto done;
13604			}
13605			/*
13606			 * Resolve NS IPv6 address/AAAA.
13607			 */
13608			result = stub_request_nameserver_address(cb_args, false,
13609								 ns_name);
13610			if (result != ISC_R_SUCCESS) {
13611				goto done;
13612			}
13613		}
13614	}
13615
13616	result = ISC_R_SUCCESS;
13617
13618done:
13619	while ((ns_name = ISC_LIST_HEAD(ns_list)) != NULL) {
13620		ISC_LIST_UNLINK(ns_list, ns_name, link);
13621		dns_name_free(ns_name, cb_args->stub->mctx);
13622		isc_mem_put(cb_args->stub->mctx, ns_name, sizeof(*ns_name));
13623	}
13624	return (result);
13625}
13626
13627static void
13628stub_callback(isc_task_t *task, isc_event_t *event) {
13629	const char me[] = "stub_callback";
13630	dns_requestevent_t *revent = (dns_requestevent_t *)event;
13631	dns_stub_t *stub = NULL;
13632	dns_message_t *msg = NULL;
13633	dns_zone_t *zone = NULL;
13634	char primary[ISC_SOCKADDR_FORMATSIZE];
13635	char source[ISC_SOCKADDR_FORMATSIZE];
13636	uint32_t nscnt, cnamecnt;
13637	isc_result_t result;
13638	isc_time_t now;
13639	bool exiting = false;
13640	unsigned int j;
13641	struct stub_cb_args *cb_args;
13642
13643	cb_args = revent->ev_arg;
13644	stub = cb_args->stub;
13645	INSIST(DNS_STUB_VALID(stub));
13646
13647	UNUSED(task);
13648
13649	zone = stub->zone;
13650
13651	ENTER;
13652
13653	TIME_NOW(&now);
13654
13655	LOCK_ZONE(zone);
13656
13657	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13658		goto exiting;
13659	}
13660
13661	isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary));
13662	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13663
13664	switch (revent->result) {
13665	case ISC_R_SUCCESS:
13666		break;
13667	case ISC_R_SHUTTINGDOWN:
13668		goto exiting;
13669	case ISC_R_TIMEDOUT:
13670		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13671			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13672			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13673				     "refreshing stub: timeout retrying "
13674				     "without EDNS primary %s (source %s)",
13675				     primary, source);
13676			goto same_primary;
13677		}
13678		FALLTHROUGH;
13679	default:
13680		dns_zonemgr_unreachableadd(zone->zmgr, &zone->primaryaddr,
13681					   &zone->sourceaddr, &now);
13682		dns_zone_log(zone, ISC_LOG_INFO,
13683			     "could not refresh stub from primary "
13684			     "%s (source %s): %s",
13685			     primary, source,
13686			     isc_result_totext(revent->result));
13687		goto next_primary;
13688	}
13689
13690	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13691
13692	result = dns_request_getresponse(revent->request, msg, 0);
13693	if (result != ISC_R_SUCCESS) {
13694		goto next_primary;
13695	}
13696
13697	/*
13698	 * Unexpected opcode.
13699	 */
13700	if (msg->opcode != dns_opcode_query) {
13701		char opcode[128];
13702		isc_buffer_t rb;
13703
13704		isc_buffer_init(&rb, opcode, sizeof(opcode));
13705		(void)dns_opcode_totext(msg->opcode, &rb);
13706
13707		dns_zone_log(zone, ISC_LOG_INFO,
13708			     "refreshing stub: "
13709			     "unexpected opcode (%.*s) from %s (source %s)",
13710			     (int)rb.used, opcode, primary, source);
13711		goto next_primary;
13712	}
13713
13714	/*
13715	 * Unexpected rcode.
13716	 */
13717	if (msg->rcode != dns_rcode_noerror) {
13718		char rcode[128];
13719		isc_buffer_t rb;
13720
13721		isc_buffer_init(&rb, rcode, sizeof(rcode));
13722		(void)dns_rcode_totext(msg->rcode, &rb);
13723
13724		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13725		    (msg->rcode == dns_rcode_servfail ||
13726		     msg->rcode == dns_rcode_notimp ||
13727		     (msg->rcode == dns_rcode_formerr && msg->opt == NULL)))
13728		{
13729			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13730				     "refreshing stub: rcode (%.*s) retrying "
13731				     "without EDNS primary %s (source %s)",
13732				     (int)rb.used, rcode, primary, source);
13733			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13734			goto same_primary;
13735		}
13736
13737		dns_zone_log(zone, ISC_LOG_INFO,
13738			     "refreshing stub: "
13739			     "unexpected rcode (%.*s) from %s (source %s)",
13740			     (int)rb.used, rcode, primary, source);
13741		goto next_primary;
13742	}
13743
13744	/*
13745	 * We need complete messages.
13746	 */
13747	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13748		if (dns_request_usedtcp(revent->request)) {
13749			dns_zone_log(zone, ISC_LOG_INFO,
13750				     "refreshing stub: truncated TCP "
13751				     "response from primary %s (source %s)",
13752				     primary, source);
13753			goto next_primary;
13754		}
13755		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
13756		goto same_primary;
13757	}
13758
13759	/*
13760	 * If non-auth log and next primary.
13761	 */
13762	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13763		dns_zone_log(zone, ISC_LOG_INFO,
13764			     "refreshing stub: "
13765			     "non-authoritative answer from "
13766			     "primary %s (source %s)",
13767			     primary, source);
13768		goto next_primary;
13769	}
13770
13771	/*
13772	 * Sanity checks.
13773	 */
13774	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13775	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
13776
13777	if (cnamecnt != 0) {
13778		dns_zone_log(zone, ISC_LOG_INFO,
13779			     "refreshing stub: unexpected CNAME response "
13780			     "from primary %s (source %s)",
13781			     primary, source);
13782		goto next_primary;
13783	}
13784
13785	if (nscnt == 0) {
13786		dns_zone_log(zone, ISC_LOG_INFO,
13787			     "refreshing stub: no NS records in response "
13788			     "from primary %s (source %s)",
13789			     primary, source);
13790		goto next_primary;
13791	}
13792
13793	atomic_fetch_add(&stub->pending_requests, 1);
13794
13795	/*
13796	 * Save answer.
13797	 */
13798	result = save_nsrrset(msg, &zone->origin, cb_args, stub->db,
13799			      stub->version);
13800	if (result != ISC_R_SUCCESS) {
13801		dns_zone_log(zone, ISC_LOG_INFO,
13802			     "refreshing stub: unable to save NS records "
13803			     "from primary %s (source %s)",
13804			     primary, source);
13805		goto next_primary;
13806	}
13807
13808	dns_message_detach(&msg);
13809	isc_event_free(&event);
13810	dns_request_destroy(&zone->request);
13811
13812	/*
13813	 * Check to see if there are no outstanding requests and
13814	 * finish off if that is so.
13815	 */
13816	if (atomic_fetch_sub(&stub->pending_requests, 1) == 1) {
13817		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13818		stub_finish_zone_update(stub, now);
13819		goto free_stub;
13820	}
13821
13822	UNLOCK_ZONE(zone);
13823	return;
13824
13825exiting:
13826	zone_debuglog(zone, me, 1, "exiting");
13827	exiting = true;
13828
13829next_primary:
13830	isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13831	if (stub->version != NULL) {
13832		dns_db_closeversion(stub->db, &stub->version, false);
13833	}
13834	if (stub->db != NULL) {
13835		dns_db_detach(&stub->db);
13836	}
13837	if (msg != NULL) {
13838		dns_message_detach(&msg);
13839	}
13840	isc_event_free(&event);
13841	dns_request_destroy(&zone->request);
13842	/*
13843	 * Skip to next failed / untried primary.
13844	 */
13845	do {
13846		zone->curprimary++;
13847	} while (zone->curprimary < zone->primariescnt &&
13848		 zone->primariesok[zone->curprimary]);
13849	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
13850	if (exiting || zone->curprimary >= zone->primariescnt) {
13851		bool done = true;
13852		if (!exiting &&
13853		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13854		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
13855		{
13856			/*
13857			 * Did we get a good answer from all the primaries?
13858			 */
13859			for (j = 0; j < zone->primariescnt; j++) {
13860				if (!zone->primariesok[j]) {
13861					{
13862						done = false;
13863						break;
13864					}
13865				}
13866			}
13867		} else {
13868			done = true;
13869		}
13870		if (!done) {
13871			zone->curprimary = 0;
13872			/*
13873			 * Find the next failed primary.
13874			 */
13875			while (zone->curprimary < zone->primariescnt &&
13876			       zone->primariesok[zone->curprimary])
13877			{
13878				zone->curprimary++;
13879			}
13880			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13881		} else {
13882			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13883
13884			zone_settimer(zone, &now);
13885			goto free_stub;
13886		}
13887	}
13888	queue_soa_query(zone);
13889	goto free_stub;
13890
13891same_primary:
13892	isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13893	if (msg != NULL) {
13894		dns_message_detach(&msg);
13895	}
13896	isc_event_free(&event);
13897	dns_request_destroy(&zone->request);
13898	ns_query(zone, NULL, stub);
13899	UNLOCK_ZONE(zone);
13900	goto done;
13901
13902free_stub:
13903	UNLOCK_ZONE(zone);
13904	stub->magic = 0;
13905	dns_zone_idetach(&stub->zone);
13906	INSIST(stub->db == NULL);
13907	INSIST(stub->version == NULL);
13908	isc_mem_put(stub->mctx, stub, sizeof(*stub));
13909
13910done:
13911	INSIST(event == NULL);
13912	return;
13913}
13914
13915/*
13916 * Get the EDNS EXPIRE option from the response and if it exists trim
13917 * expire to be not more than it.
13918 */
13919static void
13920get_edns_expire(dns_zone_t *zone, dns_message_t *message, uint32_t *expirep) {
13921	isc_result_t result;
13922	uint32_t expire;
13923	dns_rdata_t rdata = DNS_RDATA_INIT;
13924	isc_buffer_t optbuf;
13925	uint16_t optcode;
13926	uint16_t optlen;
13927
13928	REQUIRE(expirep != NULL);
13929	REQUIRE(message != NULL);
13930
13931	if (message->opt == NULL) {
13932		return;
13933	}
13934
13935	result = dns_rdataset_first(message->opt);
13936	if (result == ISC_R_SUCCESS) {
13937		dns_rdataset_current(message->opt, &rdata);
13938		isc_buffer_init(&optbuf, rdata.data, rdata.length);
13939		isc_buffer_add(&optbuf, rdata.length);
13940		while (isc_buffer_remaininglength(&optbuf) >= 4) {
13941			optcode = isc_buffer_getuint16(&optbuf);
13942			optlen = isc_buffer_getuint16(&optbuf);
13943			/*
13944			 * A EDNS EXPIRE response has a length of 4.
13945			 */
13946			if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
13947				isc_buffer_forward(&optbuf, optlen);
13948				continue;
13949			}
13950			expire = isc_buffer_getuint32(&optbuf);
13951			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13952				     "got EDNS EXPIRE of %u", expire);
13953			/*
13954			 * Trim *expirep?
13955			 */
13956			if (expire < *expirep) {
13957				*expirep = expire;
13958			}
13959			break;
13960		}
13961	}
13962}
13963
13964/*
13965 * Set the file modification time zone->expire seconds before expiretime.
13966 */
13967static void
13968setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
13969	isc_result_t result;
13970	isc_time_t when;
13971	isc_interval_t i;
13972
13973	isc_interval_set(&i, zone->expire, 0);
13974	result = isc_time_subtract(expiretime, &i, &when);
13975	if (result != ISC_R_SUCCESS) {
13976		return;
13977	}
13978
13979	result = ISC_R_FAILURE;
13980	if (zone->journal != NULL) {
13981		result = isc_file_settime(zone->journal, &when);
13982	}
13983	if (result == ISC_R_SUCCESS &&
13984	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13985	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
13986	{
13987		result = isc_file_settime(zone->masterfile, &when);
13988	} else if (result != ISC_R_SUCCESS) {
13989		result = isc_file_settime(zone->masterfile, &when);
13990	}
13991
13992	/*
13993	 * Someone removed the file from underneath us!
13994	 */
13995	if (result == ISC_R_FILENOTFOUND) {
13996		zone_needdump(zone, DNS_DUMP_DELAY);
13997	} else if (result != ISC_R_SUCCESS) {
13998		dns_zone_log(zone, ISC_LOG_ERROR,
13999			     "refresh: could not set "
14000			     "file modification time of '%s': %s",
14001			     zone->masterfile, isc_result_totext(result));
14002	}
14003}
14004
14005/*
14006 * An SOA query has finished (successfully or not).
14007 */
14008static void
14009refresh_callback(isc_task_t *task, isc_event_t *event) {
14010	const char me[] = "refresh_callback";
14011	dns_requestevent_t *revent = (dns_requestevent_t *)event;
14012	dns_zone_t *zone;
14013	dns_message_t *msg = NULL;
14014	uint32_t soacnt, cnamecnt, soacount, nscount;
14015	isc_time_t now;
14016	char primary[ISC_SOCKADDR_FORMATSIZE];
14017	char source[ISC_SOCKADDR_FORMATSIZE];
14018	dns_rdataset_t *rdataset = NULL;
14019	dns_rdata_t rdata = DNS_RDATA_INIT;
14020	dns_rdata_soa_t soa;
14021	isc_result_t result;
14022	uint32_t serial, oldserial = 0;
14023	unsigned int j;
14024	bool do_queue_xfrin = false;
14025
14026	zone = revent->ev_arg;
14027	INSIST(DNS_ZONE_VALID(zone));
14028
14029	UNUSED(task);
14030
14031	ENTER;
14032
14033	TIME_NOW(&now);
14034
14035	LOCK_ZONE(zone);
14036
14037	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14038		goto exiting;
14039	}
14040
14041	/*
14042	 * If timeout, log and try the next primary
14043	 */
14044	isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary));
14045	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14046
14047	switch (revent->result) {
14048	case ISC_R_SUCCESS:
14049		break;
14050	case ISC_R_SHUTTINGDOWN:
14051		goto exiting;
14052	case ISC_R_TIMEDOUT:
14053		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14054			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14055			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14056				     "refresh: timeout retrying without EDNS "
14057				     "primary %s (source %s)",
14058				     primary, source);
14059			goto same_primary;
14060		} else if (!dns_request_usedtcp(revent->request)) {
14061			dns_zone_log(zone, ISC_LOG_INFO,
14062				     "refresh: retry limit for "
14063				     "primary %s exceeded (source %s)",
14064				     primary, source);
14065			/* Try with secondary with TCP. */
14066			if ((zone->type == dns_zone_secondary ||
14067			     zone->type == dns_zone_mirror ||
14068			     zone->type == dns_zone_redirect) &&
14069			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
14070			{
14071				if (!dns_zonemgr_unreachable(
14072					    zone->zmgr, &zone->primaryaddr,
14073					    &zone->sourceaddr, &now))
14074				{
14075					DNS_ZONE_SETFLAG(
14076						zone,
14077						DNS_ZONEFLG_SOABEFOREAXFR);
14078					goto tcp_transfer;
14079				}
14080				dns_zone_log(zone, ISC_LOG_DEBUG(1),
14081					     "refresh: skipped tcp fallback "
14082					     "as primary %s (source %s) is "
14083					     "unreachable (cached)",
14084					     primary, source);
14085			}
14086			goto next_primary;
14087		}
14088		FALLTHROUGH;
14089	default:
14090		dns_zone_log(zone, ISC_LOG_INFO,
14091			     "refresh: failure trying primary "
14092			     "%s (source %s): %s",
14093			     primary, source,
14094			     isc_result_totext(revent->result));
14095		goto next_primary;
14096	}
14097
14098	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
14099	result = dns_request_getresponse(revent->request, msg, 0);
14100	if (result != ISC_R_SUCCESS) {
14101		dns_zone_log(zone, ISC_LOG_INFO,
14102			     "refresh: failure trying primary "
14103			     "%s (source %s): %s",
14104			     primary, source, isc_result_totext(result));
14105		goto next_primary;
14106	}
14107
14108	/*
14109	 * Unexpected opcode.
14110	 */
14111	if (msg->opcode != dns_opcode_query) {
14112		char opcode[128];
14113		isc_buffer_t rb;
14114
14115		isc_buffer_init(&rb, opcode, sizeof(opcode));
14116		(void)dns_opcode_totext(msg->opcode, &rb);
14117
14118		dns_zone_log(zone, ISC_LOG_INFO,
14119			     "refresh: "
14120			     "unexpected opcode (%.*s) from %s (source %s)",
14121			     (int)rb.used, opcode, primary, source);
14122		goto next_primary;
14123	}
14124
14125	/*
14126	 * Unexpected rcode.
14127	 */
14128	if (msg->rcode != dns_rcode_noerror) {
14129		char rcode[128];
14130		isc_buffer_t rb;
14131
14132		isc_buffer_init(&rb, rcode, sizeof(rcode));
14133		(void)dns_rcode_totext(msg->rcode, &rb);
14134
14135		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14136		    (msg->rcode == dns_rcode_servfail ||
14137		     msg->rcode == dns_rcode_notimp ||
14138		     (msg->rcode == dns_rcode_formerr && msg->opt == NULL)))
14139		{
14140			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14141				     "refresh: rcode (%.*s) retrying without "
14142				     "EDNS primary %s (source %s)",
14143				     (int)rb.used, rcode, primary, source);
14144			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14145			goto same_primary;
14146		}
14147		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14148		    msg->rcode == dns_rcode_badvers)
14149		{
14150			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14151				     "refresh: rcode (%.*s) retrying without "
14152				     "EDNS EXPIRE OPTION primary %s "
14153				     "(source %s)",
14154				     (int)rb.used, rcode, primary, source);
14155			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14156			goto same_primary;
14157		}
14158		dns_zone_log(zone, ISC_LOG_INFO,
14159			     "refresh: unexpected rcode (%.*s) from "
14160			     "primary %s (source %s)",
14161			     (int)rb.used, rcode, primary, source);
14162		/*
14163		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
14164		 */
14165		if (msg->rcode == dns_rcode_refused &&
14166		    (zone->type == dns_zone_secondary ||
14167		     zone->type == dns_zone_mirror ||
14168		     zone->type == dns_zone_redirect))
14169		{
14170			goto tcp_transfer;
14171		}
14172		goto next_primary;
14173	}
14174
14175	/*
14176	 * If truncated punt to zone transfer which will query again.
14177	 */
14178	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
14179		if (zone->type == dns_zone_secondary ||
14180		    zone->type == dns_zone_mirror ||
14181		    zone->type == dns_zone_redirect)
14182		{
14183			dns_zone_log(zone, ISC_LOG_INFO,
14184				     "refresh: truncated UDP answer, "
14185				     "initiating TCP zone xfer "
14186				     "for primary %s (source %s)",
14187				     primary, source);
14188			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14189			goto tcp_transfer;
14190		} else {
14191			INSIST(zone->type == dns_zone_stub);
14192			if (dns_request_usedtcp(revent->request)) {
14193				dns_zone_log(zone, ISC_LOG_INFO,
14194					     "refresh: truncated TCP response "
14195					     "from primary %s (source %s)",
14196					     primary, source);
14197				goto next_primary;
14198			}
14199			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
14200			goto same_primary;
14201		}
14202	}
14203
14204	/*
14205	 * If non-auth, log and try the next primary
14206	 */
14207	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
14208		dns_zone_log(zone, ISC_LOG_INFO,
14209			     "refresh: non-authoritative answer from "
14210			     "primary %s (source %s)",
14211			     primary, source);
14212		goto next_primary;
14213	}
14214
14215	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
14216	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
14217	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
14218	soacount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_soa);
14219
14220	/*
14221	 * There should not be a CNAME record at top of zone.
14222	 */
14223	if (cnamecnt != 0) {
14224		dns_zone_log(zone, ISC_LOG_INFO,
14225			     "refresh: CNAME at top of zone "
14226			     "in primary %s (source %s)",
14227			     primary, source);
14228		goto next_primary;
14229	}
14230
14231	/*
14232	 * If referral, log and try the next primary;
14233	 */
14234	if (soacnt == 0 && soacount == 0 && nscount != 0) {
14235		dns_zone_log(zone, ISC_LOG_INFO,
14236			     "refresh: referral response "
14237			     "from primary %s (source %s)",
14238			     primary, source);
14239		goto next_primary;
14240	}
14241
14242	/*
14243	 * If nodata, log and try the next primary;
14244	 */
14245	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
14246		dns_zone_log(zone, ISC_LOG_INFO,
14247			     "refresh: NODATA response "
14248			     "from primary %s (source %s)",
14249			     primary, source);
14250		goto next_primary;
14251	}
14252
14253	/*
14254	 * Only one soa at top of zone.
14255	 */
14256	if (soacnt != 1) {
14257		dns_zone_log(zone, ISC_LOG_INFO,
14258			     "refresh: answer SOA count (%d) != 1 "
14259			     "from primary %s (source %s)",
14260			     soacnt, primary, source);
14261		goto next_primary;
14262	}
14263
14264	/*
14265	 * Extract serial
14266	 */
14267	rdataset = NULL;
14268	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
14269				      dns_rdatatype_soa, dns_rdatatype_none,
14270				      NULL, &rdataset);
14271	if (result != ISC_R_SUCCESS) {
14272		dns_zone_log(zone, ISC_LOG_INFO,
14273			     "refresh: unable to get SOA record "
14274			     "from primary %s (source %s)",
14275			     primary, source);
14276		goto next_primary;
14277	}
14278
14279	result = dns_rdataset_first(rdataset);
14280	if (result != ISC_R_SUCCESS) {
14281		dns_zone_log(zone, ISC_LOG_INFO,
14282			     "refresh: dns_rdataset_first() failed");
14283		goto next_primary;
14284	}
14285
14286	dns_rdataset_current(rdataset, &rdata);
14287	result = dns_rdata_tostruct(&rdata, &soa, NULL);
14288	RUNTIME_CHECK(result == ISC_R_SUCCESS);
14289
14290	serial = soa.serial;
14291	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
14292		unsigned int dbsoacount;
14293		result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
14294					  NULL, &oldserial, NULL, NULL, NULL,
14295					  NULL, NULL);
14296		RUNTIME_CHECK(result == ISC_R_SUCCESS);
14297		RUNTIME_CHECK(dbsoacount > 0U);
14298		zone_debuglog(zone, me, 1, "serial: new %u, old %u", serial,
14299			      oldserial);
14300	} else {
14301		zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
14302			      serial);
14303	}
14304
14305	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
14306	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
14307	    isc_serial_gt(serial, oldserial))
14308	{
14309		if (dns_zonemgr_unreachable(zone->zmgr, &zone->primaryaddr,
14310					    &zone->sourceaddr, &now))
14311		{
14312			dns_zone_log(zone, ISC_LOG_INFO,
14313				     "refresh: skipping %s as primary %s "
14314				     "(source %s) is unreachable (cached)",
14315				     (zone->type == dns_zone_secondary ||
14316				      zone->type == dns_zone_mirror ||
14317				      zone->type == dns_zone_redirect)
14318					     ? "zone transfer"
14319					     : "NS query",
14320				     primary, source);
14321			goto next_primary;
14322		}
14323	tcp_transfer:
14324		isc_event_free(&event);
14325		dns_request_destroy(&zone->request);
14326		if (zone->type == dns_zone_secondary ||
14327		    zone->type == dns_zone_mirror ||
14328		    zone->type == dns_zone_redirect)
14329		{
14330			do_queue_xfrin = true;
14331		} else {
14332			INSIST(zone->type == dns_zone_stub);
14333			ns_query(zone, rdataset, NULL);
14334		}
14335		if (msg != NULL) {
14336			dns_message_detach(&msg);
14337		}
14338	} else if (isc_serial_eq(soa.serial, oldserial)) {
14339		isc_time_t expiretime;
14340		uint32_t expire;
14341
14342		/*
14343		 * Compute the new expire time based on this response.
14344		 */
14345		expire = zone->expire;
14346		get_edns_expire(zone, msg, &expire);
14347		DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
14348
14349		/*
14350		 * Has the expire time improved?
14351		 */
14352		if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
14353			zone->expiretime = expiretime;
14354			if (zone->masterfile != NULL) {
14355				setmodtime(zone, &expiretime);
14356			}
14357		}
14358
14359		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
14360		zone->primariesok[zone->curprimary] = true;
14361		goto next_primary;
14362	} else {
14363		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) {
14364			dns_zone_log(zone, ISC_LOG_INFO,
14365				     "serial number (%u) "
14366				     "received from primary %s < ours (%u)",
14367				     soa.serial, primary, oldserial);
14368		} else {
14369			zone_debuglog(zone, me, 1, "ahead");
14370		}
14371		zone->primariesok[zone->curprimary] = true;
14372		goto next_primary;
14373	}
14374	if (msg != NULL) {
14375		dns_message_detach(&msg);
14376	}
14377	goto detach;
14378
14379next_primary:
14380	if (msg != NULL) {
14381		dns_message_detach(&msg);
14382	}
14383	isc_event_free(&event);
14384	dns_request_destroy(&zone->request);
14385	/*
14386	 * Skip to next failed / untried primary.
14387	 */
14388	do {
14389		zone->curprimary++;
14390	} while (zone->curprimary < zone->primariescnt &&
14391		 zone->primariesok[zone->curprimary]);
14392	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
14393	if (zone->curprimary >= zone->primariescnt) {
14394		bool done = true;
14395		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
14396		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
14397		{
14398			/*
14399			 * Did we get a good answer from all the primaries?
14400			 */
14401			for (j = 0; j < zone->primariescnt; j++) {
14402				if (!zone->primariesok[j]) {
14403					{
14404						done = false;
14405						break;
14406					}
14407				}
14408			}
14409		} else {
14410			done = true;
14411		}
14412		if (!done) {
14413			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14414			zone->curprimary = 0;
14415			/*
14416			 * Find the next failed primary.
14417			 */
14418			while (zone->curprimary < zone->primariescnt &&
14419			       zone->primariesok[zone->curprimary])
14420			{
14421				zone->curprimary++;
14422			}
14423			goto requeue;
14424		}
14425		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14426		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
14427			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
14428			zone->refreshtime = now;
14429		}
14430		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14431		zone_settimer(zone, &now);
14432		goto detach;
14433	}
14434
14435requeue:
14436	queue_soa_query(zone);
14437	goto detach;
14438
14439exiting:
14440	isc_event_free(&event);
14441	dns_request_destroy(&zone->request);
14442	goto detach;
14443
14444same_primary:
14445	if (msg != NULL) {
14446		dns_message_detach(&msg);
14447	}
14448	isc_event_free(&event);
14449	dns_request_destroy(&zone->request);
14450	queue_soa_query(zone);
14451
14452detach:
14453	UNLOCK_ZONE(zone);
14454	if (do_queue_xfrin) {
14455		queue_xfrin(zone);
14456	}
14457	dns_zone_idetach(&zone);
14458	return;
14459}
14460
14461static void
14462queue_soa_query(dns_zone_t *zone) {
14463	const char me[] = "queue_soa_query";
14464	isc_event_t *e;
14465	dns_zone_t *dummy = NULL;
14466	isc_result_t result;
14467
14468	ENTER;
14469	/*
14470	 * Locked by caller
14471	 */
14472	REQUIRE(LOCKED_ZONE(zone));
14473
14474	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14475		cancel_refresh(zone);
14476		return;
14477	}
14478
14479	e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE, soa_query,
14480			       zone, sizeof(isc_event_t));
14481
14482	/*
14483	 * Attach so that we won't clean up
14484	 * until the event is delivered.
14485	 */
14486	zone_iattach(zone, &dummy);
14487
14488	e->ev_arg = zone;
14489	e->ev_sender = NULL;
14490	result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
14491	if (result != ISC_R_SUCCESS) {
14492		zone_idetach(&dummy);
14493		isc_event_free(&e);
14494		cancel_refresh(zone);
14495	}
14496}
14497
14498static void
14499soa_query(isc_task_t *task, isc_event_t *event) {
14500	const char me[] = "soa_query";
14501	isc_result_t result = ISC_R_FAILURE;
14502	dns_message_t *message = NULL;
14503	dns_zone_t *zone = event->ev_arg;
14504	dns_zone_t *dummy = NULL;
14505	isc_netaddr_t primaryip;
14506	dns_tsigkey_t *key = NULL;
14507	dns_transport_t *transport = NULL;
14508	uint32_t options;
14509	bool cancel = true;
14510	int timeout;
14511	bool have_xfrsource = false, reqnsid, reqexpire;
14512	uint16_t udpsize = SEND_BUFFER_SIZE;
14513	bool do_queue_xfrin = false;
14514
14515	REQUIRE(DNS_ZONE_VALID(zone));
14516
14517	UNUSED(task);
14518
14519	ENTER;
14520
14521	LOCK_ZONE(zone);
14522	if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
14523	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
14524	    zone->view->requestmgr == NULL)
14525	{
14526		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14527			cancel = false;
14528		}
14529		goto cleanup;
14530	}
14531
14532again:
14533	INSIST(zone->primariescnt > 0);
14534	INSIST(zone->curprimary < zone->primariescnt);
14535
14536	zone->primaryaddr = zone->primaries[zone->curprimary];
14537
14538	isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr);
14539	/*
14540	 * First, look for a tsig key in the primaries statement, then
14541	 * try for a server key.
14542	 */
14543	if ((zone->primarykeynames != NULL) &&
14544	    (zone->primarykeynames[zone->curprimary] != NULL))
14545	{
14546		dns_view_t *view = dns_zone_getview(zone);
14547		dns_name_t *keyname = zone->primarykeynames[zone->curprimary];
14548		result = dns_view_gettsig(view, keyname, &key);
14549		if (result != ISC_R_SUCCESS) {
14550			char namebuf[DNS_NAME_FORMATSIZE];
14551			dns_name_format(keyname, namebuf, sizeof(namebuf));
14552			dns_zone_log(zone, ISC_LOG_ERROR,
14553				     "unable to find key: %s", namebuf);
14554			goto skip_primary;
14555		}
14556	}
14557	if (key == NULL) {
14558		result = dns_view_getpeertsig(zone->view, &primaryip, &key);
14559		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14560			char addrbuf[ISC_NETADDR_FORMATSIZE];
14561			isc_netaddr_format(&primaryip, addrbuf,
14562					   sizeof(addrbuf));
14563			dns_zone_log(zone, ISC_LOG_ERROR,
14564				     "unable to find TSIG key for %s", addrbuf);
14565			goto skip_primary;
14566		}
14567	}
14568
14569	if ((zone->primarytlsnames != NULL) &&
14570	    (zone->primarytlsnames[zone->curprimary] != NULL))
14571	{
14572		dns_view_t *view = dns_zone_getview(zone);
14573		dns_name_t *tlsname = zone->primarytlsnames[zone->curprimary];
14574		result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
14575					       &transport);
14576		if (result != ISC_R_SUCCESS) {
14577			char namebuf[DNS_NAME_FORMATSIZE];
14578			dns_name_format(tlsname, namebuf, sizeof(namebuf));
14579			dns_zone_log(zone, ISC_LOG_ERROR,
14580				     "unable to find TLS configuration: %s",
14581				     namebuf);
14582			goto skip_primary;
14583		}
14584	}
14585
14586	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? DNS_REQUESTOPT_TCP
14587							 : 0;
14588	reqnsid = zone->view->requestnsid;
14589	reqexpire = zone->requestexpire;
14590	if (zone->view->peers != NULL) {
14591		dns_peer_t *peer = NULL;
14592		bool edns, usetcp;
14593		result = dns_peerlist_peerbyaddr(zone->view->peers, &primaryip,
14594						 &peer);
14595		if (result == ISC_R_SUCCESS) {
14596			result = dns_peer_getsupportedns(peer, &edns);
14597			if (result == ISC_R_SUCCESS && !edns) {
14598				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14599			}
14600			result = dns_peer_gettransfersource(peer,
14601							    &zone->sourceaddr);
14602			if (result == ISC_R_SUCCESS) {
14603				have_xfrsource = true;
14604			}
14605			if (zone->view->resolver != NULL) {
14606				udpsize = dns_resolver_getudpsize(
14607					zone->view->resolver);
14608			}
14609			(void)dns_peer_getudpsize(peer, &udpsize);
14610			(void)dns_peer_getrequestnsid(peer, &reqnsid);
14611			(void)dns_peer_getrequestexpire(peer, &reqexpire);
14612			result = dns_peer_getforcetcp(peer, &usetcp);
14613			if (result == ISC_R_SUCCESS && usetcp) {
14614				options |= DNS_REQUESTOPT_TCP;
14615			}
14616		}
14617	}
14618
14619	switch (isc_sockaddr_pf(&zone->primaryaddr)) {
14620	case PF_INET:
14621		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14622			if (isc_sockaddr_equal(&zone->altxfrsource4,
14623					       &zone->xfrsource4))
14624			{
14625				goto skip_primary;
14626			}
14627			zone->sourceaddr = zone->altxfrsource4;
14628		} else if (!have_xfrsource) {
14629			zone->sourceaddr = zone->xfrsource4;
14630		}
14631		break;
14632	case PF_INET6:
14633		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14634			if (isc_sockaddr_equal(&zone->altxfrsource6,
14635					       &zone->xfrsource6))
14636			{
14637				goto skip_primary;
14638			}
14639			zone->sourceaddr = zone->altxfrsource6;
14640		} else if (!have_xfrsource) {
14641			zone->sourceaddr = zone->xfrsource6;
14642		}
14643		break;
14644	default:
14645		result = ISC_R_NOTIMPLEMENTED;
14646		goto cleanup;
14647	}
14648
14649	/*
14650	 * FIXME(OS): This is a bit hackish, but it enforces the SOA query to go
14651	 * through the XFR channel instead of doing dns_request that doesn't
14652	 * have DoT support yet.
14653	 */
14654	if (transport != NULL) {
14655		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14656		do_queue_xfrin = true;
14657		cancel = false;
14658		result = ISC_R_SUCCESS;
14659		goto cleanup;
14660	}
14661
14662	result = create_query(zone, dns_rdatatype_soa, &zone->origin, &message);
14663	if (result != ISC_R_SUCCESS) {
14664		goto cleanup;
14665	}
14666
14667	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14668		result = add_opt(message, udpsize, reqnsid, reqexpire);
14669		if (result != ISC_R_SUCCESS) {
14670			zone_debuglog(zone, me, 1,
14671				      "unable to add opt record: %s",
14672				      isc_result_totext(result));
14673		}
14674	}
14675
14676	zone_iattach(zone, &dummy);
14677	timeout = 5;
14678	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14679		timeout = 30;
14680	}
14681	result = dns_request_create(
14682		zone->view->requestmgr, message, &zone->sourceaddr,
14683		&zone->primaryaddr, options, key, timeout * 3 + 1, timeout, 2,
14684		zone->task, refresh_callback, zone, &zone->request);
14685	if (result != ISC_R_SUCCESS) {
14686		zone_idetach(&dummy);
14687		zone_debuglog(zone, me, 1, "dns_request_create() failed: %s",
14688			      isc_result_totext(result));
14689		goto skip_primary;
14690	} else {
14691		if (isc_sockaddr_pf(&zone->primaryaddr) == PF_INET) {
14692			inc_stats(zone, dns_zonestatscounter_soaoutv4);
14693		} else {
14694			inc_stats(zone, dns_zonestatscounter_soaoutv6);
14695		}
14696	}
14697	cancel = false;
14698cleanup:
14699	if (transport != NULL) {
14700		dns_transport_detach(&transport);
14701	}
14702	if (key != NULL) {
14703		dns_tsigkey_detach(&key);
14704	}
14705	if (result != ISC_R_SUCCESS) {
14706		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14707	}
14708	if (message != NULL) {
14709		dns_message_detach(&message);
14710	}
14711	if (cancel) {
14712		cancel_refresh(zone);
14713	}
14714	isc_event_free(&event);
14715	UNLOCK_ZONE(zone);
14716	if (do_queue_xfrin) {
14717		queue_xfrin(zone);
14718	}
14719	dns_zone_idetach(&zone);
14720	return;
14721
14722skip_primary:
14723	if (transport != NULL) {
14724		dns_transport_detach(&transport);
14725	}
14726	if (key != NULL) {
14727		dns_tsigkey_detach(&key);
14728	}
14729	if (message != NULL) {
14730		dns_message_detach(&message);
14731	}
14732	/*
14733	 * Skip to next failed / untried primary.
14734	 */
14735	do {
14736		zone->curprimary++;
14737	} while (zone->curprimary < zone->primariescnt &&
14738		 zone->primariesok[zone->curprimary]);
14739	if (zone->curprimary < zone->primariescnt) {
14740		goto again;
14741	}
14742	zone->curprimary = 0;
14743	goto cleanup;
14744}
14745
14746static void
14747ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
14748	const char me[] = "ns_query";
14749	isc_result_t result;
14750	dns_message_t *message = NULL;
14751	isc_netaddr_t primaryip;
14752	dns_tsigkey_t *key = NULL;
14753	dns_dbnode_t *node = NULL;
14754	int timeout;
14755	bool have_xfrsource = false;
14756	bool reqnsid;
14757	uint16_t udpsize = SEND_BUFFER_SIZE;
14758	struct stub_cb_args *cb_args;
14759
14760	REQUIRE(DNS_ZONE_VALID(zone));
14761	REQUIRE(LOCKED_ZONE(zone));
14762	REQUIRE((soardataset != NULL && stub == NULL) ||
14763		(soardataset == NULL && stub != NULL));
14764	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
14765
14766	ENTER;
14767
14768	if (stub == NULL) {
14769		stub = isc_mem_get(zone->mctx, sizeof(*stub));
14770		stub->magic = STUB_MAGIC;
14771		stub->mctx = zone->mctx;
14772		stub->zone = NULL;
14773		stub->db = NULL;
14774		stub->version = NULL;
14775		atomic_init(&stub->pending_requests, 0);
14776
14777		/*
14778		 * Attach so that the zone won't disappear from under us.
14779		 */
14780		zone_iattach(zone, &stub->zone);
14781
14782		/*
14783		 * If a db exists we will update it, otherwise we create a
14784		 * new one and attach it to the zone once we have the NS
14785		 * RRset and glue.
14786		 */
14787		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14788		if (zone->db != NULL) {
14789			dns_db_attach(zone->db, &stub->db);
14790			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14791		} else {
14792			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14793
14794			INSIST(zone->db_argc >= 1);
14795			result = dns_db_create(zone->mctx, zone->db_argv[0],
14796					       &zone->origin, dns_dbtype_stub,
14797					       zone->rdclass, zone->db_argc - 1,
14798					       zone->db_argv + 1, &stub->db);
14799			if (result != ISC_R_SUCCESS) {
14800				dns_zone_log(zone, ISC_LOG_ERROR,
14801					     "refreshing stub: "
14802					     "could not create "
14803					     "database: %s",
14804					     isc_result_totext(result));
14805				goto cleanup;
14806			}
14807			dns_db_settask(stub->db, zone->task);
14808		}
14809
14810		result = dns_db_newversion(stub->db, &stub->version);
14811		if (result != ISC_R_SUCCESS) {
14812			dns_zone_log(zone, ISC_LOG_INFO,
14813				     "refreshing stub: "
14814				     "dns_db_newversion() failed: %s",
14815				     isc_result_totext(result));
14816			goto cleanup;
14817		}
14818
14819		/*
14820		 * Update SOA record.
14821		 */
14822		result = dns_db_findnode(stub->db, &zone->origin, true, &node);
14823		if (result != ISC_R_SUCCESS) {
14824			dns_zone_log(zone, ISC_LOG_INFO,
14825				     "refreshing stub: "
14826				     "dns_db_findnode() failed: %s",
14827				     isc_result_totext(result));
14828			goto cleanup;
14829		}
14830
14831		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
14832					    soardataset, 0, NULL);
14833		dns_db_detachnode(stub->db, &node);
14834		if (result != ISC_R_SUCCESS) {
14835			dns_zone_log(zone, ISC_LOG_INFO,
14836				     "refreshing stub: "
14837				     "dns_db_addrdataset() failed: %s",
14838				     isc_result_totext(result));
14839			goto cleanup;
14840		}
14841	}
14842
14843	/*
14844	 * XXX Optimisation: Create message when zone is setup and reuse.
14845	 */
14846	result = create_query(zone, dns_rdatatype_ns, &zone->origin, &message);
14847	INSIST(result == ISC_R_SUCCESS);
14848
14849	INSIST(zone->primariescnt > 0);
14850	INSIST(zone->curprimary < zone->primariescnt);
14851	zone->primaryaddr = zone->primaries[zone->curprimary];
14852
14853	isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr);
14854	/*
14855	 * First, look for a tsig key in the primaries statement, then
14856	 * try for a server key.
14857	 */
14858	if ((zone->primarykeynames != NULL) &&
14859	    (zone->primarykeynames[zone->curprimary] != NULL))
14860	{
14861		dns_view_t *view = dns_zone_getview(zone);
14862		dns_name_t *keyname = zone->primarykeynames[zone->curprimary];
14863		result = dns_view_gettsig(view, keyname, &key);
14864		if (result != ISC_R_SUCCESS) {
14865			char namebuf[DNS_NAME_FORMATSIZE];
14866			dns_name_format(keyname, namebuf, sizeof(namebuf));
14867			dns_zone_log(zone, ISC_LOG_ERROR,
14868				     "unable to find key: %s", namebuf);
14869		}
14870	}
14871	if (key == NULL) {
14872		(void)dns_view_getpeertsig(zone->view, &primaryip, &key);
14873	}
14874
14875	/* FIXME(OS): Do we need the transport here too? Most probably yes */
14876
14877	reqnsid = zone->view->requestnsid;
14878	if (zone->view->peers != NULL) {
14879		dns_peer_t *peer = NULL;
14880		bool edns;
14881		result = dns_peerlist_peerbyaddr(zone->view->peers, &primaryip,
14882						 &peer);
14883		if (result == ISC_R_SUCCESS) {
14884			result = dns_peer_getsupportedns(peer, &edns);
14885			if (result == ISC_R_SUCCESS && !edns) {
14886				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14887			}
14888			result = dns_peer_gettransfersource(peer,
14889							    &zone->sourceaddr);
14890			if (result == ISC_R_SUCCESS) {
14891				have_xfrsource = true;
14892			}
14893			if (zone->view->resolver != NULL) {
14894				udpsize = dns_resolver_getudpsize(
14895					zone->view->resolver);
14896			}
14897			(void)dns_peer_getudpsize(peer, &udpsize);
14898			(void)dns_peer_getrequestnsid(peer, &reqnsid);
14899		}
14900	}
14901	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14902		result = add_opt(message, udpsize, reqnsid, false);
14903		if (result != ISC_R_SUCCESS) {
14904			zone_debuglog(zone, me, 1,
14905				      "unable to add opt record: %s",
14906				      isc_result_totext(result));
14907		}
14908	}
14909
14910	/*
14911	 * Always use TCP so that we shouldn't truncate in additional section.
14912	 */
14913	switch (isc_sockaddr_pf(&zone->primaryaddr)) {
14914	case PF_INET:
14915		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14916			zone->sourceaddr = zone->altxfrsource4;
14917		} else if (!have_xfrsource) {
14918			zone->sourceaddr = zone->xfrsource4;
14919		}
14920		break;
14921	case PF_INET6:
14922		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14923			zone->sourceaddr = zone->altxfrsource6;
14924		} else if (!have_xfrsource) {
14925			zone->sourceaddr = zone->xfrsource6;
14926		}
14927		break;
14928	default:
14929		result = ISC_R_NOTIMPLEMENTED;
14930		POST(result);
14931		goto cleanup;
14932	}
14933	timeout = 5;
14934	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14935		timeout = 30;
14936	}
14937
14938	/*
14939	 * Save request parameters so we can reuse them later on
14940	 * for resolving missing glue A/AAAA records.
14941	 */
14942	cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
14943	cb_args->stub = stub;
14944	cb_args->tsig_key = key;
14945	cb_args->udpsize = udpsize;
14946	cb_args->timeout = timeout;
14947	cb_args->reqnsid = reqnsid;
14948
14949	result = dns_request_create(
14950		zone->view->requestmgr, message, &zone->sourceaddr,
14951		&zone->primaryaddr, DNS_REQUESTOPT_TCP, key, timeout * 3 + 1,
14952		timeout, 2, zone->task, stub_callback, cb_args, &zone->request);
14953	if (result != ISC_R_SUCCESS) {
14954		zone_debuglog(zone, me, 1, "dns_request_create() failed: %s",
14955			      isc_result_totext(result));
14956		goto cleanup;
14957	}
14958	dns_message_detach(&message);
14959	goto unlock;
14960
14961cleanup:
14962	cancel_refresh(zone);
14963	stub->magic = 0;
14964	if (stub->version != NULL) {
14965		dns_db_closeversion(stub->db, &stub->version, false);
14966	}
14967	if (stub->db != NULL) {
14968		dns_db_detach(&stub->db);
14969	}
14970	if (stub->zone != NULL) {
14971		zone_idetach(&stub->zone);
14972	}
14973	isc_mem_put(stub->mctx, stub, sizeof(*stub));
14974	if (message != NULL) {
14975		dns_message_detach(&message);
14976	}
14977unlock:
14978	if (key != NULL) {
14979		dns_tsigkey_detach(&key);
14980	}
14981	return;
14982}
14983
14984/*
14985 * Shut the zone down.
14986 */
14987static void
14988zone_shutdown(isc_task_t *task, isc_event_t *event) {
14989	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
14990	bool free_needed, linked = false;
14991	dns_zone_t *raw = NULL, *secure = NULL;
14992	dns_view_t *view = NULL, *prev_view = NULL;
14993
14994	UNUSED(task);
14995	REQUIRE(DNS_ZONE_VALID(zone));
14996	INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
14997	INSIST(isc_refcount_current(&zone->erefs) == 0);
14998
14999	zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
15000
15001	/*
15002	 * If we were waiting for xfrin quota, step out of
15003	 * the queue.
15004	 * If there's no zone manager, we can't be waiting for the
15005	 * xfrin quota
15006	 */
15007	if (zone->zmgr != NULL) {
15008		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15009		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
15010			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
15011					statelink);
15012			linked = true;
15013			zone->statelist = NULL;
15014		}
15015		if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
15016			ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
15017					statelink);
15018			zone->statelist = NULL;
15019			zmgr_resume_xfrs(zone->zmgr, false);
15020		}
15021		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15022	}
15023
15024	/*
15025	 * In task context, no locking required.  See zone_xfrdone().
15026	 */
15027	if (zone->xfr != NULL) {
15028		/* The final detach will happen in zone_xfrdone() */
15029		dns_xfrin_shutdown(zone->xfr);
15030	}
15031
15032	/* Safe to release the zone now */
15033	if (zone->zmgr != NULL) {
15034		dns_zonemgr_releasezone(zone->zmgr, zone);
15035	}
15036
15037	LOCK_ZONE(zone);
15038	INSIST(zone != zone->raw);
15039
15040	/*
15041	 * Detach the views early, we don't need them anymore.  However, we need
15042	 * to detach them outside of the zone lock to break the lock loop
15043	 * between view, adb and zone locks.
15044	 */
15045	view = zone->view;
15046	zone->view = NULL;
15047	prev_view = zone->prev_view;
15048	zone->prev_view = NULL;
15049
15050	if (linked) {
15051		isc_refcount_decrement(&zone->irefs);
15052	}
15053	if (zone->request != NULL) {
15054		dns_request_cancel(zone->request);
15055	}
15056
15057	if (zone->readio != NULL) {
15058		zonemgr_cancelio(zone->readio);
15059	}
15060
15061	if (zone->lctx != NULL) {
15062		dns_loadctx_cancel(zone->lctx);
15063	}
15064
15065	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
15066	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15067	{
15068		if (zone->writeio != NULL) {
15069			zonemgr_cancelio(zone->writeio);
15070		}
15071
15072		if (zone->dctx != NULL) {
15073			dns_dumpctx_cancel(zone->dctx);
15074		}
15075	}
15076
15077	checkds_cancel(zone);
15078
15079	notify_cancel(zone);
15080
15081	forward_cancel(zone);
15082
15083	if (zone->timer != NULL) {
15084		isc_timer_destroy(&zone->timer);
15085		isc_refcount_decrement(&zone->irefs);
15086	}
15087
15088	/*
15089	 * We have now canceled everything set the flag to allow exit_check()
15090	 * to succeed.	We must not unlock between setting this flag and
15091	 * calling exit_check().
15092	 */
15093	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
15094	free_needed = exit_check(zone);
15095	/*
15096	 * If a dump is in progress for the secure zone, defer detaching from
15097	 * the raw zone as it may prevent the unsigned serial number from being
15098	 * stored in the raw-format dump of the secure zone.  In this scenario,
15099	 * dump_done() takes care of cleaning up the zone->raw reference.
15100	 */
15101	if (inline_secure(zone) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
15102		raw = zone->raw;
15103		zone->raw = NULL;
15104	}
15105	if (inline_raw(zone)) {
15106		secure = zone->secure;
15107		zone->secure = NULL;
15108	}
15109	UNLOCK_ZONE(zone);
15110
15111	if (view != NULL) {
15112		dns_view_weakdetach(&view);
15113	}
15114	if (prev_view != NULL) {
15115		dns_view_weakdetach(&prev_view);
15116	}
15117
15118	if (raw != NULL) {
15119		dns_zone_detach(&raw);
15120	}
15121	if (secure != NULL) {
15122		dns_zone_idetach(&secure);
15123	}
15124	if (free_needed) {
15125		zone_free(zone);
15126	}
15127}
15128
15129static void
15130zone_timer(isc_task_t *task, isc_event_t *event) {
15131	const char me[] = "zone_timer";
15132	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
15133
15134	UNUSED(task);
15135	REQUIRE(DNS_ZONE_VALID(zone));
15136
15137	ENTER;
15138
15139	zone_maintenance(zone);
15140
15141	isc_event_free(&event);
15142}
15143
15144static void
15145zone_settimer(dns_zone_t *zone, isc_time_t *now) {
15146	const char me[] = "zone_settimer";
15147	isc_time_t next;
15148	isc_result_t result;
15149
15150	REQUIRE(DNS_ZONE_VALID(zone));
15151	REQUIRE(LOCKED_ZONE(zone));
15152	ENTER;
15153
15154	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15155		return;
15156	}
15157
15158	isc_time_settoepoch(&next);
15159
15160	switch (zone->type) {
15161	case dns_zone_redirect:
15162		if (zone->primaries != NULL) {
15163			goto treat_as_secondary;
15164		}
15165		FALLTHROUGH;
15166	case dns_zone_primary:
15167		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15168		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15169		{
15170			next = zone->notifytime;
15171		}
15172		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15173		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15174		{
15175			INSIST(!isc_time_isepoch(&zone->dumptime));
15176			if (isc_time_isepoch(&next) ||
15177			    isc_time_compare(&zone->dumptime, &next) < 0)
15178			{
15179				next = zone->dumptime;
15180			}
15181		}
15182		if (zone->type == dns_zone_redirect) {
15183			break;
15184		}
15185		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
15186		    !isc_time_isepoch(&zone->refreshkeytime))
15187		{
15188			if (isc_time_isepoch(&next) ||
15189			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
15190			{
15191				next = zone->refreshkeytime;
15192			}
15193		}
15194		if (!isc_time_isepoch(&zone->resigntime)) {
15195			if (isc_time_isepoch(&next) ||
15196			    isc_time_compare(&zone->resigntime, &next) < 0)
15197			{
15198				next = zone->resigntime;
15199			}
15200		}
15201		if (!isc_time_isepoch(&zone->keywarntime)) {
15202			if (isc_time_isepoch(&next) ||
15203			    isc_time_compare(&zone->keywarntime, &next) < 0)
15204			{
15205				next = zone->keywarntime;
15206			}
15207		}
15208		if (!isc_time_isepoch(&zone->signingtime)) {
15209			if (isc_time_isepoch(&next) ||
15210			    isc_time_compare(&zone->signingtime, &next) < 0)
15211			{
15212				next = zone->signingtime;
15213			}
15214		}
15215		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
15216			if (isc_time_isepoch(&next) ||
15217			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
15218			{
15219				next = zone->nsec3chaintime;
15220			}
15221		}
15222		break;
15223
15224	case dns_zone_secondary:
15225	case dns_zone_mirror:
15226	treat_as_secondary:
15227		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15228		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15229		{
15230			next = zone->notifytime;
15231		}
15232		FALLTHROUGH;
15233	case dns_zone_stub:
15234		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
15235		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOPRIMARIES) &&
15236		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
15237		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
15238		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
15239		    !isc_time_isepoch(&zone->refreshtime) &&
15240		    (isc_time_isepoch(&next) ||
15241		     isc_time_compare(&zone->refreshtime, &next) < 0))
15242		{
15243			next = zone->refreshtime;
15244		}
15245		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15246		    !isc_time_isepoch(&zone->expiretime))
15247		{
15248			if (isc_time_isepoch(&next) ||
15249			    isc_time_compare(&zone->expiretime, &next) < 0)
15250			{
15251				next = zone->expiretime;
15252			}
15253		}
15254		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15255		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15256		{
15257			INSIST(!isc_time_isepoch(&zone->dumptime));
15258			if (isc_time_isepoch(&next) ||
15259			    isc_time_compare(&zone->dumptime, &next) < 0)
15260			{
15261				next = zone->dumptime;
15262			}
15263		}
15264		break;
15265
15266	case dns_zone_key:
15267		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15268		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15269		{
15270			INSIST(!isc_time_isepoch(&zone->dumptime));
15271			if (isc_time_isepoch(&next) ||
15272			    isc_time_compare(&zone->dumptime, &next) < 0)
15273			{
15274				next = zone->dumptime;
15275			}
15276		}
15277		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
15278			if (isc_time_isepoch(&next) ||
15279			    (!isc_time_isepoch(&zone->refreshkeytime) &&
15280			     isc_time_compare(&zone->refreshkeytime, &next) <
15281				     0))
15282			{
15283				next = zone->refreshkeytime;
15284			}
15285		}
15286		break;
15287
15288	default:
15289		break;
15290	}
15291
15292	if (isc_time_isepoch(&next)) {
15293		zone_debuglog(zone, me, 10, "settimer inactive");
15294		result = isc_timer_reset(zone->timer, isc_timertype_inactive,
15295					 NULL, NULL, true);
15296		if (result != ISC_R_SUCCESS) {
15297			dns_zone_log(zone, ISC_LOG_ERROR,
15298				     "could not deactivate zone timer: %s",
15299				     isc_result_totext(result));
15300		}
15301	} else {
15302		if (isc_time_compare(&next, now) <= 0) {
15303			next = *now;
15304		}
15305		result = isc_timer_reset(zone->timer, isc_timertype_once, &next,
15306					 NULL, true);
15307		if (result != ISC_R_SUCCESS) {
15308			dns_zone_log(zone, ISC_LOG_ERROR,
15309				     "could not reset zone timer: %s",
15310				     isc_result_totext(result));
15311		}
15312	}
15313}
15314
15315static void
15316cancel_refresh(dns_zone_t *zone) {
15317	const char me[] = "cancel_refresh";
15318	isc_time_t now;
15319
15320	/*
15321	 * 'zone' locked by caller.
15322	 */
15323
15324	REQUIRE(DNS_ZONE_VALID(zone));
15325	REQUIRE(LOCKED_ZONE(zone));
15326
15327	ENTER;
15328
15329	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
15330	TIME_NOW(&now);
15331	zone_settimer(zone, &now);
15332}
15333
15334static isc_result_t
15335notify_createmessage(dns_zone_t *zone, unsigned int flags,
15336		     dns_message_t **messagep) {
15337	dns_db_t *zonedb = NULL;
15338	dns_dbnode_t *node = NULL;
15339	dns_dbversion_t *version = NULL;
15340	dns_message_t *message = NULL;
15341	dns_rdataset_t rdataset;
15342	dns_rdata_t rdata = DNS_RDATA_INIT;
15343
15344	dns_name_t *tempname = NULL;
15345	dns_rdata_t *temprdata = NULL;
15346	dns_rdatalist_t *temprdatalist = NULL;
15347	dns_rdataset_t *temprdataset = NULL;
15348
15349	isc_result_t result;
15350	isc_region_t r;
15351	isc_buffer_t *b = NULL;
15352
15353	REQUIRE(DNS_ZONE_VALID(zone));
15354	REQUIRE(messagep != NULL && *messagep == NULL);
15355
15356	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
15357
15358	message->opcode = dns_opcode_notify;
15359	message->flags |= DNS_MESSAGEFLAG_AA;
15360	message->rdclass = zone->rdclass;
15361
15362	result = dns_message_gettempname(message, &tempname);
15363	if (result != ISC_R_SUCCESS) {
15364		goto cleanup;
15365	}
15366
15367	result = dns_message_gettemprdataset(message, &temprdataset);
15368	if (result != ISC_R_SUCCESS) {
15369		goto cleanup;
15370	}
15371
15372	/*
15373	 * Make question.
15374	 */
15375	dns_name_clone(&zone->origin, tempname);
15376	dns_rdataset_makequestion(temprdataset, zone->rdclass,
15377				  dns_rdatatype_soa);
15378	ISC_LIST_APPEND(tempname->list, temprdataset, link);
15379	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
15380	tempname = NULL;
15381	temprdataset = NULL;
15382
15383	if ((flags & DNS_NOTIFY_NOSOA) != 0) {
15384		goto done;
15385	}
15386
15387	result = dns_message_gettempname(message, &tempname);
15388	if (result != ISC_R_SUCCESS) {
15389		goto soa_cleanup;
15390	}
15391	result = dns_message_gettemprdata(message, &temprdata);
15392	if (result != ISC_R_SUCCESS) {
15393		goto soa_cleanup;
15394	}
15395	result = dns_message_gettemprdataset(message, &temprdataset);
15396	if (result != ISC_R_SUCCESS) {
15397		goto soa_cleanup;
15398	}
15399	result = dns_message_gettemprdatalist(message, &temprdatalist);
15400	if (result != ISC_R_SUCCESS) {
15401		goto soa_cleanup;
15402	}
15403
15404	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15405	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
15406	dns_db_attach(zone->db, &zonedb);
15407	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15408
15409	dns_name_clone(&zone->origin, tempname);
15410	dns_db_currentversion(zonedb, &version);
15411	result = dns_db_findnode(zonedb, tempname, false, &node);
15412	if (result != ISC_R_SUCCESS) {
15413		goto soa_cleanup;
15414	}
15415
15416	dns_rdataset_init(&rdataset);
15417	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
15418				     dns_rdatatype_none, 0, &rdataset, NULL);
15419	if (result != ISC_R_SUCCESS) {
15420		goto soa_cleanup;
15421	}
15422	result = dns_rdataset_first(&rdataset);
15423	if (result != ISC_R_SUCCESS) {
15424		goto soa_cleanup;
15425	}
15426	dns_rdataset_current(&rdataset, &rdata);
15427	dns_rdata_toregion(&rdata, &r);
15428	isc_buffer_allocate(zone->mctx, &b, r.length);
15429	isc_buffer_putmem(b, r.base, r.length);
15430	isc_buffer_usedregion(b, &r);
15431	dns_rdata_init(temprdata);
15432	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
15433	dns_message_takebuffer(message, &b);
15434	result = dns_rdataset_next(&rdataset);
15435	dns_rdataset_disassociate(&rdataset);
15436	if (result != ISC_R_NOMORE) {
15437		goto soa_cleanup;
15438	}
15439	temprdatalist->rdclass = rdata.rdclass;
15440	temprdatalist->type = rdata.type;
15441	temprdatalist->ttl = rdataset.ttl;
15442	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
15443
15444	result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
15445	if (result != ISC_R_SUCCESS) {
15446		goto soa_cleanup;
15447	}
15448
15449	ISC_LIST_APPEND(tempname->list, temprdataset, link);
15450	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
15451	temprdatalist = NULL;
15452	temprdataset = NULL;
15453	temprdata = NULL;
15454	tempname = NULL;
15455
15456soa_cleanup:
15457	if (node != NULL) {
15458		dns_db_detachnode(zonedb, &node);
15459	}
15460	if (version != NULL) {
15461		dns_db_closeversion(zonedb, &version, false);
15462	}
15463	if (zonedb != NULL) {
15464		dns_db_detach(&zonedb);
15465	}
15466	if (tempname != NULL) {
15467		dns_message_puttempname(message, &tempname);
15468	}
15469	if (temprdata != NULL) {
15470		dns_message_puttemprdata(message, &temprdata);
15471	}
15472	if (temprdataset != NULL) {
15473		dns_message_puttemprdataset(message, &temprdataset);
15474	}
15475	if (temprdatalist != NULL) {
15476		dns_message_puttemprdatalist(message, &temprdatalist);
15477	}
15478
15479done:
15480	*messagep = message;
15481	return (ISC_R_SUCCESS);
15482
15483cleanup:
15484	if (tempname != NULL) {
15485		dns_message_puttempname(message, &tempname);
15486	}
15487	if (temprdataset != NULL) {
15488		dns_message_puttemprdataset(message, &temprdataset);
15489	}
15490	dns_message_detach(&message);
15491	return (result);
15492}
15493
15494isc_result_t
15495dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
15496		       isc_sockaddr_t *to, dns_message_t *msg) {
15497	unsigned int i;
15498	dns_rdata_soa_t soa;
15499	dns_rdataset_t *rdataset = NULL;
15500	dns_rdata_t rdata = DNS_RDATA_INIT;
15501	isc_result_t result;
15502	char fromtext[ISC_SOCKADDR_FORMATSIZE];
15503	int match = 0;
15504	isc_netaddr_t netaddr;
15505	uint32_t serial = 0;
15506	bool have_serial = false;
15507	dns_tsigkey_t *tsigkey;
15508	const dns_name_t *tsig;
15509
15510	REQUIRE(DNS_ZONE_VALID(zone));
15511
15512	/*
15513	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
15514	 * ROLLOVER.
15515	 *
15516	 * SOA:	RFC1996
15517	 * Check that 'from' is a valid notify source, (zone->primaries).
15518	 *	Return DNS_R_REFUSED if not.
15519	 *
15520	 * If the notify message contains a serial number check it
15521	 * against the zones serial and return if <= current serial
15522	 *
15523	 * If a refresh check is progress, if so just record the
15524	 * fact we received a NOTIFY and from where and return.
15525	 * We will perform a new refresh check when the current one
15526	 * completes. Return ISC_R_SUCCESS.
15527	 *
15528	 * Otherwise initiate a refresh check using 'from' as the
15529	 * first address to check.  Return ISC_R_SUCCESS.
15530	 */
15531
15532	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
15533
15534	/*
15535	 * Notify messages are processed by the raw zone.
15536	 */
15537	LOCK_ZONE(zone);
15538	INSIST(zone != zone->raw);
15539	if (inline_secure(zone)) {
15540		result = dns_zone_notifyreceive(zone->raw, from, to, msg);
15541		UNLOCK_ZONE(zone);
15542		return (result);
15543	}
15544	/*
15545	 *  We only handle NOTIFY (SOA) at the present.
15546	 */
15547	if (isc_sockaddr_pf(from) == PF_INET) {
15548		inc_stats(zone, dns_zonestatscounter_notifyinv4);
15549	} else {
15550		inc_stats(zone, dns_zonestatscounter_notifyinv6);
15551	}
15552	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
15553	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
15554				 dns_rdatatype_soa, dns_rdatatype_none, NULL,
15555				 NULL) != ISC_R_SUCCESS)
15556	{
15557		UNLOCK_ZONE(zone);
15558		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
15559			dns_zone_log(zone, ISC_LOG_NOTICE,
15560				     "NOTIFY with no "
15561				     "question section from: %s",
15562				     fromtext);
15563			return (DNS_R_FORMERR);
15564		}
15565		dns_zone_log(zone, ISC_LOG_NOTICE,
15566			     "NOTIFY zone does not match");
15567		return (DNS_R_NOTIMP);
15568	}
15569
15570	/*
15571	 * If we are a primary zone just succeed.
15572	 */
15573	if (zone->type == dns_zone_primary) {
15574		UNLOCK_ZONE(zone);
15575		return (ISC_R_SUCCESS);
15576	}
15577
15578	isc_netaddr_fromsockaddr(&netaddr, from);
15579	for (i = 0; i < zone->primariescnt; i++) {
15580		if (isc_sockaddr_eqaddr(from, &zone->primaries[i])) {
15581			break;
15582		}
15583		if (zone->view->aclenv->match_mapped &&
15584		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
15585		    isc_sockaddr_pf(&zone->primaries[i]) == AF_INET)
15586		{
15587			isc_netaddr_t na1, na2;
15588			isc_netaddr_fromv4mapped(&na1, &netaddr);
15589			isc_netaddr_fromsockaddr(&na2, &zone->primaries[i]);
15590			if (isc_netaddr_equal(&na1, &na2)) {
15591				break;
15592			}
15593		}
15594	}
15595
15596	/*
15597	 * Accept notify requests from non primaries if they are on
15598	 * 'zone->notify_acl'.
15599	 */
15600	tsigkey = dns_message_gettsigkey(msg);
15601	tsig = dns_tsigkey_identity(tsigkey);
15602	if (i >= zone->primariescnt && zone->notify_acl != NULL &&
15603	    (dns_acl_match(&netaddr, tsig, zone->notify_acl, zone->view->aclenv,
15604			   &match, NULL) == ISC_R_SUCCESS) &&
15605	    match > 0)
15606	{
15607		/* Accept notify. */
15608	} else if (i >= zone->primariescnt) {
15609		UNLOCK_ZONE(zone);
15610		dns_zone_log(zone, ISC_LOG_INFO,
15611			     "refused notify from non-primary: %s", fromtext);
15612		inc_stats(zone, dns_zonestatscounter_notifyrej);
15613		return (DNS_R_REFUSED);
15614	}
15615
15616	/*
15617	 * If the zone is loaded and there are answers check the serial
15618	 * to see if we need to do a refresh.  Do not worry about this
15619	 * check if we are a dialup zone as we use the notify request
15620	 * to trigger a refresh check.
15621	 */
15622	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
15623	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15624	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH))
15625	{
15626		result = dns_message_findname(
15627			msg, DNS_SECTION_ANSWER, &zone->origin,
15628			dns_rdatatype_soa, dns_rdatatype_none, NULL, &rdataset);
15629		if (result == ISC_R_SUCCESS) {
15630			result = dns_rdataset_first(rdataset);
15631		}
15632		if (result == ISC_R_SUCCESS) {
15633			uint32_t oldserial;
15634			unsigned int soacount;
15635
15636			dns_rdataset_current(rdataset, &rdata);
15637			result = dns_rdata_tostruct(&rdata, &soa, NULL);
15638			RUNTIME_CHECK(result == ISC_R_SUCCESS);
15639			serial = soa.serial;
15640			have_serial = true;
15641			/*
15642			 * The following should safely be performed without DB
15643			 * lock and succeed in this context.
15644			 */
15645			result = zone_get_from_db(zone, zone->db, NULL,
15646						  &soacount, NULL, &oldserial,
15647						  NULL, NULL, NULL, NULL, NULL);
15648			RUNTIME_CHECK(result == ISC_R_SUCCESS);
15649			RUNTIME_CHECK(soacount > 0U);
15650			if (isc_serial_le(serial, oldserial)) {
15651				dns_zone_log(zone, ISC_LOG_INFO,
15652					     "notify from %s: "
15653					     "zone is up to date",
15654					     fromtext);
15655				UNLOCK_ZONE(zone);
15656				return (ISC_R_SUCCESS);
15657			}
15658		}
15659	}
15660
15661	/*
15662	 * If we got this far and there was a refresh in progress just
15663	 * let it complete.  Record where we got the notify from so we
15664	 * can perform a refresh check when the current one completes
15665	 */
15666	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
15667		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15668		zone->notifyfrom = *from;
15669		UNLOCK_ZONE(zone);
15670		if (have_serial) {
15671			dns_zone_log(zone, ISC_LOG_INFO,
15672				     "notify from %s: serial %u: refresh in "
15673				     "progress, refresh check queued",
15674				     fromtext, serial);
15675		} else {
15676			dns_zone_log(zone, ISC_LOG_INFO,
15677				     "notify from %s: refresh in progress, "
15678				     "refresh check queued",
15679				     fromtext);
15680		}
15681		return (ISC_R_SUCCESS);
15682	}
15683	if (have_serial) {
15684		dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
15685			     fromtext, serial);
15686	} else {
15687		dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
15688			     fromtext);
15689	}
15690	zone->notifyfrom = *from;
15691	UNLOCK_ZONE(zone);
15692
15693	if (to != NULL) {
15694		dns_zonemgr_unreachabledel(zone->zmgr, from, to);
15695	}
15696	dns_zone_refresh(zone);
15697	return (ISC_R_SUCCESS);
15698}
15699
15700void
15701dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
15702	REQUIRE(DNS_ZONE_VALID(zone));
15703
15704	LOCK_ZONE(zone);
15705	if (zone->notify_acl != NULL) {
15706		dns_acl_detach(&zone->notify_acl);
15707	}
15708	dns_acl_attach(acl, &zone->notify_acl);
15709	UNLOCK_ZONE(zone);
15710}
15711
15712void
15713dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
15714	REQUIRE(DNS_ZONE_VALID(zone));
15715
15716	LOCK_ZONE(zone);
15717	if (zone->query_acl != NULL) {
15718		dns_acl_detach(&zone->query_acl);
15719	}
15720	dns_acl_attach(acl, &zone->query_acl);
15721	UNLOCK_ZONE(zone);
15722}
15723
15724void
15725dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
15726	REQUIRE(DNS_ZONE_VALID(zone));
15727
15728	LOCK_ZONE(zone);
15729	if (zone->queryon_acl != NULL) {
15730		dns_acl_detach(&zone->queryon_acl);
15731	}
15732	dns_acl_attach(acl, &zone->queryon_acl);
15733	UNLOCK_ZONE(zone);
15734}
15735
15736void
15737dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
15738	REQUIRE(DNS_ZONE_VALID(zone));
15739
15740	LOCK_ZONE(zone);
15741	if (zone->update_acl != NULL) {
15742		dns_acl_detach(&zone->update_acl);
15743	}
15744	dns_acl_attach(acl, &zone->update_acl);
15745	UNLOCK_ZONE(zone);
15746}
15747
15748void
15749dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
15750	REQUIRE(DNS_ZONE_VALID(zone));
15751
15752	LOCK_ZONE(zone);
15753	if (zone->forward_acl != NULL) {
15754		dns_acl_detach(&zone->forward_acl);
15755	}
15756	dns_acl_attach(acl, &zone->forward_acl);
15757	UNLOCK_ZONE(zone);
15758}
15759
15760void
15761dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
15762	REQUIRE(DNS_ZONE_VALID(zone));
15763
15764	LOCK_ZONE(zone);
15765	if (zone->xfr_acl != NULL) {
15766		dns_acl_detach(&zone->xfr_acl);
15767	}
15768	dns_acl_attach(acl, &zone->xfr_acl);
15769	UNLOCK_ZONE(zone);
15770}
15771
15772dns_acl_t *
15773dns_zone_getnotifyacl(dns_zone_t *zone) {
15774	REQUIRE(DNS_ZONE_VALID(zone));
15775
15776	return (zone->notify_acl);
15777}
15778
15779dns_acl_t *
15780dns_zone_getqueryacl(dns_zone_t *zone) {
15781	REQUIRE(DNS_ZONE_VALID(zone));
15782
15783	return (zone->query_acl);
15784}
15785
15786dns_acl_t *
15787dns_zone_getqueryonacl(dns_zone_t *zone) {
15788	REQUIRE(DNS_ZONE_VALID(zone));
15789
15790	return (zone->queryon_acl);
15791}
15792
15793dns_acl_t *
15794dns_zone_getupdateacl(dns_zone_t *zone) {
15795	REQUIRE(DNS_ZONE_VALID(zone));
15796
15797	return (zone->update_acl);
15798}
15799
15800dns_acl_t *
15801dns_zone_getforwardacl(dns_zone_t *zone) {
15802	REQUIRE(DNS_ZONE_VALID(zone));
15803
15804	return (zone->forward_acl);
15805}
15806
15807dns_acl_t *
15808dns_zone_getxfracl(dns_zone_t *zone) {
15809	REQUIRE(DNS_ZONE_VALID(zone));
15810
15811	return (zone->xfr_acl);
15812}
15813
15814void
15815dns_zone_clearupdateacl(dns_zone_t *zone) {
15816	REQUIRE(DNS_ZONE_VALID(zone));
15817
15818	LOCK_ZONE(zone);
15819	if (zone->update_acl != NULL) {
15820		dns_acl_detach(&zone->update_acl);
15821	}
15822	UNLOCK_ZONE(zone);
15823}
15824
15825void
15826dns_zone_clearforwardacl(dns_zone_t *zone) {
15827	REQUIRE(DNS_ZONE_VALID(zone));
15828
15829	LOCK_ZONE(zone);
15830	if (zone->forward_acl != NULL) {
15831		dns_acl_detach(&zone->forward_acl);
15832	}
15833	UNLOCK_ZONE(zone);
15834}
15835
15836void
15837dns_zone_clearnotifyacl(dns_zone_t *zone) {
15838	REQUIRE(DNS_ZONE_VALID(zone));
15839
15840	LOCK_ZONE(zone);
15841	if (zone->notify_acl != NULL) {
15842		dns_acl_detach(&zone->notify_acl);
15843	}
15844	UNLOCK_ZONE(zone);
15845}
15846
15847void
15848dns_zone_clearqueryacl(dns_zone_t *zone) {
15849	REQUIRE(DNS_ZONE_VALID(zone));
15850
15851	LOCK_ZONE(zone);
15852	if (zone->query_acl != NULL) {
15853		dns_acl_detach(&zone->query_acl);
15854	}
15855	UNLOCK_ZONE(zone);
15856}
15857
15858void
15859dns_zone_clearqueryonacl(dns_zone_t *zone) {
15860	REQUIRE(DNS_ZONE_VALID(zone));
15861
15862	LOCK_ZONE(zone);
15863	if (zone->queryon_acl != NULL) {
15864		dns_acl_detach(&zone->queryon_acl);
15865	}
15866	UNLOCK_ZONE(zone);
15867}
15868
15869void
15870dns_zone_clearxfracl(dns_zone_t *zone) {
15871	REQUIRE(DNS_ZONE_VALID(zone));
15872
15873	LOCK_ZONE(zone);
15874	if (zone->xfr_acl != NULL) {
15875		dns_acl_detach(&zone->xfr_acl);
15876	}
15877	UNLOCK_ZONE(zone);
15878}
15879
15880bool
15881dns_zone_getupdatedisabled(dns_zone_t *zone) {
15882	REQUIRE(DNS_ZONE_VALID(zone));
15883	return (zone->update_disabled);
15884}
15885
15886void
15887dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
15888	REQUIRE(DNS_ZONE_VALID(zone));
15889	zone->update_disabled = state;
15890}
15891
15892bool
15893dns_zone_getzeronosoattl(dns_zone_t *zone) {
15894	REQUIRE(DNS_ZONE_VALID(zone));
15895	return (zone->zero_no_soa_ttl);
15896}
15897
15898void
15899dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
15900	REQUIRE(DNS_ZONE_VALID(zone));
15901	zone->zero_no_soa_ttl = state;
15902}
15903
15904void
15905dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
15906	REQUIRE(DNS_ZONE_VALID(zone));
15907
15908	zone->check_names = severity;
15909}
15910
15911dns_severity_t
15912dns_zone_getchecknames(dns_zone_t *zone) {
15913	REQUIRE(DNS_ZONE_VALID(zone));
15914
15915	return (zone->check_names);
15916}
15917
15918void
15919dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
15920	REQUIRE(DNS_ZONE_VALID(zone));
15921
15922	zone->journalsize = size;
15923}
15924
15925int32_t
15926dns_zone_getjournalsize(dns_zone_t *zone) {
15927	REQUIRE(DNS_ZONE_VALID(zone));
15928
15929	return (zone->journalsize);
15930}
15931
15932static void
15933zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
15934	isc_result_t result = ISC_R_FAILURE;
15935	isc_buffer_t buffer;
15936
15937	REQUIRE(buf != NULL);
15938	REQUIRE(length > 1U);
15939
15940	/*
15941	 * Leave space for terminating '\0'.
15942	 */
15943	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15944	if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
15945		if (dns_name_dynamic(&zone->origin)) {
15946			result = dns_name_totext(&zone->origin, true, &buffer);
15947		}
15948		if (result != ISC_R_SUCCESS &&
15949		    isc_buffer_availablelength(&buffer) >=
15950			    (sizeof("<UNKNOWN>") - 1))
15951		{
15952			isc_buffer_putstr(&buffer, "<UNKNOWN>");
15953		}
15954
15955		if (isc_buffer_availablelength(&buffer) > 0) {
15956			isc_buffer_putstr(&buffer, "/");
15957		}
15958		(void)dns_rdataclass_totext(zone->rdclass, &buffer);
15959	}
15960
15961	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
15962	    strcmp(zone->view->name, "_default") != 0 &&
15963	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
15964	{
15965		isc_buffer_putstr(&buffer, "/");
15966		isc_buffer_putstr(&buffer, zone->view->name);
15967	}
15968	if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) {
15969		isc_buffer_putstr(&buffer, " (signed)");
15970	}
15971	if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) {
15972		isc_buffer_putstr(&buffer, " (unsigned)");
15973	}
15974
15975	buf[isc_buffer_usedlength(&buffer)] = '\0';
15976}
15977
15978static void
15979zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
15980	isc_result_t result = ISC_R_FAILURE;
15981	isc_buffer_t buffer;
15982
15983	REQUIRE(buf != NULL);
15984	REQUIRE(length > 1U);
15985
15986	/*
15987	 * Leave space for terminating '\0'.
15988	 */
15989	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15990	if (dns_name_dynamic(&zone->origin)) {
15991		result = dns_name_totext(&zone->origin, true, &buffer);
15992	}
15993	if (result != ISC_R_SUCCESS &&
15994	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
15995	{
15996		isc_buffer_putstr(&buffer, "<UNKNOWN>");
15997	}
15998
15999	buf[isc_buffer_usedlength(&buffer)] = '\0';
16000}
16001
16002static void
16003zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
16004	isc_buffer_t buffer;
16005
16006	REQUIRE(buf != NULL);
16007	REQUIRE(length > 1U);
16008
16009	/*
16010	 * Leave space for terminating '\0'.
16011	 */
16012	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
16013	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
16014
16015	buf[isc_buffer_usedlength(&buffer)] = '\0';
16016}
16017
16018static void
16019zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
16020	isc_buffer_t buffer;
16021
16022	REQUIRE(buf != NULL);
16023	REQUIRE(length > 1U);
16024
16025	/*
16026	 * Leave space for terminating '\0'.
16027	 */
16028	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
16029
16030	if (zone->view == NULL) {
16031		isc_buffer_putstr(&buffer, "_none");
16032	} else if (strlen(zone->view->name) <
16033		   isc_buffer_availablelength(&buffer))
16034	{
16035		isc_buffer_putstr(&buffer, zone->view->name);
16036	} else {
16037		isc_buffer_putstr(&buffer, "_toolong");
16038	}
16039
16040	buf[isc_buffer_usedlength(&buffer)] = '\0';
16041}
16042
16043void
16044dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
16045	REQUIRE(DNS_ZONE_VALID(zone));
16046	REQUIRE(buf != NULL);
16047
16048	LOCK_ZONE(zone);
16049	zone_namerd_tostr(zone, buf, length);
16050	UNLOCK_ZONE(zone);
16051}
16052
16053void
16054dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
16055	REQUIRE(DNS_ZONE_VALID(zone));
16056	REQUIRE(buf != NULL);
16057	zone_name_tostr(zone, buf, length);
16058}
16059
16060void
16061dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
16062	      const char *prefix, const char *fmt, va_list ap) {
16063	char message[4096];
16064	const char *zstr;
16065
16066	REQUIRE(DNS_ZONE_VALID(zone));
16067
16068	if (!isc_log_wouldlog(dns_lctx, level)) {
16069		return;
16070	}
16071
16072	vsnprintf(message, sizeof(message), fmt, ap);
16073
16074	switch (zone->type) {
16075	case dns_zone_key:
16076		zstr = "managed-keys-zone";
16077		break;
16078	case dns_zone_redirect:
16079		zstr = "redirect-zone";
16080		break;
16081	default:
16082		zstr = "zone ";
16083	}
16084
16085	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
16086		      "%s%s%s%s: %s", (prefix != NULL ? prefix : ""),
16087		      (prefix != NULL ? ": " : ""), zstr, zone->strnamerd,
16088		      message);
16089}
16090
16091static void
16092notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16093	va_list ap;
16094
16095	va_start(ap, fmt);
16096	dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
16097	va_end(ap);
16098}
16099
16100void
16101dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
16102	      const char *fmt, ...) {
16103	va_list ap;
16104
16105	va_start(ap, fmt);
16106	dns_zone_logv(zone, category, level, NULL, fmt, ap);
16107	va_end(ap);
16108}
16109
16110void
16111dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16112	va_list ap;
16113
16114	va_start(ap, fmt);
16115	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
16116	va_end(ap);
16117}
16118
16119static void
16120zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, const char *fmt,
16121	      ...) {
16122	int level = ISC_LOG_DEBUG(debuglevel);
16123	va_list ap;
16124
16125	va_start(ap, fmt);
16126	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
16127	va_end(ap);
16128}
16129
16130static void
16131dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16132	va_list ap;
16133
16134	va_start(ap, fmt);
16135	dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
16136	va_end(ap);
16137}
16138
16139static int
16140message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
16141	isc_result_t result;
16142	dns_name_t *name;
16143	dns_rdataset_t *curr;
16144	int count = 0;
16145
16146	result = dns_message_firstname(msg, section);
16147	while (result == ISC_R_SUCCESS) {
16148		name = NULL;
16149		dns_message_currentname(msg, section, &name);
16150
16151		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
16152		     curr = ISC_LIST_PREV(curr, link))
16153		{
16154			if (curr->type == type) {
16155				count++;
16156			}
16157		}
16158		result = dns_message_nextname(msg, section);
16159	}
16160
16161	return (count);
16162}
16163
16164void
16165dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
16166	REQUIRE(DNS_ZONE_VALID(zone));
16167
16168	zone->maxxfrin = maxxfrin;
16169}
16170
16171uint32_t
16172dns_zone_getmaxxfrin(dns_zone_t *zone) {
16173	REQUIRE(DNS_ZONE_VALID(zone));
16174
16175	return (zone->maxxfrin);
16176}
16177
16178void
16179dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
16180	REQUIRE(DNS_ZONE_VALID(zone));
16181	zone->maxxfrout = maxxfrout;
16182}
16183
16184uint32_t
16185dns_zone_getmaxxfrout(dns_zone_t *zone) {
16186	REQUIRE(DNS_ZONE_VALID(zone));
16187
16188	return (zone->maxxfrout);
16189}
16190
16191dns_zonetype_t
16192dns_zone_gettype(dns_zone_t *zone) {
16193	REQUIRE(DNS_ZONE_VALID(zone));
16194
16195	return (zone->type);
16196}
16197
16198const char *
16199dns_zonetype_name(dns_zonetype_t type) {
16200	switch (type) {
16201	case dns_zone_none:
16202		return ("none");
16203	case dns_zone_primary:
16204		return ("primary");
16205	case dns_zone_secondary:
16206		return ("secondary");
16207	case dns_zone_mirror:
16208		return ("mirror");
16209	case dns_zone_stub:
16210		return ("stub");
16211	case dns_zone_staticstub:
16212		return ("static-stub");
16213	case dns_zone_key:
16214		return ("key");
16215	case dns_zone_dlz:
16216		return ("dlz");
16217	case dns_zone_redirect:
16218		return ("redirect");
16219	default:
16220		return ("unknown");
16221	}
16222}
16223
16224dns_zonetype_t
16225dns_zone_getredirecttype(dns_zone_t *zone) {
16226	REQUIRE(DNS_ZONE_VALID(zone));
16227	REQUIRE(zone->type == dns_zone_redirect);
16228
16229	return (zone->primaries == NULL ? dns_zone_primary
16230					: dns_zone_secondary);
16231}
16232
16233dns_name_t *
16234dns_zone_getorigin(dns_zone_t *zone) {
16235	REQUIRE(DNS_ZONE_VALID(zone));
16236
16237	return (&zone->origin);
16238}
16239
16240void
16241dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
16242	REQUIRE(DNS_ZONE_VALID(zone));
16243
16244	LOCK_ZONE(zone);
16245	if (zone->task != NULL) {
16246		isc_task_detach(&zone->task);
16247	}
16248	isc_task_attach(task, &zone->task);
16249	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16250	if (zone->db != NULL) {
16251		dns_db_settask(zone->db, zone->task);
16252	}
16253	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16254	UNLOCK_ZONE(zone);
16255}
16256
16257void
16258dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
16259	REQUIRE(DNS_ZONE_VALID(zone));
16260	isc_task_attach(zone->task, target);
16261}
16262
16263void
16264dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
16265	REQUIRE(DNS_ZONE_VALID(zone));
16266
16267	if (idlein == 0) {
16268		idlein = DNS_DEFAULT_IDLEIN;
16269	}
16270	zone->idlein = idlein;
16271}
16272
16273uint32_t
16274dns_zone_getidlein(dns_zone_t *zone) {
16275	REQUIRE(DNS_ZONE_VALID(zone));
16276
16277	return (zone->idlein);
16278}
16279
16280void
16281dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
16282	REQUIRE(DNS_ZONE_VALID(zone));
16283
16284	zone->idleout = idleout;
16285}
16286
16287uint32_t
16288dns_zone_getidleout(dns_zone_t *zone) {
16289	REQUIRE(DNS_ZONE_VALID(zone));
16290
16291	return (zone->idleout);
16292}
16293
16294static void
16295notify_done(isc_task_t *task, isc_event_t *event) {
16296	dns_requestevent_t *revent = (dns_requestevent_t *)event;
16297	dns_notify_t *notify;
16298	isc_result_t result;
16299	dns_message_t *message = NULL;
16300	isc_buffer_t buf;
16301	char rcode[128];
16302	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
16303
16304	UNUSED(task);
16305
16306	notify = event->ev_arg;
16307	REQUIRE(DNS_NOTIFY_VALID(notify));
16308	INSIST(task == notify->zone->task);
16309
16310	isc_buffer_init(&buf, rcode, sizeof(rcode));
16311	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
16312	dns_message_create(notify->zone->mctx, DNS_MESSAGE_INTENTPARSE,
16313			   &message);
16314
16315	if (revent->result != ISC_R_SUCCESS) {
16316		result = revent->result;
16317		goto fail;
16318	}
16319
16320	result = dns_request_getresponse(revent->request, message,
16321					 DNS_MESSAGEPARSE_PRESERVEORDER);
16322	if (result != ISC_R_SUCCESS) {
16323		goto fail;
16324	}
16325
16326	result = dns_rcode_totext(message->rcode, &buf);
16327	if (result == ISC_R_SUCCESS) {
16328		notify_log(notify->zone, ISC_LOG_DEBUG(3),
16329			   "notify response from %s: %.*s", addrbuf,
16330			   (int)buf.used, rcode);
16331	}
16332
16333	goto done;
16334
16335fail:
16336	notify_log(notify->zone, ISC_LOG_DEBUG(2), "notify to %s failed: %s",
16337		   addrbuf, isc_result_totext(result));
16338	if (result == ISC_R_TIMEDOUT) {
16339		notify_log(notify->zone, ISC_LOG_DEBUG(1),
16340			   "notify to %s: retries exceeded", addrbuf);
16341	}
16342done:
16343	notify_destroy(notify, false);
16344	isc_event_free(&event);
16345	dns_message_detach(&message);
16346}
16347
16348struct secure_event {
16349	isc_event_t e;
16350	dns_db_t *db;
16351	uint32_t serial;
16352};
16353
16354static void
16355update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
16356	UNUSED(arg);
16357	dns_zone_log(zone, level, "%s", message);
16358}
16359
16360static isc_result_t
16361sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
16362		    uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
16363		    dns_diff_t *diff) {
16364	isc_result_t result;
16365	dns_difftuple_t *tuple = NULL;
16366	dns_diffop_t op = DNS_DIFFOP_ADD;
16367	int n_soa = 0;
16368
16369	REQUIRE(soatuplep != NULL);
16370
16371	if (start == end) {
16372		return (DNS_R_UNCHANGED);
16373	}
16374
16375	CHECK(dns_journal_iter_init(journal, start, end, NULL));
16376	for (result = dns_journal_first_rr(journal); result == ISC_R_SUCCESS;
16377	     result = dns_journal_next_rr(journal))
16378	{
16379		dns_name_t *name = NULL;
16380		uint32_t ttl;
16381		dns_rdata_t *rdata = NULL;
16382		dns_journal_current_rr(journal, &name, &ttl, &rdata);
16383
16384		if (rdata->type == dns_rdatatype_soa) {
16385			n_soa++;
16386			if (n_soa == 2) {
16387				/*
16388				 * Save the latest raw SOA record.
16389				 */
16390				if (*soatuplep != NULL) {
16391					dns_difftuple_free(soatuplep);
16392				}
16393				CHECK(dns_difftuple_create(
16394					diff->mctx, DNS_DIFFOP_ADD, name, ttl,
16395					rdata, soatuplep));
16396			}
16397			if (n_soa == 3) {
16398				n_soa = 1;
16399			}
16400			continue;
16401		}
16402
16403		/* Sanity. */
16404		if (n_soa == 0) {
16405			dns_zone_log(raw, ISC_LOG_ERROR,
16406				     "corrupt journal file: '%s'\n",
16407				     raw->journal);
16408			return (ISC_R_FAILURE);
16409		}
16410
16411		if (zone->privatetype != 0 && rdata->type == zone->privatetype)
16412		{
16413			continue;
16414		}
16415
16416		if (rdata->type == dns_rdatatype_nsec ||
16417		    rdata->type == dns_rdatatype_rrsig ||
16418		    rdata->type == dns_rdatatype_nsec3 ||
16419		    rdata->type == dns_rdatatype_dnskey ||
16420		    rdata->type == dns_rdatatype_nsec3param)
16421		{
16422			continue;
16423		}
16424
16425		op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
16426
16427		CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
16428					   &tuple));
16429		dns_diff_appendminimal(diff, &tuple);
16430	}
16431	if (result == ISC_R_NOMORE) {
16432		result = ISC_R_SUCCESS;
16433	}
16434
16435failure:
16436	return (result);
16437}
16438
16439static isc_result_t
16440sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
16441	       dns_dbversion_t *secver, dns_difftuple_t **soatuple,
16442	       dns_diff_t *diff) {
16443	isc_result_t result;
16444	dns_db_t *rawdb = NULL;
16445	dns_dbversion_t *rawver = NULL;
16446	dns_difftuple_t *tuple = NULL, *next;
16447	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
16448	dns_rdata_soa_t oldsoa, newsoa;
16449
16450	REQUIRE(DNS_ZONE_VALID(seczone));
16451	REQUIRE(soatuple != NULL && *soatuple == NULL);
16452
16453	if (!seczone->sourceserialset) {
16454		return (DNS_R_UNCHANGED);
16455	}
16456
16457	dns_db_attach(raw->db, &rawdb);
16458	dns_db_currentversion(rawdb, &rawver);
16459	result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
16460	dns_db_closeversion(rawdb, &rawver, false);
16461	dns_db_detach(&rawdb);
16462
16463	if (result != ISC_R_SUCCESS) {
16464		return (result);
16465	}
16466
16467	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
16468		next = ISC_LIST_NEXT(tuple, link);
16469		if (tuple->rdata.type == dns_rdatatype_nsec ||
16470		    tuple->rdata.type == dns_rdatatype_rrsig ||
16471		    tuple->rdata.type == dns_rdatatype_dnskey ||
16472		    tuple->rdata.type == dns_rdatatype_nsec3 ||
16473		    tuple->rdata.type == dns_rdatatype_nsec3param)
16474		{
16475			ISC_LIST_UNLINK(diff->tuples, tuple, link);
16476			dns_difftuple_free(&tuple);
16477			continue;
16478		}
16479		if (tuple->rdata.type == dns_rdatatype_soa) {
16480			if (tuple->op == DNS_DIFFOP_DEL) {
16481				INSIST(oldtuple == NULL);
16482				oldtuple = tuple;
16483			}
16484			if (tuple->op == DNS_DIFFOP_ADD) {
16485				INSIST(newtuple == NULL);
16486				newtuple = tuple;
16487			}
16488		}
16489	}
16490
16491	if (oldtuple != NULL && newtuple != NULL) {
16492		result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
16493		RUNTIME_CHECK(result == ISC_R_SUCCESS);
16494
16495		result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
16496		RUNTIME_CHECK(result == ISC_R_SUCCESS);
16497
16498		/*
16499		 * If the SOA records are the same except for the serial
16500		 * remove them from the diff.
16501		 */
16502		if (oldtuple->ttl == newtuple->ttl &&
16503		    oldsoa.refresh == newsoa.refresh &&
16504		    oldsoa.retry == newsoa.retry &&
16505		    oldsoa.minimum == newsoa.minimum &&
16506		    oldsoa.expire == newsoa.expire &&
16507		    dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
16508		    dns_name_equal(&oldsoa.contact, &newsoa.contact))
16509		{
16510			ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16511			dns_difftuple_free(&oldtuple);
16512			ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16513			dns_difftuple_free(&newtuple);
16514		}
16515	}
16516
16517	if (ISC_LIST_EMPTY(diff->tuples)) {
16518		return (DNS_R_UNCHANGED);
16519	}
16520
16521	/*
16522	 * If there are still SOA records in the diff they can now be removed
16523	 * saving the new SOA record.
16524	 */
16525	if (oldtuple != NULL) {
16526		ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16527		dns_difftuple_free(&oldtuple);
16528	}
16529
16530	if (newtuple != NULL) {
16531		ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16532		*soatuple = newtuple;
16533	}
16534
16535	return (ISC_R_SUCCESS);
16536}
16537
16538static void
16539receive_secure_serial(isc_task_t *task, isc_event_t *event) {
16540	static char me[] = "receive_secure_serial";
16541	isc_result_t result = ISC_R_SUCCESS;
16542	dns_journal_t *rjournal = NULL;
16543	dns_journal_t *sjournal = NULL;
16544	uint32_t start, end;
16545	dns_zone_t *zone;
16546	dns_difftuple_t *tuple = NULL, *soatuple = NULL;
16547	dns_update_log_t log = { update_log_cb, NULL };
16548	uint32_t newserial = 0, desired = 0;
16549	isc_time_t timenow;
16550	int level = ISC_LOG_ERROR;
16551
16552	UNUSED(task);
16553
16554	zone = event->ev_arg;
16555	end = ((struct secure_event *)event)->serial;
16556
16557	ENTER;
16558
16559	LOCK_ZONE(zone);
16560
16561	/*
16562	 * If we are already processing a receive secure serial event
16563	 * for the zone, just queue the new one and exit.
16564	 */
16565	if (zone->rss_event != NULL && zone->rss_event != event) {
16566		ISC_LIST_APPEND(zone->rss_events, event, ev_link);
16567		UNLOCK_ZONE(zone);
16568		return;
16569	}
16570
16571nextevent:
16572	if (zone->rss_event != NULL) {
16573		INSIST(zone->rss_event == event);
16574		UNLOCK_ZONE(zone);
16575	} else {
16576		zone->rss_event = event;
16577		dns_diff_init(zone->mctx, &zone->rss_diff);
16578
16579		/*
16580		 * zone->db may be NULL, if the load from disk failed.
16581		 */
16582		result = ISC_R_SUCCESS;
16583		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16584		if (zone->db != NULL) {
16585			dns_db_attach(zone->db, &zone->rss_db);
16586		} else {
16587			result = ISC_R_FAILURE;
16588		}
16589		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16590
16591		if (result == ISC_R_SUCCESS && zone->raw != NULL) {
16592			dns_zone_attach(zone->raw, &zone->rss_raw);
16593		} else {
16594			result = ISC_R_FAILURE;
16595		}
16596
16597		UNLOCK_ZONE(zone);
16598
16599		CHECK(result);
16600
16601		/*
16602		 * We first attempt to sync the raw zone to the secure zone
16603		 * by using the raw zone's journal, applying all the deltas
16604		 * from the latest source-serial of the secure zone up to
16605		 * the current serial number of the raw zone.
16606		 *
16607		 * If that fails, then we'll fall back to a direct comparison
16608		 * between raw and secure zones.
16609		 */
16610		CHECK(dns_journal_open(zone->rss_raw->mctx,
16611				       zone->rss_raw->journal,
16612				       DNS_JOURNAL_WRITE, &rjournal));
16613
16614		result = dns_journal_open(zone->mctx, zone->journal,
16615					  DNS_JOURNAL_READ, &sjournal);
16616		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
16617			goto failure;
16618		}
16619
16620		if (!dns_journal_get_sourceserial(rjournal, &start)) {
16621			start = dns_journal_first_serial(rjournal);
16622			dns_journal_set_sourceserial(rjournal, start);
16623		}
16624		if (sjournal != NULL) {
16625			uint32_t serial;
16626			/*
16627			 * We read the secure journal first, if that
16628			 * exists use its value provided it is greater
16629			 * that from the raw journal.
16630			 */
16631			if (dns_journal_get_sourceserial(sjournal, &serial)) {
16632				if (isc_serial_gt(serial, start)) {
16633					start = serial;
16634				}
16635			}
16636			dns_journal_destroy(&sjournal);
16637		}
16638
16639		dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
16640		CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
16641
16642		/*
16643		 * Try to apply diffs from the raw zone's journal to the secure
16644		 * zone.  If that fails, we recover by syncing up the databases
16645		 * directly.
16646		 */
16647		result = sync_secure_journal(zone, zone->rss_raw, rjournal,
16648					     start, end, &soatuple,
16649					     &zone->rss_diff);
16650		if (result == DNS_R_UNCHANGED) {
16651			goto failure;
16652		} else if (result != ISC_R_SUCCESS) {
16653			CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
16654					     zone->rss_oldver, &soatuple,
16655					     &zone->rss_diff));
16656		}
16657
16658		CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
16659				     zone->rss_newver));
16660
16661		if (soatuple != NULL) {
16662			uint32_t oldserial;
16663
16664			CHECK(dns_db_createsoatuple(
16665				zone->rss_db, zone->rss_oldver,
16666				zone->rss_diff.mctx, DNS_DIFFOP_DEL, &tuple));
16667			oldserial = dns_soa_getserial(&tuple->rdata);
16668			newserial = desired =
16669				dns_soa_getserial(&soatuple->rdata);
16670			if (!isc_serial_gt(newserial, oldserial)) {
16671				newserial = oldserial + 1;
16672				if (newserial == 0) {
16673					newserial++;
16674				}
16675				dns_soa_setserial(newserial, &soatuple->rdata);
16676			}
16677			CHECK(do_one_tuple(&tuple, zone->rss_db,
16678					   zone->rss_newver, &zone->rss_diff));
16679			CHECK(do_one_tuple(&soatuple, zone->rss_db,
16680					   zone->rss_newver, &zone->rss_diff));
16681		} else {
16682			CHECK(update_soa_serial(zone, zone->rss_db,
16683						zone->rss_newver,
16684						&zone->rss_diff, zone->mctx,
16685						zone->updatemethod));
16686		}
16687	}
16688	result = dns_update_signaturesinc(
16689		&log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver,
16690		&zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state);
16691	if (result == DNS_R_CONTINUE) {
16692		if (rjournal != NULL) {
16693			dns_journal_destroy(&rjournal);
16694		}
16695		isc_task_send(task, &event);
16696		return;
16697	}
16698	/*
16699	 * If something went wrong while trying to update the secure zone and
16700	 * the latter was already signed before, do not apply raw zone deltas
16701	 * to it as that would break existing DNSSEC signatures.  However, if
16702	 * the secure zone was not yet signed (e.g. because no signing keys
16703	 * were created for it), commence applying raw zone deltas to it so
16704	 * that contents of the raw zone and the secure zone are kept in sync.
16705	 */
16706	if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
16707		goto failure;
16708	}
16709
16710	if (rjournal == NULL) {
16711		CHECK(dns_journal_open(zone->rss_raw->mctx,
16712				       zone->rss_raw->journal,
16713				       DNS_JOURNAL_WRITE, &rjournal));
16714	}
16715	CHECK(zone_journal(zone, &zone->rss_diff, &end,
16716			   "receive_secure_serial"));
16717
16718	dns_journal_set_sourceserial(rjournal, end);
16719	dns_journal_commit(rjournal);
16720
16721	LOCK_ZONE(zone);
16722	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16723
16724	zone->sourceserial = end;
16725	zone->sourceserialset = true;
16726	zone_needdump(zone, DNS_DUMP_DELAY);
16727
16728	/*
16729	 * Set resign time to make sure it is set to the earliest
16730	 * signature expiration.
16731	 */
16732	set_resigntime(zone);
16733	TIME_NOW(&timenow);
16734	zone_settimer(zone, &timenow);
16735	UNLOCK_ZONE(zone);
16736
16737	dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
16738	dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
16739
16740	if (newserial != 0) {
16741		dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
16742			     newserial, desired);
16743	}
16744
16745failure:
16746	isc_event_free(&zone->rss_event);
16747	event = ISC_LIST_HEAD(zone->rss_events);
16748
16749	if (zone->rss_raw != NULL) {
16750		dns_zone_detach(&zone->rss_raw);
16751	}
16752	if (result != ISC_R_SUCCESS) {
16753		LOCK_ZONE(zone);
16754		set_resigntime(zone);
16755		TIME_NOW(&timenow);
16756		zone_settimer(zone, &timenow);
16757		UNLOCK_ZONE(zone);
16758		if (result == DNS_R_UNCHANGED) {
16759			level = ISC_LOG_INFO;
16760		}
16761		dns_zone_log(zone, level, "receive_secure_serial: %s",
16762			     isc_result_totext(result));
16763	}
16764	if (tuple != NULL) {
16765		dns_difftuple_free(&tuple);
16766	}
16767	if (soatuple != NULL) {
16768		dns_difftuple_free(&soatuple);
16769	}
16770	if (zone->rss_db != NULL) {
16771		if (zone->rss_oldver != NULL) {
16772			dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
16773					    false);
16774		}
16775		if (zone->rss_newver != NULL) {
16776			dns_db_closeversion(zone->rss_db, &zone->rss_newver,
16777					    false);
16778		}
16779		dns_db_detach(&zone->rss_db);
16780	}
16781	INSIST(zone->rss_oldver == NULL);
16782	INSIST(zone->rss_newver == NULL);
16783	if (rjournal != NULL) {
16784		dns_journal_destroy(&rjournal);
16785	}
16786	dns_diff_clear(&zone->rss_diff);
16787
16788	if (event != NULL) {
16789		LOCK_ZONE(zone);
16790		isc_refcount_decrement(&zone->irefs);
16791		ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
16792		goto nextevent;
16793	}
16794
16795	event = ISC_LIST_HEAD(zone->rss_post);
16796	while (event != NULL) {
16797		ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
16798		rss_post(zone, event);
16799		event = ISC_LIST_HEAD(zone->rss_post);
16800	}
16801
16802	dns_zone_idetach(&zone);
16803}
16804
16805static isc_result_t
16806zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
16807	isc_event_t *e;
16808	dns_zone_t *dummy = NULL;
16809
16810	e = isc_event_allocate(zone->secure->mctx, zone,
16811			       DNS_EVENT_ZONESECURESERIAL,
16812			       receive_secure_serial, zone->secure,
16813			       sizeof(struct secure_event));
16814	((struct secure_event *)e)->serial = serial;
16815	INSIST(LOCKED_ZONE(zone->secure));
16816	zone_iattach(zone->secure, &dummy);
16817	isc_task_send(zone->secure->task, &e);
16818
16819	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
16820	return (ISC_R_SUCCESS);
16821}
16822
16823static isc_result_t
16824checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
16825	       dns_rdataset_t *rdataset, uint32_t oldserial) {
16826	dns_rdata_soa_t soa;
16827	dns_rdata_t rdata = DNS_RDATA_INIT;
16828	dns_rdatalist_t temprdatalist;
16829	dns_rdataset_t temprdataset;
16830	isc_buffer_t b;
16831	isc_result_t result;
16832	unsigned char buf[DNS_SOA_BUFFERSIZE];
16833	dns_fixedname_t fixed;
16834	dns_name_t *name;
16835
16836	result = dns_rdataset_first(rdataset);
16837	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16838	dns_rdataset_current(rdataset, &rdata);
16839	result = dns_rdata_tostruct(&rdata, &soa, NULL);
16840	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16841
16842	if (isc_serial_gt(soa.serial, oldserial)) {
16843		return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
16844					   NULL));
16845	}
16846	/*
16847	 * Always bump the serial.
16848	 */
16849	oldserial++;
16850	if (oldserial == 0) {
16851		oldserial++;
16852	}
16853	soa.serial = oldserial;
16854
16855	/*
16856	 * Construct a replacement rdataset.
16857	 */
16858	dns_rdata_reset(&rdata);
16859	isc_buffer_init(&b, buf, sizeof(buf));
16860	result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
16861				      dns_rdatatype_soa, &soa, &b);
16862	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16863	dns_rdatalist_init(&temprdatalist);
16864	temprdatalist.rdclass = rdata.rdclass;
16865	temprdatalist.type = rdata.type;
16866	temprdatalist.ttl = rdataset->ttl;
16867	ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
16868
16869	dns_rdataset_init(&temprdataset);
16870	result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
16871	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16872
16873	name = dns_fixedname_initname(&fixed);
16874	result = dns_db_nodefullname(db, node, name);
16875	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16876	dns_rdataset_getownercase(rdataset, name);
16877	dns_rdataset_setownercase(&temprdataset, name);
16878	return (dns_db_addrdataset(db, node, version, 0, &temprdataset, 0,
16879				   NULL));
16880}
16881
16882/*
16883 * This function should populate an nsec3paramlist_t with the
16884 * nsecparam_t data from a zone.
16885 */
16886static isc_result_t
16887save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
16888	isc_result_t result;
16889	dns_dbnode_t *node = NULL;
16890	dns_rdataset_t rdataset, prdataset;
16891	dns_dbversion_t *version = NULL;
16892	nsec3param_t *nsec3param = NULL;
16893	nsec3param_t *nsec3p = NULL;
16894	nsec3param_t *next;
16895	dns_db_t *db = NULL;
16896	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16897
16898	REQUIRE(DNS_ZONE_VALID(zone));
16899	REQUIRE(nsec3list != NULL);
16900	REQUIRE(ISC_LIST_EMPTY(*nsec3list));
16901
16902	dns_rdataset_init(&rdataset);
16903	dns_rdataset_init(&prdataset);
16904
16905	dns_db_attach(zone->db, &db);
16906	CHECK(dns_db_getoriginnode(db, &node));
16907
16908	dns_db_currentversion(db, &version);
16909	result = dns_db_findrdataset(db, node, version,
16910				     dns_rdatatype_nsec3param,
16911				     dns_rdatatype_none, 0, &rdataset, NULL);
16912
16913	if (result != ISC_R_SUCCESS) {
16914		goto getprivate;
16915	}
16916
16917	/*
16918	 * Walk nsec3param rdataset making a list of parameters (note that
16919	 * multiple simultaneous nsec3 chains are annoyingly legal -- this
16920	 * is why we use an nsec3list, even though we will usually only
16921	 * have one).
16922	 */
16923	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
16924	     result = dns_rdataset_next(&rdataset))
16925	{
16926		dns_rdata_t rdata = DNS_RDATA_INIT;
16927		dns_rdata_t private = DNS_RDATA_INIT;
16928
16929		dns_rdataset_current(&rdataset, &rdata);
16930		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16931			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16932			      "looping through nsec3param data");
16933		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16934		ISC_LINK_INIT(nsec3param, link);
16935
16936		/*
16937		 * now transfer the data from the rdata to
16938		 * the nsec3param
16939		 */
16940		dns_nsec3param_toprivate(&rdata, &private, zone->privatetype,
16941					 nsec3param->data,
16942					 sizeof(nsec3param->data));
16943		nsec3param->length = private.length;
16944		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16945	}
16946
16947getprivate:
16948	result = dns_db_findrdataset(db, node, version, zone->privatetype,
16949				     dns_rdatatype_none, 0, &prdataset, NULL);
16950	if (result != ISC_R_SUCCESS) {
16951		goto done;
16952	}
16953
16954	/*
16955	 * walk private type records, converting them to nsec3 parameters
16956	 * using dns_nsec3param_fromprivate(), do the right thing based on
16957	 * CREATE and REMOVE flags
16958	 */
16959	for (result = dns_rdataset_first(&prdataset); result == ISC_R_SUCCESS;
16960	     result = dns_rdataset_next(&prdataset))
16961	{
16962		dns_rdata_t rdata = DNS_RDATA_INIT;
16963		dns_rdata_t private = DNS_RDATA_INIT;
16964
16965		dns_rdataset_current(&prdataset, &private);
16966		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16967			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16968			      "looping through nsec3param private data");
16969
16970		/*
16971		 * Do we have a valid private record?
16972		 */
16973		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
16974						sizeof(buf)))
16975		{
16976			continue;
16977		}
16978
16979		/*
16980		 * Remove any NSEC3PARAM records scheduled to be removed.
16981		 */
16982		if (NSEC3REMOVE(rdata.data[1])) {
16983			/*
16984			 * Zero out the flags.
16985			 */
16986			rdata.data[1] = 0;
16987
16988			for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL;
16989			     nsec3p = next)
16990			{
16991				next = ISC_LIST_NEXT(nsec3p, link);
16992
16993				if (nsec3p->length == rdata.length + 1 &&
16994				    memcmp(rdata.data, nsec3p->data + 1,
16995					   nsec3p->length - 1) == 0)
16996				{
16997					ISC_LIST_UNLINK(*nsec3list, nsec3p,
16998							link);
16999					isc_mem_put(zone->mctx, nsec3p,
17000						    sizeof(nsec3param_t));
17001				}
17002			}
17003			continue;
17004		}
17005
17006		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
17007		ISC_LINK_INIT(nsec3param, link);
17008
17009		/*
17010		 * Copy the remaining private records so the nsec/nsec3
17011		 * chain gets created.
17012		 */
17013		INSIST(private.length <= sizeof(nsec3param->data));
17014		memmove(nsec3param->data, private.data, private.length);
17015		nsec3param->length = private.length;
17016		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
17017	}
17018
17019done:
17020	if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) {
17021		result = ISC_R_SUCCESS;
17022	}
17023
17024failure:
17025	if (node != NULL) {
17026		dns_db_detachnode(db, &node);
17027	}
17028	if (version != NULL) {
17029		dns_db_closeversion(db, &version, false);
17030	}
17031	if (db != NULL) {
17032		dns_db_detach(&db);
17033	}
17034	if (dns_rdataset_isassociated(&rdataset)) {
17035		dns_rdataset_disassociate(&rdataset);
17036	}
17037	if (dns_rdataset_isassociated(&prdataset)) {
17038		dns_rdataset_disassociate(&prdataset);
17039	}
17040	return (result);
17041}
17042
17043/*
17044 * Populate new zone db with private type records found by save_nsec3param().
17045 */
17046static isc_result_t
17047restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
17048		   nsec3paramlist_t *nsec3list) {
17049	isc_result_t result = ISC_R_SUCCESS;
17050	dns_diff_t diff;
17051	dns_rdata_t rdata;
17052	nsec3param_t *nsec3p = NULL;
17053	nsec3param_t *next;
17054
17055	REQUIRE(DNS_ZONE_VALID(zone));
17056	REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
17057
17058	dns_diff_init(zone->mctx, &diff);
17059
17060	/*
17061	 * Loop through the list of private-type records, set the INITIAL
17062	 * and CREATE flags, and the add the record to the apex of the tree
17063	 * in db.
17064	 */
17065	for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next)
17066	{
17067		next = ISC_LIST_NEXT(nsec3p, link);
17068		dns_rdata_init(&rdata);
17069		nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
17070		rdata.length = nsec3p->length;
17071		rdata.data = nsec3p->data;
17072		rdata.type = zone->privatetype;
17073		rdata.rdclass = zone->rdclass;
17074		result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
17075				       &zone->origin, 0, &rdata);
17076		if (result != ISC_R_SUCCESS) {
17077			break;
17078		}
17079	}
17080
17081	dns_diff_clear(&diff);
17082	return (result);
17083}
17084
17085static isc_result_t
17086copy_non_dnssec_records(dns_db_t *db, dns_db_t *version, dns_db_t *rawdb,
17087			dns_dbiterator_t *dbiterator, unsigned int *oldserial) {
17088	dns_dbnode_t *rawnode = NULL, *node = NULL;
17089	dns_fixedname_t fixed;
17090	dns_name_t *name = dns_fixedname_initname(&fixed);
17091	dns_rdataset_t rdataset;
17092	dns_rdatasetiter_t *rdsit = NULL;
17093	isc_result_t result;
17094
17095	result = dns_dbiterator_current(dbiterator, &rawnode, name);
17096	if (result != ISC_R_SUCCESS) {
17097		return (ISC_R_SUCCESS);
17098	}
17099
17100	dns_dbiterator_pause(dbiterator);
17101
17102	result = dns_db_findnode(db, name, true, &node);
17103	if (result != ISC_R_SUCCESS) {
17104		goto cleanup;
17105	}
17106
17107	result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, 0, &rdsit);
17108	if (result != ISC_R_SUCCESS) {
17109		goto cleanup;
17110	}
17111
17112	dns_rdataset_init(&rdataset);
17113
17114	for (result = dns_rdatasetiter_first(rdsit); result == ISC_R_SUCCESS;
17115	     result = dns_rdatasetiter_next(rdsit))
17116	{
17117		dns_rdatasetiter_current(rdsit, &rdataset);
17118		if (rdataset.type == dns_rdatatype_nsec ||
17119		    rdataset.type == dns_rdatatype_rrsig ||
17120		    rdataset.type == dns_rdatatype_nsec3 ||
17121		    rdataset.type == dns_rdatatype_dnskey ||
17122		    rdataset.type == dns_rdatatype_nsec3param)
17123		{
17124			dns_rdataset_disassociate(&rdataset);
17125			continue;
17126		}
17127		if (rdataset.type == dns_rdatatype_soa && oldserial != NULL) {
17128			result = checkandaddsoa(db, node, version, &rdataset,
17129						*oldserial);
17130		} else {
17131			result = dns_db_addrdataset(db, node, version, 0,
17132						    &rdataset, 0, NULL);
17133		}
17134		dns_rdataset_disassociate(&rdataset);
17135		if (result != ISC_R_SUCCESS) {
17136			goto cleanup;
17137		}
17138	}
17139	if (result == ISC_R_NOMORE) {
17140		result = ISC_R_SUCCESS;
17141	}
17142
17143cleanup:
17144	if (rdsit != NULL) {
17145		dns_rdatasetiter_destroy(&rdsit);
17146	}
17147	if (rawnode) {
17148		dns_db_detachnode(rawdb, &rawnode);
17149	}
17150	if (node) {
17151		dns_db_detachnode(db, &node);
17152	}
17153	return (result);
17154}
17155
17156static void
17157receive_secure_db(isc_task_t *task, isc_event_t *event) {
17158	isc_result_t result;
17159	dns_zone_t *zone;
17160	dns_db_t *rawdb, *db = NULL;
17161	dns_dbiterator_t *dbiterator = NULL;
17162	dns_dbversion_t *version = NULL;
17163	isc_time_t loadtime;
17164	unsigned int oldserial = 0, *oldserialp = NULL;
17165	nsec3paramlist_t nsec3list;
17166	isc_event_t *setnsec3param_event;
17167	dns_zone_t *dummy;
17168
17169	UNUSED(task);
17170
17171	ISC_LIST_INIT(nsec3list);
17172
17173	zone = event->ev_arg;
17174	rawdb = ((struct secure_event *)event)->db;
17175	isc_event_free(&event);
17176
17177	LOCK_ZONE(zone);
17178	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
17179		result = ISC_R_SHUTTINGDOWN;
17180		goto failure;
17181	}
17182
17183	TIME_NOW(&loadtime);
17184	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17185	if (zone->db != NULL) {
17186		result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
17187		if (result == ISC_R_SUCCESS) {
17188			oldserialp = &oldserial;
17189		}
17190
17191		/*
17192		 * assemble nsec3parameters from the old zone, and set a flag
17193		 * if any are found
17194		 */
17195		result = save_nsec3param(zone, &nsec3list);
17196		if (result != ISC_R_SUCCESS) {
17197			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17198			goto failure;
17199		}
17200	}
17201	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17202
17203	result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
17204			       dns_dbtype_zone, zone->rdclass,
17205			       zone->db_argc - 1, zone->db_argv + 1, &db);
17206	if (result != ISC_R_SUCCESS) {
17207		goto failure;
17208	}
17209
17210	result = dns_db_setgluecachestats(db, zone->gluecachestats);
17211	if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
17212		goto failure;
17213	}
17214
17215	result = dns_db_newversion(db, &version);
17216	if (result != ISC_R_SUCCESS) {
17217		goto failure;
17218	}
17219
17220	result = dns_db_createiterator(rawdb, 0, &dbiterator);
17221	if (result != ISC_R_SUCCESS) {
17222		goto failure;
17223	}
17224
17225	for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
17226	     result = dns_dbiterator_next(dbiterator))
17227	{
17228		result = copy_non_dnssec_records(db, version, rawdb, dbiterator,
17229						 oldserialp);
17230		if (result != ISC_R_SUCCESS) {
17231			goto failure;
17232		}
17233	}
17234	dns_dbiterator_destroy(&dbiterator);
17235	if (result != ISC_R_NOMORE) {
17236		goto failure;
17237	}
17238
17239	/*
17240	 * Call restore_nsec3param() to create private-type records from
17241	 * the old nsec3 parameters and insert them into db
17242	 */
17243	if (!ISC_LIST_EMPTY(nsec3list)) {
17244		result = restore_nsec3param(zone, db, version, &nsec3list);
17245		if (result != ISC_R_SUCCESS) {
17246			goto failure;
17247		}
17248	}
17249
17250	dns_db_closeversion(db, &version, true);
17251
17252	/*
17253	 * Lock hierarchy: zmgr, zone, raw.
17254	 */
17255	INSIST(zone != zone->raw);
17256	LOCK_ZONE(zone->raw);
17257	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17258	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
17259	zone_needdump(zone, 0); /* XXXMPA */
17260	UNLOCK_ZONE(zone->raw);
17261
17262	/*
17263	 * Process any queued NSEC3PARAM change requests.
17264	 */
17265	while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
17266		setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
17267		ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
17268				ev_link);
17269		dummy = NULL;
17270		zone_iattach(zone, &dummy);
17271		isc_task_send(zone->task, &setnsec3param_event);
17272	}
17273
17274failure:
17275	UNLOCK_ZONE(zone);
17276	if (dbiterator != NULL) {
17277		dns_dbiterator_destroy(&dbiterator);
17278	}
17279	if (result != ISC_R_SUCCESS) {
17280		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
17281			     isc_result_totext(result));
17282	}
17283
17284	while (!ISC_LIST_EMPTY(nsec3list)) {
17285		nsec3param_t *nsec3p;
17286		nsec3p = ISC_LIST_HEAD(nsec3list);
17287		ISC_LIST_UNLINK(nsec3list, nsec3p, link);
17288		isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
17289	}
17290	if (db != NULL) {
17291		if (version != NULL) {
17292			dns_db_closeversion(db, &version, false);
17293		}
17294		dns_db_detach(&db);
17295	}
17296	dns_db_detach(&rawdb);
17297	dns_zone_idetach(&zone);
17298
17299	INSIST(version == NULL);
17300}
17301
17302static isc_result_t
17303zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
17304	isc_event_t *e;
17305	dns_db_t *dummy = NULL;
17306	dns_zone_t *secure = NULL;
17307
17308	e = isc_event_allocate(zone->secure->mctx, zone, DNS_EVENT_ZONESECUREDB,
17309			       receive_secure_db, zone->secure,
17310			       sizeof(struct secure_event));
17311	dns_db_attach(db, &dummy);
17312	((struct secure_event *)e)->db = dummy;
17313	INSIST(LOCKED_ZONE(zone->secure));
17314	zone_iattach(zone->secure, &secure);
17315	isc_task_send(zone->secure->task, &e);
17316	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
17317	return (ISC_R_SUCCESS);
17318}
17319
17320isc_result_t
17321dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17322	isc_result_t result;
17323	dns_zone_t *secure = NULL;
17324
17325	REQUIRE(DNS_ZONE_VALID(zone));
17326again:
17327	LOCK_ZONE(zone);
17328	if (inline_raw(zone)) {
17329		secure = zone->secure;
17330		INSIST(secure != zone);
17331		TRYLOCK_ZONE(result, secure);
17332		if (result != ISC_R_SUCCESS) {
17333			UNLOCK_ZONE(zone);
17334			secure = NULL;
17335			isc_thread_yield();
17336			goto again;
17337		}
17338	}
17339	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
17340	result = zone_replacedb(zone, db, dump);
17341	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
17342	if (secure != NULL) {
17343		UNLOCK_ZONE(secure);
17344	}
17345	UNLOCK_ZONE(zone);
17346	return (result);
17347}
17348
17349static isc_result_t
17350zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17351	dns_dbversion_t *ver;
17352	isc_result_t result;
17353	unsigned int soacount = 0;
17354	unsigned int nscount = 0;
17355
17356	/*
17357	 * 'zone' and 'zone->db' locked by caller.
17358	 */
17359	REQUIRE(DNS_ZONE_VALID(zone));
17360	REQUIRE(LOCKED_ZONE(zone));
17361	if (inline_raw(zone)) {
17362		REQUIRE(LOCKED_ZONE(zone->secure));
17363	}
17364
17365	result = zone_get_from_db(zone, db, &nscount, &soacount, NULL, NULL,
17366				  NULL, NULL, NULL, NULL, NULL);
17367	if (result == ISC_R_SUCCESS) {
17368		if (soacount != 1) {
17369			dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records",
17370				     soacount);
17371			result = DNS_R_BADZONE;
17372		}
17373		if (nscount == 0 && zone->type != dns_zone_key) {
17374			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
17375			result = DNS_R_BADZONE;
17376		}
17377		if (result != ISC_R_SUCCESS) {
17378			return (result);
17379		}
17380	} else {
17381		dns_zone_log(zone, ISC_LOG_ERROR,
17382			     "retrieving SOA and NS records failed: %s",
17383			     isc_result_totext(result));
17384		return (result);
17385	}
17386
17387	result = check_nsec3param(zone, db);
17388	if (result != ISC_R_SUCCESS) {
17389		return (result);
17390	}
17391
17392	ver = NULL;
17393	dns_db_currentversion(db, &ver);
17394
17395	/*
17396	 * The initial version of a secondary zone is always dumped;
17397	 * subsequent versions may be journaled instead if this
17398	 * is enabled in the configuration.
17399	 */
17400	if (zone->db != NULL && zone->journal != NULL &&
17401	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
17402	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
17403	{
17404		uint32_t serial, oldserial;
17405
17406		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
17407
17408		result = dns_db_getsoaserial(db, ver, &serial);
17409		if (result != ISC_R_SUCCESS) {
17410			dns_zone_log(zone, ISC_LOG_ERROR,
17411				     "ixfr-from-differences: unable to get "
17412				     "new serial");
17413			goto fail;
17414		}
17415
17416		/*
17417		 * This is checked in zone_postload() for primary zones.
17418		 */
17419		result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
17420					  &oldserial, NULL, NULL, NULL, NULL,
17421					  NULL);
17422		RUNTIME_CHECK(result == ISC_R_SUCCESS);
17423		RUNTIME_CHECK(soacount > 0U);
17424		if ((zone->type == dns_zone_secondary ||
17425		     (zone->type == dns_zone_redirect &&
17426		      zone->primaries != NULL)) &&
17427		    !isc_serial_gt(serial, oldserial))
17428		{
17429			uint32_t serialmin, serialmax;
17430			serialmin = (oldserial + 1) & 0xffffffffU;
17431			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
17432			dns_zone_log(zone, ISC_LOG_ERROR,
17433				     "ixfr-from-differences: failed: "
17434				     "new serial (%u) out of range [%u - %u]",
17435				     serial, serialmin, serialmax);
17436			result = ISC_R_RANGE;
17437			goto fail;
17438		}
17439
17440		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
17441				     zone->journal);
17442		if (result != ISC_R_SUCCESS) {
17443			char strbuf[ISC_STRERRORSIZE];
17444			strerror_r(errno, strbuf, sizeof(strbuf));
17445			dns_zone_log(zone, ISC_LOG_ERROR,
17446				     "ixfr-from-differences: failed: "
17447				     "%s",
17448				     strbuf);
17449			goto fallback;
17450		}
17451		if (dump) {
17452			zone_needdump(zone, DNS_DUMP_DELAY);
17453		} else {
17454			zone_journal_compact(zone, zone->db, serial);
17455		}
17456		if (zone->type == dns_zone_primary && inline_raw(zone)) {
17457			zone_send_secureserial(zone, serial);
17458		}
17459	} else {
17460	fallback:
17461		if (dump && zone->masterfile != NULL) {
17462			/*
17463			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
17464			 * to keep the old masterfile.
17465			 */
17466			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
17467			    remove(zone->masterfile) < 0 && errno != ENOENT)
17468			{
17469				char strbuf[ISC_STRERRORSIZE];
17470				strerror_r(errno, strbuf, sizeof(strbuf));
17471				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17472					      DNS_LOGMODULE_ZONE,
17473					      ISC_LOG_WARNING,
17474					      "unable to remove masterfile "
17475					      "'%s': '%s'",
17476					      zone->masterfile, strbuf);
17477			}
17478			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
17479				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
17480			} else {
17481				zone_needdump(zone, 0);
17482			}
17483		}
17484		if (dump && zone->journal != NULL) {
17485			/*
17486			 * The in-memory database just changed, and
17487			 * because 'dump' is set, it didn't change by
17488			 * being loaded from disk.  Also, we have not
17489			 * journaled diffs for this change.
17490			 * Therefore, the on-disk journal is missing
17491			 * the deltas for this change.	Since it can
17492			 * no longer be used to bring the zone
17493			 * up-to-date, it is useless and should be
17494			 * removed.
17495			 */
17496			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17497				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
17498				      "removing journal file");
17499			if (remove(zone->journal) < 0 && errno != ENOENT) {
17500				char strbuf[ISC_STRERRORSIZE];
17501				strerror_r(errno, strbuf, sizeof(strbuf));
17502				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17503					      DNS_LOGMODULE_ZONE,
17504					      ISC_LOG_WARNING,
17505					      "unable to remove journal "
17506					      "'%s': '%s'",
17507					      zone->journal, strbuf);
17508			}
17509		}
17510
17511		if (inline_raw(zone)) {
17512			zone_send_securedb(zone, db);
17513		}
17514	}
17515
17516	dns_db_closeversion(db, &ver, false);
17517
17518	dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
17519
17520	if (zone->db != NULL) {
17521		zone_detachdb(zone);
17522	}
17523	zone_attachdb(zone, db);
17524	dns_db_settask(zone->db, zone->task);
17525	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
17526	return (ISC_R_SUCCESS);
17527
17528fail:
17529	dns_db_closeversion(db, &ver, false);
17530	return (result);
17531}
17532
17533/* The caller must hold the dblock as a writer. */
17534static void
17535zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
17536	REQUIRE(zone->db == NULL && db != NULL);
17537
17538	dns_db_attach(db, &zone->db);
17539}
17540
17541/* The caller must hold the dblock as a writer. */
17542static void
17543zone_detachdb(dns_zone_t *zone) {
17544	REQUIRE(zone->db != NULL);
17545
17546	dns_zone_rpz_disable_db(zone, zone->db);
17547	dns_zone_catz_disable_db(zone, zone->db);
17548	dns_db_detach(&zone->db);
17549}
17550
17551static void
17552zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
17553	isc_time_t now;
17554	bool again = false;
17555	unsigned int soacount;
17556	unsigned int nscount;
17557	uint32_t serial, refresh, retry, expire, minimum, soattl;
17558	isc_result_t xfrresult = result;
17559	bool free_needed;
17560	dns_zone_t *secure = NULL;
17561
17562	REQUIRE(DNS_ZONE_VALID(zone));
17563
17564	dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17565		      "zone transfer finished: %s", isc_result_totext(result));
17566
17567	/*
17568	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
17569	 * could result in a deadlock due to a LOR so we will spin if we
17570	 * can't obtain both locks.
17571	 */
17572again:
17573	LOCK_ZONE(zone);
17574	if (inline_raw(zone)) {
17575		secure = zone->secure;
17576		INSIST(secure != zone);
17577		TRYLOCK_ZONE(result, secure);
17578		if (result != ISC_R_SUCCESS) {
17579			UNLOCK_ZONE(zone);
17580			secure = NULL;
17581			isc_thread_yield();
17582			goto again;
17583		}
17584	}
17585
17586	INSIST(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH));
17587	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
17588	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
17589
17590	TIME_NOW(&now);
17591	switch (xfrresult) {
17592	case ISC_R_SUCCESS:
17593		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17594		FALLTHROUGH;
17595	case DNS_R_UPTODATE:
17596		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17597		/*
17598		 * Has the zone expired underneath us?
17599		 */
17600		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17601		if (zone->db == NULL) {
17602			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17603			goto same_primary;
17604		}
17605
17606		/*
17607		 * Update the zone structure's data from the actual
17608		 * SOA received.
17609		 */
17610		nscount = 0;
17611		soacount = 0;
17612		INSIST(zone->db != NULL);
17613		result = zone_get_from_db(zone, zone->db, &nscount, &soacount,
17614					  &soattl, &serial, &refresh, &retry,
17615					  &expire, &minimum, NULL);
17616		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17617		if (result == ISC_R_SUCCESS) {
17618			if (soacount != 1) {
17619				dns_zone_log(zone, ISC_LOG_ERROR,
17620					     "transferred zone "
17621					     "has %d SOA records",
17622					     soacount);
17623				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17624				{
17625					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17626					zone->retry = DNS_ZONE_DEFAULTRETRY;
17627				}
17628				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17629				zone_unload(zone);
17630				goto next_primary;
17631			}
17632			if (nscount == 0) {
17633				dns_zone_log(zone, ISC_LOG_ERROR,
17634					     "transferred zone "
17635					     "has no NS records");
17636				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17637				{
17638					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17639					zone->retry = DNS_ZONE_DEFAULTRETRY;
17640				}
17641				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17642				zone_unload(zone);
17643				goto next_primary;
17644			}
17645			zone->refresh = RANGE(refresh, zone->minrefresh,
17646					      zone->maxrefresh);
17647			zone->retry = RANGE(retry, zone->minretry,
17648					    zone->maxretry);
17649			zone->expire = RANGE(expire,
17650					     zone->refresh + zone->retry,
17651					     DNS_MAX_EXPIRE);
17652			zone->soattl = soattl;
17653			zone->minimum = minimum;
17654			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17655		}
17656
17657		/*
17658		 * Set our next update/expire times.
17659		 */
17660		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
17661			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
17662			zone->refreshtime = now;
17663			DNS_ZONE_TIME_ADD(&now, zone->expire,
17664					  &zone->expiretime);
17665		} else {
17666			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
17667					    &zone->refreshtime);
17668			DNS_ZONE_TIME_ADD(&now, zone->expire,
17669					  &zone->expiretime);
17670		}
17671
17672		/*
17673		 * Set loadtime.
17674		 */
17675		zone->loadtime = now;
17676
17677		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
17678			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
17679			if (zone->tsigkey != NULL) {
17680				char namebuf[DNS_NAME_FORMATSIZE];
17681				dns_name_format(&zone->tsigkey->name, namebuf,
17682						sizeof(namebuf));
17683				snprintf(buf, sizeof(buf), ": TSIG '%s'",
17684					 namebuf);
17685			} else {
17686				buf[0] = '\0';
17687			}
17688			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17689				      ISC_LOG_INFO, "transferred serial %u%s",
17690				      serial, buf);
17691			if (inline_raw(zone)) {
17692				zone_send_secureserial(zone, serial);
17693			}
17694		}
17695
17696		/*
17697		 * This is not necessary if we just performed a AXFR
17698		 * however it is necessary for an IXFR / UPTODATE and
17699		 * won't hurt with an AXFR.
17700		 */
17701		if (zone->masterfile != NULL || zone->journal != NULL) {
17702			unsigned int delay = DNS_DUMP_DELAY;
17703
17704			result = ISC_R_FAILURE;
17705			if (zone->journal != NULL) {
17706				result = isc_file_settime(zone->journal, &now);
17707			}
17708			if (result != ISC_R_SUCCESS && zone->masterfile != NULL)
17709			{
17710				result = isc_file_settime(zone->masterfile,
17711							  &now);
17712			}
17713
17714			if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
17715			    result == ISC_R_FILENOTFOUND)
17716			{
17717				delay = 0;
17718			}
17719
17720			if ((result == ISC_R_SUCCESS ||
17721			     result == ISC_R_FILENOTFOUND) &&
17722			    zone->masterfile != NULL)
17723			{
17724				zone_needdump(zone, delay);
17725			} else if (result != ISC_R_SUCCESS) {
17726				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17727					      ISC_LOG_ERROR,
17728					      "transfer: could not set file "
17729					      "modification time of '%s': %s",
17730					      zone->masterfile,
17731					      isc_result_totext(result));
17732			}
17733		}
17734		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
17735		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
17736		break;
17737
17738	case DNS_R_BADIXFR:
17739		/* Force retry with AXFR. */
17740		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOIXFR);
17741		goto same_primary;
17742
17743	case DNS_R_TOOMANYRECORDS:
17744	case DNS_R_VERIFYFAILURE:
17745		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
17746		inc_stats(zone, dns_zonestatscounter_xfrfail);
17747		break;
17748
17749	default:
17750	next_primary:
17751		/*
17752		 * Skip to next failed / untried primary.
17753		 */
17754		do {
17755			zone->curprimary++;
17756		} while (zone->curprimary < zone->primariescnt &&
17757			 zone->primariesok[zone->curprimary]);
17758	same_primary:
17759		if (zone->curprimary >= zone->primariescnt) {
17760			zone->curprimary = 0;
17761			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
17762			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
17763			{
17764				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17765				DNS_ZONE_SETFLAG(zone,
17766						 DNS_ZONEFLG_USEALTXFRSRC);
17767				while (zone->curprimary < zone->primariescnt &&
17768				       zone->primariesok[zone->curprimary])
17769				{
17770					zone->curprimary++;
17771				}
17772				again = true;
17773			} else {
17774				DNS_ZONE_CLRFLAG(zone,
17775						 DNS_ZONEFLG_USEALTXFRSRC);
17776			}
17777		} else {
17778			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17779			again = true;
17780		}
17781		inc_stats(zone, dns_zonestatscounter_xfrfail);
17782		break;
17783	}
17784	zone_settimer(zone, &now);
17785
17786	/*
17787	 * If creating the transfer object failed, zone->xfr is NULL.
17788	 * Otherwise, we are called as the done callback of a zone
17789	 * transfer object that just entered its shutting-down
17790	 * state.  Since we are no longer responsible for shutting
17791	 * it down, we can detach our reference.
17792	 */
17793	if (zone->xfr != NULL) {
17794		dns_xfrin_detach(&zone->xfr);
17795	}
17796
17797	if (zone->tsigkey != NULL) {
17798		dns_tsigkey_detach(&zone->tsigkey);
17799	}
17800
17801	if (zone->transport != NULL) {
17802		dns_transport_detach(&zone->transport);
17803	}
17804
17805	/*
17806	 * Handle any deferred journal compaction.
17807	 */
17808	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
17809		dns_db_t *db = NULL;
17810		if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
17811			zone_journal_compact(zone, db, zone->compact_serial);
17812			dns_db_detach(&db);
17813			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
17814		}
17815	}
17816
17817	if (secure != NULL) {
17818		UNLOCK_ZONE(secure);
17819	}
17820	/*
17821	 * This transfer finishing freed up a transfer quota slot.
17822	 * Let any other zones waiting for quota have it.
17823	 */
17824	if (zone->zmgr != NULL &&
17825	    zone->statelist == &zone->zmgr->xfrin_in_progress)
17826	{
17827		UNLOCK_ZONE(zone);
17828		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17829		ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
17830		zone->statelist = NULL;
17831		zmgr_resume_xfrs(zone->zmgr, false);
17832		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17833		LOCK_ZONE(zone);
17834	}
17835
17836	/*
17837	 * Retry with a different server if necessary.
17838	 */
17839	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17840		queue_soa_query(zone);
17841	}
17842
17843	isc_refcount_decrement(&zone->irefs);
17844	free_needed = exit_check(zone);
17845	UNLOCK_ZONE(zone);
17846	if (free_needed) {
17847		zone_free(zone);
17848	}
17849}
17850
17851static void
17852zone_loaddone(void *arg, isc_result_t result) {
17853	static char me[] = "zone_loaddone";
17854	dns_load_t *load = arg;
17855	dns_zone_t *zone;
17856	isc_result_t tresult;
17857	dns_zone_t *secure = NULL;
17858
17859	REQUIRE(DNS_LOAD_VALID(load));
17860	zone = load->zone;
17861
17862	ENTER;
17863
17864	/*
17865	 * If zone loading failed, remove the update db callbacks prior
17866	 * to calling the list of callbacks in the zone load structure.
17867	 */
17868	if (result != ISC_R_SUCCESS) {
17869		dns_zone_rpz_disable_db(zone, load->db);
17870		dns_zone_catz_disable_db(zone, load->db);
17871	}
17872
17873	tresult = dns_db_endload(load->db, &load->callbacks);
17874	if (tresult != ISC_R_SUCCESS &&
17875	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
17876	{
17877		result = tresult;
17878	}
17879
17880	/*
17881	 * Lock hierarchy: zmgr, zone, raw.
17882	 */
17883again:
17884	LOCK_ZONE(zone);
17885	INSIST(zone != zone->raw);
17886	if (inline_secure(zone)) {
17887		LOCK_ZONE(zone->raw);
17888	} else if (inline_raw(zone)) {
17889		secure = zone->secure;
17890		TRYLOCK_ZONE(tresult, secure);
17891		if (tresult != ISC_R_SUCCESS) {
17892			UNLOCK_ZONE(zone);
17893			secure = NULL;
17894			isc_thread_yield();
17895			goto again;
17896		}
17897	}
17898	(void)zone_postload(zone, load->db, load->loadtime, result);
17899	zonemgr_putio(&zone->readio);
17900	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
17901	zone_idetach(&load->callbacks.zone);
17902	/*
17903	 * Leave the zone frozen if the reload fails.
17904	 */
17905	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
17906	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
17907	{
17908		zone->update_disabled = false;
17909	}
17910	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
17911	if (inline_secure(zone)) {
17912		UNLOCK_ZONE(zone->raw);
17913	} else if (secure != NULL) {
17914		UNLOCK_ZONE(secure);
17915	}
17916	UNLOCK_ZONE(zone);
17917
17918	load->magic = 0;
17919	dns_db_detach(&load->db);
17920	if (load->zone->lctx != NULL) {
17921		dns_loadctx_detach(&load->zone->lctx);
17922	}
17923	dns_zone_idetach(&load->zone);
17924	isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
17925}
17926
17927void
17928dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
17929	REQUIRE(DNS_ZONE_VALID(zone));
17930	REQUIRE(table != NULL);
17931	REQUIRE(*table == NULL);
17932
17933	LOCK_ZONE(zone);
17934	if (zone->ssutable != NULL) {
17935		dns_ssutable_attach(zone->ssutable, table);
17936	}
17937	UNLOCK_ZONE(zone);
17938}
17939
17940void
17941dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
17942	REQUIRE(DNS_ZONE_VALID(zone));
17943
17944	LOCK_ZONE(zone);
17945	if (zone->ssutable != NULL) {
17946		dns_ssutable_detach(&zone->ssutable);
17947	}
17948	if (table != NULL) {
17949		dns_ssutable_attach(table, &zone->ssutable);
17950	}
17951	UNLOCK_ZONE(zone);
17952}
17953
17954void
17955dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17956	REQUIRE(DNS_ZONE_VALID(zone));
17957
17958	zone->sigvalidityinterval = interval;
17959}
17960
17961uint32_t
17962dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
17963	REQUIRE(DNS_ZONE_VALID(zone));
17964
17965	return (zone->sigvalidityinterval);
17966}
17967
17968void
17969dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17970	REQUIRE(DNS_ZONE_VALID(zone));
17971
17972	zone->keyvalidityinterval = interval;
17973}
17974
17975uint32_t
17976dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
17977	REQUIRE(DNS_ZONE_VALID(zone));
17978
17979	return (zone->keyvalidityinterval);
17980}
17981
17982void
17983dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
17984	isc_time_t now;
17985
17986	REQUIRE(DNS_ZONE_VALID(zone));
17987
17988	LOCK_ZONE(zone);
17989	zone->sigresigninginterval = interval;
17990	set_resigntime(zone);
17991	if (zone->task != NULL) {
17992		TIME_NOW(&now);
17993		zone_settimer(zone, &now);
17994	}
17995	UNLOCK_ZONE(zone);
17996}
17997
17998uint32_t
17999dns_zone_getsigresigninginterval(dns_zone_t *zone) {
18000	REQUIRE(DNS_ZONE_VALID(zone));
18001
18002	return (zone->sigresigninginterval);
18003}
18004
18005static void
18006queue_xfrin(dns_zone_t *zone) {
18007	const char me[] = "queue_xfrin";
18008	isc_result_t result;
18009	dns_zonemgr_t *zmgr = zone->zmgr;
18010
18011	ENTER;
18012
18013	INSIST(zone->statelist == NULL);
18014
18015	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18016	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
18017	isc_refcount_increment0(&zone->irefs);
18018	zone->statelist = &zmgr->waiting_for_xfrin;
18019	result = zmgr_start_xfrin_ifquota(zmgr, zone);
18020	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18021
18022	if (result == ISC_R_QUOTA) {
18023		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18024			      "zone transfer deferred due to quota");
18025	} else if (result != ISC_R_SUCCESS) {
18026		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
18027			      "starting zone transfer: %s",
18028			      isc_result_totext(result));
18029	}
18030}
18031
18032/*
18033 * This event callback is called when a zone has received
18034 * any necessary zone transfer quota.  This is the time
18035 * to go ahead and start the transfer.
18036 */
18037static void
18038got_transfer_quota(isc_task_t *task, isc_event_t *event) {
18039	isc_result_t result = ISC_R_SUCCESS;
18040	dns_peer_t *peer = NULL;
18041	char primary[ISC_SOCKADDR_FORMATSIZE];
18042	char source[ISC_SOCKADDR_FORMATSIZE];
18043	dns_rdatatype_t xfrtype;
18044	dns_zone_t *zone = event->ev_arg;
18045	isc_netaddr_t primaryip;
18046	isc_sockaddr_t sourceaddr;
18047	isc_sockaddr_t primaryaddr;
18048	isc_time_t now;
18049	const char *soa_before = "";
18050	bool loaded;
18051	isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
18052
18053	UNUSED(task);
18054
18055	INSIST(task == zone->task);
18056
18057	isc_event_free(&event);
18058
18059	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
18060		zone_xfrdone(zone, ISC_R_CANCELED);
18061		return;
18062	}
18063
18064	TIME_NOW(&now);
18065
18066	isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary));
18067	if (dns_zonemgr_unreachable(zone->zmgr, &zone->primaryaddr,
18068				    &zone->sourceaddr, &now))
18069	{
18070		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
18071		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18072			      "got_transfer_quota: skipping zone transfer as "
18073			      "primary %s (source %s) is unreachable (cached)",
18074			      primary, source);
18075		zone_xfrdone(zone, ISC_R_CANCELED);
18076		return;
18077	}
18078
18079	isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr);
18080	(void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer);
18081
18082	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18083		soa_before = "SOA before ";
18084	}
18085	/*
18086	 * Decide whether we should request IXFR or AXFR.
18087	 */
18088	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18089	loaded = (zone->db != NULL);
18090	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18091
18092	if (!loaded) {
18093		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18094			      "no database exists yet, requesting AXFR of "
18095			      "initial version from %s",
18096			      primary);
18097		xfrtype = dns_rdatatype_axfr;
18098	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
18099		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18100			      "forced reload, requesting AXFR of "
18101			      "initial version from %s",
18102			      primary);
18103		xfrtype = dns_rdatatype_axfr;
18104	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOIXFR)) {
18105		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18106			      "retrying with AXFR from %s due to "
18107			      "previous IXFR failure",
18108			      primary);
18109		xfrtype = dns_rdatatype_axfr;
18110		LOCK_ZONE(zone);
18111		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOIXFR);
18112		UNLOCK_ZONE(zone);
18113	} else {
18114		bool use_ixfr = true;
18115		if (peer != NULL) {
18116			result = dns_peer_getrequestixfr(peer, &use_ixfr);
18117		}
18118		if (peer == NULL || result != ISC_R_SUCCESS) {
18119			use_ixfr = zone->requestixfr;
18120		}
18121		if (!use_ixfr) {
18122			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18123				      ISC_LOG_DEBUG(1),
18124				      "IXFR disabled, "
18125				      "requesting %sAXFR from %s",
18126				      soa_before, primary);
18127			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18128				xfrtype = dns_rdatatype_soa;
18129			} else {
18130				xfrtype = dns_rdatatype_axfr;
18131			}
18132		} else {
18133			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18134				      ISC_LOG_DEBUG(1),
18135				      "requesting IXFR from %s", primary);
18136			xfrtype = dns_rdatatype_ixfr;
18137		}
18138	}
18139
18140	/*
18141	 * Determine if we should attempt to sign the request with TSIG.
18142	 */
18143	result = ISC_R_NOTFOUND;
18144
18145	/*
18146	 * First, look for a tsig key in the primaries statement, then
18147	 * try for a server key.
18148	 */
18149	if ((zone->primarykeynames != NULL) &&
18150	    (zone->primarykeynames[zone->curprimary] != NULL))
18151	{
18152		dns_view_t *view = dns_zone_getview(zone);
18153		dns_name_t *keyname = zone->primarykeynames[zone->curprimary];
18154		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
18155	}
18156	if (result != ISC_R_SUCCESS) {
18157		INSIST(zone->tsigkey == NULL);
18158		result = dns_view_getpeertsig(zone->view, &primaryip,
18159					      &zone->tsigkey);
18160	}
18161	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
18162		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
18163			      "could not get TSIG key for zone transfer: %s",
18164			      isc_result_totext(result));
18165	}
18166
18167	/*
18168	 * Get the TLS transport for the primary, if configured.
18169	 */
18170	if ((zone->primarytlsnames != NULL) &&
18171	    (zone->primarytlsnames[zone->curprimary] != NULL))
18172	{
18173		dns_view_t *view = dns_zone_getview(zone);
18174		dns_name_t *tlsname = zone->primarytlsnames[zone->curprimary];
18175		result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
18176					       &zone->transport);
18177		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
18178			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18179				      ISC_LOG_ERROR,
18180				      "could not get TLS configuration for "
18181				      "zone transfer: %s",
18182				      isc_result_totext(result));
18183		}
18184	}
18185
18186	LOCK_ZONE(zone);
18187	primaryaddr = zone->primaryaddr;
18188	sourceaddr = zone->sourceaddr;
18189	UNLOCK_ZONE(zone);
18190	INSIST(isc_sockaddr_pf(&primaryaddr) == isc_sockaddr_pf(&sourceaddr));
18191
18192	if (zone->xfr != NULL) {
18193		dns_xfrin_detach(&zone->xfr);
18194	}
18195
18196	zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
18197
18198	result = dns_xfrin_create(zone, xfrtype, &primaryaddr, &sourceaddr,
18199				  zone->tsigkey, zone->transport,
18200				  zmgr_tlsctx_cache, zone->mctx,
18201				  zone->zmgr->netmgr, zone_xfrdone, &zone->xfr);
18202
18203	isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
18204
18205	/*
18206	 * Any failure in this function is handled like a failed
18207	 * zone transfer.  This ensures that we get removed from
18208	 * zmgr->xfrin_in_progress.
18209	 */
18210	if (result != ISC_R_SUCCESS) {
18211		zone_xfrdone(zone, result);
18212		return;
18213	}
18214
18215	LOCK_ZONE(zone);
18216	if (xfrtype == dns_rdatatype_axfr) {
18217		if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {
18218			inc_stats(zone, dns_zonestatscounter_axfrreqv4);
18219		} else {
18220			inc_stats(zone, dns_zonestatscounter_axfrreqv6);
18221		}
18222	} else if (xfrtype == dns_rdatatype_ixfr) {
18223		if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {
18224			inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
18225		} else {
18226			inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
18227		}
18228	}
18229	UNLOCK_ZONE(zone);
18230}
18231
18232/*
18233 * Update forwarding support.
18234 */
18235
18236static void
18237forward_destroy(dns_forward_t *forward) {
18238	forward->magic = 0;
18239	if (forward->request != NULL) {
18240		dns_request_destroy(&forward->request);
18241	}
18242	if (forward->msgbuf != NULL) {
18243		isc_buffer_free(&forward->msgbuf);
18244	}
18245	if (forward->zone != NULL) {
18246		LOCK(&forward->zone->lock);
18247		if (ISC_LINK_LINKED(forward, link)) {
18248			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
18249		}
18250		UNLOCK(&forward->zone->lock);
18251		dns_zone_idetach(&forward->zone);
18252	}
18253	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
18254}
18255
18256static isc_result_t
18257sendtoprimary(dns_forward_t *forward) {
18258	isc_result_t result;
18259	isc_sockaddr_t src;
18260
18261	LOCK_ZONE(forward->zone);
18262
18263	if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
18264		UNLOCK_ZONE(forward->zone);
18265		return (ISC_R_CANCELED);
18266	}
18267
18268	if (forward->which >= forward->zone->primariescnt) {
18269		UNLOCK_ZONE(forward->zone);
18270		return (ISC_R_NOMORE);
18271	}
18272
18273	forward->addr = forward->zone->primaries[forward->which];
18274	/*
18275	 * Always use TCP regardless of whether the original update
18276	 * used TCP.
18277	 * XXX The timeout may but a bit small if we are far down a
18278	 * transfer graph and have to try several primaries.
18279	 */
18280	switch (isc_sockaddr_pf(&forward->addr)) {
18281	case PF_INET:
18282		src = forward->zone->xfrsource4;
18283		break;
18284	case PF_INET6:
18285		src = forward->zone->xfrsource6;
18286		break;
18287	default:
18288		result = ISC_R_NOTIMPLEMENTED;
18289		goto unlock;
18290	}
18291	result = dns_request_createraw(forward->zone->view->requestmgr,
18292				       forward->msgbuf, &src, &forward->addr,
18293				       forward->options, 15 /* XXX */, 0, 0,
18294				       forward->zone->task, forward_callback,
18295				       forward, &forward->request);
18296	if (result == ISC_R_SUCCESS) {
18297		if (!ISC_LINK_LINKED(forward, link)) {
18298			ISC_LIST_APPEND(forward->zone->forwards, forward, link);
18299		}
18300	}
18301
18302unlock:
18303	UNLOCK_ZONE(forward->zone);
18304	return (result);
18305}
18306
18307static void
18308forward_callback(isc_task_t *task, isc_event_t *event) {
18309	const char me[] = "forward_callback";
18310	dns_requestevent_t *revent = (dns_requestevent_t *)event;
18311	dns_message_t *msg = NULL;
18312	char primary[ISC_SOCKADDR_FORMATSIZE];
18313	isc_result_t result;
18314	dns_forward_t *forward;
18315	dns_zone_t *zone;
18316
18317	UNUSED(task);
18318
18319	forward = revent->ev_arg;
18320	INSIST(DNS_FORWARD_VALID(forward));
18321	zone = forward->zone;
18322	INSIST(DNS_ZONE_VALID(zone));
18323
18324	ENTER;
18325
18326	isc_sockaddr_format(&forward->addr, primary, sizeof(primary));
18327
18328	if (revent->result != ISC_R_SUCCESS) {
18329		dns_zone_log(zone, ISC_LOG_INFO,
18330			     "could not forward dynamic update to %s: %s",
18331			     primary, isc_result_totext(revent->result));
18332		goto next_primary;
18333	}
18334
18335	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
18336
18337	result = dns_request_getresponse(revent->request, msg,
18338					 DNS_MESSAGEPARSE_PRESERVEORDER |
18339						 DNS_MESSAGEPARSE_CLONEBUFFER);
18340	if (result != ISC_R_SUCCESS) {
18341		goto next_primary;
18342	}
18343
18344	/*
18345	 * Unexpected opcode.
18346	 */
18347	if (msg->opcode != dns_opcode_update) {
18348		char opcode[128];
18349		isc_buffer_t rb;
18350
18351		isc_buffer_init(&rb, opcode, sizeof(opcode));
18352		(void)dns_opcode_totext(msg->opcode, &rb);
18353
18354		dns_zone_log(zone, ISC_LOG_INFO,
18355			     "forwarding dynamic update: "
18356			     "unexpected opcode (%.*s) from %s",
18357			     (int)rb.used, opcode, primary);
18358		goto next_primary;
18359	}
18360
18361	switch (msg->rcode) {
18362	/*
18363	 * Pass these rcodes back to client.
18364	 */
18365	case dns_rcode_noerror:
18366	case dns_rcode_yxdomain:
18367	case dns_rcode_yxrrset:
18368	case dns_rcode_nxrrset:
18369	case dns_rcode_refused:
18370	case dns_rcode_nxdomain: {
18371		char rcode[128];
18372		isc_buffer_t rb;
18373
18374		isc_buffer_init(&rb, rcode, sizeof(rcode));
18375		(void)dns_rcode_totext(msg->rcode, &rb);
18376		dns_zone_log(zone, ISC_LOG_INFO,
18377			     "forwarded dynamic update: "
18378			     "primary %s returned: %.*s",
18379			     primary, (int)rb.used, rcode);
18380		break;
18381	}
18382
18383	/* These should not occur if the primaries/zone are valid. */
18384	case dns_rcode_notzone:
18385	case dns_rcode_notauth: {
18386		char rcode[128];
18387		isc_buffer_t rb;
18388
18389		isc_buffer_init(&rb, rcode, sizeof(rcode));
18390		(void)dns_rcode_totext(msg->rcode, &rb);
18391		dns_zone_log(zone, ISC_LOG_WARNING,
18392			     "forwarding dynamic update: "
18393			     "unexpected response: primary %s returned: %.*s",
18394			     primary, (int)rb.used, rcode);
18395		goto next_primary;
18396	}
18397
18398	/* Try another server for these rcodes. */
18399	case dns_rcode_formerr:
18400	case dns_rcode_servfail:
18401	case dns_rcode_notimp:
18402	case dns_rcode_badvers:
18403	default:
18404		goto next_primary;
18405	}
18406
18407	/* call callback */
18408	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
18409	msg = NULL;
18410	dns_request_destroy(&forward->request);
18411	forward_destroy(forward);
18412	isc_event_free(&event);
18413	return;
18414
18415next_primary:
18416	if (msg != NULL) {
18417		dns_message_detach(&msg);
18418	}
18419	isc_event_free(&event);
18420	forward->which++;
18421	dns_request_destroy(&forward->request);
18422	result = sendtoprimary(forward);
18423	if (result != ISC_R_SUCCESS) {
18424		/* call callback */
18425		dns_zone_log(zone, ISC_LOG_DEBUG(3),
18426			     "exhausted dynamic update forwarder list");
18427		(forward->callback)(forward->callback_arg, result, NULL);
18428		forward_destroy(forward);
18429	}
18430}
18431
18432isc_result_t
18433dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
18434		       dns_updatecallback_t callback, void *callback_arg) {
18435	dns_forward_t *forward;
18436	isc_result_t result;
18437	isc_region_t *mr;
18438
18439	REQUIRE(DNS_ZONE_VALID(zone));
18440	REQUIRE(msg != NULL);
18441	REQUIRE(callback != NULL);
18442
18443	forward = isc_mem_get(zone->mctx, sizeof(*forward));
18444
18445	forward->request = NULL;
18446	forward->zone = NULL;
18447	forward->msgbuf = NULL;
18448	forward->which = 0;
18449	forward->mctx = 0;
18450	forward->callback = callback;
18451	forward->callback_arg = callback_arg;
18452	ISC_LINK_INIT(forward, link);
18453	forward->magic = FORWARD_MAGIC;
18454	forward->options = DNS_REQUESTOPT_TCP;
18455	/*
18456	 * If we have a SIG(0) signed message we need to preserve the
18457	 * query id as that is included in the SIG(0) computation.
18458	 */
18459	if (msg->sig0 != NULL) {
18460		forward->options |= DNS_REQUESTOPT_FIXEDID;
18461	}
18462
18463	mr = dns_message_getrawmessage(msg);
18464	if (mr == NULL) {
18465		result = ISC_R_UNEXPECTEDEND;
18466		goto cleanup;
18467	}
18468
18469	isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
18470	result = isc_buffer_copyregion(forward->msgbuf, mr);
18471	if (result != ISC_R_SUCCESS) {
18472		goto cleanup;
18473	}
18474
18475	isc_mem_attach(zone->mctx, &forward->mctx);
18476	dns_zone_iattach(zone, &forward->zone);
18477	result = sendtoprimary(forward);
18478
18479cleanup:
18480	if (result != ISC_R_SUCCESS) {
18481		forward_destroy(forward);
18482	}
18483	return (result);
18484}
18485
18486isc_result_t
18487dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
18488	REQUIRE(DNS_ZONE_VALID(zone));
18489	REQUIRE(next != NULL && *next == NULL);
18490
18491	*next = ISC_LIST_NEXT(zone, link);
18492	if (*next == NULL) {
18493		return (ISC_R_NOMORE);
18494	} else {
18495		return (ISC_R_SUCCESS);
18496	}
18497}
18498
18499isc_result_t
18500dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
18501	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18502	REQUIRE(first != NULL && *first == NULL);
18503
18504	*first = ISC_LIST_HEAD(zmgr->zones);
18505	if (*first == NULL) {
18506		return (ISC_R_NOMORE);
18507	} else {
18508		return (ISC_R_SUCCESS);
18509	}
18510}
18511
18512/***
18513 ***	Zone manager.
18514 ***/
18515
18516#define KEYMGMT_OVERCOMMIT 3
18517#define KEYMGMT_BITS_MIN   2U
18518#define KEYMGMT_BITS_MAX   32U
18519
18520/*
18521 * WMM: Static hash functions copied from lib/dns/rbtdb.c. Should be moved to
18522 * lib/isc/hash.c when we refactor the hash table code.
18523 */
18524#define GOLDEN_RATIO_32 0x61C88647
18525#define HASHSIZE(bits)	(UINT64_C(1) << (bits))
18526
18527static uint32_t
18528hash_index(uint32_t val, uint32_t bits) {
18529	return (val * GOLDEN_RATIO_32 >> (32 - bits));
18530}
18531
18532static uint32_t
18533hash_bits_grow(uint32_t bits, uint32_t count) {
18534	uint32_t newbits = bits;
18535	while (count >= HASHSIZE(newbits) && newbits < KEYMGMT_BITS_MAX) {
18536		newbits++;
18537	}
18538	return (newbits);
18539}
18540
18541static uint32_t
18542hash_bits_shrink(uint32_t bits, uint32_t count) {
18543	uint32_t newbits = bits;
18544	while (count <= HASHSIZE(newbits) && newbits > KEYMGMT_BITS_MIN) {
18545		newbits--;
18546	}
18547	return (newbits);
18548}
18549
18550static void
18551zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) {
18552	dns_keymgmt_t *mgmt = isc_mem_get(zmgr->mctx, sizeof(*mgmt));
18553	uint32_t size;
18554
18555	*mgmt = (dns_keymgmt_t){
18556		.bits = KEYMGMT_BITS_MIN,
18557	};
18558	isc_mem_attach(zmgr->mctx, &mgmt->mctx);
18559	isc_rwlock_init(&mgmt->lock, 0, 0);
18560
18561	size = HASHSIZE(mgmt->bits);
18562	mgmt->table = isc_mem_get(mgmt->mctx, sizeof(*mgmt->table) * size);
18563	memset(mgmt->table, 0, size * sizeof(mgmt->table[0]));
18564
18565	atomic_init(&mgmt->count, 0);
18566	mgmt->magic = KEYMGMT_MAGIC;
18567
18568	zmgr->keymgmt = mgmt;
18569}
18570
18571static void
18572zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) {
18573	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18574	uint32_t size;
18575
18576	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18577
18578	size = HASHSIZE(mgmt->bits);
18579
18580	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18581	INSIST(mgmt->count == 0);
18582	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18583
18584	mgmt->magic = 0;
18585	isc_rwlock_destroy(&mgmt->lock);
18586	isc_mem_put(mgmt->mctx, mgmt->table, size * sizeof(mgmt->table[0]));
18587	isc_mem_putanddetach(&mgmt->mctx, mgmt, sizeof(dns_keymgmt_t));
18588}
18589
18590static void
18591zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) {
18592	dns_keyfileio_t **newtable;
18593	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18594	uint32_t bits, newbits, count, size, newsize;
18595	bool grow;
18596
18597	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18598
18599	RWLOCK(&mgmt->lock, isc_rwlocktype_read);
18600	count = atomic_load_relaxed(&mgmt->count);
18601	bits = mgmt->bits;
18602	RWUNLOCK(&mgmt->lock, isc_rwlocktype_read);
18603
18604	size = HASHSIZE(bits);
18605	INSIST(size > 0);
18606
18607	if (count >= (size * KEYMGMT_OVERCOMMIT)) {
18608		grow = true;
18609	} else if (count < (size / 2)) {
18610		grow = false;
18611	} else {
18612		/* No need to resize. */
18613		return;
18614	}
18615
18616	if (grow) {
18617		newbits = hash_bits_grow(bits, count);
18618	} else {
18619		newbits = hash_bits_shrink(bits, count);
18620	}
18621
18622	if (newbits == bits) {
18623		/*
18624		 * Bit values may stay the same if maximum or minimum is
18625		 * reached.
18626		 */
18627		return;
18628	}
18629
18630	newsize = HASHSIZE(newbits);
18631	INSIST(newsize > 0);
18632
18633	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18634
18635	newtable = isc_mem_get(mgmt->mctx, sizeof(dns_keyfileio_t *) * newsize);
18636	memset(newtable, 0, sizeof(dns_keyfileio_t *) * newsize);
18637
18638	for (unsigned int i = 0; i < size; i++) {
18639		dns_keyfileio_t *kfio, *next;
18640		for (kfio = mgmt->table[i]; kfio != NULL; kfio = next) {
18641			uint32_t hash = hash_index(kfio->hashval, newbits);
18642			next = kfio->next;
18643			kfio->next = newtable[hash];
18644			newtable[hash] = kfio;
18645		}
18646		mgmt->table[i] = NULL;
18647	}
18648
18649	isc_mem_put(mgmt->mctx, mgmt->table, sizeof(*mgmt->table) * size);
18650	mgmt->bits = newbits;
18651	mgmt->table = newtable;
18652
18653	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18654}
18655
18656static void
18657zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
18658		    dns_keyfileio_t **added) {
18659	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18660	uint32_t hashval, hash;
18661	dns_keyfileio_t *kfio, *next;
18662
18663	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18664	REQUIRE(added != NULL && *added == NULL);
18665
18666	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18667
18668	hashval = dns_name_hash(&zone->origin, false);
18669	hash = hash_index(hashval, mgmt->bits);
18670
18671	for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
18672		next = kfio->next;
18673		if (dns_name_equal(kfio->name, &zone->origin)) {
18674			/* Already in table, increment the counter. */
18675			isc_refcount_increment(&kfio->references);
18676			break;
18677		}
18678	}
18679
18680	if (kfio == NULL) {
18681		/* No entry found, add it. */
18682		kfio = isc_mem_get(mgmt->mctx, sizeof(*kfio));
18683		*kfio = (dns_keyfileio_t){
18684			.hashval = hashval,
18685			.next = mgmt->table[hash],
18686			.magic = KEYFILEIO_MAGIC,
18687		};
18688
18689		isc_refcount_init(&kfio->references, 1);
18690
18691		kfio->name = dns_fixedname_initname(&kfio->fname);
18692		dns_name_copy(&zone->origin, kfio->name);
18693
18694		isc_mutex_init(&kfio->lock);
18695
18696		mgmt->table[hash] = kfio;
18697
18698		atomic_fetch_add_relaxed(&mgmt->count, 1);
18699	}
18700
18701	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18702
18703	*added = kfio;
18704
18705	/*
18706	 * Call resize, that function will also check if resize is necessary.
18707	 */
18708	zonemgr_keymgmt_resize(zmgr);
18709}
18710
18711static void
18712zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_zone_t *zone,
18713		       dns_keyfileio_t **deleted) {
18714	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18715	uint32_t hashval, hash;
18716	dns_keyfileio_t *kfio, *prev, *next;
18717
18718	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18719	REQUIRE(deleted != NULL && DNS_KEYFILEIO_VALID(*deleted));
18720
18721	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18722
18723	hashval = dns_name_hash(&zone->origin, false);
18724	hash = hash_index(hashval, mgmt->bits);
18725
18726	prev = NULL;
18727	for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
18728		next = kfio->next;
18729		if (dns_name_equal(kfio->name, &zone->origin)) {
18730			INSIST(kfio == *deleted);
18731			*deleted = NULL;
18732
18733			if (isc_refcount_decrement(&kfio->references) == 1) {
18734				if (prev == NULL) {
18735					mgmt->table[hash] = kfio->next;
18736				} else {
18737					prev->next = kfio->next;
18738				}
18739
18740				isc_refcount_destroy(&kfio->references);
18741				isc_mutex_destroy(&kfio->lock);
18742				isc_mem_put(mgmt->mctx, kfio, sizeof(*kfio));
18743
18744				atomic_fetch_sub_relaxed(&mgmt->count, 1);
18745			}
18746			break;
18747		}
18748
18749		prev = kfio;
18750	}
18751
18752	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18753
18754	/*
18755	 * Call resize, that function will also check if resize is necessary.
18756	 */
18757	zonemgr_keymgmt_resize(zmgr);
18758}
18759
18760isc_result_t
18761dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
18762		   isc_timermgr_t *timermgr, isc_nm_t *netmgr,
18763		   dns_zonemgr_t **zmgrp) {
18764	dns_zonemgr_t *zmgr;
18765	isc_result_t result;
18766
18767	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
18768	zmgr->mctx = NULL;
18769	isc_refcount_init(&zmgr->refs, 1);
18770	isc_mem_attach(mctx, &zmgr->mctx);
18771	zmgr->taskmgr = taskmgr;
18772	zmgr->timermgr = timermgr;
18773	zmgr->netmgr = netmgr;
18774	zmgr->zonetasks = NULL;
18775	zmgr->loadtasks = NULL;
18776	zmgr->mctxpool = NULL;
18777	zmgr->task = NULL;
18778	zmgr->checkdsrl = NULL;
18779	zmgr->notifyrl = NULL;
18780	zmgr->refreshrl = NULL;
18781	zmgr->startupnotifyrl = NULL;
18782	zmgr->startuprefreshrl = NULL;
18783	ISC_LIST_INIT(zmgr->zones);
18784	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
18785	ISC_LIST_INIT(zmgr->xfrin_in_progress);
18786	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
18787	for (size_t i = 0; i < UNREACH_CACHE_SIZE; i++) {
18788		atomic_init(&zmgr->unreachable[i].expire, 0);
18789	}
18790	isc_rwlock_init(&zmgr->rwlock, 0, 0);
18791
18792	zmgr->transfersin = 10;
18793	zmgr->transfersperns = 2;
18794
18795	/* Unreachable lock. */
18796	isc_rwlock_init(&zmgr->urlock, 0, 0);
18797
18798	/* Create a single task for queueing of SOA queries. */
18799	result = isc_task_create(taskmgr, 1, &zmgr->task);
18800	if (result != ISC_R_SUCCESS) {
18801		goto free_urlock;
18802	}
18803
18804	isc_task_setname(zmgr->task, "zmgr", zmgr);
18805	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18806					&zmgr->checkdsrl);
18807	if (result != ISC_R_SUCCESS) {
18808		goto free_task;
18809	}
18810
18811	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18812					&zmgr->notifyrl);
18813	if (result != ISC_R_SUCCESS) {
18814		goto free_checkdsrl;
18815	}
18816
18817	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18818					&zmgr->refreshrl);
18819	if (result != ISC_R_SUCCESS) {
18820		goto free_notifyrl;
18821	}
18822
18823	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18824					&zmgr->startupnotifyrl);
18825	if (result != ISC_R_SUCCESS) {
18826		goto free_refreshrl;
18827	}
18828
18829	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18830					&zmgr->startuprefreshrl);
18831	if (result != ISC_R_SUCCESS) {
18832		goto free_startupnotifyrl;
18833	}
18834
18835	/* Key file I/O locks. */
18836	zonemgr_keymgmt_init(zmgr);
18837
18838	/* Default to 20 refresh queries / notifies / checkds per second. */
18839	setrl(zmgr->checkdsrl, &zmgr->checkdsrate, 20);
18840	setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
18841	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
18842	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
18843	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
18844	isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
18845	isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
18846
18847	zmgr->iolimit = 1;
18848	zmgr->ioactive = 0;
18849	ISC_LIST_INIT(zmgr->high);
18850	ISC_LIST_INIT(zmgr->low);
18851
18852	isc_mutex_init(&zmgr->iolock);
18853
18854	zmgr->tlsctx_cache = NULL;
18855	isc_rwlock_init(&zmgr->tlsctx_cache_rwlock, 0, 0);
18856
18857	zmgr->magic = ZONEMGR_MAGIC;
18858
18859	*zmgrp = zmgr;
18860	return (ISC_R_SUCCESS);
18861
18862#if 0
18863 free_iolock:
18864	isc_mutex_destroy(&zmgr->iolock);
18865#endif /* if 0 */
18866free_startupnotifyrl:
18867	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
18868free_refreshrl:
18869	isc_ratelimiter_detach(&zmgr->refreshrl);
18870free_notifyrl:
18871	isc_ratelimiter_detach(&zmgr->notifyrl);
18872free_checkdsrl:
18873	isc_ratelimiter_detach(&zmgr->checkdsrl);
18874free_task:
18875	isc_task_detach(&zmgr->task);
18876free_urlock:
18877	isc_rwlock_destroy(&zmgr->urlock);
18878	isc_rwlock_destroy(&zmgr->rwlock);
18879	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
18880	isc_mem_detach(&mctx);
18881	return (result);
18882}
18883
18884isc_result_t
18885dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
18886	isc_result_t result;
18887	isc_mem_t *mctx = NULL;
18888	dns_zone_t *zone = NULL;
18889	void *item;
18890
18891	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18892	REQUIRE(zonep != NULL && *zonep == NULL);
18893
18894	if (zmgr->mctxpool == NULL) {
18895		return (ISC_R_FAILURE);
18896	}
18897
18898	item = isc_pool_get(zmgr->mctxpool);
18899	if (item == NULL) {
18900		return (ISC_R_FAILURE);
18901	}
18902
18903	isc_mem_attach((isc_mem_t *)item, &mctx);
18904	result = dns_zone_create(&zone, mctx);
18905	isc_mem_detach(&mctx);
18906
18907	if (result == ISC_R_SUCCESS) {
18908		*zonep = zone;
18909	}
18910
18911	return (result);
18912}
18913
18914isc_result_t
18915dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18916	isc_result_t result;
18917
18918	REQUIRE(DNS_ZONE_VALID(zone));
18919	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18920
18921	if (zmgr->zonetasks == NULL) {
18922		return (ISC_R_FAILURE);
18923	}
18924
18925	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18926	LOCK_ZONE(zone);
18927	REQUIRE(zone->task == NULL);
18928	REQUIRE(zone->timer == NULL);
18929	REQUIRE(zone->zmgr == NULL);
18930
18931	isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
18932	isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
18933
18934	/*
18935	 * Set the task name.  The tag will arbitrarily point to one
18936	 * of the zones sharing the task (in practice, the one
18937	 * to be managed last).
18938	 */
18939	isc_task_setname(zone->task, "zone", zone);
18940	isc_task_setname(zone->loadtask, "loadzone", zone);
18941
18942	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
18943				  NULL, zone->task, zone_timer, zone,
18944				  &zone->timer);
18945
18946	if (result != ISC_R_SUCCESS) {
18947		goto cleanup_tasks;
18948	}
18949
18950	/*
18951	 * The timer "holds" a iref.
18952	 */
18953	isc_refcount_increment0(&zone->irefs);
18954
18955	zonemgr_keymgmt_add(zmgr, zone, &zone->kfio);
18956	INSIST(zone->kfio != NULL);
18957
18958	ISC_LIST_APPEND(zmgr->zones, zone, link);
18959	zone->zmgr = zmgr;
18960	isc_refcount_increment(&zmgr->refs);
18961
18962	goto unlock;
18963
18964cleanup_tasks:
18965	isc_task_detach(&zone->loadtask);
18966	isc_task_detach(&zone->task);
18967
18968unlock:
18969	UNLOCK_ZONE(zone);
18970	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18971	return (result);
18972}
18973
18974void
18975dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18976	REQUIRE(DNS_ZONE_VALID(zone));
18977	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18978	REQUIRE(zone->zmgr == zmgr);
18979
18980	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18981	LOCK_ZONE(zone);
18982
18983	ISC_LIST_UNLINK(zmgr->zones, zone, link);
18984
18985	if (zone->kfio != NULL) {
18986		zonemgr_keymgmt_delete(zmgr, zone, &zone->kfio);
18987		ENSURE(zone->kfio == NULL);
18988	}
18989
18990	/* Detach below, outside of the write lock. */
18991	zone->zmgr = NULL;
18992
18993	UNLOCK_ZONE(zone);
18994	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18995
18996	dns_zonemgr_detach(&zmgr);
18997}
18998
18999void
19000dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
19001	REQUIRE(DNS_ZONEMGR_VALID(source));
19002	REQUIRE(target != NULL && *target == NULL);
19003
19004	isc_refcount_increment(&source->refs);
19005
19006	*target = source;
19007}
19008
19009void
19010dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
19011	dns_zonemgr_t *zmgr;
19012
19013	REQUIRE(zmgrp != NULL);
19014	zmgr = *zmgrp;
19015	*zmgrp = NULL;
19016	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19017
19018	if (isc_refcount_decrement(&zmgr->refs) == 1) {
19019		zonemgr_free(zmgr);
19020	}
19021}
19022
19023isc_result_t
19024dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
19025	dns_zone_t *p;
19026
19027	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19028
19029	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19030	for (p = ISC_LIST_HEAD(zmgr->zones); p != NULL;
19031	     p = ISC_LIST_NEXT(p, link))
19032	{
19033		dns_zone_maintenance(p);
19034	}
19035	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19036
19037	/*
19038	 * Recent configuration changes may have increased the
19039	 * amount of available transfers quota.  Make sure any
19040	 * transfers currently blocked on quota get started if
19041	 * possible.
19042	 */
19043	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19044	zmgr_resume_xfrs(zmgr, true);
19045	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19046	return (ISC_R_SUCCESS);
19047}
19048
19049void
19050dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
19051	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19052
19053	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19054	zmgr_resume_xfrs(zmgr, true);
19055	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19056}
19057
19058void
19059dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
19060	dns_zone_t *zone;
19061
19062	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19063
19064	isc_ratelimiter_shutdown(zmgr->checkdsrl);
19065	isc_ratelimiter_shutdown(zmgr->notifyrl);
19066	isc_ratelimiter_shutdown(zmgr->refreshrl);
19067	isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
19068	isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
19069
19070	if (zmgr->task != NULL) {
19071		isc_task_destroy(&zmgr->task);
19072	}
19073	if (zmgr->zonetasks != NULL) {
19074		isc_taskpool_destroy(&zmgr->zonetasks);
19075	}
19076	if (zmgr->loadtasks != NULL) {
19077		isc_taskpool_destroy(&zmgr->loadtasks);
19078	}
19079	if (zmgr->mctxpool != NULL) {
19080		isc_pool_destroy(&zmgr->mctxpool);
19081	}
19082
19083	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19084	for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19085	     zone = ISC_LIST_NEXT(zone, link))
19086	{
19087		LOCK_ZONE(zone);
19088		forward_cancel(zone);
19089		UNLOCK_ZONE(zone);
19090	}
19091	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19092}
19093
19094static isc_result_t
19095mctxinit(void **target, void *arg) {
19096	isc_mem_t *mctx = NULL;
19097
19098	UNUSED(arg);
19099
19100	REQUIRE(target != NULL && *target == NULL);
19101
19102	isc_mem_create(&mctx);
19103	isc_mem_setname(mctx, "zonemgr-pool");
19104
19105	*target = mctx;
19106	return (ISC_R_SUCCESS);
19107}
19108
19109static void
19110mctxfree(void **target) {
19111	isc_mem_t *mctx = *(isc_mem_t **)target;
19112	isc_mem_detach(&mctx);
19113	*target = NULL;
19114}
19115
19116#define ZONES_PER_TASK 100
19117#define ZONES_PER_MCTX 1000
19118
19119isc_result_t
19120dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
19121	isc_result_t result;
19122	int ntasks = num_zones / ZONES_PER_TASK;
19123	int nmctx = num_zones / ZONES_PER_MCTX;
19124	isc_taskpool_t *pool = NULL;
19125	isc_pool_t *mctxpool = NULL;
19126
19127	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19128
19129	/*
19130	 * For anything fewer than 1000 zones we use 10 tasks in
19131	 * the task pools.  More than that, and we'll scale at one
19132	 * task per 100 zones.  Similarly, for anything smaller than
19133	 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
19134	 */
19135	if (ntasks < 10) {
19136		ntasks = 10;
19137	}
19138	if (nmctx < 2) {
19139		nmctx = 2;
19140	}
19141
19142	/* Create or resize the zone task pools. */
19143	if (zmgr->zonetasks == NULL) {
19144		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
19145					     2, false, &pool);
19146	} else {
19147		result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, false,
19148					     &pool);
19149	}
19150
19151	if (result == ISC_R_SUCCESS) {
19152		zmgr->zonetasks = pool;
19153	}
19154
19155	/*
19156	 * We always set all tasks in the zone-load task pool to
19157	 * privileged.  This prevents other tasks in the system from
19158	 * running while the server task manager is in privileged
19159	 * mode.
19160	 */
19161	pool = NULL;
19162	if (zmgr->loadtasks == NULL) {
19163		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
19164					     UINT_MAX, true, &pool);
19165	} else {
19166		result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, true,
19167					     &pool);
19168	}
19169
19170	if (result == ISC_R_SUCCESS) {
19171		zmgr->loadtasks = pool;
19172	}
19173
19174	/* Create or resize the zone memory context pool. */
19175	if (zmgr->mctxpool == NULL) {
19176		result = isc_pool_create(zmgr->mctx, nmctx, mctxfree, mctxinit,
19177					 NULL, &mctxpool);
19178	} else {
19179		result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
19180	}
19181
19182	if (result == ISC_R_SUCCESS) {
19183		zmgr->mctxpool = mctxpool;
19184	}
19185
19186	return (result);
19187}
19188
19189static void
19190zonemgr_free(dns_zonemgr_t *zmgr) {
19191	isc_mem_t *mctx;
19192
19193	INSIST(ISC_LIST_EMPTY(zmgr->zones));
19194
19195	zmgr->magic = 0;
19196
19197	isc_refcount_destroy(&zmgr->refs);
19198	isc_mutex_destroy(&zmgr->iolock);
19199	isc_ratelimiter_detach(&zmgr->checkdsrl);
19200	isc_ratelimiter_detach(&zmgr->notifyrl);
19201	isc_ratelimiter_detach(&zmgr->refreshrl);
19202	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
19203	isc_ratelimiter_detach(&zmgr->startuprefreshrl);
19204
19205	isc_rwlock_destroy(&zmgr->urlock);
19206	isc_rwlock_destroy(&zmgr->rwlock);
19207	isc_rwlock_destroy(&zmgr->tlsctx_cache_rwlock);
19208
19209	zonemgr_keymgmt_destroy(zmgr);
19210
19211	mctx = zmgr->mctx;
19212	if (zmgr->tlsctx_cache != NULL) {
19213		isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
19214	}
19215	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
19216	isc_mem_detach(&mctx);
19217}
19218
19219void
19220dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
19221	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19222
19223	zmgr->transfersin = value;
19224}
19225
19226uint32_t
19227dns_zonemgr_gettransfersin(dns_zonemgr_t *zmgr) {
19228	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19229
19230	return (zmgr->transfersin);
19231}
19232
19233void
19234dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
19235	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19236
19237	zmgr->transfersperns = value;
19238}
19239
19240uint32_t
19241dns_zonemgr_gettransfersperns(dns_zonemgr_t *zmgr) {
19242	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19243
19244	return (zmgr->transfersperns);
19245}
19246
19247isc_taskmgr_t *
19248dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr) {
19249	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19250
19251	return (zmgr->taskmgr);
19252}
19253
19254isc_timermgr_t *
19255dns_zonemgr_gettimermgr(dns_zonemgr_t *zmgr) {
19256	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19257
19258	return (zmgr->timermgr);
19259}
19260
19261/*
19262 * Try to start a new incoming zone transfer to fill a quota
19263 * slot that was just vacated.
19264 *
19265 * Requires:
19266 *	The zone manager is locked by the caller.
19267 */
19268static void
19269zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
19270	dns_zone_t *zone;
19271	dns_zone_t *next;
19272
19273	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); zone != NULL;
19274	     zone = next)
19275	{
19276		isc_result_t result;
19277		next = ISC_LIST_NEXT(zone, statelink);
19278		result = zmgr_start_xfrin_ifquota(zmgr, zone);
19279		if (result == ISC_R_SUCCESS) {
19280			if (multi) {
19281				continue;
19282			}
19283			/*
19284			 * We successfully filled the slot.  We're done.
19285			 */
19286			break;
19287		} else if (result == ISC_R_QUOTA) {
19288			/*
19289			 * Not enough quota.  This is probably the per-server
19290			 * quota, because we usually get called when a unit of
19291			 * global quota has just been freed.  Try the next
19292			 * zone, it may succeed if it uses another primary.
19293			 */
19294			continue;
19295		} else {
19296			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
19297				      ISC_LOG_DEBUG(1),
19298				      "starting zone transfer: %s",
19299				      isc_result_totext(result));
19300			break;
19301		}
19302	}
19303}
19304
19305/*
19306 * Try to start an incoming zone transfer for 'zone', quota permitting.
19307 *
19308 * Requires:
19309 *	The zone manager is locked by the caller.
19310 *
19311 * Returns:
19312 *	ISC_R_SUCCESS	There was enough quota and we attempted to
19313 *			start a transfer.  zone_xfrdone() has been or will
19314 *			be called.
19315 *	ISC_R_QUOTA	Not enough quota.
19316 *	Others		Failure.
19317 */
19318static isc_result_t
19319zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
19320	dns_peer_t *peer = NULL;
19321	isc_netaddr_t primaryip;
19322	uint32_t nxfrsin, nxfrsperns;
19323	dns_zone_t *x;
19324	uint32_t maxtransfersin, maxtransfersperns;
19325	isc_event_t *e;
19326
19327	/*
19328	 * If we are exiting just pretend we got quota so the zone will
19329	 * be cleaned up in the zone's task context.
19330	 */
19331	LOCK_ZONE(zone);
19332	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
19333		UNLOCK_ZONE(zone);
19334		goto gotquota;
19335	}
19336
19337	/*
19338	 * Find any configured information about the server we'd
19339	 * like to transfer this zone from.
19340	 */
19341	isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr);
19342	(void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer);
19343	UNLOCK_ZONE(zone);
19344
19345	/*
19346	 * Determine the total maximum number of simultaneous
19347	 * transfers allowed, and the maximum for this specific
19348	 * primary.
19349	 */
19350	maxtransfersin = zmgr->transfersin;
19351	maxtransfersperns = zmgr->transfersperns;
19352	if (peer != NULL) {
19353		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
19354	}
19355
19356	/*
19357	 * Count the total number of transfers that are in progress,
19358	 * and the number of transfers in progress from this primary.
19359	 * We linearly scan a list of all transfers; if this turns
19360	 * out to be too slow, we could hash on the primary address.
19361	 */
19362	nxfrsin = nxfrsperns = 0;
19363	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); x != NULL;
19364	     x = ISC_LIST_NEXT(x, statelink))
19365	{
19366		isc_netaddr_t xip;
19367
19368		LOCK_ZONE(x);
19369		isc_netaddr_fromsockaddr(&xip, &x->primaryaddr);
19370		UNLOCK_ZONE(x);
19371
19372		nxfrsin++;
19373		if (isc_netaddr_equal(&xip, &primaryip)) {
19374			nxfrsperns++;
19375		}
19376	}
19377
19378	/* Enforce quota. */
19379	if (nxfrsin >= maxtransfersin) {
19380		return (ISC_R_QUOTA);
19381	}
19382
19383	if (nxfrsperns >= maxtransfersperns) {
19384		return (ISC_R_QUOTA);
19385	}
19386
19387gotquota:
19388	/*
19389	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
19390	 * list and send it an event to let it start the actual transfer in the
19391	 * context of its own task.
19392	 */
19393	e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
19394			       got_transfer_quota, zone, sizeof(isc_event_t));
19395
19396	LOCK_ZONE(zone);
19397	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
19398	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
19399	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
19400	zone->statelist = &zmgr->xfrin_in_progress;
19401	isc_task_send(zone->task, &e);
19402	dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
19403		      "Transfer started.");
19404	UNLOCK_ZONE(zone);
19405
19406	return (ISC_R_SUCCESS);
19407}
19408
19409void
19410dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
19411	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19412	REQUIRE(iolimit > 0);
19413
19414	zmgr->iolimit = iolimit;
19415}
19416
19417uint32_t
19418dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
19419	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19420
19421	return (zmgr->iolimit);
19422}
19423
19424/*
19425 * Get permission to request a file handle from the OS.
19426 * An event will be sent to action when one is available.
19427 * There are two queues available (high and low), the high
19428 * queue will be serviced before the low one.
19429 *
19430 * zonemgr_putio() must be called after the event is delivered to
19431 * 'action'.
19432 */
19433
19434static isc_result_t
19435zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
19436	      isc_taskaction_t action, void *arg, dns_io_t **iop) {
19437	dns_io_t *io;
19438	bool queue;
19439
19440	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19441	REQUIRE(iop != NULL && *iop == NULL);
19442
19443	io = isc_mem_get(zmgr->mctx, sizeof(*io));
19444
19445	io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
19446				       action, arg, sizeof(*io->event));
19447
19448	io->zmgr = zmgr;
19449	io->high = high;
19450	io->task = NULL;
19451	isc_task_attach(task, &io->task);
19452	ISC_LINK_INIT(io, link);
19453	io->magic = IO_MAGIC;
19454
19455	LOCK(&zmgr->iolock);
19456	zmgr->ioactive++;
19457	queue = (zmgr->ioactive > zmgr->iolimit);
19458	if (queue) {
19459		if (io->high) {
19460			ISC_LIST_APPEND(zmgr->high, io, link);
19461		} else {
19462			ISC_LIST_APPEND(zmgr->low, io, link);
19463		}
19464	}
19465	UNLOCK(&zmgr->iolock);
19466	*iop = io;
19467
19468	if (!queue) {
19469		isc_task_send(io->task, &io->event);
19470	}
19471	return (ISC_R_SUCCESS);
19472}
19473
19474static void
19475zonemgr_putio(dns_io_t **iop) {
19476	dns_io_t *io;
19477	dns_io_t *next;
19478	dns_zonemgr_t *zmgr;
19479
19480	REQUIRE(iop != NULL);
19481	io = *iop;
19482	*iop = NULL;
19483	REQUIRE(DNS_IO_VALID(io));
19484
19485	INSIST(!ISC_LINK_LINKED(io, link));
19486	INSIST(io->event == NULL);
19487
19488	zmgr = io->zmgr;
19489	isc_task_detach(&io->task);
19490	io->magic = 0;
19491	isc_mem_put(zmgr->mctx, io, sizeof(*io));
19492
19493	LOCK(&zmgr->iolock);
19494	INSIST(zmgr->ioactive > 0);
19495	zmgr->ioactive--;
19496	next = HEAD(zmgr->high);
19497	if (next == NULL) {
19498		next = HEAD(zmgr->low);
19499	}
19500	if (next != NULL) {
19501		if (next->high) {
19502			ISC_LIST_UNLINK(zmgr->high, next, link);
19503		} else {
19504			ISC_LIST_UNLINK(zmgr->low, next, link);
19505		}
19506		INSIST(next->event != NULL);
19507	}
19508	UNLOCK(&zmgr->iolock);
19509	if (next != NULL) {
19510		isc_task_send(next->task, &next->event);
19511	}
19512}
19513
19514static void
19515zonemgr_cancelio(dns_io_t *io) {
19516	bool send_event = false;
19517
19518	REQUIRE(DNS_IO_VALID(io));
19519
19520	/*
19521	 * If we are queued to be run then dequeue.
19522	 */
19523	LOCK(&io->zmgr->iolock);
19524	if (ISC_LINK_LINKED(io, link)) {
19525		if (io->high) {
19526			ISC_LIST_UNLINK(io->zmgr->high, io, link);
19527		} else {
19528			ISC_LIST_UNLINK(io->zmgr->low, io, link);
19529		}
19530
19531		send_event = true;
19532		INSIST(io->event != NULL);
19533	}
19534	UNLOCK(&io->zmgr->iolock);
19535	if (send_event) {
19536		io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
19537		isc_task_send(io->task, &io->event);
19538	}
19539}
19540
19541static void
19542zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
19543	char *buf;
19544	int buflen;
19545	isc_result_t result;
19546
19547	buflen = strlen(path) + strlen(templat) + 2;
19548
19549	buf = isc_mem_get(zone->mctx, buflen);
19550
19551	result = isc_file_template(path, templat, buf, buflen);
19552	if (result != ISC_R_SUCCESS) {
19553		goto cleanup;
19554	}
19555
19556	result = isc_file_renameunique(path, buf);
19557	if (result != ISC_R_SUCCESS) {
19558		goto cleanup;
19559	}
19560
19561	dns_zone_log(zone, ISC_LOG_WARNING,
19562		     "unable to load from '%s'; "
19563		     "renaming file to '%s' for failure analysis and "
19564		     "retransferring.",
19565		     path, buf);
19566
19567cleanup:
19568	isc_mem_put(zone->mctx, buf, buflen);
19569}
19570
19571static void
19572setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
19573	isc_interval_t interval;
19574	uint32_t s, ns;
19575	uint32_t pertic;
19576	isc_result_t result;
19577
19578	if (value == 0) {
19579		value = 1;
19580	}
19581
19582	if (value == 1) {
19583		s = 1;
19584		ns = 0;
19585		pertic = 1;
19586	} else if (value <= 10) {
19587		s = 0;
19588		ns = 1000000000 / value;
19589		pertic = 1;
19590	} else {
19591		s = 0;
19592		ns = (1000000000 / value) * 10;
19593		pertic = 10;
19594	}
19595
19596	isc_interval_set(&interval, s, ns);
19597
19598	result = isc_ratelimiter_setinterval(rl, &interval);
19599	RUNTIME_CHECK(result == ISC_R_SUCCESS);
19600	isc_ratelimiter_setpertic(rl, pertic);
19601
19602	*rate = value;
19603}
19604
19605void
19606dns_zonemgr_setcheckdsrate(dns_zonemgr_t *zmgr, unsigned int value) {
19607	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19608
19609	setrl(zmgr->checkdsrl, &zmgr->checkdsrate, value);
19610}
19611
19612void
19613dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19614	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19615
19616	setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
19617}
19618
19619void
19620dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19621	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19622
19623	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
19624}
19625
19626void
19627dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
19628	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19629
19630	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
19631	/* XXXMPA separate out once we have the code to support this. */
19632	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
19633}
19634
19635unsigned int
19636dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
19637	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19638
19639	return (zmgr->notifyrate);
19640}
19641
19642unsigned int
19643dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
19644	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19645
19646	return (zmgr->startupnotifyrate);
19647}
19648
19649unsigned int
19650dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
19651	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19652
19653	return (zmgr->serialqueryrate);
19654}
19655
19656bool
19657dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19658			isc_sockaddr_t *local, isc_time_t *now) {
19659	unsigned int i;
19660	uint32_t seconds = isc_time_seconds(now);
19661	uint32_t count = 0;
19662
19663	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19664
19665	RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19666	for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19667		if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
19668		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19669		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19670		{
19671			atomic_store_relaxed(&zmgr->unreachable[i].last,
19672					     seconds);
19673			count = zmgr->unreachable[i].count;
19674			break;
19675		}
19676	}
19677	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19678	return (i < UNREACH_CACHE_SIZE && count > 1U);
19679}
19680
19681void
19682dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19683			   isc_sockaddr_t *local) {
19684	unsigned int i;
19685	char primary[ISC_SOCKADDR_FORMATSIZE];
19686	char source[ISC_SOCKADDR_FORMATSIZE];
19687
19688	isc_sockaddr_format(remote, primary, sizeof(primary));
19689	isc_sockaddr_format(local, source, sizeof(source));
19690
19691	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19692
19693	RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19694	for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19695		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19696		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19697		{
19698			atomic_store_relaxed(&zmgr->unreachable[i].expire, 0);
19699			break;
19700		}
19701	}
19702	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19703}
19704
19705void
19706dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19707			   isc_sockaddr_t *local, isc_time_t *now) {
19708	uint32_t seconds = isc_time_seconds(now);
19709	uint32_t expire = 0, last = seconds;
19710	unsigned int slot = UNREACH_CACHE_SIZE, oldest = 0;
19711	bool update_entry = true;
19712	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19713
19714	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
19715	for (unsigned int i = 0; i < UNREACH_CACHE_SIZE; i++) {
19716		/* Existing entry? */
19717		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19718		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19719		{
19720			update_entry = false;
19721			slot = i;
19722			expire = atomic_load_relaxed(
19723				&zmgr->unreachable[i].expire);
19724			break;
19725		}
19726		/* Pick first empty slot? */
19727		if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds)
19728		{
19729			slot = i;
19730			break;
19731		}
19732		/* The worst case, least recently used slot? */
19733		if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
19734			last = atomic_load_relaxed(&zmgr->unreachable[i].last);
19735			oldest = i;
19736		}
19737	}
19738
19739	/* We haven't found any existing or free slots, use the oldest */
19740	if (slot == UNREACH_CACHE_SIZE) {
19741		slot = oldest;
19742	}
19743
19744	if (expire < seconds) {
19745		/* Expired or new entry, reset count to 1 */
19746		zmgr->unreachable[slot].count = 1;
19747	} else {
19748		zmgr->unreachable[slot].count++;
19749	}
19750	atomic_store_relaxed(&zmgr->unreachable[slot].expire,
19751			     seconds + UNREACH_HOLD_TIME);
19752	atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
19753	if (update_entry) {
19754		zmgr->unreachable[slot].remote = *remote;
19755		zmgr->unreachable[slot].local = *local;
19756	}
19757
19758	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
19759}
19760
19761void
19762dns_zone_forcereload(dns_zone_t *zone) {
19763	REQUIRE(DNS_ZONE_VALID(zone));
19764
19765	if (zone->type == dns_zone_primary ||
19766	    (zone->type == dns_zone_redirect && zone->primaries == NULL))
19767	{
19768		return;
19769	}
19770
19771	LOCK_ZONE(zone);
19772	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
19773	UNLOCK_ZONE(zone);
19774	dns_zone_refresh(zone);
19775}
19776
19777bool
19778dns_zone_isforced(dns_zone_t *zone) {
19779	REQUIRE(DNS_ZONE_VALID(zone));
19780
19781	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
19782}
19783
19784isc_result_t
19785dns_zone_setstatistics(dns_zone_t *zone, bool on) {
19786	/*
19787	 * This function is obsoleted.
19788	 */
19789	UNUSED(zone);
19790	UNUSED(on);
19791	return (ISC_R_NOTIMPLEMENTED);
19792}
19793
19794uint64_t *
19795dns_zone_getstatscounters(dns_zone_t *zone) {
19796	/*
19797	 * This function is obsoleted.
19798	 */
19799	UNUSED(zone);
19800	return (NULL);
19801}
19802
19803void
19804dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
19805	REQUIRE(DNS_ZONE_VALID(zone));
19806	REQUIRE(zone->stats == NULL);
19807
19808	LOCK_ZONE(zone);
19809	zone->stats = NULL;
19810	isc_stats_attach(stats, &zone->stats);
19811	UNLOCK_ZONE(zone);
19812}
19813
19814void
19815dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
19816	REQUIRE(DNS_ZONE_VALID(zone));
19817
19818	LOCK_ZONE(zone);
19819	if (zone->requeststats_on && stats == NULL) {
19820		zone->requeststats_on = false;
19821	} else if (!zone->requeststats_on && stats != NULL) {
19822		if (zone->requeststats == NULL) {
19823			isc_stats_attach(stats, &zone->requeststats);
19824		}
19825		zone->requeststats_on = true;
19826	}
19827	UNLOCK_ZONE(zone);
19828}
19829
19830void
19831dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
19832	REQUIRE(DNS_ZONE_VALID(zone));
19833
19834	LOCK_ZONE(zone);
19835	if (zone->requeststats_on && stats != NULL) {
19836		if (zone->rcvquerystats == NULL) {
19837			dns_stats_attach(stats, &zone->rcvquerystats);
19838			zone->requeststats_on = true;
19839		}
19840	}
19841	UNLOCK_ZONE(zone);
19842}
19843
19844void
19845dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
19846	REQUIRE(DNS_ZONE_VALID(zone));
19847
19848	LOCK_ZONE(zone);
19849	if (stats != NULL && zone->dnssecsignstats == NULL) {
19850		dns_stats_attach(stats, &zone->dnssecsignstats);
19851	}
19852	UNLOCK_ZONE(zone);
19853}
19854
19855dns_stats_t *
19856dns_zone_getdnssecsignstats(dns_zone_t *zone) {
19857	REQUIRE(DNS_ZONE_VALID(zone));
19858
19859	return (zone->dnssecsignstats);
19860}
19861
19862isc_stats_t *
19863dns_zone_getrequeststats(dns_zone_t *zone) {
19864	/*
19865	 * We don't lock zone for efficiency reason.  This is not catastrophic
19866	 * because requeststats must always be valid when requeststats_on is
19867	 * true.
19868	 * Some counters may be incremented while requeststats_on is becoming
19869	 * false, or some cannot be incremented just after the statistics are
19870	 * installed, but it shouldn't matter much in practice.
19871	 */
19872	if (zone->requeststats_on) {
19873		return (zone->requeststats);
19874	} else {
19875		return (NULL);
19876	}
19877}
19878
19879/*
19880 * Return the received query stats bucket
19881 * see note from dns_zone_getrequeststats()
19882 */
19883dns_stats_t *
19884dns_zone_getrcvquerystats(dns_zone_t *zone) {
19885	if (zone->requeststats_on) {
19886		return (zone->rcvquerystats);
19887	} else {
19888		return (NULL);
19889	}
19890}
19891
19892void
19893dns_zone_dialup(dns_zone_t *zone) {
19894	REQUIRE(DNS_ZONE_VALID(zone));
19895
19896	zone_debuglog(zone, "dns_zone_dialup", 3, "notify = %d, refresh = %d",
19897		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
19898		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
19899
19900	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
19901		dns_zone_notify(zone);
19902	}
19903	if (zone->type != dns_zone_primary && zone->primaries != NULL &&
19904	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
19905	{
19906		dns_zone_refresh(zone);
19907	}
19908}
19909
19910void
19911dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
19912	REQUIRE(DNS_ZONE_VALID(zone));
19913
19914	LOCK_ZONE(zone);
19915	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
19916				       DNS_ZONEFLG_DIALREFRESH |
19917				       DNS_ZONEFLG_NOREFRESH);
19918	switch (dialup) {
19919	case dns_dialuptype_no:
19920		break;
19921	case dns_dialuptype_yes:
19922		DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
19923					DNS_ZONEFLG_DIALREFRESH |
19924					DNS_ZONEFLG_NOREFRESH));
19925		break;
19926	case dns_dialuptype_notify:
19927		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19928		break;
19929	case dns_dialuptype_notifypassive:
19930		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19931		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19932		break;
19933	case dns_dialuptype_refresh:
19934		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
19935		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19936		break;
19937	case dns_dialuptype_passive:
19938		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19939		break;
19940	default:
19941		UNREACHABLE();
19942	}
19943	UNLOCK_ZONE(zone);
19944}
19945
19946isc_result_t
19947dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
19948	isc_result_t result = ISC_R_SUCCESS;
19949
19950	REQUIRE(DNS_ZONE_VALID(zone));
19951
19952	LOCK_ZONE(zone);
19953	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
19954	UNLOCK_ZONE(zone);
19955
19956	return (result);
19957}
19958
19959const char *
19960dns_zone_getkeydirectory(dns_zone_t *zone) {
19961	REQUIRE(DNS_ZONE_VALID(zone));
19962
19963	return (zone->keydirectory);
19964}
19965
19966unsigned int
19967dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
19968	dns_zone_t *zone;
19969	unsigned int count = 0;
19970
19971	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19972
19973	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19974	switch (state) {
19975	case DNS_ZONESTATE_XFERRUNNING:
19976		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
19977		     zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19978		{
19979			count++;
19980		}
19981		break;
19982	case DNS_ZONESTATE_XFERDEFERRED:
19983		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
19984		     zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19985		{
19986			count++;
19987		}
19988		break;
19989	case DNS_ZONESTATE_SOAQUERY:
19990		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19991		     zone = ISC_LIST_NEXT(zone, link))
19992		{
19993			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
19994				count++;
19995			}
19996		}
19997		break;
19998	case DNS_ZONESTATE_ANY:
19999		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
20000		     zone = ISC_LIST_NEXT(zone, link))
20001		{
20002			dns_view_t *view = zone->view;
20003			if (view != NULL && strcmp(view->name, "_bind") == 0) {
20004				continue;
20005			}
20006			count++;
20007		}
20008		break;
20009	case DNS_ZONESTATE_AUTOMATIC:
20010		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
20011		     zone = ISC_LIST_NEXT(zone, link))
20012		{
20013			dns_view_t *view = zone->view;
20014			if (view != NULL && strcmp(view->name, "_bind") == 0) {
20015				continue;
20016			}
20017			if (zone->automatic) {
20018				count++;
20019			}
20020		}
20021		break;
20022	default:
20023		UNREACHABLE();
20024	}
20025
20026	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
20027
20028	return (count);
20029}
20030
20031void
20032dns_zone_lock_keyfiles(dns_zone_t *zone) {
20033	REQUIRE(DNS_ZONE_VALID(zone));
20034
20035	if (zone->kasp == NULL) {
20036		/* No need to lock, nothing is writing key files. */
20037		return;
20038	}
20039
20040	REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
20041	isc_mutex_lock(&zone->kfio->lock);
20042}
20043
20044void
20045dns_zone_unlock_keyfiles(dns_zone_t *zone) {
20046	REQUIRE(DNS_ZONE_VALID(zone));
20047
20048	if (zone->kasp == NULL) {
20049		/* No need to lock, nothing is writing key files. */
20050		return;
20051	}
20052
20053	REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
20054	isc_mutex_unlock(&zone->kfio->lock);
20055}
20056
20057isc_result_t
20058dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
20059		    dns_rdata_t *rdata) {
20060	bool ok = true;
20061	bool fail = false;
20062	char namebuf[DNS_NAME_FORMATSIZE];
20063	char namebuf2[DNS_NAME_FORMATSIZE];
20064	char typebuf[DNS_RDATATYPE_FORMATSIZE];
20065	int level = ISC_LOG_WARNING;
20066	dns_name_t bad;
20067
20068	REQUIRE(DNS_ZONE_VALID(zone));
20069
20070	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
20071	    rdata->type != dns_rdatatype_nsec3)
20072	{
20073		return (ISC_R_SUCCESS);
20074	}
20075
20076	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
20077	    rdata->type == dns_rdatatype_nsec3)
20078	{
20079		level = ISC_LOG_ERROR;
20080		fail = true;
20081	}
20082
20083	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
20084	if (!ok) {
20085		dns_name_format(name, namebuf, sizeof(namebuf));
20086		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20087		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
20088			     isc_result_totext(DNS_R_BADOWNERNAME));
20089		if (fail) {
20090			return (DNS_R_BADOWNERNAME);
20091		}
20092	}
20093
20094	dns_name_init(&bad, NULL);
20095	ok = dns_rdata_checknames(rdata, name, &bad);
20096	if (!ok) {
20097		dns_name_format(name, namebuf, sizeof(namebuf));
20098		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
20099		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20100		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
20101			     namebuf2, isc_result_totext(DNS_R_BADNAME));
20102		if (fail) {
20103			return (DNS_R_BADNAME);
20104		}
20105	}
20106
20107	return (ISC_R_SUCCESS);
20108}
20109
20110void
20111dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
20112	REQUIRE(DNS_ZONE_VALID(zone));
20113	zone->checkmx = checkmx;
20114}
20115
20116void
20117dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
20118	REQUIRE(DNS_ZONE_VALID(zone));
20119	zone->checksrv = checksrv;
20120}
20121
20122void
20123dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
20124	REQUIRE(DNS_ZONE_VALID(zone));
20125	zone->checkns = checkns;
20126}
20127
20128void
20129dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
20130	REQUIRE(DNS_ZONE_VALID(zone));
20131
20132	LOCK_ZONE(zone);
20133	zone->isself = isself;
20134	zone->isselfarg = arg;
20135	UNLOCK_ZONE(zone);
20136}
20137
20138void
20139dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
20140	REQUIRE(DNS_ZONE_VALID(zone));
20141
20142	LOCK_ZONE(zone);
20143	zone->notifydelay = delay;
20144	UNLOCK_ZONE(zone);
20145}
20146
20147uint32_t
20148dns_zone_getnotifydelay(dns_zone_t *zone) {
20149	REQUIRE(DNS_ZONE_VALID(zone));
20150
20151	return (zone->notifydelay);
20152}
20153
20154isc_result_t
20155dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20156		     bool deleteit) {
20157	isc_result_t result;
20158	REQUIRE(DNS_ZONE_VALID(zone));
20159
20160	dnssec_log(zone, ISC_LOG_NOTICE,
20161		   "dns_zone_signwithkey(algorithm=%u, keyid=%u)", algorithm,
20162		   keyid);
20163	LOCK_ZONE(zone);
20164	result = zone_signwithkey(zone, algorithm, keyid, deleteit);
20165	UNLOCK_ZONE(zone);
20166
20167	return (result);
20168}
20169
20170/*
20171 * Called when a dynamic update for an NSEC3PARAM record is received.
20172 *
20173 * If set, transform the NSEC3 salt into human-readable form so that it can be
20174 * logged.  Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
20175 */
20176isc_result_t
20177dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
20178	isc_result_t result;
20179	char salt[255 * 2 + 1];
20180
20181	REQUIRE(DNS_ZONE_VALID(zone));
20182
20183	result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
20184	RUNTIME_CHECK(result == ISC_R_SUCCESS);
20185	dnssec_log(zone, ISC_LOG_NOTICE,
20186		   "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
20187		   nsec3param->hash, nsec3param->iterations, salt);
20188	LOCK_ZONE(zone);
20189	result = zone_addnsec3chain(zone, nsec3param);
20190	UNLOCK_ZONE(zone);
20191
20192	return (result);
20193}
20194
20195void
20196dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
20197	REQUIRE(DNS_ZONE_VALID(zone));
20198
20199	if (nodes == 0) {
20200		nodes = 1;
20201	}
20202	zone->nodes = nodes;
20203}
20204
20205void
20206dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
20207	REQUIRE(DNS_ZONE_VALID(zone));
20208
20209	/*
20210	 * We treat signatures as a signed value so explicitly
20211	 * limit its range here.
20212	 */
20213	if (signatures > INT32_MAX) {
20214		signatures = INT32_MAX;
20215	} else if (signatures == 0) {
20216		signatures = 1;
20217	}
20218	zone->signatures = signatures;
20219}
20220
20221uint32_t
20222dns_zone_getsignatures(dns_zone_t *zone) {
20223	REQUIRE(DNS_ZONE_VALID(zone));
20224	return (zone->signatures);
20225}
20226
20227void
20228dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
20229	REQUIRE(DNS_ZONE_VALID(zone));
20230	zone->privatetype = type;
20231}
20232
20233dns_rdatatype_t
20234dns_zone_getprivatetype(dns_zone_t *zone) {
20235	REQUIRE(DNS_ZONE_VALID(zone));
20236	return (zone->privatetype);
20237}
20238
20239static isc_result_t
20240zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20241		 bool deleteit) {
20242	dns_signing_t *signing;
20243	dns_signing_t *current;
20244	isc_result_t result = ISC_R_SUCCESS;
20245	isc_time_t now;
20246	dns_db_t *db = NULL;
20247
20248	signing = isc_mem_get(zone->mctx, sizeof *signing);
20249
20250	signing->magic = 0;
20251	signing->db = NULL;
20252	signing->dbiterator = NULL;
20253	signing->algorithm = algorithm;
20254	signing->keyid = keyid;
20255	signing->deleteit = deleteit;
20256	signing->done = false;
20257
20258	TIME_NOW(&now);
20259
20260	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
20261	if (zone->db != NULL) {
20262		dns_db_attach(zone->db, &db);
20263	}
20264	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
20265
20266	if (db == NULL) {
20267		result = ISC_R_NOTFOUND;
20268		goto cleanup;
20269	}
20270
20271	dns_db_attach(db, &signing->db);
20272
20273	for (current = ISC_LIST_HEAD(zone->signing); current != NULL;
20274	     current = ISC_LIST_NEXT(current, link))
20275	{
20276		if (current->db == signing->db &&
20277		    current->algorithm == signing->algorithm &&
20278		    current->keyid == signing->keyid)
20279		{
20280			if (current->deleteit != signing->deleteit) {
20281				current->done = true;
20282			} else {
20283				goto cleanup;
20284			}
20285		}
20286	}
20287
20288	result = dns_db_createiterator(signing->db, 0, &signing->dbiterator);
20289
20290	if (result == ISC_R_SUCCESS) {
20291		result = dns_dbiterator_first(signing->dbiterator);
20292	}
20293	if (result == ISC_R_SUCCESS) {
20294		dns_dbiterator_pause(signing->dbiterator);
20295		ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
20296		signing = NULL;
20297		if (isc_time_isepoch(&zone->signingtime)) {
20298			zone->signingtime = now;
20299			if (zone->task != NULL) {
20300				zone_settimer(zone, &now);
20301			}
20302		}
20303	}
20304
20305cleanup:
20306	if (signing != NULL) {
20307		if (signing->db != NULL) {
20308			dns_db_detach(&signing->db);
20309		}
20310		if (signing->dbiterator != NULL) {
20311			dns_dbiterator_destroy(&signing->dbiterator);
20312		}
20313		isc_mem_put(zone->mctx, signing, sizeof *signing);
20314	}
20315	if (db != NULL) {
20316		dns_db_detach(&db);
20317	}
20318	return (result);
20319}
20320
20321/* Called once; *timep should be set to the current time. */
20322static isc_result_t
20323next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
20324	isc_result_t result;
20325	isc_stdtime_t now, then = 0, event;
20326	int i;
20327
20328	now = *timep;
20329
20330	for (i = 0; i <= DST_MAX_TIMES; i++) {
20331		result = dst_key_gettime(key, i, &event);
20332		if (result == ISC_R_SUCCESS && event > now &&
20333		    (then == 0 || event < then))
20334		{
20335			then = event;
20336		}
20337	}
20338
20339	if (then != 0) {
20340		*timep = then;
20341		return (ISC_R_SUCCESS);
20342	}
20343
20344	return (ISC_R_NOTFOUND);
20345}
20346
20347static isc_result_t
20348rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
20349	  const dns_rdata_t *rdata, bool *flag) {
20350	dns_rdataset_t rdataset;
20351	dns_dbnode_t *node = NULL;
20352	isc_result_t result;
20353
20354	dns_rdataset_init(&rdataset);
20355	if (rdata->type == dns_rdatatype_nsec3) {
20356		CHECK(dns_db_findnsec3node(db, name, false, &node));
20357	} else {
20358		CHECK(dns_db_findnode(db, name, false, &node));
20359	}
20360	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
20361				     (isc_stdtime_t)0, &rdataset, NULL);
20362	if (result == ISC_R_NOTFOUND) {
20363		*flag = false;
20364		result = ISC_R_SUCCESS;
20365		goto failure;
20366	}
20367
20368	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
20369	     result = dns_rdataset_next(&rdataset))
20370	{
20371		dns_rdata_t myrdata = DNS_RDATA_INIT;
20372		dns_rdataset_current(&rdataset, &myrdata);
20373		if (!dns_rdata_compare(&myrdata, rdata)) {
20374			break;
20375		}
20376	}
20377	dns_rdataset_disassociate(&rdataset);
20378	if (result == ISC_R_SUCCESS) {
20379		*flag = true;
20380	} else if (result == ISC_R_NOMORE) {
20381		*flag = false;
20382		result = ISC_R_SUCCESS;
20383	}
20384
20385failure:
20386	if (node != NULL) {
20387		dns_db_detachnode(db, &node);
20388	}
20389	return (result);
20390}
20391
20392/*
20393 * Add records to signal the state of signing or of key removal.
20394 */
20395static isc_result_t
20396add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
20397		    dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
20398	dns_difftuple_t *tuple, *newtuple = NULL;
20399	dns_rdata_dnskey_t dnskey;
20400	dns_rdata_t rdata = DNS_RDATA_INIT;
20401	bool flag;
20402	isc_region_t r;
20403	isc_result_t result = ISC_R_SUCCESS;
20404	uint16_t keyid;
20405	unsigned char buf[5];
20406	dns_name_t *name = dns_db_origin(db);
20407
20408	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20409	     tuple = ISC_LIST_NEXT(tuple, link))
20410	{
20411		if (tuple->rdata.type != dns_rdatatype_dnskey) {
20412			continue;
20413		}
20414
20415		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
20416		RUNTIME_CHECK(result == ISC_R_SUCCESS);
20417		if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK |
20418				     DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE)
20419		{
20420			continue;
20421		}
20422
20423		dns_rdata_toregion(&tuple->rdata, &r);
20424
20425		keyid = dst_region_computeid(&r);
20426
20427		buf[0] = dnskey.algorithm;
20428		buf[1] = (keyid & 0xff00) >> 8;
20429		buf[2] = (keyid & 0xff);
20430		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
20431		buf[4] = 0;
20432		rdata.data = buf;
20433		rdata.length = sizeof(buf);
20434		rdata.type = privatetype;
20435		rdata.rdclass = tuple->rdata.rdclass;
20436
20437		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
20438			CHECK(rr_exists(db, ver, name, &rdata, &flag));
20439			if (flag) {
20440				continue;
20441			}
20442
20443			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
20444						   name, 0, &rdata, &newtuple));
20445			CHECK(do_one_tuple(&newtuple, db, ver, diff));
20446			INSIST(newtuple == NULL);
20447		}
20448
20449		/*
20450		 * Remove any record which says this operation has already
20451		 * completed.
20452		 */
20453		buf[4] = 1;
20454		CHECK(rr_exists(db, ver, name, &rdata, &flag));
20455		if (flag) {
20456			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
20457						   name, 0, &rdata, &newtuple));
20458			CHECK(do_one_tuple(&newtuple, db, ver, diff));
20459			INSIST(newtuple == NULL);
20460		}
20461	}
20462failure:
20463	return (result);
20464}
20465
20466/*
20467 * See if dns__zone_updatesigs() will update signature for RRset 'rrtype' at
20468 * the apex, and if not tickle them and cause to sign so that newly activated
20469 * keys are used.
20470 */
20471static isc_result_t
20472tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db,
20473		  dns_dbversion_t *ver, isc_stdtime_t now, dns_diff_t *diff,
20474		  dns__zonediff_t *zonediff, dst_key_t **keys,
20475		  unsigned int nkeys, isc_stdtime_t inception,
20476		  isc_stdtime_t keyexpire, bool check_ksk,
20477		  bool keyset_kskonly) {
20478	dns_difftuple_t *tuple;
20479	isc_result_t result;
20480
20481	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20482	     tuple = ISC_LIST_NEXT(tuple, link))
20483	{
20484		if (tuple->rdata.type == rrtype &&
20485		    dns_name_equal(&tuple->name, &zone->origin))
20486		{
20487			break;
20488		}
20489	}
20490
20491	if (tuple == NULL) {
20492		result = del_sigs(zone, db, ver, &zone->origin, rrtype,
20493				  zonediff, keys, nkeys, now, false);
20494		if (result != ISC_R_SUCCESS) {
20495			dnssec_log(zone, ISC_LOG_ERROR,
20496				   "sign_apex:del_sigs -> %s",
20497				   isc_result_totext(result));
20498			return (result);
20499		}
20500		result = add_sigs(db, ver, &zone->origin, zone, rrtype,
20501				  zonediff->diff, keys, nkeys, zone->mctx, now,
20502				  inception, keyexpire, check_ksk,
20503				  keyset_kskonly);
20504		if (result != ISC_R_SUCCESS) {
20505			dnssec_log(zone, ISC_LOG_ERROR,
20506				   "sign_apex:add_sigs -> %s",
20507				   isc_result_totext(result));
20508			return (result);
20509		}
20510	}
20511
20512	return (ISC_R_SUCCESS);
20513}
20514
20515static isc_result_t
20516sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20517	  isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff) {
20518	isc_result_t result;
20519	isc_stdtime_t inception, soaexpire, keyexpire;
20520	bool check_ksk, keyset_kskonly;
20521	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
20522	unsigned int nkeys = 0, i;
20523
20524	result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
20525				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
20526	if (result != ISC_R_SUCCESS) {
20527		dnssec_log(zone, ISC_LOG_ERROR,
20528			   "sign_apex:dns__zone_findkeys -> %s",
20529			   isc_result_totext(result));
20530		return (result);
20531	}
20532
20533	inception = now - 3600; /* Allow for clock skew. */
20534	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
20535
20536	keyexpire = dns_zone_getkeyvalidityinterval(zone);
20537	if (keyexpire == 0) {
20538		keyexpire = soaexpire - 1;
20539	} else {
20540		keyexpire += now;
20541	}
20542
20543	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
20544	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
20545
20546	/*
20547	 * See if dns__zone_updatesigs() will update DNSKEY/CDS/CDNSKEY
20548	 * signature and if not cause them to sign so that newly activated
20549	 * keys are used.
20550	 */
20551	result = tickle_apex_rrset(dns_rdatatype_dnskey, zone, db, ver, now,
20552				   diff, zonediff, zone_keys, nkeys, inception,
20553				   keyexpire, check_ksk, keyset_kskonly);
20554	if (result != ISC_R_SUCCESS) {
20555		goto failure;
20556	}
20557	result = tickle_apex_rrset(dns_rdatatype_cds, zone, db, ver, now, diff,
20558				   zonediff, zone_keys, nkeys, inception,
20559				   keyexpire, check_ksk, keyset_kskonly);
20560	if (result != ISC_R_SUCCESS) {
20561		goto failure;
20562	}
20563	result = tickle_apex_rrset(dns_rdatatype_cdnskey, zone, db, ver, now,
20564				   diff, zonediff, zone_keys, nkeys, inception,
20565				   keyexpire, check_ksk, keyset_kskonly);
20566	if (result != ISC_R_SUCCESS) {
20567		goto failure;
20568	}
20569
20570	result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
20571				      inception, soaexpire, keyexpire, now,
20572				      check_ksk, keyset_kskonly, zonediff);
20573
20574	if (result != ISC_R_SUCCESS) {
20575		dnssec_log(zone, ISC_LOG_ERROR,
20576			   "sign_apex:dns__zone_updatesigs -> %s",
20577			   isc_result_totext(result));
20578		goto failure;
20579	}
20580
20581failure:
20582	for (i = 0; i < nkeys; i++) {
20583		dst_key_free(&zone_keys[i]);
20584	}
20585	return (result);
20586}
20587
20588static isc_result_t
20589clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20590		 dns_diff_t *diff) {
20591	isc_result_t result;
20592	dns_dbnode_t *node = NULL;
20593	dns_rdataset_t rdataset;
20594
20595	dns_rdataset_init(&rdataset);
20596	CHECK(dns_db_getoriginnode(db, &node));
20597
20598	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
20599				     dns_rdatatype_none, 0, &rdataset, NULL);
20600	if (dns_rdataset_isassociated(&rdataset)) {
20601		dns_rdataset_disassociate(&rdataset);
20602	}
20603	if (result != ISC_R_NOTFOUND) {
20604		goto failure;
20605	}
20606
20607	result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
20608
20609failure:
20610	if (node != NULL) {
20611		dns_db_detachnode(db, &node);
20612	}
20613	return (result);
20614}
20615
20616/*
20617 * Given an RRSIG rdataset and an algorithm, determine whether there
20618 * are any signatures using that algorithm.
20619 */
20620static bool
20621signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
20622	dns_rdata_t rdata = DNS_RDATA_INIT;
20623	dns_rdata_rrsig_t rrsig;
20624	isc_result_t result;
20625
20626	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
20627	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
20628		return (false);
20629	}
20630
20631	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
20632	     result = dns_rdataset_next(rdataset))
20633	{
20634		dns_rdataset_current(rdataset, &rdata);
20635		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
20636		RUNTIME_CHECK(result == ISC_R_SUCCESS);
20637		dns_rdata_reset(&rdata);
20638		if (rrsig.algorithm == alg) {
20639			return (true);
20640		}
20641	}
20642
20643	return (false);
20644}
20645
20646static isc_result_t
20647add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20648	   dns_diff_t *diff) {
20649	dns_name_t *origin;
20650	bool build_nsec3;
20651	isc_result_t result;
20652
20653	origin = dns_db_origin(db);
20654	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
20655				 &build_nsec3));
20656	if (build_nsec3) {
20657		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone_nsecttl(zone),
20658					   false, zone->privatetype, diff));
20659	}
20660	CHECK(updatesecure(db, ver, origin, zone_nsecttl(zone), true, diff));
20661
20662failure:
20663	return (result);
20664}
20665
20666static void
20667dnssec_report(const char *format, ...) {
20668	va_list args;
20669	va_start(args, format);
20670	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
20671		       ISC_LOG_INFO, format, args);
20672	va_end(args);
20673}
20674
20675static void
20676checkds_destroy(dns_checkds_t *checkds, bool locked) {
20677	isc_mem_t *mctx;
20678
20679	REQUIRE(DNS_CHECKDS_VALID(checkds));
20680
20681	dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
20682		     "checkds: destroy DS query");
20683
20684	if (checkds->zone != NULL) {
20685		if (!locked) {
20686			LOCK_ZONE(checkds->zone);
20687		}
20688		REQUIRE(LOCKED_ZONE(checkds->zone));
20689		if (ISC_LINK_LINKED(checkds, link)) {
20690			ISC_LIST_UNLINK(checkds->zone->checkds_requests,
20691					checkds, link);
20692		}
20693		if (!locked) {
20694			UNLOCK_ZONE(checkds->zone);
20695		}
20696		if (locked) {
20697			zone_idetach(&checkds->zone);
20698		} else {
20699			dns_zone_idetach(&checkds->zone);
20700		}
20701	}
20702	if (checkds->request != NULL) {
20703		dns_request_destroy(&checkds->request);
20704	}
20705	if (checkds->key != NULL) {
20706		dns_tsigkey_detach(&checkds->key);
20707	}
20708	if (checkds->transport != NULL) {
20709		dns_transport_detach(&checkds->transport);
20710	}
20711	mctx = checkds->mctx;
20712	isc_mem_put(checkds->mctx, checkds, sizeof(*checkds));
20713	isc_mem_detach(&mctx);
20714}
20715
20716static isc_result_t
20717make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
20718	    dns_rdata_t *target) {
20719	isc_result_t result;
20720	isc_buffer_t b;
20721	isc_region_t r;
20722
20723	isc_buffer_init(&b, buf, bufsize);
20724	result = dst_key_todns(key, &b);
20725	if (result != ISC_R_SUCCESS) {
20726		return (result);
20727	}
20728
20729	dns_rdata_reset(target);
20730	isc_buffer_usedregion(&b, &r);
20731	dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey,
20732			     &r);
20733	return (ISC_R_SUCCESS);
20734}
20735
20736static bool
20737do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now,
20738	   bool dspublish) {
20739	dns_kasp_t *kasp = dns_zone_getkasp(zone);
20740	const char *dir = dns_zone_getkeydirectory(zone);
20741	isc_result_t result;
20742	uint32_t count = 0;
20743
20744	if (dspublish) {
20745		(void)dst_key_getnum(key, DST_NUM_DSPUBCOUNT, &count);
20746		count += 1;
20747		dst_key_setnum(key, DST_NUM_DSPUBCOUNT, count);
20748		dns_zone_log(zone, ISC_LOG_DEBUG(3),
20749			     "checkds: %u DS published "
20750			     "for key %u",
20751			     count, dst_key_id(key));
20752
20753		if (count != zone->parentalscnt) {
20754			return false;
20755		}
20756	} else {
20757		(void)dst_key_getnum(key, DST_NUM_DSDELCOUNT, &count);
20758		count += 1;
20759		dst_key_setnum(key, DST_NUM_DSDELCOUNT, count);
20760		dns_zone_log(zone, ISC_LOG_DEBUG(3),
20761			     "checkds: %u DS withdrawn "
20762			     "for key %u",
20763			     count, dst_key_id(key));
20764
20765		if (count != zone->parentalscnt) {
20766			return false;
20767		}
20768	}
20769
20770	dns_zone_log(zone, ISC_LOG_DEBUG(3),
20771		     "checkds: checkds %s for key "
20772		     "%u",
20773		     dspublish ? "published" : "withdrawn", dst_key_id(key));
20774
20775	dns_zone_lock_keyfiles(zone);
20776	result = dns_keymgr_checkds_id(kasp, &zone->checkds_ok, dir, now, now,
20777				       dspublish, dst_key_id(key),
20778				       dst_key_alg(key));
20779	dns_zone_unlock_keyfiles(zone);
20780
20781	if (result != ISC_R_SUCCESS) {
20782		dns_zone_log(zone, ISC_LOG_WARNING,
20783			     "checkds: checkds for key %u failed: %s",
20784			     dst_key_id(key), isc_result_totext(result));
20785		return false;
20786	}
20787
20788	return true;
20789}
20790
20791static isc_result_t
20792validate_ds(dns_zone_t *zone, dns_message_t *message) {
20793	UNUSED(zone);
20794	UNUSED(message);
20795
20796	/* Get closest trust anchor */
20797
20798	/* Check that trust anchor is (grand)parent of zone. */
20799
20800	/* Find the DNSKEY signing the message. */
20801
20802	/* Check that DNSKEY is in chain of trust. */
20803
20804	/* Validate DS RRset. */
20805
20806	return (ISC_R_SUCCESS);
20807}
20808
20809static void
20810checkds_done(isc_task_t *task, isc_event_t *event) {
20811	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
20812	char rcode[128];
20813	dns_checkds_t *checkds;
20814	dns_zone_t *zone;
20815	dns_db_t *db = NULL;
20816	dns_dbversion_t *version = NULL;
20817	dns_dnsseckey_t *key;
20818	dns_dnsseckeylist_t keys;
20819	dns_kasp_t *kasp = NULL;
20820	dns_message_t *message = NULL;
20821	dns_rdataset_t *ds_rrset = NULL;
20822	dns_requestevent_t *revent = (dns_requestevent_t *)event;
20823	isc_buffer_t buf;
20824	isc_result_t result;
20825	isc_stdtime_t now;
20826	isc_time_t timenow;
20827	bool rekey = false;
20828	bool empty = false;
20829
20830	UNUSED(task);
20831
20832	checkds = event->ev_arg;
20833	REQUIRE(DNS_CHECKDS_VALID(checkds));
20834
20835	zone = checkds->zone;
20836	INSIST(task == zone->task);
20837
20838	ISC_LIST_INIT(keys);
20839
20840	kasp = zone->kasp;
20841	INSIST(kasp != NULL);
20842
20843	isc_buffer_init(&buf, rcode, sizeof(rcode));
20844	isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
20845
20846	dns_zone_log(zone, ISC_LOG_DEBUG(1), "checkds: DS query to %s: done",
20847		     addrbuf);
20848
20849	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &message);
20850	INSIST(message != NULL);
20851
20852	CHECK(revent->result);
20853	CHECK(dns_request_getresponse(revent->request, message,
20854				      DNS_MESSAGEPARSE_PRESERVEORDER));
20855	CHECK(dns_rcode_totext(message->rcode, &buf));
20856
20857	dns_zone_log(zone, ISC_LOG_DEBUG(3),
20858		     "checkds: DS response from %s: %.*s", addrbuf,
20859		     (int)buf.used, rcode);
20860
20861	/* Validate response. */
20862	CHECK(validate_ds(zone, message));
20863
20864	/* Check RCODE. */
20865	if (message->rcode != dns_rcode_noerror) {
20866		dns_zone_log(zone, ISC_LOG_NOTICE,
20867			     "checkds: bad DS response from %s: %.*s", addrbuf,
20868			     (int)buf.used, rcode);
20869		goto failure;
20870	}
20871
20872	/* Make sure that either AA or RA bit is set. */
20873	if ((message->flags & DNS_MESSAGEFLAG_AA) == 0 &&
20874	    (message->flags & DNS_MESSAGEFLAG_RA) == 0)
20875	{
20876		dns_zone_log(zone, ISC_LOG_NOTICE,
20877			     "checkds: bad DS response from %s: expected AA or "
20878			     "RA bit set",
20879			     addrbuf);
20880		goto failure;
20881	}
20882
20883	/* Lookup DS RRset. */
20884	result = dns_message_firstname(message, DNS_SECTION_ANSWER);
20885	while (result == ISC_R_SUCCESS) {
20886		dns_name_t *name = NULL;
20887		dns_rdataset_t *rdataset;
20888
20889		dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
20890		if (dns_name_compare(&zone->origin, name) != 0) {
20891			goto next;
20892		}
20893
20894		for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
20895		     rdataset = ISC_LIST_NEXT(rdataset, link))
20896		{
20897			if (rdataset->type != dns_rdatatype_ds) {
20898				goto next;
20899			}
20900
20901			ds_rrset = rdataset;
20902			break;
20903		}
20904
20905		if (ds_rrset != NULL) {
20906			break;
20907		}
20908
20909	next:
20910		result = dns_message_nextname(message, DNS_SECTION_ANSWER);
20911	}
20912
20913	if (ds_rrset == NULL) {
20914		empty = true;
20915		dns_zone_log(zone, ISC_LOG_NOTICE,
20916			     "checkds: empty DS response from %s", addrbuf);
20917	}
20918
20919	TIME_NOW(&timenow);
20920	now = isc_time_seconds(&timenow);
20921
20922	CHECK(dns_zone_getdb(zone, &db));
20923	dns_db_currentversion(db, &version);
20924
20925	KASP_LOCK(kasp);
20926	LOCK_ZONE(zone);
20927	for (key = ISC_LIST_HEAD(zone->checkds_ok); key != NULL;
20928	     key = ISC_LIST_NEXT(key, link))
20929	{
20930		bool alldone = false, found = false;
20931		bool checkdspub = false, checkdsdel = false, ksk = false;
20932		dst_key_state_t ds_state = DST_KEY_STATE_NA;
20933		isc_stdtime_t published = 0, withdrawn = 0;
20934		isc_result_t ret = ISC_R_SUCCESS;
20935
20936		/* Is this key have the KSK role? */
20937		(void)dst_key_role(key->key, &ksk, NULL);
20938		if (!ksk) {
20939			continue;
20940		}
20941
20942		/* Do we need to check the DS RRset for this key? */
20943		(void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
20944		(void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
20945		(void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
20946
20947		if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
20948			checkdspub = true;
20949		} else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
20950			   withdrawn == 0)
20951		{
20952			checkdsdel = true;
20953		}
20954		if (!checkdspub && !checkdsdel) {
20955			continue;
20956		}
20957
20958		if (empty) {
20959			goto dswithdrawn;
20960		}
20961
20962		/* Find the appropriate DS record. */
20963		ret = dns_rdataset_first(ds_rrset);
20964		while (ret == ISC_R_SUCCESS) {
20965			dns_rdata_ds_t ds;
20966			dns_rdata_t dnskey = DNS_RDATA_INIT;
20967			dns_rdata_t dsrdata = DNS_RDATA_INIT;
20968			dns_rdata_t rdata = DNS_RDATA_INIT;
20969			isc_result_t r;
20970			unsigned char dsbuf[DNS_DS_BUFFERSIZE];
20971			unsigned char keybuf[DST_KEY_MAXSIZE];
20972
20973			dns_rdataset_current(ds_rrset, &rdata);
20974			r = dns_rdata_tostruct(&rdata, &ds, NULL);
20975			if (r != ISC_R_SUCCESS) {
20976				goto nextds;
20977			}
20978			/* Check key tag and algorithm. */
20979			if (dst_key_id(key->key) != ds.key_tag) {
20980				goto nextds;
20981			}
20982			if (dst_key_alg(key->key) != ds.algorithm) {
20983				goto nextds;
20984			}
20985			/* Derive DS from DNSKEY, see if the rdata is equal. */
20986			make_dnskey(key->key, keybuf, sizeof(keybuf), &dnskey);
20987			r = dns_ds_buildrdata(&zone->origin, &dnskey,
20988					      ds.digest_type, dsbuf, &dsrdata);
20989			if (r != ISC_R_SUCCESS) {
20990				goto nextds;
20991			}
20992			if (dns_rdata_compare(&rdata, &dsrdata) == 0) {
20993				found = true;
20994				if (checkdspub) {
20995					/* DS Published. */
20996					alldone = do_checkds(zone, key->key,
20997							     now, true);
20998					if (alldone) {
20999						rekey = true;
21000					}
21001				}
21002			}
21003
21004		nextds:
21005			ret = dns_rdataset_next(ds_rrset);
21006		}
21007
21008	dswithdrawn:
21009		/* DS withdrawn. */
21010		if (checkdsdel && !found) {
21011			alldone = do_checkds(zone, key->key, now, false);
21012			if (alldone) {
21013				rekey = true;
21014			}
21015		}
21016	}
21017	UNLOCK_ZONE(zone);
21018	KASP_UNLOCK(kasp);
21019
21020	/* Rekey after checkds. */
21021	if (rekey) {
21022		dns_zone_rekey(zone, false);
21023	}
21024
21025failure:
21026	if (result != ISC_R_SUCCESS) {
21027		dns_zone_log(zone, ISC_LOG_DEBUG(3),
21028			     "checkds: DS request failed: %s",
21029			     isc_result_totext(result));
21030	}
21031
21032	if (version != NULL) {
21033		dns_db_closeversion(db, &version, false);
21034	}
21035	if (db != NULL) {
21036		dns_db_detach(&db);
21037	}
21038
21039	while (!ISC_LIST_EMPTY(keys)) {
21040		key = ISC_LIST_HEAD(keys);
21041		ISC_LIST_UNLINK(keys, key, link);
21042		dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
21043	}
21044
21045	isc_event_free(&event);
21046	checkds_destroy(checkds, false);
21047	dns_message_detach(&message);
21048}
21049
21050static bool
21051checkds_isqueued(dns_zone_t *zone, isc_sockaddr_t *addr, dns_tsigkey_t *key,
21052		 dns_transport_t *transport) {
21053	dns_checkds_t *checkds;
21054
21055	for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
21056	     checkds = ISC_LIST_NEXT(checkds, link))
21057	{
21058		if (checkds->request != NULL) {
21059			continue;
21060		}
21061		if (addr != NULL && isc_sockaddr_equal(addr, &checkds->dst) &&
21062		    checkds->key == key && checkds->transport == transport)
21063		{
21064			return (true);
21065		}
21066	}
21067	return (false);
21068}
21069
21070static isc_result_t
21071checkds_create(isc_mem_t *mctx, unsigned int flags, dns_checkds_t **checkdsp) {
21072	dns_checkds_t *checkds;
21073
21074	REQUIRE(checkdsp != NULL && *checkdsp == NULL);
21075
21076	checkds = isc_mem_get(mctx, sizeof(*checkds));
21077	*checkds = (dns_checkds_t){
21078		.flags = flags,
21079	};
21080
21081	isc_mem_attach(mctx, &checkds->mctx);
21082	isc_sockaddr_any(&checkds->dst);
21083	ISC_LINK_INIT(checkds, link);
21084	checkds->magic = CHECKDS_MAGIC;
21085	*checkdsp = checkds;
21086	return (ISC_R_SUCCESS);
21087}
21088
21089static isc_result_t
21090checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep) {
21091	dns_message_t *message = NULL;
21092
21093	dns_name_t *tempname = NULL;
21094	dns_rdataset_t *temprdataset = NULL;
21095
21096	isc_result_t result;
21097
21098	REQUIRE(DNS_ZONE_VALID(zone));
21099	REQUIRE(messagep != NULL && *messagep == NULL);
21100
21101	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
21102
21103	message->opcode = dns_opcode_query;
21104	message->rdclass = zone->rdclass;
21105	message->flags |= DNS_MESSAGEFLAG_RD;
21106
21107	result = dns_message_gettempname(message, &tempname);
21108	if (result != ISC_R_SUCCESS) {
21109		goto cleanup;
21110	}
21111
21112	result = dns_message_gettemprdataset(message, &temprdataset);
21113	if (result != ISC_R_SUCCESS) {
21114		goto cleanup;
21115	}
21116
21117	/*
21118	 * Make question.
21119	 */
21120	dns_name_init(tempname, NULL);
21121	dns_name_clone(&zone->origin, tempname);
21122	dns_rdataset_makequestion(temprdataset, zone->rdclass,
21123				  dns_rdatatype_ds);
21124	ISC_LIST_APPEND(tempname->list, temprdataset, link);
21125	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
21126	tempname = NULL;
21127	temprdataset = NULL;
21128
21129	*messagep = message;
21130	return (ISC_R_SUCCESS);
21131
21132cleanup:
21133	if (tempname != NULL) {
21134		dns_message_puttempname(message, &tempname);
21135	}
21136	if (temprdataset != NULL) {
21137		dns_message_puttemprdataset(message, &temprdataset);
21138	}
21139	dns_message_detach(&message);
21140	return (result);
21141}
21142
21143static void
21144checkds_send_toaddr(isc_task_t *task, isc_event_t *event) {
21145	dns_checkds_t *checkds;
21146	isc_result_t result;
21147	dns_message_t *message = NULL;
21148	isc_netaddr_t dstip;
21149	dns_tsigkey_t *key = NULL;
21150	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
21151	isc_sockaddr_t src;
21152	unsigned int options, timeout;
21153	bool have_checkdssource = false;
21154
21155	checkds = event->ev_arg;
21156	REQUIRE(DNS_CHECKDS_VALID(checkds));
21157
21158	UNUSED(task);
21159
21160	LOCK_ZONE(checkds->zone);
21161
21162	checkds->event = NULL;
21163
21164	if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_LOADED) == 0) {
21165		result = ISC_R_CANCELED;
21166		goto cleanup;
21167	}
21168
21169	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
21170	    DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING) ||
21171	    checkds->zone->view->requestmgr == NULL ||
21172	    checkds->zone->db == NULL)
21173	{
21174		result = ISC_R_CANCELED;
21175		goto cleanup;
21176	}
21177
21178	/*
21179	 * The raw IPv4 address should also exist.  Don't send to the
21180	 * mapped form.
21181	 */
21182	if (isc_sockaddr_pf(&checkds->dst) == PF_INET6 &&
21183	    IN6_IS_ADDR_V4MAPPED(&checkds->dst.type.sin6.sin6_addr))
21184	{
21185		isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21186		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21187			     "checkds: ignoring IPv6 mapped IPV4 address: %s",
21188			     addrbuf);
21189		result = ISC_R_CANCELED;
21190		goto cleanup;
21191	}
21192
21193	result = checkds_createmessage(checkds->zone, &message);
21194	if (result != ISC_R_SUCCESS) {
21195		goto cleanup;
21196	}
21197
21198	isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21199	if (checkds->key != NULL) {
21200		/* Transfer ownership of key */
21201		key = checkds->key;
21202		checkds->key = NULL;
21203	} else {
21204		isc_netaddr_fromsockaddr(&dstip, &checkds->dst);
21205		result = dns_view_getpeertsig(checkds->zone->view, &dstip,
21206					      &key);
21207		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
21208			dns_zone_log(checkds->zone, ISC_LOG_ERROR,
21209				     "checkds: DS query to %s not sent. "
21210				     "Peer TSIG key lookup failure.",
21211				     addrbuf);
21212			goto cleanup_message;
21213		}
21214	}
21215
21216	if (key != NULL) {
21217		char namebuf[DNS_NAME_FORMATSIZE];
21218
21219		dns_name_format(&key->name, namebuf, sizeof(namebuf));
21220		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21221			     "checkds: sending DS query to %s : TSIG (%s)",
21222			     addrbuf, namebuf);
21223	} else {
21224		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21225			     "checkds: sending DS query to %s", addrbuf);
21226	}
21227	options = 0;
21228	if (checkds->zone->view->peers != NULL) {
21229		dns_peer_t *peer = NULL;
21230		bool usetcp = false;
21231		result = dns_peerlist_peerbyaddr(checkds->zone->view->peers,
21232						 &dstip, &peer);
21233		if (result == ISC_R_SUCCESS) {
21234			result = dns_peer_getquerysource(peer, &src);
21235			if (result == ISC_R_SUCCESS) {
21236				have_checkdssource = true;
21237			}
21238			result = dns_peer_getforcetcp(peer, &usetcp);
21239			if (result == ISC_R_SUCCESS && usetcp) {
21240				options |= DNS_FETCHOPT_TCP;
21241			}
21242		}
21243	}
21244	switch (isc_sockaddr_pf(&checkds->dst)) {
21245	case PF_INET:
21246		if (!have_checkdssource) {
21247			src = checkds->zone->parentalsrc4;
21248		}
21249		break;
21250	case PF_INET6:
21251		if (!have_checkdssource) {
21252			src = checkds->zone->parentalsrc6;
21253		}
21254		break;
21255	default:
21256		result = ISC_R_NOTIMPLEMENTED;
21257		goto cleanup_key;
21258	}
21259
21260	dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21261		     "checkds: create request for DS query to %s", addrbuf);
21262
21263	timeout = 5;
21264	options |= DNS_REQUESTOPT_TCP;
21265	result = dns_request_create(
21266		checkds->zone->view->requestmgr, message, &src, &checkds->dst,
21267		options, key, timeout * 3 + 1, timeout, 2, checkds->zone->task,
21268		checkds_done, checkds, &checkds->request);
21269	if (result != ISC_R_SUCCESS) {
21270		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21271			     "checkds: dns_request_create() to %s failed: %s",
21272			     addrbuf, isc_result_totext(result));
21273	}
21274
21275cleanup_key:
21276	if (key != NULL) {
21277		dns_tsigkey_detach(&key);
21278	}
21279cleanup_message:
21280	dns_message_detach(&message);
21281cleanup:
21282	UNLOCK_ZONE(checkds->zone);
21283	isc_event_free(&event);
21284	if (result != ISC_R_SUCCESS) {
21285		checkds_destroy(checkds, false);
21286	}
21287}
21288
21289static isc_result_t
21290checkds_send_queue(dns_checkds_t *checkds) {
21291	isc_event_t *e;
21292	isc_result_t result;
21293
21294	INSIST(checkds->event == NULL);
21295	e = isc_event_allocate(checkds->mctx, NULL, DNS_EVENT_CHECKDSSENDTOADDR,
21296			       checkds_send_toaddr, checkds,
21297			       sizeof(isc_event_t));
21298	e->ev_arg = checkds;
21299	e->ev_sender = NULL;
21300	result = isc_ratelimiter_enqueue(checkds->zone->zmgr->checkdsrl,
21301					 checkds->zone->task, &e);
21302	if (result != ISC_R_SUCCESS) {
21303		isc_event_free(&e);
21304		checkds->event = NULL;
21305	}
21306	return (result);
21307}
21308
21309static void
21310checkds_send(dns_zone_t *zone) {
21311	dns_view_t *view = dns_zone_getview(zone);
21312	isc_result_t result;
21313	unsigned int flags = 0;
21314
21315	/*
21316	 * Zone lock held by caller.
21317	 */
21318	REQUIRE(LOCKED_ZONE(zone));
21319
21320	dns_zone_log(zone, ISC_LOG_DEBUG(3),
21321		     "checkds: start sending DS queries to %u parentals",
21322		     zone->parentalscnt);
21323
21324	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
21325		dns_zone_log(zone, ISC_LOG_DEBUG(3),
21326			     "checkds: abort, named exiting");
21327		return;
21328	}
21329
21330	for (unsigned int i = 0; i < zone->parentalscnt; i++) {
21331		dns_tsigkey_t *key = NULL;
21332		dns_transport_t *transport = NULL;
21333		isc_sockaddr_t dst;
21334		dns_checkds_t *checkds = NULL;
21335
21336		if ((zone->parentalkeynames != NULL) &&
21337		    (zone->parentalkeynames[i] != NULL))
21338		{
21339			dns_name_t *keyname = zone->parentalkeynames[i];
21340			(void)dns_view_gettsig(view, keyname, &key);
21341		}
21342
21343		if ((zone->parentaltlsnames != NULL) &&
21344		    (zone->parentaltlsnames[i] != NULL))
21345		{
21346			dns_name_t *tlsname = zone->parentaltlsnames[i];
21347			(void)dns_view_gettransport(view, DNS_TRANSPORT_TLS,
21348						    tlsname, &transport);
21349			dns_zone_logc(
21350				zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
21351				"got TLS configuration for zone transfer");
21352		}
21353
21354		dst = zone->parentals[i];
21355
21356		/* TODO: glue the transport to the checkds request */
21357
21358		if (checkds_isqueued(zone, &dst, key, transport)) {
21359			dns_zone_log(zone, ISC_LOG_DEBUG(3),
21360				     "checkds: DS query to parent "
21361				     "%d is queued",
21362				     i);
21363			if (key != NULL) {
21364				dns_tsigkey_detach(&key);
21365			}
21366			if (transport != NULL) {
21367				dns_transport_detach(&transport);
21368			}
21369			continue;
21370		}
21371
21372		dns_zone_log(zone, ISC_LOG_DEBUG(3),
21373			     "checkds: create DS query for "
21374			     "parent %d",
21375			     i);
21376
21377		result = checkds_create(zone->mctx, flags, &checkds);
21378		if (result != ISC_R_SUCCESS) {
21379			dns_zone_log(zone, ISC_LOG_DEBUG(3),
21380				     "checkds: create DS query for "
21381				     "parent %d failed",
21382				     i);
21383			continue;
21384		}
21385		zone_iattach(zone, &checkds->zone);
21386		checkds->dst = dst;
21387
21388		INSIST(checkds->key == NULL);
21389		if (key != NULL) {
21390			checkds->key = key;
21391			key = NULL;
21392		}
21393
21394		INSIST(checkds->transport == NULL);
21395		if (transport != NULL) {
21396			checkds->transport = transport;
21397			transport = NULL;
21398		}
21399
21400		ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
21401		result = checkds_send_queue(checkds);
21402		if (result != ISC_R_SUCCESS) {
21403			dns_zone_log(zone, ISC_LOG_DEBUG(3),
21404				     "checkds: send DS query to "
21405				     "parent %d failed",
21406				     i);
21407			checkds_destroy(checkds, true);
21408		}
21409	}
21410}
21411
21412static void
21413zone_checkds(dns_zone_t *zone) {
21414	bool cdscheck = false;
21415
21416	for (dns_dnsseckey_t *key = ISC_LIST_HEAD(zone->checkds_ok);
21417	     key != NULL; key = ISC_LIST_NEXT(key, link))
21418	{
21419		dst_key_state_t ds_state = DST_KEY_STATE_NA;
21420		bool ksk = false;
21421		isc_stdtime_t published = 0, withdrawn = 0;
21422
21423		/* Is this key have the KSK role? */
21424		(void)dst_key_role(key->key, &ksk, NULL);
21425		if (!ksk) {
21426			continue;
21427		}
21428
21429		/* Do we need to check the DS RRset? */
21430		(void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
21431		(void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
21432		(void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
21433
21434		if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
21435			dst_key_setnum(key->key, DST_NUM_DSPUBCOUNT, 0);
21436			cdscheck = true;
21437		} else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
21438			   withdrawn == 0)
21439		{
21440			dst_key_setnum(key->key, DST_NUM_DSDELCOUNT, 0);
21441			cdscheck = true;
21442		}
21443	}
21444
21445	if (cdscheck) {
21446		/* Request the DS RRset. */
21447		LOCK_ZONE(zone);
21448		checkds_send(zone);
21449		UNLOCK_ZONE(zone);
21450	}
21451}
21452
21453static void
21454zone_rekey(dns_zone_t *zone) {
21455	isc_result_t result;
21456	dns_db_t *db = NULL;
21457	dns_dbnode_t *node = NULL;
21458	dns_dbversion_t *ver = NULL;
21459	dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
21460	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
21461	dns_dnsseckey_t *key = NULL;
21462	dns_diff_t diff, _sig_diff;
21463	dns_kasp_t *kasp;
21464	dns__zonediff_t zonediff;
21465	bool commit = false, newactive = false;
21466	bool newalg = false;
21467	bool fullsign;
21468	dns_ttl_t ttl = 3600;
21469	const char *dir = NULL;
21470	isc_mem_t *mctx = NULL;
21471	isc_stdtime_t now, nexttime = 0;
21472	isc_time_t timenow;
21473	isc_interval_t ival;
21474	char timebuf[80];
21475
21476	REQUIRE(DNS_ZONE_VALID(zone));
21477
21478	ISC_LIST_INIT(dnskeys);
21479	ISC_LIST_INIT(keys);
21480	ISC_LIST_INIT(rmkeys);
21481	dns_rdataset_init(&soaset);
21482	dns_rdataset_init(&soasigs);
21483	dns_rdataset_init(&keyset);
21484	dns_rdataset_init(&keysigs);
21485	dns_rdataset_init(&cdsset);
21486	dns_rdataset_init(&cdnskeyset);
21487	dir = dns_zone_getkeydirectory(zone);
21488	mctx = zone->mctx;
21489	dns_diff_init(mctx, &diff);
21490	dns_diff_init(mctx, &_sig_diff);
21491	zonediff_init(&zonediff, &_sig_diff);
21492
21493	CHECK(dns_zone_getdb(zone, &db));
21494	CHECK(dns_db_newversion(db, &ver));
21495	CHECK(dns_db_getoriginnode(db, &node));
21496
21497	TIME_NOW(&timenow);
21498	now = isc_time_seconds(&timenow);
21499
21500	kasp = dns_zone_getkasp(zone);
21501
21502	dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
21503
21504	/* Get the SOA record's TTL */
21505	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
21506				  dns_rdatatype_none, 0, &soaset, &soasigs));
21507	ttl = soaset.ttl;
21508	dns_rdataset_disassociate(&soaset);
21509
21510	/* Get the DNSKEY rdataset */
21511	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
21512				     dns_rdatatype_none, 0, &keyset, &keysigs);
21513	if (result == ISC_R_SUCCESS) {
21514		ttl = keyset.ttl;
21515
21516		dns_zone_lock_keyfiles(zone);
21517
21518		result = dns_dnssec_keylistfromrdataset(
21519			&zone->origin, dir, mctx, &keyset, &keysigs, &soasigs,
21520			false, false, &dnskeys);
21521
21522		dns_zone_unlock_keyfiles(zone);
21523
21524		if (result != ISC_R_SUCCESS) {
21525			goto failure;
21526		}
21527	} else if (result != ISC_R_NOTFOUND) {
21528		goto failure;
21529	}
21530
21531	/* Get the CDS rdataset */
21532	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
21533				     dns_rdatatype_none, 0, &cdsset, NULL);
21534	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
21535		dns_rdataset_disassociate(&cdsset);
21536	}
21537
21538	/* Get the CDNSKEY rdataset */
21539	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
21540				     dns_rdatatype_none, 0, &cdnskeyset, NULL);
21541	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
21542		dns_rdataset_disassociate(&cdnskeyset);
21543	}
21544
21545	/*
21546	 * True when called from "rndc sign".  Indicates the zone should be
21547	 * fully signed now.
21548	 */
21549	fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
21550
21551	KASP_LOCK(kasp);
21552
21553	dns_zone_lock_keyfiles(zone);
21554	result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
21555					     &keys);
21556	dns_zone_unlock_keyfiles(zone);
21557
21558	if (result != ISC_R_SUCCESS) {
21559		dnssec_log(zone, ISC_LOG_DEBUG(1),
21560			   "zone_rekey:dns_dnssec_findmatchingkeys failed: %s",
21561			   isc_result_totext(result));
21562	}
21563
21564	if (kasp != NULL) {
21565		/*
21566		 * Check DS at parental agents. Clear ongoing checks.
21567		 */
21568		LOCK_ZONE(zone);
21569		checkds_cancel(zone);
21570		clear_keylist(&zone->checkds_ok, zone->mctx);
21571		ISC_LIST_INIT(zone->checkds_ok);
21572		UNLOCK_ZONE(zone);
21573
21574		result = dns_zone_getdnsseckeys(zone, db, ver, now,
21575						&zone->checkds_ok);
21576
21577		if (result == ISC_R_SUCCESS) {
21578			zone_checkds(zone);
21579		} else {
21580			dnssec_log(zone,
21581				   (result == ISC_R_NOTFOUND) ? ISC_LOG_DEBUG(1)
21582							      : ISC_LOG_ERROR,
21583				   "zone_rekey:dns_zone_getdnsseckeys failed: "
21584				   "%s",
21585				   isc_result_totext(result));
21586		}
21587
21588		if (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND) {
21589			dns_zone_lock_keyfiles(zone);
21590			result = dns_keymgr_run(&zone->origin, zone->rdclass,
21591						dir, mctx, &keys, &dnskeys,
21592						kasp, now, &nexttime);
21593			dns_zone_unlock_keyfiles(zone);
21594
21595			if (result != ISC_R_SUCCESS) {
21596				dnssec_log(zone, ISC_LOG_ERROR,
21597					   "zone_rekey:dns_dnssec_keymgr "
21598					   "failed: %s",
21599					   isc_result_totext(result));
21600				KASP_UNLOCK(kasp);
21601				goto failure;
21602			}
21603		}
21604	}
21605
21606	KASP_UNLOCK(kasp);
21607
21608	if (result == ISC_R_SUCCESS) {
21609		bool cdsdel = false;
21610		bool cdnskeydel = false;
21611		bool sane_diff, sane_dnskey;
21612		isc_stdtime_t when;
21613
21614		/*
21615		 * Publish CDS/CDNSKEY DELETE records if the zone is
21616		 * transitioning from secure to insecure.
21617		 */
21618		if (kasp != NULL) {
21619			if (strcmp(dns_kasp_getname(kasp), "insecure") == 0) {
21620				cdsdel = true;
21621				cdnskeydel = true;
21622			}
21623		} else {
21624			/* Check if there is a CDS DELETE record. */
21625			if (dns_rdataset_isassociated(&cdsset)) {
21626				for (result = dns_rdataset_first(&cdsset);
21627				     result == ISC_R_SUCCESS;
21628				     result = dns_rdataset_next(&cdsset))
21629				{
21630					dns_rdata_t crdata = DNS_RDATA_INIT;
21631					dns_rdataset_current(&cdsset, &crdata);
21632					/*
21633					 * CDS deletion record has this form
21634					 * "0 0 0 00" which is 5 zero octets.
21635					 */
21636					if (crdata.length == 5U &&
21637					    memcmp(crdata.data,
21638						   (unsigned char[5]){ 0, 0, 0,
21639								       0, 0 },
21640						   5) == 0)
21641					{
21642						cdsdel = true;
21643						break;
21644					}
21645				}
21646			}
21647
21648			/* Check if there is a CDNSKEY DELETE record. */
21649			if (dns_rdataset_isassociated(&cdnskeyset)) {
21650				for (result = dns_rdataset_first(&cdnskeyset);
21651				     result == ISC_R_SUCCESS;
21652				     result = dns_rdataset_next(&cdnskeyset))
21653				{
21654					dns_rdata_t crdata = DNS_RDATA_INIT;
21655					dns_rdataset_current(&cdnskeyset,
21656							     &crdata);
21657					/*
21658					 * CDNSKEY deletion record has this form
21659					 * "0 3 0 AA==" which is 2 zero octets,
21660					 * a 3, and 2 zero octets.
21661					 */
21662					if (crdata.length == 5U &&
21663					    memcmp(crdata.data,
21664						   (unsigned char[5]){ 0, 0, 3,
21665								       0, 0 },
21666						   5) == 0)
21667					{
21668						cdnskeydel = true;
21669						break;
21670					}
21671				}
21672			}
21673		}
21674
21675		/*
21676		 * Only update DNSKEY TTL if we have a policy.
21677		 */
21678		if (kasp != NULL) {
21679			ttl = dns_kasp_dnskeyttl(kasp);
21680		}
21681
21682		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
21683					       &zone->origin, ttl, &diff, mctx,
21684					       dnssec_report);
21685		/*
21686		 * Keys couldn't be updated for some reason;
21687		 * try again later.
21688		 */
21689		if (result != ISC_R_SUCCESS) {
21690			dnssec_log(zone, ISC_LOG_ERROR,
21691				   "zone_rekey:couldn't update zone keys: %s",
21692				   isc_result_totext(result));
21693			goto failure;
21694		}
21695
21696		/*
21697		 * Update CDS / CDNSKEY records.
21698		 */
21699		result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
21700					       &cdnskeyset, now, ttl, &diff,
21701					       mctx);
21702		if (result != ISC_R_SUCCESS) {
21703			dnssec_log(zone, ISC_LOG_ERROR,
21704				   "zone_rekey:couldn't update CDS/CDNSKEY: %s",
21705				   isc_result_totext(result));
21706			goto failure;
21707		}
21708
21709		if (cdsdel || cdnskeydel) {
21710			/*
21711			 * Only publish CDS/CDNSKEY DELETE records if there is
21712			 * a KSK that can be used to verify the RRset. This
21713			 * means there must be a key with the KSK role that is
21714			 * published and is used for signing.
21715			 */
21716			bool allow = false;
21717			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21718			     key = ISC_LIST_NEXT(key, link))
21719			{
21720				dst_key_t *dstk = key->key;
21721
21722				if (dst_key_is_published(dstk, now, &when) &&
21723				    dst_key_is_signing(dstk, DST_BOOL_KSK, now,
21724						       &when))
21725				{
21726					allow = true;
21727					break;
21728				}
21729			}
21730			if (cdsdel) {
21731				cdsdel = allow;
21732			}
21733			if (cdnskeydel) {
21734				cdnskeydel = allow;
21735			}
21736		}
21737		result = dns_dnssec_syncdelete(
21738			&cdsset, &cdnskeyset, &zone->origin, zone->rdclass, ttl,
21739			&diff, mctx, cdsdel, cdnskeydel);
21740		if (result != ISC_R_SUCCESS) {
21741			dnssec_log(zone, ISC_LOG_ERROR,
21742				   "zone_rekey:couldn't update CDS/CDNSKEY "
21743				   "DELETE records: %s",
21744				   isc_result_totext(result));
21745			goto failure;
21746		}
21747
21748		/*
21749		 * See if any pre-existing keys have newly become active;
21750		 * also, see if any new key is for a new algorithm, as in that
21751		 * event, we need to sign the zone fully.  (If there's a new
21752		 * key, but it's for an already-existing algorithm, then
21753		 * the zone signing can be handled incrementally.)
21754		 */
21755		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21756		     key = ISC_LIST_NEXT(key, link))
21757		{
21758			if (!key->first_sign) {
21759				continue;
21760			}
21761
21762			newactive = true;
21763
21764			if (!dns_rdataset_isassociated(&keysigs)) {
21765				newalg = true;
21766				break;
21767			}
21768
21769			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
21770				/*
21771				 * This isn't a new algorithm; clear
21772				 * first_sign so we won't sign the
21773				 * whole zone with this key later.
21774				 */
21775				key->first_sign = false;
21776			} else {
21777				newalg = true;
21778				break;
21779			}
21780		}
21781
21782		/*
21783		 * A sane diff is one that is not empty, and that does not
21784		 * introduce a zone with NSEC only DNSKEYs along with NSEC3
21785		 * chains.
21786		 */
21787		sane_dnskey = dns_zone_check_dnskey_nsec3(zone, db, ver, &diff,
21788							  NULL, 0);
21789		sane_diff = !ISC_LIST_EMPTY(diff.tuples) && sane_dnskey;
21790		if (!sane_dnskey) {
21791			dnssec_log(zone, ISC_LOG_ERROR,
21792				   "NSEC only DNSKEYs and NSEC3 chains not "
21793				   "allowed");
21794		}
21795
21796		if (newactive || fullsign || sane_diff) {
21797			CHECK(dns_diff_apply(&diff, db, ver));
21798			CHECK(clean_nsec3param(zone, db, ver, &diff));
21799			CHECK(add_signing_records(db, zone->privatetype, ver,
21800						  &diff, (newalg || fullsign)));
21801			CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
21802						zone->updatemethod));
21803			CHECK(add_chains(zone, db, ver, &diff));
21804			CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
21805			CHECK(zone_journal(zone, zonediff.diff, NULL,
21806					   "zone_rekey"));
21807			commit = true;
21808		}
21809	}
21810
21811	dns_db_closeversion(db, &ver, true);
21812
21813	LOCK_ZONE(zone);
21814
21815	if (commit) {
21816		dns_difftuple_t *tuple;
21817		dns_stats_t *dnssecsignstats =
21818			dns_zone_getdnssecsignstats(zone);
21819
21820		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
21821
21822		zone_needdump(zone, DNS_DUMP_DELAY);
21823
21824		zone_settimer(zone, &timenow);
21825
21826		/* Remove any signatures from removed keys.  */
21827		if (!ISC_LIST_EMPTY(rmkeys)) {
21828			for (key = ISC_LIST_HEAD(rmkeys); key != NULL;
21829			     key = ISC_LIST_NEXT(key, link))
21830			{
21831				result = zone_signwithkey(
21832					zone, dst_key_alg(key->key),
21833					dst_key_id(key->key), true);
21834				if (result != ISC_R_SUCCESS) {
21835					dnssec_log(zone, ISC_LOG_ERROR,
21836						   "zone_signwithkey failed: "
21837						   "%s",
21838						   isc_result_totext(result));
21839				}
21840
21841				/* Clear DNSSEC sign statistics. */
21842				if (dnssecsignstats != NULL) {
21843					dns_dnssecsignstats_clear(
21844						dnssecsignstats,
21845						dst_key_id(key->key),
21846						dst_key_alg(key->key));
21847					/*
21848					 * Also clear the dnssec-sign
21849					 * statistics of the revoked key id.
21850					 */
21851					dns_dnssecsignstats_clear(
21852						dnssecsignstats,
21853						dst_key_rid(key->key),
21854						dst_key_alg(key->key));
21855				}
21856			}
21857		}
21858
21859		if (fullsign) {
21860			/*
21861			 * "rndc sign" was called, so we now sign the zone
21862			 * with all active keys, whether they're new or not.
21863			 */
21864			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21865			     key = ISC_LIST_NEXT(key, link))
21866			{
21867				if (!key->force_sign && !key->hint_sign) {
21868					continue;
21869				}
21870
21871				result = zone_signwithkey(
21872					zone, dst_key_alg(key->key),
21873					dst_key_id(key->key), false);
21874				if (result != ISC_R_SUCCESS) {
21875					dnssec_log(zone, ISC_LOG_ERROR,
21876						   "zone_signwithkey failed: "
21877						   "%s",
21878						   isc_result_totext(result));
21879				}
21880			}
21881		} else if (newalg) {
21882			/*
21883			 * We haven't been told to sign fully, but a new
21884			 * algorithm was added to the DNSKEY.  We sign
21885			 * the full zone, but only with newly active
21886			 * keys.
21887			 */
21888			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21889			     key = ISC_LIST_NEXT(key, link))
21890			{
21891				if (!key->first_sign) {
21892					continue;
21893				}
21894
21895				result = zone_signwithkey(
21896					zone, dst_key_alg(key->key),
21897					dst_key_id(key->key), false);
21898				if (result != ISC_R_SUCCESS) {
21899					dnssec_log(zone, ISC_LOG_ERROR,
21900						   "zone_signwithkey failed: "
21901						   "%s",
21902						   isc_result_totext(result));
21903				}
21904			}
21905		}
21906
21907		/*
21908		 * Clear fullsign flag, if it was set, so we don't do
21909		 * another full signing next time.
21910		 */
21911		DNS_ZONEKEY_CLROPTION(zone, DNS_ZONEKEY_FULLSIGN);
21912
21913		/*
21914		 * Cause the zone to add/delete NSEC3 chains for the
21915		 * deferred NSEC3PARAM changes.
21916		 */
21917		for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
21918		     tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
21919		{
21920			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
21921			dns_rdata_t rdata = DNS_RDATA_INIT;
21922			dns_rdata_nsec3param_t nsec3param;
21923
21924			if (tuple->rdata.type != zone->privatetype ||
21925			    tuple->op != DNS_DIFFOP_ADD)
21926			{
21927				continue;
21928			}
21929
21930			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
21931							buf, sizeof(buf)))
21932			{
21933				continue;
21934			}
21935
21936			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
21937			RUNTIME_CHECK(result == ISC_R_SUCCESS);
21938			if (nsec3param.flags == 0) {
21939				continue;
21940			}
21941
21942			result = zone_addnsec3chain(zone, &nsec3param);
21943			if (result != ISC_R_SUCCESS) {
21944				dnssec_log(zone, ISC_LOG_ERROR,
21945					   "zone_addnsec3chain failed: %s",
21946					   isc_result_totext(result));
21947			}
21948		}
21949
21950		/*
21951		 * Activate any NSEC3 chain updates that may have
21952		 * been scheduled before this rekey.
21953		 */
21954		if (fullsign || newalg) {
21955			resume_addnsec3chain(zone);
21956		}
21957
21958		/*
21959		 * Schedule the next resigning event
21960		 */
21961		set_resigntime(zone);
21962	}
21963
21964	isc_time_settoepoch(&zone->refreshkeytime);
21965
21966	/*
21967	 * If keymgr provided a next time, use the calculated next rekey time.
21968	 */
21969	if (kasp != NULL) {
21970		isc_time_t timenext;
21971		uint32_t nexttime_seconds;
21972
21973		/*
21974		 * Set the key refresh timer to the next scheduled key event
21975		 * or to 'dnssec-loadkeys-interval' seconds in the future
21976		 * if no next key event is scheduled (nexttime == 0).
21977		 */
21978		if (nexttime > 0) {
21979			nexttime_seconds = nexttime - now;
21980		} else {
21981			nexttime_seconds = zone->refreshkeyinterval;
21982		}
21983
21984		DNS_ZONE_TIME_ADD(&timenow, nexttime_seconds, &timenext);
21985		zone->refreshkeytime = timenext;
21986		zone_settimer(zone, &timenow);
21987		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
21988
21989		dnssec_log(zone, ISC_LOG_DEBUG(3),
21990			   "next key event in %u seconds", nexttime_seconds);
21991		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
21992	}
21993	/*
21994	 * If we're doing key maintenance, set the key refresh timer to
21995	 * the next scheduled key event or to 'dnssec-loadkeys-interval'
21996	 * seconds in the future, whichever is sooner.
21997	 */
21998	else if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
21999	{
22000		isc_time_t timethen;
22001		isc_stdtime_t then;
22002
22003		DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
22004				  &timethen);
22005		zone->refreshkeytime = timethen;
22006
22007		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
22008		     key = ISC_LIST_NEXT(key, link))
22009		{
22010			then = now;
22011			result = next_keyevent(key->key, &then);
22012			if (result != ISC_R_SUCCESS) {
22013				continue;
22014			}
22015
22016			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
22017			if (isc_time_compare(&timethen, &zone->refreshkeytime) <
22018			    0)
22019			{
22020				zone->refreshkeytime = timethen;
22021			}
22022		}
22023
22024		zone_settimer(zone, &timenow);
22025
22026		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
22027		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
22028	}
22029	UNLOCK_ZONE(zone);
22030
22031	if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
22032		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
22033		     key = ISC_LIST_NEXT(key, link))
22034		{
22035			/* This debug log is used in the kasp system test */
22036			char algbuf[DNS_SECALG_FORMATSIZE];
22037			dns_secalg_format(dst_key_alg(key->key), algbuf,
22038					  sizeof(algbuf));
22039			dnssec_log(zone, ISC_LOG_DEBUG(3),
22040				   "zone_rekey done: key %d/%s",
22041				   dst_key_id(key->key), algbuf);
22042		}
22043	}
22044
22045	result = ISC_R_SUCCESS;
22046
22047failure:
22048	LOCK_ZONE(zone);
22049	if (result != ISC_R_SUCCESS) {
22050		/*
22051		 * Something went wrong; try again in ten minutes or
22052		 * after a key refresh interval, whichever is shorter.
22053		 */
22054		dnssec_log(zone, ISC_LOG_DEBUG(3),
22055			   "zone_rekey failure: %s (retry in %u seconds)",
22056			   isc_result_totext(result),
22057			   ISC_MIN(zone->refreshkeyinterval, 600));
22058		isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600),
22059				 0);
22060		isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
22061	}
22062	UNLOCK_ZONE(zone);
22063
22064	dns_diff_clear(&diff);
22065	dns_diff_clear(&_sig_diff);
22066
22067	clear_keylist(&dnskeys, mctx);
22068	clear_keylist(&keys, mctx);
22069	clear_keylist(&rmkeys, mctx);
22070
22071	if (ver != NULL) {
22072		dns_db_closeversion(db, &ver, false);
22073	}
22074	if (dns_rdataset_isassociated(&cdsset)) {
22075		dns_rdataset_disassociate(&cdsset);
22076	}
22077	if (dns_rdataset_isassociated(&keyset)) {
22078		dns_rdataset_disassociate(&keyset);
22079	}
22080	if (dns_rdataset_isassociated(&keysigs)) {
22081		dns_rdataset_disassociate(&keysigs);
22082	}
22083	if (dns_rdataset_isassociated(&soasigs)) {
22084		dns_rdataset_disassociate(&soasigs);
22085	}
22086	if (dns_rdataset_isassociated(&cdnskeyset)) {
22087		dns_rdataset_disassociate(&cdnskeyset);
22088	}
22089	if (node != NULL) {
22090		dns_db_detachnode(db, &node);
22091	}
22092	if (db != NULL) {
22093		dns_db_detach(&db);
22094	}
22095
22096	INSIST(ver == NULL);
22097}
22098
22099void
22100dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
22101	isc_time_t now;
22102
22103	if (zone->type == dns_zone_primary && zone->task != NULL) {
22104		LOCK_ZONE(zone);
22105
22106		if (fullsign) {
22107			DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
22108		}
22109
22110		TIME_NOW(&now);
22111		zone->refreshkeytime = now;
22112		zone_settimer(zone, &now);
22113
22114		UNLOCK_ZONE(zone);
22115	}
22116}
22117
22118isc_result_t
22119dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
22120		 unsigned int *errors) {
22121	isc_result_t result;
22122	dns_dbnode_t *node = NULL;
22123
22124	REQUIRE(DNS_ZONE_VALID(zone));
22125	REQUIRE(errors != NULL);
22126
22127	result = dns_db_getoriginnode(db, &node);
22128	if (result != ISC_R_SUCCESS) {
22129		return (result);
22130	}
22131	result = zone_count_ns_rr(zone, db, node, version, NULL, errors, false);
22132	dns_db_detachnode(db, &node);
22133	return (result);
22134}
22135
22136isc_result_t
22137dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
22138	isc_result_t result;
22139	dns_dbnode_t *node = NULL;
22140	dns_rdataset_t dnskey, cds, cdnskey;
22141	unsigned char algorithms[256];
22142	unsigned int i;
22143	bool empty = false;
22144
22145	enum { notexpected = 0, expected = 1, found = 2 };
22146
22147	REQUIRE(DNS_ZONE_VALID(zone));
22148
22149	result = dns_db_getoriginnode(db, &node);
22150	if (result != ISC_R_SUCCESS) {
22151		return (result);
22152	}
22153
22154	dns_rdataset_init(&cds);
22155	dns_rdataset_init(&dnskey);
22156	dns_rdataset_init(&cdnskey);
22157
22158	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
22159				     dns_rdatatype_none, 0, &cds, NULL);
22160	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
22161		goto failure;
22162	}
22163
22164	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
22165				     dns_rdatatype_none, 0, &cdnskey, NULL);
22166	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
22167		goto failure;
22168	}
22169
22170	if (!dns_rdataset_isassociated(&cds) &&
22171	    !dns_rdataset_isassociated(&cdnskey))
22172	{
22173		result = ISC_R_SUCCESS;
22174		goto failure;
22175	}
22176
22177	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
22178				     dns_rdatatype_none, 0, &dnskey, NULL);
22179	if (result == ISC_R_NOTFOUND) {
22180		empty = true;
22181	} else if (result != ISC_R_SUCCESS) {
22182		goto failure;
22183	}
22184
22185	/*
22186	 * For each DNSSEC algorithm in the CDS RRset there must be
22187	 * a matching DNSKEY record with the exception of a CDS deletion
22188	 * record which must be by itself.
22189	 */
22190	if (dns_rdataset_isassociated(&cds)) {
22191		bool delete = false;
22192		memset(algorithms, notexpected, sizeof(algorithms));
22193		for (result = dns_rdataset_first(&cds); result == ISC_R_SUCCESS;
22194		     result = dns_rdataset_next(&cds))
22195		{
22196			dns_rdata_t crdata = DNS_RDATA_INIT;
22197			dns_rdata_cds_t structcds;
22198
22199			dns_rdataset_current(&cds, &crdata);
22200			/*
22201			 * CDS deletion record has this form "0 0 0 00" which
22202			 * is 5 zero octets.
22203			 */
22204			if (crdata.length == 5U &&
22205			    memcmp(crdata.data,
22206				   (unsigned char[5]){ 0, 0, 0, 0, 0 }, 5) == 0)
22207			{
22208				delete = true;
22209				continue;
22210			}
22211
22212			if (empty) {
22213				result = DNS_R_BADCDS;
22214				goto failure;
22215			}
22216
22217			CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
22218			if (algorithms[structcds.algorithm] == 0) {
22219				algorithms[structcds.algorithm] = expected;
22220			}
22221			for (result = dns_rdataset_first(&dnskey);
22222			     result == ISC_R_SUCCESS;
22223			     result = dns_rdataset_next(&dnskey))
22224			{
22225				dns_rdata_t rdata = DNS_RDATA_INIT;
22226				dns_rdata_dnskey_t structdnskey;
22227
22228				dns_rdataset_current(&dnskey, &rdata);
22229				CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
22230							 NULL));
22231
22232				if (structdnskey.algorithm ==
22233				    structcds.algorithm)
22234				{
22235					algorithms[structcds.algorithm] = found;
22236				}
22237			}
22238			if (result != ISC_R_NOMORE) {
22239				goto failure;
22240			}
22241		}
22242		for (i = 0; i < sizeof(algorithms); i++) {
22243			if (delete) {
22244				if (algorithms[i] != notexpected) {
22245					result = DNS_R_BADCDS;
22246					goto failure;
22247				}
22248			} else if (algorithms[i] == expected) {
22249				result = DNS_R_BADCDS;
22250				goto failure;
22251			}
22252		}
22253	}
22254
22255	/*
22256	 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
22257	 * a matching DNSKEY record with the exception of a CDNSKEY deletion
22258	 * record which must be by itself.
22259	 */
22260	if (dns_rdataset_isassociated(&cdnskey)) {
22261		bool delete = false;
22262		memset(algorithms, notexpected, sizeof(algorithms));
22263		for (result = dns_rdataset_first(&cdnskey);
22264		     result == ISC_R_SUCCESS;
22265		     result = dns_rdataset_next(&cdnskey))
22266		{
22267			dns_rdata_t crdata = DNS_RDATA_INIT;
22268			dns_rdata_cdnskey_t structcdnskey;
22269
22270			dns_rdataset_current(&cdnskey, &crdata);
22271			/*
22272			 * CDNSKEY deletion record has this form
22273			 * "0 3 0 AA==" which is 2 zero octets, a 3,
22274			 * and 2 zero octets.
22275			 */
22276			if (crdata.length == 5U &&
22277			    memcmp(crdata.data,
22278				   (unsigned char[5]){ 0, 0, 3, 0, 0 }, 5) == 0)
22279			{
22280				delete = true;
22281				continue;
22282			}
22283
22284			if (empty) {
22285				result = DNS_R_BADCDNSKEY;
22286				goto failure;
22287			}
22288
22289			CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
22290						 NULL));
22291			if (algorithms[structcdnskey.algorithm] == 0) {
22292				algorithms[structcdnskey.algorithm] = expected;
22293			}
22294			for (result = dns_rdataset_first(&dnskey);
22295			     result == ISC_R_SUCCESS;
22296			     result = dns_rdataset_next(&dnskey))
22297			{
22298				dns_rdata_t rdata = DNS_RDATA_INIT;
22299				dns_rdata_dnskey_t structdnskey;
22300
22301				dns_rdataset_current(&dnskey, &rdata);
22302				CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
22303							 NULL));
22304
22305				if (structdnskey.algorithm ==
22306				    structcdnskey.algorithm)
22307				{
22308					algorithms[structcdnskey.algorithm] =
22309						found;
22310				}
22311			}
22312			if (result != ISC_R_NOMORE) {
22313				goto failure;
22314			}
22315		}
22316		for (i = 0; i < sizeof(algorithms); i++) {
22317			if (delete) {
22318				if (algorithms[i] != notexpected) {
22319					result = DNS_R_BADCDNSKEY;
22320					goto failure;
22321				}
22322			} else if (algorithms[i] == expected) {
22323				result = DNS_R_BADCDNSKEY;
22324				goto failure;
22325			}
22326		}
22327	}
22328	result = ISC_R_SUCCESS;
22329
22330failure:
22331	if (dns_rdataset_isassociated(&cds)) {
22332		dns_rdataset_disassociate(&cds);
22333	}
22334	if (dns_rdataset_isassociated(&dnskey)) {
22335		dns_rdataset_disassociate(&dnskey);
22336	}
22337	if (dns_rdataset_isassociated(&cdnskey)) {
22338		dns_rdataset_disassociate(&cdnskey);
22339	}
22340	dns_db_detachnode(db, &node);
22341	return (result);
22342}
22343
22344void
22345dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
22346	REQUIRE(DNS_ZONE_VALID(zone));
22347
22348	LOCK_ZONE(zone);
22349	zone->automatic = automatic;
22350	UNLOCK_ZONE(zone);
22351}
22352
22353bool
22354dns_zone_getautomatic(dns_zone_t *zone) {
22355	REQUIRE(DNS_ZONE_VALID(zone));
22356	return (zone->automatic);
22357}
22358
22359void
22360dns_zone_setadded(dns_zone_t *zone, bool added) {
22361	REQUIRE(DNS_ZONE_VALID(zone));
22362
22363	LOCK_ZONE(zone);
22364	zone->added = added;
22365	UNLOCK_ZONE(zone);
22366}
22367
22368bool
22369dns_zone_getadded(dns_zone_t *zone) {
22370	REQUIRE(DNS_ZONE_VALID(zone));
22371	return (zone->added);
22372}
22373
22374isc_result_t
22375dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) {
22376	isc_time_t loadtime;
22377	isc_result_t result;
22378	dns_zone_t *secure = NULL;
22379
22380	TIME_NOW(&loadtime);
22381
22382	/*
22383	 * Lock hierarchy: zmgr, zone, raw.
22384	 */
22385again:
22386	LOCK_ZONE(zone);
22387	INSIST(zone != zone->raw);
22388	if (inline_secure(zone)) {
22389		LOCK_ZONE(zone->raw);
22390	} else if (inline_raw(zone)) {
22391		secure = zone->secure;
22392		TRYLOCK_ZONE(result, secure);
22393		if (result != ISC_R_SUCCESS) {
22394			UNLOCK_ZONE(zone);
22395			secure = NULL;
22396			isc_thread_yield();
22397			goto again;
22398		}
22399	}
22400	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
22401	if (inline_secure(zone)) {
22402		UNLOCK_ZONE(zone->raw);
22403	} else if (secure != NULL) {
22404		UNLOCK_ZONE(secure);
22405	}
22406	UNLOCK_ZONE(zone);
22407	return (result);
22408}
22409
22410isc_result_t
22411dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
22412	REQUIRE(DNS_ZONE_VALID(zone));
22413	if (interval == 0) {
22414		return (ISC_R_RANGE);
22415	}
22416	/* Maximum value: 24 hours (3600 minutes) */
22417	if (interval > (24 * 60)) {
22418		interval = (24 * 60);
22419	}
22420	/* Multiply by 60 for seconds */
22421	zone->refreshkeyinterval = interval * 60;
22422	return (ISC_R_SUCCESS);
22423}
22424
22425void
22426dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
22427	REQUIRE(DNS_ZONE_VALID(zone));
22428	zone->requestixfr = flag;
22429}
22430
22431bool
22432dns_zone_getrequestixfr(dns_zone_t *zone) {
22433	REQUIRE(DNS_ZONE_VALID(zone));
22434	return (zone->requestixfr);
22435}
22436
22437void
22438dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
22439	REQUIRE(DNS_ZONE_VALID(zone));
22440	zone->ixfr_ratio = ratio;
22441}
22442
22443uint32_t
22444dns_zone_getixfrratio(dns_zone_t *zone) {
22445	REQUIRE(DNS_ZONE_VALID(zone));
22446	return (zone->ixfr_ratio);
22447}
22448
22449void
22450dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
22451	REQUIRE(DNS_ZONE_VALID(zone));
22452	zone->requestexpire = flag;
22453}
22454
22455bool
22456dns_zone_getrequestexpire(dns_zone_t *zone) {
22457	REQUIRE(DNS_ZONE_VALID(zone));
22458	return (zone->requestexpire);
22459}
22460
22461void
22462dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
22463	REQUIRE(DNS_ZONE_VALID(zone));
22464	zone->updatemethod = method;
22465}
22466
22467dns_updatemethod_t
22468dns_zone_getserialupdatemethod(dns_zone_t *zone) {
22469	REQUIRE(DNS_ZONE_VALID(zone));
22470	return (zone->updatemethod);
22471}
22472
22473/*
22474 * Lock hierarchy: zmgr, zone, raw.
22475 */
22476isc_result_t
22477dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
22478	isc_result_t result;
22479	dns_zonemgr_t *zmgr;
22480
22481	REQUIRE(DNS_ZONE_VALID(zone));
22482	REQUIRE(zone->zmgr != NULL);
22483	REQUIRE(zone->task != NULL);
22484	REQUIRE(zone->loadtask != NULL);
22485	REQUIRE(zone->raw == NULL);
22486
22487	REQUIRE(DNS_ZONE_VALID(raw));
22488	REQUIRE(raw->zmgr == NULL);
22489	REQUIRE(raw->task == NULL);
22490	REQUIRE(raw->loadtask == NULL);
22491	REQUIRE(raw->secure == NULL);
22492
22493	REQUIRE(zone != raw);
22494
22495	/*
22496	 * Lock hierarchy: zmgr, zone, raw.
22497	 */
22498	zmgr = zone->zmgr;
22499	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
22500	LOCK_ZONE(zone);
22501	LOCK_ZONE(raw);
22502
22503	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
22504				  NULL, zone->task, zone_timer, raw,
22505				  &raw->timer);
22506	if (result != ISC_R_SUCCESS) {
22507		goto unlock;
22508	}
22509
22510	/*
22511	 * The timer "holds" a iref.
22512	 */
22513	isc_refcount_increment0(&raw->irefs);
22514
22515	/* dns_zone_attach(raw, &zone->raw); */
22516	isc_refcount_increment(&raw->erefs);
22517	zone->raw = raw;
22518
22519	/* dns_zone_iattach(zone,  &raw->secure); */
22520	zone_iattach(zone, &raw->secure);
22521
22522	isc_task_attach(zone->task, &raw->task);
22523	isc_task_attach(zone->loadtask, &raw->loadtask);
22524
22525	ISC_LIST_APPEND(zmgr->zones, raw, link);
22526	raw->zmgr = zmgr;
22527	isc_refcount_increment(&zmgr->refs);
22528
22529unlock:
22530	UNLOCK_ZONE(raw);
22531	UNLOCK_ZONE(zone);
22532	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
22533	return (result);
22534}
22535
22536void
22537dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
22538	REQUIRE(DNS_ZONE_VALID(zone));
22539	REQUIRE(raw != NULL && *raw == NULL);
22540
22541	LOCK(&zone->lock);
22542	INSIST(zone != zone->raw);
22543	if (zone->raw != NULL) {
22544		dns_zone_attach(zone->raw, raw);
22545	}
22546	UNLOCK(&zone->lock);
22547}
22548
22549struct keydone {
22550	isc_event_t event;
22551	bool all;
22552	unsigned char data[5];
22553};
22554
22555#define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL)
22556
22557static void
22558keydone(isc_task_t *task, isc_event_t *event) {
22559	const char *me = "keydone";
22560	bool commit = false;
22561	isc_result_t result;
22562	dns_rdata_t rdata = DNS_RDATA_INIT;
22563	dns_dbversion_t *oldver = NULL, *newver = NULL;
22564	dns_zone_t *zone;
22565	dns_db_t *db = NULL;
22566	dns_dbnode_t *node = NULL;
22567	dns_rdataset_t rdataset;
22568	dns_diff_t diff;
22569	struct keydone *kd = (struct keydone *)event;
22570	dns_update_log_t log = { update_log_cb, NULL };
22571	bool clear_pending = false;
22572
22573	UNUSED(task);
22574
22575	zone = event->ev_arg;
22576	INSIST(DNS_ZONE_VALID(zone));
22577
22578	ENTER;
22579
22580	dns_rdataset_init(&rdataset);
22581	dns_diff_init(zone->mctx, &diff);
22582
22583	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22584	if (zone->db != NULL) {
22585		dns_db_attach(zone->db, &db);
22586	}
22587	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22588	if (db == NULL) {
22589		goto failure;
22590	}
22591
22592	dns_db_currentversion(db, &oldver);
22593	result = dns_db_newversion(db, &newver);
22594	if (result != ISC_R_SUCCESS) {
22595		dnssec_log(zone, ISC_LOG_ERROR,
22596			   "keydone:dns_db_newversion -> %s",
22597			   isc_result_totext(result));
22598		goto failure;
22599	}
22600
22601	result = dns_db_getoriginnode(db, &node);
22602	if (result != ISC_R_SUCCESS) {
22603		goto failure;
22604	}
22605
22606	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
22607				     dns_rdatatype_none, 0, &rdataset, NULL);
22608	if (result == ISC_R_NOTFOUND) {
22609		INSIST(!dns_rdataset_isassociated(&rdataset));
22610		goto failure;
22611	}
22612	if (result != ISC_R_SUCCESS) {
22613		INSIST(!dns_rdataset_isassociated(&rdataset));
22614		goto failure;
22615	}
22616
22617	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
22618	     result = dns_rdataset_next(&rdataset))
22619	{
22620		bool found = false;
22621
22622		dns_rdataset_current(&rdataset, &rdata);
22623
22624		if (kd->all) {
22625			if (rdata.length == 5 && rdata.data[0] != 0 &&
22626			    rdata.data[3] == 0 && rdata.data[4] == 1)
22627			{
22628				found = true;
22629			} else if (rdata.data[0] == 0 &&
22630				   (rdata.data[2] & PENDINGFLAGS) != 0)
22631			{
22632				found = true;
22633				clear_pending = true;
22634			}
22635		} else if (rdata.length == 5 &&
22636			   memcmp(rdata.data, kd->data, 5) == 0)
22637		{
22638			found = true;
22639		}
22640
22641		if (found) {
22642			CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
22643					    &zone->origin, rdataset.ttl,
22644					    &rdata));
22645		}
22646		dns_rdata_reset(&rdata);
22647	}
22648
22649	if (!ISC_LIST_EMPTY(diff.tuples)) {
22650		/* Write changes to journal file. */
22651		CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
22652					zone->updatemethod));
22653
22654		result = dns_update_signatures(&log, zone, db, oldver, newver,
22655					       &diff,
22656					       zone->sigvalidityinterval);
22657		if (!clear_pending) {
22658			CHECK(result);
22659		}
22660
22661		CHECK(zone_journal(zone, &diff, NULL, "keydone"));
22662		commit = true;
22663
22664		LOCK_ZONE(zone);
22665		DNS_ZONE_SETFLAG(zone,
22666				 DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
22667		zone_needdump(zone, 30);
22668		UNLOCK_ZONE(zone);
22669	}
22670
22671failure:
22672	if (dns_rdataset_isassociated(&rdataset)) {
22673		dns_rdataset_disassociate(&rdataset);
22674	}
22675	if (db != NULL) {
22676		if (node != NULL) {
22677			dns_db_detachnode(db, &node);
22678		}
22679		if (oldver != NULL) {
22680			dns_db_closeversion(db, &oldver, false);
22681		}
22682		if (newver != NULL) {
22683			dns_db_closeversion(db, &newver, commit);
22684		}
22685		dns_db_detach(&db);
22686	}
22687	dns_diff_clear(&diff);
22688	isc_event_free(&event);
22689	dns_zone_idetach(&zone);
22690
22691	INSIST(oldver == NULL);
22692	INSIST(newver == NULL);
22693}
22694
22695isc_result_t
22696dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
22697	isc_result_t result = ISC_R_SUCCESS;
22698	isc_event_t *e;
22699	isc_buffer_t b;
22700	dns_zone_t *dummy = NULL;
22701	struct keydone *kd;
22702
22703	REQUIRE(DNS_ZONE_VALID(zone));
22704
22705	LOCK_ZONE(zone);
22706
22707	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
22708			       zone, sizeof(struct keydone));
22709
22710	kd = (struct keydone *)e;
22711	if (strcasecmp(keystr, "all") == 0) {
22712		kd->all = true;
22713	} else {
22714		isc_textregion_t r;
22715		const char *algstr;
22716		dns_keytag_t keyid;
22717		dns_secalg_t alg;
22718		size_t n;
22719
22720		kd->all = false;
22721
22722		n = sscanf(keystr, "%hu/", &keyid);
22723		if (n == 0U) {
22724			CHECK(ISC_R_FAILURE);
22725		}
22726
22727		algstr = strchr(keystr, '/');
22728		if (algstr != NULL) {
22729			algstr++;
22730		} else {
22731			CHECK(ISC_R_FAILURE);
22732		}
22733
22734		n = sscanf(algstr, "%hhu", &alg);
22735		if (n == 0U) {
22736			DE_CONST(algstr, r.base);
22737			r.length = strlen(algstr);
22738			CHECK(dns_secalg_fromtext(&alg, &r));
22739		}
22740
22741		/* construct a private-type rdata */
22742		isc_buffer_init(&b, kd->data, sizeof(kd->data));
22743		isc_buffer_putuint8(&b, alg);
22744		isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
22745		isc_buffer_putuint8(&b, (keyid & 0xff));
22746		isc_buffer_putuint8(&b, 0);
22747		isc_buffer_putuint8(&b, 1);
22748	}
22749
22750	zone_iattach(zone, &dummy);
22751	isc_task_send(zone->task, &e);
22752
22753failure:
22754	if (e != NULL) {
22755		isc_event_free(&e);
22756	}
22757	UNLOCK_ZONE(zone);
22758	return (result);
22759}
22760
22761/*
22762 * Called from the zone task's queue after the relevant event is posted by
22763 * dns_zone_setnsec3param().
22764 */
22765static void
22766setnsec3param(isc_task_t *task, isc_event_t *event) {
22767	const char *me = "setnsec3param";
22768	dns_zone_t *zone = event->ev_arg;
22769	bool loadpending;
22770
22771	INSIST(DNS_ZONE_VALID(zone));
22772
22773	UNUSED(task);
22774
22775	ENTER;
22776
22777	LOCK_ZONE(zone);
22778	loadpending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
22779	UNLOCK_ZONE(zone);
22780
22781	/*
22782	 * If receive_secure_serial is still processing or we have a
22783	 * queued event append rss_post queue.
22784	 */
22785	if (zone->rss_newver != NULL || ISC_LIST_HEAD(zone->rss_post) != NULL) {
22786		/*
22787		 * Wait for receive_secure_serial() to finish processing.
22788		 */
22789		ISC_LIST_APPEND(zone->rss_post, event, ev_link);
22790	} else {
22791		bool rescheduled = false;
22792		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22793		/*
22794		 * The zone is not yet fully loaded. Reschedule the event to
22795		 * be picked up later. This turns this function into a busy
22796		 * wait, but it only happens at startup.
22797		 */
22798		if (zone->db == NULL && loadpending) {
22799			rescheduled = true;
22800			isc_task_send(task, &event);
22801		}
22802		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22803		if (rescheduled) {
22804			return;
22805		}
22806
22807		rss_post(zone, event);
22808	}
22809	dns_zone_idetach(&zone);
22810}
22811
22812static void
22813salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
22814	  unsigned int textlen) {
22815	isc_region_t r;
22816	isc_buffer_t buf;
22817	isc_result_t result;
22818
22819	r.base = salt;
22820	r.length = (unsigned int)saltlen;
22821
22822	isc_buffer_init(&buf, text, textlen);
22823	result = isc_hex_totext(&r, 2, "", &buf);
22824	if (result == ISC_R_SUCCESS) {
22825		text[saltlen * 2] = 0;
22826	} else {
22827		text[0] = 0;
22828	}
22829}
22830
22831/*
22832 * Check whether NSEC3 chain addition or removal specified by the private-type
22833 * record passed with the event was already queued (or even fully performed).
22834 * If not, modify the relevant private-type records at the zone apex and call
22835 * resume_addnsec3chain().
22836 */
22837static void
22838rss_post(dns_zone_t *zone, isc_event_t *event) {
22839	const char *me = "rss_post";
22840	bool commit = false;
22841	isc_result_t result;
22842	dns_dbversion_t *oldver = NULL, *newver = NULL;
22843	dns_db_t *db = NULL;
22844	dns_dbnode_t *node = NULL;
22845	dns_rdataset_t prdataset, nrdataset;
22846	dns_diff_t diff;
22847	struct np3event *npe = (struct np3event *)event;
22848	nsec3param_t *np;
22849	dns_update_log_t log = { update_log_cb, NULL };
22850	dns_rdata_t rdata;
22851	bool nseconly;
22852	bool exists = false;
22853
22854	ENTER;
22855
22856	np = &npe->params;
22857
22858	dns_rdataset_init(&prdataset);
22859	dns_rdataset_init(&nrdataset);
22860	dns_diff_init(zone->mctx, &diff);
22861
22862	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22863	if (zone->db != NULL) {
22864		dns_db_attach(zone->db, &db);
22865	}
22866	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22867	if (db == NULL) {
22868		goto failure;
22869	}
22870
22871	dns_db_currentversion(db, &oldver);
22872	result = dns_db_newversion(db, &newver);
22873	if (result != ISC_R_SUCCESS) {
22874		dnssec_log(zone, ISC_LOG_ERROR,
22875			   "setnsec3param:dns_db_newversion -> %s",
22876			   isc_result_totext(result));
22877		goto failure;
22878	}
22879
22880	CHECK(dns_db_getoriginnode(db, &node));
22881
22882	/*
22883	 * Do we need to look up the NSEC3 parameters?
22884	 */
22885	if (np->lookup) {
22886		dns_rdata_nsec3param_t param;
22887		dns_rdata_t nrdata = DNS_RDATA_INIT;
22888		dns_rdata_t prdata = DNS_RDATA_INIT;
22889		unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
22890		unsigned char saltbuf[255];
22891		isc_buffer_t b;
22892
22893		param.salt = NULL;
22894		result = dns__zone_lookup_nsec3param(zone, &np->rdata, &param,
22895						     saltbuf, np->resalt);
22896		if (result == ISC_R_SUCCESS) {
22897			/*
22898			 * Success because the NSEC3PARAM already exists, but
22899			 * function returns void, so goto failure to clean up.
22900			 */
22901			goto failure;
22902		}
22903		if (result != DNS_R_NSEC3RESALT && result != ISC_R_NOTFOUND) {
22904			dnssec_log(zone, ISC_LOG_DEBUG(3),
22905				   "setnsec3param:lookup nsec3param -> %s",
22906				   isc_result_totext(result));
22907			goto failure;
22908		}
22909
22910		INSIST(param.salt != NULL);
22911
22912		/* Update NSEC3 parameters. */
22913		np->rdata.hash = param.hash;
22914		np->rdata.flags = param.flags;
22915		np->rdata.iterations = param.iterations;
22916		np->rdata.salt_length = param.salt_length;
22917		np->rdata.salt = param.salt;
22918
22919		isc_buffer_init(&b, nbuf, sizeof(nbuf));
22920		CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
22921					   dns_rdatatype_nsec3param, &np->rdata,
22922					   &b));
22923		dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
22924					 np->data, sizeof(np->data));
22925		np->length = prdata.length;
22926		np->nsec = false;
22927	}
22928
22929	/*
22930	 * Does a private-type record already exist for this chain?
22931	 */
22932	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
22933				     dns_rdatatype_none, 0, &prdataset, NULL);
22934	if (result == ISC_R_SUCCESS) {
22935		for (result = dns_rdataset_first(&prdataset);
22936		     result == ISC_R_SUCCESS;
22937		     result = dns_rdataset_next(&prdataset))
22938		{
22939			dns_rdata_init(&rdata);
22940			dns_rdataset_current(&prdataset, &rdata);
22941
22942			if (np->length == rdata.length &&
22943			    memcmp(rdata.data, np->data, np->length) == 0)
22944			{
22945				exists = true;
22946				break;
22947			}
22948		}
22949	} else if (result != ISC_R_NOTFOUND) {
22950		INSIST(!dns_rdataset_isassociated(&prdataset));
22951		goto failure;
22952	}
22953
22954	/*
22955	 * Does the chain already exist?
22956	 */
22957	result = dns_db_findrdataset(db, node, newver, dns_rdatatype_nsec3param,
22958				     dns_rdatatype_none, 0, &nrdataset, NULL);
22959	if (result == ISC_R_SUCCESS) {
22960		for (result = dns_rdataset_first(&nrdataset);
22961		     result == ISC_R_SUCCESS;
22962		     result = dns_rdataset_next(&nrdataset))
22963		{
22964			dns_rdata_init(&rdata);
22965			dns_rdataset_current(&nrdataset, &rdata);
22966
22967			if (np->length == (rdata.length + 1) &&
22968			    memcmp(rdata.data, np->data + 1, np->length - 1) ==
22969				    0)
22970			{
22971				exists = true;
22972				break;
22973			}
22974		}
22975	} else if (result != ISC_R_NOTFOUND) {
22976		INSIST(!dns_rdataset_isassociated(&nrdataset));
22977		goto failure;
22978	}
22979
22980	/*
22981	 * We need to remove any existing NSEC3 chains if the supplied NSEC3
22982	 * parameters are supposed to replace the current ones or if we are
22983	 * switching to NSEC.
22984	 */
22985	if (!exists && np->replace && (np->length != 0 || np->nsec)) {
22986		CHECK(dns_nsec3param_deletechains(db, newver, zone, !np->nsec,
22987						  &diff));
22988	}
22989
22990	if (!exists && np->length != 0) {
22991		/*
22992		 * We're creating an NSEC3 chain.  Add the private-type record
22993		 * passed in the event handler's argument to the zone apex.
22994		 *
22995		 * If the zone is not currently capable of supporting an NSEC3
22996		 * chain (due to the DNSKEY RRset at the zone apex not existing
22997		 * or containing at least one key using an NSEC-only
22998		 * algorithm), add the INITIAL flag, so these parameters can be
22999		 * used later when NSEC3 becomes available.
23000		 */
23001		dns_rdata_init(&rdata);
23002
23003		np->data[2] |= DNS_NSEC3FLAG_CREATE;
23004		result = dns_nsec_nseconly(db, newver, NULL, &nseconly);
23005		if (result == ISC_R_NOTFOUND || nseconly) {
23006			np->data[2] |= DNS_NSEC3FLAG_INITIAL;
23007		}
23008
23009		rdata.length = np->length;
23010		rdata.data = np->data;
23011		rdata.type = zone->privatetype;
23012		rdata.rdclass = zone->rdclass;
23013		CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
23014				    &zone->origin, 0, &rdata));
23015	}
23016
23017	/*
23018	 * If we changed anything in the zone, write changes to journal file
23019	 * and set commit to true so that resume_addnsec3chain() will be
23020	 * called below in order to kick off adding/removing relevant NSEC3
23021	 * records.
23022	 */
23023	if (!ISC_LIST_EMPTY(diff.tuples)) {
23024		CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
23025					zone->updatemethod));
23026		result = dns_update_signatures(&log, zone, db, oldver, newver,
23027					       &diff,
23028					       zone->sigvalidityinterval);
23029		if (result != ISC_R_NOTFOUND) {
23030			CHECK(result);
23031		}
23032		CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
23033		commit = true;
23034
23035		LOCK_ZONE(zone);
23036		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
23037		zone_needdump(zone, 30);
23038		UNLOCK_ZONE(zone);
23039	}
23040
23041failure:
23042	if (dns_rdataset_isassociated(&prdataset)) {
23043		dns_rdataset_disassociate(&prdataset);
23044	}
23045	if (dns_rdataset_isassociated(&nrdataset)) {
23046		dns_rdataset_disassociate(&nrdataset);
23047	}
23048	if (node != NULL) {
23049		dns_db_detachnode(db, &node);
23050	}
23051	if (oldver != NULL) {
23052		dns_db_closeversion(db, &oldver, false);
23053	}
23054	if (newver != NULL) {
23055		dns_db_closeversion(db, &newver, commit);
23056	}
23057	if (db != NULL) {
23058		dns_db_detach(&db);
23059	}
23060	if (commit) {
23061		LOCK_ZONE(zone);
23062		resume_addnsec3chain(zone);
23063		UNLOCK_ZONE(zone);
23064	}
23065	dns_diff_clear(&diff);
23066	isc_event_free(&event);
23067
23068	INSIST(oldver == NULL);
23069	INSIST(newver == NULL);
23070}
23071
23072/*
23073 * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
23074 *
23075 * If 'salt' is NULL, a match is found if the salt has the requested length,
23076 * otherwise the NSEC3 salt must match the requested salt value too.
23077 *
23078 * Returns  ISC_R_SUCCESS, if a match is found, or an error if no match is
23079 * found, or if the db lookup failed.
23080 */
23081isc_result_t
23082dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup,
23083			    dns_rdata_nsec3param_t *param,
23084			    unsigned char saltbuf[255], bool resalt) {
23085	isc_result_t result = ISC_R_UNEXPECTED;
23086	dns_dbnode_t *node = NULL;
23087	dns_db_t *db = NULL;
23088	dns_dbversion_t *version = NULL;
23089	dns_rdataset_t rdataset;
23090	dns_rdata_nsec3param_t nsec3param;
23091	dns_rdata_t rdata = DNS_RDATA_INIT;
23092
23093	REQUIRE(DNS_ZONE_VALID(zone));
23094
23095	dns_rdataset_init(&rdataset);
23096
23097	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23098	if (zone->db != NULL) {
23099		dns_db_attach(zone->db, &db);
23100	}
23101	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23102	if (db == NULL) {
23103		result = ISC_R_FAILURE;
23104		goto setparam;
23105	}
23106
23107	result = dns_db_findnode(db, &zone->origin, false, &node);
23108	if (result != ISC_R_SUCCESS) {
23109		dns_zone_log(zone, ISC_LOG_ERROR,
23110			     "dns__zone_lookup_nsec3param:"
23111			     "dns_db_findnode -> %s",
23112			     isc_result_totext(result));
23113		result = ISC_R_FAILURE;
23114		goto setparam;
23115	}
23116	dns_db_currentversion(db, &version);
23117
23118	result = dns_db_findrdataset(db, node, version,
23119				     dns_rdatatype_nsec3param,
23120				     dns_rdatatype_none, 0, &rdataset, NULL);
23121	if (result != ISC_R_SUCCESS) {
23122		INSIST(!dns_rdataset_isassociated(&rdataset));
23123		if (result != ISC_R_NOTFOUND) {
23124			dns_zone_log(zone, ISC_LOG_ERROR,
23125				     "dns__zone_lookup_nsec3param:"
23126				     "dns_db_findrdataset -> %s",
23127				     isc_result_totext(result));
23128		}
23129		goto setparam;
23130	}
23131
23132	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
23133	     result = dns_rdataset_next(&rdataset))
23134	{
23135		dns_rdataset_current(&rdataset, &rdata);
23136		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
23137		INSIST(result == ISC_R_SUCCESS);
23138		dns_rdata_reset(&rdata);
23139
23140		/* Check parameters. */
23141		if (nsec3param.hash != lookup->hash) {
23142			continue;
23143		}
23144		if (nsec3param.iterations != lookup->iterations) {
23145			continue;
23146		}
23147		if (nsec3param.salt_length != lookup->salt_length) {
23148			continue;
23149		}
23150		if (lookup->salt != NULL) {
23151			if (memcmp(nsec3param.salt, lookup->salt,
23152				   lookup->salt_length) != 0)
23153			{
23154				continue;
23155			}
23156		}
23157		/* Found a match. */
23158		result = ISC_R_SUCCESS;
23159		param->hash = nsec3param.hash;
23160		param->flags = nsec3param.flags;
23161		param->iterations = nsec3param.iterations;
23162		param->salt_length = nsec3param.salt_length;
23163		param->salt = nsec3param.salt;
23164		break;
23165	}
23166
23167	if (result == ISC_R_NOMORE) {
23168		result = ISC_R_NOTFOUND;
23169	}
23170
23171setparam:
23172	if (result != ISC_R_SUCCESS) {
23173		/* Found no match. */
23174		param->hash = lookup->hash;
23175		param->flags = lookup->flags;
23176		param->iterations = lookup->iterations;
23177		param->salt_length = lookup->salt_length;
23178		param->salt = lookup->salt;
23179	}
23180
23181	if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
23182		goto failure;
23183	}
23184
23185	if (param->salt_length == 0) {
23186		DE_CONST("-", param->salt);
23187	} else if (resalt || param->salt == NULL) {
23188		unsigned char *newsalt;
23189		unsigned char salttext[255 * 2 + 1];
23190		do {
23191			/* Generate a new salt. */
23192			result = dns_nsec3_generate_salt(saltbuf,
23193							 param->salt_length);
23194			if (result != ISC_R_SUCCESS) {
23195				break;
23196			}
23197			newsalt = saltbuf;
23198			salt2text(newsalt, param->salt_length, salttext,
23199				  sizeof(salttext));
23200			dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s",
23201				   salttext);
23202			/* Check for salt conflict. */
23203			if (param->salt != NULL &&
23204			    memcmp(newsalt, param->salt, param->salt_length) ==
23205				    0)
23206			{
23207				result = ISC_R_SUCCESS;
23208			} else {
23209				param->salt = newsalt;
23210				result = DNS_R_NSEC3RESALT;
23211			}
23212		} while (result == ISC_R_SUCCESS);
23213
23214		INSIST(result != ISC_R_SUCCESS);
23215	}
23216
23217failure:
23218	if (dns_rdataset_isassociated(&rdataset)) {
23219		dns_rdataset_disassociate(&rdataset);
23220	}
23221	if (node != NULL) {
23222		dns_db_detachnode(db, &node);
23223	}
23224	if (version != NULL) {
23225		dns_db_closeversion(db, &version, false);
23226	}
23227	if (db != NULL) {
23228		dns_db_detach(&db);
23229	}
23230
23231	return (result);
23232}
23233
23234/*
23235 * Called when an "rndc signing -nsec3param ..." command is received, or the
23236 * 'dnssec-policy' has changed.
23237 *
23238 * Allocate and prepare an nsec3param_t structure which holds information about
23239 * the NSEC3 changes requested for the zone:
23240 *
23241 *   - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
23242 *     field of the structure to true and the "replace" field to the value
23243 *     of the "replace" argument, leaving other fields initialized to zeros, to
23244 *     signal that the zone should be signed using NSEC instead of NSEC3,
23245 *
23246 *   - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
23247 *     the zone apex, convert it to a private-type record and store the latter
23248 *     in the "data" field of the nsec3param_t structure.
23249 *
23250 * Once the nsec3param_t structure is prepared, post an event to the zone's
23251 * task which will cause setnsec3param() to be called with the prepared
23252 * structure passed as an argument.
23253 */
23254isc_result_t
23255dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
23256		       uint16_t iter, uint8_t saltlen, unsigned char *salt,
23257		       bool replace, bool resalt) {
23258	isc_result_t result = ISC_R_SUCCESS;
23259	dns_rdata_nsec3param_t param, lookup;
23260	dns_rdata_t nrdata = DNS_RDATA_INIT;
23261	dns_rdata_t prdata = DNS_RDATA_INIT;
23262	unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
23263	unsigned char saltbuf[255];
23264	struct np3event *npe;
23265	nsec3param_t *np;
23266	dns_zone_t *dummy = NULL;
23267	isc_buffer_t b;
23268	isc_event_t *e = NULL;
23269	bool do_lookup = false;
23270
23271	REQUIRE(DNS_ZONE_VALID(zone));
23272
23273	LOCK_ZONE(zone);
23274
23275	/*
23276	 * First check if the requested NSEC3 parameters are already set,
23277	 * if so, no need to set again.
23278	 */
23279	if (hash != 0) {
23280		lookup.hash = hash;
23281		lookup.flags = flags;
23282		lookup.iterations = iter;
23283		lookup.salt_length = saltlen;
23284		lookup.salt = salt;
23285		param.salt = NULL;
23286		result = dns__zone_lookup_nsec3param(zone, &lookup, &param,
23287						     saltbuf, resalt);
23288		if (result == ISC_R_SUCCESS) {
23289			UNLOCK_ZONE(zone);
23290			return (ISC_R_SUCCESS);
23291		}
23292		/*
23293		 * Schedule lookup if lookup above failed (may happen if zone
23294		 * db is NULL for example).
23295		 */
23296		do_lookup = (param.salt == NULL) ? true : false;
23297	}
23298
23299	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
23300			       setnsec3param, zone, sizeof(struct np3event));
23301
23302	npe = (struct np3event *)e;
23303	np = &npe->params;
23304	np->replace = replace;
23305	np->resalt = resalt;
23306	np->lookup = do_lookup;
23307	if (hash == 0) {
23308		np->length = 0;
23309		np->nsec = true;
23310		dnssec_log(zone, ISC_LOG_DEBUG(3), "setnsec3param:nsec");
23311	} else {
23312		param.common.rdclass = zone->rdclass;
23313		param.common.rdtype = dns_rdatatype_nsec3param;
23314		ISC_LINK_INIT(&param.common, link);
23315		param.mctx = NULL;
23316		/* nsec3 specific param set in dns__zone_lookup_nsec3param() */
23317		isc_buffer_init(&b, nbuf, sizeof(nbuf));
23318
23319		if (param.salt != NULL) {
23320			CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
23321						   dns_rdatatype_nsec3param,
23322						   &param, &b));
23323			dns_nsec3param_toprivate(&nrdata, &prdata,
23324						 zone->privatetype, np->data,
23325						 sizeof(np->data));
23326			np->length = prdata.length;
23327		}
23328
23329		np->rdata = param;
23330		np->nsec = false;
23331
23332		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
23333			unsigned char salttext[255 * 2 + 1];
23334			if (param.salt != NULL) {
23335				salt2text(param.salt, param.salt_length,
23336					  salttext, sizeof(salttext));
23337			}
23338			dnssec_log(zone, ISC_LOG_DEBUG(3),
23339				   "setnsec3param:nsec3 %u %u %u %u:%s",
23340				   param.hash, param.flags, param.iterations,
23341				   param.salt_length,
23342				   param.salt == NULL ? "unknown"
23343						      : (char *)salttext);
23344		}
23345	}
23346
23347	/*
23348	 * setnsec3param() will silently return early if the zone does not yet
23349	 * have a database.  Prevent that by queueing the event up if zone->db
23350	 * is NULL.  All events queued here are subsequently processed by
23351	 * receive_secure_db() if it ever gets called or simply freed by
23352	 * zone_free() otherwise.
23353	 */
23354
23355	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23356	if (zone->db != NULL) {
23357		zone_iattach(zone, &dummy);
23358		isc_task_send(zone->task, &e);
23359	} else {
23360		ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
23361		e = NULL;
23362	}
23363	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23364
23365	result = ISC_R_SUCCESS;
23366
23367failure:
23368	if (e != NULL) {
23369		isc_event_free(&e);
23370	}
23371	UNLOCK_ZONE(zone);
23372	return (result);
23373}
23374
23375isc_result_t
23376dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
23377	REQUIRE(DNS_ZONE_VALID(zone));
23378	REQUIRE(loadtime != NULL);
23379
23380	LOCK_ZONE(zone);
23381	*loadtime = zone->loadtime;
23382	UNLOCK_ZONE(zone);
23383	return (ISC_R_SUCCESS);
23384}
23385
23386isc_result_t
23387dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
23388	REQUIRE(DNS_ZONE_VALID(zone));
23389	REQUIRE(expiretime != NULL);
23390
23391	LOCK_ZONE(zone);
23392	*expiretime = zone->expiretime;
23393	UNLOCK_ZONE(zone);
23394	return (ISC_R_SUCCESS);
23395}
23396
23397isc_result_t
23398dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
23399	REQUIRE(DNS_ZONE_VALID(zone));
23400	REQUIRE(refreshtime != NULL);
23401
23402	LOCK_ZONE(zone);
23403	*refreshtime = zone->refreshtime;
23404	UNLOCK_ZONE(zone);
23405	return (ISC_R_SUCCESS);
23406}
23407
23408isc_result_t
23409dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
23410	REQUIRE(DNS_ZONE_VALID(zone));
23411	REQUIRE(refreshkeytime != NULL);
23412
23413	LOCK_ZONE(zone);
23414	*refreshkeytime = zone->refreshkeytime;
23415	UNLOCK_ZONE(zone);
23416	return (ISC_R_SUCCESS);
23417}
23418
23419unsigned int
23420dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
23421	dns_include_t *include;
23422	char **array = NULL;
23423	unsigned int n = 0;
23424
23425	REQUIRE(DNS_ZONE_VALID(zone));
23426	REQUIRE(includesp != NULL && *includesp == NULL);
23427
23428	LOCK_ZONE(zone);
23429	if (zone->nincludes == 0) {
23430		goto done;
23431	}
23432
23433	array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
23434	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
23435	     include = ISC_LIST_NEXT(include, link))
23436	{
23437		INSIST(n < zone->nincludes);
23438		array[n++] = isc_mem_strdup(zone->mctx, include->name);
23439	}
23440	INSIST(n == zone->nincludes);
23441	*includesp = array;
23442
23443done:
23444	UNLOCK_ZONE(zone);
23445	return (n);
23446}
23447
23448void
23449dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
23450	REQUIRE(DNS_ZONE_VALID(zone));
23451
23452	zone->statlevel = level;
23453}
23454
23455dns_zonestat_level_t
23456dns_zone_getstatlevel(dns_zone_t *zone) {
23457	REQUIRE(DNS_ZONE_VALID(zone));
23458
23459	return (zone->statlevel);
23460}
23461
23462static void
23463setserial(isc_task_t *task, isc_event_t *event) {
23464	uint32_t oldserial, desired;
23465	const char *me = "setserial";
23466	bool commit = false;
23467	isc_result_t result;
23468	dns_dbversion_t *oldver = NULL, *newver = NULL;
23469	dns_zone_t *zone;
23470	dns_db_t *db = NULL;
23471	dns_diff_t diff;
23472	struct ssevent *sse = (struct ssevent *)event;
23473	dns_update_log_t log = { update_log_cb, NULL };
23474	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
23475
23476	UNUSED(task);
23477
23478	zone = event->ev_arg;
23479	INSIST(DNS_ZONE_VALID(zone));
23480
23481	ENTER;
23482
23483	if (zone->update_disabled) {
23484		goto disabled;
23485	}
23486
23487	desired = sse->serial;
23488
23489	dns_diff_init(zone->mctx, &diff);
23490
23491	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23492	if (zone->db != NULL) {
23493		dns_db_attach(zone->db, &db);
23494	}
23495	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23496	if (db == NULL) {
23497		goto failure;
23498	}
23499
23500	dns_db_currentversion(db, &oldver);
23501	result = dns_db_newversion(db, &newver);
23502	if (result != ISC_R_SUCCESS) {
23503		dns_zone_log(zone, ISC_LOG_ERROR,
23504			     "setserial:dns_db_newversion -> %s",
23505			     isc_result_totext(result));
23506		goto failure;
23507	}
23508
23509	CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL,
23510				    &oldtuple));
23511	CHECK(dns_difftuple_copy(oldtuple, &newtuple));
23512	newtuple->op = DNS_DIFFOP_ADD;
23513
23514	oldserial = dns_soa_getserial(&oldtuple->rdata);
23515	if (desired == 0U) {
23516		desired = 1;
23517	}
23518	if (!isc_serial_gt(desired, oldserial)) {
23519		if (desired != oldserial) {
23520			dns_zone_log(zone, ISC_LOG_INFO,
23521				     "setserial: desired serial (%u) "
23522				     "out of range (%u-%u)",
23523				     desired, oldserial + 1,
23524				     (oldserial + 0x7fffffff));
23525		}
23526		goto failure;
23527	}
23528
23529	dns_soa_setserial(desired, &newtuple->rdata);
23530	CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
23531	CHECK(do_one_tuple(&newtuple, db, newver, &diff));
23532	result = dns_update_signatures(&log, zone, db, oldver, newver, &diff,
23533				       zone->sigvalidityinterval);
23534	if (result != ISC_R_NOTFOUND) {
23535		CHECK(result);
23536	}
23537
23538	/* Write changes to journal file. */
23539	CHECK(zone_journal(zone, &diff, NULL, "setserial"));
23540	commit = true;
23541
23542	LOCK_ZONE(zone);
23543	zone_needdump(zone, 30);
23544	UNLOCK_ZONE(zone);
23545
23546failure:
23547	if (oldtuple != NULL) {
23548		dns_difftuple_free(&oldtuple);
23549	}
23550	if (newtuple != NULL) {
23551		dns_difftuple_free(&newtuple);
23552	}
23553	if (oldver != NULL) {
23554		dns_db_closeversion(db, &oldver, false);
23555	}
23556	if (newver != NULL) {
23557		dns_db_closeversion(db, &newver, commit);
23558	}
23559	if (db != NULL) {
23560		dns_db_detach(&db);
23561	}
23562	dns_diff_clear(&diff);
23563
23564disabled:
23565	isc_event_free(&event);
23566	dns_zone_idetach(&zone);
23567
23568	INSIST(oldver == NULL);
23569	INSIST(newver == NULL);
23570}
23571
23572isc_result_t
23573dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
23574	isc_result_t result = ISC_R_SUCCESS;
23575	dns_zone_t *dummy = NULL;
23576	isc_event_t *e = NULL;
23577	struct ssevent *sse;
23578
23579	REQUIRE(DNS_ZONE_VALID(zone));
23580
23581	LOCK_ZONE(zone);
23582
23583	if (!inline_secure(zone)) {
23584		if (!dns_zone_isdynamic(zone, true)) {
23585			result = DNS_R_NOTDYNAMIC;
23586			goto failure;
23587		}
23588	}
23589
23590	if (zone->update_disabled) {
23591		result = DNS_R_FROZEN;
23592		goto failure;
23593	}
23594
23595	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL, setserial,
23596			       zone, sizeof(struct ssevent));
23597
23598	sse = (struct ssevent *)e;
23599	sse->serial = serial;
23600
23601	zone_iattach(zone, &dummy);
23602	isc_task_send(zone->task, &e);
23603
23604failure:
23605	if (e != NULL) {
23606		isc_event_free(&e);
23607	}
23608	UNLOCK_ZONE(zone);
23609	return (result);
23610}
23611
23612isc_stats_t *
23613dns_zone_getgluecachestats(dns_zone_t *zone) {
23614	REQUIRE(DNS_ZONE_VALID(zone));
23615
23616	return (zone->gluecachestats);
23617}
23618
23619bool
23620dns_zone_isloaded(dns_zone_t *zone) {
23621	REQUIRE(DNS_ZONE_VALID(zone));
23622
23623	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
23624}
23625
23626isc_result_t
23627dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
23628	dns_dbversion_t *version = NULL;
23629	dns_keytable_t *secroots = NULL;
23630	isc_result_t result;
23631	dns_name_t *origin;
23632
23633	const char me[] = "dns_zone_verifydb";
23634
23635	REQUIRE(DNS_ZONE_VALID(zone));
23636	REQUIRE(db != NULL);
23637
23638	ENTER;
23639
23640	if (dns_zone_gettype(zone) != dns_zone_mirror) {
23641		return (ISC_R_SUCCESS);
23642	}
23643
23644	if (ver == NULL) {
23645		dns_db_currentversion(db, &version);
23646	} else {
23647		version = ver;
23648	}
23649
23650	if (zone->view != NULL) {
23651		result = dns_view_getsecroots(zone->view, &secroots);
23652		if (result != ISC_R_SUCCESS) {
23653			goto done;
23654		}
23655	}
23656
23657	origin = dns_db_origin(db);
23658	result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
23659				       zone->mctx, true, false, dnssec_report);
23660
23661done:
23662	if (secroots != NULL) {
23663		dns_keytable_detach(&secroots);
23664	}
23665
23666	if (ver == NULL) {
23667		dns_db_closeversion(db, &version, false);
23668	}
23669
23670	if (result != ISC_R_SUCCESS) {
23671		dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
23672			   isc_result_totext(result));
23673		result = DNS_R_VERIFYFAILURE;
23674	}
23675
23676	return (result);
23677}
23678
23679static dns_ttl_t
23680zone_nsecttl(dns_zone_t *zone) {
23681	REQUIRE(DNS_ZONE_VALID(zone));
23682
23683	return (ISC_MIN(zone->minimum, zone->soattl));
23684}
23685
23686void
23687dns_zonemgr_set_tlsctx_cache(dns_zonemgr_t *zmgr,
23688			     isc_tlsctx_cache_t *tlsctx_cache) {
23689	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
23690	REQUIRE(tlsctx_cache != NULL);
23691
23692	RWLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_write);
23693
23694	if (zmgr->tlsctx_cache != NULL) {
23695		isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
23696	}
23697
23698	isc_tlsctx_cache_attach(tlsctx_cache, &zmgr->tlsctx_cache);
23699
23700	RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_write);
23701}
23702
23703static void
23704zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache) {
23705	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
23706	REQUIRE(ptlsctx_cache != NULL && *ptlsctx_cache == NULL);
23707
23708	RWLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
23709
23710	INSIST(zmgr->tlsctx_cache != NULL);
23711	isc_tlsctx_cache_attach(zmgr->tlsctx_cache, ptlsctx_cache);
23712
23713	RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
23714}
23715