1 /*
2  * Copyright (C) 2004-2016  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /*! \file */
19 
20 #include <config.h>
21 #include <errno.h>
22 
23 #include <isc/file.h>
24 #include <isc/hex.h>
25 #include <isc/mutex.h>
26 #include <isc/pool.h>
27 #include <isc/print.h>
28 #include <isc/random.h>
29 #include <isc/ratelimiter.h>
30 #include <isc/refcount.h>
31 #include <isc/rwlock.h>
32 #include <isc/serial.h>
33 #include <isc/stats.h>
34 #include <isc/stdtime.h>
35 #include <isc/strerror.h>
36 #include <isc/string.h>
37 #include <isc/taskpool.h>
38 #include <isc/thread.h>
39 #include <isc/timer.h>
40 #include <isc/util.h>
41 
42 #include <dns/acache.h>
43 #include <dns/acl.h>
44 #include <dns/adb.h>
45 #include <dns/callbacks.h>
46 #include <dns/db.h>
47 #include <dns/dbiterator.h>
48 #include <dns/dnssec.h>
49 #include <dns/ds.h>
50 #include <dns/events.h>
51 #include <dns/journal.h>
52 #include <dns/keydata.h>
53 #include <dns/keytable.h>
54 #include <dns/keyvalues.h>
55 #include <dns/log.h>
56 #include <dns/master.h>
57 #include <dns/masterdump.h>
58 #include <dns/message.h>
59 #include <dns/name.h>
60 #include <dns/nsec.h>
61 #include <dns/nsec3.h>
62 #include <dns/peer.h>
63 #include <dns/private.h>
64 #include <dns/rbt.h>
65 #include <dns/rcode.h>
66 #include <dns/rdata.h>
67 #include <dns/rdataclass.h>
68 #include <dns/rdatalist.h>
69 #include <dns/rdataset.h>
70 #include <dns/rdatasetiter.h>
71 #include <dns/rdatastruct.h>
72 #include <dns/rdatatype.h>
73 #include <dns/request.h>
74 #include <dns/resolver.h>
75 #include <dns/result.h>
76 #include <dns/rriterator.h>
77 #include <dns/soa.h>
78 #include <dns/ssu.h>
79 #include <dns/stats.h>
80 #include <dns/time.h>
81 #include <dns/tsig.h>
82 #include <dns/update.h>
83 #include <dns/xfrin.h>
84 #include <dns/zone.h>
85 #include <dns/zt.h>
86 
87 #include <dst/dst.h>
88 
89 #define ZONE_MAGIC			ISC_MAGIC('Z', 'O', 'N', 'E')
90 #define DNS_ZONE_VALID(zone)		ISC_MAGIC_VALID(zone, ZONE_MAGIC)
91 
92 #define NOTIFY_MAGIC			ISC_MAGIC('N', 't', 'f', 'y')
93 #define DNS_NOTIFY_VALID(notify)	ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
94 
95 #define STUB_MAGIC			ISC_MAGIC('S', 't', 'u', 'b')
96 #define DNS_STUB_VALID(stub)		ISC_MAGIC_VALID(stub, STUB_MAGIC)
97 
98 #define ZONEMGR_MAGIC			ISC_MAGIC('Z', 'm', 'g', 'r')
99 #define DNS_ZONEMGR_VALID(stub)		ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
100 
101 #define LOAD_MAGIC			ISC_MAGIC('L', 'o', 'a', 'd')
102 #define DNS_LOAD_VALID(load)		ISC_MAGIC_VALID(load, LOAD_MAGIC)
103 
104 #define FORWARD_MAGIC			ISC_MAGIC('F', 'o', 'r', 'w')
105 #define DNS_FORWARD_VALID(load)		ISC_MAGIC_VALID(load, FORWARD_MAGIC)
106 
107 #define IO_MAGIC			ISC_MAGIC('Z', 'm', 'I', 'O')
108 #define DNS_IO_VALID(load)		ISC_MAGIC_VALID(load, IO_MAGIC)
109 
110 /*%
111  * Ensure 'a' is at least 'min' but not more than 'max'.
112  */
113 #define RANGE(a, min, max) \
114 		(((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
115 
116 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
117 
118 /*%
119  * Key flags
120  */
121 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
122 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
123 #define ALG(x) dst_key_alg(x)
124 
125 /*
126  * Default values.
127  */
128 #define DNS_DEFAULT_IDLEIN 3600		/*%< 1 hour */
129 #define DNS_DEFAULT_IDLEOUT 3600	/*%< 1 hour */
130 #define MAX_XFER_TIME (2*3600)		/*%< Documented default is 2 hours */
131 #define RESIGN_DELAY 3600		/*%< 1 hour */
132 
133 #ifndef DNS_MAX_EXPIRE
134 #define DNS_MAX_EXPIRE	14515200	/*%< 24 weeks */
135 #endif
136 
137 #ifndef DNS_DUMP_DELAY
138 #define DNS_DUMP_DELAY 900		/*%< 15 minutes */
139 #endif
140 
141 typedef struct dns_notify dns_notify_t;
142 typedef struct dns_stub dns_stub_t;
143 typedef struct dns_load dns_load_t;
144 typedef struct dns_forward dns_forward_t;
145 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
146 typedef struct dns_io dns_io_t;
147 typedef ISC_LIST(dns_io_t) dns_iolist_t;
148 typedef struct dns_signing dns_signing_t;
149 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
150 typedef struct dns_nsec3chain dns_nsec3chain_t;
151 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
152 typedef struct dns_keyfetch dns_keyfetch_t;
153 typedef struct dns_asyncload dns_asyncload_t;
154 
155 #define DNS_ZONE_CHECKLOCK
156 #ifdef DNS_ZONE_CHECKLOCK
157 #define LOCK_ZONE(z) \
158 	 do { LOCK(&(z)->lock); \
159 	      INSIST((z)->locked == ISC_FALSE); \
160 	     (z)->locked = ISC_TRUE; \
161 		} while (0)
162 #define UNLOCK_ZONE(z) \
163 	do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
164 #define LOCKED_ZONE(z) ((z)->locked)
165 #define TRYLOCK_ZONE(result, z) \
166 	do { \
167 	      result = isc_mutex_trylock(&(z)->lock); \
168 	      if (result == ISC_R_SUCCESS) {  \
169 		     INSIST((z)->locked == ISC_FALSE); \
170 		     (z)->locked = ISC_TRUE; \
171 	      } \
172 	} while (0)
173 #else
174 #define LOCK_ZONE(z) LOCK(&(z)->lock)
175 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
176 #define LOCKED_ZONE(z) ISC_TRUE
177 #define TRYLOCK_ZONE(result, z) \
178 	do { result = isc_mutex_trylock(&(z)->lock); } while (0)
179 #endif
180 
181 #ifdef ISC_RWLOCK_USEATOMIC
182 #define ZONEDB_INITLOCK(l)	isc_rwlock_init((l), 0, 0)
183 #define ZONEDB_DESTROYLOCK(l)	isc_rwlock_destroy(l)
184 #define ZONEDB_LOCK(l, t)	RWLOCK((l), (t))
185 #define ZONEDB_UNLOCK(l, t)	RWUNLOCK((l), (t))
186 #else
187 #define ZONEDB_INITLOCK(l)	isc_mutex_init(l)
188 #define ZONEDB_DESTROYLOCK(l)	DESTROYLOCK(l)
189 #define ZONEDB_LOCK(l, t)	LOCK(l)
190 #define ZONEDB_UNLOCK(l, t)	UNLOCK(l)
191 #endif
192 
193 struct dns_zone {
194 	/* Unlocked */
195 	unsigned int		magic;
196 	isc_mutex_t		lock;
197 #ifdef DNS_ZONE_CHECKLOCK
198 	isc_boolean_t		locked;
199 #endif
200 	isc_mem_t		*mctx;
201 	isc_refcount_t		erefs;
202 
203 #ifdef ISC_RWLOCK_USEATOMIC
204 	isc_rwlock_t		dblock;
205 #else
206 	isc_mutex_t		dblock;
207 #endif
208 	dns_db_t		*db;		/* Locked by dblock */
209 
210 	/* Locked */
211 	dns_zonemgr_t		*zmgr;
212 	ISC_LINK(dns_zone_t)	link;		/* Used by zmgr. */
213 	isc_timer_t		*timer;
214 	unsigned int		irefs;
215 	dns_name_t		origin;
216 	char			*masterfile;
217 	dns_masterformat_t	masterformat;
218 	char			*journal;
219 	isc_int32_t		journalsize;
220 	dns_rdataclass_t	rdclass;
221 	dns_zonetype_t		type;
222 	unsigned int		flags;
223 	unsigned int		options;
224 	unsigned int		db_argc;
225 	char			**db_argv;
226 	isc_time_t		expiretime;
227 	isc_time_t		refreshtime;
228 	isc_time_t		dumptime;
229 	isc_time_t		loadtime;
230 	isc_time_t		notifytime;
231 	isc_time_t		resigntime;
232 	isc_time_t		keywarntime;
233 	isc_time_t		signingtime;
234 	isc_time_t		nsec3chaintime;
235 	isc_time_t		refreshkeytime;
236 	isc_uint32_t		refreshkeyinterval;
237 	isc_uint32_t		refreshkeycount;
238 	isc_uint32_t		refresh;
239 	isc_uint32_t		retry;
240 	isc_uint32_t		expire;
241 	isc_uint32_t		minimum;
242 	isc_stdtime_t		key_expiry;
243 	isc_stdtime_t		log_key_expired_timer;
244 	char			*keydirectory;
245 
246 	isc_uint32_t		maxrefresh;
247 	isc_uint32_t		minrefresh;
248 	isc_uint32_t		maxretry;
249 	isc_uint32_t		minretry;
250 
251 	isc_sockaddr_t		*masters;
252 	dns_name_t		**masterkeynames;
253 	isc_boolean_t		*mastersok;
254 	unsigned int		masterscnt;
255 	unsigned int		curmaster;
256 	isc_sockaddr_t		masteraddr;
257 	dns_notifytype_t	notifytype;
258 	isc_sockaddr_t		*notify;
259 	dns_name_t		**notifykeynames;
260 	unsigned int		notifycnt;
261 	isc_sockaddr_t		notifyfrom;
262 	isc_task_t		*task;
263 	isc_task_t		*loadtask;
264 	isc_sockaddr_t		notifysrc4;
265 	isc_sockaddr_t		notifysrc6;
266 	isc_sockaddr_t		xfrsource4;
267 	isc_sockaddr_t		xfrsource6;
268 	isc_sockaddr_t		altxfrsource4;
269 	isc_sockaddr_t		altxfrsource6;
270 	isc_sockaddr_t		sourceaddr;
271 	dns_xfrin_ctx_t		*xfr;		/* task locked */
272 	dns_tsigkey_t		*tsigkey;	/* key used for xfr */
273 	/* Access Control Lists */
274 	dns_acl_t		*update_acl;
275 	dns_acl_t		*forward_acl;
276 	dns_acl_t		*notify_acl;
277 	dns_acl_t		*query_acl;
278 	dns_acl_t		*queryon_acl;
279 	dns_acl_t		*xfr_acl;
280 	isc_boolean_t		update_disabled;
281 	isc_boolean_t		zero_no_soa_ttl;
282 	dns_severity_t		check_names;
283 	ISC_LIST(dns_notify_t)	notifies;
284 	dns_request_t		*request;
285 	dns_loadctx_t		*lctx;
286 	dns_io_t		*readio;
287 	dns_dumpctx_t		*dctx;
288 	dns_io_t		*writeio;
289 	isc_uint32_t		maxxfrin;
290 	isc_uint32_t		maxxfrout;
291 	isc_uint32_t		idlein;
292 	isc_uint32_t		idleout;
293 	isc_event_t		ctlevent;
294 	dns_ssutable_t		*ssutable;
295 	isc_uint32_t		sigvalidityinterval;
296 	isc_uint32_t		sigresigninginterval;
297 	dns_view_t		*view;
298 	dns_acache_t		*acache;
299 	dns_checkmxfunc_t	checkmx;
300 	dns_checksrvfunc_t	checksrv;
301 	dns_checknsfunc_t	checkns;
302 	/*%
303 	 * Zones in certain states such as "waiting for zone transfer"
304 	 * or "zone transfer in progress" are kept on per-state linked lists
305 	 * in the zone manager using the 'statelink' field.  The 'statelist'
306 	 * field points at the list the zone is currently on.  It the zone
307 	 * is not on any such list, statelist is NULL.
308 	 */
309 	ISC_LINK(dns_zone_t)	statelink;
310 	dns_zonelist_t		*statelist;
311 	/*%
312 	 * Statistics counters about zone management.
313 	 */
314 	isc_stats_t		*stats;
315 	/*%
316 	 * Optional per-zone statistics counters.  Counted outside of this
317 	 * module.
318 	 */
319 	dns_zonestat_level_t	statlevel;
320 	isc_boolean_t		requeststats_on;
321 	isc_stats_t		*requeststats;
322 	dns_stats_t		*rcvquerystats;
323 	isc_uint32_t		notifydelay;
324 	dns_isselffunc_t	isself;
325 	void			*isselfarg;
326 
327 	char *			strnamerd;
328 	char *			strname;
329 	char *			strrdclass;
330 	char *			strviewname;
331 
332 	/*%
333 	 * Serial number for deferred journal compaction.
334 	 */
335 	isc_uint32_t		compact_serial;
336 	/*%
337 	 * Keys that are signing the zone for the first time.
338 	 */
339 	dns_signinglist_t	signing;
340 	dns_nsec3chainlist_t	nsec3chain;
341 	/*%
342 	 * Signing / re-signing quantum stopping parameters.
343 	 */
344 	isc_uint32_t		signatures;
345 	isc_uint32_t		nodes;
346 	dns_rdatatype_t		privatetype;
347 
348 	/*%
349 	 * Autosigning/key-maintenance options
350 	 */
351 	isc_uint32_t		keyopts;
352 
353 	/*%
354 	 * True if added by "rndc addzone"
355 	 */
356 	isc_boolean_t           added;
357 
358 	/*%
359 	 * whether this is a response policy zone
360 	 */
361 	isc_boolean_t           is_rpz;
362 
363 	/*%
364 	 * Serial number update method.
365 	 */
366 	dns_updatemethod_t	updatemethod;
367 
368 	/*%
369 	 * whether ixfr is requested
370 	 */
371 	isc_boolean_t		requestixfr;
372 
373 	/*%
374 	 * Outstanding forwarded UPDATE requests.
375 	 */
376 	dns_forwardlist_t	forwards;
377 
378 	dns_zone_t		*raw;
379 	dns_zone_t		*secure;
380 
381 	isc_boolean_t		sourceserialset;
382 	isc_uint32_t		sourceserial;
383 
384 	/*%
385 	 * maximum zone ttl
386 	 */
387 	dns_ttl_t		maxttl;
388 
389 	/*
390 	 * Inline zone signing state.
391 	 */
392 	dns_diff_t		rss_diff;
393 	isc_eventlist_t		rss_events;
394 	dns_dbversion_t		*rss_newver;
395 	dns_dbversion_t		*rss_oldver;
396 	dns_db_t		*rss_db;
397 	dns_zone_t		*rss_raw;
398 	isc_event_t		*rss_event;
399 	dns_update_state_t      *rss_state;
400 };
401 
402 typedef struct {
403 	dns_diff_t	*diff;
404 	isc_boolean_t	offline;
405 } zonediff_t;
406 
407 #define zonediff_init(z, d) \
408 	do { \
409 		zonediff_t *_z = (z); \
410 		(_z)->diff = (d); \
411 		(_z)->offline = ISC_FALSE; \
412 	} while (0)
413 
414 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
415 #define DNS_ZONE_SETFLAG(z,f) do { \
416 		INSIST(LOCKED_ZONE(z)); \
417 		(z)->flags |= (f); \
418 		} while (0)
419 #define DNS_ZONE_CLRFLAG(z,f) do { \
420 		INSIST(LOCKED_ZONE(z)); \
421 		(z)->flags &= ~(f); \
422 		} while (0)
423 	/* XXX MPA these may need to go back into zone.h */
424 #define DNS_ZONEFLG_REFRESH	0x00000001U	/*%< refresh check in progress */
425 #define DNS_ZONEFLG_NEEDDUMP	0x00000002U	/*%< zone need consolidation */
426 #define DNS_ZONEFLG_USEVC	0x00000004U	/*%< use tcp for refresh query */
427 #define DNS_ZONEFLG_DUMPING	0x00000008U	/*%< a dump is in progress */
428 #define DNS_ZONEFLG_HASINCLUDE	0x00000010U	/*%< $INCLUDE in zone file */
429 #define DNS_ZONEFLG_LOADED	0x00000020U	/*%< database has loaded */
430 #define DNS_ZONEFLG_EXITING	0x00000040U	/*%< zone is being destroyed */
431 #define DNS_ZONEFLG_EXPIRED	0x00000080U	/*%< zone has expired */
432 #define DNS_ZONEFLG_NEEDREFRESH	0x00000100U	/*%< refresh check needed */
433 #define DNS_ZONEFLG_UPTODATE	0x00000200U	/*%< zone contents are
434 						 * uptodate */
435 #define DNS_ZONEFLG_NEEDNOTIFY	0x00000400U	/*%< need to send out notify
436 						 * messages */
437 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U	/*%< generate a journal diff on
438 						 * reload */
439 #define DNS_ZONEFLG_NOMASTERS	0x00001000U	/*%< an attempt to refresh a
440 						 * zone with no masters
441 						 * occurred */
442 #define DNS_ZONEFLG_LOADING	0x00002000U	/*%< load from disk in progress*/
443 #define DNS_ZONEFLG_HAVETIMERS	0x00004000U	/*%< timer values have been set
444 						 * from SOA (if not set, we
445 						 * are still using
446 						 * default timer values) */
447 #define DNS_ZONEFLG_FORCEXFER	0x00008000U	/*%< Force a zone xfer */
448 #define DNS_ZONEFLG_NOREFRESH	0x00010000U
449 #define DNS_ZONEFLG_DIALNOTIFY	0x00020000U
450 #define DNS_ZONEFLG_DIALREFRESH	0x00040000U
451 #define DNS_ZONEFLG_SHUTDOWN	0x00080000U
452 #define DNS_ZONEFLAG_NOIXFR	0x00100000U	/*%< IXFR failed, force AXFR */
453 #define DNS_ZONEFLG_FLUSH	0x00200000U
454 #define DNS_ZONEFLG_NOEDNS	0x00400000U
455 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
456 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
457 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
458 #define DNS_ZONEFLG_REFRESHING	0x04000000U	/*%< Refreshing keydata */
459 #define DNS_ZONEFLG_THAW	0x08000000U
460 #define DNS_ZONEFLG_LOADPENDING	0x10000000U	/*%< Loading scheduled */
461 #define DNS_ZONEFLG_NODELAY	0x20000000U
462 #define DNS_ZONEFLG_SENDSECURE  0x40000000U
463 #define DNS_ZONEFLG_NEEDSTARTUPNOTIFY 0x80000000U /*%< need to send out notify
464 						   *   due to the zone just
465 						   *   being loaded for the
466 						   *   first time.  */
467 
468 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
469 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
470 
471 /* Flags for zone_load() */
472 #define DNS_ZONELOADFLAG_NOSTAT	0x00000001U	/* Do not stat() master files */
473 #define DNS_ZONELOADFLAG_THAW	0x00000002U	/* Thaw the zone on successful
474 						   load. */
475 
476 #define UNREACH_CHACHE_SIZE	10U
477 #define UNREACH_HOLD_TIME	600	/* 10 minutes */
478 
479 #define CHECK(op) \
480 	do { result = (op); \
481 		if (result != ISC_R_SUCCESS) goto failure; \
482 	} while (0)
483 
484 struct dns_unreachable {
485 	isc_sockaddr_t	remote;
486 	isc_sockaddr_t	local;
487 	isc_uint32_t	expire;
488 	isc_uint32_t	last;
489 	isc_uint32_t	count;
490 };
491 
492 struct dns_zonemgr {
493 	unsigned int		magic;
494 	isc_mem_t *		mctx;
495 	int			refs;		/* Locked by rwlock */
496 	isc_taskmgr_t *		taskmgr;
497 	isc_timermgr_t *	timermgr;
498 	isc_socketmgr_t *	socketmgr;
499 	isc_taskpool_t *	zonetasks;
500 	isc_taskpool_t *	loadtasks;
501 	isc_task_t *		task;
502 	isc_pool_t *		mctxpool;
503 	isc_ratelimiter_t *	notifyrl;
504 	isc_ratelimiter_t *	refreshrl;
505 	isc_ratelimiter_t *	startupnotifyrl;
506 	isc_ratelimiter_t *	startuprefreshrl;
507 	isc_rwlock_t		rwlock;
508 	isc_mutex_t		iolock;
509 	isc_rwlock_t		urlock;
510 
511 	/* Locked by rwlock. */
512 	dns_zonelist_t		zones;
513 	dns_zonelist_t		waiting_for_xfrin;
514 	dns_zonelist_t		xfrin_in_progress;
515 
516 	/* Configuration data. */
517 	isc_uint32_t		transfersin;
518 	isc_uint32_t		transfersperns;
519 	unsigned int		notifyrate;
520 	unsigned int		startupnotifyrate;
521 	unsigned int		serialqueryrate;
522 	unsigned int		startupserialqueryrate;
523 
524 	/* Locked by iolock */
525 	isc_uint32_t		iolimit;
526 	isc_uint32_t		ioactive;
527 	dns_iolist_t		high;
528 	dns_iolist_t		low;
529 
530 	/* Locked by urlock. */
531 	/* LRU cache */
532 	struct dns_unreachable	unreachable[UNREACH_CHACHE_SIZE];
533 };
534 
535 /*%
536  * Hold notify state.
537  */
538 struct dns_notify {
539 	unsigned int		magic;
540 	unsigned int		flags;
541 	isc_mem_t		*mctx;
542 	dns_zone_t		*zone;
543 	dns_adbfind_t		*find;
544 	dns_request_t		*request;
545 	dns_name_t		ns;
546 	isc_sockaddr_t		dst;
547 	dns_tsigkey_t		*key;
548 	ISC_LINK(dns_notify_t)	link;
549 	isc_event_t		*event;
550 };
551 
552 #define DNS_NOTIFY_NOSOA	0x0001U
553 #define DNS_NOTIFY_STARTUP	0x0002U
554 
555 /*%
556  *	dns_stub holds state while performing a 'stub' transfer.
557  *	'db' is the zone's 'db' or a new one if this is the initial
558  *	transfer.
559  */
560 
561 struct dns_stub {
562 	unsigned int		magic;
563 	isc_mem_t		*mctx;
564 	dns_zone_t		*zone;
565 	dns_db_t		*db;
566 	dns_dbversion_t		*version;
567 };
568 
569 /*%
570  *	Hold load state.
571  */
572 struct dns_load {
573 	unsigned int		magic;
574 	isc_mem_t		*mctx;
575 	dns_zone_t		*zone;
576 	dns_db_t		*db;
577 	isc_time_t		loadtime;
578 	dns_rdatacallbacks_t	callbacks;
579 };
580 
581 /*%
582  *	Hold forward state.
583  */
584 struct dns_forward {
585 	unsigned int		magic;
586 	isc_mem_t		*mctx;
587 	dns_zone_t		*zone;
588 	isc_buffer_t		*msgbuf;
589 	dns_request_t		*request;
590 	isc_uint32_t		which;
591 	isc_sockaddr_t		addr;
592 	dns_updatecallback_t	callback;
593 	void			*callback_arg;
594 	unsigned int		options;
595 	ISC_LINK(dns_forward_t)	link;
596 };
597 
598 /*%
599  *	Hold IO request state.
600  */
601 struct dns_io {
602 	unsigned int	magic;
603 	dns_zonemgr_t	*zmgr;
604 	isc_boolean_t	high;
605 	isc_task_t	*task;
606 	ISC_LINK(dns_io_t) link;
607 	isc_event_t	*event;
608 };
609 
610 /*%
611  *	Hold state for when we are signing a zone with a new
612  *	DNSKEY as result of an update.
613  */
614 struct dns_signing {
615 	unsigned int		magic;
616 	dns_db_t		*db;
617 	dns_dbiterator_t	*dbiterator;
618 	dns_secalg_t		algorithm;
619 	isc_uint16_t		keyid;
620 	isc_boolean_t		delete;
621 	isc_boolean_t		done;
622 	ISC_LINK(dns_signing_t)	link;
623 };
624 
625 struct dns_nsec3chain {
626 	unsigned int			magic;
627 	dns_db_t			*db;
628 	dns_dbiterator_t		*dbiterator;
629 	dns_rdata_nsec3param_t		nsec3param;
630 	unsigned char			salt[255];
631 	isc_boolean_t			done;
632 	isc_boolean_t			seen_nsec;
633 	isc_boolean_t			delete_nsec;
634 	isc_boolean_t			save_delete_nsec;
635 	ISC_LINK(dns_nsec3chain_t)	link;
636 };
637 /*%<
638  * 'dbiterator' contains a iterator for the database.  If we are creating
639  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
640  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
641  * iterated.
642  *
643  * 'nsec3param' contains the parameters of the NSEC3 chain being created
644  * or removed.
645  *
646  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
647  *
648  * 'seen_nsec' will be set to true if, while iterating the zone to create a
649  * NSEC3 chain, a NSEC record is seen.
650  *
651  * 'delete_nsec' will be set to true if, at the completion of the creation
652  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
653  * are in the process of deleting the NSEC chain.
654  *
655  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
656  * so it can be recovered in the event of a error.
657  */
658 
659 struct dns_keyfetch {
660 	dns_fixedname_t name;
661 	dns_rdataset_t keydataset;
662 	dns_rdataset_t dnskeyset;
663 	dns_rdataset_t dnskeysigset;
664 	dns_zone_t *zone;
665 	dns_db_t *db;
666 	dns_fetch_t *fetch;
667 };
668 
669 /*%
670  * Hold state for an asynchronous load
671  */
672 struct dns_asyncload {
673 	dns_zone_t *zone;
674 	dns_zt_zoneloaded_t loaded;
675 	void *loaded_arg;
676 };
677 
678 #define HOUR 3600
679 #define DAY (24*HOUR)
680 #define MONTH (30*DAY)
681 
682 /*
683  * These can be overridden by the -T mkeytimers option on the command
684  * line, so that we can test with shorter periods than specified in
685  * RFC 5011.
686  */
687 unsigned int dns_zone_mkey_hour = HOUR;
688 unsigned int dns_zone_mkey_day = DAY;
689 unsigned int dns_zone_mkey_month = MONTH;
690 
691 #define SEND_BUFFER_SIZE 2048
692 
693 static void zone_settimer(dns_zone_t *, isc_time_t *);
694 static void cancel_refresh(dns_zone_t *);
695 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
696 			  const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
697 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
698      ISC_FORMAT_PRINTF(3, 4);
699 static void queue_xfrin(dns_zone_t *zone);
700 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
701 				  dns_diff_t *diff, dns_diffop_t op,
702 				  dns_name_t *name, dns_ttl_t ttl,
703 				  dns_rdata_t *rdata);
704 static void zone_unload(dns_zone_t *zone);
705 static void zone_expire(dns_zone_t *zone);
706 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
707 static void zone_idetach(dns_zone_t **zonep);
708 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
709 				   isc_boolean_t dump);
710 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
711 static inline void zone_detachdb(dns_zone_t *zone);
712 static isc_result_t default_journal(dns_zone_t *zone);
713 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
714 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
715 				  isc_time_t loadtime, isc_result_t result);
716 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
717 static void zone_shutdown(isc_task_t *, isc_event_t *);
718 static void zone_loaddone(void *arg, isc_result_t result);
719 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
720 				   isc_time_t loadtime);
721 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
722 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
723 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
724 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
725 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
726 					   isc_uint32_t serial);
727 
728 #if 0
729 /* ondestroy example */
730 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
731 #endif
732 
733 static void refresh_callback(isc_task_t *, isc_event_t *);
734 static void stub_callback(isc_task_t *, isc_event_t *);
735 static void queue_soa_query(dns_zone_t *zone);
736 static void soa_query(isc_task_t *, isc_event_t *);
737 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
738 		     dns_stub_t *stub);
739 static int message_count(dns_message_t *msg, dns_section_t section,
740 			 dns_rdatatype_t type);
741 static void notify_cancel(dns_zone_t *zone);
742 static void notify_find_address(dns_notify_t *notify);
743 static void notify_send(dns_notify_t *notify);
744 static isc_result_t notify_createmessage(dns_zone_t *zone,
745 					 unsigned int flags,
746 					 dns_message_t **messagep);
747 static void notify_done(isc_task_t *task, isc_event_t *event);
748 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
749 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
750 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
751 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
752 					     dns_zone_t *zone);
753 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
754 static void zonemgr_free(dns_zonemgr_t *zmgr);
755 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
756 				  isc_task_t *task, isc_taskaction_t action,
757 				  void *arg, dns_io_t **iop);
758 static void zonemgr_putio(dns_io_t **iop);
759 static void zonemgr_cancelio(dns_io_t *io);
760 
761 static isc_result_t
762 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
763 		 unsigned int *soacount, isc_uint32_t *serial,
764 		 isc_uint32_t *refresh, isc_uint32_t *retry,
765 		 isc_uint32_t *expire, isc_uint32_t *minimum,
766 		 unsigned int *errors);
767 
768 static void zone_freedbargs(dns_zone_t *zone);
769 static void forward_callback(isc_task_t *task, isc_event_t *event);
770 static void zone_saveunique(dns_zone_t *zone, const char *path,
771 			    const char *templat);
772 static void zone_maintenance(dns_zone_t *zone);
773 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
774 static void dump_done(void *arg, isc_result_t result);
775 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
776 				     isc_uint16_t keyid, isc_boolean_t delete);
777 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
778 				dns_dbnode_t *node, dns_name_t *name,
779 				dns_diff_t *diff);
780 static void zone_rekey(dns_zone_t *zone);
781 static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
782 static void setrl(isc_ratelimiter_t *rl, unsigned int *rate,
783 		  unsigned int value);
784 
785 #define ENTER zone_debuglog(zone, me, 1, "enter")
786 
787 static const unsigned int dbargc_default = 1;
788 static const char *dbargv_default[] = { "rbt" };
789 
790 #define DNS_ZONE_JITTER_ADD(a, b, c) \
791 	do { \
792 		isc_interval_t _i; \
793 		isc_uint32_t _j; \
794 		_j = isc_random_jitter((b), (b)/4); \
795 		isc_interval_set(&_i, _j, 0); \
796 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
797 			dns_zone_log(zone, ISC_LOG_WARNING, \
798 				     "epoch approaching: upgrade required: " \
799 				     "now + %s failed", #b); \
800 			isc_interval_set(&_i, _j/2, 0); \
801 			(void)isc_time_add((a), &_i, (c)); \
802 		} \
803 	} while (0)
804 
805 #define DNS_ZONE_TIME_ADD(a, b, c) \
806 	do { \
807 		isc_interval_t _i; \
808 		isc_interval_set(&_i, (b), 0); \
809 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
810 			dns_zone_log(zone, ISC_LOG_WARNING, \
811 				     "epoch approaching: upgrade required: " \
812 				     "now + %s failed", #b); \
813 			isc_interval_set(&_i, (b)/2, 0); \
814 			(void)isc_time_add((a), &_i, (c)); \
815 		} \
816 	} while (0)
817 
818 typedef struct nsec3param nsec3param_t;
819 struct nsec3param {
820 	unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
821 	unsigned int length;
822 	isc_boolean_t nsec;
823 	isc_boolean_t replace;
824 	ISC_LINK(nsec3param_t)	link;
825 };
826 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
827 struct np3event {
828 	isc_event_t event;
829 	nsec3param_t params;
830 };
831 
832 /*%
833  * Increment resolver-related statistics counters.  Zone must be locked.
834  */
835 static inline void
inc_stats(dns_zone_t * zone,isc_statscounter_t counter)836 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
837 	if (zone->stats != NULL)
838 		isc_stats_increment(zone->stats, counter);
839 }
840 
841 /***
842  ***	Public functions.
843  ***/
844 
845 isc_result_t
dns_zone_create(dns_zone_t ** zonep,isc_mem_t * mctx)846 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
847 	isc_result_t result;
848 	dns_zone_t *zone;
849 	isc_time_t now;
850 
851 	REQUIRE(zonep != NULL && *zonep == NULL);
852 	REQUIRE(mctx != NULL);
853 
854 	TIME_NOW(&now);
855 	zone = isc_mem_get(mctx, sizeof(*zone));
856 	if (zone == NULL)
857 		return (ISC_R_NOMEMORY);
858 
859 	zone->mctx = NULL;
860 	isc_mem_attach(mctx, &zone->mctx);
861 
862 	result = isc_mutex_init(&zone->lock);
863 	if (result != ISC_R_SUCCESS)
864 		goto free_zone;
865 
866 	result = ZONEDB_INITLOCK(&zone->dblock);
867 	if (result != ISC_R_SUCCESS)
868 		goto free_mutex;
869 
870 	/* XXX MPA check that all elements are initialised */
871 #ifdef DNS_ZONE_CHECKLOCK
872 	zone->locked = ISC_FALSE;
873 #endif
874 	zone->db = NULL;
875 	zone->zmgr = NULL;
876 	ISC_LINK_INIT(zone, link);
877 	result = isc_refcount_init(&zone->erefs, 1);	/* Implicit attach. */
878 	if (result != ISC_R_SUCCESS)
879 		goto free_dblock;
880 	zone->irefs = 0;
881 	dns_name_init(&zone->origin, NULL);
882 	zone->strnamerd = NULL;
883 	zone->strname = NULL;
884 	zone->strrdclass = NULL;
885 	zone->strviewname = NULL;
886 	zone->masterfile = NULL;
887 	zone->masterformat = dns_masterformat_none;
888 	zone->keydirectory = NULL;
889 	zone->journalsize = -1;
890 	zone->journal = NULL;
891 	zone->rdclass = dns_rdataclass_none;
892 	zone->type = dns_zone_none;
893 	zone->flags = 0;
894 	zone->options = 0;
895 	zone->keyopts = 0;
896 	zone->db_argc = 0;
897 	zone->db_argv = NULL;
898 	isc_time_settoepoch(&zone->expiretime);
899 	isc_time_settoepoch(&zone->refreshtime);
900 	isc_time_settoepoch(&zone->dumptime);
901 	isc_time_settoepoch(&zone->loadtime);
902 	zone->notifytime = now;
903 	isc_time_settoepoch(&zone->resigntime);
904 	isc_time_settoepoch(&zone->keywarntime);
905 	isc_time_settoepoch(&zone->signingtime);
906 	isc_time_settoepoch(&zone->nsec3chaintime);
907 	isc_time_settoepoch(&zone->refreshkeytime);
908 	zone->refreshkeyinterval = 0;
909 	zone->refreshkeycount = 0;
910 	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
911 	zone->retry = DNS_ZONE_DEFAULTRETRY;
912 	zone->expire = 0;
913 	zone->minimum = 0;
914 	zone->maxrefresh = DNS_ZONE_MAXREFRESH;
915 	zone->minrefresh = DNS_ZONE_MINREFRESH;
916 	zone->maxretry = DNS_ZONE_MAXRETRY;
917 	zone->minretry = DNS_ZONE_MINRETRY;
918 	zone->masters = NULL;
919 	zone->masterkeynames = NULL;
920 	zone->mastersok = NULL;
921 	zone->masterscnt = 0;
922 	zone->curmaster = 0;
923 	zone->notify = NULL;
924 	zone->notifykeynames = NULL;
925 	zone->notifytype = dns_notifytype_yes;
926 	zone->notifycnt = 0;
927 	zone->task = NULL;
928 	zone->loadtask = NULL;
929 	zone->update_acl = NULL;
930 	zone->forward_acl = NULL;
931 	zone->notify_acl = NULL;
932 	zone->query_acl = NULL;
933 	zone->queryon_acl = NULL;
934 	zone->xfr_acl = NULL;
935 	zone->update_disabled = ISC_FALSE;
936 	zone->zero_no_soa_ttl = ISC_TRUE;
937 	zone->check_names = dns_severity_ignore;
938 	zone->request = NULL;
939 	zone->lctx = NULL;
940 	zone->readio = NULL;
941 	zone->dctx = NULL;
942 	zone->writeio = NULL;
943 	zone->timer = NULL;
944 	zone->idlein = DNS_DEFAULT_IDLEIN;
945 	zone->idleout = DNS_DEFAULT_IDLEOUT;
946 	zone->log_key_expired_timer = 0;
947 	ISC_LIST_INIT(zone->notifies);
948 	isc_sockaddr_any(&zone->notifysrc4);
949 	isc_sockaddr_any6(&zone->notifysrc6);
950 	isc_sockaddr_any(&zone->xfrsource4);
951 	isc_sockaddr_any6(&zone->xfrsource6);
952 	isc_sockaddr_any(&zone->altxfrsource4);
953 	isc_sockaddr_any6(&zone->altxfrsource6);
954 	zone->xfr = NULL;
955 	zone->tsigkey = NULL;
956 	zone->maxxfrin = MAX_XFER_TIME;
957 	zone->maxxfrout = MAX_XFER_TIME;
958 	zone->ssutable = NULL;
959 	zone->sigvalidityinterval = 30 * 24 * 3600;
960 	zone->sigresigninginterval = 7 * 24 * 3600;
961 	zone->view = NULL;
962 	zone->acache = NULL;
963 	zone->checkmx = NULL;
964 	zone->checksrv = NULL;
965 	zone->checkns = NULL;
966 	ISC_LINK_INIT(zone, statelink);
967 	zone->statelist = NULL;
968 	zone->stats = NULL;
969 	zone->requeststats_on = ISC_FALSE;
970 	zone->statlevel = dns_zonestat_none;
971 	zone->requeststats = NULL;
972 	zone->rcvquerystats = NULL;
973 	zone->notifydelay = 5;
974 	zone->isself = NULL;
975 	zone->isselfarg = NULL;
976 	ISC_LIST_INIT(zone->signing);
977 	ISC_LIST_INIT(zone->nsec3chain);
978 	zone->signatures = 10;
979 	zone->nodes = 100;
980 	zone->privatetype = (dns_rdatatype_t)0xffffU;
981 	zone->added = ISC_FALSE;
982 	zone->is_rpz = ISC_FALSE;
983 	ISC_LIST_INIT(zone->forwards);
984 	zone->raw = NULL;
985 	zone->secure = NULL;
986 	zone->sourceserial = 0;
987 	zone->sourceserialset = ISC_FALSE;
988 	ISC_LIST_INIT(zone->rss_events);
989 	zone->rss_db = NULL;
990 	zone->rss_raw = NULL;
991 	zone->rss_newver = NULL;
992 	zone->rss_oldver = NULL;
993 	zone->rss_event = NULL;
994 	zone->rss_state = NULL;
995 	zone->updatemethod = dns_updatemethod_increment;
996 
997 	zone->magic = ZONE_MAGIC;
998 
999 	/* Must be after magic is set. */
1000 	result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1001 	if (result != ISC_R_SUCCESS)
1002 		goto free_erefs;
1003 
1004 	ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1005 		       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
1006 		       NULL, NULL);
1007 	*zonep = zone;
1008 	return (ISC_R_SUCCESS);
1009 
1010  free_erefs:
1011 	isc_refcount_decrement(&zone->erefs, NULL);
1012 	isc_refcount_destroy(&zone->erefs);
1013 
1014  free_dblock:
1015 	ZONEDB_DESTROYLOCK(&zone->dblock);
1016 
1017  free_mutex:
1018 	DESTROYLOCK(&zone->lock);
1019 
1020  free_zone:
1021 	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1022 	return (result);
1023 }
1024 
1025 /*
1026  * Free a zone.  Because we require that there be no more
1027  * outstanding events or references, no locking is necessary.
1028  */
1029 static void
zone_free(dns_zone_t * zone)1030 zone_free(dns_zone_t *zone) {
1031 	isc_mem_t *mctx = NULL;
1032 	dns_signing_t *signing;
1033 	dns_nsec3chain_t *nsec3chain;
1034 
1035 	REQUIRE(DNS_ZONE_VALID(zone));
1036 	REQUIRE(isc_refcount_current(&zone->erefs) == 0);
1037 	REQUIRE(zone->irefs == 0);
1038 	REQUIRE(!LOCKED_ZONE(zone));
1039 	REQUIRE(zone->timer == NULL);
1040 	REQUIRE(zone->zmgr == NULL);
1041 
1042 	/*
1043 	 * Managed objects.  Order is important.
1044 	 */
1045 	if (zone->request != NULL)
1046 		dns_request_destroy(&zone->request); /* XXXMPA */
1047 	INSIST(zone->readio == NULL);
1048 	INSIST(zone->statelist == NULL);
1049 	INSIST(zone->writeio == NULL);
1050 
1051 	if (zone->task != NULL)
1052 		isc_task_detach(&zone->task);
1053 	if (zone->loadtask != NULL)
1054 		isc_task_detach(&zone->loadtask);
1055 	if (zone->view != NULL)
1056 		dns_view_weakdetach(&zone->view);
1057 
1058 	/* Unmanaged objects */
1059 	for (signing = ISC_LIST_HEAD(zone->signing);
1060 	     signing != NULL;
1061 	     signing = ISC_LIST_HEAD(zone->signing)) {
1062 		ISC_LIST_UNLINK(zone->signing, signing, link);
1063 		dns_db_detach(&signing->db);
1064 		dns_dbiterator_destroy(&signing->dbiterator);
1065 		isc_mem_put(zone->mctx, signing, sizeof *signing);
1066 	}
1067 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
1068 	     nsec3chain != NULL;
1069 	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
1070 		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1071 		dns_db_detach(&nsec3chain->db);
1072 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
1073 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1074 	}
1075 	if (zone->masterfile != NULL)
1076 		isc_mem_free(zone->mctx, zone->masterfile);
1077 	zone->masterfile = NULL;
1078 	if (zone->keydirectory != NULL)
1079 		isc_mem_free(zone->mctx, zone->keydirectory);
1080 	zone->keydirectory = NULL;
1081 	zone->journalsize = -1;
1082 	if (zone->journal != NULL)
1083 		isc_mem_free(zone->mctx, zone->journal);
1084 	zone->journal = NULL;
1085 	if (zone->stats != NULL)
1086 		isc_stats_detach(&zone->stats);
1087 	if (zone->requeststats != NULL)
1088 		isc_stats_detach(&zone->requeststats);
1089 	if(zone->rcvquerystats != NULL )
1090 		dns_stats_detach(&zone->rcvquerystats);
1091 	if (zone->db != NULL)
1092 		zone_detachdb(zone);
1093 	if (zone->acache != NULL)
1094 		dns_acache_detach(&zone->acache);
1095 	zone_freedbargs(zone);
1096 	RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
1097 		      == ISC_R_SUCCESS);
1098 	RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
1099 		      == ISC_R_SUCCESS);
1100 	zone->check_names = dns_severity_ignore;
1101 	if (zone->update_acl != NULL)
1102 		dns_acl_detach(&zone->update_acl);
1103 	if (zone->forward_acl != NULL)
1104 		dns_acl_detach(&zone->forward_acl);
1105 	if (zone->notify_acl != NULL)
1106 		dns_acl_detach(&zone->notify_acl);
1107 	if (zone->query_acl != NULL)
1108 		dns_acl_detach(&zone->query_acl);
1109 	if (zone->queryon_acl != NULL)
1110 		dns_acl_detach(&zone->queryon_acl);
1111 	if (zone->xfr_acl != NULL)
1112 		dns_acl_detach(&zone->xfr_acl);
1113 	if (dns_name_dynamic(&zone->origin))
1114 		dns_name_free(&zone->origin, zone->mctx);
1115 	if (zone->strnamerd != NULL)
1116 		isc_mem_free(zone->mctx, zone->strnamerd);
1117 	if (zone->strname != NULL)
1118 		isc_mem_free(zone->mctx, zone->strname);
1119 	if (zone->strrdclass != NULL)
1120 		isc_mem_free(zone->mctx, zone->strrdclass);
1121 	if (zone->strviewname != NULL)
1122 		isc_mem_free(zone->mctx, zone->strviewname);
1123 	if (zone->ssutable != NULL)
1124 		dns_ssutable_detach(&zone->ssutable);
1125 
1126 	/* last stuff */
1127 	ZONEDB_DESTROYLOCK(&zone->dblock);
1128 	DESTROYLOCK(&zone->lock);
1129 	isc_refcount_destroy(&zone->erefs);
1130 	zone->magic = 0;
1131 	mctx = zone->mctx;
1132 	isc_mem_put(mctx, zone, sizeof(*zone));
1133 	isc_mem_detach(&mctx);
1134 }
1135 
1136 /*
1137  * Returns ISC_TRUE iff this the signed side of an inline-signing zone.
1138  * Caller should hold zone lock.
1139  */
1140 static inline isc_boolean_t
inline_secure(dns_zone_t * zone)1141 inline_secure(dns_zone_t *zone) {
1142 	REQUIRE(DNS_ZONE_VALID(zone));
1143 	if (zone->raw != NULL)
1144 		return (ISC_TRUE);
1145 	return (ISC_FALSE);
1146 }
1147 
1148 /*
1149  * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone
1150  * Caller should hold zone lock.
1151  */
1152 static inline isc_boolean_t
inline_raw(dns_zone_t * zone)1153 inline_raw(dns_zone_t *zone) {
1154 	REQUIRE(DNS_ZONE_VALID(zone));
1155 	if (zone->secure != NULL)
1156 		return (ISC_TRUE);
1157 	return (ISC_FALSE);
1158 }
1159 
1160 /*
1161  *	Single shot.
1162  */
1163 void
dns_zone_setclass(dns_zone_t * zone,dns_rdataclass_t rdclass)1164 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1165 	char namebuf[1024];
1166 
1167 	REQUIRE(DNS_ZONE_VALID(zone));
1168 	REQUIRE(rdclass != dns_rdataclass_none);
1169 
1170 	/*
1171 	 * Test and set.
1172 	 */
1173 	LOCK_ZONE(zone);
1174 	REQUIRE(zone->rdclass == dns_rdataclass_none ||
1175 		zone->rdclass == rdclass);
1176 	zone->rdclass = rdclass;
1177 
1178 	if (zone->strnamerd != NULL)
1179 		isc_mem_free(zone->mctx, zone->strnamerd);
1180 	if (zone->strrdclass != NULL)
1181 		isc_mem_free(zone->mctx, zone->strrdclass);
1182 
1183 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1184 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1185 	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1186 	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1187 
1188 	if (inline_secure(zone))
1189 		dns_zone_setclass(zone->raw, rdclass);
1190 	UNLOCK_ZONE(zone);
1191 }
1192 
1193 dns_rdataclass_t
dns_zone_getclass(dns_zone_t * zone)1194 dns_zone_getclass(dns_zone_t *zone) {
1195 	REQUIRE(DNS_ZONE_VALID(zone));
1196 
1197 	return (zone->rdclass);
1198 }
1199 
1200 void
dns_zone_setnotifytype(dns_zone_t * zone,dns_notifytype_t notifytype)1201 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1202 	REQUIRE(DNS_ZONE_VALID(zone));
1203 
1204 	LOCK_ZONE(zone);
1205 	zone->notifytype = notifytype;
1206 	UNLOCK_ZONE(zone);
1207 }
1208 
1209 isc_result_t
dns_zone_getserial2(dns_zone_t * zone,isc_uint32_t * serialp)1210 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1211 	isc_result_t result;
1212 	unsigned int soacount;
1213 
1214 	REQUIRE(DNS_ZONE_VALID(zone));
1215 	REQUIRE(serialp != NULL);
1216 
1217 	LOCK_ZONE(zone);
1218 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1219 	if (zone->db != NULL) {
1220 		result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1221 					  serialp, NULL, NULL, NULL, NULL,
1222 					  NULL);
1223 		if (result == ISC_R_SUCCESS && soacount == 0)
1224 			result = ISC_R_FAILURE;
1225 	} else
1226 		result = DNS_R_NOTLOADED;
1227 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1228 	UNLOCK_ZONE(zone);
1229 
1230 	return (result);
1231 }
1232 
1233 isc_uint32_t
dns_zone_getserial(dns_zone_t * zone)1234 dns_zone_getserial(dns_zone_t *zone) {
1235 	isc_result_t result;
1236 	isc_uint32_t serial;
1237 
1238 	result = dns_zone_getserial2(zone, &serial);
1239 	if (result != ISC_R_SUCCESS)
1240 		serial = 0; /* XXX: not really correct, but no other choice */
1241 
1242 	return (serial);
1243 }
1244 
1245 /*
1246  *	Single shot.
1247  */
1248 void
dns_zone_settype(dns_zone_t * zone,dns_zonetype_t type)1249 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1250 	char namebuf[1024];
1251 
1252 	REQUIRE(DNS_ZONE_VALID(zone));
1253 	REQUIRE(type != dns_zone_none);
1254 
1255 	/*
1256 	 * Test and set.
1257 	 */
1258 	LOCK_ZONE(zone);
1259 	REQUIRE(zone->type == dns_zone_none || zone->type == type);
1260 	zone->type = type;
1261 
1262 	if (zone->strnamerd != NULL)
1263 		isc_mem_free(zone->mctx, zone->strnamerd);
1264 
1265 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1266 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1267 	UNLOCK_ZONE(zone);
1268 }
1269 
1270 static void
zone_freedbargs(dns_zone_t * zone)1271 zone_freedbargs(dns_zone_t *zone) {
1272 	unsigned int i;
1273 
1274 	/* Free the old database argument list. */
1275 	if (zone->db_argv != NULL) {
1276 		for (i = 0; i < zone->db_argc; i++)
1277 			isc_mem_free(zone->mctx, zone->db_argv[i]);
1278 		isc_mem_put(zone->mctx, zone->db_argv,
1279 			    zone->db_argc * sizeof(*zone->db_argv));
1280 	}
1281 	zone->db_argc = 0;
1282 	zone->db_argv = NULL;
1283 }
1284 
1285 isc_result_t
dns_zone_getdbtype(dns_zone_t * zone,char *** argv,isc_mem_t * mctx)1286 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1287 	size_t size = 0;
1288 	unsigned int i;
1289 	isc_result_t result = ISC_R_SUCCESS;
1290 	void *mem;
1291 	char **tmp, *tmp2;
1292 
1293 	REQUIRE(DNS_ZONE_VALID(zone));
1294 	REQUIRE(argv != NULL && *argv == NULL);
1295 
1296 	LOCK_ZONE(zone);
1297 	size = (zone->db_argc + 1) * sizeof(char *);
1298 	for (i = 0; i < zone->db_argc; i++)
1299 		size += strlen(zone->db_argv[i]) + 1;
1300 	mem = isc_mem_allocate(mctx, size);
1301 	if (mem != NULL) {
1302 		tmp = mem;
1303 		tmp2 = mem;
1304 		tmp2 += (zone->db_argc + 1) * sizeof(char *);
1305 		for (i = 0; i < zone->db_argc; i++) {
1306 			*tmp++ = tmp2;
1307 			strcpy(tmp2, zone->db_argv[i]);
1308 			tmp2 += strlen(tmp2) + 1;
1309 		}
1310 		*tmp = NULL;
1311 	} else
1312 		result = ISC_R_NOMEMORY;
1313 	UNLOCK_ZONE(zone);
1314 	*argv = mem;
1315 	return (result);
1316 }
1317 
1318 isc_result_t
dns_zone_setdbtype(dns_zone_t * zone,unsigned int dbargc,const char * const * dbargv)1319 dns_zone_setdbtype(dns_zone_t *zone,
1320 		   unsigned int dbargc, const char * const *dbargv) {
1321 	isc_result_t result = ISC_R_SUCCESS;
1322 	char **new = NULL;
1323 	unsigned int i;
1324 
1325 	REQUIRE(DNS_ZONE_VALID(zone));
1326 	REQUIRE(dbargc >= 1);
1327 	REQUIRE(dbargv != NULL);
1328 
1329 	LOCK_ZONE(zone);
1330 
1331 	/* Set up a new database argument list. */
1332 	new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1333 	if (new == NULL)
1334 		goto nomem;
1335 	for (i = 0; i < dbargc; i++)
1336 		new[i] = NULL;
1337 	for (i = 0; i < dbargc; i++) {
1338 		new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1339 		if (new[i] == NULL)
1340 			goto nomem;
1341 	}
1342 
1343 	/* Free the old list. */
1344 	zone_freedbargs(zone);
1345 
1346 	zone->db_argc = dbargc;
1347 	zone->db_argv = new;
1348 	result = ISC_R_SUCCESS;
1349 	goto unlock;
1350 
1351  nomem:
1352 	if (new != NULL) {
1353 		for (i = 0; i < dbargc; i++)
1354 			if (new[i] != NULL)
1355 				isc_mem_free(zone->mctx, new[i]);
1356 		isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1357 	}
1358 	result = ISC_R_NOMEMORY;
1359 
1360  unlock:
1361 	UNLOCK_ZONE(zone);
1362 	return (result);
1363 }
1364 
1365 void
dns_zone_setview(dns_zone_t * zone,dns_view_t * view)1366 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1367 	char namebuf[1024];
1368 	REQUIRE(DNS_ZONE_VALID(zone));
1369 
1370 	LOCK_ZONE(zone);
1371 	if (zone->view != NULL)
1372 		dns_view_weakdetach(&zone->view);
1373 	dns_view_weakattach(view, &zone->view);
1374 
1375 	if (zone->strviewname != NULL)
1376 		isc_mem_free(zone->mctx, zone->strviewname);
1377 	if (zone->strnamerd != NULL)
1378 		isc_mem_free(zone->mctx, zone->strnamerd);
1379 
1380 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1381 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1382 	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1383 	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1384 
1385 	if (inline_secure(zone))
1386 		dns_zone_setview(zone->raw, view);
1387 
1388 	UNLOCK_ZONE(zone);
1389 }
1390 
1391 dns_view_t *
dns_zone_getview(dns_zone_t * zone)1392 dns_zone_getview(dns_zone_t *zone) {
1393 	REQUIRE(DNS_ZONE_VALID(zone));
1394 
1395 	return (zone->view);
1396 }
1397 
1398 
1399 isc_result_t
dns_zone_setorigin(dns_zone_t * zone,const dns_name_t * origin)1400 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1401 	isc_result_t result;
1402 	char namebuf[1024];
1403 
1404 	REQUIRE(DNS_ZONE_VALID(zone));
1405 	REQUIRE(origin != NULL);
1406 
1407 	LOCK_ZONE(zone);
1408 	if (dns_name_dynamic(&zone->origin)) {
1409 		dns_name_free(&zone->origin, zone->mctx);
1410 		dns_name_init(&zone->origin, NULL);
1411 	}
1412 	result = dns_name_dup(origin, zone->mctx, &zone->origin);
1413 
1414 	if (zone->strnamerd != NULL)
1415 		isc_mem_free(zone->mctx, zone->strnamerd);
1416 	if (zone->strname != NULL)
1417 		isc_mem_free(zone->mctx, zone->strname);
1418 
1419 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1420 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1421 	zone_name_tostr(zone, namebuf, sizeof namebuf);
1422 	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1423 
1424 	if (result == ISC_R_SUCCESS && inline_secure(zone))
1425 		result = dns_zone_setorigin(zone->raw, origin);
1426 	UNLOCK_ZONE(zone);
1427 	return (result);
1428 }
1429 
1430 void
dns_zone_setacache(dns_zone_t * zone,dns_acache_t * acache)1431 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1432 	REQUIRE(DNS_ZONE_VALID(zone));
1433 	REQUIRE(acache != NULL);
1434 
1435 	LOCK_ZONE(zone);
1436 	if (zone->acache != NULL)
1437 		dns_acache_detach(&zone->acache);
1438 	dns_acache_attach(acache, &zone->acache);
1439 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1440 	if (zone->db != NULL) {
1441 		isc_result_t result;
1442 
1443 		/*
1444 		 * If the zone reuses an existing DB, the DB needs to be
1445 		 * set in the acache explicitly.  We can safely ignore the
1446 		 * case where the DB is already set.  If other error happens,
1447 		 * the acache will not work effectively.
1448 		 */
1449 		result = dns_acache_setdb(acache, zone->db);
1450 		if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1451 			UNEXPECTED_ERROR(__FILE__, __LINE__,
1452 					 "dns_acache_setdb() failed: %s",
1453 					 isc_result_totext(result));
1454 		}
1455 	}
1456 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1457 	UNLOCK_ZONE(zone);
1458 }
1459 
1460 static isc_result_t
dns_zone_setstring(dns_zone_t * zone,char ** field,const char * value)1461 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1462 	char *copy;
1463 
1464 	if (value != NULL) {
1465 		copy = isc_mem_strdup(zone->mctx, value);
1466 		if (copy == NULL)
1467 			return (ISC_R_NOMEMORY);
1468 	} else {
1469 		copy = NULL;
1470 	}
1471 
1472 	if (*field != NULL)
1473 		isc_mem_free(zone->mctx, *field);
1474 
1475 	*field = copy;
1476 	return (ISC_R_SUCCESS);
1477 }
1478 
1479 isc_result_t
dns_zone_setfile(dns_zone_t * zone,const char * file)1480 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1481 	return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1482 }
1483 
1484 isc_result_t
dns_zone_setfile2(dns_zone_t * zone,const char * file,dns_masterformat_t format)1485 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1486 		  dns_masterformat_t format) {
1487 	isc_result_t result = ISC_R_SUCCESS;
1488 
1489 	REQUIRE(DNS_ZONE_VALID(zone));
1490 
1491 	LOCK_ZONE(zone);
1492 	result = dns_zone_setstring(zone, &zone->masterfile, file);
1493 	if (result == ISC_R_SUCCESS) {
1494 		zone->masterformat = format;
1495 		result = default_journal(zone);
1496 	}
1497 	UNLOCK_ZONE(zone);
1498 
1499 	return (result);
1500 }
1501 
1502 const char *
dns_zone_getfile(dns_zone_t * zone)1503 dns_zone_getfile(dns_zone_t *zone) {
1504 	REQUIRE(DNS_ZONE_VALID(zone));
1505 
1506 	return (zone->masterfile);
1507 }
1508 
1509 static isc_result_t
default_journal(dns_zone_t * zone)1510 default_journal(dns_zone_t *zone) {
1511 	isc_result_t result;
1512 	char *journal;
1513 
1514 	REQUIRE(DNS_ZONE_VALID(zone));
1515 	REQUIRE(LOCKED_ZONE(zone));
1516 
1517 	if (zone->masterfile != NULL) {
1518 		/* Calculate string length including '\0'. */
1519 		int len = strlen(zone->masterfile) + sizeof(".jnl");
1520 		journal = isc_mem_allocate(zone->mctx, len);
1521 		if (journal == NULL)
1522 			return (ISC_R_NOMEMORY);
1523 		strcpy(journal, zone->masterfile);
1524 		strcat(journal, ".jnl");
1525 	} else {
1526 		journal = NULL;
1527 	}
1528 	result = dns_zone_setstring(zone, &zone->journal, journal);
1529 	if (journal != NULL)
1530 		isc_mem_free(zone->mctx, journal);
1531 	return (result);
1532 }
1533 
1534 isc_result_t
dns_zone_setjournal(dns_zone_t * zone,const char * journal)1535 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1536 	isc_result_t result = ISC_R_SUCCESS;
1537 
1538 	REQUIRE(DNS_ZONE_VALID(zone));
1539 
1540 	LOCK_ZONE(zone);
1541 	result = dns_zone_setstring(zone, &zone->journal, journal);
1542 	UNLOCK_ZONE(zone);
1543 
1544 	return (result);
1545 }
1546 
1547 char *
dns_zone_getjournal(dns_zone_t * zone)1548 dns_zone_getjournal(dns_zone_t *zone) {
1549 	REQUIRE(DNS_ZONE_VALID(zone));
1550 
1551 	return (zone->journal);
1552 }
1553 
1554 /*
1555  * Return true iff the zone is "dynamic", in the sense that the zone's
1556  * master file (if any) is written by the server, rather than being
1557  * updated manually and read by the server.
1558  *
1559  * This is true for slave zones, stub zones, key zones, and zones that
1560  * allow dynamic updates either by having an update policy ("ssutable")
1561  * or an "allow-update" ACL with a value other than exactly "{ none; }".
1562  */
1563 isc_boolean_t
dns_zone_isdynamic(dns_zone_t * zone,isc_boolean_t ignore_freeze)1564 dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) {
1565 	REQUIRE(DNS_ZONE_VALID(zone));
1566 
1567 	if (zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1568 	    zone->type == dns_zone_key ||
1569 	    (zone->type == dns_zone_redirect && zone->masters != NULL))
1570 		return (ISC_TRUE);
1571 
1572 	/* If !ignore_freeze, we need check whether updates are disabled.  */
1573 	if (zone->type == dns_zone_master &&
1574 	    (!zone->update_disabled || ignore_freeze) &&
1575 	    ((zone->ssutable != NULL) ||
1576 	     (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1577 		return (ISC_TRUE);
1578 
1579 	return (ISC_FALSE);
1580 
1581 }
1582 
1583 /*
1584  * Set the response policy index and information for a zone.
1585  */
1586 isc_result_t
dns_zone_rpz_enable(dns_zone_t * zone)1587 dns_zone_rpz_enable(dns_zone_t *zone) {
1588 	/*
1589 	 * Only RBTDB zones can be used for response policy zones,
1590 	 * because only they have the code to load the create the summary data.
1591 	 * Only zones that are loaded instead of mmap()ed create the
1592 	 * summary data and so can be policy zones.
1593 	 */
1594 	if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1595 	    strcmp(zone->db_argv[0], "rbt64") != 0)
1596 		return (ISC_R_NOTIMPLEMENTED);
1597 
1598 	zone->is_rpz = ISC_TRUE;
1599 
1600 	return (ISC_R_SUCCESS);
1601 }
1602 
1603 isc_boolean_t
dns_zone_get_rpz(dns_zone_t * zone)1604 dns_zone_get_rpz(dns_zone_t *zone) {
1605 	return (zone->is_rpz);
1606 }
1607 
1608 /*
1609  * If a zone is a response policy zone, mark its new database.
1610  */
1611 isc_result_t
dns_zone_rpz_enable_db(dns_zone_t * zone,dns_db_t * db)1612 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1613 #ifdef BIND9
1614 	if (zone->is_rpz)
1615 		return (dns_db_rpz_enabled(db, NULL));
1616 #endif
1617 	return (ISC_R_SUCCESS);
1618 }
1619 
1620 static isc_result_t
zone_load(dns_zone_t * zone,unsigned int flags,isc_boolean_t locked)1621 zone_load(dns_zone_t *zone, unsigned int flags, isc_boolean_t locked) {
1622 	isc_result_t result;
1623 	isc_time_t now;
1624 	isc_time_t loadtime, filetime;
1625 	dns_db_t *db = NULL;
1626 	isc_boolean_t rbt, hasraw;
1627 
1628 	REQUIRE(DNS_ZONE_VALID(zone));
1629 
1630 	if (!locked)
1631 		LOCK_ZONE(zone);
1632 	hasraw = inline_secure(zone);
1633 	if (hasraw) {
1634 		result = zone_load(zone->raw, flags, ISC_FALSE);
1635 		if (result != ISC_R_SUCCESS) {
1636 			if (!locked)
1637 				UNLOCK_ZONE(zone);
1638 			return(result);
1639 		}
1640 		LOCK_ZONE(zone->raw);
1641 	}
1642 
1643 	TIME_NOW(&now);
1644 
1645 	INSIST(zone->type != dns_zone_none);
1646 
1647 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1648 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1649 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1650 		result = DNS_R_CONTINUE;
1651 		goto cleanup;
1652 	}
1653 
1654 	INSIST(zone->db_argc >= 1);
1655 
1656 	rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1657 	      strcmp(zone->db_argv[0], "rbt64") == 0;
1658 
1659 	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1660 		/*
1661 		 * The zone has no master file configured.
1662 		 */
1663 		result = ISC_R_SUCCESS;
1664 		goto cleanup;
1665 	}
1666 
1667 	if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) {
1668 		/*
1669 		 * This is a slave, stub, or dynamically updated
1670 		 * zone being reloaded.  Do nothing - the database
1671 		 * we already have is guaranteed to be up-to-date.
1672 		 */
1673 		if (zone->type == dns_zone_master)
1674 			result = DNS_R_DYNAMIC;
1675 		else
1676 			result = ISC_R_SUCCESS;
1677 		goto cleanup;
1678 	}
1679 
1680 	/*
1681 	 * Store the current time before the zone is loaded, so that if the
1682 	 * file changes between the time of the load and the time that
1683 	 * zone->loadtime is set, then the file will still be reloaded
1684 	 * the next time dns_zone_load is called.
1685 	 */
1686 	TIME_NOW(&loadtime);
1687 
1688 	/*
1689 	 * Don't do the load if the file that stores the zone is older
1690 	 * than the last time the zone was loaded.  If the zone has not
1691 	 * been loaded yet, zone->loadtime will be the epoch.
1692 	 */
1693 	if (zone->masterfile != NULL) {
1694 		/*
1695 		 * The file is already loaded.	If we are just doing a
1696 		 * "rndc reconfig", we are done.
1697 		 */
1698 		if (!isc_time_isepoch(&zone->loadtime) &&
1699 		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1700 			result = ISC_R_SUCCESS;
1701 			goto cleanup;
1702 		}
1703 
1704 		result = isc_file_getmodtime(zone->masterfile, &filetime);
1705 		if (result == ISC_R_SUCCESS) {
1706 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1707 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1708 			    isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1709 				dns_zone_log(zone, ISC_LOG_DEBUG(1),
1710 					     "skipping load: master file "
1711 					     "older than last load");
1712 				result = DNS_R_UPTODATE;
1713 				goto cleanup;
1714 			}
1715 			loadtime = filetime;
1716 		}
1717 	}
1718 
1719 	/*
1720 	 * Built in zones (with the exception of empty zones) don't need
1721 	 * to be reloaded.
1722 	 */
1723 	if (zone->type == dns_zone_master &&
1724 	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
1725 	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1726 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1727 		result = ISC_R_SUCCESS;
1728 		goto cleanup;
1729 	}
1730 
1731 	if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1732 	     (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
1733 	    rbt) {
1734 		if (zone->masterfile == NULL ||
1735 		    !isc_file_exists(zone->masterfile)) {
1736 			if (zone->masterfile != NULL) {
1737 				dns_zone_log(zone, ISC_LOG_DEBUG(1),
1738 					     "no master file");
1739 			}
1740 			zone->refreshtime = now;
1741 			if (zone->task != NULL)
1742 				zone_settimer(zone, &now);
1743 			result = ISC_R_SUCCESS;
1744 			goto cleanup;
1745 		}
1746 	}
1747 
1748 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1749 
1750 	result = dns_db_create(zone->mctx, zone->db_argv[0],
1751 			       &zone->origin, (zone->type == dns_zone_stub) ?
1752 			       dns_dbtype_stub : dns_dbtype_zone,
1753 			       zone->rdclass,
1754 			       zone->db_argc - 1, zone->db_argv + 1,
1755 			       &db);
1756 
1757 	if (result != ISC_R_SUCCESS) {
1758 		dns_zone_log(zone, ISC_LOG_ERROR,
1759 			     "loading zone: creating database: %s",
1760 			     isc_result_totext(result));
1761 		goto cleanup;
1762 	}
1763 	dns_db_settask(db, zone->task);
1764 
1765 	if (! dns_db_ispersistent(db)) {
1766 		if (zone->masterfile != NULL) {
1767 			result = zone_startload(db, zone, loadtime);
1768 		} else {
1769 			result = DNS_R_NOMASTERFILE;
1770 			if (zone->type == dns_zone_master ||
1771 			    (zone->type == dns_zone_redirect &&
1772 			     zone->masters == NULL)) {
1773 				dns_zone_log(zone, ISC_LOG_ERROR,
1774 					     "loading zone: "
1775 					     "no master file configured");
1776 				goto cleanup;
1777 			}
1778 			dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1779 				     "no master file configured: continuing");
1780 		}
1781 	}
1782 
1783 	if (result == DNS_R_CONTINUE) {
1784 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1785 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1786 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1787 		goto cleanup;
1788 	}
1789 
1790 	result = zone_postload(zone, db, loadtime, result);
1791 
1792  cleanup:
1793 	if (hasraw)
1794 		UNLOCK_ZONE(zone->raw);
1795 	if (!locked)
1796 		UNLOCK_ZONE(zone);
1797 	if (db != NULL)
1798 		dns_db_detach(&db);
1799 	return (result);
1800 }
1801 
1802 isc_result_t
dns_zone_load(dns_zone_t * zone)1803 dns_zone_load(dns_zone_t *zone) {
1804 	return (zone_load(zone, 0, ISC_FALSE));
1805 }
1806 
1807 isc_result_t
dns_zone_loadnew(dns_zone_t * zone)1808 dns_zone_loadnew(dns_zone_t *zone) {
1809 	return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT, ISC_FALSE));
1810 }
1811 
1812 static void
zone_asyncload(isc_task_t * task,isc_event_t * event)1813 zone_asyncload(isc_task_t *task, isc_event_t *event) {
1814 	dns_asyncload_t *asl = event->ev_arg;
1815 	dns_zone_t *zone = asl->zone;
1816 	isc_result_t result = ISC_R_SUCCESS;
1817 	isc_boolean_t load_pending;
1818 
1819 	UNUSED(task);
1820 
1821 	REQUIRE(DNS_ZONE_VALID(zone));
1822 
1823 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1824 		result = ISC_R_CANCELED;
1825 	isc_event_free(&event);
1826 
1827 	if (result == ISC_R_CANCELED)
1828 		goto cleanup;
1829 
1830 	/* Make sure load is still pending */
1831 	LOCK_ZONE(zone);
1832 	load_pending = ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
1833 
1834 	if (!load_pending) {
1835 		UNLOCK_ZONE(zone);
1836 		goto cleanup;
1837 	}
1838 
1839 	zone_load(zone, 0, ISC_TRUE);
1840 
1841 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1842 	UNLOCK_ZONE(zone);
1843 
1844 	/* Inform the zone table we've finished loading */
1845 	if (asl->loaded != NULL)
1846 		(asl->loaded)(asl->loaded_arg, zone, task);
1847 
1848  cleanup:
1849 	isc_mem_put(zone->mctx, asl, sizeof (*asl));
1850 	dns_zone_idetach(&zone);
1851 }
1852 
1853 isc_result_t
dns_zone_asyncload(dns_zone_t * zone,dns_zt_zoneloaded_t done,void * arg)1854 dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
1855 	isc_event_t *e;
1856 	dns_asyncload_t *asl = NULL;
1857 	isc_result_t result = ISC_R_SUCCESS;
1858 
1859 	REQUIRE(DNS_ZONE_VALID(zone));
1860 
1861 	if (zone->zmgr == NULL)
1862 		return (ISC_R_FAILURE);
1863 
1864 	/* If we already have a load pending, stop now */
1865 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
1866 		return (ISC_R_ALREADYRUNNING);
1867 
1868 	asl = isc_mem_get(zone->mctx, sizeof (*asl));
1869 	if (asl == NULL)
1870 		CHECK(ISC_R_NOMEMORY);
1871 
1872 	asl->zone = NULL;
1873 	asl->loaded = done;
1874 	asl->loaded_arg = arg;
1875 
1876 	e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
1877 			       DNS_EVENT_ZONELOAD,
1878 			       zone_asyncload, asl,
1879 			       sizeof(isc_event_t));
1880 	if (e == NULL)
1881 		CHECK(ISC_R_NOMEMORY);
1882 
1883 	LOCK_ZONE(zone);
1884 	zone_iattach(zone, &asl->zone);
1885 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1886 	isc_task_send(zone->loadtask, &e);
1887 	UNLOCK_ZONE(zone);
1888 
1889 	return (ISC_R_SUCCESS);
1890 
1891   failure:
1892 	if (asl != NULL)
1893 		isc_mem_put(zone->mctx, asl, sizeof (*asl));
1894 	return (result);
1895 }
1896 
1897 isc_boolean_t
dns__zone_loadpending(dns_zone_t * zone)1898 dns__zone_loadpending(dns_zone_t *zone) {
1899 	REQUIRE(DNS_ZONE_VALID(zone));
1900 
1901 	return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)));
1902 }
1903 
1904 isc_result_t
dns_zone_loadandthaw(dns_zone_t * zone)1905 dns_zone_loadandthaw(dns_zone_t *zone) {
1906 	isc_result_t result;
1907 
1908 	if (inline_raw(zone))
1909 		result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW,
1910 				   ISC_FALSE);
1911 	else
1912 		result = zone_load(zone, DNS_ZONELOADFLAG_THAW, ISC_FALSE);
1913 
1914 	switch (result) {
1915 	case DNS_R_CONTINUE:
1916 		/* Deferred thaw. */
1917 		break;
1918 	case DNS_R_UPTODATE:
1919 	case ISC_R_SUCCESS:
1920 	case DNS_R_SEENINCLUDE:
1921 		zone->update_disabled = ISC_FALSE;
1922 		break;
1923 	case DNS_R_NOMASTERFILE:
1924 		zone->update_disabled = ISC_FALSE;
1925 		break;
1926 	default:
1927 		/* Error, remain in disabled state. */
1928 		break;
1929 	}
1930 	return (result);
1931 }
1932 
1933 static unsigned int
get_master_options(dns_zone_t * zone)1934 get_master_options(dns_zone_t *zone) {
1935 	unsigned int options;
1936 
1937 	options = DNS_MASTER_ZONE;
1938 	if (zone->type == dns_zone_slave ||
1939 	    (zone->type == dns_zone_redirect && zone->masters == NULL))
1940 		options |= DNS_MASTER_SLAVE;
1941 	if (zone->type == dns_zone_key)
1942 		options |= DNS_MASTER_KEY;
1943 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1944 		options |= DNS_MASTER_CHECKNS;
1945 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1946 		options |= DNS_MASTER_FATALNS;
1947 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1948 		options |= DNS_MASTER_CHECKNAMES;
1949 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1950 		options |= DNS_MASTER_CHECKNAMESFAIL;
1951 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1952 		options |= DNS_MASTER_CHECKMX;
1953 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1954 		options |= DNS_MASTER_CHECKMXFAIL;
1955 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1956 		options |= DNS_MASTER_CHECKWILDCARD;
1957 	if (inline_secure(zone) || (zone->type == dns_zone_master &&
1958 	    ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1959 	      zone->ssutable != NULL)))
1960 		options |= DNS_MASTER_RESIGN;
1961 	return (options);
1962 }
1963 
1964 static void
zone_gotreadhandle(isc_task_t * task,isc_event_t * event)1965 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1966 	dns_load_t *load = event->ev_arg;
1967 	isc_result_t result = ISC_R_SUCCESS;
1968 	unsigned int options;
1969 
1970 	REQUIRE(DNS_LOAD_VALID(load));
1971 
1972 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1973 		result = ISC_R_CANCELED;
1974 	isc_event_free(&event);
1975 	if (result == ISC_R_CANCELED)
1976 		goto fail;
1977 
1978 	options = get_master_options(load->zone);
1979 
1980 	result = dns_master_loadfileinc3(load->zone->masterfile,
1981 					 dns_db_origin(load->db),
1982 					 dns_db_origin(load->db),
1983 					 load->zone->rdclass, options, 0,
1984 					 &load->callbacks, task,
1985 					 zone_loaddone, load,
1986 					 &load->zone->lctx, load->zone->mctx,
1987 					 load->zone->masterformat);
1988 	if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1989 	    result != DNS_R_SEENINCLUDE)
1990 		goto fail;
1991 	return;
1992 
1993  fail:
1994 	zone_loaddone(load, result);
1995 }
1996 
1997 static void
get_raw_serial(dns_zone_t * raw,dns_masterrawheader_t * rawdata)1998 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
1999 	isc_result_t result;
2000 	unsigned int soacount;
2001 
2002 	LOCK(&raw->lock);
2003 	if (raw->db != NULL) {
2004 		result = zone_get_from_db(raw, raw->db, NULL, &soacount,
2005 					  &rawdata->sourceserial,
2006 					  NULL, NULL, NULL, NULL,
2007 					  NULL);
2008 		if (result == ISC_R_SUCCESS && soacount > 0U)
2009 			rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2010 	}
2011 	UNLOCK(&raw->lock);
2012 }
2013 
2014 static void
zone_gotwritehandle(isc_task_t * task,isc_event_t * event)2015 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2016 	const char me[] = "zone_gotwritehandle";
2017 	dns_zone_t *zone = event->ev_arg;
2018 	isc_result_t result = ISC_R_SUCCESS;
2019 	dns_dbversion_t *version = NULL;
2020 	dns_masterrawheader_t rawdata;
2021 
2022 	REQUIRE(DNS_ZONE_VALID(zone));
2023 	INSIST(task == zone->task);
2024 	ENTER;
2025 
2026 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2027 		result = ISC_R_CANCELED;
2028 	isc_event_free(&event);
2029 	if (result == ISC_R_CANCELED)
2030 		goto fail;
2031 
2032 	LOCK_ZONE(zone);
2033 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2034 	if (zone->db != NULL) {
2035 		const dns_master_style_t *output_style;
2036 
2037 		dns_db_currentversion(zone->db, &version);
2038 		dns_master_initrawheader(&rawdata);
2039 		if (inline_secure(zone))
2040 			get_raw_serial(zone->raw, &rawdata);
2041 		if (zone->type == dns_zone_key)
2042 			output_style = &dns_master_style_keyzone;
2043 		else
2044 			output_style = &dns_master_style_default;
2045 		result = dns_master_dumpinc3(zone->mctx, zone->db, version,
2046 					     output_style, zone->masterfile,
2047 					     zone->task, dump_done, zone,						     &zone->dctx, zone->masterformat,
2048 					     &rawdata);
2049 		dns_db_closeversion(zone->db, &version, ISC_FALSE);
2050 	} else
2051 		result = ISC_R_CANCELED;
2052 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2053 	UNLOCK_ZONE(zone);
2054 	if (result != DNS_R_CONTINUE)
2055 		goto fail;
2056 	return;
2057 
2058  fail:
2059 	dump_done(zone, result);
2060 }
2061 
2062 /*
2063  * Save the raw serial number for inline-signing zones.
2064  * (XXX: Other information from the header will be used
2065  * for other purposes in the future, but for now this is
2066  * all we're interested in.)
2067  */
2068 static void
zone_setrawdata(dns_zone_t * zone,dns_masterrawheader_t * header)2069 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2070 	if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
2071 		return;
2072 
2073 	zone->sourceserial = header->sourceserial;
2074 	zone->sourceserialset = ISC_TRUE;
2075 }
2076 
2077 void
dns_zone_setrawdata(dns_zone_t * zone,dns_masterrawheader_t * header)2078 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2079 	if (zone == NULL)
2080 		return;
2081 
2082 	LOCK_ZONE(zone);
2083 	zone_setrawdata(zone, header);
2084 	UNLOCK_ZONE(zone);
2085 }
2086 
2087 static isc_result_t
zone_startload(dns_db_t * db,dns_zone_t * zone,isc_time_t loadtime)2088 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2089 	dns_load_t *load;
2090 	isc_result_t result;
2091 	isc_result_t tresult;
2092 	unsigned int options;
2093 
2094 	result = dns_zone_rpz_enable_db(zone, db);
2095 	if (result != ISC_R_SUCCESS)
2096 		return (result);
2097 	options = get_master_options(zone);
2098 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
2099 		options |= DNS_MASTER_MANYERRORS;
2100 
2101 	if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2102 		load = isc_mem_get(zone->mctx, sizeof(*load));
2103 		if (load == NULL)
2104 			return (ISC_R_NOMEMORY);
2105 
2106 		load->mctx = NULL;
2107 		load->zone = NULL;
2108 		load->db = NULL;
2109 		load->loadtime = loadtime;
2110 		load->magic = LOAD_MAGIC;
2111 
2112 		isc_mem_attach(zone->mctx, &load->mctx);
2113 		zone_iattach(zone, &load->zone);
2114 		dns_db_attach(db, &load->db);
2115 		dns_rdatacallbacks_init(&load->callbacks);
2116 		load->callbacks.rawdata = zone_setrawdata;
2117 		zone_iattach(zone, &load->callbacks.zone);
2118 		result = dns_db_beginload(db, &load->callbacks.add,
2119 					  &load->callbacks.add_private);
2120 		if (result != ISC_R_SUCCESS)
2121 			goto cleanup;
2122 		result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask,
2123 				       zone_gotreadhandle, load,
2124 				       &zone->readio);
2125 		if (result != ISC_R_SUCCESS) {
2126 			/*
2127 			 * We can't report multiple errors so ignore
2128 			 * the result of dns_db_endload().
2129 			 */
2130 			(void)dns_db_endload(load->db,
2131 					     &load->callbacks.add_private);
2132 			goto cleanup;
2133 		} else
2134 			result = DNS_R_CONTINUE;
2135 	} else {
2136 		dns_rdatacallbacks_t callbacks;
2137 
2138 		dns_rdatacallbacks_init(&callbacks);
2139 		callbacks.rawdata = zone_setrawdata;
2140 		zone_iattach(zone, &callbacks.zone);
2141 		result = dns_db_beginload(db, &callbacks.add,
2142 					  &callbacks.add_private);
2143 		if (result != ISC_R_SUCCESS) {
2144 			zone_idetach(&callbacks.zone);
2145 			return (result);
2146 		}
2147 		result = dns_master_loadfile3(zone->masterfile,
2148 					      &zone->origin, &zone->origin,
2149 					      zone->rdclass, options, 0,
2150 					      &callbacks, zone->mctx,
2151 					      zone->masterformat);
2152 		tresult = dns_db_endload(db, &callbacks.add_private);
2153 		if (result == ISC_R_SUCCESS)
2154 			result = tresult;
2155 		zone_idetach(&callbacks.zone);
2156 	}
2157 
2158 	return (result);
2159 
2160  cleanup:
2161 	load->magic = 0;
2162 	dns_db_detach(&load->db);
2163 	zone_idetach(&load->zone);
2164 	zone_idetach(&load->callbacks.zone);
2165 	isc_mem_detach(&load->mctx);
2166 	isc_mem_put(zone->mctx, load, sizeof(*load));
2167 	return (result);
2168 }
2169 
2170 static isc_boolean_t
zone_check_mx(dns_zone_t * zone,dns_db_t * db,dns_name_t * name,dns_name_t * owner)2171 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2172 	      dns_name_t *owner)
2173 {
2174 	isc_result_t result;
2175 	char ownerbuf[DNS_NAME_FORMATSIZE];
2176 	char namebuf[DNS_NAME_FORMATSIZE];
2177 	char altbuf[DNS_NAME_FORMATSIZE];
2178 	dns_fixedname_t fixed;
2179 	dns_name_t *foundname;
2180 	int level;
2181 
2182 	/*
2183 	 * "." means the services does not exist.
2184 	 */
2185 	if (dns_name_equal(name, dns_rootname))
2186 		return (ISC_TRUE);
2187 
2188 	/*
2189 	 * Outside of zone.
2190 	 */
2191 	if (!dns_name_issubdomain(name, &zone->origin)) {
2192 		if (zone->checkmx != NULL)
2193 			return ((zone->checkmx)(zone, name, owner));
2194 		return (ISC_TRUE);
2195 	}
2196 
2197 	if (zone->type == dns_zone_master)
2198 		level = ISC_LOG_ERROR;
2199 	else
2200 		level = ISC_LOG_WARNING;
2201 
2202 	dns_fixedname_init(&fixed);
2203 	foundname = dns_fixedname_name(&fixed);
2204 
2205 	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2206 			     0, 0, NULL, foundname, NULL, NULL);
2207 	if (result == ISC_R_SUCCESS)
2208 		return (ISC_TRUE);
2209 
2210 	if (result == DNS_R_NXRRSET) {
2211 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2212 				     0, 0, NULL, foundname, NULL, NULL);
2213 		if (result == ISC_R_SUCCESS)
2214 			return (ISC_TRUE);
2215 	}
2216 
2217 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2218 	dns_name_format(name, namebuf, sizeof namebuf);
2219 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2220 	    result == DNS_R_EMPTYNAME) {
2221 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2222 			level = ISC_LOG_WARNING;
2223 		dns_zone_log(zone, level,
2224 			     "%s/MX '%s' has no address records (A or AAAA)",
2225 			     ownerbuf, namebuf);
2226 		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2227 	}
2228 
2229 	if (result == DNS_R_CNAME) {
2230 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2231 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2232 			level = ISC_LOG_WARNING;
2233 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2234 			dns_zone_log(zone, level,
2235 				     "%s/MX '%s' is a CNAME (illegal)",
2236 				     ownerbuf, namebuf);
2237 		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2238 	}
2239 
2240 	if (result == DNS_R_DNAME) {
2241 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2242 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2243 			level = ISC_LOG_WARNING;
2244 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2245 			dns_name_format(foundname, altbuf, sizeof altbuf);
2246 			dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2247 				     " '%s' (illegal)", ownerbuf, namebuf,
2248 				     altbuf);
2249 		}
2250 		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2251 	}
2252 
2253 	if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2254 		return ((zone->checkmx)(zone, name, owner));
2255 
2256 	return (ISC_TRUE);
2257 }
2258 
2259 static isc_boolean_t
zone_check_srv(dns_zone_t * zone,dns_db_t * db,dns_name_t * name,dns_name_t * owner)2260 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2261 	       dns_name_t *owner)
2262 {
2263 	isc_result_t result;
2264 	char ownerbuf[DNS_NAME_FORMATSIZE];
2265 	char namebuf[DNS_NAME_FORMATSIZE];
2266 	char altbuf[DNS_NAME_FORMATSIZE];
2267 	dns_fixedname_t fixed;
2268 	dns_name_t *foundname;
2269 	int level;
2270 
2271 	/*
2272 	 * "." means the services does not exist.
2273 	 */
2274 	if (dns_name_equal(name, dns_rootname))
2275 		return (ISC_TRUE);
2276 
2277 	/*
2278 	 * Outside of zone.
2279 	 */
2280 	if (!dns_name_issubdomain(name, &zone->origin)) {
2281 		if (zone->checksrv != NULL)
2282 			return ((zone->checksrv)(zone, name, owner));
2283 		return (ISC_TRUE);
2284 	}
2285 
2286 	if (zone->type == dns_zone_master)
2287 		level = ISC_LOG_ERROR;
2288 	else
2289 		level = ISC_LOG_WARNING;
2290 
2291 	dns_fixedname_init(&fixed);
2292 	foundname = dns_fixedname_name(&fixed);
2293 
2294 	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2295 			     0, 0, NULL, foundname, NULL, NULL);
2296 	if (result == ISC_R_SUCCESS)
2297 		return (ISC_TRUE);
2298 
2299 	if (result == DNS_R_NXRRSET) {
2300 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2301 				     0, 0, NULL, foundname, NULL, NULL);
2302 		if (result == ISC_R_SUCCESS)
2303 			return (ISC_TRUE);
2304 	}
2305 
2306 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2307 	dns_name_format(name, namebuf, sizeof namebuf);
2308 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2309 	    result == DNS_R_EMPTYNAME) {
2310 		dns_zone_log(zone, level,
2311 			     "%s/SRV '%s' has no address records (A or AAAA)",
2312 			     ownerbuf, namebuf);
2313 		/* XXX950 make fatal for 9.5.0. */
2314 		return (ISC_TRUE);
2315 	}
2316 
2317 	if (result == DNS_R_CNAME) {
2318 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2319 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2320 			level = ISC_LOG_WARNING;
2321 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2322 			dns_zone_log(zone, level,
2323 				     "%s/SRV '%s' is a CNAME (illegal)",
2324 				     ownerbuf, namebuf);
2325 		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2326 	}
2327 
2328 	if (result == DNS_R_DNAME) {
2329 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2330 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2331 			level = ISC_LOG_WARNING;
2332 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2333 			dns_name_format(foundname, altbuf, sizeof altbuf);
2334 			dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2335 				     "DNAME '%s' (illegal)", ownerbuf, namebuf,
2336 				     altbuf);
2337 		}
2338 		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2339 	}
2340 
2341 	if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2342 		return ((zone->checksrv)(zone, name, owner));
2343 
2344 	return (ISC_TRUE);
2345 }
2346 
2347 static isc_boolean_t
zone_check_glue(dns_zone_t * zone,dns_db_t * db,dns_name_t * name,dns_name_t * owner)2348 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2349 		dns_name_t *owner)
2350 {
2351 	isc_boolean_t answer = ISC_TRUE;
2352 	isc_result_t result, tresult;
2353 	char ownerbuf[DNS_NAME_FORMATSIZE];
2354 	char namebuf[DNS_NAME_FORMATSIZE];
2355 	char altbuf[DNS_NAME_FORMATSIZE];
2356 	dns_fixedname_t fixed;
2357 	dns_name_t *foundname;
2358 	dns_rdataset_t a;
2359 	dns_rdataset_t aaaa;
2360 	int level;
2361 
2362 	/*
2363 	 * Outside of zone.
2364 	 */
2365 	if (!dns_name_issubdomain(name, &zone->origin)) {
2366 		if (zone->checkns != NULL)
2367 			return ((zone->checkns)(zone, name, owner, NULL, NULL));
2368 		return (ISC_TRUE);
2369 	}
2370 
2371 	if (zone->type == dns_zone_master)
2372 		level = ISC_LOG_ERROR;
2373 	else
2374 		level = ISC_LOG_WARNING;
2375 
2376 	dns_fixedname_init(&fixed);
2377 	foundname = dns_fixedname_name(&fixed);
2378 	dns_rdataset_init(&a);
2379 	dns_rdataset_init(&aaaa);
2380 
2381 	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2382 			     DNS_DBFIND_GLUEOK, 0, NULL,
2383 			     foundname, &a, NULL);
2384 
2385 	if (result == ISC_R_SUCCESS) {
2386 		dns_rdataset_disassociate(&a);
2387 		return (ISC_TRUE);
2388 	} else if (result == DNS_R_DELEGATION)
2389 		dns_rdataset_disassociate(&a);
2390 
2391 	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2392 	    result == DNS_R_GLUE) {
2393 		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2394 				     DNS_DBFIND_GLUEOK, 0, NULL,
2395 				     foundname, &aaaa, NULL);
2396 		if (tresult == ISC_R_SUCCESS) {
2397 			if (dns_rdataset_isassociated(&a))
2398 				dns_rdataset_disassociate(&a);
2399 			dns_rdataset_disassociate(&aaaa);
2400 			return (ISC_TRUE);
2401 		}
2402 		if (tresult == DNS_R_DELEGATION)
2403 			dns_rdataset_disassociate(&aaaa);
2404 		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2405 			/*
2406 			 * Check glue against child zone.
2407 			 */
2408 			if (zone->checkns != NULL)
2409 				answer = (zone->checkns)(zone, name, owner,
2410 							 &a, &aaaa);
2411 			if (dns_rdataset_isassociated(&a))
2412 				dns_rdataset_disassociate(&a);
2413 			if (dns_rdataset_isassociated(&aaaa))
2414 				dns_rdataset_disassociate(&aaaa);
2415 			return (answer);
2416 		}
2417 	}
2418 
2419 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2420 	dns_name_format(name, namebuf, sizeof namebuf);
2421 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2422 	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2423 		const char *what;
2424 		isc_boolean_t required = ISC_FALSE;
2425 		if (dns_name_issubdomain(name, owner)) {
2426 			what = "REQUIRED GLUE ";
2427 			required = ISC_TRUE;
2428 		 } else if (result == DNS_R_DELEGATION)
2429 			what = "SIBLING GLUE ";
2430 		else
2431 			what = "";
2432 
2433 		if (result != DNS_R_DELEGATION || required ||
2434 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2435 			dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2436 				     "address records (A or AAAA)",
2437 				     ownerbuf, namebuf, what);
2438 			/*
2439 			 * Log missing address record.
2440 			 */
2441 			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2442 				(void)(zone->checkns)(zone, name, owner,
2443 						      &a, &aaaa);
2444 			/* XXX950 make fatal for 9.5.0. */
2445 			/* answer = ISC_FALSE; */
2446 		}
2447 	} else if (result == DNS_R_CNAME) {
2448 		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2449 			     ownerbuf, namebuf);
2450 		/* XXX950 make fatal for 9.5.0. */
2451 		/* answer = ISC_FALSE; */
2452 	} else if (result == DNS_R_DNAME) {
2453 		dns_name_format(foundname, altbuf, sizeof altbuf);
2454 		dns_zone_log(zone, level,
2455 			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
2456 			     ownerbuf, namebuf, altbuf);
2457 		/* XXX950 make fatal for 9.5.0. */
2458 		/* answer = ISC_FALSE; */
2459 	}
2460 
2461 	if (dns_rdataset_isassociated(&a))
2462 		dns_rdataset_disassociate(&a);
2463 	if (dns_rdataset_isassociated(&aaaa))
2464 		dns_rdataset_disassociate(&aaaa);
2465 	return (answer);
2466 }
2467 
2468 static isc_boolean_t
zone_rrset_check_dup(dns_zone_t * zone,dns_name_t * owner,dns_rdataset_t * rdataset)2469 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2470 		     dns_rdataset_t *rdataset)
2471 {
2472 	dns_rdataset_t tmprdataset;
2473 	isc_result_t result;
2474 	isc_boolean_t answer = ISC_TRUE;
2475 	isc_boolean_t format = ISC_TRUE;
2476 	int level = ISC_LOG_WARNING;
2477 	char ownerbuf[DNS_NAME_FORMATSIZE];
2478 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2479 	unsigned int count1 = 0;
2480 
2481 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2482 		level = ISC_LOG_ERROR;
2483 
2484 	dns_rdataset_init(&tmprdataset);
2485 	for (result = dns_rdataset_first(rdataset);
2486 	     result == ISC_R_SUCCESS;
2487 	     result = dns_rdataset_next(rdataset)) {
2488 		dns_rdata_t rdata1 = DNS_RDATA_INIT;
2489 		unsigned int count2 = 0;
2490 
2491 		count1++;
2492 		dns_rdataset_current(rdataset, &rdata1);
2493 		dns_rdataset_clone(rdataset, &tmprdataset);
2494 		for (result = dns_rdataset_first(&tmprdataset);
2495 		     result == ISC_R_SUCCESS;
2496 		     result = dns_rdataset_next(&tmprdataset)) {
2497 			dns_rdata_t rdata2 = DNS_RDATA_INIT;
2498 			count2++;
2499 			if (count1 >= count2)
2500 				continue;
2501 			dns_rdataset_current(&tmprdataset, &rdata2);
2502 			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2503 				if (format) {
2504 					dns_name_format(owner, ownerbuf,
2505 							sizeof ownerbuf);
2506 					dns_rdatatype_format(rdata1.type,
2507 							     typebuf,
2508 							     sizeof(typebuf));
2509 					format = ISC_FALSE;
2510 				}
2511 				dns_zone_log(zone, level, "%s/%s has "
2512 					     "semantically identical records",
2513 					     ownerbuf, typebuf);
2514 				if (level == ISC_LOG_ERROR)
2515 					answer = ISC_FALSE;
2516 				break;
2517 			}
2518 		}
2519 		dns_rdataset_disassociate(&tmprdataset);
2520 		if (!format)
2521 			break;
2522 	}
2523 	return (answer);
2524 }
2525 
2526 static isc_boolean_t
zone_check_dup(dns_zone_t * zone,dns_db_t * db)2527 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2528 	dns_dbiterator_t *dbiterator = NULL;
2529 	dns_dbnode_t *node = NULL;
2530 	dns_fixedname_t fixed;
2531 	dns_name_t *name;
2532 	dns_rdataset_t rdataset;
2533 	dns_rdatasetiter_t *rdsit = NULL;
2534 	isc_boolean_t ok = ISC_TRUE;
2535 	isc_result_t result;
2536 
2537 	dns_fixedname_init(&fixed);
2538 	name = dns_fixedname_name(&fixed);
2539 	dns_rdataset_init(&rdataset);
2540 
2541 	result = dns_db_createiterator(db, 0, &dbiterator);
2542 	if (result != ISC_R_SUCCESS)
2543 		return (ISC_TRUE);
2544 
2545 	for (result = dns_dbiterator_first(dbiterator);
2546 	     result == ISC_R_SUCCESS;
2547 	     result = dns_dbiterator_next(dbiterator)) {
2548 		result = dns_dbiterator_current(dbiterator, &node, name);
2549 		if (result != ISC_R_SUCCESS)
2550 			continue;
2551 
2552 		result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2553 		if (result != ISC_R_SUCCESS)
2554 			continue;
2555 
2556 		for (result = dns_rdatasetiter_first(rdsit);
2557 		     result == ISC_R_SUCCESS;
2558 		     result = dns_rdatasetiter_next(rdsit)) {
2559 			dns_rdatasetiter_current(rdsit, &rdataset);
2560 			if (!zone_rrset_check_dup(zone, name, &rdataset))
2561 				ok = ISC_FALSE;
2562 			dns_rdataset_disassociate(&rdataset);
2563 		}
2564 		dns_rdatasetiter_destroy(&rdsit);
2565 		dns_db_detachnode(db, &node);
2566 	}
2567 
2568 	if (node != NULL)
2569 		dns_db_detachnode(db, &node);
2570 	dns_dbiterator_destroy(&dbiterator);
2571 
2572 	return (ok);
2573 }
2574 
2575 static isc_boolean_t
isspf(const dns_rdata_t * rdata)2576 isspf(const dns_rdata_t *rdata) {
2577 	char buf[1024];
2578 	const unsigned char *data = rdata->data;
2579 	unsigned int rdl = rdata->length, i = 0, tl, len;
2580 
2581 	while (rdl > 0U) {
2582 		len = tl = *data;
2583 		++data;
2584 		--rdl;
2585 		INSIST(tl <= rdl);
2586 		if (len > sizeof(buf) - i - 1)
2587 			len = sizeof(buf) - i - 1;
2588 		memmove(buf + i, data, len);
2589 		i += len;
2590 		data += tl;
2591 		rdl -= tl;
2592 	}
2593 
2594 	if (i < 6U)
2595 		return(ISC_FALSE);
2596 
2597 	buf[i] = 0;
2598 	if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
2599 		return (ISC_TRUE);
2600 	return (ISC_FALSE);
2601 }
2602 
2603 static isc_boolean_t
integrity_checks(dns_zone_t * zone,dns_db_t * db)2604 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2605 	dns_dbiterator_t *dbiterator = NULL;
2606 	dns_dbnode_t *node = NULL;
2607 	dns_rdataset_t rdataset;
2608 	dns_fixedname_t fixed;
2609 	dns_fixedname_t fixedbottom;
2610 	dns_rdata_mx_t mx;
2611 	dns_rdata_ns_t ns;
2612 	dns_rdata_in_srv_t srv;
2613 	dns_rdata_t rdata;
2614 	dns_name_t *name;
2615 	dns_name_t *bottom;
2616 	isc_result_t result;
2617 	isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
2618 
2619 	dns_fixedname_init(&fixed);
2620 	name = dns_fixedname_name(&fixed);
2621 	dns_fixedname_init(&fixedbottom);
2622 	bottom = dns_fixedname_name(&fixedbottom);
2623 	dns_rdataset_init(&rdataset);
2624 	dns_rdata_init(&rdata);
2625 
2626 	result = dns_db_createiterator(db, 0, &dbiterator);
2627 	if (result != ISC_R_SUCCESS)
2628 		return (ISC_TRUE);
2629 
2630 	result = dns_dbiterator_first(dbiterator);
2631 	while (result == ISC_R_SUCCESS) {
2632 		result = dns_dbiterator_current(dbiterator, &node, name);
2633 		if (result != ISC_R_SUCCESS)
2634 			goto cleanup;
2635 
2636 		/*
2637 		 * Is this name visible in the zone?
2638 		 */
2639 		if (!dns_name_issubdomain(name, &zone->origin) ||
2640 		    (dns_name_countlabels(bottom) > 0 &&
2641 		     dns_name_issubdomain(name, bottom)))
2642 			goto next;
2643 
2644 		/*
2645 		 * Don't check the NS records at the origin.
2646 		 */
2647 		if (dns_name_equal(name, &zone->origin))
2648 			goto checkmx;
2649 
2650 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2651 					     0, 0, &rdataset, NULL);
2652 		if (result != ISC_R_SUCCESS)
2653 			goto checkmx;
2654 		/*
2655 		 * Remember bottom of zone.
2656 		 */
2657 		dns_name_copy(name, bottom, NULL);
2658 
2659 		result = dns_rdataset_first(&rdataset);
2660 		while (result == ISC_R_SUCCESS) {
2661 			dns_rdataset_current(&rdataset, &rdata);
2662 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
2663 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2664 			if (!zone_check_glue(zone, db, &ns.name, name))
2665 				ok = ISC_FALSE;
2666 			dns_rdata_reset(&rdata);
2667 			result = dns_rdataset_next(&rdataset);
2668 		}
2669 		dns_rdataset_disassociate(&rdataset);
2670 		goto next;
2671 
2672  checkmx:
2673 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2674 					     0, 0, &rdataset, NULL);
2675 		if (result != ISC_R_SUCCESS)
2676 			goto checksrv;
2677 		result = dns_rdataset_first(&rdataset);
2678 		while (result == ISC_R_SUCCESS) {
2679 			dns_rdataset_current(&rdataset, &rdata);
2680 			result = dns_rdata_tostruct(&rdata, &mx, NULL);
2681 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2682 			if (!zone_check_mx(zone, db, &mx.mx, name))
2683 				ok = ISC_FALSE;
2684 			dns_rdata_reset(&rdata);
2685 			result = dns_rdataset_next(&rdataset);
2686 		}
2687 		dns_rdataset_disassociate(&rdataset);
2688 
2689  checksrv:
2690 		if (zone->rdclass != dns_rdataclass_in)
2691 			goto next;
2692 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2693 					     0, 0, &rdataset, NULL);
2694 		if (result != ISC_R_SUCCESS)
2695 			goto checkspf;
2696 		result = dns_rdataset_first(&rdataset);
2697 		while (result == ISC_R_SUCCESS) {
2698 			dns_rdataset_current(&rdataset, &rdata);
2699 			result = dns_rdata_tostruct(&rdata, &srv, NULL);
2700 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
2701 			if (!zone_check_srv(zone, db, &srv.target, name))
2702 				ok = ISC_FALSE;
2703 			dns_rdata_reset(&rdata);
2704 			result = dns_rdataset_next(&rdataset);
2705 		}
2706 		dns_rdataset_disassociate(&rdataset);
2707 
2708  checkspf:
2709 		/*
2710 		 * Check if there is a type SPF record without an
2711 		 * SPF-formatted type TXT record also being present.
2712 		 */
2713 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
2714 			goto next;
2715 		if (zone->rdclass != dns_rdataclass_in)
2716 			goto next;
2717 		have_spf = have_txt = ISC_FALSE;
2718 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
2719 					     0, 0, &rdataset, NULL);
2720 		if (result == ISC_R_SUCCESS) {
2721 			dns_rdataset_disassociate(&rdataset);
2722 			have_spf = ISC_TRUE;
2723 		}
2724 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
2725 					     0, 0, &rdataset, NULL);
2726 		if (result != ISC_R_SUCCESS)
2727 			goto notxt;
2728 		result = dns_rdataset_first(&rdataset);
2729 		while (result == ISC_R_SUCCESS) {
2730 			dns_rdataset_current(&rdataset, &rdata);
2731 			have_txt = isspf(&rdata);
2732 			dns_rdata_reset(&rdata);
2733 			if (have_txt)
2734 				break;
2735 			result = dns_rdataset_next(&rdataset);
2736 		}
2737 		dns_rdataset_disassociate(&rdataset);
2738 
2739  notxt:
2740 		if (have_spf && !have_txt) {
2741 			char namebuf[DNS_NAME_FORMATSIZE];
2742 
2743 			dns_name_format(name, namebuf, sizeof(namebuf));
2744 			dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
2745 				     "SPF record but no SPF TXT record found, "
2746 				     "add matching type TXT record", namebuf);
2747 		}
2748 
2749  next:
2750 		dns_db_detachnode(db, &node);
2751 		result = dns_dbiterator_next(dbiterator);
2752 	}
2753 
2754  cleanup:
2755 	if (node != NULL)
2756 		dns_db_detachnode(db, &node);
2757 	dns_dbiterator_destroy(&dbiterator);
2758 
2759 	return (ok);
2760 }
2761 
2762 /*
2763  * OpenSSL verification of RSA keys with exponent 3 is known to be
2764  * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
2765  * if they are in use.
2766  */
2767 static void
zone_check_dnskeys(dns_zone_t * zone,dns_db_t * db)2768 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2769 	dns_dbnode_t *node = NULL;
2770 	dns_dbversion_t *version = NULL;
2771 	dns_rdata_dnskey_t dnskey;
2772 	dns_rdata_t rdata = DNS_RDATA_INIT;
2773 	dns_rdataset_t rdataset;
2774 	isc_result_t result;
2775 	isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2776 	const char *algorithm;
2777 
2778 	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2779 	if (result != ISC_R_SUCCESS)
2780 		goto cleanup;
2781 
2782 	dns_db_currentversion(db, &version);
2783 	dns_rdataset_init(&rdataset);
2784 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2785 				     dns_rdatatype_none, 0, &rdataset, NULL);
2786 	if (result != ISC_R_SUCCESS)
2787 		goto cleanup;
2788 
2789 	for (result = dns_rdataset_first(&rdataset);
2790 	     result == ISC_R_SUCCESS;
2791 	     result = dns_rdataset_next(&rdataset))
2792 	{
2793 		dns_rdataset_current(&rdataset, &rdata);
2794 		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2795 		INSIST(result == ISC_R_SUCCESS);
2796 
2797 		if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2798 		     dnskey.algorithm == DST_ALG_RSAMD5) &&
2799 		     dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2800 		     dnskey.data[1] == 3)
2801 		{
2802 			if (dnskey.algorithm == DST_ALG_RSASHA1) {
2803 				logit = !foundrsa;
2804 				foundrsa = ISC_TRUE;
2805 				algorithm = "RSASHA1";
2806 			} else {
2807 				logit = !foundmd5;
2808 				foundmd5 = ISC_TRUE;
2809 				algorithm = "RSAMD5";
2810 			}
2811 			if (logit)
2812 				dns_zone_log(zone, ISC_LOG_WARNING,
2813 					     "weak %s (%u) key found "
2814 					     "(exponent=3)", algorithm,
2815 					     dnskey.algorithm);
2816 			if (foundrsa && foundmd5)
2817 				break;
2818 		}
2819 		dns_rdata_reset(&rdata);
2820 	}
2821 	dns_rdataset_disassociate(&rdataset);
2822 
2823  cleanup:
2824 	if (node != NULL)
2825 		dns_db_detachnode(db, &node);
2826 	if (version != NULL)
2827 		dns_db_closeversion(db, &version, ISC_FALSE);
2828 }
2829 
2830 static void
resume_signingwithkey(dns_zone_t * zone)2831 resume_signingwithkey(dns_zone_t *zone) {
2832 	dns_dbnode_t *node = NULL;
2833 	dns_dbversion_t *version = NULL;
2834 	dns_rdata_t rdata = DNS_RDATA_INIT;
2835 	dns_rdataset_t rdataset;
2836 	isc_result_t result;
2837 	dns_db_t *db = NULL;
2838 
2839 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2840 	if (zone->db != NULL)
2841 		dns_db_attach(zone->db, &db);
2842 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2843 	if (db == NULL)
2844 		goto cleanup;
2845 
2846 	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2847 	if (result != ISC_R_SUCCESS)
2848 		goto cleanup;
2849 
2850 	dns_db_currentversion(db, &version);
2851 	dns_rdataset_init(&rdataset);
2852 	result = dns_db_findrdataset(db, node, version,
2853 				     zone->privatetype,
2854 				     dns_rdatatype_none, 0,
2855 				     &rdataset, NULL);
2856 	if (result != ISC_R_SUCCESS) {
2857 		INSIST(!dns_rdataset_isassociated(&rdataset));
2858 		goto cleanup;
2859 	}
2860 
2861 	for (result = dns_rdataset_first(&rdataset);
2862 	     result == ISC_R_SUCCESS;
2863 	     result = dns_rdataset_next(&rdataset))
2864 	{
2865 		dns_rdataset_current(&rdataset, &rdata);
2866 		if (rdata.length != 5 ||
2867 		    rdata.data[0] == 0 || rdata.data[4] != 0) {
2868 			dns_rdata_reset(&rdata);
2869 			continue;
2870 		}
2871 
2872 		result = zone_signwithkey(zone, rdata.data[0],
2873 					  (rdata.data[1] << 8) | rdata.data[2],
2874 					  ISC_TF(rdata.data[3]));
2875 		if (result != ISC_R_SUCCESS) {
2876 			dns_zone_log(zone, ISC_LOG_ERROR,
2877 				     "zone_signwithkey failed: %s",
2878 				     dns_result_totext(result));
2879 		}
2880 		dns_rdata_reset(&rdata);
2881 	}
2882 	dns_rdataset_disassociate(&rdataset);
2883 
2884  cleanup:
2885 	if (db != NULL) {
2886 		if (node != NULL)
2887 			dns_db_detachnode(db, &node);
2888 		if (version != NULL)
2889 			dns_db_closeversion(db, &version, ISC_FALSE);
2890 		dns_db_detach(&db);
2891 	}
2892 }
2893 
2894 static isc_result_t
zone_addnsec3chain(dns_zone_t * zone,dns_rdata_nsec3param_t * nsec3param)2895 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2896 	dns_nsec3chain_t *nsec3chain, *current;
2897 	dns_dbversion_t *version = NULL;
2898 	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
2899 	isc_result_t result;
2900 	isc_time_t now;
2901 	unsigned int options = 0;
2902 	char saltbuf[255*2+1];
2903 	char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
2904 	dns_db_t *db = NULL;
2905 	int i;
2906 
2907 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2908 	if (zone->db != NULL)
2909 		dns_db_attach(zone->db, &db);
2910 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2911 
2912 	if (db == NULL) {
2913 		result = ISC_R_SUCCESS;
2914 		goto cleanup;
2915 	}
2916 
2917 	dns_db_currentversion(db, &version);
2918 	result = dns_nsec_nseconly(db, version, &nseconly);
2919 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
2920 	dns_db_closeversion(db, &version, ISC_FALSE);
2921 	if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
2922 		result = ISC_R_SUCCESS;
2923 		goto cleanup;
2924 	}
2925 
2926 	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2927 	if (nsec3chain == NULL) {
2928 		result = ISC_R_NOMEMORY;
2929 		goto cleanup;
2930 	}
2931 
2932 	nsec3chain->magic = 0;
2933 	nsec3chain->done = ISC_FALSE;
2934 	nsec3chain->db = NULL;
2935 	nsec3chain->dbiterator = NULL;
2936 	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2937 	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2938 	nsec3chain->nsec3param.hash = nsec3param->hash;
2939 	nsec3chain->nsec3param.iterations = nsec3param->iterations;
2940 	nsec3chain->nsec3param.flags = nsec3param->flags;
2941 	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2942 	memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2943 	nsec3chain->nsec3param.salt = nsec3chain->salt;
2944 	nsec3chain->seen_nsec = ISC_FALSE;
2945 	nsec3chain->delete_nsec = ISC_FALSE;
2946 	nsec3chain->save_delete_nsec = ISC_FALSE;
2947 
2948 	if (nsec3param->flags == 0)
2949 		strlcpy(flags, "NONE", sizeof(flags));
2950 	else {
2951 		flags[0] = '\0';
2952 		if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2953 			strlcat(flags, "REMOVE", sizeof(flags));
2954 		if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) {
2955 			if (flags[0] == '\0')
2956 				strlcpy(flags, "INITIAL", sizeof(flags));
2957 			else
2958 				strlcat(flags, "|INITIAL", sizeof(flags));
2959 		}
2960 		if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2961 			if (flags[0] == '\0')
2962 				strlcpy(flags, "CREATE", sizeof(flags));
2963 			else
2964 				strlcat(flags, "|CREATE", sizeof(flags));
2965 		}
2966 		if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2967 			if (flags[0] == '\0')
2968 				strlcpy(flags, "NONSEC", sizeof(flags));
2969 			else
2970 				strlcat(flags, "|NONSEC", sizeof(flags));
2971 		}
2972 		if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2973 			if (flags[0] == '\0')
2974 				strlcpy(flags, "OPTOUT", sizeof(flags));
2975 			else
2976 				strlcat(flags, "|OPTOUT", sizeof(flags));
2977 		}
2978 	}
2979 	if (nsec3param->salt_length == 0)
2980 		strlcpy(saltbuf, "-", sizeof(saltbuf));
2981 	else
2982 		for (i = 0; i < nsec3param->salt_length; i++)
2983 			sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2984 	dns_zone_log(zone, ISC_LOG_INFO,
2985 		     "zone_addnsec3chain(%u,%s,%u,%s)",
2986 		      nsec3param->hash, flags, nsec3param->iterations,
2987 		      saltbuf);
2988 
2989 	for (current = ISC_LIST_HEAD(zone->nsec3chain);
2990 	     current != NULL;
2991 	     current = ISC_LIST_NEXT(current, link)) {
2992 		if (current->db == db &&
2993 		    current->nsec3param.hash == nsec3param->hash &&
2994 		    current->nsec3param.iterations == nsec3param->iterations &&
2995 		    current->nsec3param.salt_length == nsec3param->salt_length
2996 		    && !memcmp(current->nsec3param.salt, nsec3param->salt,
2997 			       nsec3param->salt_length))
2998 			current->done = ISC_TRUE;
2999 	}
3000 
3001 	dns_db_attach(db, &nsec3chain->db);
3002 	if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
3003 		options = DNS_DB_NONSEC3;
3004 	result = dns_db_createiterator(nsec3chain->db, options,
3005 				       &nsec3chain->dbiterator);
3006 	if (result == ISC_R_SUCCESS)
3007 		dns_dbiterator_first(nsec3chain->dbiterator);
3008 	if (result == ISC_R_SUCCESS) {
3009 		dns_dbiterator_pause(nsec3chain->dbiterator);
3010 		ISC_LIST_INITANDAPPEND(zone->nsec3chain,
3011 				       nsec3chain, link);
3012 		nsec3chain = NULL;
3013 		if (isc_time_isepoch(&zone->nsec3chaintime)) {
3014 			TIME_NOW(&now);
3015 			zone->nsec3chaintime = now;
3016 			if (zone->task != NULL)
3017 				zone_settimer(zone, &now);
3018 		}
3019 	}
3020 
3021 	if (nsec3chain != NULL) {
3022 		if (nsec3chain->db != NULL)
3023 			dns_db_detach(&nsec3chain->db);
3024 		if (nsec3chain->dbiterator != NULL)
3025 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
3026 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3027 	}
3028 
3029  cleanup:
3030 	if (db != NULL)
3031 		dns_db_detach(&db);
3032 	return (result);
3033 }
3034 
3035 static void
resume_addnsec3chain(dns_zone_t * zone)3036 resume_addnsec3chain(dns_zone_t *zone) {
3037 	dns_dbnode_t *node = NULL;
3038 	dns_dbversion_t *version = NULL;
3039 	dns_rdataset_t rdataset;
3040 	isc_result_t result;
3041 	dns_rdata_nsec3param_t nsec3param;
3042 	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
3043 	dns_db_t *db = NULL;
3044 
3045 	if (zone->privatetype == 0)
3046 		return;
3047 
3048 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3049 	if (zone->db != NULL)
3050 		dns_db_attach(zone->db, &db);
3051 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3052 	if (db == NULL)
3053 		goto cleanup;
3054 
3055 	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3056 	if (result != ISC_R_SUCCESS)
3057 		goto cleanup;
3058 
3059 	dns_db_currentversion(db, &version);
3060 
3061 	result = dns_nsec_nseconly(db, version, &nseconly);
3062 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3063 
3064 	dns_rdataset_init(&rdataset);
3065 	result = dns_db_findrdataset(db, node, version,
3066 				     zone->privatetype, dns_rdatatype_none,
3067 				     0, &rdataset, NULL);
3068 	if (result != ISC_R_SUCCESS) {
3069 		INSIST(!dns_rdataset_isassociated(&rdataset));
3070 		goto cleanup;
3071 	}
3072 
3073 	for (result = dns_rdataset_first(&rdataset);
3074 	     result == ISC_R_SUCCESS;
3075 	     result = dns_rdataset_next(&rdataset))
3076 	{
3077 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3078 		dns_rdata_t rdata = DNS_RDATA_INIT;
3079 		dns_rdata_t private = DNS_RDATA_INIT;
3080 
3081 		dns_rdataset_current(&rdataset, &private);
3082 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3083 						sizeof(buf)))
3084 			continue;
3085 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3086 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3087 		if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3088 		    ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3089 		{
3090 			result = zone_addnsec3chain(zone, &nsec3param);
3091 			if (result != ISC_R_SUCCESS) {
3092 				dns_zone_log(zone, ISC_LOG_ERROR,
3093 					     "zone_addnsec3chain failed: %s",
3094 					     dns_result_totext(result));
3095 			}
3096 		}
3097 	}
3098 	dns_rdataset_disassociate(&rdataset);
3099  cleanup:
3100 	if (db != NULL) {
3101 		if (node != NULL)
3102 			dns_db_detachnode(db, &node);
3103 		if (version != NULL)
3104 			dns_db_closeversion(db, &version, ISC_FALSE);
3105 		dns_db_detach(&db);
3106 	}
3107 }
3108 
3109 static void
set_resigntime(dns_zone_t * zone)3110 set_resigntime(dns_zone_t *zone) {
3111 	dns_rdataset_t rdataset;
3112 	dns_fixedname_t fixed;
3113 	unsigned int resign;
3114 	isc_result_t result;
3115 	isc_uint32_t nanosecs;
3116 	dns_db_t *db = NULL;
3117 
3118 	dns_rdataset_init(&rdataset);
3119 	dns_fixedname_init(&fixed);
3120 
3121 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3122 	if (zone->db != NULL)
3123 		dns_db_attach(zone->db, &db);
3124 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3125 	if (db == NULL) {
3126 		isc_time_settoepoch(&zone->resigntime);
3127 		return;
3128 	}
3129 
3130 	result = dns_db_getsigningtime(db, &rdataset,
3131 				       dns_fixedname_name(&fixed));
3132 	if (result != ISC_R_SUCCESS) {
3133 		isc_time_settoepoch(&zone->resigntime);
3134 		goto cleanup;
3135 	}
3136 
3137 	resign = rdataset.resign - zone->sigresigninginterval;
3138 	dns_rdataset_disassociate(&rdataset);
3139 	isc_random_get(&nanosecs);
3140 	nanosecs %= 1000000000;
3141 	isc_time_set(&zone->resigntime, resign, nanosecs);
3142  cleanup:
3143 	dns_db_detach(&db);
3144 	return;
3145 }
3146 
3147 static isc_result_t
check_nsec3param(dns_zone_t * zone,dns_db_t * db)3148 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3149 	dns_dbnode_t *node = NULL;
3150 	dns_rdataset_t rdataset;
3151 	dns_dbversion_t *version = NULL;
3152 	dns_rdata_nsec3param_t nsec3param;
3153 	isc_boolean_t ok = ISC_FALSE;
3154 	isc_result_t result;
3155 	dns_rdata_t rdata = DNS_RDATA_INIT;
3156 	isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
3157 				dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE;
3158 
3159 	dns_rdataset_init(&rdataset);
3160 	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3161 	if (result != ISC_R_SUCCESS) {
3162 		dns_zone_log(zone, ISC_LOG_ERROR,
3163 			     "nsec3param lookup failure: %s",
3164 			     dns_result_totext(result));
3165 		return (result);
3166 	}
3167 	dns_db_currentversion(db, &version);
3168 
3169 	result = dns_db_findrdataset(db, node, version,
3170 				     dns_rdatatype_nsec3param,
3171 				     dns_rdatatype_none, 0, &rdataset, NULL);
3172 	if (result == ISC_R_NOTFOUND) {
3173 		INSIST(!dns_rdataset_isassociated(&rdataset));
3174 		result = ISC_R_SUCCESS;
3175 		goto cleanup;
3176 	}
3177 	if (result != ISC_R_SUCCESS) {
3178 		INSIST(!dns_rdataset_isassociated(&rdataset));
3179 		dns_zone_log(zone, ISC_LOG_ERROR,
3180 			     "nsec3param lookup failure: %s",
3181 			     dns_result_totext(result));
3182 		goto cleanup;
3183 	}
3184 
3185 	/*
3186 	 * For dynamic zones we must support every algorithm so we can
3187 	 * regenerate all the NSEC3 chains.
3188 	 * For non-dynamic zones we only need to find a supported algorithm.
3189 	 */
3190 	for (result = dns_rdataset_first(&rdataset);
3191 	     result == ISC_R_SUCCESS;
3192 	     result = dns_rdataset_next(&rdataset))
3193 	{
3194 		dns_rdataset_current(&rdataset, &rdata);
3195 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3196 		dns_rdata_reset(&rdata);
3197 		INSIST(result == ISC_R_SUCCESS);
3198 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3199 		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3200 		{
3201 			dns_zone_log(zone, ISC_LOG_WARNING,
3202 			     "nsec3 test \"unknown\" hash algorithm found: %u",
3203 				     nsec3param.hash);
3204 			ok = ISC_TRUE;
3205 		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3206 			if (dynamic) {
3207 				dns_zone_log(zone, ISC_LOG_ERROR,
3208 					     "unsupported nsec3 hash algorithm"
3209 					     " in dynamic zone: %u",
3210 					     nsec3param.hash);
3211 				result = DNS_R_BADZONE;
3212 				/* Stop second error message. */
3213 				ok = ISC_TRUE;
3214 				break;
3215 			} else
3216 				dns_zone_log(zone, ISC_LOG_WARNING,
3217 				     "unsupported nsec3 hash algorithm: %u",
3218 					     nsec3param.hash);
3219 		} else
3220 			ok = ISC_TRUE;
3221 	}
3222 	if (result == ISC_R_NOMORE)
3223 		result = ISC_R_SUCCESS;
3224 
3225 	if (!ok) {
3226 		result = DNS_R_BADZONE;
3227 		dns_zone_log(zone, ISC_LOG_ERROR,
3228 			     "no supported nsec3 hash algorithm");
3229 	}
3230 
3231  cleanup:
3232 	if (dns_rdataset_isassociated(&rdataset))
3233 		dns_rdataset_disassociate(&rdataset);
3234 	dns_db_closeversion(db, &version, ISC_FALSE);
3235 	dns_db_detachnode(db, &node);
3236 	return (result);
3237 }
3238 
3239 /*
3240  * Set the timer for refreshing the key zone to the soonest future time
3241  * of the set (current timer, keydata->refresh, keydata->addhd,
3242  * keydata->removehd).
3243  */
3244 static void
set_refreshkeytimer(dns_zone_t * zone,dns_rdata_keydata_t * key,isc_stdtime_t now,isc_boolean_t force)3245 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3246 		    isc_stdtime_t now, isc_boolean_t force)
3247 {
3248 	const char me[] = "set_refreshkeytimer";
3249 	isc_stdtime_t then;
3250 	isc_time_t timenow, timethen;
3251 	char timebuf[80];
3252 
3253 	ENTER;
3254 	then = key->refresh;
3255 	if (force)
3256 		then = now;
3257 	if (key->addhd > now && key->addhd < then)
3258 		then = key->addhd;
3259 	if (key->removehd > now && key->removehd < then)
3260 		then = key->removehd;
3261 
3262 	TIME_NOW(&timenow);
3263 	if (then > now)
3264 		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
3265 	else
3266 		timethen = timenow;
3267 	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
3268 	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
3269 		zone->refreshkeytime = timethen;
3270 
3271 	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
3272 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
3273 	zone_settimer(zone, &timenow);
3274 }
3275 
3276 /*
3277  * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3278  * If the key zone is changed, set '*changed' to ISC_TRUE.
3279  */
3280 static isc_result_t
create_keydata(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff,dns_keytable_t * keytable,dns_keynode_t ** keynodep,isc_boolean_t * changed)3281 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3282 	       dns_diff_t *diff, dns_keytable_t *keytable,
3283 	       dns_keynode_t **keynodep, isc_boolean_t *changed)
3284 {
3285 	const char me[] = "create_keydata";
3286 	isc_result_t result = ISC_R_SUCCESS;
3287 	isc_buffer_t keyb, dstb;
3288 	unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3289 	dns_rdata_keydata_t keydata;
3290 	dns_rdata_dnskey_t dnskey;
3291 	dns_rdata_t rdata = DNS_RDATA_INIT;
3292 	dns_keynode_t *keynode;
3293 	isc_stdtime_t now;
3294 	isc_region_t r;
3295 	dst_key_t *key;
3296 
3297 	REQUIRE(keynodep != NULL);
3298 	keynode = *keynodep;
3299 
3300 	ENTER;
3301 	isc_stdtime_get(&now);
3302 
3303 	/* Loop in case there's more than one key. */
3304 	while (result == ISC_R_SUCCESS) {
3305 		dns_keynode_t *nextnode = NULL;
3306 
3307 		key = dns_keynode_key(keynode);
3308 		if (key == NULL)
3309 			goto skip;
3310 
3311 		isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3312 		CHECK(dst_key_todns(key, &dstb));
3313 
3314 		/* Convert DST key to DNSKEY. */
3315 		dns_rdata_reset(&rdata);
3316 		isc_buffer_usedregion(&dstb, &r);
3317 		dns_rdata_fromregion(&rdata, dst_key_class(key),
3318 				     dns_rdatatype_dnskey, &r);
3319 
3320 		/* DSTKEY to KEYDATA. */
3321 		CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3322 		CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3323 					     NULL));
3324 
3325 		/* KEYDATA to rdata. */
3326 		dns_rdata_reset(&rdata);
3327 		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3328 		CHECK(dns_rdata_fromstruct(&rdata,
3329 					   zone->rdclass, dns_rdatatype_keydata,
3330 					   &keydata, &keyb));
3331 
3332 		/* Add rdata to zone. */
3333 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3334 				    dst_key_name(key), 0, &rdata));
3335 		*changed = ISC_TRUE;
3336 
3337 		/* Refresh new keys from the zone apex as soon as possible. */
3338 		set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
3339 
3340  skip:
3341 		result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3342 		if (result != ISC_R_NOTFOUND) {
3343 			dns_keytable_detachkeynode(keytable, &keynode);
3344 			keynode = nextnode;
3345 		}
3346 	}
3347 
3348 	if (keynode != NULL)
3349 		dns_keytable_detachkeynode(keytable, &keynode);
3350 	*keynodep = NULL;
3351 
3352 	return (ISC_R_SUCCESS);
3353 
3354   failure:
3355 	return (result);
3356 }
3357 
3358 /*
3359  * Remove from the key zone all the KEYDATA records found in rdataset.
3360  */
3361 static isc_result_t
delete_keydata(dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff,dns_name_t * name,dns_rdataset_t * rdataset)3362 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3363 	       dns_name_t *name, dns_rdataset_t *rdataset)
3364 {
3365 	dns_rdata_t rdata = DNS_RDATA_INIT;
3366 	isc_result_t result, uresult;
3367 
3368 	for (result = dns_rdataset_first(rdataset);
3369 	     result == ISC_R_SUCCESS;
3370 	     result = dns_rdataset_next(rdataset)) {
3371 		dns_rdata_reset(&rdata);
3372 		dns_rdataset_current(rdataset, &rdata);
3373 		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3374 					name, 0, &rdata);
3375 		if (uresult != ISC_R_SUCCESS)
3376 			return (uresult);
3377 	}
3378 	if (result == ISC_R_NOMORE)
3379 		result = ISC_R_SUCCESS;
3380 	return (result);
3381 }
3382 
3383 /*
3384  * Compute the DNSSEC key ID for a DNSKEY record.
3385  */
3386 static isc_result_t
compute_tag(dns_name_t * name,dns_rdata_dnskey_t * dnskey,isc_mem_t * mctx,dns_keytag_t * tag)3387 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3388 	    dns_keytag_t *tag)
3389 {
3390 	isc_result_t result;
3391 	dns_rdata_t rdata = DNS_RDATA_INIT;
3392 	unsigned char data[4096];
3393 	isc_buffer_t buffer;
3394 	dst_key_t *dstkey = NULL;
3395 
3396 	isc_buffer_init(&buffer, data, sizeof(data));
3397 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3398 			     dns_rdatatype_dnskey, dnskey, &buffer);
3399 
3400 	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3401 	if (result == ISC_R_SUCCESS)
3402 		*tag = dst_key_id(dstkey);
3403 	dst_key_free(&dstkey);
3404 
3405 	return (result);
3406 }
3407 
3408 /*
3409  * Add key to the security roots.
3410  */
3411 static void
trust_key(dns_zone_t * zone,dns_name_t * keyname,dns_rdata_dnskey_t * dnskey,isc_mem_t * mctx)3412 trust_key(dns_zone_t *zone, dns_name_t *keyname,
3413 	  dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
3414 {
3415 	isc_result_t result;
3416 	dns_rdata_t rdata = DNS_RDATA_INIT;
3417 	unsigned char data[4096];
3418 	isc_buffer_t buffer;
3419 	dns_keytable_t *sr = NULL;
3420 	dst_key_t *dstkey = NULL;
3421 
3422 	/* Convert dnskey to DST key. */
3423 	isc_buffer_init(&buffer, data, sizeof(data));
3424 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3425 			     dns_rdatatype_dnskey, dnskey, &buffer);
3426 
3427 	result = dns_view_getsecroots(zone->view, &sr);
3428 	if (result != ISC_R_SUCCESS)
3429 		goto failure;
3430 
3431 	CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
3432 	CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
3433 	dns_keytable_detach(&sr);
3434 
3435   failure:
3436 	if (dstkey != NULL)
3437 		dst_key_free(&dstkey);
3438 	if (sr != NULL)
3439 		dns_keytable_detach(&sr);
3440 	return;
3441 }
3442 
3443 /*
3444  * Add a null key to the security roots for so that all queries
3445  * to the zone will fail.
3446  */
3447 static void
fail_secure(dns_zone_t * zone,dns_name_t * keyname)3448 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
3449 	isc_result_t result;
3450 	dns_keytable_t *sr = NULL;
3451 
3452 	result = dns_view_getsecroots(zone->view, &sr);
3453 	if (result == ISC_R_SUCCESS) {
3454 		dns_keytable_marksecure(sr, keyname);
3455 		dns_keytable_detach(&sr);
3456 	}
3457 }
3458 
3459 /*
3460  * Scan a set of KEYDATA records from the key zone.  The ones that are
3461  * valid (i.e., the add holddown timer has expired) become trusted keys.
3462  */
3463 static void
load_secroots(dns_zone_t * zone,dns_name_t * name,dns_rdataset_t * rdataset)3464 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
3465 	isc_result_t result;
3466 	dns_rdata_t rdata = DNS_RDATA_INIT;
3467 	dns_rdata_keydata_t keydata;
3468 	dns_rdata_dnskey_t dnskey;
3469 	isc_mem_t *mctx = zone->mctx;
3470 	int trusted = 0, revoked = 0, pending = 0;
3471 	isc_stdtime_t now;
3472 	dns_keytable_t *sr = NULL;
3473 
3474 	isc_stdtime_get(&now);
3475 
3476 	result = dns_view_getsecroots(zone->view, &sr);
3477 	if (result == ISC_R_SUCCESS) {
3478 		dns_keytable_delete(sr, name);
3479 		dns_keytable_detach(&sr);
3480 	}
3481 
3482 	/* Now insert all the accepted trust anchors from this keydata set. */
3483 	for (result = dns_rdataset_first(rdataset);
3484 	     result == ISC_R_SUCCESS;
3485 	     result = dns_rdataset_next(rdataset)) {
3486 		dns_rdata_reset(&rdata);
3487 		dns_rdataset_current(rdataset, &rdata);
3488 
3489 		/* Convert rdata to keydata. */
3490 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
3491 		if (result == ISC_R_UNEXPECTEDEND)
3492 			continue;
3493 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3494 
3495 		/* Set the key refresh timer to force a fast refresh. */
3496 		set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
3497 
3498 		/* If the removal timer is nonzero, this key was revoked. */
3499 		if (keydata.removehd != 0) {
3500 			revoked++;
3501 			continue;
3502 		}
3503 
3504 		/*
3505 		 * If the add timer is still pending, this key is not
3506 		 * trusted yet.
3507 		 */
3508 		if (now < keydata.addhd) {
3509 			pending++;
3510 			continue;
3511 		}
3512 
3513 		/* Convert keydata to dnskey. */
3514 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
3515 
3516 		/* Add to keytables. */
3517 		trusted++;
3518 		trust_key(zone, name, &dnskey, mctx);
3519 	}
3520 
3521 	if (trusted == 0 && pending != 0) {
3522 		char namebuf[DNS_NAME_FORMATSIZE];
3523 		dns_name_format(name, namebuf, sizeof namebuf);
3524 		dns_zone_log(zone, ISC_LOG_ERROR,
3525 			     "No valid trust anchors for '%s'!", namebuf);
3526 		dns_zone_log(zone, ISC_LOG_ERROR,
3527 			     "%d key(s) revoked, %d still pending",
3528 			     revoked, pending);
3529 		dns_zone_log(zone, ISC_LOG_ERROR,
3530 			     "All queries to '%s' will fail", namebuf);
3531 		fail_secure(zone, name);
3532 	}
3533 }
3534 
3535 static isc_result_t
do_one_tuple(dns_difftuple_t ** tuple,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff)3536 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3537 	     dns_diff_t *diff)
3538 {
3539 	dns_diff_t temp_diff;
3540 	isc_result_t result;
3541 
3542 	/*
3543 	 * Create a singleton diff.
3544 	 */
3545 	dns_diff_init(diff->mctx, &temp_diff);
3546 	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3547 
3548 	/*
3549 	 * Apply it to the database.
3550 	 */
3551 	result = dns_diff_apply(&temp_diff, db, ver);
3552 	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3553 	if (result != ISC_R_SUCCESS) {
3554 		dns_difftuple_free(tuple);
3555 		return (result);
3556 	}
3557 
3558 	/*
3559 	 * Merge it into the current pending journal entry.
3560 	 */
3561 	dns_diff_appendminimal(diff, tuple);
3562 
3563 	/*
3564 	 * Do not clear temp_diff.
3565 	 */
3566 	return (ISC_R_SUCCESS);
3567 }
3568 
3569 static isc_result_t
update_one_rr(dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff,dns_diffop_t op,dns_name_t * name,dns_ttl_t ttl,dns_rdata_t * rdata)3570 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3571 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3572 	      dns_rdata_t *rdata)
3573 {
3574 	dns_difftuple_t *tuple = NULL;
3575 	isc_result_t result;
3576 	result = dns_difftuple_create(diff->mctx, op,
3577 				      name, ttl, rdata, &tuple);
3578 	if (result != ISC_R_SUCCESS)
3579 		return (result);
3580 	return (do_one_tuple(&tuple, db, ver, diff));
3581 }
3582 
3583 static isc_result_t
update_soa_serial(dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff,isc_mem_t * mctx,dns_updatemethod_t method)3584 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3585 		  isc_mem_t *mctx, dns_updatemethod_t method) {
3586 	dns_difftuple_t *deltuple = NULL;
3587 	dns_difftuple_t *addtuple = NULL;
3588 	isc_uint32_t serial;
3589 	isc_result_t result;
3590 
3591 	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3592 	CHECK(dns_difftuple_copy(deltuple, &addtuple));
3593 	addtuple->op = DNS_DIFFOP_ADD;
3594 
3595 	serial = dns_soa_getserial(&addtuple->rdata);
3596 	serial = dns_update_soaserial(serial, method);
3597 	dns_soa_setserial(serial, &addtuple->rdata);
3598 	CHECK(do_one_tuple(&deltuple, db, ver, diff));
3599 	CHECK(do_one_tuple(&addtuple, db, ver, diff));
3600 	result = ISC_R_SUCCESS;
3601 
3602 	failure:
3603 	if (addtuple != NULL)
3604 		dns_difftuple_free(&addtuple);
3605 	if (deltuple != NULL)
3606 		dns_difftuple_free(&deltuple);
3607 	return (result);
3608 }
3609 
3610 /*
3611  * Write all transactions in 'diff' to the zone journal file.
3612  */
3613 static isc_result_t
zone_journal(dns_zone_t * zone,dns_diff_t * diff,isc_uint32_t * sourceserial,const char * caller)3614 zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial,
3615 	     const char *caller)
3616 {
3617 	const char me[] = "zone_journal";
3618 	const char *journalfile;
3619 	isc_result_t result = ISC_R_SUCCESS;
3620 	dns_journal_t *journal = NULL;
3621 	unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
3622 
3623 	ENTER;
3624 	journalfile = dns_zone_getjournal(zone);
3625 	if (journalfile != NULL) {
3626 		result = dns_journal_open(zone->mctx, journalfile, mode,
3627 					  &journal);
3628 		if (result != ISC_R_SUCCESS) {
3629 			dns_zone_log(zone, ISC_LOG_ERROR,
3630 				     "%s:dns_journal_open -> %s",
3631 				     caller, dns_result_totext(result));
3632 			return (result);
3633 		}
3634 
3635 		if (sourceserial != NULL)
3636 			dns_journal_set_sourceserial(journal, *sourceserial);
3637 
3638 		result = dns_journal_write_transaction(journal, diff);
3639 		if (result != ISC_R_SUCCESS) {
3640 			dns_zone_log(zone, ISC_LOG_ERROR,
3641 				     "%s:dns_journal_write_transaction -> %s",
3642 				     caller, dns_result_totext(result));
3643 		}
3644 		dns_journal_destroy(&journal);
3645 	}
3646 
3647 	return (result);
3648 }
3649 
3650 /*
3651  * Create an SOA record for a newly-created zone
3652  */
3653 static isc_result_t
add_soa(dns_zone_t * zone,dns_db_t * db)3654 add_soa(dns_zone_t *zone, dns_db_t *db) {
3655 	isc_result_t result;
3656 	dns_rdata_t rdata = DNS_RDATA_INIT;
3657 	unsigned char buf[DNS_SOA_BUFFERSIZE];
3658 	dns_dbversion_t *ver = NULL;
3659 	dns_diff_t diff;
3660 
3661 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3662 
3663 	dns_diff_init(zone->mctx, &diff);
3664 	result = dns_db_newversion(db, &ver);
3665 	if (result != ISC_R_SUCCESS) {
3666 		dns_zone_log(zone, ISC_LOG_ERROR,
3667 			     "add_soa:dns_db_newversion -> %s",
3668 			     dns_result_totext(result));
3669 		goto failure;
3670 	}
3671 
3672 	/* Build SOA record */
3673 	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3674 				    0, 0, 0, 0, 0, buf, &rdata);
3675 	if (result != ISC_R_SUCCESS) {
3676 		dns_zone_log(zone, ISC_LOG_ERROR,
3677 			     "add_soa:dns_soa_buildrdata -> %s",
3678 			     dns_result_totext(result));
3679 		goto failure;
3680 	}
3681 
3682 	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3683 			       &zone->origin, 0, &rdata);
3684 
3685 failure:
3686 	dns_diff_clear(&diff);
3687 	if (ver != NULL)
3688 		dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3689 
3690 	INSIST(ver == NULL);
3691 
3692 	return (result);
3693 }
3694 
3695 /*
3696  * Synchronize the set of initializing keys found in managed-keys {}
3697  * statements with the set of trust anchors found in the managed-keys.bind
3698  * zone.  If a domain is no longer named in managed-keys, delete all keys
3699  * from that domain from the key zone.	If a domain is mentioned in in
3700  * managed-keys but there are no references to it in the key zone, load
3701  * the key zone with the initializing key(s) for that domain.
3702  */
3703 static isc_result_t
sync_keyzone(dns_zone_t * zone,dns_db_t * db)3704 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3705 	isc_result_t result = ISC_R_SUCCESS;
3706 	isc_boolean_t changed = ISC_FALSE;
3707 	isc_boolean_t commit = ISC_FALSE;
3708 	dns_rbtnodechain_t chain;
3709 	dns_fixedname_t fn;
3710 	dns_name_t foundname, *origin;
3711 	dns_keynode_t *keynode = NULL;
3712 	dns_view_t *view = zone->view;
3713 	dns_keytable_t *sr = NULL;
3714 	dns_dbversion_t *ver = NULL;
3715 	dns_diff_t diff;
3716 	dns_rriterator_t rrit;
3717 
3718 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3719 
3720 	dns_name_init(&foundname, NULL);
3721 	dns_fixedname_init(&fn);
3722 	origin = dns_fixedname_name(&fn);
3723 
3724 	dns_diff_init(zone->mctx, &diff);
3725 
3726 	CHECK(dns_view_getsecroots(view, &sr));
3727 
3728 	result = dns_db_newversion(db, &ver);
3729 	if (result != ISC_R_SUCCESS) {
3730 		dns_zone_log(zone, ISC_LOG_ERROR,
3731 			     "sync_keyzone:dns_db_newversion -> %s",
3732 			     dns_result_totext(result));
3733 		goto failure;
3734 	}
3735 
3736 	/*
3737 	 * Walk the zone DB.  If we find any keys whose names are no longer
3738 	 * in managed-keys (or *are* in trusted-keys, meaning they are
3739 	 * permanent and not RFC5011-maintained), delete them from the
3740 	 * zone.  Otherwise call load_secroots(), which loads keys into
3741 	 * secroots as appropriate.
3742 	 */
3743 	dns_rriterator_init(&rrit, db, ver, 0);
3744 	for (result = dns_rriterator_first(&rrit);
3745 	     result == ISC_R_SUCCESS;
3746 	     result = dns_rriterator_nextrrset(&rrit)) {
3747 		dns_rdataset_t *rdataset = NULL;
3748 		dns_name_t *rrname = NULL;
3749 		isc_uint32_t ttl;
3750 
3751 		dns_rriterator_current(&rrit, &rrname, &ttl,
3752 				       &rdataset, NULL);
3753 		if (!dns_rdataset_isassociated(rdataset)) {
3754 			dns_rriterator_destroy(&rrit);
3755 			goto failure;
3756 		}
3757 
3758 		if (rdataset->type != dns_rdatatype_keydata)
3759 			continue;
3760 
3761 		result = dns_keytable_find(sr, rrname, &keynode);
3762 		if ((result != ISC_R_SUCCESS &&
3763 		     result != DNS_R_PARTIALMATCH) ||
3764 		    dns_keynode_managed(keynode) == ISC_FALSE)
3765 		{
3766 			CHECK(delete_keydata(db, ver, &diff,
3767 					     rrname, rdataset));
3768 			changed = ISC_TRUE;
3769 		} else {
3770 			load_secroots(zone, rrname, rdataset);
3771 		}
3772 
3773 		if (keynode != NULL)
3774 			dns_keytable_detachkeynode(sr, &keynode);
3775 	}
3776 	dns_rriterator_destroy(&rrit);
3777 
3778 	/*
3779 	 * Now walk secroots to find any managed keys that aren't
3780 	 * in the zone.  If we find any, we add them to the zone.
3781 	 */
3782 	RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3783 	dns_rbtnodechain_init(&chain, zone->mctx);
3784 	result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3785 	if (result == ISC_R_NOTFOUND)
3786 		result = ISC_R_NOMORE;
3787 	while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3788 		dns_rbtnode_t *rbtnode = NULL;
3789 
3790 		dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3791 		if (rbtnode->data == NULL)
3792 			goto skip;
3793 
3794 		dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3795 		if (dns_keynode_managed(keynode)) {
3796 			dns_fixedname_t fname;
3797 			dns_name_t *keyname;
3798 			dst_key_t *key;
3799 
3800 			key = dns_keynode_key(keynode);
3801 			dns_fixedname_init(&fname);
3802 
3803 			if (key == NULL)   /* fail_secure() was called. */
3804 				goto skip;
3805 
3806 			keyname = dst_key_name(key);
3807 			result = dns_db_find(db, keyname, ver,
3808 					     dns_rdatatype_keydata,
3809 					     DNS_DBFIND_NOWILD, 0, NULL,
3810 					     dns_fixedname_name(&fname),
3811 					     NULL, NULL);
3812 			if (result != ISC_R_SUCCESS)
3813 				result = create_keydata(zone, db, ver, &diff,
3814 							sr, &keynode, &changed);
3815 			if (result != ISC_R_SUCCESS)
3816 				break;
3817 		}
3818   skip:
3819 		result = dns_rbtnodechain_next(&chain, &foundname, origin);
3820 		if (keynode != NULL)
3821 			dns_keytable_detachkeynode(sr, &keynode);
3822 	}
3823 	RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3824 
3825 	if (result == ISC_R_NOMORE)
3826 		result = ISC_R_SUCCESS;
3827 
3828 	if (changed) {
3829 		/* Write changes to journal file. */
3830 		CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
3831 					zone->updatemethod));
3832 		CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
3833 
3834 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3835 		zone_needdump(zone, 30);
3836 		commit = ISC_TRUE;
3837 	}
3838 
3839  failure:
3840 	if (result != ISC_R_SUCCESS &&
3841 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3842 		dns_zone_log(zone, ISC_LOG_ERROR,
3843 			     "unable to synchronize managed keys: %s",
3844 			     dns_result_totext(result));
3845 		isc_time_settoepoch(&zone->refreshkeytime);
3846 	}
3847 	if (keynode != NULL)
3848 		dns_keytable_detachkeynode(sr, &keynode);
3849 	if (sr != NULL)
3850 		dns_keytable_detach(&sr);
3851 	if (ver != NULL)
3852 		dns_db_closeversion(db, &ver, commit);
3853 	dns_diff_clear(&diff);
3854 
3855 	INSIST(ver == NULL);
3856 
3857 	return (result);
3858 }
3859 
3860 isc_result_t
dns_zone_synckeyzone(dns_zone_t * zone)3861 dns_zone_synckeyzone(dns_zone_t *zone) {
3862 	isc_result_t result;
3863 	dns_db_t *db = NULL;
3864 
3865 	if (zone->type != dns_zone_key)
3866 		return (DNS_R_BADZONE);
3867 
3868 	CHECK(dns_zone_getdb(zone, &db));
3869 
3870 	LOCK_ZONE(zone);
3871 	result = sync_keyzone(zone, db);
3872 	UNLOCK_ZONE(zone);
3873 
3874  failure:
3875 	if (db != NULL)
3876 		dns_db_detach(&db);
3877 	return (result);
3878 }
3879 
3880 static void
maybe_send_secure(dns_zone_t * zone)3881 maybe_send_secure(dns_zone_t *zone) {
3882 	isc_result_t result;
3883 
3884 	/*
3885 	 * We've finished loading, or else failed to load, an inline-signing
3886 	 * 'secure' zone.  We now need information about the status of the
3887 	 * 'raw' zone.  If we failed to load, then we need it to send a
3888 	 * copy of its database; if we succeeded, we need it to send its
3889 	 * serial number so that we can sync with it.  If it has not yet
3890 	 * loaded, we set a flag so that it will send the necessary
3891 	 * information when it has finished loading.
3892 	 */
3893 	if (zone->raw->db != NULL) {
3894 		if (zone->db != NULL) {
3895 			isc_uint32_t serial;
3896 			unsigned int soacount;
3897 
3898 			result = zone_get_from_db(zone->raw, zone->raw->db,
3899 						  NULL, &soacount, &serial, NULL,
3900 						  NULL, NULL, NULL, NULL);
3901 			if (result == ISC_R_SUCCESS && soacount > 0U)
3902 				zone_send_secureserial(zone->raw, serial);
3903 		} else
3904 			zone_send_securedb(zone->raw, zone->raw->db);
3905 
3906 	} else
3907 		DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
3908 }
3909 
3910 static isc_boolean_t
zone_unchanged(dns_db_t * db1,dns_db_t * db2,isc_mem_t * mctx)3911 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
3912 	isc_result_t result;
3913 	isc_boolean_t answer = ISC_FALSE;
3914 	dns_diff_t diff;
3915 
3916 	dns_diff_init(mctx, &diff);
3917 	result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
3918 	if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
3919 		answer = ISC_TRUE;
3920 	dns_diff_clear(&diff);
3921 	return (answer);
3922 }
3923 
3924 /*
3925  * The zone is presumed to be locked.
3926  * If this is a inline_raw zone the secure version is also locked.
3927  */
3928 static isc_result_t
zone_postload(dns_zone_t * zone,dns_db_t * db,isc_time_t loadtime,isc_result_t result)3929 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3930 	      isc_result_t result)
3931 {
3932 	unsigned int soacount = 0;
3933 	unsigned int nscount = 0;
3934 	unsigned int errors = 0;
3935 	isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3936 	isc_time_t now;
3937 	isc_boolean_t needdump = ISC_FALSE;
3938 	isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3939 	isc_boolean_t nomaster = ISC_FALSE;
3940 	unsigned int options;
3941 
3942 	INSIST(LOCKED_ZONE(zone));
3943 	if (inline_raw(zone))
3944 		INSIST(LOCKED_ZONE(zone->secure));
3945 
3946 	TIME_NOW(&now);
3947 
3948 	/*
3949 	 * Initiate zone transfer?  We may need a error code that
3950 	 * indicates that the "permanent" form does not exist.
3951 	 * XXX better error feedback to log.
3952 	 */
3953 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3954 		if (zone->type == dns_zone_slave ||
3955 		    zone->type == dns_zone_stub ||
3956 		    (zone->type == dns_zone_redirect &&
3957 		     zone->masters == NULL)) {
3958 			if (result == ISC_R_FILENOTFOUND)
3959 				dns_zone_log(zone, ISC_LOG_DEBUG(1),
3960 					     "no master file");
3961 			else if (result != DNS_R_NOMASTERFILE)
3962 				dns_zone_log(zone, ISC_LOG_ERROR,
3963 					     "loading from master file %s "
3964 					     "failed: %s",
3965 					     zone->masterfile,
3966 					     dns_result_totext(result));
3967 		} else if (zone->type == dns_zone_master &&
3968 			   inline_secure(zone) && result == ISC_R_FILENOTFOUND)
3969 		{
3970 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
3971 				     "no master file, requesting db");
3972 			maybe_send_secure(zone);
3973 		} else {
3974 			int level = ISC_LOG_ERROR;
3975 			if (zone->type == dns_zone_key &&
3976 			    result == ISC_R_FILENOTFOUND)
3977 				level = ISC_LOG_DEBUG(1);
3978 			dns_zone_log(zone, level,
3979 				     "loading from master file %s failed: %s",
3980 				     zone->masterfile,
3981 				     dns_result_totext(result));
3982 			nomaster = ISC_TRUE;
3983 		}
3984 
3985 		if (zone->type != dns_zone_key)
3986 			goto cleanup;
3987 	}
3988 
3989 	dns_zone_log(zone, ISC_LOG_DEBUG(2),
3990 		     "number of nodes in database: %u",
3991 		     dns_db_nodecount(db));
3992 
3993 	if (result == DNS_R_SEENINCLUDE)
3994 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3995 	else
3996 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3997 
3998 	/*
3999 	 * If there's no master file for a key zone, then the zone is new:
4000 	 * create an SOA record.  (We do this now, instead of later, so that
4001 	 * if there happens to be a journal file, we can roll forward from
4002 	 * a sane starting point.)
4003 	 */
4004 	if (nomaster && zone->type == dns_zone_key) {
4005 		result = add_soa(zone, db);
4006 		if (result != ISC_R_SUCCESS)
4007 			goto cleanup;
4008 	}
4009 
4010 	/*
4011 	 * Apply update log, if any, on initial load.
4012 	 */
4013 	if (zone->journal != NULL &&
4014 	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4015 	    ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4016 	{
4017 		if (zone->type == dns_zone_master &&
4018 		    (zone->update_acl != NULL || zone->ssutable != NULL))
4019 			options = DNS_JOURNALOPT_RESIGN;
4020 		else
4021 			options = 0;
4022 		result = dns_journal_rollforward2(zone->mctx, db, options,
4023 						  0, zone->journal);
4024 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
4025 		    result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
4026 		    result != ISC_R_RANGE) {
4027 			dns_zone_log(zone, ISC_LOG_ERROR,
4028 				     "journal rollforward failed: %s",
4029 				     dns_result_totext(result));
4030 			goto cleanup;
4031 
4032 
4033 		}
4034 		if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
4035 			dns_zone_log(zone, ISC_LOG_ERROR,
4036 				     "journal rollforward failed: "
4037 				     "journal out of sync with zone");
4038 			goto cleanup;
4039 		}
4040 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
4041 			     "journal rollforward completed "
4042 			     "successfully: %s",
4043 			     dns_result_totext(result));
4044 		if (result == ISC_R_SUCCESS)
4045 			needdump = ISC_TRUE;
4046 	}
4047 
4048 	/*
4049 	 * Obtain ns, soa and cname counts for top of zone.
4050 	 */
4051 	INSIST(db != NULL);
4052 	result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
4053 				  &refresh, &retry, &expire, &minimum,
4054 				  &errors);
4055 	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4056 		dns_zone_log(zone, ISC_LOG_ERROR,
4057 			     "could not find NS and/or SOA records");
4058 	}
4059 
4060 	/*
4061 	 * Check to make sure the journal is up to date, and remove the
4062 	 * journal file if it isn't, as we wouldn't be able to apply
4063 	 * updates otherwise.
4064 	 */
4065 	if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) &&
4066 	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
4067 		isc_uint32_t jserial;
4068 		dns_journal_t *journal = NULL;
4069 
4070 		result = dns_journal_open(zone->mctx, zone->journal,
4071 					  DNS_JOURNAL_READ, &journal);
4072 		if (result == ISC_R_SUCCESS) {
4073 			jserial = dns_journal_last_serial(journal);
4074 			dns_journal_destroy(&journal);
4075 		} else {
4076 			jserial = serial;
4077 			result = ISC_R_SUCCESS;
4078 		}
4079 
4080 		if (jserial != serial) {
4081 			dns_zone_log(zone, ISC_LOG_INFO,
4082 				     "journal file is out of date: "
4083 				     "removing journal file");
4084 			if (remove(zone->journal) < 0 && errno != ENOENT) {
4085 				char strbuf[ISC_STRERRORSIZE];
4086 				isc__strerror(errno, strbuf, sizeof(strbuf));
4087 				isc_log_write(dns_lctx,
4088 					      DNS_LOGCATEGORY_GENERAL,
4089 					      DNS_LOGMODULE_ZONE,
4090 					      ISC_LOG_WARNING,
4091 					      "unable to remove journal "
4092 					      "'%s': '%s'",
4093 					      zone->journal, strbuf);
4094 			}
4095 		}
4096 	}
4097 
4098 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
4099 
4100 	/*
4101 	 * Master / Slave / Stub zones require both NS and SOA records at
4102 	 * the top of the zone.
4103 	 */
4104 
4105 	switch (zone->type) {
4106 	case dns_zone_dlz:
4107 	case dns_zone_master:
4108 	case dns_zone_slave:
4109 	case dns_zone_stub:
4110 	case dns_zone_redirect:
4111 		if (soacount != 1) {
4112 			dns_zone_log(zone, ISC_LOG_ERROR,
4113 				     "has %d SOA records", soacount);
4114 			result = DNS_R_BADZONE;
4115 		}
4116 		if (nscount == 0) {
4117 			dns_zone_log(zone, ISC_LOG_ERROR,
4118 				     "has no NS records");
4119 			result = DNS_R_BADZONE;
4120 		}
4121 		if (result != ISC_R_SUCCESS)
4122 			goto cleanup;
4123 		if (zone->type == dns_zone_master && errors != 0) {
4124 			result = DNS_R_BADZONE;
4125 			goto cleanup;
4126 		}
4127 		if (zone->type != dns_zone_stub &&
4128 		    zone->type != dns_zone_redirect) {
4129 			result = check_nsec3param(zone, db);
4130 			if (result != ISC_R_SUCCESS)
4131 				goto cleanup;
4132 		}
4133 		if (zone->type == dns_zone_master &&
4134 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4135 		    !integrity_checks(zone, db)) {
4136 			result = DNS_R_BADZONE;
4137 			goto cleanup;
4138 		}
4139 		if (zone->type == dns_zone_master &&
4140 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4141 		    !zone_check_dup(zone, db)) {
4142 			result = DNS_R_BADZONE;
4143 			goto cleanup;
4144 		}
4145 
4146 		if (zone->db != NULL) {
4147 			unsigned int oldsoacount;
4148 
4149 			/*
4150 			 * This is checked in zone_replacedb() for slave zones
4151 			 * as they don't reload from disk.
4152 			 */
4153 			result = zone_get_from_db(zone, zone->db, NULL,
4154 						  &oldsoacount, &oldserial,
4155 						  NULL, NULL, NULL, NULL,
4156 						  NULL);
4157 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
4158 			RUNTIME_CHECK(soacount > 0U);
4159 			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4160 			    !isc_serial_gt(serial, oldserial)) {
4161 				isc_uint32_t serialmin, serialmax;
4162 
4163 				INSIST(zone->type == dns_zone_master);
4164 
4165 				if (serial == oldserial &&
4166 				    zone_unchanged(zone->db, db, zone->mctx)) {
4167 					dns_zone_log(zone, ISC_LOG_INFO,
4168 						     "ixfr-from-differences: "
4169 						     "unchanged");
4170 					return(ISC_R_SUCCESS);
4171 				}
4172 
4173 				serialmin = (oldserial + 1) & 0xffffffffU;
4174 				serialmax = (oldserial + 0x7fffffffU) &
4175 					     0xffffffffU;
4176 				dns_zone_log(zone, ISC_LOG_ERROR,
4177 					     "ixfr-from-differences: "
4178 					     "new serial (%u) out of range "
4179 					     "[%u - %u]", serial, serialmin,
4180 					     serialmax);
4181 				result = DNS_R_BADZONE;
4182 				goto cleanup;
4183 			} else if (!isc_serial_ge(serial, oldserial))
4184 				dns_zone_log(zone, ISC_LOG_ERROR,
4185 					     "zone serial (%u/%u) has gone "
4186 					     "backwards", serial, oldserial);
4187 			else if (serial == oldserial && !hasinclude &&
4188 				 strcmp(zone->db_argv[0], "_builtin") != 0)
4189 				dns_zone_log(zone, ISC_LOG_ERROR,
4190 					     "zone serial (%u) unchanged. "
4191 					     "zone may fail to transfer "
4192 					     "to slaves.", serial);
4193 		}
4194 
4195 		if (zone->type == dns_zone_master &&
4196 		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
4197 		    zone->sigresigninginterval < (3 * refresh) &&
4198 		    dns_db_issecure(db))
4199 		{
4200 			dns_zone_log(zone, ISC_LOG_WARNING,
4201 				     "sig-re-signing-interval less than "
4202 				     "3 * refresh.");
4203 		}
4204 
4205 		zone->refresh = RANGE(refresh,
4206 				      zone->minrefresh, zone->maxrefresh);
4207 		zone->retry = RANGE(retry,
4208 				    zone->minretry, zone->maxretry);
4209 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
4210 				     DNS_MAX_EXPIRE);
4211 		zone->minimum = minimum;
4212 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4213 
4214 		if (zone->type == dns_zone_slave ||
4215 		    zone->type == dns_zone_stub ||
4216 		    (zone->type == dns_zone_redirect &&
4217 		     zone->masters != NULL)) {
4218 			isc_time_t t;
4219 			isc_uint32_t delay;
4220 
4221 			result = isc_file_getmodtime(zone->journal, &t);
4222 			if (result != ISC_R_SUCCESS)
4223 				result = isc_file_getmodtime(zone->masterfile,
4224 							     &t);
4225 			if (result == ISC_R_SUCCESS)
4226 				DNS_ZONE_TIME_ADD(&t, zone->expire,
4227 						  &zone->expiretime);
4228 			else
4229 				DNS_ZONE_TIME_ADD(&now, zone->retry,
4230 						  &zone->expiretime);
4231 
4232 			delay = isc_random_jitter(zone->retry,
4233 						  (zone->retry * 3) / 4);
4234 			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
4235 			if (isc_time_compare(&zone->refreshtime,
4236 					     &zone->expiretime) >= 0)
4237 				zone->refreshtime = now;
4238 		}
4239 
4240 		break;
4241 
4242 	case dns_zone_key:
4243 		result = sync_keyzone(zone, db);
4244 		if (result != ISC_R_SUCCESS)
4245 			goto cleanup;
4246 		break;
4247 
4248 	default:
4249 		UNEXPECTED_ERROR(__FILE__, __LINE__,
4250 				 "unexpected zone type %d", zone->type);
4251 		result = ISC_R_UNEXPECTED;
4252 		goto cleanup;
4253 	}
4254 
4255 	/*
4256 	 * Check for weak DNSKEY's.
4257 	 */
4258 	if (zone->type == dns_zone_master)
4259 		zone_check_dnskeys(zone, db);
4260 
4261 	/*
4262 	 * Schedule DNSSEC key refresh.
4263 	 */
4264 	if (zone->type == dns_zone_master &&
4265 	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
4266 		zone->refreshkeytime = now;
4267 
4268 #if 0
4269 	/* destroy notification example. */
4270 	{
4271 		isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
4272 						    DNS_EVENT_DBDESTROYED,
4273 						    dns_zonemgr_dbdestroyed,
4274 						    zone,
4275 						    sizeof(isc_event_t));
4276 		dns_db_ondestroy(db, zone->task, &e);
4277 	}
4278 #endif
4279 
4280 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4281 	if (zone->db != NULL) {
4282 		result = zone_replacedb(zone, db, ISC_FALSE);
4283 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4284 		if (result != ISC_R_SUCCESS)
4285 			goto cleanup;
4286 	} else {
4287 		zone_attachdb(zone, db);
4288 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4289 		DNS_ZONE_SETFLAG(zone,
4290 				 DNS_ZONEFLG_LOADED|
4291 				 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
4292 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
4293 		    inline_raw(zone))
4294 		{
4295 			if (zone->secure->db == NULL)
4296 				zone_send_securedb(zone, db);
4297 			else
4298 				zone_send_secureserial(zone, serial);
4299 		}
4300 	}
4301 
4302 	/*
4303 	 * Finished loading inline-signing zone; need to get status
4304 	 * from the raw side now.
4305 	 */
4306 	if (zone->type == dns_zone_master && inline_secure(zone))
4307 		maybe_send_secure(zone);
4308 
4309 
4310 	result = ISC_R_SUCCESS;
4311 
4312 	if (needdump) {
4313 		if (zone->type == dns_zone_key)
4314 			zone_needdump(zone, 30);
4315 		else
4316 			zone_needdump(zone, DNS_DUMP_DELAY);
4317 	}
4318 
4319 	if (zone->task != NULL) {
4320 		if (zone->type == dns_zone_master) {
4321 			set_resigntime(zone);
4322 			resume_signingwithkey(zone);
4323 			resume_addnsec3chain(zone);
4324 		}
4325 
4326 		if (zone->type == dns_zone_master &&
4327 		    !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4328 		    dns_zone_isdynamic(zone, ISC_FALSE) &&
4329 		    dns_db_issecure(db)) {
4330 			dns_name_t *name;
4331 			dns_fixedname_t fixed;
4332 			dns_rdataset_t next;
4333 
4334 			dns_rdataset_init(&next);
4335 			dns_fixedname_init(&fixed);
4336 			name = dns_fixedname_name(&fixed);
4337 
4338 			result = dns_db_getsigningtime(db, &next, name);
4339 			if (result == ISC_R_SUCCESS) {
4340 				isc_stdtime_t timenow;
4341 				char namebuf[DNS_NAME_FORMATSIZE];
4342 				char typebuf[DNS_RDATATYPE_FORMATSIZE];
4343 
4344 				isc_stdtime_get(&timenow);
4345 				dns_name_format(name, namebuf, sizeof(namebuf));
4346 				dns_rdatatype_format(next.covers,
4347 						     typebuf, sizeof(typebuf));
4348 				dns_zone_log(zone, ISC_LOG_DEBUG(3),
4349 					     "next resign: %s/%s in %d seconds",
4350 					     namebuf, typebuf,
4351 					     next.resign - timenow -
4352 					     zone->sigresigninginterval);
4353 				dns_rdataset_disassociate(&next);
4354 			} else
4355 				dns_zone_log(zone, ISC_LOG_WARNING,
4356 					     "signed dynamic zone has no "
4357 					     "resign event scheduled");
4358 		}
4359 
4360 		zone_settimer(zone, &now);
4361 	}
4362 
4363 	if (! dns_db_ispersistent(db))
4364 		dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
4365 			     dns_db_issecure(db) ? " (DNSSEC signed)" : "");
4366 
4367 	zone->loadtime = loadtime;
4368 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
4369 	return (result);
4370 
4371  cleanup:
4372 	if (zone->type == dns_zone_slave ||
4373 	    zone->type == dns_zone_stub ||
4374 	    zone->type == dns_zone_key ||
4375 	    (zone->type == dns_zone_redirect && zone->masters != NULL)) {
4376 		if (result != ISC_R_NOMEMORY) {
4377 			if (zone->journal != NULL)
4378 				zone_saveunique(zone, zone->journal,
4379 						"jn-XXXXXXXX");
4380 			if (zone->masterfile != NULL)
4381 				zone_saveunique(zone, zone->masterfile,
4382 						"db-XXXXXXXX");
4383 		}
4384 
4385 		/* Mark the zone for immediate refresh. */
4386 		zone->refreshtime = now;
4387 		if (zone->task != NULL)
4388 			zone_settimer(zone, &now);
4389 		result = ISC_R_SUCCESS;
4390 	} else if (zone->type == dns_zone_master ||
4391 		   zone->type == dns_zone_redirect) {
4392 		if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND))
4393 			dns_zone_log(zone, ISC_LOG_ERROR,
4394 				     "not loaded due to errors.");
4395 		else if (zone->type == dns_zone_master)
4396 			result = ISC_R_SUCCESS;
4397 	}
4398 
4399 	return (result);
4400 }
4401 
4402 static isc_boolean_t
exit_check(dns_zone_t * zone)4403 exit_check(dns_zone_t *zone) {
4404 	REQUIRE(LOCKED_ZONE(zone));
4405 
4406 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
4407 		/*
4408 		 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
4409 		 */
4410 		INSIST(isc_refcount_current(&zone->erefs) == 0);
4411 		return (ISC_TRUE);
4412 	}
4413 	return (ISC_FALSE);
4414 }
4415 
4416 static isc_boolean_t
zone_check_ns(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * version,dns_name_t * name,isc_boolean_t logit)4417 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
4418 	      dns_name_t *name, isc_boolean_t logit)
4419 {
4420 	isc_result_t result;
4421 	char namebuf[DNS_NAME_FORMATSIZE];
4422 	char altbuf[DNS_NAME_FORMATSIZE];
4423 	dns_fixedname_t fixed;
4424 	dns_name_t *foundname;
4425 	int level;
4426 
4427 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
4428 		return (ISC_TRUE);
4429 
4430 	if (zone->type == dns_zone_master)
4431 		level = ISC_LOG_ERROR;
4432 	else
4433 		level = ISC_LOG_WARNING;
4434 
4435 	dns_fixedname_init(&fixed);
4436 	foundname = dns_fixedname_name(&fixed);
4437 
4438 	result = dns_db_find(db, name, version, dns_rdatatype_a,
4439 			     0, 0, NULL, foundname, NULL, NULL);
4440 	if (result == ISC_R_SUCCESS)
4441 		return (ISC_TRUE);
4442 
4443 	if (result == DNS_R_NXRRSET) {
4444 		result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
4445 				     0, 0, NULL, foundname, NULL, NULL);
4446 		if (result == ISC_R_SUCCESS)
4447 			return (ISC_TRUE);
4448 	}
4449 
4450 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
4451 	    result == DNS_R_EMPTYNAME) {
4452 		if (logit) {
4453 			dns_name_format(name, namebuf, sizeof namebuf);
4454 			dns_zone_log(zone, level, "NS '%s' has no address "
4455 				     "records (A or AAAA)", namebuf);
4456 		}
4457 		return (ISC_FALSE);
4458 	}
4459 
4460 	if (result == DNS_R_CNAME) {
4461 		if (logit) {
4462 			dns_name_format(name, namebuf, sizeof namebuf);
4463 			dns_zone_log(zone, level, "NS '%s' is a CNAME "
4464 				     "(illegal)", namebuf);
4465 		}
4466 		return (ISC_FALSE);
4467 	}
4468 
4469 	if (result == DNS_R_DNAME) {
4470 		if (logit) {
4471 			dns_name_format(name, namebuf, sizeof namebuf);
4472 			dns_name_format(foundname, altbuf, sizeof altbuf);
4473 			dns_zone_log(zone, level, "NS '%s' is below a DNAME "
4474 				     "'%s' (illegal)", namebuf, altbuf);
4475 		}
4476 		return (ISC_FALSE);
4477 	}
4478 
4479 	return (ISC_TRUE);
4480 }
4481 
4482 static isc_result_t
zone_count_ns_rr(dns_zone_t * zone,dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,unsigned int * nscount,unsigned int * errors,isc_boolean_t logit)4483 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
4484 		 dns_dbversion_t *version, unsigned int *nscount,
4485 		 unsigned int *errors, isc_boolean_t logit)
4486 {
4487 	isc_result_t result;
4488 	unsigned int count = 0;
4489 	unsigned int ecount = 0;
4490 	dns_rdataset_t rdataset;
4491 	dns_rdata_t rdata;
4492 	dns_rdata_ns_t ns;
4493 
4494 	dns_rdataset_init(&rdataset);
4495 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
4496 				     dns_rdatatype_none, 0, &rdataset, NULL);
4497 	if (result == ISC_R_NOTFOUND) {
4498 		INSIST(!dns_rdataset_isassociated(&rdataset));
4499 		goto success;
4500 	}
4501 	if (result != ISC_R_SUCCESS) {
4502 		INSIST(!dns_rdataset_isassociated(&rdataset));
4503 		goto invalidate_rdataset;
4504 	}
4505 
4506 	result = dns_rdataset_first(&rdataset);
4507 	while (result == ISC_R_SUCCESS) {
4508 		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
4509 		    (zone->type == dns_zone_master ||
4510 		     zone->type == dns_zone_slave)) {
4511 			dns_rdata_init(&rdata);
4512 			dns_rdataset_current(&rdataset, &rdata);
4513 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
4514 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
4515 			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
4516 			    !zone_check_ns(zone, db, version, &ns.name, logit))
4517 				ecount++;
4518 		}
4519 		count++;
4520 		result = dns_rdataset_next(&rdataset);
4521 	}
4522 	dns_rdataset_disassociate(&rdataset);
4523 
4524  success:
4525 	if (nscount != NULL)
4526 		*nscount = count;
4527 	if (errors != NULL)
4528 		*errors = ecount;
4529 
4530 	result = ISC_R_SUCCESS;
4531 
4532  invalidate_rdataset:
4533 	dns_rdataset_invalidate(&rdataset);
4534 
4535 	return (result);
4536 }
4537 
4538 static isc_result_t
zone_load_soa_rr(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,unsigned int * soacount,isc_uint32_t * serial,isc_uint32_t * refresh,isc_uint32_t * retry,isc_uint32_t * expire,isc_uint32_t * minimum)4539 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
4540 		 unsigned int *soacount,
4541 		 isc_uint32_t *serial, isc_uint32_t *refresh,
4542 		 isc_uint32_t *retry, isc_uint32_t *expire,
4543 		 isc_uint32_t *minimum)
4544 {
4545 	isc_result_t result;
4546 	unsigned int count;
4547 	dns_rdataset_t rdataset;
4548 	dns_rdata_t rdata = DNS_RDATA_INIT;
4549 	dns_rdata_soa_t soa;
4550 
4551 	dns_rdataset_init(&rdataset);
4552 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
4553 				     dns_rdatatype_none, 0, &rdataset, NULL);
4554 	if (result == ISC_R_NOTFOUND) {
4555 		INSIST(!dns_rdataset_isassociated(&rdataset));
4556 		if (soacount != NULL)
4557 			*soacount = 0;
4558 		if (serial != NULL)
4559 			*serial = 0;
4560 		if (refresh != NULL)
4561 			*refresh = 0;
4562 		if (retry != NULL)
4563 			*retry = 0;
4564 		if (expire != NULL)
4565 			*expire = 0;
4566 		if (minimum != NULL)
4567 			*minimum = 0;
4568 		result = ISC_R_SUCCESS;
4569 		goto invalidate_rdataset;
4570 	}
4571 	if (result != ISC_R_SUCCESS) {
4572 		INSIST(!dns_rdataset_isassociated(&rdataset));
4573 		goto invalidate_rdataset;
4574 	}
4575 
4576 	count = 0;
4577 	result = dns_rdataset_first(&rdataset);
4578 	while (result == ISC_R_SUCCESS) {
4579 		dns_rdata_init(&rdata);
4580 		dns_rdataset_current(&rdataset, &rdata);
4581 		count++;
4582 		if (count == 1) {
4583 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
4584 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
4585 		}
4586 
4587 		result = dns_rdataset_next(&rdataset);
4588 		dns_rdata_reset(&rdata);
4589 	}
4590 	dns_rdataset_disassociate(&rdataset);
4591 
4592 	if (soacount != NULL)
4593 		*soacount = count;
4594 
4595 	if (count > 0) {
4596 		if (serial != NULL)
4597 			*serial = soa.serial;
4598 		if (refresh != NULL)
4599 			*refresh = soa.refresh;
4600 		if (retry != NULL)
4601 			*retry = soa.retry;
4602 		if (expire != NULL)
4603 			*expire = soa.expire;
4604 		if (minimum != NULL)
4605 			*minimum = soa.minimum;
4606 	} else {
4607 		if (soacount != NULL)
4608 			*soacount = 0;
4609 		if (serial != NULL)
4610 			*serial = 0;
4611 		if (refresh != NULL)
4612 			*refresh = 0;
4613 		if (retry != NULL)
4614 			*retry = 0;
4615 		if (expire != NULL)
4616 			*expire = 0;
4617 		if (minimum != NULL)
4618 			*minimum = 0;
4619 	}
4620 
4621 	result = ISC_R_SUCCESS;
4622 
4623  invalidate_rdataset:
4624 	dns_rdataset_invalidate(&rdataset);
4625 
4626 	return (result);
4627 }
4628 
4629 /*
4630  * zone must be locked.
4631  */
4632 static isc_result_t
zone_get_from_db(dns_zone_t * zone,dns_db_t * db,unsigned int * nscount,unsigned int * soacount,isc_uint32_t * serial,isc_uint32_t * refresh,isc_uint32_t * retry,isc_uint32_t * expire,isc_uint32_t * minimum,unsigned int * errors)4633 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
4634 		 unsigned int *soacount, isc_uint32_t *serial,
4635 		 isc_uint32_t *refresh, isc_uint32_t *retry,
4636 		 isc_uint32_t *expire, isc_uint32_t *minimum,
4637 		 unsigned int *errors)
4638 {
4639 	isc_result_t result;
4640 	isc_result_t answer = ISC_R_SUCCESS;
4641 	dns_dbversion_t *version = NULL;
4642 	dns_dbnode_t *node;
4643 
4644 	REQUIRE(db != NULL);
4645 	REQUIRE(zone != NULL);
4646 
4647 	dns_db_currentversion(db, &version);
4648 
4649 	if (nscount != NULL)
4650 		*nscount = 0;
4651 	if (soacount != NULL)
4652 		*soacount = 0;
4653 	if (serial != NULL)
4654 		*serial = 0;
4655 	if (refresh != NULL)
4656 		*refresh = 0;
4657 	if (retry != NULL)
4658 		*retry = 0;
4659 	if (expire != NULL)
4660 		*expire = 0;
4661 	if (errors != NULL)
4662 		*errors = 0;
4663 
4664 	node = NULL;
4665 	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
4666 	if (result != ISC_R_SUCCESS) {
4667 		answer = result;
4668 		goto closeversion;
4669 	}
4670 
4671 	if (nscount != NULL || errors != NULL) {
4672 		result = zone_count_ns_rr(zone, db, node, version,
4673 					  nscount, errors, ISC_TRUE);
4674 		if (result != ISC_R_SUCCESS)
4675 			answer = result;
4676 	}
4677 
4678 	if (soacount != NULL || serial != NULL || refresh != NULL
4679 	    || retry != NULL || expire != NULL || minimum != NULL) {
4680 		result = zone_load_soa_rr(db, node, version, soacount,
4681 					  serial, refresh, retry, expire,
4682 					  minimum);
4683 		if (result != ISC_R_SUCCESS)
4684 			answer = result;
4685 	}
4686 
4687 	dns_db_detachnode(db, &node);
4688  closeversion:
4689 	dns_db_closeversion(db, &version, ISC_FALSE);
4690 
4691 	return (answer);
4692 }
4693 
4694 void
dns_zone_attach(dns_zone_t * source,dns_zone_t ** target)4695 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
4696 	REQUIRE(DNS_ZONE_VALID(source));
4697 	REQUIRE(target != NULL && *target == NULL);
4698 	isc_refcount_increment(&source->erefs, NULL);
4699 	*target = source;
4700 }
4701 
4702 void
dns_zone_detach(dns_zone_t ** zonep)4703 dns_zone_detach(dns_zone_t **zonep) {
4704 	dns_zone_t *zone;
4705 	dns_zone_t *raw = NULL;
4706 	dns_zone_t *secure = NULL;
4707 	unsigned int refs;
4708 	isc_boolean_t free_now = ISC_FALSE;
4709 
4710 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4711 
4712 	zone = *zonep;
4713 
4714 	isc_refcount_decrement(&zone->erefs, &refs);
4715 
4716 	if (refs == 0) {
4717 		LOCK_ZONE(zone);
4718 		/*
4719 		 * We just detached the last external reference.
4720 		 */
4721 		if (zone->task != NULL) {
4722 			/*
4723 			 * This zone is being managed.	Post
4724 			 * its control event and let it clean
4725 			 * up synchronously in the context of
4726 			 * its task.
4727 			 */
4728 			isc_event_t *ev = &zone->ctlevent;
4729 			isc_task_send(zone->task, &ev);
4730 		} else {
4731 			/*
4732 			 * This zone is not being managed; it has
4733 			 * no task and can have no outstanding
4734 			 * events.  Free it immediately.
4735 			 */
4736 			/*
4737 			 * Unmanaged zones should not have non-null views;
4738 			 * we have no way of detaching from the view here
4739 			 * without causing deadlock because this code is called
4740 			 * with the view already locked.
4741 			 */
4742 			INSIST(zone->view == NULL);
4743 			free_now = ISC_TRUE;
4744 			raw = zone->raw;
4745 			zone->raw = NULL;
4746 			secure = zone->secure;
4747 			zone->secure = NULL;
4748 		}
4749 		UNLOCK_ZONE(zone);
4750 	}
4751 	*zonep = NULL;
4752 	if (free_now) {
4753 		if (raw != NULL)
4754 			dns_zone_detach(&raw);
4755 		if (secure != NULL)
4756 			dns_zone_idetach(&secure);
4757 		zone_free(zone);
4758 	}
4759 }
4760 
4761 void
dns_zone_iattach(dns_zone_t * source,dns_zone_t ** target)4762 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4763 	REQUIRE(DNS_ZONE_VALID(source));
4764 	REQUIRE(target != NULL && *target == NULL);
4765 	LOCK_ZONE(source);
4766 	zone_iattach(source, target);
4767 	UNLOCK_ZONE(source);
4768 }
4769 
4770 static void
zone_iattach(dns_zone_t * source,dns_zone_t ** target)4771 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4772 
4773 	/*
4774 	 * 'source' locked by caller.
4775 	 */
4776 	REQUIRE(LOCKED_ZONE(source));
4777 	REQUIRE(DNS_ZONE_VALID(source));
4778 	REQUIRE(target != NULL && *target == NULL);
4779 	INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
4780 	source->irefs++;
4781 	INSIST(source->irefs != 0);
4782 	*target = source;
4783 }
4784 
4785 static void
zone_idetach(dns_zone_t ** zonep)4786 zone_idetach(dns_zone_t **zonep) {
4787 	dns_zone_t *zone;
4788 
4789 	/*
4790 	 * 'zone' locked by caller.
4791 	 */
4792 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4793 	zone = *zonep;
4794 	REQUIRE(LOCKED_ZONE(*zonep));
4795 	*zonep = NULL;
4796 
4797 	INSIST(zone->irefs > 0);
4798 	zone->irefs--;
4799 	INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4800 }
4801 
4802 void
dns_zone_idetach(dns_zone_t ** zonep)4803 dns_zone_idetach(dns_zone_t **zonep) {
4804 	dns_zone_t *zone;
4805 	isc_boolean_t free_needed;
4806 
4807 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4808 	zone = *zonep;
4809 	*zonep = NULL;
4810 
4811 	LOCK_ZONE(zone);
4812 	INSIST(zone->irefs > 0);
4813 	zone->irefs--;
4814 	free_needed = exit_check(zone);
4815 	UNLOCK_ZONE(zone);
4816 	if (free_needed)
4817 		zone_free(zone);
4818 }
4819 
4820 isc_mem_t *
dns_zone_getmctx(dns_zone_t * zone)4821 dns_zone_getmctx(dns_zone_t *zone) {
4822 	REQUIRE(DNS_ZONE_VALID(zone));
4823 
4824 	return (zone->mctx);
4825 }
4826 
4827 dns_zonemgr_t *
dns_zone_getmgr(dns_zone_t * zone)4828 dns_zone_getmgr(dns_zone_t *zone) {
4829 	REQUIRE(DNS_ZONE_VALID(zone));
4830 
4831 	return (zone->zmgr);
4832 }
4833 
4834 void
dns_zone_setflag(dns_zone_t * zone,unsigned int flags,isc_boolean_t value)4835 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4836 	REQUIRE(DNS_ZONE_VALID(zone));
4837 
4838 	LOCK_ZONE(zone);
4839 	if (value)
4840 		DNS_ZONE_SETFLAG(zone, flags);
4841 	else
4842 		DNS_ZONE_CLRFLAG(zone, flags);
4843 	UNLOCK_ZONE(zone);
4844 }
4845 
4846 void
dns_zone_setoption(dns_zone_t * zone,unsigned int option,isc_boolean_t value)4847 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4848 {
4849 	REQUIRE(DNS_ZONE_VALID(zone));
4850 
4851 	LOCK_ZONE(zone);
4852 	if (value)
4853 		zone->options |= option;
4854 	else
4855 		zone->options &= ~option;
4856 	UNLOCK_ZONE(zone);
4857 }
4858 
4859 unsigned int
dns_zone_getoptions(dns_zone_t * zone)4860 dns_zone_getoptions(dns_zone_t *zone) {
4861 
4862 	REQUIRE(DNS_ZONE_VALID(zone));
4863 
4864 	return (zone->options);
4865 }
4866 
4867 void
dns_zone_setkeyopt(dns_zone_t * zone,unsigned int keyopt,isc_boolean_t value)4868 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4869 {
4870 	REQUIRE(DNS_ZONE_VALID(zone));
4871 
4872 	LOCK_ZONE(zone);
4873 	if (value)
4874 		zone->keyopts |= keyopt;
4875 	else
4876 		zone->keyopts &= ~keyopt;
4877 	UNLOCK_ZONE(zone);
4878 }
4879 
4880 unsigned int
dns_zone_getkeyopts(dns_zone_t * zone)4881 dns_zone_getkeyopts(dns_zone_t *zone) {
4882 
4883 	REQUIRE(DNS_ZONE_VALID(zone));
4884 
4885 	return (zone->keyopts);
4886 }
4887 
4888 isc_result_t
dns_zone_setxfrsource4(dns_zone_t * zone,const isc_sockaddr_t * xfrsource)4889 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4890 	REQUIRE(DNS_ZONE_VALID(zone));
4891 
4892 	LOCK_ZONE(zone);
4893 	zone->xfrsource4 = *xfrsource;
4894 	UNLOCK_ZONE(zone);
4895 
4896 	return (ISC_R_SUCCESS);
4897 }
4898 
4899 isc_sockaddr_t *
dns_zone_getxfrsource4(dns_zone_t * zone)4900 dns_zone_getxfrsource4(dns_zone_t *zone) {
4901 	REQUIRE(DNS_ZONE_VALID(zone));
4902 	return (&zone->xfrsource4);
4903 }
4904 
4905 isc_result_t
dns_zone_setxfrsource6(dns_zone_t * zone,const isc_sockaddr_t * xfrsource)4906 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4907 	REQUIRE(DNS_ZONE_VALID(zone));
4908 
4909 	LOCK_ZONE(zone);
4910 	zone->xfrsource6 = *xfrsource;
4911 	UNLOCK_ZONE(zone);
4912 
4913 	return (ISC_R_SUCCESS);
4914 }
4915 
4916 isc_sockaddr_t *
dns_zone_getxfrsource6(dns_zone_t * zone)4917 dns_zone_getxfrsource6(dns_zone_t *zone) {
4918 	REQUIRE(DNS_ZONE_VALID(zone));
4919 	return (&zone->xfrsource6);
4920 }
4921 
4922 isc_result_t
dns_zone_setaltxfrsource4(dns_zone_t * zone,const isc_sockaddr_t * altxfrsource)4923 dns_zone_setaltxfrsource4(dns_zone_t *zone,
4924 			  const isc_sockaddr_t *altxfrsource)
4925 {
4926 	REQUIRE(DNS_ZONE_VALID(zone));
4927 
4928 	LOCK_ZONE(zone);
4929 	zone->altxfrsource4 = *altxfrsource;
4930 	UNLOCK_ZONE(zone);
4931 
4932 	return (ISC_R_SUCCESS);
4933 }
4934 
4935 isc_sockaddr_t *
dns_zone_getaltxfrsource4(dns_zone_t * zone)4936 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4937 	REQUIRE(DNS_ZONE_VALID(zone));
4938 	return (&zone->altxfrsource4);
4939 }
4940 
4941 isc_result_t
dns_zone_setaltxfrsource6(dns_zone_t * zone,const isc_sockaddr_t * altxfrsource)4942 dns_zone_setaltxfrsource6(dns_zone_t *zone,
4943 			  const isc_sockaddr_t *altxfrsource)
4944 {
4945 	REQUIRE(DNS_ZONE_VALID(zone));
4946 
4947 	LOCK_ZONE(zone);
4948 	zone->altxfrsource6 = *altxfrsource;
4949 	UNLOCK_ZONE(zone);
4950 
4951 	return (ISC_R_SUCCESS);
4952 }
4953 
4954 isc_sockaddr_t *
dns_zone_getaltxfrsource6(dns_zone_t * zone)4955 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4956 	REQUIRE(DNS_ZONE_VALID(zone));
4957 	return (&zone->altxfrsource6);
4958 }
4959 
4960 isc_result_t
dns_zone_setnotifysrc4(dns_zone_t * zone,const isc_sockaddr_t * notifysrc)4961 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4962 	REQUIRE(DNS_ZONE_VALID(zone));
4963 
4964 	LOCK_ZONE(zone);
4965 	zone->notifysrc4 = *notifysrc;
4966 	UNLOCK_ZONE(zone);
4967 
4968 	return (ISC_R_SUCCESS);
4969 }
4970 
4971 isc_sockaddr_t *
dns_zone_getnotifysrc4(dns_zone_t * zone)4972 dns_zone_getnotifysrc4(dns_zone_t *zone) {
4973 	REQUIRE(DNS_ZONE_VALID(zone));
4974 	return (&zone->notifysrc4);
4975 }
4976 
4977 isc_result_t
dns_zone_setnotifysrc6(dns_zone_t * zone,const isc_sockaddr_t * notifysrc)4978 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4979 	REQUIRE(DNS_ZONE_VALID(zone));
4980 
4981 	LOCK_ZONE(zone);
4982 	zone->notifysrc6 = *notifysrc;
4983 	UNLOCK_ZONE(zone);
4984 
4985 	return (ISC_R_SUCCESS);
4986 }
4987 
4988 isc_sockaddr_t *
dns_zone_getnotifysrc6(dns_zone_t * zone)4989 dns_zone_getnotifysrc6(dns_zone_t *zone) {
4990 	REQUIRE(DNS_ZONE_VALID(zone));
4991 	return (&zone->notifysrc6);
4992 }
4993 
4994 static isc_boolean_t
same_addrs(const isc_sockaddr_t * old,const isc_sockaddr_t * new,isc_uint32_t count)4995 same_addrs(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4996 	     isc_uint32_t count)
4997 {
4998 	unsigned int i;
4999 
5000 	for (i = 0; i < count; i++)
5001 		if (!isc_sockaddr_equal(&old[i], &new[i]))
5002 			return (ISC_FALSE);
5003 	return (ISC_TRUE);
5004 }
5005 
5006 static isc_boolean_t
same_keynames(dns_name_t ** old,dns_name_t ** new,isc_uint32_t count)5007 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
5008 	unsigned int i;
5009 
5010 	if (old == NULL && new == NULL)
5011 		return (ISC_TRUE);
5012 	if (old == NULL || new == NULL)
5013 		return (ISC_FALSE);
5014 
5015 	for (i = 0; i < count; i++) {
5016 		if (old[i] == NULL && new[i] == NULL)
5017 			continue;
5018 		if (old[i] == NULL || new[i] == NULL ||
5019 		     !dns_name_equal(old[i], new[i]))
5020 			return (ISC_FALSE);
5021 	}
5022 	return (ISC_TRUE);
5023 }
5024 
5025 static void
clear_addresskeylist(isc_sockaddr_t ** addrsp,dns_name_t *** keynamesp,unsigned int * countp,isc_mem_t * mctx)5026 clear_addresskeylist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
5027 		     unsigned int *countp, isc_mem_t *mctx)
5028 {
5029 	unsigned int count;
5030 	isc_sockaddr_t *addrs;
5031 	dns_name_t **keynames;
5032 
5033 	REQUIRE(countp != NULL && addrsp != NULL && keynamesp != NULL);
5034 
5035 	count = *countp;
5036 	*countp = 0;
5037 	addrs = *addrsp;
5038 	*addrsp = NULL;
5039 	keynames = *keynamesp;
5040 	*keynamesp = NULL;
5041 
5042 	if (addrs != NULL)
5043 		isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
5044 
5045 	if (keynames != NULL) {
5046 		unsigned int i;
5047 		for (i = 0; i < count; i++) {
5048 			if (keynames[i] != NULL) {
5049 				dns_name_free(keynames[i], mctx);
5050 				isc_mem_put(mctx, keynames[i],
5051 					    sizeof(dns_name_t));
5052 				keynames[i] = NULL;
5053 			}
5054 		}
5055 		isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
5056 	}
5057 }
5058 
5059 static isc_result_t
set_addrkeylist(unsigned int count,const isc_sockaddr_t * addrs,isc_sockaddr_t ** newaddrsp,dns_name_t ** names,dns_name_t *** newnamesp,isc_mem_t * mctx)5060 set_addrkeylist(unsigned int count,
5061 		const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
5062 		dns_name_t **names, dns_name_t ***newnamesp,
5063 		isc_mem_t *mctx)
5064 {
5065 	isc_result_t result;
5066 	isc_sockaddr_t *newaddrs = NULL;
5067 	dns_name_t **newnames = NULL;
5068 	unsigned int i;
5069 
5070 	REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
5071 	REQUIRE(newnamesp != NULL && *newnamesp == NULL);
5072 
5073 	newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
5074 	if (newaddrs == NULL)
5075 		return (ISC_R_NOMEMORY);
5076 	memmove(newaddrs, addrs, count * sizeof(*newaddrs));
5077 
5078 	newnames = NULL;
5079 	if (names != NULL) {
5080 		newnames = isc_mem_get(mctx, count * sizeof(*newnames));
5081 		if (newnames == NULL) {
5082 			isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5083 			return (ISC_R_NOMEMORY);
5084 		}
5085 		for (i = 0; i < count; i++)
5086 			newnames[i] = NULL;
5087 		for (i = 0; i < count; i++) {
5088 			if (names[i] != NULL) {
5089 				newnames[i] = isc_mem_get(mctx,
5090 							 sizeof(dns_name_t));
5091 				if (newnames[i] == NULL)
5092 					goto allocfail;
5093 				dns_name_init(newnames[i], NULL);
5094 				result = dns_name_dup(names[i], mctx,
5095 						      newnames[i]);
5096 				if (result != ISC_R_SUCCESS) {
5097 				allocfail:
5098 					for (i = 0; i < count; i++)
5099 						if (newnames[i] != NULL)
5100 							dns_name_free(
5101 							       newnames[i],
5102 							       mctx);
5103 					isc_mem_put(mctx, newaddrs,
5104 						    count * sizeof(*newaddrs));
5105 					isc_mem_put(mctx, newnames,
5106 						    count * sizeof(*newnames));
5107 					return (ISC_R_NOMEMORY);
5108 				}
5109 			}
5110 		}
5111 	}
5112 
5113 	*newaddrsp = newaddrs;
5114 	*newnamesp = newnames;
5115 	return (ISC_R_SUCCESS);
5116 }
5117 
5118 isc_result_t
dns_zone_setalsonotify(dns_zone_t * zone,const isc_sockaddr_t * notify,isc_uint32_t count)5119 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
5120 		       isc_uint32_t count)
5121 {
5122 	return (dns_zone_setalsonotifywithkeys(zone, notify, NULL, count));
5123 }
5124 
5125 isc_result_t
dns_zone_setalsonotifywithkeys(dns_zone_t * zone,const isc_sockaddr_t * notify,dns_name_t ** keynames,isc_uint32_t count)5126 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5127 			       dns_name_t **keynames, isc_uint32_t count)
5128 {
5129 	isc_result_t result;
5130 	isc_sockaddr_t *newaddrs = NULL;
5131 	dns_name_t **newnames = NULL;
5132 
5133 	REQUIRE(DNS_ZONE_VALID(zone));
5134 	REQUIRE(count == 0 || notify != NULL);
5135 	if (keynames != NULL)
5136 		REQUIRE(count != 0);
5137 
5138 	LOCK_ZONE(zone);
5139 
5140 	if (count == zone->notifycnt &&
5141 	    same_addrs(zone->notify, notify, count) &&
5142 	    same_keynames(zone->notifykeynames, keynames, count))
5143 		goto unlock;
5144 
5145 	clear_addresskeylist(&zone->notify, &zone->notifykeynames,
5146 			     &zone->notifycnt, zone->mctx);
5147 
5148 	if (count == 0)
5149 		goto unlock;
5150 
5151 	/*
5152 	 * Set up the notify and notifykey lists
5153 	 */
5154 	result = set_addrkeylist(count, notify, &newaddrs,
5155 				 keynames, &newnames, zone->mctx);
5156 	if (result != ISC_R_SUCCESS)
5157 		goto unlock;
5158 
5159 	/*
5160 	 * Everything is ok so attach to the zone.
5161 	 */
5162 	zone->notify = newaddrs;
5163 	zone->notifykeynames = newnames;
5164 	zone->notifycnt = count;
5165  unlock:
5166 	UNLOCK_ZONE(zone);
5167 	return (ISC_R_SUCCESS);
5168 }
5169 
5170 isc_result_t
dns_zone_setmasters(dns_zone_t * zone,const isc_sockaddr_t * masters,isc_uint32_t count)5171 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
5172 		    isc_uint32_t count)
5173 {
5174 	isc_result_t result;
5175 
5176 	result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
5177 	return (result);
5178 }
5179 
5180 isc_result_t
dns_zone_setmasterswithkeys(dns_zone_t * zone,const isc_sockaddr_t * masters,dns_name_t ** keynames,isc_uint32_t count)5181 dns_zone_setmasterswithkeys(dns_zone_t *zone,
5182 			    const isc_sockaddr_t *masters,
5183 			    dns_name_t **keynames,
5184 			    isc_uint32_t count)
5185 {
5186 	isc_result_t result = ISC_R_SUCCESS;
5187 	isc_sockaddr_t *newaddrs = NULL;
5188 	dns_name_t **newnames = NULL;
5189 	isc_boolean_t *newok;
5190 	unsigned int i;
5191 
5192 	REQUIRE(DNS_ZONE_VALID(zone));
5193 	REQUIRE(count == 0 || masters != NULL);
5194 	if (keynames != NULL) {
5195 		REQUIRE(count != 0);
5196 	}
5197 
5198 	LOCK_ZONE(zone);
5199 	/*
5200 	 * The refresh code assumes that 'masters' wouldn't change under it.
5201 	 * If it will change then kill off any current refresh in progress
5202 	 * and update the masters info.  If it won't change then we can just
5203 	 * unlock and exit.
5204 	 */
5205 	if (count != zone->masterscnt ||
5206 	    !same_addrs(zone->masters, masters, count) ||
5207 	    !same_keynames(zone->masterkeynames, keynames, count)) {
5208 		if (zone->request != NULL)
5209 			dns_request_cancel(zone->request);
5210 	} else
5211 		goto unlock;
5212 
5213 	/*
5214 	 * This needs to happen before clear_addresskeylist() sets
5215 	 * zone->masterscnt to 0:
5216 	 */
5217 	if (zone->mastersok != NULL) {
5218 		isc_mem_put(zone->mctx, zone->mastersok,
5219 			    zone->masterscnt * sizeof(isc_boolean_t));
5220 		zone->mastersok = NULL;
5221 	}
5222 	clear_addresskeylist(&zone->masters, &zone->masterkeynames,
5223 			     &zone->masterscnt, zone->mctx);
5224 	/*
5225 	 * If count == 0, don't allocate any space for masters, mastersok or
5226 	 * keynames so internally, those pointers are NULL if count == 0
5227 	 */
5228 	if (count == 0)
5229 		goto unlock;
5230 
5231 	/*
5232 	 * mastersok must contain count elements
5233 	 */
5234 	newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
5235 	if (newok == NULL) {
5236 		result = ISC_R_NOMEMORY;
5237 		isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
5238 		goto unlock;
5239 	};
5240 	for (i = 0; i < count; i++)
5241 		newok[i] = ISC_FALSE;
5242 
5243 	/*
5244 	 * Now set up the masters and masterkey lists
5245 	 */
5246 	result = set_addrkeylist(count, masters, &newaddrs,
5247 				 keynames, &newnames, zone->mctx);
5248 	if (result != ISC_R_SUCCESS) {
5249 		isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
5250 		goto unlock;
5251 	}
5252 
5253 	/*
5254 	 * Everything is ok so attach to the zone.
5255 	 */
5256 	zone->curmaster = 0;
5257 	zone->mastersok = newok;
5258 	zone->masters = newaddrs;
5259 	zone->masterkeynames = newnames;
5260 	zone->masterscnt = count;
5261 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
5262 
5263  unlock:
5264 	UNLOCK_ZONE(zone);
5265 	return (result);
5266 }
5267 
5268 isc_result_t
dns_zone_getdb(dns_zone_t * zone,dns_db_t ** dpb)5269 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
5270 	isc_result_t result = ISC_R_SUCCESS;
5271 
5272 	REQUIRE(DNS_ZONE_VALID(zone));
5273 
5274 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5275 	if (zone->db == NULL)
5276 		result = DNS_R_NOTLOADED;
5277 	else
5278 		dns_db_attach(zone->db, dpb);
5279 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5280 
5281 	return (result);
5282 }
5283 
5284 void
dns_zone_setdb(dns_zone_t * zone,dns_db_t * db)5285 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
5286 	REQUIRE(DNS_ZONE_VALID(zone));
5287 	REQUIRE(zone->type == dns_zone_staticstub);
5288 
5289 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5290 	REQUIRE(zone->db == NULL);
5291 	dns_db_attach(db, &zone->db);
5292 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5293 }
5294 
5295 /*
5296  * Co-ordinates the starting of routine jobs.
5297  */
5298 
5299 void
dns_zone_maintenance(dns_zone_t * zone)5300 dns_zone_maintenance(dns_zone_t *zone) {
5301 	const char me[] = "dns_zone_maintenance";
5302 	isc_time_t now;
5303 
5304 	REQUIRE(DNS_ZONE_VALID(zone));
5305 	ENTER;
5306 
5307 	LOCK_ZONE(zone);
5308 	TIME_NOW(&now);
5309 	zone_settimer(zone, &now);
5310 	UNLOCK_ZONE(zone);
5311 }
5312 
5313 static inline isc_boolean_t
was_dumping(dns_zone_t * zone)5314 was_dumping(dns_zone_t *zone) {
5315 	isc_boolean_t dumping;
5316 
5317 	REQUIRE(LOCKED_ZONE(zone));
5318 
5319 	dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
5320 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
5321 	if (!dumping) {
5322 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
5323 		isc_time_settoepoch(&zone->dumptime);
5324 	}
5325 	return (dumping);
5326 }
5327 
5328 static isc_result_t
find_zone_keys(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,isc_mem_t * mctx,unsigned int maxkeys,dst_key_t ** keys,unsigned int * nkeys)5329 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
5330 	       isc_mem_t *mctx, unsigned int maxkeys,
5331 	       dst_key_t **keys, unsigned int *nkeys)
5332 {
5333 	isc_result_t result;
5334 	dns_dbnode_t *node = NULL;
5335 	const char *directory = dns_zone_getkeydirectory(zone);
5336 
5337 	CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
5338 	memset(keys, 0, sizeof(*keys) * maxkeys);
5339 	result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
5340 					  directory, mctx, maxkeys, keys,
5341 					  nkeys);
5342 	if (result == ISC_R_NOTFOUND)
5343 		result = ISC_R_SUCCESS;
5344  failure:
5345 	if (node != NULL)
5346 		dns_db_detachnode(db, &node);
5347 	return (result);
5348 }
5349 
5350 static isc_result_t
offline(dns_db_t * db,dns_dbversion_t * ver,zonediff_t * zonediff,dns_name_t * name,dns_ttl_t ttl,dns_rdata_t * rdata)5351 offline(dns_db_t *db, dns_dbversion_t *ver, zonediff_t *zonediff,
5352 	dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
5353 {
5354 	isc_result_t result;
5355 
5356 	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
5357 		return (ISC_R_SUCCESS);
5358 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
5359 			       name, ttl, rdata);
5360 	if (result != ISC_R_SUCCESS)
5361 		return (result);
5362 	rdata->flags |= DNS_RDATA_OFFLINE;
5363 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
5364 			       name, ttl, rdata);
5365 	zonediff->offline = ISC_TRUE;
5366 	return (result);
5367 }
5368 
5369 static void
set_key_expiry_warning(dns_zone_t * zone,isc_stdtime_t when,isc_stdtime_t now)5370 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
5371 {
5372 	unsigned int delta;
5373 	char timebuf[80];
5374 
5375 	zone->key_expiry = when;
5376 	if (when <= now) {
5377 		dns_zone_log(zone, ISC_LOG_ERROR,
5378 			     "DNSKEY RRSIG(s) have expired");
5379 		isc_time_settoepoch(&zone->keywarntime);
5380 	} else if (when < now + 7 * 24 * 3600) {
5381 		isc_time_t t;
5382 		isc_time_set(&t, when, 0);
5383 		isc_time_formattimestamp(&t, timebuf, 80);
5384 		dns_zone_log(zone, ISC_LOG_WARNING,
5385 			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
5386 			     timebuf);
5387 		delta = when - now;
5388 		delta--;		/* loop prevention */
5389 		delta /= 24 * 3600;	/* to whole days */
5390 		delta *= 24 * 3600;	/* to seconds */
5391 		isc_time_set(&zone->keywarntime, when - delta, 0);
5392 	}  else {
5393 		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
5394 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
5395 		dns_zone_log(zone, ISC_LOG_NOTICE,
5396 			     "setting keywarntime to %s", timebuf);
5397 	}
5398 }
5399 
5400 /*
5401  * Helper function to del_sigs(). We don't want to delete RRSIGs that
5402  * have no new key.
5403  */
5404 static isc_boolean_t
delsig_ok(dns_rdata_rrsig_t * rrsig_ptr,dst_key_t ** keys,unsigned int nkeys,isc_boolean_t * warn)5405 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
5406 	  isc_boolean_t *warn)
5407 {
5408 	unsigned int i = 0;
5409 	isc_boolean_t have_ksk = ISC_FALSE, have_zsk = ISC_FALSE;
5410 	isc_boolean_t have_pksk = ISC_FALSE, have_pzsk = ISC_FALSE;
5411 
5412 	for (i = 0; i < nkeys; i++) {
5413 		if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
5414 			continue;
5415 		if (dst_key_isprivate(keys[i])) {
5416 			if (KSK(keys[i]))
5417 				have_ksk = have_pksk = ISC_TRUE;
5418 			else
5419 				have_zsk = have_pzsk = ISC_TRUE;
5420 		} else {
5421 			if (KSK(keys[i]))
5422 				have_ksk = ISC_TRUE;
5423 			else
5424 				have_zsk = ISC_TRUE;
5425 		}
5426 	}
5427 
5428 	if (have_zsk && have_ksk && !have_pzsk)
5429 		*warn = ISC_TRUE;
5430 
5431 	/*
5432 	 * It's okay to delete a signature if there is an active key
5433 	 * with the same algorithm to replace it.
5434 	 */
5435 	if (have_pksk || have_pzsk)
5436 		return (ISC_TRUE);
5437 
5438 	/*
5439 	 * Failing that, it is *not* okay to delete a signature
5440 	 * if the associated public key is still in the DNSKEY RRset
5441 	 */
5442 	for (i = 0; i < nkeys; i++) {
5443 		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
5444 		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
5445 			return (ISC_FALSE);
5446 	}
5447 
5448 	/*
5449 	 * But if the key is gone, then go ahead.
5450 	 */
5451 	return (ISC_TRUE);
5452 }
5453 
5454 /*
5455  * Delete expired RRsigs and any RRsigs we are about to re-sign.
5456  * See also update.c:del_keysigs().
5457  */
5458 static isc_result_t
del_sigs(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_rdatatype_t type,zonediff_t * zonediff,dst_key_t ** keys,unsigned int nkeys,isc_stdtime_t now,isc_boolean_t incremental)5459 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5460 	 dns_rdatatype_t type, zonediff_t *zonediff, dst_key_t **keys,
5461 	 unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
5462 {
5463 	isc_result_t result;
5464 	dns_dbnode_t *node = NULL;
5465 	dns_rdataset_t rdataset;
5466 	unsigned int i;
5467 	dns_rdata_rrsig_t rrsig;
5468 	isc_boolean_t found;
5469 	isc_int64_t timewarn = 0, timemaybe = 0;
5470 
5471 	dns_rdataset_init(&rdataset);
5472 
5473 	if (type == dns_rdatatype_nsec3)
5474 		result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5475 	else
5476 		result = dns_db_findnode(db, name, ISC_FALSE, &node);
5477 	if (result == ISC_R_NOTFOUND)
5478 		return (ISC_R_SUCCESS);
5479 	if (result != ISC_R_SUCCESS)
5480 		goto failure;
5481 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
5482 				     (isc_stdtime_t) 0, &rdataset, NULL);
5483 	dns_db_detachnode(db, &node);
5484 
5485 	if (result == ISC_R_NOTFOUND) {
5486 		INSIST(!dns_rdataset_isassociated(&rdataset));
5487 		return (ISC_R_SUCCESS);
5488 	}
5489 	if (result != ISC_R_SUCCESS) {
5490 		INSIST(!dns_rdataset_isassociated(&rdataset));
5491 		goto failure;
5492 	}
5493 
5494 	for (result = dns_rdataset_first(&rdataset);
5495 	     result == ISC_R_SUCCESS;
5496 	     result = dns_rdataset_next(&rdataset)) {
5497 		dns_rdata_t rdata = DNS_RDATA_INIT;
5498 
5499 		dns_rdataset_current(&rdataset, &rdata);
5500 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5501 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
5502 
5503 		if (type != dns_rdatatype_dnskey) {
5504 			isc_boolean_t warn = ISC_FALSE, deleted = ISC_FALSE;
5505 			if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
5506 				result = update_one_rr(db, ver, zonediff->diff,
5507 					       DNS_DIFFOP_DELRESIGN, name,
5508 					       rdataset.ttl, &rdata);
5509 				if (result != ISC_R_SUCCESS)
5510 					break;
5511 				deleted = ISC_TRUE;
5512 			}
5513 			if (warn) {
5514 				/*
5515 				 * At this point, we've got an RRSIG,
5516 				 * which is signed by an inactive key.
5517 				 * An administrator needs to provide a new
5518 				 * key/alg, but until that time, we want to
5519 				 * keep the old RRSIG.  Marking the key as
5520 				 * offline will prevent us spinning waiting
5521 				 * for the private part.
5522 				 */
5523 				if (incremental && !deleted) {
5524 					result = offline(db, ver, zonediff,
5525 							 name, rdataset.ttl,
5526 							 &rdata);
5527 					if (result != ISC_R_SUCCESS)
5528 						break;
5529 				}
5530 
5531 				/*
5532 				 * Log the key id and algorithm of
5533 				 * the inactive key with no replacement
5534 				 */
5535 				if (zone->log_key_expired_timer <= now) {
5536 					char origin[DNS_NAME_FORMATSIZE];
5537 					char algbuf[DNS_NAME_FORMATSIZE];
5538 					dns_name_format(&zone->origin, origin,
5539 							sizeof(origin));
5540 					dns_secalg_format(rrsig.algorithm,
5541 							  algbuf,
5542 							  sizeof(algbuf));
5543 					dns_zone_log(zone, ISC_LOG_WARNING,
5544 						     "Key %s/%s/%d "
5545 						     "missing or inactive "
5546 						     "and has no replacement: "
5547 						     "retaining signatures.",
5548 						     origin, algbuf,
5549 						     rrsig.keyid);
5550 					zone->log_key_expired_timer = now +
5551 									3600;
5552 				}
5553 			}
5554 			continue;
5555 		}
5556 
5557 		/*
5558 		 * RRSIG(DNSKEY) requires special processing.
5559 		 */
5560 		found = ISC_FALSE;
5561 		for (i = 0; i < nkeys; i++) {
5562 			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
5563 			    rrsig.keyid == dst_key_id(keys[i])) {
5564 				found = ISC_TRUE;
5565 				/*
5566 				 * Mark offline RRSIG(DNSKEY).
5567 				 * We want the earliest offline expire time
5568 				 * iff there is a new offline signature.
5569 				 */
5570 				if (!dst_key_inactive(keys[i]) &&
5571 				    !dst_key_isprivate(keys[i]))
5572 				{
5573 					isc_int64_t timeexpire =
5574 					   dns_time64_from32(rrsig.timeexpire);
5575 					if (timewarn != 0 &&
5576 					    timewarn > timeexpire)
5577 						timewarn = timeexpire;
5578 					if (rdata.flags & DNS_RDATA_OFFLINE) {
5579 						if (timemaybe == 0 ||
5580 						    timemaybe > timeexpire)
5581 							timemaybe = timeexpire;
5582 						break;
5583 					}
5584 					if (timewarn == 0)
5585 						timewarn = timemaybe;
5586 					if (timewarn == 0 ||
5587 					    timewarn > timeexpire)
5588 						timewarn = timeexpire;
5589 					result = offline(db, ver, zonediff,
5590 							 name, rdataset.ttl,
5591 							 &rdata);
5592 					break;
5593 				}
5594 				result = update_one_rr(db, ver, zonediff->diff,
5595 						       DNS_DIFFOP_DELRESIGN,
5596 						       name, rdataset.ttl,
5597 						       &rdata);
5598 				break;
5599 			}
5600 		}
5601 
5602 		/*
5603 		 * If there is not a matching DNSKEY then
5604 		 * delete the RRSIG.
5605 		 */
5606 		if (!found)
5607 			result = update_one_rr(db, ver, zonediff->diff,
5608 					       DNS_DIFFOP_DELRESIGN, name,
5609 					       rdataset.ttl, &rdata);
5610 		if (result != ISC_R_SUCCESS)
5611 			break;
5612 	}
5613 
5614 	dns_rdataset_disassociate(&rdataset);
5615 	if (result == ISC_R_NOMORE)
5616 		result = ISC_R_SUCCESS;
5617 	if (timewarn > 0) {
5618 #if defined(STDTIME_ON_32BITS)
5619 		isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
5620 		if (timewarn == stdwarn)
5621 #endif
5622 			set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
5623 					       now);
5624 #if defined(STDTIME_ON_32BITS)
5625 		else
5626 			dns_zone_log(zone, ISC_LOG_ERROR,
5627 				     "key expiry warning time out of range");
5628 #endif
5629 	}
5630  failure:
5631 	if (node != NULL)
5632 		dns_db_detachnode(db, &node);
5633 	return (result);
5634 }
5635 
5636 static isc_result_t
add_sigs(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_rdatatype_t type,dns_diff_t * diff,dst_key_t ** keys,unsigned int nkeys,isc_mem_t * mctx,isc_stdtime_t inception,isc_stdtime_t expire,isc_boolean_t check_ksk,isc_boolean_t keyset_kskonly)5637 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5638 	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
5639 	 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
5640 	 isc_stdtime_t expire, isc_boolean_t check_ksk,
5641 	 isc_boolean_t keyset_kskonly)
5642 {
5643 	isc_result_t result;
5644 	dns_dbnode_t *node = NULL;
5645 	dns_rdataset_t rdataset;
5646 	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
5647 	unsigned char data[1024]; /* XXX */
5648 	isc_buffer_t buffer;
5649 	unsigned int i, j;
5650 
5651 	dns_rdataset_init(&rdataset);
5652 	isc_buffer_init(&buffer, data, sizeof(data));
5653 
5654 	if (type == dns_rdatatype_nsec3)
5655 		result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5656 	else
5657 		result = dns_db_findnode(db, name, ISC_FALSE, &node);
5658 	if (result == ISC_R_NOTFOUND)
5659 		return (ISC_R_SUCCESS);
5660 	if (result != ISC_R_SUCCESS)
5661 		goto failure;
5662 	result = dns_db_findrdataset(db, node, ver, type, 0,
5663 				     (isc_stdtime_t) 0, &rdataset, NULL);
5664 	dns_db_detachnode(db, &node);
5665 	if (result == ISC_R_NOTFOUND) {
5666 		INSIST(!dns_rdataset_isassociated(&rdataset));
5667 		return (ISC_R_SUCCESS);
5668 	}
5669 	if (result != ISC_R_SUCCESS) {
5670 		INSIST(!dns_rdataset_isassociated(&rdataset));
5671 		goto failure;
5672 	}
5673 
5674 	for (i = 0; i < nkeys; i++) {
5675 		isc_boolean_t both = ISC_FALSE;
5676 
5677 		if (!dst_key_isprivate(keys[i]))
5678 			continue;
5679 
5680 		if (check_ksk && !REVOKE(keys[i])) {
5681 			isc_boolean_t have_ksk, have_nonksk;
5682 			if (KSK(keys[i])) {
5683 				have_ksk = ISC_TRUE;
5684 				have_nonksk = ISC_FALSE;
5685 			} else {
5686 				have_ksk = ISC_FALSE;
5687 				have_nonksk = ISC_TRUE;
5688 			}
5689 			for (j = 0; j < nkeys; j++) {
5690 				if (j == i || ALG(keys[i]) != ALG(keys[j]))
5691 					continue;
5692 				if (REVOKE(keys[j]))
5693 					continue;
5694 				if (KSK(keys[j]))
5695 					have_ksk = ISC_TRUE;
5696 				else
5697 					have_nonksk = ISC_TRUE;
5698 				both = have_ksk && have_nonksk;
5699 				if (both)
5700 					break;
5701 			}
5702 		}
5703 		if (both) {
5704 			if (type == dns_rdatatype_dnskey) {
5705 				if (!KSK(keys[i]) && keyset_kskonly)
5706 					continue;
5707 			} else if (KSK(keys[i]))
5708 				continue;
5709 		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
5710 				continue;
5711 
5712 		/* Calculate the signature, creating a RRSIG RDATA. */
5713 		isc_buffer_clear(&buffer);
5714 		CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
5715 				      &inception, &expire,
5716 				      mctx, &buffer, &sig_rdata));
5717 		/* Update the database and journal with the RRSIG. */
5718 		/* XXX inefficient - will cause dataset merging */
5719 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
5720 				    name, rdataset.ttl, &sig_rdata));
5721 		dns_rdata_reset(&sig_rdata);
5722 		isc_buffer_init(&buffer, data, sizeof(data));
5723 	}
5724 
5725  failure:
5726 	if (dns_rdataset_isassociated(&rdataset))
5727 		dns_rdataset_disassociate(&rdataset);
5728 	if (node != NULL)
5729 		dns_db_detachnode(db, &node);
5730 	return (result);
5731 }
5732 
5733 static void
zone_resigninc(dns_zone_t * zone)5734 zone_resigninc(dns_zone_t *zone) {
5735 	const char *me = "zone_resigninc";
5736 	dns_db_t *db = NULL;
5737 	dns_dbversion_t *version = NULL;
5738 	dns_diff_t _sig_diff;
5739 	zonediff_t zonediff;
5740 	dns_fixedname_t fixed;
5741 	dns_name_t *name;
5742 	dns_rdataset_t rdataset;
5743 	dns_rdatatype_t covers;
5744 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
5745 	isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
5746 	isc_result_t result;
5747 	isc_stdtime_t now, inception, soaexpire, expire, stop;
5748 	isc_uint32_t jitter;
5749 	unsigned int i;
5750 	unsigned int nkeys = 0;
5751 	unsigned int resign;
5752 
5753 	ENTER;
5754 
5755 	dns_rdataset_init(&rdataset);
5756 	dns_fixedname_init(&fixed);
5757 	dns_diff_init(zone->mctx, &_sig_diff);
5758 	zonediff_init(&zonediff, &_sig_diff);
5759 
5760 	/*
5761 	 * Zone is frozen or automatic resigning is disabled.
5762 	 * Pause for 5 minutes.
5763 	 */
5764 	if (zone->update_disabled ||
5765 	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
5766 	{
5767 		result = ISC_R_FAILURE;
5768 		goto failure;
5769 	}
5770 
5771 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5772 	dns_db_attach(zone->db, &db);
5773 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5774 
5775 	result = dns_db_newversion(db, &version);
5776 	if (result != ISC_R_SUCCESS) {
5777 		dns_zone_log(zone, ISC_LOG_ERROR,
5778 			     "zone_resigninc:dns_db_newversion -> %s",
5779 			     dns_result_totext(result));
5780 		goto failure;
5781 	}
5782 
5783 	result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
5784 				zone_keys, &nkeys);
5785 	if (result != ISC_R_SUCCESS) {
5786 		dns_zone_log(zone, ISC_LOG_ERROR,
5787 			     "zone_resigninc:find_zone_keys -> %s",
5788 			     dns_result_totext(result));
5789 		goto failure;
5790 	}
5791 
5792 	isc_stdtime_get(&now);
5793 	inception = now - 3600;	/* Allow for clock skew. */
5794 	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5795 	/*
5796 	 * Spread out signatures over time if they happen to be
5797 	 * clumped.  We don't do this for each add_sigs() call as
5798 	 * we still want some clustering to occur.
5799 	 */
5800 	isc_random_get(&jitter);
5801 	expire = soaexpire - jitter % 3600;
5802 	stop = now + 5;
5803 
5804 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5805 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5806 
5807 	name = dns_fixedname_name(&fixed);
5808 	result = dns_db_getsigningtime(db, &rdataset, name);
5809 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
5810 		dns_zone_log(zone, ISC_LOG_ERROR,
5811 			     "zone_resigninc:dns_db_getsigningtime -> %s",
5812 			     dns_result_totext(result));
5813 	}
5814 
5815 	i = 0;
5816 	while (result == ISC_R_SUCCESS) {
5817 		resign = rdataset.resign - zone->sigresigninginterval;
5818 		covers = rdataset.covers;
5819 		dns_rdataset_disassociate(&rdataset);
5820 
5821 		/*
5822 		 * Stop if we hit the SOA as that means we have walked the
5823 		 * entire zone.  The SOA record should always be the most
5824 		 * recent signature.
5825 		 */
5826 		/* XXXMPA increase number of RRsets signed pre call */
5827 		if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
5828 		    resign > stop)
5829 			break;
5830 
5831 		result = del_sigs(zone, db, version, name, covers, &zonediff,
5832 				  zone_keys, nkeys, now, ISC_TRUE);
5833 		if (result != ISC_R_SUCCESS) {
5834 			dns_zone_log(zone, ISC_LOG_ERROR,
5835 				     "zone_resigninc:del_sigs -> %s",
5836 				     dns_result_totext(result));
5837 			break;
5838 		}
5839 
5840 		result = add_sigs(db, version, name, covers, zonediff.diff,
5841 				  zone_keys, nkeys, zone->mctx, inception,
5842 				  expire, check_ksk, keyset_kskonly);
5843 		if (result != ISC_R_SUCCESS) {
5844 			dns_zone_log(zone, ISC_LOG_ERROR,
5845 				     "zone_resigninc:add_sigs -> %s",
5846 				     dns_result_totext(result));
5847 			break;
5848 		}
5849 		result	= dns_db_getsigningtime(db, &rdataset, name);
5850 		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
5851 			result = ISC_R_SUCCESS;
5852 			break;
5853 		}
5854 		if (result != ISC_R_SUCCESS)
5855 			dns_zone_log(zone, ISC_LOG_ERROR,
5856 			     "zone_resigninc:dns_db_getsigningtime -> %s",
5857 				     dns_result_totext(result));
5858 	}
5859 
5860 	if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
5861 		goto failure;
5862 
5863 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5864 			  &zonediff, zone_keys, nkeys, now, ISC_TRUE);
5865 	if (result != ISC_R_SUCCESS) {
5866 		dns_zone_log(zone, ISC_LOG_ERROR,
5867 			     "zone_resigninc:del_sigs -> %s",
5868 			     dns_result_totext(result));
5869 		goto failure;
5870 	}
5871 
5872 	/*
5873 	 * Did we change anything in the zone?
5874 	 */
5875 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
5876 		/*
5877 		 * Commit the changes if any key has been marked as offline.			 */
5878 		if (zonediff.offline)
5879 			dns_db_closeversion(db, &version, ISC_TRUE);
5880 		goto failure;
5881 	}
5882 
5883 	/* Increment SOA serial if we have made changes */
5884 	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
5885 				   zone->updatemethod);
5886 	if (result != ISC_R_SUCCESS) {
5887 		dns_zone_log(zone, ISC_LOG_ERROR,
5888 			     "zone_resigninc:update_soa_serial -> %s",
5889 			     dns_result_totext(result));
5890 		goto failure;
5891 	}
5892 
5893 	/*
5894 	 * Generate maximum life time signatures so that the above loop
5895 	 * termination is sensible.
5896 	 */
5897 	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5898 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
5899 			  inception, soaexpire, check_ksk, keyset_kskonly);
5900 	if (result != ISC_R_SUCCESS) {
5901 		dns_zone_log(zone, ISC_LOG_ERROR,
5902 			     "zone_resigninc:add_sigs -> %s",
5903 			     dns_result_totext(result));
5904 		goto failure;
5905 	}
5906 
5907 	/* Write changes to journal file. */
5908 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
5909 
5910 	/* Everything has succeeded. Commit the changes. */
5911 	dns_db_closeversion(db, &version, ISC_TRUE);
5912 
5913  failure:
5914 	dns_diff_clear(&_sig_diff);
5915 	for (i = 0; i < nkeys; i++)
5916 		dst_key_free(&zone_keys[i]);
5917 	if (version != NULL) {
5918 		dns_db_closeversion(zone->db, &version, ISC_FALSE);
5919 		dns_db_detach(&db);
5920 	} else if (db != NULL)
5921 		dns_db_detach(&db);
5922 	if (result == ISC_R_SUCCESS) {
5923 		set_resigntime(zone);
5924 		LOCK_ZONE(zone);
5925 		zone_needdump(zone, DNS_DUMP_DELAY);
5926 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5927 		UNLOCK_ZONE(zone);
5928 	} else {
5929 		/*
5930 		 * Something failed.  Retry in 5 minutes.
5931 		 */
5932 		isc_interval_t ival;
5933 		isc_interval_set(&ival, 300, 0);
5934 		isc_time_nowplusinterval(&zone->resigntime, &ival);
5935 	}
5936 
5937 	INSIST(version == NULL);
5938 }
5939 
5940 static isc_result_t
next_active(dns_db_t * db,dns_dbversion_t * version,dns_name_t * oldname,dns_name_t * newname,isc_boolean_t bottom)5941 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
5942 	    dns_name_t *newname, isc_boolean_t bottom)
5943 {
5944 	isc_result_t result;
5945 	dns_dbiterator_t *dbit = NULL;
5946 	dns_rdatasetiter_t *rdsit = NULL;
5947 	dns_dbnode_t *node = NULL;
5948 
5949 	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
5950 	CHECK(dns_dbiterator_seek(dbit, oldname));
5951 	do {
5952 		result = dns_dbiterator_next(dbit);
5953 		if (result == ISC_R_NOMORE)
5954 			CHECK(dns_dbiterator_first(dbit));
5955 		CHECK(dns_dbiterator_current(dbit, &node, newname));
5956 		if (bottom && dns_name_issubdomain(newname, oldname) &&
5957 		    !dns_name_equal(newname, oldname)) {
5958 			dns_db_detachnode(db, &node);
5959 			continue;
5960 		}
5961 		/*
5962 		 * Is this node empty?
5963 		 */
5964 		CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
5965 		result = dns_rdatasetiter_first(rdsit);
5966 		dns_db_detachnode(db, &node);
5967 		dns_rdatasetiter_destroy(&rdsit);
5968 		if (result != ISC_R_NOMORE)
5969 			break;
5970 	} while (1);
5971  failure:
5972 	if (node != NULL)
5973 		dns_db_detachnode(db, &node);
5974 	if (dbit != NULL)
5975 		dns_dbiterator_destroy(&dbit);
5976 	return (result);
5977 }
5978 
5979 static isc_boolean_t
signed_with_key(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdatatype_t type,dst_key_t * key)5980 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5981 		dns_rdatatype_t type, dst_key_t *key)
5982 {
5983 	isc_result_t result;
5984 	dns_rdataset_t rdataset;
5985 	dns_rdata_t rdata = DNS_RDATA_INIT;
5986 	dns_rdata_rrsig_t rrsig;
5987 
5988 	dns_rdataset_init(&rdataset);
5989 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
5990 				     type, 0, &rdataset, NULL);
5991 	if (result != ISC_R_SUCCESS) {
5992 		INSIST(!dns_rdataset_isassociated(&rdataset));
5993 		return (ISC_FALSE);
5994 	}
5995 	for (result = dns_rdataset_first(&rdataset);
5996 	     result == ISC_R_SUCCESS;
5997 	     result = dns_rdataset_next(&rdataset)) {
5998 		dns_rdataset_current(&rdataset, &rdata);
5999 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6000 		INSIST(result == ISC_R_SUCCESS);
6001 		if (rrsig.algorithm == dst_key_alg(key) &&
6002 		    rrsig.keyid == dst_key_id(key)) {
6003 			dns_rdataset_disassociate(&rdataset);
6004 			return (ISC_TRUE);
6005 		}
6006 		dns_rdata_reset(&rdata);
6007 	}
6008 	dns_rdataset_disassociate(&rdataset);
6009 	return (ISC_FALSE);
6010 }
6011 
6012 static isc_result_t
add_nsec(dns_db_t * db,dns_dbversion_t * version,dns_name_t * name,dns_dbnode_t * node,dns_ttl_t ttl,isc_boolean_t bottom,dns_diff_t * diff)6013 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6014 	 dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
6015 	 dns_diff_t *diff)
6016 {
6017 	dns_fixedname_t fixed;
6018 	dns_name_t *next;
6019 	dns_rdata_t rdata = DNS_RDATA_INIT;
6020 	isc_result_t result;
6021 	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
6022 
6023 	dns_fixedname_init(&fixed);
6024 	next = dns_fixedname_name(&fixed);
6025 
6026 	CHECK(next_active(db, version, name, next, bottom));
6027 	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
6028 				  &rdata));
6029 	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
6030 			    &rdata));
6031  failure:
6032 	return (result);
6033 }
6034 
6035 static isc_result_t
sign_a_node(dns_db_t * db,dns_name_t * name,dns_dbnode_t * node,dns_dbversion_t * version,isc_boolean_t build_nsec3,isc_boolean_t build_nsec,dst_key_t * key,isc_stdtime_t inception,isc_stdtime_t expire,unsigned int minimum,isc_boolean_t is_ksk,isc_boolean_t keyset_kskonly,isc_boolean_t * delegation,dns_diff_t * diff,isc_int32_t * signatures,isc_mem_t * mctx)6036 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
6037 	    dns_dbversion_t *version, isc_boolean_t build_nsec3,
6038 	    isc_boolean_t build_nsec, dst_key_t *key,
6039 	    isc_stdtime_t inception, isc_stdtime_t expire,
6040 	    unsigned int minimum, isc_boolean_t is_ksk,
6041 	    isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
6042 	    dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
6043 {
6044 	isc_result_t result;
6045 	dns_rdatasetiter_t *iterator = NULL;
6046 	dns_rdataset_t rdataset;
6047 	dns_rdata_t rdata = DNS_RDATA_INIT;
6048 	isc_buffer_t buffer;
6049 	unsigned char data[1024];
6050 	isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
6051 		      seen_nsec3, seen_ds;
6052 	isc_boolean_t bottom;
6053 
6054 	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6055 	if (result != ISC_R_SUCCESS) {
6056 		if (result == ISC_R_NOTFOUND)
6057 			result = ISC_R_SUCCESS;
6058 		return (result);
6059 	}
6060 
6061 	dns_rdataset_init(&rdataset);
6062 	isc_buffer_init(&buffer, data, sizeof(data));
6063 	seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
6064 	seen_nsec3 = seen_ds = ISC_FALSE;
6065 	for (result = dns_rdatasetiter_first(iterator);
6066 	     result == ISC_R_SUCCESS;
6067 	     result = dns_rdatasetiter_next(iterator)) {
6068 		dns_rdatasetiter_current(iterator, &rdataset);
6069 		if (rdataset.type == dns_rdatatype_soa)
6070 			seen_soa = ISC_TRUE;
6071 		else if (rdataset.type == dns_rdatatype_ns)
6072 			seen_ns = ISC_TRUE;
6073 		else if (rdataset.type == dns_rdatatype_ds)
6074 			seen_ds = ISC_TRUE;
6075 		else if (rdataset.type == dns_rdatatype_dname)
6076 			seen_dname = ISC_TRUE;
6077 		else if (rdataset.type == dns_rdatatype_nsec)
6078 			seen_nsec = ISC_TRUE;
6079 		else if (rdataset.type == dns_rdatatype_nsec3)
6080 			seen_nsec3 = ISC_TRUE;
6081 		if (rdataset.type != dns_rdatatype_rrsig)
6082 			seen_rr = ISC_TRUE;
6083 		dns_rdataset_disassociate(&rdataset);
6084 	}
6085 	if (result != ISC_R_NOMORE)
6086 		goto failure;
6087 	if (seen_ns && !seen_soa)
6088 		*delegation = ISC_TRUE;
6089 	/*
6090 	 * Going from insecure to NSEC3.
6091 	 * Don't generate NSEC3 records for NSEC3 records.
6092 	 */
6093 	if (build_nsec3 && !seen_nsec3 && seen_rr) {
6094 		isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
6095 		CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
6096 					  unsecure, diff));
6097 		(*signatures)--;
6098 	}
6099 	/*
6100 	 * Going from insecure to NSEC.
6101 	 * Don't generate NSEC records for NSEC3 records.
6102 	 */
6103 	if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
6104 		/* Build and add NSEC. */
6105 		bottom = (seen_ns && !seen_soa) || seen_dname;
6106 		/*
6107 		 * Build a NSEC record except at the origin.
6108 		 */
6109 		if (!dns_name_equal(name, dns_db_origin(db))) {
6110 			CHECK(add_nsec(db, version, name, node, minimum,
6111 				       bottom, diff));
6112 			/* Count a NSEC generation as a signature generation. */
6113 			(*signatures)--;
6114 		}
6115 	}
6116 	result = dns_rdatasetiter_first(iterator);
6117 	while (result == ISC_R_SUCCESS) {
6118 		dns_rdatasetiter_current(iterator, &rdataset);
6119 		if (rdataset.type == dns_rdatatype_soa ||
6120 		    rdataset.type == dns_rdatatype_rrsig)
6121 			goto next_rdataset;
6122 		if (rdataset.type == dns_rdatatype_dnskey) {
6123 			if (!is_ksk && keyset_kskonly)
6124 				goto next_rdataset;
6125 		} else if (is_ksk) {
6126 			/*
6127 			 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
6128 			 */
6129 			if (rdataset.type != dns_rdatatype_cds &&
6130 			    rdataset.type != dns_rdatatype_cdnskey)
6131 				goto next_rdataset;
6132 		}
6133 		if (*delegation &&
6134 		    rdataset.type != dns_rdatatype_ds &&
6135 		    rdataset.type != dns_rdatatype_nsec)
6136 			goto next_rdataset;
6137 		if (signed_with_key(db, node, version, rdataset.type, key))
6138 			goto next_rdataset;
6139 		/* Calculate the signature, creating a RRSIG RDATA. */
6140 		isc_buffer_clear(&buffer);
6141 		CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
6142 				      &expire, mctx, &buffer, &rdata));
6143 		/* Update the database and journal with the RRSIG. */
6144 		/* XXX inefficient - will cause dataset merging */
6145 		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
6146 				    name, rdataset.ttl, &rdata));
6147 		dns_rdata_reset(&rdata);
6148 		(*signatures)--;
6149  next_rdataset:
6150 		dns_rdataset_disassociate(&rdataset);
6151 		result = dns_rdatasetiter_next(iterator);
6152 	}
6153 	if (result == ISC_R_NOMORE)
6154 		result = ISC_R_SUCCESS;
6155 	if (seen_dname)
6156 		*delegation = ISC_TRUE;
6157  failure:
6158 	if (dns_rdataset_isassociated(&rdataset))
6159 		dns_rdataset_disassociate(&rdataset);
6160 	if (iterator != NULL)
6161 		dns_rdatasetiter_destroy(&iterator);
6162 	return (result);
6163 }
6164 
6165 /*
6166  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
6167  */
6168 static isc_result_t
updatesecure(dns_db_t * db,dns_dbversion_t * version,dns_name_t * name,dns_ttl_t minimum,isc_boolean_t update_only,dns_diff_t * diff)6169 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6170 	     dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
6171 {
6172 	isc_result_t result;
6173 	dns_rdataset_t rdataset;
6174 	dns_dbnode_t *node = NULL;
6175 
6176 	CHECK(dns_db_getoriginnode(db, &node));
6177 	if (update_only) {
6178 		dns_rdataset_init(&rdataset);
6179 		result = dns_db_findrdataset(db, node, version,
6180 					     dns_rdatatype_nsec,
6181 					     dns_rdatatype_none,
6182 					     0, &rdataset, NULL);
6183 		if (dns_rdataset_isassociated(&rdataset))
6184 			dns_rdataset_disassociate(&rdataset);
6185 		if (result == ISC_R_NOTFOUND)
6186 			goto success;
6187 		if (result != ISC_R_SUCCESS)
6188 			goto failure;
6189 	}
6190 	CHECK(delete_nsec(db, version, node, name, diff));
6191 	CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
6192  success:
6193 	result = ISC_R_SUCCESS;
6194  failure:
6195 	if (node != NULL)
6196 		dns_db_detachnode(db, &node);
6197 	return (result);
6198 }
6199 
6200 static isc_result_t
updatesignwithkey(dns_zone_t * zone,dns_signing_t * signing,dns_dbversion_t * version,isc_boolean_t build_nsec3,dns_ttl_t minimum,dns_diff_t * diff)6201 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
6202 		  dns_dbversion_t *version, isc_boolean_t build_nsec3,
6203 		  dns_ttl_t minimum, dns_diff_t *diff)
6204 {
6205 	isc_result_t result;
6206 	dns_dbnode_t *node = NULL;
6207 	dns_rdataset_t rdataset;
6208 	dns_rdata_t rdata = DNS_RDATA_INIT;
6209 	unsigned char data[5];
6210 	isc_boolean_t seen_done = ISC_FALSE;
6211 	isc_boolean_t have_rr = ISC_FALSE;
6212 
6213 	dns_rdataset_init(&rdataset);
6214 	result = dns_db_getoriginnode(signing->db, &node);
6215 	if (result != ISC_R_SUCCESS)
6216 		goto failure;
6217 
6218 	result = dns_db_findrdataset(signing->db, node, version,
6219 				     zone->privatetype, dns_rdatatype_none,
6220 				     0, &rdataset, NULL);
6221 	if (result == ISC_R_NOTFOUND) {
6222 		INSIST(!dns_rdataset_isassociated(&rdataset));
6223 		result = ISC_R_SUCCESS;
6224 		goto failure;
6225 	}
6226 	if (result != ISC_R_SUCCESS) {
6227 		INSIST(!dns_rdataset_isassociated(&rdataset));
6228 		goto failure;
6229 	}
6230 	for (result = dns_rdataset_first(&rdataset);
6231 	     result == ISC_R_SUCCESS;
6232 	     result = dns_rdataset_next(&rdataset)) {
6233 		dns_rdataset_current(&rdataset, &rdata);
6234 		/*
6235 		 * If we don't match the algorithm or keyid skip the record.
6236 		 */
6237 		if (rdata.length != 5 ||
6238 		    rdata.data[0] != signing->algorithm ||
6239 		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
6240 		    rdata.data[2] != (signing->keyid & 0xff)) {
6241 			have_rr = ISC_TRUE;
6242 			dns_rdata_reset(&rdata);
6243 			continue;
6244 		}
6245 		/*
6246 		 * We have a match.  If we were signing (!signing->delete)
6247 		 * and we already have a record indicating that we have
6248 		 * finished signing (rdata.data[4] != 0) then keep it.
6249 		 * Otherwise it needs to be deleted as we have removed all
6250 		 * the signatures (signing->delete), so any record indicating
6251 		 * completion is now out of date, or we have finished signing
6252 		 * with the new record so we no longer need to remember that
6253 		 * we need to sign the zone with the matching key across a
6254 		 * nameserver re-start.
6255 		 */
6256 		if (!signing->delete && rdata.data[4] != 0) {
6257 			seen_done = ISC_TRUE;
6258 			have_rr = ISC_TRUE;
6259 		} else
6260 			CHECK(update_one_rr(signing->db, version, diff,
6261 					    DNS_DIFFOP_DEL, &zone->origin,
6262 					    rdataset.ttl, &rdata));
6263 		dns_rdata_reset(&rdata);
6264 	}
6265 	if (result == ISC_R_NOMORE)
6266 		result = ISC_R_SUCCESS;
6267 	if (!signing->delete && !seen_done) {
6268 		/*
6269 		 * If we were signing then we need to indicate that we have
6270 		 * finished signing the zone with this key.  If it is already
6271 		 * there we don't need to add it a second time.
6272 		 */
6273 		data[0] = signing->algorithm;
6274 		data[1] = (signing->keyid >> 8) & 0xff;
6275 		data[2] = signing->keyid & 0xff;
6276 		data[3] = 0;
6277 		data[4] = 1;
6278 		rdata.length = sizeof(data);
6279 		rdata.data = data;
6280 		rdata.type = zone->privatetype;
6281 		rdata.rdclass = dns_db_class(signing->db);
6282 		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
6283 				    &zone->origin, rdataset.ttl, &rdata));
6284 	} else if (!have_rr) {
6285 		dns_name_t *origin = dns_db_origin(signing->db);
6286 		/*
6287 		 * Rebuild the NSEC/NSEC3 record for the origin as we no
6288 		 * longer have any private records.
6289 		 */
6290 		if (build_nsec3)
6291 			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
6292 						  minimum, ISC_FALSE, diff));
6293 		CHECK(updatesecure(signing->db, version, origin, minimum,
6294 				   ISC_TRUE, diff));
6295 	}
6296 
6297  failure:
6298 	if (dns_rdataset_isassociated(&rdataset))
6299 		dns_rdataset_disassociate(&rdataset);
6300 	if (node != NULL)
6301 		dns_db_detachnode(signing->db, &node);
6302 	return (result);
6303 }
6304 
6305 /*
6306  * If 'active' is set then we are not done with the chain yet so only
6307  * delete the nsec3param record which indicates a full chain exists
6308  * (flags == 0).
6309  */
6310 static isc_result_t
fixup_nsec3param(dns_db_t * db,dns_dbversion_t * ver,dns_nsec3chain_t * chain,isc_boolean_t active,dns_rdatatype_t privatetype,dns_diff_t * diff)6311 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
6312 		 isc_boolean_t active, dns_rdatatype_t privatetype,
6313 		 dns_diff_t *diff)
6314 {
6315 	dns_dbnode_t *node = NULL;
6316 	dns_name_t *name = dns_db_origin(db);
6317 	dns_rdata_t rdata = DNS_RDATA_INIT;
6318 	dns_rdataset_t rdataset;
6319 	dns_rdata_nsec3param_t nsec3param;
6320 	isc_result_t result;
6321 	isc_buffer_t buffer;
6322 	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
6323 	dns_ttl_t ttl = 0;
6324 	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
6325 
6326 	dns_rdataset_init(&rdataset);
6327 
6328 	result = dns_db_getoriginnode(db, &node);
6329 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
6330 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6331 				     0, 0, &rdataset, NULL);
6332 	if (result == ISC_R_NOTFOUND)
6333 		goto try_private;
6334 	if (result != ISC_R_SUCCESS)
6335 		goto failure;
6336 
6337 	/*
6338 	 * Preserve the existing ttl.
6339 	 */
6340 	ttl = rdataset.ttl;
6341 
6342 	/*
6343 	 * Delete all NSEC3PARAM records which match that in nsec3chain.
6344 	 */
6345 	for (result = dns_rdataset_first(&rdataset);
6346 	     result == ISC_R_SUCCESS;
6347 	     result = dns_rdataset_next(&rdataset)) {
6348 
6349 		dns_rdataset_current(&rdataset, &rdata);
6350 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6351 
6352 		if (nsec3param.hash != chain->nsec3param.hash ||
6353 		    (active && nsec3param.flags != 0) ||
6354 		    nsec3param.iterations != chain->nsec3param.iterations ||
6355 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
6356 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
6357 			   nsec3param.salt_length)) {
6358 			dns_rdata_reset(&rdata);
6359 			continue;
6360 		}
6361 
6362 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6363 				    name, rdataset.ttl, &rdata));
6364 		dns_rdata_reset(&rdata);
6365 	}
6366 	if (result != ISC_R_NOMORE)
6367 		goto failure;
6368 
6369 	dns_rdataset_disassociate(&rdataset);
6370 
6371  try_private:
6372 
6373 	if (active)
6374 		goto add;
6375 
6376 	result = dns_nsec_nseconly(db, ver, &nseconly);
6377 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
6378 
6379 	/*
6380 	 * Delete all private records which match that in nsec3chain.
6381 	 */
6382 	result = dns_db_findrdataset(db, node, ver, privatetype,
6383 				     0, 0, &rdataset, NULL);
6384 	if (result == ISC_R_NOTFOUND)
6385 		goto add;
6386 	if (result != ISC_R_SUCCESS)
6387 		goto failure;
6388 
6389 	for (result = dns_rdataset_first(&rdataset);
6390 	     result == ISC_R_SUCCESS;
6391 	     result = dns_rdataset_next(&rdataset)) {
6392 		dns_rdata_t private = DNS_RDATA_INIT;
6393 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
6394 
6395 		dns_rdataset_current(&rdataset, &private);
6396 		if (!dns_nsec3param_fromprivate(&private, &rdata,
6397 						buf, sizeof(buf)))
6398 			continue;
6399 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6400 
6401 		if ((!nsec3ok &&
6402 		     (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
6403 		    nsec3param.hash != chain->nsec3param.hash ||
6404 		    nsec3param.iterations != chain->nsec3param.iterations ||
6405 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
6406 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
6407 			   nsec3param.salt_length)) {
6408 			dns_rdata_reset(&rdata);
6409 			continue;
6410 		}
6411 
6412 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6413 				    name, rdataset.ttl, &private));
6414 		dns_rdata_reset(&rdata);
6415 	}
6416 	if (result != ISC_R_NOMORE)
6417 		goto failure;
6418 
6419   add:
6420 	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
6421 		result = ISC_R_SUCCESS;
6422 		goto failure;
6423 	}
6424 
6425 	/*
6426 	 * Add a NSEC3PARAM record which matches that in nsec3chain but
6427 	 * with all flags bits cleared.
6428 	 *
6429 	 * Note: we do not clear chain->nsec3param.flags as this change
6430 	 * may be reversed.
6431 	 */
6432 	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
6433 	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
6434 				   dns_rdatatype_nsec3param,
6435 				   &chain->nsec3param, &buffer));
6436 	rdata.data[1] = 0;	/* Clear flag bits. */
6437 	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
6438 
6439   failure:
6440 	dns_db_detachnode(db, &node);
6441 	if (dns_rdataset_isassociated(&rdataset))
6442 		dns_rdataset_disassociate(&rdataset);
6443 	return (result);
6444 }
6445 
6446 static isc_result_t
delete_nsec(dns_db_t * db,dns_dbversion_t * ver,dns_dbnode_t * node,dns_name_t * name,dns_diff_t * diff)6447 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6448 	    dns_name_t *name, dns_diff_t *diff)
6449 {
6450 	dns_rdataset_t rdataset;
6451 	isc_result_t result;
6452 
6453 	dns_rdataset_init(&rdataset);
6454 
6455 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6456 				     0, 0, &rdataset, NULL);
6457 	if (result == ISC_R_NOTFOUND)
6458 		return (ISC_R_SUCCESS);
6459 	if (result != ISC_R_SUCCESS)
6460 		return (result);
6461 	for (result = dns_rdataset_first(&rdataset);
6462 	     result == ISC_R_SUCCESS;
6463 	     result = dns_rdataset_next(&rdataset)) {
6464 		dns_rdata_t rdata = DNS_RDATA_INIT;
6465 
6466 		dns_rdataset_current(&rdataset, &rdata);
6467 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6468 				    rdataset.ttl, &rdata));
6469 	}
6470 	if (result == ISC_R_NOMORE)
6471 		result = ISC_R_SUCCESS;
6472  failure:
6473 	dns_rdataset_disassociate(&rdataset);
6474 	return (result);
6475 }
6476 
6477 static isc_result_t
deletematchingnsec3(dns_db_t * db,dns_dbversion_t * ver,dns_dbnode_t * node,dns_name_t * name,const dns_rdata_nsec3param_t * param,dns_diff_t * diff)6478 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6479 		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
6480 		    dns_diff_t *diff)
6481 {
6482 	dns_rdataset_t rdataset;
6483 	dns_rdata_nsec3_t nsec3;
6484 	isc_result_t result;
6485 
6486 	dns_rdataset_init(&rdataset);
6487 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
6488 				     0, 0, &rdataset, NULL);
6489 	if (result == ISC_R_NOTFOUND)
6490 		return (ISC_R_SUCCESS);
6491 	if (result != ISC_R_SUCCESS)
6492 		return (result);
6493 
6494 	for (result = dns_rdataset_first(&rdataset);
6495 	     result == ISC_R_SUCCESS;
6496 	     result = dns_rdataset_next(&rdataset)) {
6497 		dns_rdata_t rdata = DNS_RDATA_INIT;
6498 
6499 		dns_rdataset_current(&rdataset, &rdata);
6500 		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
6501 		if (nsec3.hash != param->hash ||
6502 		    nsec3.iterations != param->iterations ||
6503 		    nsec3.salt_length != param->salt_length ||
6504 		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
6505 			continue;
6506 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6507 				    rdataset.ttl, &rdata));
6508 	}
6509 	if (result == ISC_R_NOMORE)
6510 		result = ISC_R_SUCCESS;
6511  failure:
6512 	dns_rdataset_disassociate(&rdataset);
6513 	return (result);
6514 }
6515 
6516 static isc_result_t
need_nsec_chain(dns_db_t * db,dns_dbversion_t * ver,const dns_rdata_nsec3param_t * param,isc_boolean_t * answer)6517 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
6518 		const dns_rdata_nsec3param_t *param,
6519 		isc_boolean_t *answer)
6520 {
6521 	dns_dbnode_t *node = NULL;
6522 	dns_rdata_t rdata = DNS_RDATA_INIT;
6523 	dns_rdata_nsec3param_t myparam;
6524 	dns_rdataset_t rdataset;
6525 	isc_result_t result;
6526 
6527 	*answer = ISC_FALSE;
6528 
6529 	result = dns_db_getoriginnode(db, &node);
6530 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
6531 
6532 	dns_rdataset_init(&rdataset);
6533 
6534 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6535 				     0, 0, &rdataset, NULL);
6536 	if (result == ISC_R_SUCCESS) {
6537 		dns_rdataset_disassociate(&rdataset);
6538 		dns_db_detachnode(db, &node);
6539 		return (result);
6540 	}
6541 	if (result != ISC_R_NOTFOUND) {
6542 		dns_db_detachnode(db, &node);
6543 		return (result);
6544 	}
6545 
6546 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6547 				     0, 0, &rdataset, NULL);
6548 	if (result == ISC_R_NOTFOUND) {
6549 		*answer = ISC_TRUE;
6550 		dns_db_detachnode(db, &node);
6551 		return (ISC_R_SUCCESS);
6552 	}
6553 	if (result != ISC_R_SUCCESS) {
6554 		dns_db_detachnode(db, &node);
6555 		return (result);
6556 	}
6557 
6558 	for (result = dns_rdataset_first(&rdataset);
6559 	     result == ISC_R_SUCCESS;
6560 	     result = dns_rdataset_next(&rdataset)) {
6561 		dns_rdataset_current(&rdataset, &rdata);
6562 		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
6563 		dns_rdata_reset(&rdata);
6564 		/*
6565 		 * Ignore any NSEC3PARAM removals.
6566 		 */
6567 		if (NSEC3REMOVE(myparam.flags))
6568 			continue;
6569 		/*
6570 		 * Ignore the chain that we are in the process of deleting.
6571 		 */
6572 		if (myparam.hash == param->hash &&
6573 		    myparam.iterations == param->iterations &&
6574 		    myparam.salt_length == param->salt_length &&
6575 		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
6576 			continue;
6577 		/*
6578 		 * Found an active NSEC3 chain.
6579 		 */
6580 		break;
6581 	}
6582 	if (result == ISC_R_NOMORE) {
6583 		*answer = ISC_TRUE;
6584 		result = ISC_R_SUCCESS;
6585 	}
6586 
6587  failure:
6588 	if (dns_rdataset_isassociated(&rdataset))
6589 		dns_rdataset_disassociate(&rdataset);
6590 	dns_db_detachnode(db, &node);
6591 	return (result);
6592 }
6593 
6594 static isc_result_t
update_sigs(dns_diff_t * diff,dns_db_t * db,dns_dbversion_t * version,dst_key_t * zone_keys[],unsigned int nkeys,dns_zone_t * zone,isc_stdtime_t inception,isc_stdtime_t expire,isc_stdtime_t now,isc_boolean_t check_ksk,isc_boolean_t keyset_kskonly,zonediff_t * zonediff)6595 update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
6596 	    dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
6597 	    isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
6598 	    isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
6599 	    zonediff_t *zonediff)
6600 {
6601 	dns_difftuple_t *tuple;
6602 	isc_result_t result;
6603 
6604 	for (tuple = ISC_LIST_HEAD(diff->tuples);
6605 	     tuple != NULL;
6606 	     tuple = ISC_LIST_HEAD(diff->tuples)) {
6607 		result = del_sigs(zone, db, version, &tuple->name,
6608 				  tuple->rdata.type, zonediff,
6609 				  zone_keys, nkeys, now, ISC_FALSE);
6610 		if (result != ISC_R_SUCCESS) {
6611 			dns_zone_log(zone, ISC_LOG_ERROR,
6612 				     "update_sigs:del_sigs -> %s",
6613 				     dns_result_totext(result));
6614 			return (result);
6615 		}
6616 		result = add_sigs(db, version, &tuple->name,
6617 				  tuple->rdata.type, zonediff->diff,
6618 				  zone_keys, nkeys, zone->mctx, inception,
6619 				  expire, check_ksk, keyset_kskonly);
6620 		if (result != ISC_R_SUCCESS) {
6621 			dns_zone_log(zone, ISC_LOG_ERROR,
6622 				     "update_sigs:add_sigs -> %s",
6623 				     dns_result_totext(result));
6624 			return (result);
6625 		}
6626 
6627 		do {
6628 			dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
6629 			while (next != NULL &&
6630 			       (tuple->rdata.type != next->rdata.type ||
6631 				!dns_name_equal(&tuple->name, &next->name)))
6632 				next = ISC_LIST_NEXT(next, link);
6633 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
6634 			dns_diff_appendminimal(zonediff->diff, &tuple);
6635 			INSIST(tuple == NULL);
6636 			tuple = next;
6637 		} while (tuple != NULL);
6638 	}
6639 	return (ISC_R_SUCCESS);
6640 }
6641 
6642 /*
6643  * Incrementally build and sign a new NSEC3 chain using the parameters
6644  * requested.
6645  */
6646 static void
zone_nsec3chain(dns_zone_t * zone)6647 zone_nsec3chain(dns_zone_t *zone) {
6648 	const char *me = "zone_nsec3chain";
6649 	dns_db_t *db = NULL;
6650 	dns_dbnode_t *node = NULL;
6651 	dns_dbversion_t *version = NULL;
6652 	dns_diff_t _sig_diff;
6653 	dns_diff_t nsec_diff;
6654 	dns_diff_t nsec3_diff;
6655 	dns_diff_t param_diff;
6656 	zonediff_t zonediff;
6657 	dns_fixedname_t fixed;
6658 	dns_fixedname_t nextfixed;
6659 	dns_name_t *name, *nextname;
6660 	dns_rdataset_t rdataset;
6661 	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
6662 	dns_nsec3chainlist_t cleanup;
6663 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6664 	isc_int32_t signatures;
6665 	isc_boolean_t check_ksk, keyset_kskonly;
6666 	isc_boolean_t delegation;
6667 	isc_boolean_t first;
6668 	isc_result_t result;
6669 	isc_stdtime_t now, inception, soaexpire, expire;
6670 	isc_uint32_t jitter;
6671 	unsigned int i;
6672 	unsigned int nkeys = 0;
6673 	isc_uint32_t nodes;
6674 	isc_boolean_t unsecure = ISC_FALSE;
6675 	isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
6676 	isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
6677 	dns_rdatasetiter_t *iterator = NULL;
6678 	isc_boolean_t buildnsecchain;
6679 	isc_boolean_t updatensec = ISC_FALSE;
6680 	dns_rdatatype_t privatetype = zone->privatetype;
6681 
6682 	ENTER;
6683 
6684 	dns_rdataset_init(&rdataset);
6685 	dns_fixedname_init(&fixed);
6686 	name = dns_fixedname_name(&fixed);
6687 	dns_fixedname_init(&nextfixed);
6688 	nextname = dns_fixedname_name(&nextfixed);
6689 	dns_diff_init(zone->mctx, &param_diff);
6690 	dns_diff_init(zone->mctx, &nsec3_diff);
6691 	dns_diff_init(zone->mctx, &nsec_diff);
6692 	dns_diff_init(zone->mctx, &_sig_diff);
6693 	zonediff_init(&zonediff, &_sig_diff);
6694 	ISC_LIST_INIT(cleanup);
6695 
6696 	/*
6697 	 * Updates are disabled.  Pause for 5 minutes.
6698 	 */
6699 	if (zone->update_disabled) {
6700 		result = ISC_R_FAILURE;
6701 		goto failure;
6702 	}
6703 
6704 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6705 	dns_db_attach(zone->db, &db);
6706 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6707 
6708 	result = dns_db_newversion(db, &version);
6709 	if (result != ISC_R_SUCCESS) {
6710 		dns_zone_log(zone, ISC_LOG_ERROR,
6711 			     "zone_nsec3chain:dns_db_newversion -> %s",
6712 			     dns_result_totext(result));
6713 		goto failure;
6714 	}
6715 
6716 	result = find_zone_keys(zone, db, version, zone->mctx,
6717 				DNS_MAXZONEKEYS, zone_keys, &nkeys);
6718 	if (result != ISC_R_SUCCESS) {
6719 		dns_zone_log(zone, ISC_LOG_ERROR,
6720 			     "zone_nsec3chain:find_zone_keys -> %s",
6721 			     dns_result_totext(result));
6722 		goto failure;
6723 	}
6724 
6725 	isc_stdtime_get(&now);
6726 	inception = now - 3600;	/* Allow for clock skew. */
6727 	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6728 
6729 	/*
6730 	 * Spread out signatures over time if they happen to be
6731 	 * clumped.  We don't do this for each add_sigs() call as
6732 	 * we still want some clustering to occur.
6733 	 */
6734 	isc_random_get(&jitter);
6735 	expire = soaexpire - jitter % 3600;
6736 
6737 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6738 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6739 
6740 	/*
6741 	 * We keep pulling nodes off each iterator in turn until
6742 	 * we have no more nodes to pull off or we reach the limits
6743 	 * for this quantum.
6744 	 */
6745 	nodes = zone->nodes;
6746 	signatures = zone->signatures;
6747 	LOCK_ZONE(zone);
6748 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6749 	UNLOCK_ZONE(zone);
6750 	first = ISC_TRUE;
6751 
6752 	if (nsec3chain != NULL)
6753 		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6754 	/*
6755 	 * Generate new NSEC3 chains first.
6756 	 */
6757 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6758 		LOCK_ZONE(zone);
6759 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6760 
6761 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6762 		if (nsec3chain->done || nsec3chain->db != zone->db) {
6763 			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
6764 			ISC_LIST_APPEND(cleanup, nsec3chain, link);
6765 		}
6766 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6767 		UNLOCK_ZONE(zone);
6768 		if (ISC_LIST_TAIL(cleanup) == nsec3chain)
6769 			goto next_addchain;
6770 
6771 		/*
6772 		 * Possible future db.
6773 		 */
6774 		if (nsec3chain->db != db) {
6775 			goto next_addchain;
6776 		}
6777 
6778 		if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
6779 			goto next_addchain;
6780 
6781 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6782 
6783 		if (nsec3chain->delete_nsec) {
6784 			delegation = ISC_FALSE;
6785 			dns_dbiterator_pause(nsec3chain->dbiterator);
6786 			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
6787 			goto next_addnode;
6788 		}
6789 		/*
6790 		 * On the first pass we need to check if the current node
6791 		 * has not been obscured.
6792 		 */
6793 		delegation = ISC_FALSE;
6794 		unsecure = ISC_FALSE;
6795 		if (first) {
6796 			dns_fixedname_t ffound;
6797 			dns_name_t *found;
6798 			dns_fixedname_init(&ffound);
6799 			found = dns_fixedname_name(&ffound);
6800 			result = dns_db_find(db, name, version,
6801 					     dns_rdatatype_soa,
6802 					     DNS_DBFIND_NOWILD, 0, NULL, found,
6803 					     NULL, NULL);
6804 			if ((result == DNS_R_DELEGATION ||
6805 			    result == DNS_R_DNAME) &&
6806 			    !dns_name_equal(name, found)) {
6807 				/*
6808 				 * Remember the obscuring name so that
6809 				 * we skip all obscured names.
6810 				 */
6811 				dns_name_copy(found, name, NULL);
6812 				delegation = ISC_TRUE;
6813 				goto next_addnode;
6814 			}
6815 		}
6816 
6817 		/*
6818 		 * Check to see if this is a bottom of zone node.
6819 		 */
6820 		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6821 		if (result == ISC_R_NOTFOUND)	/* Empty node? */
6822 			goto next_addnode;
6823 		if (result != ISC_R_SUCCESS)
6824 			goto failure;
6825 
6826 		seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
6827 			ISC_FALSE;
6828 		for (result = dns_rdatasetiter_first(iterator);
6829 		     result == ISC_R_SUCCESS;
6830 		     result = dns_rdatasetiter_next(iterator)) {
6831 			dns_rdatasetiter_current(iterator, &rdataset);
6832 			INSIST(rdataset.type != dns_rdatatype_nsec3);
6833 			if (rdataset.type == dns_rdatatype_soa)
6834 				seen_soa = ISC_TRUE;
6835 			else if (rdataset.type == dns_rdatatype_ns)
6836 				seen_ns = ISC_TRUE;
6837 			else if (rdataset.type == dns_rdatatype_dname)
6838 				seen_dname = ISC_TRUE;
6839 			else if (rdataset.type == dns_rdatatype_ds)
6840 				seen_ds = ISC_TRUE;
6841 			else if (rdataset.type == dns_rdatatype_nsec)
6842 				seen_nsec = ISC_TRUE;
6843 			dns_rdataset_disassociate(&rdataset);
6844 		}
6845 		dns_rdatasetiter_destroy(&iterator);
6846 		/*
6847 		 * Is there a NSEC chain than needs to be cleaned up?
6848 		 */
6849 		if (seen_nsec)
6850 			nsec3chain->seen_nsec = ISC_TRUE;
6851 		if (seen_ns && !seen_soa && !seen_ds)
6852 			unsecure = ISC_TRUE;
6853 		if ((seen_ns && !seen_soa) || seen_dname)
6854 			delegation = ISC_TRUE;
6855 
6856 		/*
6857 		 * Process one node.
6858 		 */
6859 		dns_dbiterator_pause(nsec3chain->dbiterator);
6860 		result = dns_nsec3_addnsec3(db, version, name,
6861 					    &nsec3chain->nsec3param,
6862 					    zone->minimum, unsecure,
6863 					    &nsec3_diff);
6864 		if (result != ISC_R_SUCCESS) {
6865 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6866 				     "dns_nsec3_addnsec3 -> %s",
6867 				     dns_result_totext(result));
6868 			goto failure;
6869 		}
6870 
6871 		/*
6872 		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
6873 		 * two signatures.  Additionally there will, in general, be
6874 		 * two signature generated below.
6875 		 *
6876 		 * If we are only changing the optout flag the cost is half
6877 		 * that of the cost of generating a completely new chain.
6878 		 */
6879 		signatures -= 4;
6880 
6881 		/*
6882 		 * Go onto next node.
6883 		 */
6884  next_addnode:
6885 		first = ISC_FALSE;
6886 		dns_db_detachnode(db, &node);
6887 		do {
6888 			result = dns_dbiterator_next(nsec3chain->dbiterator);
6889 
6890 			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
6891 				dns_dbiterator_pause(nsec3chain->dbiterator);
6892 				CHECK(fixup_nsec3param(db, version, nsec3chain,
6893 						       ISC_FALSE, privatetype,
6894 						       &param_diff));
6895 				LOCK_ZONE(zone);
6896 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6897 						link);
6898 				UNLOCK_ZONE(zone);
6899 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
6900 				goto next_addchain;
6901 			}
6902 			if (result == ISC_R_NOMORE) {
6903 				dns_dbiterator_pause(nsec3chain->dbiterator);
6904 				if (nsec3chain->seen_nsec) {
6905 					CHECK(fixup_nsec3param(db, version,
6906 							       nsec3chain,
6907 							       ISC_TRUE,
6908 							       privatetype,
6909 							       &param_diff));
6910 					nsec3chain->delete_nsec = ISC_TRUE;
6911 					goto same_addchain;
6912 				}
6913 				CHECK(fixup_nsec3param(db, version, nsec3chain,
6914 						       ISC_FALSE, privatetype,
6915 						       &param_diff));
6916 				LOCK_ZONE(zone);
6917 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6918 						link);
6919 				UNLOCK_ZONE(zone);
6920 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
6921 				goto next_addchain;
6922 			} else if (result != ISC_R_SUCCESS) {
6923 				dns_zone_log(zone, ISC_LOG_ERROR,
6924 					     "zone_nsec3chain:"
6925 					     "dns_dbiterator_next -> %s",
6926 					     dns_result_totext(result));
6927 				goto failure;
6928 			} else if (delegation) {
6929 				dns_dbiterator_current(nsec3chain->dbiterator,
6930 						       &node, nextname);
6931 				dns_db_detachnode(db, &node);
6932 				if (!dns_name_issubdomain(nextname, name))
6933 					break;
6934 			} else
6935 				break;
6936 		} while (1);
6937 		continue;
6938 
6939  same_addchain:
6940 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6941 		first = ISC_TRUE;
6942 		continue;
6943 
6944  next_addchain:
6945 		dns_dbiterator_pause(nsec3chain->dbiterator);
6946 		nsec3chain = nextnsec3chain;
6947 		first = ISC_TRUE;
6948 		if (nsec3chain != NULL)
6949 			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6950 	}
6951 
6952 	/*
6953 	 * Process removals.
6954 	 */
6955 	LOCK_ZONE(zone);
6956 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6957 	UNLOCK_ZONE(zone);
6958 	first = ISC_TRUE;
6959 	buildnsecchain = ISC_FALSE;
6960 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6961 		LOCK_ZONE(zone);
6962 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6963 		UNLOCK_ZONE(zone);
6964 
6965 		if (nsec3chain->db != db)
6966 			goto next_removechain;
6967 
6968 		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
6969 			goto next_removechain;
6970 
6971 		/*
6972 		 * Work out if we need to build a NSEC chain as a consequence
6973 		 * of removing this NSEC3 chain.
6974 		 */
6975 		if (first && !updatensec &&
6976 		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
6977 		{
6978 			result = need_nsec_chain(db, version,
6979 						 &nsec3chain->nsec3param,
6980 						 &buildnsecchain);
6981 			if (result != ISC_R_SUCCESS) {
6982 				dns_zone_log(zone, ISC_LOG_ERROR,
6983 					     "zone_nsec3chain:"
6984 					     "need_nsec_chain -> %s",
6985 					     dns_result_totext(result));
6986 				goto failure;
6987 			}
6988 		}
6989 
6990 		if (first)
6991 			dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
6992 				     "buildnsecchain = %u\n", buildnsecchain);
6993 
6994 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6995 		delegation = ISC_FALSE;
6996 
6997 		if (!buildnsecchain) {
6998 			/*
6999 			 * Delete the NSECPARAM record that matches this chain.
7000 			 */
7001 			if (first) {
7002 				result = fixup_nsec3param(db, version,
7003 							  nsec3chain,
7004 							  ISC_TRUE, privatetype,
7005 							  &param_diff);
7006 				if (result != ISC_R_SUCCESS) {
7007 					dns_zone_log(zone, ISC_LOG_ERROR,
7008 						     "zone_nsec3chain:"
7009 						     "fixup_nsec3param -> %s",
7010 						     dns_result_totext(result));
7011 					goto failure;
7012 				}
7013 			}
7014 
7015 			/*
7016 			 *  Delete the NSEC3 records.
7017 			 */
7018 			result = deletematchingnsec3(db, version, node, name,
7019 						     &nsec3chain->nsec3param,
7020 						     &nsec3_diff);
7021 			if (result != ISC_R_SUCCESS) {
7022 				dns_zone_log(zone, ISC_LOG_ERROR,
7023 					     "zone_nsec3chain:"
7024 					     "deletematchingnsec3 -> %s",
7025 					     dns_result_totext(result));
7026 				goto failure;
7027 			}
7028 			goto next_removenode;
7029 		}
7030 
7031 		if (first) {
7032 			dns_fixedname_t ffound;
7033 			dns_name_t *found;
7034 			dns_fixedname_init(&ffound);
7035 			found = dns_fixedname_name(&ffound);
7036 			result = dns_db_find(db, name, version,
7037 					     dns_rdatatype_soa,
7038 					     DNS_DBFIND_NOWILD, 0, NULL, found,
7039 					     NULL, NULL);
7040 			if ((result == DNS_R_DELEGATION ||
7041 			     result == DNS_R_DNAME) &&
7042 			    !dns_name_equal(name, found)) {
7043 				/*
7044 				 * Remember the obscuring name so that
7045 				 * we skip all obscured names.
7046 				 */
7047 				dns_name_copy(found, name, NULL);
7048 				delegation = ISC_TRUE;
7049 				goto next_removenode;
7050 			}
7051 		}
7052 
7053 		/*
7054 		 * Check to see if this is a bottom of zone node.
7055 		 */
7056 		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7057 		if (result == ISC_R_NOTFOUND)	/* Empty node? */
7058 			goto next_removenode;
7059 		if (result != ISC_R_SUCCESS)
7060 			goto failure;
7061 
7062 		seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
7063 			seen_rr = ISC_FALSE;
7064 		for (result = dns_rdatasetiter_first(iterator);
7065 		     result == ISC_R_SUCCESS;
7066 		     result = dns_rdatasetiter_next(iterator)) {
7067 			dns_rdatasetiter_current(iterator, &rdataset);
7068 			if (rdataset.type == dns_rdatatype_soa)
7069 				seen_soa = ISC_TRUE;
7070 			else if (rdataset.type == dns_rdatatype_ns)
7071 				seen_ns = ISC_TRUE;
7072 			else if (rdataset.type == dns_rdatatype_dname)
7073 				seen_dname = ISC_TRUE;
7074 			else if (rdataset.type == dns_rdatatype_nsec)
7075 				seen_nsec = ISC_TRUE;
7076 			else if (rdataset.type == dns_rdatatype_nsec3)
7077 				seen_nsec3 = ISC_TRUE;
7078 			if (rdataset.type != dns_rdatatype_rrsig)
7079 				seen_rr = ISC_TRUE;
7080 			dns_rdataset_disassociate(&rdataset);
7081 		}
7082 		dns_rdatasetiter_destroy(&iterator);
7083 
7084 		if (!seen_rr || seen_nsec3 || seen_nsec)
7085 			goto next_removenode;
7086 		if ((seen_ns && !seen_soa) || seen_dname)
7087 			delegation = ISC_TRUE;
7088 
7089 		/*
7090 		 * Add a NSEC record except at the origin.
7091 		 */
7092 		if (!dns_name_equal(name, dns_db_origin(db))) {
7093 			dns_dbiterator_pause(nsec3chain->dbiterator);
7094 			CHECK(add_nsec(db, version, name, node, zone->minimum,
7095 				       delegation, &nsec_diff));
7096 		}
7097 
7098  next_removenode:
7099 		first = ISC_FALSE;
7100 		dns_db_detachnode(db, &node);
7101 		do {
7102 			result = dns_dbiterator_next(nsec3chain->dbiterator);
7103 			if (result == ISC_R_NOMORE && buildnsecchain) {
7104 				/*
7105 				 * The NSEC chain should now be built.
7106 				 * We can now remove the NSEC3 chain.
7107 				 */
7108 				updatensec = ISC_TRUE;
7109 				goto same_removechain;
7110 			}
7111 			if (result == ISC_R_NOMORE) {
7112 				LOCK_ZONE(zone);
7113 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7114 						link);
7115 				UNLOCK_ZONE(zone);
7116 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
7117 				dns_dbiterator_pause(nsec3chain->dbiterator);
7118 				result = fixup_nsec3param(db, version,
7119 							  nsec3chain, ISC_FALSE,
7120 							  privatetype,
7121 							  &param_diff);
7122 				if (result != ISC_R_SUCCESS) {
7123 					dns_zone_log(zone, ISC_LOG_ERROR,
7124 						     "zone_nsec3chain:"
7125 						     "fixup_nsec3param -> %s",
7126 						     dns_result_totext(result));
7127 					goto failure;
7128 				}
7129 				goto next_removechain;
7130 			} else if (result != ISC_R_SUCCESS) {
7131 				dns_zone_log(zone, ISC_LOG_ERROR,
7132 					     "zone_nsec3chain:"
7133 					     "dns_dbiterator_next -> %s",
7134 					     dns_result_totext(result));
7135 				goto failure;
7136 			} else if (delegation) {
7137 				dns_dbiterator_current(nsec3chain->dbiterator,
7138 						       &node, nextname);
7139 				dns_db_detachnode(db, &node);
7140 				if (!dns_name_issubdomain(nextname, name))
7141 					break;
7142 			} else
7143 				break;
7144 		} while (1);
7145 		continue;
7146 
7147  same_removechain:
7148 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
7149 		buildnsecchain = ISC_FALSE;
7150 		first = ISC_TRUE;
7151 		continue;
7152 
7153  next_removechain:
7154 		dns_dbiterator_pause(nsec3chain->dbiterator);
7155 		nsec3chain = nextnsec3chain;
7156 		first = ISC_TRUE;
7157 	}
7158 
7159 	/*
7160 	 * We may need to update the NSEC/NSEC3 records for the zone apex.
7161 	 */
7162 	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
7163 		isc_boolean_t rebuild_nsec = ISC_FALSE,
7164 			      rebuild_nsec3 = ISC_FALSE;
7165 		result = dns_db_getoriginnode(db, &node);
7166 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
7167 		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7168 		if (result != ISC_R_SUCCESS) {
7169 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7170 				     "dns_db_allrdatasets -> %s",
7171 				     dns_result_totext(result));
7172 			goto failure;
7173 		}
7174 		for (result = dns_rdatasetiter_first(iterator);
7175 		     result == ISC_R_SUCCESS;
7176 		     result = dns_rdatasetiter_next(iterator)) {
7177 			dns_rdatasetiter_current(iterator, &rdataset);
7178 			if (rdataset.type == dns_rdatatype_nsec)
7179 				rebuild_nsec = ISC_TRUE;
7180 			if (rdataset.type == dns_rdatatype_nsec3param)
7181 				rebuild_nsec3 = ISC_TRUE;
7182 			dns_rdataset_disassociate(&rdataset);
7183 		}
7184 		dns_rdatasetiter_destroy(&iterator);
7185 		dns_db_detachnode(db, &node);
7186 
7187 		if (rebuild_nsec) {
7188 			if (nsec3chain != NULL)
7189 				dns_dbiterator_pause(nsec3chain->dbiterator);
7190 
7191 			result = updatesecure(db, version, &zone->origin,
7192 					      zone->minimum, ISC_TRUE,
7193 					      &nsec_diff);
7194 			if (result != ISC_R_SUCCESS) {
7195 				dns_zone_log(zone, ISC_LOG_ERROR,
7196 					     "zone_nsec3chain:"
7197 					     "updatesecure -> %s",
7198 					     dns_result_totext(result));
7199 				goto failure;
7200 			}
7201 		}
7202 
7203 		if (rebuild_nsec3) {
7204 			if (nsec3chain != NULL)
7205 				dns_dbiterator_pause(nsec3chain->dbiterator);
7206 
7207 			result = dns_nsec3_addnsec3s(db, version,
7208 						     dns_db_origin(db),
7209 						     zone->minimum, ISC_FALSE,
7210 						     &nsec3_diff);
7211 			if (result != ISC_R_SUCCESS) {
7212 				dns_zone_log(zone, ISC_LOG_ERROR,
7213 					     "zone_nsec3chain:"
7214 					     "dns_nsec3_addnsec3s -> %s",
7215 					     dns_result_totext(result));
7216 				goto failure;
7217 			}
7218 		}
7219 	}
7220 
7221 	if (nsec3chain != NULL)
7222 		dns_dbiterator_pause(nsec3chain->dbiterator);
7223 
7224 	/*
7225 	 * Add / update signatures for the NSEC3 records.
7226 	 */
7227 	if (nsec3chain != NULL)
7228 		dns_dbiterator_pause(nsec3chain->dbiterator);
7229 	result = update_sigs(&nsec3_diff, db, version, zone_keys,
7230 			     nkeys, zone, inception, expire, now,
7231 			     check_ksk, keyset_kskonly, &zonediff);
7232 	if (result != ISC_R_SUCCESS) {
7233 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7234 			     "update_sigs -> %s", dns_result_totext(result));
7235 		goto failure;
7236 	}
7237 
7238 	/*
7239 	 * We have changed the NSEC3PARAM or private RRsets
7240 	 * above so we need to update the signatures.
7241 	 */
7242 	result = update_sigs(&param_diff, db, version, zone_keys,
7243 			     nkeys, zone, inception, expire, now,
7244 			     check_ksk, keyset_kskonly, &zonediff);
7245 	if (result != ISC_R_SUCCESS) {
7246 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7247 			     "update_sigs -> %s", dns_result_totext(result));
7248 		goto failure;
7249 	}
7250 
7251 	if (updatensec) {
7252 		result = updatesecure(db, version, &zone->origin,
7253 				      zone->minimum, ISC_FALSE, &nsec_diff);
7254 		if (result != ISC_R_SUCCESS) {
7255 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7256 				     "updatesecure -> %s",
7257 				     dns_result_totext(result));
7258 			goto failure;
7259 		}
7260 	}
7261 
7262 	result = update_sigs(&nsec_diff, db, version, zone_keys,
7263 			     nkeys, zone, inception, expire, now,
7264 			     check_ksk, keyset_kskonly, &zonediff);
7265 	if (result != ISC_R_SUCCESS) {
7266 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7267 			     "update_sigs -> %s", dns_result_totext(result));
7268 		goto failure;
7269 	}
7270 
7271 	/*
7272 	 * If we made no effective changes to the zone then we can just
7273 	 * cleanup otherwise we need to increment the serial.
7274 	 */
7275 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7276 		/*
7277 		 * No need to call dns_db_closeversion() here as it is
7278 		 * called with commit = ISC_TRUE below.
7279 		 */
7280 		goto done;
7281 	}
7282 
7283 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7284 			  &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7285 	if (result != ISC_R_SUCCESS) {
7286 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7287 			     "del_sigs -> %s", dns_result_totext(result));
7288 		goto failure;
7289 	}
7290 
7291 	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7292 				   zone->updatemethod);
7293 	if (result != ISC_R_SUCCESS) {
7294 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7295 			     "update_soa_serial -> %s",
7296 			     dns_result_totext(result));
7297 		goto failure;
7298 	}
7299 
7300 	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7301 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
7302 			  inception, soaexpire, check_ksk, keyset_kskonly);
7303 	if (result != ISC_R_SUCCESS) {
7304 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7305 			     "add_sigs -> %s", dns_result_totext(result));
7306 		goto failure;
7307 	}
7308 
7309 	/* Write changes to journal file. */
7310 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
7311 
7312 	LOCK_ZONE(zone);
7313 	zone_needdump(zone, DNS_DUMP_DELAY);
7314 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7315 	UNLOCK_ZONE(zone);
7316 
7317  done:
7318 	/*
7319 	 * Pause all iterators so that dns_db_closeversion() can succeed.
7320 	 */
7321 	LOCK_ZONE(zone);
7322 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7323 	     nsec3chain != NULL;
7324 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7325 		dns_dbiterator_pause(nsec3chain->dbiterator);
7326 	UNLOCK_ZONE(zone);
7327 
7328 	/*
7329 	 * Everything has succeeded. Commit the changes.
7330 	 * Unconditionally commit as zonediff.offline not checked above.
7331 	 */
7332 	dns_db_closeversion(db, &version, ISC_TRUE);
7333 
7334 	/*
7335 	 * Everything succeeded so we can clean these up now.
7336 	 */
7337 	nsec3chain = ISC_LIST_HEAD(cleanup);
7338 	while (nsec3chain != NULL) {
7339 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7340 		dns_db_detach(&nsec3chain->db);
7341 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
7342 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7343 		nsec3chain = ISC_LIST_HEAD(cleanup);
7344 	}
7345 
7346 	set_resigntime(zone);
7347 
7348  failure:
7349 	if (result != ISC_R_SUCCESS)
7350 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
7351 			     dns_result_totext(result));
7352 	/*
7353 	 * On error roll back the current nsec3chain.
7354 	 */
7355 	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
7356 		if (nsec3chain->done) {
7357 			dns_db_detach(&nsec3chain->db);
7358 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
7359 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7360 		} else {
7361 			result = dns_dbiterator_first(nsec3chain->dbiterator);
7362 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
7363 			dns_dbiterator_pause(nsec3chain->dbiterator);
7364 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7365 		}
7366 	}
7367 
7368 	/*
7369 	 * Rollback the cleanup list.
7370 	 */
7371 	nsec3chain = ISC_LIST_TAIL(cleanup);
7372 	while (nsec3chain != NULL) {
7373 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7374 		if (nsec3chain->done) {
7375 			dns_db_detach(&nsec3chain->db);
7376 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
7377 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7378 		} else {
7379 			LOCK_ZONE(zone);
7380 			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
7381 			UNLOCK_ZONE(zone);
7382 			result = dns_dbiterator_first(nsec3chain->dbiterator);
7383 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
7384 			dns_dbiterator_pause(nsec3chain->dbiterator);
7385 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7386 		}
7387 		nsec3chain = ISC_LIST_TAIL(cleanup);
7388 	}
7389 
7390 	LOCK_ZONE(zone);
7391 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7392 	     nsec3chain != NULL;
7393 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7394 		dns_dbiterator_pause(nsec3chain->dbiterator);
7395 	UNLOCK_ZONE(zone);
7396 
7397 	dns_diff_clear(&param_diff);
7398 	dns_diff_clear(&nsec3_diff);
7399 	dns_diff_clear(&nsec_diff);
7400 	dns_diff_clear(&_sig_diff);
7401 
7402 	if (iterator != NULL)
7403 		dns_rdatasetiter_destroy(&iterator);
7404 
7405 	for (i = 0; i < nkeys; i++)
7406 		dst_key_free(&zone_keys[i]);
7407 
7408 	if (node != NULL)
7409 		dns_db_detachnode(db, &node);
7410 	if (version != NULL) {
7411 		dns_db_closeversion(db, &version, ISC_FALSE);
7412 		dns_db_detach(&db);
7413 	} else if (db != NULL)
7414 		dns_db_detach(&db);
7415 
7416 	LOCK_ZONE(zone);
7417 	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
7418 		isc_interval_t interval;
7419 		if (zone->update_disabled || result != ISC_R_SUCCESS)
7420 			isc_interval_set(&interval, 60, 0);	  /* 1 minute */
7421 		else
7422 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
7423 		isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
7424 	} else
7425 		isc_time_settoepoch(&zone->nsec3chaintime);
7426 	UNLOCK_ZONE(zone);
7427 
7428 	INSIST(version == NULL);
7429 }
7430 
7431 static isc_result_t
del_sig(dns_db_t * db,dns_dbversion_t * version,dns_name_t * name,dns_dbnode_t * node,unsigned int nkeys,dns_secalg_t algorithm,isc_uint16_t keyid,dns_diff_t * diff)7432 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7433 	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
7434 	isc_uint16_t keyid, dns_diff_t *diff)
7435 {
7436 	dns_rdata_rrsig_t rrsig;
7437 	dns_rdataset_t rdataset;
7438 	dns_rdatasetiter_t *iterator = NULL;
7439 	isc_result_t result;
7440 
7441 	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7442 	if (result != ISC_R_SUCCESS) {
7443 		if (result == ISC_R_NOTFOUND)
7444 			result = ISC_R_SUCCESS;
7445 		return (result);
7446 	}
7447 
7448 	dns_rdataset_init(&rdataset);
7449 	for (result = dns_rdatasetiter_first(iterator);
7450 	     result == ISC_R_SUCCESS;
7451 	     result = dns_rdatasetiter_next(iterator)) {
7452 		dns_rdatasetiter_current(iterator, &rdataset);
7453 		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
7454 			for (result = dns_rdataset_first(&rdataset);
7455 			     result == ISC_R_SUCCESS;
7456 			     result = dns_rdataset_next(&rdataset)) {
7457 				dns_rdata_t rdata = DNS_RDATA_INIT;
7458 				dns_rdataset_current(&rdataset, &rdata);
7459 				CHECK(update_one_rr(db, version, diff,
7460 						    DNS_DIFFOP_DEL, name,
7461 						    rdataset.ttl, &rdata));
7462 			}
7463 			if (result != ISC_R_NOMORE)
7464 				goto failure;
7465 			dns_rdataset_disassociate(&rdataset);
7466 			continue;
7467 		}
7468 		if (rdataset.type != dns_rdatatype_rrsig) {
7469 			dns_rdataset_disassociate(&rdataset);
7470 			continue;
7471 		}
7472 		for (result = dns_rdataset_first(&rdataset);
7473 		     result == ISC_R_SUCCESS;
7474 		     result = dns_rdataset_next(&rdataset)) {
7475 			dns_rdata_t rdata = DNS_RDATA_INIT;
7476 			dns_rdataset_current(&rdataset, &rdata);
7477 			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
7478 			if (rrsig.algorithm != algorithm ||
7479 			    rrsig.keyid != keyid)
7480 				continue;
7481 			CHECK(update_one_rr(db, version, diff,
7482 					    DNS_DIFFOP_DELRESIGN, name,
7483 					    rdataset.ttl, &rdata));
7484 		}
7485 		dns_rdataset_disassociate(&rdataset);
7486 		if (result != ISC_R_NOMORE)
7487 			break;
7488 	}
7489 	if (result == ISC_R_NOMORE)
7490 		result = ISC_R_SUCCESS;
7491  failure:
7492 	if (dns_rdataset_isassociated(&rdataset))
7493 		dns_rdataset_disassociate(&rdataset);
7494 	dns_rdatasetiter_destroy(&iterator);
7495 	return (result);
7496 }
7497 
7498 /*
7499  * Incrementally sign the zone using the keys requested.
7500  * Builds the NSEC chain if required.
7501  */
7502 static void
zone_sign(dns_zone_t * zone)7503 zone_sign(dns_zone_t *zone) {
7504 	const char *me = "zone_sign";
7505 	dns_db_t *db = NULL;
7506 	dns_dbnode_t *node = NULL;
7507 	dns_dbversion_t *version = NULL;
7508 	dns_diff_t _sig_diff;
7509 	dns_diff_t post_diff;
7510 	zonediff_t zonediff;
7511 	dns_fixedname_t fixed;
7512 	dns_fixedname_t nextfixed;
7513 	dns_name_t *name, *nextname;
7514 	dns_rdataset_t rdataset;
7515 	dns_signing_t *signing, *nextsigning;
7516 	dns_signinglist_t cleanup;
7517 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7518 	isc_int32_t signatures;
7519 	isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
7520 	isc_boolean_t commit = ISC_FALSE;
7521 	isc_boolean_t delegation;
7522 	isc_boolean_t build_nsec = ISC_FALSE;
7523 	isc_boolean_t build_nsec3 = ISC_FALSE;
7524 	isc_boolean_t first;
7525 	isc_result_t result;
7526 	isc_stdtime_t now, inception, soaexpire, expire;
7527 	isc_uint32_t jitter;
7528 	unsigned int i, j;
7529 	unsigned int nkeys = 0;
7530 	isc_uint32_t nodes;
7531 
7532 	ENTER;
7533 
7534 	dns_rdataset_init(&rdataset);
7535 	dns_fixedname_init(&fixed);
7536 	name = dns_fixedname_name(&fixed);
7537 	dns_fixedname_init(&nextfixed);
7538 	nextname = dns_fixedname_name(&nextfixed);
7539 	dns_diff_init(zone->mctx, &_sig_diff);
7540 	dns_diff_init(zone->mctx, &post_diff);
7541 	zonediff_init(&zonediff, &_sig_diff);
7542 	ISC_LIST_INIT(cleanup);
7543 
7544 	/*
7545 	 * Updates are disabled.  Pause for 5 minutes.
7546 	 */
7547 	if (zone->update_disabled) {
7548 		result = ISC_R_FAILURE;
7549 		goto failure;
7550 	}
7551 
7552 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7553 	if (zone->db != NULL)
7554 		dns_db_attach(zone->db, &db);
7555 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7556 	if (db == NULL) {
7557 		result = ISC_R_FAILURE;
7558 		goto failure;
7559 	}
7560 
7561 	result = dns_db_newversion(db, &version);
7562 	if (result != ISC_R_SUCCESS) {
7563 		dns_zone_log(zone, ISC_LOG_ERROR,
7564 			     "zone_sign:dns_db_newversion -> %s",
7565 			     dns_result_totext(result));
7566 		goto failure;
7567 	}
7568 
7569 	result = find_zone_keys(zone, db, version, zone->mctx,
7570 				DNS_MAXZONEKEYS, zone_keys, &nkeys);
7571 	if (result != ISC_R_SUCCESS) {
7572 		dns_zone_log(zone, ISC_LOG_ERROR,
7573 			     "zone_sign:find_zone_keys -> %s",
7574 			     dns_result_totext(result));
7575 		goto failure;
7576 	}
7577 
7578 	isc_stdtime_get(&now);
7579 	inception = now - 3600;	/* Allow for clock skew. */
7580 	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
7581 
7582 	/*
7583 	 * Spread out signatures over time if they happen to be
7584 	 * clumped.  We don't do this for each add_sigs() call as
7585 	 * we still want some clustering to occur.
7586 	 */
7587 	isc_random_get(&jitter);
7588 	expire = soaexpire - jitter % 3600;
7589 
7590 	/*
7591 	 * We keep pulling nodes off each iterator in turn until
7592 	 * we have no more nodes to pull off or we reach the limits
7593 	 * for this quantum.
7594 	 */
7595 	nodes = zone->nodes;
7596 	signatures = zone->signatures;
7597 	signing = ISC_LIST_HEAD(zone->signing);
7598 	first = ISC_TRUE;
7599 
7600 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7601 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7602 
7603 	/* Determine which type of chain to build */
7604 	CHECK(dns_private_chains(db, version, zone->privatetype,
7605 				 &build_nsec, &build_nsec3));
7606 
7607 	/* If neither chain is found, default to NSEC */
7608 	if (!build_nsec && !build_nsec3)
7609 		build_nsec = ISC_TRUE;
7610 
7611 	while (signing != NULL && nodes-- > 0 && signatures > 0) {
7612 		nextsigning = ISC_LIST_NEXT(signing, link);
7613 
7614 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7615 		if (signing->done || signing->db != zone->db) {
7616 			/*
7617 			 * The zone has been reloaded.	We will have
7618 			 * created new signings as part of the reload
7619 			 * process so we can destroy this one.
7620 			 */
7621 			ISC_LIST_UNLINK(zone->signing, signing, link);
7622 			ISC_LIST_APPEND(cleanup, signing, link);
7623 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7624 			goto next_signing;
7625 		}
7626 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7627 
7628 		if (signing->db != db)
7629 			goto next_signing;
7630 
7631 		delegation = ISC_FALSE;
7632 
7633 		if (first && signing->delete) {
7634 			/*
7635 			 * Remove the key we are deleting from consideration.
7636 			 */
7637 			for (i = 0, j = 0; i < nkeys; i++) {
7638 				/*
7639 				 * Find the key we want to remove.
7640 				 */
7641 				if (ALG(zone_keys[i]) == signing->algorithm &&
7642 				    dst_key_id(zone_keys[i]) == signing->keyid)
7643 				{
7644 					if (KSK(zone_keys[i]))
7645 						dst_key_free(&zone_keys[i]);
7646 					continue;
7647 				}
7648 				zone_keys[j] = zone_keys[i];
7649 				j++;
7650 			}
7651 			nkeys = j;
7652 		}
7653 
7654 		dns_dbiterator_current(signing->dbiterator, &node, name);
7655 
7656 		if (signing->delete) {
7657 			dns_dbiterator_pause(signing->dbiterator);
7658 			CHECK(del_sig(db, version, name, node, nkeys,
7659 				      signing->algorithm, signing->keyid,
7660 				      zonediff.diff));
7661 		}
7662 
7663 		/*
7664 		 * On the first pass we need to check if the current node
7665 		 * has not been obscured.
7666 		 */
7667 		if (first) {
7668 			dns_fixedname_t ffound;
7669 			dns_name_t *found;
7670 			dns_fixedname_init(&ffound);
7671 			found = dns_fixedname_name(&ffound);
7672 			result = dns_db_find(db, name, version,
7673 					     dns_rdatatype_soa,
7674 					     DNS_DBFIND_NOWILD, 0, NULL, found,
7675 					     NULL, NULL);
7676 			if ((result == DNS_R_DELEGATION ||
7677 			    result == DNS_R_DNAME) &&
7678 			    !dns_name_equal(name, found)) {
7679 				/*
7680 				 * Remember the obscuring name so that
7681 				 * we skip all obscured names.
7682 				 */
7683 				dns_name_copy(found, name, NULL);
7684 				delegation = ISC_TRUE;
7685 				goto next_node;
7686 			}
7687 		}
7688 
7689 		/*
7690 		 * Process one node.
7691 		 */
7692 		dns_dbiterator_pause(signing->dbiterator);
7693 		for (i = 0; i < nkeys; i++) {
7694 			isc_boolean_t both = ISC_FALSE;
7695 
7696 			/*
7697 			 * Find the keys we want to sign with.
7698 			 */
7699 			if (!dst_key_isprivate(zone_keys[i]))
7700 				continue;
7701 
7702 			/*
7703 			 * When adding look for the specific key.
7704 			 */
7705 			if (!signing->delete &&
7706 			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
7707 			     dst_key_id(zone_keys[i]) != signing->keyid))
7708 				continue;
7709 
7710 			/*
7711 			 * When deleting make sure we are properly signed
7712 			 * with the algorithm that was being removed.
7713 			 */
7714 			if (signing->delete &&
7715 			    ALG(zone_keys[i]) != signing->algorithm)
7716 				continue;
7717 
7718 			/*
7719 			 * Do we do KSK processing?
7720 			 */
7721 			if (check_ksk && !REVOKE(zone_keys[i])) {
7722 				isc_boolean_t have_ksk, have_nonksk;
7723 				if (KSK(zone_keys[i])) {
7724 					have_ksk = ISC_TRUE;
7725 					have_nonksk = ISC_FALSE;
7726 				} else {
7727 					have_ksk = ISC_FALSE;
7728 					have_nonksk = ISC_TRUE;
7729 				}
7730 				for (j = 0; j < nkeys; j++) {
7731 					if (j == i ||
7732 					    ALG(zone_keys[i]) !=
7733 					    ALG(zone_keys[j]))
7734 						continue;
7735 					if (REVOKE(zone_keys[j]))
7736 						continue;
7737 					if (KSK(zone_keys[j]))
7738 						have_ksk = ISC_TRUE;
7739 					else
7740 						have_nonksk = ISC_TRUE;
7741 					both = have_ksk && have_nonksk;
7742 					if (both)
7743 						break;
7744 				}
7745 			}
7746 			if (both || REVOKE(zone_keys[i]))
7747 				is_ksk = KSK(zone_keys[i]);
7748 			else
7749 				is_ksk = ISC_FALSE;
7750 
7751 			CHECK(sign_a_node(db, name, node, version, build_nsec3,
7752 					  build_nsec, zone_keys[i], inception,
7753 					  expire, zone->minimum, is_ksk,
7754 					  ISC_TF(both && keyset_kskonly),
7755 					  &delegation, zonediff.diff,
7756 					  &signatures, zone->mctx));
7757 			/*
7758 			 * If we are adding we are done.  Look for other keys
7759 			 * of the same algorithm if deleting.
7760 			 */
7761 			if (!signing->delete)
7762 				break;
7763 		}
7764 
7765 		/*
7766 		 * Go onto next node.
7767 		 */
7768  next_node:
7769 		first = ISC_FALSE;
7770 		dns_db_detachnode(db, &node);
7771 		do {
7772 			result = dns_dbiterator_next(signing->dbiterator);
7773 			if (result == ISC_R_NOMORE) {
7774 				ISC_LIST_UNLINK(zone->signing, signing, link);
7775 				ISC_LIST_APPEND(cleanup, signing, link);
7776 				dns_dbiterator_pause(signing->dbiterator);
7777 				if (nkeys != 0 && build_nsec) {
7778 					/*
7779 					 * We have finished regenerating the
7780 					 * zone with a zone signing key.
7781 					 * The NSEC chain is now complete and
7782 					 * there is a full set of signatures
7783 					 * for the zone.  We can now clear the
7784 					 * OPT bit from the NSEC record.
7785 					 */
7786 					result = updatesecure(db, version,
7787 							      &zone->origin,
7788 							      zone->minimum,
7789 							      ISC_FALSE,
7790 							      &post_diff);
7791 					if (result != ISC_R_SUCCESS) {
7792 						dns_zone_log(zone,
7793 							     ISC_LOG_ERROR,
7794 						    "updatesecure -> %s",
7795 						    dns_result_totext(result));
7796 						goto failure;
7797 					}
7798 				}
7799 				result = updatesignwithkey(zone, signing,
7800 							   version,
7801 							   build_nsec3,
7802 							   zone->minimum,
7803 							   &post_diff);
7804 				if (result != ISC_R_SUCCESS) {
7805 					dns_zone_log(zone, ISC_LOG_ERROR,
7806 						     "updatesignwithkey -> %s",
7807 						     dns_result_totext(result));
7808 					goto failure;
7809 				}
7810 				build_nsec = ISC_FALSE;
7811 				goto next_signing;
7812 			} else if (result != ISC_R_SUCCESS) {
7813 				dns_zone_log(zone, ISC_LOG_ERROR,
7814 					"zone_sign:dns_dbiterator_next -> %s",
7815 					     dns_result_totext(result));
7816 				goto failure;
7817 			} else if (delegation) {
7818 				dns_dbiterator_current(signing->dbiterator,
7819 						       &node, nextname);
7820 				dns_db_detachnode(db, &node);
7821 				if (!dns_name_issubdomain(nextname, name))
7822 					break;
7823 			} else
7824 				break;
7825 		} while (1);
7826 		continue;
7827 
7828  next_signing:
7829 		dns_dbiterator_pause(signing->dbiterator);
7830 		signing = nextsigning;
7831 		first = ISC_TRUE;
7832 	}
7833 
7834 	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
7835 		result = update_sigs(&post_diff, db, version, zone_keys,
7836 				     nkeys, zone, inception, expire, now,
7837 				     check_ksk, keyset_kskonly, &zonediff);
7838 		if (result != ISC_R_SUCCESS) {
7839 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
7840 				     "update_sigs -> %s",
7841 				     dns_result_totext(result));
7842 			goto failure;
7843 		}
7844 	}
7845 
7846 	/*
7847 	 * Have we changed anything?
7848 	 */
7849 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7850 		if (zonediff.offline)
7851 			commit = ISC_TRUE;
7852 		result = ISC_R_SUCCESS;
7853 		goto pauseall;
7854 	}
7855 
7856 	commit = ISC_TRUE;
7857 
7858 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7859 			  &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7860 	if (result != ISC_R_SUCCESS) {
7861 		dns_zone_log(zone, ISC_LOG_ERROR,
7862 			     "zone_sign:del_sigs -> %s",
7863 			     dns_result_totext(result));
7864 		goto failure;
7865 	}
7866 
7867 	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7868 				   zone->updatemethod);
7869 	if (result != ISC_R_SUCCESS) {
7870 		dns_zone_log(zone, ISC_LOG_ERROR,
7871 			     "zone_sign:update_soa_serial -> %s",
7872 			     dns_result_totext(result));
7873 		goto failure;
7874 	}
7875 
7876 	/*
7877 	 * Generate maximum life time signatures so that the above loop
7878 	 * termination is sensible.
7879 	 */
7880 	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7881 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
7882 			  inception, soaexpire, check_ksk, keyset_kskonly);
7883 	if (result != ISC_R_SUCCESS) {
7884 		dns_zone_log(zone, ISC_LOG_ERROR,
7885 			     "zone_sign:add_sigs -> %s",
7886 			     dns_result_totext(result));
7887 		goto failure;
7888 	}
7889 
7890 	/*
7891 	 * Write changes to journal file.
7892 	 */
7893 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
7894 
7895  pauseall:
7896 	/*
7897 	 * Pause all iterators so that dns_db_closeversion() can succeed.
7898 	 */
7899 	for (signing = ISC_LIST_HEAD(zone->signing);
7900 	     signing != NULL;
7901 	     signing = ISC_LIST_NEXT(signing, link))
7902 		dns_dbiterator_pause(signing->dbiterator);
7903 
7904 	for (signing = ISC_LIST_HEAD(cleanup);
7905 	     signing != NULL;
7906 	     signing = ISC_LIST_NEXT(signing, link))
7907 		dns_dbiterator_pause(signing->dbiterator);
7908 
7909 	/*
7910 	 * Everything has succeeded. Commit the changes.
7911 	 */
7912 	dns_db_closeversion(db, &version, commit);
7913 
7914 	/*
7915 	 * Everything succeeded so we can clean these up now.
7916 	 */
7917 	signing = ISC_LIST_HEAD(cleanup);
7918 	while (signing != NULL) {
7919 		ISC_LIST_UNLINK(cleanup, signing, link);
7920 		dns_db_detach(&signing->db);
7921 		dns_dbiterator_destroy(&signing->dbiterator);
7922 		isc_mem_put(zone->mctx, signing, sizeof *signing);
7923 		signing = ISC_LIST_HEAD(cleanup);
7924 	}
7925 
7926 	set_resigntime(zone);
7927 
7928 	if (commit) {
7929 		LOCK_ZONE(zone);
7930 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7931 		zone_needdump(zone, DNS_DUMP_DELAY);
7932 		UNLOCK_ZONE(zone);
7933 	}
7934 
7935  failure:
7936 	/*
7937 	 * Rollback the cleanup list.
7938 	 */
7939 	signing = ISC_LIST_HEAD(cleanup);
7940 	while (signing != NULL) {
7941 		ISC_LIST_UNLINK(cleanup, signing, link);
7942 		ISC_LIST_PREPEND(zone->signing, signing, link);
7943 		dns_dbiterator_first(signing->dbiterator);
7944 		dns_dbiterator_pause(signing->dbiterator);
7945 		signing = ISC_LIST_HEAD(cleanup);
7946 	}
7947 
7948 	for (signing = ISC_LIST_HEAD(zone->signing);
7949 	     signing != NULL;
7950 	     signing = ISC_LIST_NEXT(signing, link))
7951 		dns_dbiterator_pause(signing->dbiterator);
7952 
7953 	dns_diff_clear(&_sig_diff);
7954 
7955 	for (i = 0; i < nkeys; i++)
7956 		dst_key_free(&zone_keys[i]);
7957 
7958 	if (node != NULL)
7959 		dns_db_detachnode(db, &node);
7960 
7961 	if (version != NULL) {
7962 		dns_db_closeversion(db, &version, ISC_FALSE);
7963 		dns_db_detach(&db);
7964 	} else if (db != NULL)
7965 		dns_db_detach(&db);
7966 
7967 	if (ISC_LIST_HEAD(zone->signing) != NULL) {
7968 		isc_interval_t interval;
7969 		if (zone->update_disabled || result != ISC_R_SUCCESS)
7970 			isc_interval_set(&interval, 60, 0);	  /* 1 minute */
7971 		else
7972 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
7973 		isc_time_nowplusinterval(&zone->signingtime, &interval);
7974 	} else
7975 		isc_time_settoepoch(&zone->signingtime);
7976 
7977 	INSIST(version == NULL);
7978 }
7979 
7980 static isc_result_t
normalize_key(dns_rdata_t * rr,dns_rdata_t * target,unsigned char * data,int size)7981 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
7982 	      unsigned char *data, int size)
7983 {
7984 	dns_rdata_dnskey_t dnskey;
7985 	dns_rdata_keydata_t keydata;
7986 	isc_buffer_t buf;
7987 	isc_result_t result;
7988 
7989 	dns_rdata_reset(target);
7990 	isc_buffer_init(&buf, data, size);
7991 
7992 	switch (rr->type) {
7993 	    case dns_rdatatype_dnskey:
7994 		result = dns_rdata_tostruct(rr, &dnskey, NULL);
7995 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
7996 		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
7997 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7998 				     &dnskey, &buf);
7999 		break;
8000 	    case dns_rdatatype_keydata:
8001 		result = dns_rdata_tostruct(rr, &keydata, NULL);
8002 		if (result == ISC_R_UNEXPECTEDEND)
8003 			return (result);
8004 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
8005 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
8006 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
8007 				     &dnskey, &buf);
8008 		break;
8009 	    default:
8010 		INSIST(0);
8011 	}
8012 	return (ISC_R_SUCCESS);
8013 }
8014 
8015 /*
8016  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
8017  * a KEYDATA rdataset from the key zone.
8018  *
8019  * 'rr' contains either a DNSKEY record, or a KEYDATA record
8020  *
8021  * After normalizing keys to the same format (DNSKEY, with revoke bit
8022  * cleared), return ISC_TRUE if a key that matches 'rr' is found in
8023  * 'rdset', or ISC_FALSE if not.
8024  */
8025 
8026 static isc_boolean_t
matchkey(dns_rdataset_t * rdset,dns_rdata_t * rr)8027 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
8028 	unsigned char data1[4096], data2[4096];
8029 	dns_rdata_t rdata, rdata1, rdata2;
8030 	isc_result_t result;
8031 
8032 	dns_rdata_init(&rdata);
8033 	dns_rdata_init(&rdata1);
8034 	dns_rdata_init(&rdata2);
8035 
8036 	result = normalize_key(rr, &rdata1, data1, sizeof(data1));
8037 	if (result != ISC_R_SUCCESS)
8038 		return (ISC_FALSE);
8039 
8040 	for (result = dns_rdataset_first(rdset);
8041 	     result == ISC_R_SUCCESS;
8042 	     result = dns_rdataset_next(rdset)) {
8043 		dns_rdata_reset(&rdata);
8044 		dns_rdataset_current(rdset, &rdata);
8045 		result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
8046 		if (result != ISC_R_SUCCESS)
8047 			continue;
8048 		if (dns_rdata_compare(&rdata1, &rdata2) == 0)
8049 			return (ISC_TRUE);
8050 	}
8051 
8052 	return (ISC_FALSE);
8053 }
8054 
8055 /*
8056  * Calculate the refresh interval for a keydata zone, per
8057  * RFC5011: MAX(1 hr,
8058  *		MIN(15 days,
8059  *		    1/2 * OrigTTL,
8060  *		    1/2 * RRSigExpirationInterval))
8061  * or for retries: MAX(1 hr,
8062  *		       MIN(1 day,
8063  *			   1/10 * OrigTTL,
8064  *			   1/10 * RRSigExpirationInterval))
8065  */
8066 static inline isc_stdtime_t
refresh_time(dns_keyfetch_t * kfetch,isc_boolean_t retry)8067 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
8068 	isc_result_t result;
8069 	isc_uint32_t t;
8070 	dns_rdataset_t *rdset;
8071 	dns_rdata_t sigrr = DNS_RDATA_INIT;
8072 	dns_rdata_sig_t sig;
8073 	isc_stdtime_t now;
8074 
8075 	isc_stdtime_get(&now);
8076 
8077 	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8078 		rdset = &kfetch->dnskeysigset;
8079 	else
8080 		return (now + dns_zone_mkey_hour);
8081 
8082 	result = dns_rdataset_first(rdset);
8083 	if (result != ISC_R_SUCCESS)
8084 		return (now + dns_zone_mkey_hour);
8085 
8086 	dns_rdataset_current(rdset, &sigrr);
8087 	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8088 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
8089 
8090 	if (!retry) {
8091 		t = sig.originalttl / 2;
8092 
8093 		if (isc_serial_gt(sig.timeexpire, now)) {
8094 			isc_uint32_t exp = (sig.timeexpire - now) / 2;
8095 			if (t > exp)
8096 				t = exp;
8097 		}
8098 
8099 		if (t > (15 * dns_zone_mkey_day))
8100 			t = (15 * dns_zone_mkey_day);
8101 
8102 		if (t < dns_zone_mkey_hour)
8103 			t = dns_zone_mkey_hour;
8104 	} else {
8105 		t = sig.originalttl / 10;
8106 
8107 		if (isc_serial_gt(sig.timeexpire, now)) {
8108 			isc_uint32_t exp = (sig.timeexpire - now) / 10;
8109 			if (t > exp)
8110 				t = exp;
8111 		}
8112 
8113 		if (t > dns_zone_mkey_day)
8114 			t = dns_zone_mkey_day;
8115 
8116 		if (t < dns_zone_mkey_hour)
8117 			t = dns_zone_mkey_hour;
8118 	}
8119 
8120 	return (now + t);
8121 }
8122 
8123 /*
8124  * This routine is called when no changes are needed in a KEYDATA
8125  * record except to simply update the refresh timer.  Caller should
8126  * hold zone lock.
8127  */
8128 static isc_result_t
minimal_update(dns_keyfetch_t * kfetch,dns_dbversion_t * ver,dns_diff_t * diff)8129 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
8130 {
8131 	isc_result_t result;
8132 	isc_buffer_t keyb;
8133 	unsigned char key_buf[4096];
8134 	dns_rdata_t rdata = DNS_RDATA_INIT;
8135 	dns_rdata_keydata_t keydata;
8136 	dns_name_t *name;
8137 	dns_zone_t *zone = kfetch->zone;
8138 	isc_stdtime_t now;
8139 
8140 	name = dns_fixedname_name(&kfetch->name);
8141 	isc_stdtime_get(&now);
8142 
8143 	for (result = dns_rdataset_first(&kfetch->keydataset);
8144 	     result == ISC_R_SUCCESS;
8145 	     result = dns_rdataset_next(&kfetch->keydataset)) {
8146 		dns_rdata_reset(&rdata);
8147 		dns_rdataset_current(&kfetch->keydataset, &rdata);
8148 
8149 		/* Delete old version */
8150 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
8151 				    name, 0, &rdata));
8152 
8153 		/* Update refresh timer */
8154 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
8155 		if (result == ISC_R_UNEXPECTEDEND)
8156 			continue;
8157 		if (result != ISC_R_SUCCESS)
8158 			goto failure;
8159 		keydata.refresh = refresh_time(kfetch, ISC_TRUE);
8160 		set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
8161 
8162 		dns_rdata_reset(&rdata);
8163 		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8164 		CHECK(dns_rdata_fromstruct(&rdata,
8165 					   zone->rdclass, dns_rdatatype_keydata,
8166 					   &keydata, &keyb));
8167 
8168 		/* Insert updated version */
8169 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
8170 				    name, 0, &rdata));
8171 	}
8172 	result = ISC_R_SUCCESS;
8173   failure:
8174 	return (result);
8175 }
8176 
8177 /*
8178  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
8179  */
8180 static isc_boolean_t
revocable(dns_keyfetch_t * kfetch,dns_rdata_keydata_t * keydata)8181 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
8182 	isc_result_t result;
8183 	dns_name_t *keyname;
8184 	isc_mem_t *mctx;
8185 	dns_rdata_t sigrr = DNS_RDATA_INIT;
8186 	dns_rdata_t rr = DNS_RDATA_INIT;
8187 	dns_rdata_rrsig_t sig;
8188 	dns_rdata_dnskey_t dnskey;
8189 	dst_key_t *dstkey = NULL;
8190 	unsigned char key_buf[4096];
8191 	isc_buffer_t keyb;
8192 	isc_boolean_t answer = ISC_FALSE;
8193 
8194 	REQUIRE(kfetch != NULL && keydata != NULL);
8195 	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
8196 
8197 	keyname = dns_fixedname_name(&kfetch->name);
8198 	mctx = kfetch->zone->view->mctx;
8199 
8200 	/* Generate a key from keydata */
8201 	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8202 	dns_keydata_todnskey(keydata, &dnskey, NULL);
8203 	dns_rdata_fromstruct(&rr, keydata->common.rdclass,
8204 			     dns_rdatatype_dnskey, &dnskey, &keyb);
8205 	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
8206 	if (result != ISC_R_SUCCESS)
8207 		return (ISC_FALSE);
8208 
8209 	/* See if that key generated any of the signatures */
8210 	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8211 	     result == ISC_R_SUCCESS;
8212 	     result = dns_rdataset_next(&kfetch->dnskeysigset))
8213 	{
8214 		dns_fixedname_t fixed;
8215 		dns_fixedname_init(&fixed);
8216 
8217 		dns_rdata_reset(&sigrr);
8218 		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8219 		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8220 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
8221 
8222 		if (dst_key_alg(dstkey) == sig.algorithm &&
8223 		    dst_key_rid(dstkey) == sig.keyid)
8224 		{
8225 			result = dns_dnssec_verify2(keyname,
8226 					    &kfetch->dnskeyset,
8227 					    dstkey, ISC_FALSE, mctx, &sigrr,
8228 					    dns_fixedname_name(&fixed));
8229 
8230 			dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
8231 				     "Confirm revoked DNSKEY is self-signed: "
8232 				     "%s", dns_result_totext(result));
8233 
8234 			if (result == ISC_R_SUCCESS) {
8235 				answer = ISC_TRUE;
8236 				break;
8237 			}
8238 		}
8239 	}
8240 
8241 	dst_key_free(&dstkey);
8242 	return (answer);
8243 }
8244 
8245 /*
8246  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
8247  * anchors are being managed; scan the keyset, and update the key zone and the
8248  * local trust anchors according to RFC5011.
8249  */
8250 static void
keyfetch_done(isc_task_t * task,isc_event_t * event)8251 keyfetch_done(isc_task_t *task, isc_event_t *event) {
8252 	isc_result_t result, eresult;
8253 	dns_fetchevent_t *devent;
8254 	dns_keyfetch_t *kfetch;
8255 	dns_zone_t *zone;
8256 	isc_mem_t *mctx = NULL;
8257 	dns_keytable_t *secroots = NULL;
8258 	dns_dbversion_t *ver = NULL;
8259 	dns_diff_t diff;
8260 	isc_boolean_t alldone = ISC_FALSE;
8261 	isc_boolean_t commit = ISC_FALSE;
8262 	dns_name_t *keyname;
8263 	dns_rdata_t sigrr = DNS_RDATA_INIT;
8264 	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
8265 	dns_rdata_t keydatarr = DNS_RDATA_INIT;
8266 	dns_rdata_rrsig_t sig;
8267 	dns_rdata_dnskey_t dnskey;
8268 	dns_rdata_keydata_t keydata;
8269 	isc_boolean_t initializing;
8270 	char namebuf[DNS_NAME_FORMATSIZE];
8271 	unsigned char key_buf[4096];
8272 	isc_buffer_t keyb;
8273 	dst_key_t *dstkey;
8274 	isc_stdtime_t now;
8275 	int pending = 0;
8276 	isc_boolean_t secure;
8277 	isc_boolean_t free_needed;
8278 
8279 	UNUSED(task);
8280 	INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
8281 	INSIST(event->ev_arg != NULL);
8282 
8283 	kfetch = event->ev_arg;
8284 	zone = kfetch->zone;
8285 	isc_mem_attach(zone->mctx, &mctx);
8286 	keyname = dns_fixedname_name(&kfetch->name);
8287 
8288 	devent = (dns_fetchevent_t *) event;
8289 	eresult = devent->result;
8290 
8291 	/* Free resources which are not of interest */
8292 	if (devent->node != NULL)
8293 		dns_db_detachnode(devent->db, &devent->node);
8294 	if (devent->db != NULL)
8295 		dns_db_detach(&devent->db);
8296 	isc_event_free(&event);
8297 	dns_resolver_destroyfetch(&kfetch->fetch);
8298 
8299 	LOCK_ZONE(zone);
8300 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
8301 		goto cleanup;
8302 
8303 	isc_stdtime_get(&now);
8304 	dns_name_format(keyname, namebuf, sizeof(namebuf));
8305 
8306 	result = dns_view_getsecroots(zone->view, &secroots);
8307 	INSIST(result == ISC_R_SUCCESS);
8308 
8309 	dns_diff_init(mctx, &diff);
8310 
8311 	CHECK(dns_db_newversion(kfetch->db, &ver));
8312 
8313 	zone->refreshkeycount--;
8314 	alldone = ISC_TF(zone->refreshkeycount == 0);
8315 
8316 	if (alldone)
8317 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8318 
8319 	/* Fetch failed */
8320 	if (eresult != ISC_R_SUCCESS ||
8321 	    !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
8322 		dns_zone_log(zone, ISC_LOG_WARNING,
8323 			     "Unable to fetch DNSKEY set "
8324 			     "'%s': %s", namebuf, dns_result_totext(eresult));
8325 		CHECK(minimal_update(kfetch, ver, &diff));
8326 		goto done;
8327 	}
8328 
8329 	/* No RRSIGs found */
8330 	if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
8331 		dns_zone_log(zone, ISC_LOG_WARNING,
8332 			     "No DNSKEY RRSIGs found for "
8333 			     "'%s': %s", namebuf, dns_result_totext(eresult));
8334 		CHECK(minimal_update(kfetch, ver, &diff));
8335 		goto done;
8336 	}
8337 
8338 	/*
8339 	 * Clear any cached trust level, as we need to run validation
8340 	 * over again; trusted keys might have changed.
8341 	 */
8342 	kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
8343 
8344 	/*
8345 	 * Validate the dnskeyset against the current trusted keys.
8346 	 */
8347 	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8348 	     result == ISC_R_SUCCESS;
8349 	     result = dns_rdataset_next(&kfetch->dnskeysigset)) {
8350 		dns_keynode_t *keynode = NULL;
8351 
8352 		dns_rdata_reset(&sigrr);
8353 		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8354 		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8355 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
8356 
8357 		result = dns_keytable_find(secroots, keyname, &keynode);
8358 		while (result == ISC_R_SUCCESS) {
8359 			dns_keynode_t *nextnode = NULL;
8360 			dns_fixedname_t fixed;
8361 			dns_fixedname_init(&fixed);
8362 
8363 			dstkey = dns_keynode_key(keynode);
8364 			if (dstkey == NULL) /* fail_secure() was called */
8365 				break;
8366 
8367 			if (dst_key_alg(dstkey) == sig.algorithm &&
8368 			    dst_key_id(dstkey) == sig.keyid) {
8369 				result = dns_dnssec_verify2(keyname,
8370 						    &kfetch->dnskeyset,
8371 						    dstkey, ISC_FALSE,
8372 						    zone->view->mctx, &sigrr,
8373 						    dns_fixedname_name(&fixed));
8374 
8375 				dns_zone_log(zone, ISC_LOG_DEBUG(3),
8376 					     "Verifying DNSKEY set for zone "
8377 					     "'%s' using key %d/%d: %s",
8378 					     namebuf, sig.keyid, sig.algorithm,
8379 					     dns_result_totext(result));
8380 
8381 				if (result == ISC_R_SUCCESS) {
8382 					kfetch->dnskeyset.trust =
8383 						dns_trust_secure;
8384 					kfetch->dnskeysigset.trust =
8385 						dns_trust_secure;
8386 					break;
8387 				}
8388 			}
8389 
8390 			result = dns_keytable_nextkeynode(secroots,
8391 							  keynode, &nextnode);
8392 			dns_keytable_detachkeynode(secroots, &keynode);
8393 			keynode = nextnode;
8394 		}
8395 
8396 		if (keynode != NULL)
8397 			dns_keytable_detachkeynode(secroots, &keynode);
8398 
8399 		if (kfetch->dnskeyset.trust == dns_trust_secure)
8400 			break;
8401 	}
8402 
8403 	/*
8404 	 * If we were not able to verify the answer using the current
8405 	 * trusted keys then all we can do is look at any revoked keys.
8406 	 */
8407 	secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
8408 
8409 	/*
8410 	 * First scan keydataset to find keys that are not in dnskeyset
8411 	 *   - Missing keys which are not scheduled for removal,
8412 	 *     log a warning
8413 	 *   - Missing keys which are scheduled for removal and
8414 	 *     the remove hold-down timer has completed should
8415 	 *     be removed from the key zone
8416 	 *   - Missing keys whose acceptance timers have not yet
8417 	 *     completed, log a warning and reset the acceptance
8418 	 *     timer to 30 days in the future
8419 	 *   - All keys not being removed have their refresh timers
8420 	 *     updated
8421 	 */
8422 	initializing = ISC_TRUE;
8423 	for (result = dns_rdataset_first(&kfetch->keydataset);
8424 	     result == ISC_R_SUCCESS;
8425 	     result = dns_rdataset_next(&kfetch->keydataset)) {
8426 		dns_rdata_reset(&keydatarr);
8427 		dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8428 		result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8429 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
8430 
8431 		/*
8432 		 * If any keydata record has a nonzero add holddown, then
8433 		 * there was a pre-existing trust anchor for this domain;
8434 		 * that means we are *not* initializing it and shouldn't
8435 		 * automatically trust all the keys we find at the zone apex.
8436 		 */
8437 		initializing = initializing && ISC_TF(keydata.addhd == 0);
8438 
8439 		if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
8440 			isc_boolean_t deletekey = ISC_FALSE;
8441 
8442 			if (!secure) {
8443 				if (keydata.removehd != 0 &&
8444 				    keydata.removehd <= now)
8445 					deletekey = ISC_TRUE;
8446 			} else if (keydata.addhd == 0) {
8447 				deletekey = ISC_TRUE;
8448 			} else if (keydata.addhd > now) {
8449 				dns_zone_log(zone, ISC_LOG_WARNING,
8450 					     "Pending key unexpectedly missing "
8451 					     "from %s; restarting acceptance "
8452 					     "timer", namebuf);
8453 				if (keydata.addhd < now + dns_zone_mkey_month)
8454 					keydata.addhd =
8455 						now + dns_zone_mkey_month;
8456 				keydata.refresh = refresh_time(kfetch,
8457 							       ISC_FALSE);
8458 			} else if (keydata.removehd == 0) {
8459 				dns_zone_log(zone, ISC_LOG_WARNING,
8460 					     "Active key unexpectedly missing "
8461 					     "from %s", namebuf);
8462 				keydata.refresh = now + dns_zone_mkey_hour;
8463 			} else if (keydata.removehd <= now) {
8464 				deletekey = ISC_TRUE;
8465 			} else {
8466 				keydata.refresh = refresh_time(kfetch,
8467 							       ISC_FALSE);
8468 			}
8469 
8470 			if (secure || deletekey) {
8471 				/* Delete old version */
8472 				CHECK(update_one_rr(kfetch->db, ver, &diff,
8473 						    DNS_DIFFOP_DEL, keyname, 0,
8474 						    &keydatarr));
8475 			}
8476 
8477 			if (!secure || deletekey)
8478 				continue;
8479 
8480 			dns_rdata_reset(&keydatarr);
8481 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8482 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8483 					     dns_rdatatype_keydata,
8484 					     &keydata, &keyb);
8485 
8486 			/* Insert updated version */
8487 			CHECK(update_one_rr(kfetch->db, ver, &diff,
8488 					    DNS_DIFFOP_ADD, keyname, 0,
8489 					    &keydatarr));
8490 
8491 			set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
8492 		}
8493 	}
8494 
8495 	/*
8496 	 * Next scan dnskeyset:
8497 	 *   - If new keys are found (i.e., lacking a match in keydataset)
8498 	 *     add them to the key zone and set the acceptance timer
8499 	 *     to 30 days in the future (or to immediately if we've
8500 	 *     determined that we're initializing the zone for the
8501 	 *     first time)
8502 	 *   - Previously-known keys that have been revoked
8503 	 *     must be scheduled for removal from the key zone (or,
8504 	 *     if they hadn't been accepted as trust anchors yet
8505 	 *     anyway, removed at once)
8506 	 *   - Previously-known unrevoked keys whose acceptance timers
8507 	 *     have completed are promoted to trust anchors
8508 	 *   - All keys not being removed have their refresh
8509 	 *     timers updated
8510 	 */
8511 	for (result = dns_rdataset_first(&kfetch->dnskeyset);
8512 	     result == ISC_R_SUCCESS;
8513 	     result = dns_rdataset_next(&kfetch->dnskeyset))
8514 	{
8515 		isc_boolean_t revoked = ISC_FALSE;
8516 		isc_boolean_t newkey = ISC_FALSE;
8517 		isc_boolean_t updatekey = ISC_FALSE;
8518 		isc_boolean_t deletekey = ISC_FALSE;
8519 		isc_boolean_t trustkey = ISC_FALSE;
8520 
8521 		dns_rdata_reset(&dnskeyrr);
8522 		dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
8523 		result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8524 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
8525 
8526 		/* Skip ZSK's */
8527 		if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
8528 			continue;
8529 
8530 		revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
8531 
8532 		if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
8533 			dns_rdata_reset(&keydatarr);
8534 			dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8535 			result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8536 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
8537 
8538 			if (revoked && revocable(kfetch, &keydata)) {
8539 				if (keydata.addhd > now) {
8540 					/*
8541 					 * Key wasn't trusted yet, and now
8542 					 * it's been revoked?  Just remove it
8543 					 */
8544 					deletekey = ISC_TRUE;
8545 				} else if (keydata.removehd == 0) {
8546 					/*
8547 					 * Remove key from secroots.
8548 					 */
8549 					dns_view_untrust(zone->view, keyname,
8550 							 &dnskey, mctx);
8551 
8552 					/* If initializing, delete now */
8553 					if (keydata.addhd == 0)
8554 						deletekey = ISC_TRUE;
8555 					else {
8556 						keydata.removehd = now +
8557 							dns_zone_mkey_month;
8558 						keydata.flags |=
8559 							DNS_KEYFLAG_REVOKE;
8560 					}
8561 				} else if (keydata.removehd < now) {
8562 					/* Scheduled for removal */
8563 					deletekey = ISC_TRUE;
8564 				}
8565 			} else if (revoked && keydata.removehd == 0) {
8566 				dns_zone_log(zone, ISC_LOG_WARNING,
8567 					     "Active key for zone "
8568 					     "'%s' is revoked but "
8569 					     "did not self-sign; "
8570 					     "ignoring.", namebuf);
8571 					continue;
8572 			} else if (secure) {
8573 				if (keydata.removehd != 0) {
8574 					/*
8575 					 * Key isn't revoked--but it
8576 					 * seems it used to be.
8577 					 * Remove it now and add it
8578 					 * back as if it were a fresh key,
8579 					 * with a 30 day acceptance timer.
8580 					 */
8581 					deletekey = ISC_TRUE;
8582 					newkey = ISC_TRUE;
8583 					keydata.removehd = 0;
8584 					keydata.addhd =
8585 						now + dns_zone_mkey_month;
8586 				} else if (keydata.addhd > now)
8587 					pending++;
8588 				else if (keydata.addhd == 0)
8589 					keydata.addhd = now;
8590 
8591 				if (keydata.addhd <= now)
8592 					trustkey = ISC_TRUE;
8593 			} else if (keydata.addhd > now) {
8594 				/*
8595 				 * Not secure, and key is pending:
8596 				 * reset the acceptance timer
8597 				 */
8598 				pending++;
8599 				keydata.addhd = now + dns_zone_mkey_month;
8600 			}
8601 
8602 			if (!deletekey && !newkey)
8603 				updatekey = ISC_TRUE;
8604 		} else if (secure) {
8605 			/*
8606 			 * Key wasn't in the key zone but it's
8607 			 * revoked now anyway, so just skip it
8608 			 */
8609 			if (revoked)
8610 				continue;
8611 
8612 			/* Key wasn't in the key zone: add it */
8613 			newkey = ISC_TRUE;
8614 
8615 			if (initializing) {
8616 				dns_keytag_t tag = 0;
8617 				CHECK(compute_tag(keyname, &dnskey,
8618 						  mctx, &tag));
8619 				dns_zone_log(zone, ISC_LOG_WARNING,
8620 					     "Initializing automatic trust "
8621 					     "anchor management for zone '%s'; "
8622 					     "DNSKEY ID %d is now trusted, "
8623 					     "waiving the normal 30-day "
8624 					     "waiting period.",
8625 					     namebuf, tag);
8626 				trustkey = ISC_TRUE;
8627 			}
8628 		} else {
8629 			/*
8630 			 * No previously known key, and the key is not
8631 			 * secure, so skip it.
8632 			 */
8633 			continue;
8634 		}
8635 
8636 		/* Delete old version */
8637 		if (deletekey || !newkey)
8638 			CHECK(update_one_rr(kfetch->db, ver, &diff,
8639 					    DNS_DIFFOP_DEL, keyname, 0,
8640 					    &keydatarr));
8641 
8642 		if (updatekey) {
8643 			/* Set refresh timer */
8644 			keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8645 			dns_rdata_reset(&keydatarr);
8646 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8647 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8648 					     dns_rdatatype_keydata,
8649 					     &keydata, &keyb);
8650 
8651 			/* Insert updated version */
8652 			CHECK(update_one_rr(kfetch->db, ver, &diff,
8653 					    DNS_DIFFOP_ADD, keyname, 0,
8654 					    &keydatarr));
8655 		} else if (newkey) {
8656 			/* Convert DNSKEY to KEYDATA */
8657 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8658 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
8659 			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
8660 					       NULL);
8661 			keydata.addhd = initializing
8662 					 ? now : now + dns_zone_mkey_month;
8663 			keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8664 			dns_rdata_reset(&keydatarr);
8665 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8666 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8667 					     dns_rdatatype_keydata,
8668 					     &keydata, &keyb);
8669 
8670 			/* Insert into key zone */
8671 			CHECK(update_one_rr(kfetch->db, ver, &diff,
8672 					    DNS_DIFFOP_ADD, keyname, 0,
8673 					    &keydatarr));
8674 		}
8675 
8676 		if (trustkey) {
8677 			/* Trust this key. */
8678 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8679 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
8680 			trust_key(zone, keyname, &dnskey, mctx);
8681 		}
8682 
8683 		if (secure && !deletekey) {
8684 			INSIST(newkey || updatekey);
8685 			set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
8686 		}
8687 	}
8688 
8689 	/*
8690 	 * RFC5011 says, "A trust point that has all of its trust anchors
8691 	 * revoked is considered deleted and is treated as if the trust
8692 	 * point was never configured."  But if someone revoked their
8693 	 * active key before the standby was trusted, that would mean the
8694 	 * zone would suddenly be nonsecured.  We avoid this by checking to
8695 	 * see if there's pending keydata.  If so, we put a null key in
8696 	 * the security roots; then all queries to the zone will fail.
8697 	 */
8698 	if (pending != 0)
8699 		fail_secure(zone, keyname);
8700 
8701  done:
8702 
8703 	if (!ISC_LIST_EMPTY(diff.tuples)) {
8704 		/* Write changes to journal file. */
8705 		CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
8706 					zone->updatemethod));
8707 		CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
8708 		commit = ISC_TRUE;
8709 
8710 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8711 		zone_needdump(zone, 30);
8712 	}
8713 
8714  failure:
8715 
8716 	dns_diff_clear(&diff);
8717 	if (ver != NULL)
8718 		dns_db_closeversion(kfetch->db, &ver, commit);
8719 
8720  cleanup:
8721 	dns_db_detach(&kfetch->db);
8722 
8723 	INSIST(zone->irefs > 0);
8724 	zone->irefs--;
8725 	kfetch->zone = NULL;
8726 
8727 	if (dns_rdataset_isassociated(&kfetch->keydataset))
8728 		dns_rdataset_disassociate(&kfetch->keydataset);
8729 	if (dns_rdataset_isassociated(&kfetch->dnskeyset))
8730 		dns_rdataset_disassociate(&kfetch->dnskeyset);
8731 	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8732 		dns_rdataset_disassociate(&kfetch->dnskeysigset);
8733 
8734 	dns_name_free(keyname, mctx);
8735 	isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
8736 	isc_mem_detach(&mctx);
8737 
8738 	if (secroots != NULL)
8739 		dns_keytable_detach(&secroots);
8740 
8741 	free_needed = exit_check(zone);
8742 	UNLOCK_ZONE(zone);
8743 	if (free_needed)
8744 		zone_free(zone);
8745 
8746 	INSIST(ver == NULL);
8747 }
8748 
8749 /*
8750  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
8751  * records from the zone apex.
8752  */
8753 static void
zone_refreshkeys(dns_zone_t * zone)8754 zone_refreshkeys(dns_zone_t *zone) {
8755 	const char me[] = "zone_refreshkeys";
8756 	isc_result_t result;
8757 	dns_rriterator_t rrit;
8758 	dns_db_t *db = NULL;
8759 	dns_dbversion_t *ver = NULL;
8760 	dns_diff_t diff;
8761 	dns_rdata_t rdata = DNS_RDATA_INIT;
8762 	dns_rdata_keydata_t kd;
8763 	isc_stdtime_t now;
8764 	isc_boolean_t commit = ISC_FALSE;
8765 	isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
8766 
8767 	ENTER;
8768 	REQUIRE(zone->db != NULL);
8769 
8770 	isc_stdtime_get(&now);
8771 
8772 	LOCK_ZONE(zone);
8773 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
8774 		isc_time_settoepoch(&zone->refreshkeytime);
8775 		UNLOCK_ZONE(zone);
8776 		return;
8777 	}
8778 
8779 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8780 	dns_db_attach(zone->db, &db);
8781 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8782 
8783 	dns_diff_init(zone->mctx, &diff);
8784 
8785 	CHECK(dns_db_newversion(db, &ver));
8786 
8787 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
8788 
8789 	dns_rriterator_init(&rrit, db, ver, 0);
8790 	for (result = dns_rriterator_first(&rrit);
8791 	     result == ISC_R_SUCCESS;
8792 	     result = dns_rriterator_nextrrset(&rrit)) {
8793 		isc_stdtime_t timer = 0xffffffff;
8794 		dns_name_t *name = NULL, *kname = NULL;
8795 		dns_rdataset_t *kdset = NULL;
8796 		dns_keyfetch_t *kfetch;
8797 		isc_uint32_t ttl;
8798 
8799 		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
8800 		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
8801 		    !dns_rdataset_isassociated(kdset))
8802 			continue;
8803 
8804 		/*
8805 		 * Scan the stored keys looking for ones that need
8806 		 * removal or refreshing
8807 		 */
8808 		for (result = dns_rdataset_first(kdset);
8809 		     result == ISC_R_SUCCESS;
8810 		     result = dns_rdataset_next(kdset)) {
8811 			dns_rdata_reset(&rdata);
8812 			dns_rdataset_current(kdset, &rdata);
8813 			result = dns_rdata_tostruct(&rdata, &kd, NULL);
8814 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
8815 
8816 			/* Removal timer expired? */
8817 			if (kd.removehd != 0 && kd.removehd < now) {
8818 				CHECK(update_one_rr(db, ver, &diff,
8819 						    DNS_DIFFOP_DEL, name, ttl,
8820 						    &rdata));
8821 				continue;
8822 			}
8823 
8824 			/* Acceptance timer expired? */
8825 			if (kd.addhd != 0 && kd.addhd < now)
8826 				timer = kd.addhd;
8827 
8828 			/* Or do we just need to refresh the keyset? */
8829 			if (timer > kd.refresh)
8830 				timer = kd.refresh;
8831 		}
8832 
8833 		if (timer > now)
8834 			continue;
8835 
8836 		kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
8837 		if (kfetch == NULL) {
8838 			fetch_err = ISC_TRUE;
8839 			goto failure;
8840 		}
8841 
8842 		zone->refreshkeycount++;
8843 		kfetch->zone = zone;
8844 		zone->irefs++;
8845 		INSIST(zone->irefs != 0);
8846 		dns_fixedname_init(&kfetch->name);
8847 		kname = dns_fixedname_name(&kfetch->name);
8848 		dns_name_dup(name, zone->mctx, kname);
8849 		dns_rdataset_init(&kfetch->dnskeyset);
8850 		dns_rdataset_init(&kfetch->dnskeysigset);
8851 		dns_rdataset_init(&kfetch->keydataset);
8852 		dns_rdataset_clone(kdset, &kfetch->keydataset);
8853 		kfetch->db = NULL;
8854 		dns_db_attach(db, &kfetch->db);
8855 		kfetch->fetch = NULL;
8856 
8857 		result = dns_resolver_createfetch(zone->view->resolver,
8858 						  kname, dns_rdatatype_dnskey,
8859 						  NULL, NULL, NULL,
8860 						  DNS_FETCHOPT_NOVALIDATE|
8861 						  DNS_FETCHOPT_UNSHARED,
8862 						  zone->task,
8863 						  keyfetch_done, kfetch,
8864 						  &kfetch->dnskeyset,
8865 						  &kfetch->dnskeysigset,
8866 						  &kfetch->fetch);
8867 		if (result == ISC_R_SUCCESS)
8868 			fetching = ISC_TRUE;
8869 		else {
8870 			zone->refreshkeycount--;
8871 			zone->irefs--;
8872 			dns_db_detach(&kfetch->db);
8873 			dns_rdataset_disassociate(&kfetch->keydataset);
8874 			dns_name_free(kname, zone->mctx);
8875 			isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
8876 			dns_zone_log(zone, ISC_LOG_WARNING,
8877 				     "Failed to create fetch for "
8878 				     "DNSKEY update");
8879 			fetch_err = ISC_TRUE;
8880 		}
8881 	}
8882 	if (!ISC_LIST_EMPTY(diff.tuples)) {
8883 		CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
8884 					zone->updatemethod));
8885 		CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
8886 		commit = ISC_TRUE;
8887 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8888 		zone_needdump(zone, 30);
8889 	}
8890 
8891   failure:
8892 	if (fetch_err) {
8893 		/*
8894 		 * Error during a key fetch; retry in an hour.
8895 		 */
8896 		isc_time_t timenow, timethen;
8897 		char timebuf[80];
8898 
8899 		TIME_NOW(&timenow);
8900 		DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
8901 		zone->refreshkeytime = timethen;
8902 		zone_settimer(zone, &timenow);
8903 
8904 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
8905 		dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
8906 			     timebuf);
8907 
8908 		if (!fetching)
8909 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8910 	}
8911 
8912 	UNLOCK_ZONE(zone);
8913 
8914 	dns_diff_clear(&diff);
8915 	if (ver != NULL) {
8916 		dns_rriterator_destroy(&rrit);
8917 		dns_db_closeversion(db, &ver, commit);
8918 	}
8919 	dns_db_detach(&db);
8920 
8921 	INSIST(ver == NULL);
8922 }
8923 
8924 static void
zone_maintenance(dns_zone_t * zone)8925 zone_maintenance(dns_zone_t *zone) {
8926 	const char me[] = "zone_maintenance";
8927 	isc_time_t now;
8928 	isc_result_t result;
8929 	isc_boolean_t dumping;
8930 
8931 	REQUIRE(DNS_ZONE_VALID(zone));
8932 	ENTER;
8933 
8934 	/*
8935 	 * Are we pending load/reload?
8936 	 */
8937 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
8938 		return;
8939 
8940 	/*
8941 	 * Configuring the view of this zone may have
8942 	 * failed, for example because the config file
8943 	 * had a syntax error.	In that case, the view
8944 	 * adb or resolver will be NULL, and we had better not try
8945 	 * to do further maintenance on it.
8946 	 */
8947 	if (zone->view == NULL || zone->view->adb == NULL)
8948 		return;
8949 
8950 	TIME_NOW(&now);
8951 
8952 	/*
8953 	 * Expire check.
8954 	 */
8955 	switch (zone->type) {
8956 	case dns_zone_redirect:
8957 		if (zone->masters == NULL)
8958 			break;
8959 	case dns_zone_slave:
8960 	case dns_zone_stub:
8961 		LOCK_ZONE(zone);
8962 		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
8963 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8964 			zone_expire(zone);
8965 			zone->refreshtime = now;
8966 		}
8967 		UNLOCK_ZONE(zone);
8968 		break;
8969 	default:
8970 		break;
8971 	}
8972 
8973 	/*
8974 	 * Up to date check.
8975 	 */
8976 	switch (zone->type) {
8977 	case dns_zone_redirect:
8978 		if (zone->masters == NULL)
8979 			break;
8980 	case dns_zone_slave:
8981 	case dns_zone_stub:
8982 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8983 		    isc_time_compare(&now, &zone->refreshtime) >= 0)
8984 			dns_zone_refresh(zone);
8985 		break;
8986 	default:
8987 		break;
8988 	}
8989 
8990 	/*
8991 	 * Slaves send notifies before backing up to disk, masters after.
8992 	 */
8993 	if (zone->type == dns_zone_slave &&
8994 	    (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
8995 	     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
8996 	    isc_time_compare(&now, &zone->notifytime) >= 0)
8997 		zone_notify(zone, &now);
8998 
8999 	/*
9000 	 * Do we need to consolidate the backing store?
9001 	 */
9002 	switch (zone->type) {
9003 	case dns_zone_master:
9004 	case dns_zone_slave:
9005 	case dns_zone_key:
9006 	case dns_zone_redirect:
9007 	case dns_zone_stub:
9008 		LOCK_ZONE(zone);
9009 		if (zone->masterfile != NULL &&
9010 		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
9011 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
9012 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
9013 			dumping = was_dumping(zone);
9014 		} else
9015 			dumping = ISC_TRUE;
9016 		UNLOCK_ZONE(zone);
9017 		if (!dumping) {
9018 			result = zone_dump(zone, ISC_TRUE); /* task locked */
9019 			if (result != ISC_R_SUCCESS)
9020 				dns_zone_log(zone, ISC_LOG_WARNING,
9021 					     "dump failed: %s",
9022 					     dns_result_totext(result));
9023 		}
9024 		break;
9025 	default:
9026 		break;
9027 	}
9028 
9029 	/*
9030 	 * Master/redirect zones send notifies now, if needed
9031 	 */
9032 	switch (zone->type) {
9033 	case dns_zone_master:
9034 	case dns_zone_redirect:
9035 		if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
9036 		     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&&
9037 		    isc_time_compare(&now, &zone->notifytime) >= 0)
9038 			zone_notify(zone, &now);
9039 	default:
9040 		break;
9041 	}
9042 
9043 	/*
9044 	 * Do we need to refresh keys?
9045 	 */
9046 	switch (zone->type) {
9047 	case dns_zone_key:
9048 		if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
9049 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
9050 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
9051 				zone_refreshkeys(zone);
9052 			}
9053 		}
9054 		break;
9055 	case dns_zone_master:
9056 		if (!isc_time_isepoch(&zone->refreshkeytime) &&
9057 		    isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
9058 		    zone->rss_event == NULL)
9059 			zone_rekey(zone);
9060 	default:
9061 		break;
9062 	}
9063 
9064 	switch (zone->type) {
9065 	case dns_zone_master:
9066 	case dns_zone_redirect:
9067 	case dns_zone_slave:
9068 		/*
9069 		 * Do we need to sign/resign some RRsets?
9070 		 */
9071 		if (zone->rss_event != NULL)
9072 			break;
9073 		if (!isc_time_isepoch(&zone->signingtime) &&
9074 		    isc_time_compare(&now, &zone->signingtime) >= 0)
9075 			zone_sign(zone);
9076 		else if (!isc_time_isepoch(&zone->resigntime) &&
9077 		    isc_time_compare(&now, &zone->resigntime) >= 0)
9078 			zone_resigninc(zone);
9079 		else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
9080 			isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
9081 			zone_nsec3chain(zone);
9082 		/*
9083 		 * Do we need to issue a key expiry warning?
9084 		 */
9085 		if (!isc_time_isepoch(&zone->keywarntime) &&
9086 		    isc_time_compare(&now, &zone->keywarntime) >= 0)
9087 			set_key_expiry_warning(zone, zone->key_expiry,
9088 					       isc_time_seconds(&now));
9089 		break;
9090 
9091 	default:
9092 		break;
9093 	}
9094 	zone_settimer(zone, &now);
9095 }
9096 
9097 void
dns_zone_markdirty(dns_zone_t * zone)9098 dns_zone_markdirty(dns_zone_t *zone) {
9099 	isc_uint32_t serial;
9100 	isc_result_t result = ISC_R_SUCCESS;
9101 	dns_zone_t *secure = NULL;
9102 
9103 	/*
9104 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
9105 	 * could result in a deadlock due to a LOR so we will spin if we
9106 	 * can't obtain the both locks.
9107 	 */
9108  again:
9109 	LOCK_ZONE(zone);
9110 	if (zone->type == dns_zone_master) {
9111 		if (inline_raw(zone)) {
9112 			unsigned int soacount;
9113 			secure = zone->secure;
9114 			INSIST(secure != zone);
9115 			TRYLOCK_ZONE(result, secure);
9116 			if (result != ISC_R_SUCCESS) {
9117 				UNLOCK_ZONE(zone);
9118 				secure = NULL;
9119 #ifdef ISC_PLATFORM_USETHREADS
9120 				isc_thread_yield();
9121 #endif
9122 				goto again;
9123 			}
9124 
9125 			ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9126 			if (zone->db != NULL) {
9127 				result = zone_get_from_db(zone, zone->db, NULL,
9128 							  &soacount, &serial,
9129 							  NULL, NULL, NULL,
9130 							  NULL, NULL);
9131 			} else
9132 				result = DNS_R_NOTLOADED;
9133 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9134 			if (result == ISC_R_SUCCESS && soacount > 0U)
9135 				zone_send_secureserial(zone, serial);
9136 		}
9137 
9138 		/* XXXMPA make separate call back */
9139 		if (result == ISC_R_SUCCESS)
9140 			set_resigntime(zone);
9141 	}
9142 	if (secure != NULL)
9143 		UNLOCK_ZONE(secure);
9144 	zone_needdump(zone, DNS_DUMP_DELAY);
9145 	UNLOCK_ZONE(zone);
9146 }
9147 
9148 void
dns_zone_expire(dns_zone_t * zone)9149 dns_zone_expire(dns_zone_t *zone) {
9150 	REQUIRE(DNS_ZONE_VALID(zone));
9151 
9152 	LOCK_ZONE(zone);
9153 	zone_expire(zone);
9154 	UNLOCK_ZONE(zone);
9155 }
9156 
9157 static void
zone_expire(dns_zone_t * zone)9158 zone_expire(dns_zone_t *zone) {
9159 	/*
9160 	 * 'zone' locked by caller.
9161 	 */
9162 
9163 	REQUIRE(LOCKED_ZONE(zone));
9164 
9165 	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
9166 
9167 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
9168 	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
9169 	zone->retry = DNS_ZONE_DEFAULTRETRY;
9170 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9171 	zone_unload(zone);
9172 }
9173 
9174 void
dns_zone_refresh(dns_zone_t * zone)9175 dns_zone_refresh(dns_zone_t *zone) {
9176 	isc_interval_t i;
9177 	isc_uint32_t oldflags;
9178 	unsigned int j;
9179 	isc_result_t result;
9180 
9181 	REQUIRE(DNS_ZONE_VALID(zone));
9182 
9183 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
9184 		return;
9185 
9186 	/*
9187 	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
9188 	 * in progress at a time.
9189 	 */
9190 
9191 	LOCK_ZONE(zone);
9192 	oldflags = zone->flags;
9193 	if (zone->masterscnt == 0) {
9194 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
9195 		if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
9196 			dns_zone_log(zone, ISC_LOG_ERROR,
9197 				     "cannot refresh: no masters");
9198 		goto unlock;
9199 	}
9200 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
9201 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9202 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9203 	if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
9204 		goto unlock;
9205 
9206 	/*
9207 	 * Set the next refresh time as if refresh check has failed.
9208 	 * Setting this to the retry time will do that.  XXXMLG
9209 	 * If we are successful it will be reset using zone->refresh.
9210 	 */
9211 	isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
9212 			 0);
9213 	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
9214 	if (result != ISC_R_SUCCESS)
9215 		dns_zone_log(zone, ISC_LOG_WARNING,
9216 			     "isc_time_nowplusinterval() failed: %s",
9217 			     dns_result_totext(result));
9218 
9219 	/*
9220 	 * When lacking user-specified timer values from the SOA,
9221 	 * do exponential backoff of the retry time up to a
9222 	 * maximum of six hours.
9223 	 */
9224 	if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
9225 		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
9226 
9227 	zone->curmaster = 0;
9228 	for (j = 0; j < zone->masterscnt; j++)
9229 		zone->mastersok[j] = ISC_FALSE;
9230 	/* initiate soa query */
9231 	queue_soa_query(zone);
9232  unlock:
9233 	UNLOCK_ZONE(zone);
9234 }
9235 
9236 isc_result_t
dns_zone_flush(dns_zone_t * zone)9237 dns_zone_flush(dns_zone_t *zone) {
9238 	isc_result_t result = ISC_R_SUCCESS;
9239 	isc_boolean_t dumping;
9240 
9241 	REQUIRE(DNS_ZONE_VALID(zone));
9242 
9243 	LOCK_ZONE(zone);
9244 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
9245 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9246 	    zone->masterfile != NULL) {
9247 		result = ISC_R_ALREADYRUNNING;
9248 		dumping = was_dumping(zone);
9249 	} else
9250 		dumping = ISC_TRUE;
9251 	UNLOCK_ZONE(zone);
9252 	if (!dumping)
9253 		result = zone_dump(zone, ISC_FALSE);	/* Unknown task. */
9254 	return (result);
9255 }
9256 
9257 isc_result_t
dns_zone_dump(dns_zone_t * zone)9258 dns_zone_dump(dns_zone_t *zone) {
9259 	isc_result_t result = ISC_R_ALREADYRUNNING;
9260 	isc_boolean_t dumping;
9261 
9262 	REQUIRE(DNS_ZONE_VALID(zone));
9263 
9264 	LOCK_ZONE(zone);
9265 	dumping = was_dumping(zone);
9266 	UNLOCK_ZONE(zone);
9267 	if (!dumping)
9268 		result = zone_dump(zone, ISC_FALSE);	/* Unknown task. */
9269 	return (result);
9270 }
9271 
9272 static void
zone_needdump(dns_zone_t * zone,unsigned int delay)9273 zone_needdump(dns_zone_t *zone, unsigned int delay) {
9274 	const char me[] = "zone_needdump";
9275 	isc_time_t dumptime;
9276 	isc_time_t now;
9277 
9278 	/*
9279 	 * 'zone' locked by caller
9280 	 */
9281 
9282 	REQUIRE(DNS_ZONE_VALID(zone));
9283 	REQUIRE(LOCKED_ZONE(zone));
9284 	ENTER;
9285 
9286 	/*
9287 	 * Do we have a place to dump to and are we loaded?
9288 	 */
9289 	if (zone->masterfile == NULL ||
9290 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
9291 		return;
9292 
9293 	TIME_NOW(&now);
9294 	/* add some noise */
9295 	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
9296 
9297 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9298 	if (isc_time_isepoch(&zone->dumptime) ||
9299 	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
9300 		zone->dumptime = dumptime;
9301 	if (zone->task != NULL)
9302 		zone_settimer(zone, &now);
9303 }
9304 
9305 static void
dump_done(void * arg,isc_result_t result)9306 dump_done(void *arg, isc_result_t result) {
9307 	const char me[] = "dump_done";
9308 	dns_zone_t *zone = arg;
9309 	dns_zone_t *secure = NULL;
9310 	dns_db_t *db;
9311 	dns_dbversion_t *version;
9312 	isc_boolean_t again = ISC_FALSE;
9313 	isc_boolean_t compact = ISC_FALSE;
9314 	isc_uint32_t serial;
9315 	isc_result_t tresult;
9316 
9317 	REQUIRE(DNS_ZONE_VALID(zone));
9318 
9319 	ENTER;
9320 
9321 	if (result == ISC_R_SUCCESS && zone->journal != NULL &&
9322 	    zone->journalsize != -1) {
9323 		/*
9324 		 * We don't own these, zone->dctx must stay valid.
9325 		 */
9326 		db = dns_dumpctx_db(zone->dctx);
9327 		version = dns_dumpctx_version(zone->dctx);
9328 		tresult = dns_db_getsoaserial(db, version, &serial);
9329 
9330 		/*
9331 		 * Handle lock order inversion.
9332 		 */
9333  again:
9334 		LOCK_ZONE(zone);
9335 		if (inline_raw(zone)) {
9336 			secure = zone->secure;
9337 			INSIST(secure != zone);
9338 			TRYLOCK_ZONE(result, secure);
9339 			if (result != ISC_R_SUCCESS) {
9340 				UNLOCK_ZONE(zone);
9341 				secure = NULL;
9342 #if ISC_PLATFORM_USETHREADS
9343 				isc_thread_yield();
9344 #endif
9345 				goto again;
9346 			}
9347 		}
9348 
9349 		/*
9350 		 * If there is a secure version of this zone
9351 		 * use its serial if it is less than ours.
9352 		 */
9353 		if (tresult == ISC_R_SUCCESS && secure != NULL) {
9354 			isc_uint32_t sserial;
9355 			isc_result_t mresult;
9356 
9357 			ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
9358 			if (secure->db != NULL) {
9359 				mresult = dns_db_getsoaserial(zone->secure->db,
9360 							      NULL, &sserial);
9361 				if (mresult == ISC_R_SUCCESS &&
9362 				    isc_serial_lt(sserial, serial))
9363 					serial = sserial;
9364 			}
9365 			ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
9366 		}
9367 		if (secure != NULL)
9368 			UNLOCK_ZONE(secure);
9369 		UNLOCK_ZONE(zone);
9370 
9371 		/*
9372 		 * Note: we are task locked here so we can test
9373 		 * zone->xfr safely.
9374 		 */
9375 		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
9376 			tresult = dns_journal_compact(zone->mctx,
9377 						      zone->journal,
9378 						      serial,
9379 						      zone->journalsize);
9380 			switch (tresult) {
9381 			case ISC_R_SUCCESS:
9382 			case ISC_R_NOSPACE:
9383 			case ISC_R_NOTFOUND:
9384 				dns_zone_log(zone, ISC_LOG_DEBUG(3),
9385 					     "dns_journal_compact: %s",
9386 					     dns_result_totext(tresult));
9387 				break;
9388 			default:
9389 				dns_zone_log(zone, ISC_LOG_ERROR,
9390 					     "dns_journal_compact failed: %s",
9391 					     dns_result_totext(tresult));
9392 				break;
9393 			}
9394 		} else if (tresult == ISC_R_SUCCESS) {
9395 			compact = ISC_TRUE;
9396 			zone->compact_serial = serial;
9397 		}
9398 	}
9399 
9400 	LOCK_ZONE(zone);
9401 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9402 	if (compact)
9403 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
9404 	if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
9405 		/*
9406 		 * Try again in a short while.
9407 		 */
9408 		zone_needdump(zone, DNS_DUMP_DELAY);
9409 	} else if (result == ISC_R_SUCCESS &&
9410 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9411 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9412 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9413 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9414 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9415 		isc_time_settoepoch(&zone->dumptime);
9416 		again = ISC_TRUE;
9417 	} else if (result == ISC_R_SUCCESS)
9418 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9419 
9420 	if (zone->dctx != NULL)
9421 		dns_dumpctx_detach(&zone->dctx);
9422 	zonemgr_putio(&zone->writeio);
9423 	UNLOCK_ZONE(zone);
9424 	if (again)
9425 		(void)zone_dump(zone, ISC_FALSE);
9426 	dns_zone_idetach(&zone);
9427 }
9428 
9429 static isc_result_t
zone_dump(dns_zone_t * zone,isc_boolean_t compact)9430 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
9431 	const char me[] = "zone_dump";
9432 	isc_result_t result;
9433 	dns_dbversion_t *version = NULL;
9434 	isc_boolean_t again;
9435 	dns_db_t *db = NULL;
9436 	char *masterfile = NULL;
9437 	dns_masterformat_t masterformat = dns_masterformat_none;
9438 
9439 /*
9440  * 'compact' MUST only be set if we are task locked.
9441  */
9442 
9443 	REQUIRE(DNS_ZONE_VALID(zone));
9444 	ENTER;
9445 
9446  redo:
9447 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9448 	if (zone->db != NULL)
9449 		dns_db_attach(zone->db, &db);
9450 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9451 	LOCK_ZONE(zone);
9452 	if (zone->masterfile != NULL) {
9453 		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
9454 		masterformat = zone->masterformat;
9455 	}
9456 	UNLOCK_ZONE(zone);
9457 	if (db == NULL) {
9458 		result = DNS_R_NOTLOADED;
9459 		goto fail;
9460 	}
9461 	if (masterfile == NULL) {
9462 		result = DNS_R_NOMASTERFILE;
9463 		goto fail;
9464 	}
9465 
9466 	if (compact && zone->type != dns_zone_stub) {
9467 		dns_zone_t *dummy = NULL;
9468 		LOCK_ZONE(zone);
9469 		zone_iattach(zone, &dummy);
9470 		result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
9471 				       zone_gotwritehandle, zone,
9472 				       &zone->writeio);
9473 		if (result != ISC_R_SUCCESS)
9474 			zone_idetach(&dummy);
9475 		else
9476 			result = DNS_R_CONTINUE;
9477 		UNLOCK_ZONE(zone);
9478 	} else {
9479 		const dns_master_style_t *output_style;
9480 
9481 		dns_masterrawheader_t rawdata;
9482 		dns_db_currentversion(db, &version);
9483 		dns_master_initrawheader(&rawdata);
9484 		if (inline_secure(zone))
9485 			get_raw_serial(zone->raw, &rawdata);
9486 		if (zone->type == dns_zone_key)
9487 			output_style = &dns_master_style_keyzone;
9488 		else
9489 			output_style = &dns_master_style_default;
9490 		result = dns_master_dump3(zone->mctx, db, version,
9491 					  output_style, masterfile,
9492 					  masterformat, &rawdata);
9493 		dns_db_closeversion(db, &version, ISC_FALSE);
9494 	}
9495  fail:
9496 	if (db != NULL)
9497 		dns_db_detach(&db);
9498 	if (masterfile != NULL)
9499 		isc_mem_free(zone->mctx, masterfile);
9500 	masterfile = NULL;
9501 
9502 	if (result == DNS_R_CONTINUE)
9503 		return (ISC_R_SUCCESS); /* XXXMPA */
9504 
9505 	again = ISC_FALSE;
9506 	LOCK_ZONE(zone);
9507 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9508 	if (result != ISC_R_SUCCESS) {
9509 		/*
9510 		 * Try again in a short while.
9511 		 */
9512 		zone_needdump(zone, DNS_DUMP_DELAY);
9513 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9514 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9515 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9516 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9517 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9518 		isc_time_settoepoch(&zone->dumptime);
9519 		again = ISC_TRUE;
9520 	} else
9521 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9522 	UNLOCK_ZONE(zone);
9523 	if (again)
9524 		goto redo;
9525 
9526 	return (result);
9527 }
9528 
9529 static isc_result_t
dumptostream(dns_zone_t * zone,FILE * fd,const dns_master_style_t * style,dns_masterformat_t format,const isc_uint32_t rawversion)9530 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
9531 	     dns_masterformat_t format, const isc_uint32_t rawversion)
9532 {
9533 	isc_result_t result;
9534 	dns_dbversion_t *version = NULL;
9535 	dns_db_t *db = NULL;
9536 	dns_masterrawheader_t rawdata;
9537 
9538 	REQUIRE(DNS_ZONE_VALID(zone));
9539 
9540 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9541 	if (zone->db != NULL)
9542 		dns_db_attach(zone->db, &db);
9543 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9544 	if (db == NULL)
9545 		return (DNS_R_NOTLOADED);
9546 
9547 	dns_db_currentversion(db, &version);
9548 	dns_master_initrawheader(&rawdata);
9549 	if (rawversion == 0)
9550 		rawdata.flags |= DNS_MASTERRAW_COMPAT;
9551 	else if (inline_secure(zone))
9552 		get_raw_serial(zone->raw, &rawdata);
9553 	else if (zone->sourceserialset) {
9554 		rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
9555 		rawdata.sourceserial = zone->sourceserial;
9556 	}
9557 	result = dns_master_dumptostream3(zone->mctx, db, version, style,
9558 					  format, &rawdata, fd);
9559 	dns_db_closeversion(db, &version, ISC_FALSE);
9560 	dns_db_detach(&db);
9561 	return (result);
9562 }
9563 
9564 isc_result_t
dns_zone_dumptostream3(dns_zone_t * zone,FILE * fd,dns_masterformat_t format,const dns_master_style_t * style,const isc_uint32_t rawversion)9565 dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9566 		       const dns_master_style_t *style,
9567 		       const isc_uint32_t rawversion)
9568 {
9569 	return (dumptostream(zone, fd, style, format, rawversion));
9570 }
9571 
9572 isc_result_t
dns_zone_dumptostream2(dns_zone_t * zone,FILE * fd,dns_masterformat_t format,const dns_master_style_t * style)9573 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9574 		       const dns_master_style_t *style) {
9575 	return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
9576 }
9577 
9578 isc_result_t
dns_zone_dumptostream(dns_zone_t * zone,FILE * fd)9579 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
9580 	return (dumptostream(zone, fd, &dns_master_style_default,
9581 			     dns_masterformat_text, 0));
9582 }
9583 
9584 isc_result_t
dns_zone_fulldumptostream(dns_zone_t * zone,FILE * fd)9585 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
9586 	return (dumptostream(zone, fd, &dns_master_style_full,
9587 			     dns_masterformat_text, 0));
9588 }
9589 
9590 void
dns_zone_unload(dns_zone_t * zone)9591 dns_zone_unload(dns_zone_t *zone) {
9592 	REQUIRE(DNS_ZONE_VALID(zone));
9593 
9594 	LOCK_ZONE(zone);
9595 	zone_unload(zone);
9596 	UNLOCK_ZONE(zone);
9597 }
9598 
9599 static void
notify_cancel(dns_zone_t * zone)9600 notify_cancel(dns_zone_t *zone) {
9601 	dns_notify_t *notify;
9602 
9603 	/*
9604 	 * 'zone' locked by caller.
9605 	 */
9606 
9607 	REQUIRE(LOCKED_ZONE(zone));
9608 
9609 	for (notify = ISC_LIST_HEAD(zone->notifies);
9610 	     notify != NULL;
9611 	     notify = ISC_LIST_NEXT(notify, link)) {
9612 		if (notify->find != NULL)
9613 			dns_adb_cancelfind(notify->find);
9614 		if (notify->request != NULL)
9615 			dns_request_cancel(notify->request);
9616 	}
9617 }
9618 
9619 static void
forward_cancel(dns_zone_t * zone)9620 forward_cancel(dns_zone_t *zone) {
9621 	dns_forward_t *forward;
9622 
9623 	/*
9624 	 * 'zone' locked by caller.
9625 	 */
9626 
9627 	REQUIRE(LOCKED_ZONE(zone));
9628 
9629 	for (forward = ISC_LIST_HEAD(zone->forwards);
9630 	     forward != NULL;
9631 	     forward = ISC_LIST_NEXT(forward, link)) {
9632 		if (forward->request != NULL)
9633 			dns_request_cancel(forward->request);
9634 	}
9635 }
9636 
9637 static void
zone_unload(dns_zone_t * zone)9638 zone_unload(dns_zone_t *zone) {
9639 	/*
9640 	 * 'zone' locked by caller.
9641 	 */
9642 
9643 	REQUIRE(LOCKED_ZONE(zone));
9644 
9645 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
9646 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9647 		if (zone->writeio != NULL)
9648 			zonemgr_cancelio(zone->writeio);
9649 
9650 		if (zone->dctx != NULL)
9651 			dns_dumpctx_cancel(zone->dctx);
9652 	}
9653 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9654 	zone_detachdb(zone);
9655 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9656 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
9657 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9658 }
9659 
9660 void
dns_zone_setminrefreshtime(dns_zone_t * zone,isc_uint32_t val)9661 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9662 	REQUIRE(DNS_ZONE_VALID(zone));
9663 	REQUIRE(val > 0);
9664 
9665 	zone->minrefresh = val;
9666 }
9667 
9668 void
dns_zone_setmaxrefreshtime(dns_zone_t * zone,isc_uint32_t val)9669 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9670 	REQUIRE(DNS_ZONE_VALID(zone));
9671 	REQUIRE(val > 0);
9672 
9673 	zone->maxrefresh = val;
9674 }
9675 
9676 void
dns_zone_setminretrytime(dns_zone_t * zone,isc_uint32_t val)9677 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
9678 	REQUIRE(DNS_ZONE_VALID(zone));
9679 	REQUIRE(val > 0);
9680 
9681 	zone->minretry = val;
9682 }
9683 
9684 void
dns_zone_setmaxretrytime(dns_zone_t * zone,isc_uint32_t val)9685 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
9686 	REQUIRE(DNS_ZONE_VALID(zone));
9687 	REQUIRE(val > 0);
9688 
9689 	zone->maxretry = val;
9690 }
9691 
9692 static isc_boolean_t
notify_isqueued(dns_zone_t * zone,unsigned int flags,dns_name_t * name,isc_sockaddr_t * addr,dns_tsigkey_t * key)9693 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
9694 		isc_sockaddr_t *addr, dns_tsigkey_t *key)
9695 {
9696 	dns_notify_t *notify;
9697 	dns_zonemgr_t *zmgr;
9698 	isc_result_t result;
9699 
9700 	for (notify = ISC_LIST_HEAD(zone->notifies);
9701 	     notify != NULL;
9702 	     notify = ISC_LIST_NEXT(notify, link)) {
9703 		if (notify->request != NULL)
9704 			continue;
9705 		if (name != NULL && dns_name_dynamic(&notify->ns) &&
9706 		    dns_name_equal(name, &notify->ns))
9707 			goto requeue;
9708 		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
9709 		    notify->key == key)
9710 			goto requeue;
9711 	}
9712 	return (ISC_FALSE);
9713 
9714 requeue:
9715 	/*
9716 	 * If we are enqueued on the startup ratelimiter and this is
9717 	 * not a startup notify, re-enqueue on the normal notify
9718 	 * ratelimiter.
9719 	 */
9720 	if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
9721 	    (notify->flags & DNS_NOTIFY_STARTUP) != 0) {
9722 		zmgr = notify->zone->zmgr;
9723 		result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
9724 						 notify->event);
9725 		if (result != ISC_R_SUCCESS)
9726 			return (ISC_TRUE);
9727 
9728 		notify->flags &= ~DNS_NOTIFY_STARTUP;
9729 		result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
9730 						 notify->zone->task,
9731 						 &notify->event);
9732 		if (result != ISC_R_SUCCESS) {
9733 			isc_event_free(&notify->event);
9734 			return (ISC_FALSE);
9735 		}
9736 	}
9737 
9738 	return (ISC_TRUE);
9739 }
9740 
9741 static isc_boolean_t
notify_isself(dns_zone_t * zone,isc_sockaddr_t * dst)9742 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
9743 	dns_tsigkey_t *key = NULL;
9744 	isc_sockaddr_t src;
9745 	isc_sockaddr_t any;
9746 	isc_boolean_t isself;
9747 	isc_netaddr_t dstaddr;
9748 	isc_result_t result;
9749 
9750 	if (zone->view == NULL || zone->isself == NULL)
9751 		return (ISC_FALSE);
9752 
9753 	switch (isc_sockaddr_pf(dst)) {
9754 	case PF_INET:
9755 		src = zone->notifysrc4;
9756 		isc_sockaddr_any(&any);
9757 		break;
9758 	case PF_INET6:
9759 		src = zone->notifysrc6;
9760 		isc_sockaddr_any6(&any);
9761 		break;
9762 	default:
9763 		return (ISC_FALSE);
9764 	}
9765 
9766 	/*
9767 	 * When sending from any the kernel will assign a source address
9768 	 * that matches the destination address.
9769 	 */
9770 	if (isc_sockaddr_eqaddr(&any, &src))
9771 		src = *dst;
9772 
9773 	isc_netaddr_fromsockaddr(&dstaddr, dst);
9774 	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
9775 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
9776 		return (ISC_FALSE);
9777 	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
9778 				zone->isselfarg);
9779 	if (key != NULL)
9780 		dns_tsigkey_detach(&key);
9781 	return (isself);
9782 }
9783 
9784 static void
notify_destroy(dns_notify_t * notify,isc_boolean_t locked)9785 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
9786 	isc_mem_t *mctx;
9787 
9788 	REQUIRE(DNS_NOTIFY_VALID(notify));
9789 
9790 	if (notify->zone != NULL) {
9791 		if (!locked)
9792 			LOCK_ZONE(notify->zone);
9793 		REQUIRE(LOCKED_ZONE(notify->zone));
9794 		if (ISC_LINK_LINKED(notify, link))
9795 			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
9796 		if (!locked)
9797 			UNLOCK_ZONE(notify->zone);
9798 		if (locked)
9799 			zone_idetach(&notify->zone);
9800 		else
9801 			dns_zone_idetach(&notify->zone);
9802 	}
9803 	if (notify->find != NULL)
9804 		dns_adb_destroyfind(&notify->find);
9805 	if (notify->request != NULL)
9806 		dns_request_destroy(&notify->request);
9807 	if (dns_name_dynamic(&notify->ns))
9808 		dns_name_free(&notify->ns, notify->mctx);
9809 	if (notify->key != NULL)
9810 		dns_tsigkey_detach(&notify->key);
9811 	mctx = notify->mctx;
9812 	isc_mem_put(notify->mctx, notify, sizeof(*notify));
9813 	isc_mem_detach(&mctx);
9814 }
9815 
9816 static isc_result_t
notify_create(isc_mem_t * mctx,unsigned int flags,dns_notify_t ** notifyp)9817 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
9818 	dns_notify_t *notify;
9819 
9820 	REQUIRE(notifyp != NULL && *notifyp == NULL);
9821 
9822 	notify = isc_mem_get(mctx, sizeof(*notify));
9823 	if (notify == NULL)
9824 		return (ISC_R_NOMEMORY);
9825 
9826 	notify->mctx = NULL;
9827 	isc_mem_attach(mctx, &notify->mctx);
9828 	notify->flags = flags;
9829 	notify->zone = NULL;
9830 	notify->find = NULL;
9831 	notify->request = NULL;
9832 	notify->key = NULL;
9833 	notify->event = NULL;
9834 	isc_sockaddr_any(&notify->dst);
9835 	dns_name_init(&notify->ns, NULL);
9836 	ISC_LINK_INIT(notify, link);
9837 	notify->magic = NOTIFY_MAGIC;
9838 	*notifyp = notify;
9839 	return (ISC_R_SUCCESS);
9840 }
9841 
9842 /*
9843  * XXXAG should check for DNS_ZONEFLG_EXITING
9844  */
9845 static void
process_adb_event(isc_task_t * task,isc_event_t * ev)9846 process_adb_event(isc_task_t *task, isc_event_t *ev) {
9847 	dns_notify_t *notify;
9848 	isc_eventtype_t result;
9849 
9850 	UNUSED(task);
9851 
9852 	notify = ev->ev_arg;
9853 	REQUIRE(DNS_NOTIFY_VALID(notify));
9854 	INSIST(task == notify->zone->task);
9855 	result = ev->ev_type;
9856 	isc_event_free(&ev);
9857 	if (result == DNS_EVENT_ADBMOREADDRESSES) {
9858 		dns_adb_destroyfind(&notify->find);
9859 		notify_find_address(notify);
9860 		return;
9861 	}
9862 	if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
9863 		LOCK_ZONE(notify->zone);
9864 		notify_send(notify);
9865 		UNLOCK_ZONE(notify->zone);
9866 	}
9867 	notify_destroy(notify, ISC_FALSE);
9868 }
9869 
9870 static void
notify_find_address(dns_notify_t * notify)9871 notify_find_address(dns_notify_t *notify) {
9872 	isc_result_t result;
9873 	unsigned int options;
9874 
9875 	REQUIRE(DNS_NOTIFY_VALID(notify));
9876 	options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
9877 		  DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
9878 
9879 	if (notify->zone->view->adb == NULL)
9880 		goto destroy;
9881 
9882 	result = dns_adb_createfind(notify->zone->view->adb,
9883 				    notify->zone->task,
9884 				    process_adb_event, notify,
9885 				    &notify->ns, dns_rootname, 0,
9886 				    options, 0, NULL,
9887 				    notify->zone->view->dstport,
9888 				    &notify->find);
9889 
9890 	/* Something failed? */
9891 	if (result != ISC_R_SUCCESS)
9892 		goto destroy;
9893 
9894 	/* More addresses pending? */
9895 	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
9896 		return;
9897 
9898 	/* We have as many addresses as we can get. */
9899 	LOCK_ZONE(notify->zone);
9900 	notify_send(notify);
9901 	UNLOCK_ZONE(notify->zone);
9902 
9903  destroy:
9904 	notify_destroy(notify, ISC_FALSE);
9905 }
9906 
9907 
9908 static isc_result_t
notify_send_queue(dns_notify_t * notify,isc_boolean_t startup)9909 notify_send_queue(dns_notify_t *notify, isc_boolean_t startup) {
9910 	isc_event_t *e;
9911 	isc_result_t result;
9912 
9913 	INSIST(notify->event == NULL);
9914 	e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
9915 			       notify_send_toaddr, notify, sizeof(isc_event_t));
9916 	if (e == NULL)
9917 		return (ISC_R_NOMEMORY);
9918 	if (startup)
9919 		notify->event = e;
9920 	e->ev_arg = notify;
9921 	e->ev_sender = NULL;
9922 	result = isc_ratelimiter_enqueue(startup
9923 					  ? notify->zone->zmgr->startupnotifyrl
9924 					  : notify->zone->zmgr->notifyrl,
9925 					 notify->zone->task, &e);
9926 	if (result != ISC_R_SUCCESS) {
9927 		isc_event_free(&e);
9928 		notify->event = NULL;
9929 	}
9930 	return (result);
9931 }
9932 
9933 static void
notify_send_toaddr(isc_task_t * task,isc_event_t * event)9934 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
9935 	dns_notify_t *notify;
9936 	isc_result_t result;
9937 	dns_message_t *message = NULL;
9938 	isc_netaddr_t dstip;
9939 	dns_tsigkey_t *key = NULL;
9940 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9941 	isc_sockaddr_t src;
9942 	int timeout;
9943 	isc_boolean_t have_notifysource = ISC_FALSE;
9944 
9945 	notify = event->ev_arg;
9946 	REQUIRE(DNS_NOTIFY_VALID(notify));
9947 
9948 	UNUSED(task);
9949 
9950 	LOCK_ZONE(notify->zone);
9951 
9952 	notify->event = NULL;
9953 
9954 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
9955 		result = ISC_R_CANCELED;
9956 		goto cleanup;
9957 	}
9958 
9959 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
9960 	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
9961 	    notify->zone->view->requestmgr == NULL ||
9962 	    notify->zone->db == NULL) {
9963 		result = ISC_R_CANCELED;
9964 		goto cleanup;
9965 	}
9966 
9967 	/*
9968 	 * The raw IPv4 address should also exist.  Don't send to the
9969 	 * mapped form.
9970 	 */
9971 	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
9972 	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
9973 		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9974 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
9975 			   "notify: ignoring IPv6 mapped IPV4 address: %s",
9976 			   addrbuf);
9977 		result = ISC_R_CANCELED;
9978 		goto cleanup;
9979 	}
9980 
9981 	result = notify_createmessage(notify->zone, notify->flags, &message);
9982 	if (result != ISC_R_SUCCESS)
9983 		goto cleanup;
9984 
9985 	if (notify->key != NULL) {
9986 		/* Transfer ownership of key */
9987 		key = notify->key;
9988 		notify->key = NULL;
9989 	} else {
9990 		isc_netaddr_fromsockaddr(&dstip, &notify->dst);
9991 		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9992 		result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
9993 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9994 			notify_log(notify->zone, ISC_LOG_ERROR,
9995 				   "NOTIFY to %s not sent. "
9996 				   "Peer TSIG key lookup failure.", addrbuf);
9997 			goto cleanup_message;
9998 		}
9999 	}
10000 
10001 	/* XXX: should we log the tsig key too? */
10002 	notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
10003 		   addrbuf);
10004 	if (notify->zone->view->peers != NULL) {
10005 		dns_peer_t *peer = NULL;
10006 		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
10007 						 &dstip, &peer);
10008 		if (result == ISC_R_SUCCESS) {
10009 			result = dns_peer_getnotifysource(peer, &src);
10010 			if (result == ISC_R_SUCCESS)
10011 				have_notifysource = ISC_TRUE;
10012 		}
10013 	}
10014 	switch (isc_sockaddr_pf(&notify->dst)) {
10015 	case PF_INET:
10016 		if (!have_notifysource)
10017 			src = notify->zone->notifysrc4;
10018 		break;
10019 	case PF_INET6:
10020 		if (!have_notifysource)
10021 			src = notify->zone->notifysrc6;
10022 		break;
10023 	default:
10024 		result = ISC_R_NOTIMPLEMENTED;
10025 		goto cleanup_key;
10026 	}
10027 	timeout = 15;
10028 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
10029 		timeout = 30;
10030 	result = dns_request_createvia2(notify->zone->view->requestmgr,
10031 					message, &src, &notify->dst, 0, key,
10032 					timeout * 3, timeout,
10033 					notify->zone->task, notify_done,
10034 					notify, &notify->request);
10035 	if (result == ISC_R_SUCCESS) {
10036 		if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
10037 			inc_stats(notify->zone,
10038 				  dns_zonestatscounter_notifyoutv4);
10039 		} else {
10040 			inc_stats(notify->zone,
10041 				  dns_zonestatscounter_notifyoutv6);
10042 		}
10043 	}
10044 
10045  cleanup_key:
10046 	if (key != NULL)
10047 		dns_tsigkey_detach(&key);
10048  cleanup_message:
10049 	dns_message_destroy(&message);
10050  cleanup:
10051 	UNLOCK_ZONE(notify->zone);
10052 	isc_event_free(&event);
10053 	if (result != ISC_R_SUCCESS)
10054 		notify_destroy(notify, ISC_FALSE);
10055 }
10056 
10057 static void
notify_send(dns_notify_t * notify)10058 notify_send(dns_notify_t *notify) {
10059 	dns_adbaddrinfo_t *ai;
10060 	isc_sockaddr_t dst;
10061 	isc_result_t result;
10062 	dns_notify_t *new = NULL;
10063 	unsigned int flags;
10064 	isc_boolean_t startup;
10065 
10066 	/*
10067 	 * Zone lock held by caller.
10068 	 */
10069 	REQUIRE(DNS_NOTIFY_VALID(notify));
10070 	REQUIRE(LOCKED_ZONE(notify->zone));
10071 
10072 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING))
10073 		return;
10074 
10075 	for (ai = ISC_LIST_HEAD(notify->find->list);
10076 	     ai != NULL;
10077 	     ai = ISC_LIST_NEXT(ai, publink)) {
10078 		dst = ai->sockaddr;
10079 		if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
10080 				    NULL))
10081 			continue;
10082 		if (notify_isself(notify->zone, &dst))
10083 			continue;
10084 		new = NULL;
10085 		flags = notify->flags & DNS_NOTIFY_NOSOA;
10086 		result = notify_create(notify->mctx, flags, &new);
10087 		if (result != ISC_R_SUCCESS)
10088 			goto cleanup;
10089 		zone_iattach(notify->zone, &new->zone);
10090 		ISC_LIST_APPEND(new->zone->notifies, new, link);
10091 		new->dst = dst;
10092 		startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
10093 		result = notify_send_queue(new, startup);
10094 		if (result != ISC_R_SUCCESS)
10095 			goto cleanup;
10096 		new = NULL;
10097 	}
10098 
10099  cleanup:
10100 	if (new != NULL)
10101 		notify_destroy(new, ISC_TRUE);
10102 }
10103 
10104 void
dns_zone_notify(dns_zone_t * zone)10105 dns_zone_notify(dns_zone_t *zone) {
10106 	isc_time_t now;
10107 
10108 	REQUIRE(DNS_ZONE_VALID(zone));
10109 
10110 	LOCK_ZONE(zone);
10111 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10112 
10113 	TIME_NOW(&now);
10114 	zone_settimer(zone, &now);
10115 	UNLOCK_ZONE(zone);
10116 }
10117 
10118 static void
zone_notify(dns_zone_t * zone,isc_time_t * now)10119 zone_notify(dns_zone_t *zone, isc_time_t *now) {
10120 	dns_dbnode_t *node = NULL;
10121 	dns_db_t *zonedb = NULL;
10122 	dns_dbversion_t *version = NULL;
10123 	dns_name_t *origin = NULL;
10124 	dns_name_t master;
10125 	dns_rdata_ns_t ns;
10126 	dns_rdata_soa_t soa;
10127 	isc_uint32_t serial;
10128 	dns_rdata_t rdata = DNS_RDATA_INIT;
10129 	dns_rdataset_t nsrdset;
10130 	dns_rdataset_t soardset;
10131 	isc_result_t result;
10132 	unsigned int i;
10133 	isc_sockaddr_t dst;
10134 	isc_boolean_t isqueued;
10135 	dns_notifytype_t notifytype;
10136 	unsigned int flags = 0;
10137 	isc_boolean_t loggednotify = ISC_FALSE;
10138 	isc_boolean_t startup;
10139 
10140 	REQUIRE(DNS_ZONE_VALID(zone));
10141 
10142 	LOCK_ZONE(zone);
10143 	startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10144 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10145 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
10146 	notifytype = zone->notifytype;
10147 	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
10148 	UNLOCK_ZONE(zone);
10149 
10150 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
10151 	    ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
10152 		return;
10153 
10154 	if (notifytype == dns_notifytype_no)
10155 		return;
10156 
10157 	if (notifytype == dns_notifytype_masteronly &&
10158 	    zone->type != dns_zone_master)
10159 		return;
10160 
10161 	origin = &zone->origin;
10162 
10163 	/*
10164 	 * If the zone is dialup we are done as we don't want to send
10165 	 * the current soa so as to force a refresh query.
10166 	 */
10167 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
10168 		flags |= DNS_NOTIFY_NOSOA;
10169 
10170 	/*
10171 	 * Record that this was a notify due to starting up.
10172 	 */
10173 	if (startup)
10174 		flags |= DNS_NOTIFY_STARTUP;
10175 
10176 	/*
10177 	 * Get SOA RRset.
10178 	 */
10179 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10180 	if (zone->db != NULL)
10181 		dns_db_attach(zone->db, &zonedb);
10182 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10183 	if (zonedb == NULL)
10184 		return;
10185 	dns_db_currentversion(zonedb, &version);
10186 	result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
10187 	if (result != ISC_R_SUCCESS)
10188 		goto cleanup1;
10189 
10190 	dns_rdataset_init(&soardset);
10191 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
10192 				     dns_rdatatype_none, 0, &soardset, NULL);
10193 	if (result != ISC_R_SUCCESS)
10194 		goto cleanup2;
10195 
10196 	/*
10197 	 * Find serial and master server's name.
10198 	 */
10199 	dns_name_init(&master, NULL);
10200 	result = dns_rdataset_first(&soardset);
10201 	if (result != ISC_R_SUCCESS)
10202 		goto cleanup3;
10203 	dns_rdataset_current(&soardset, &rdata);
10204 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
10205 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
10206 	dns_rdata_reset(&rdata);
10207 	result = dns_name_dup(&soa.origin, zone->mctx, &master);
10208 	serial = soa.serial;
10209 	dns_rdataset_disassociate(&soardset);
10210 	if (result != ISC_R_SUCCESS)
10211 		goto cleanup3;
10212 
10213 	/*
10214 	 * Enqueue notify requests for 'also-notify' servers.
10215 	 */
10216 	LOCK_ZONE(zone);
10217 	for (i = 0; i < zone->notifycnt; i++) {
10218 		dns_tsigkey_t *key = NULL;
10219 		dns_notify_t *notify = NULL;
10220 
10221 		if ((zone->notifykeynames != NULL) &&
10222 		    (zone->notifykeynames[i] != NULL)) {
10223 			dns_view_t *view = dns_zone_getview(zone);
10224 			dns_name_t *keyname = zone->notifykeynames[i];
10225 			(void)dns_view_gettsig(view, keyname, &key);
10226 		}
10227 
10228 		dst = zone->notify[i];
10229 		if (notify_isqueued(zone, flags, NULL, &dst, key)) {
10230 			if (key != NULL)
10231 				dns_tsigkey_detach(&key);
10232 			continue;
10233 		}
10234 
10235 		result = notify_create(zone->mctx, flags, &notify);
10236 		if (result != ISC_R_SUCCESS) {
10237 			if (key != NULL)
10238 				dns_tsigkey_detach(&key);
10239 			continue;
10240 		}
10241 
10242 		zone_iattach(zone, &notify->zone);
10243 		notify->dst = dst;
10244 
10245 		INSIST(notify->key == NULL);
10246 
10247 		if (key != NULL) {
10248 			notify->key = key;
10249 			key = NULL;
10250 		}
10251 
10252 		ISC_LIST_APPEND(zone->notifies, notify, link);
10253 		result = notify_send_queue(notify, startup);
10254 		if (result != ISC_R_SUCCESS)
10255 			notify_destroy(notify, ISC_TRUE);
10256 		if (!loggednotify) {
10257 			notify_log(zone, ISC_LOG_INFO,
10258 				   "sending notifies (serial %u)",
10259 				   serial);
10260 			loggednotify = ISC_TRUE;
10261 		}
10262 	}
10263 	UNLOCK_ZONE(zone);
10264 
10265 	if (notifytype == dns_notifytype_explicit)
10266 		goto cleanup3;
10267 
10268 	/*
10269 	 * Process NS RRset to generate notifies.
10270 	 */
10271 
10272 	dns_rdataset_init(&nsrdset);
10273 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
10274 				     dns_rdatatype_none, 0, &nsrdset, NULL);
10275 	if (result != ISC_R_SUCCESS)
10276 		goto cleanup3;
10277 
10278 	result = dns_rdataset_first(&nsrdset);
10279 	while (result == ISC_R_SUCCESS) {
10280 		dns_notify_t *notify = NULL;
10281 
10282 		dns_rdataset_current(&nsrdset, &rdata);
10283 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
10284 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10285 		dns_rdata_reset(&rdata);
10286 		/*
10287 		 * Don't notify the master server unless explicitly
10288 		 * configured to do so.
10289 		 */
10290 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
10291 		    dns_name_compare(&master, &ns.name) == 0) {
10292 			result = dns_rdataset_next(&nsrdset);
10293 			continue;
10294 		}
10295 
10296 		if (!loggednotify) {
10297 			notify_log(zone, ISC_LOG_INFO,
10298 				   "sending notifies (serial %u)",
10299 				   serial);
10300 			loggednotify = ISC_TRUE;
10301 		}
10302 
10303 		LOCK_ZONE(zone);
10304 		isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
10305 		UNLOCK_ZONE(zone);
10306 		if (isqueued) {
10307 			result = dns_rdataset_next(&nsrdset);
10308 			continue;
10309 		}
10310 		result = notify_create(zone->mctx, flags, &notify);
10311 		if (result != ISC_R_SUCCESS)
10312 			continue;
10313 		dns_zone_iattach(zone, &notify->zone);
10314 		result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
10315 		if (result != ISC_R_SUCCESS) {
10316 			LOCK_ZONE(zone);
10317 			notify_destroy(notify, ISC_TRUE);
10318 			UNLOCK_ZONE(zone);
10319 			continue;
10320 		}
10321 		LOCK_ZONE(zone);
10322 		ISC_LIST_APPEND(zone->notifies, notify, link);
10323 		UNLOCK_ZONE(zone);
10324 		notify_find_address(notify);
10325 		result = dns_rdataset_next(&nsrdset);
10326 	}
10327 	dns_rdataset_disassociate(&nsrdset);
10328 
10329  cleanup3:
10330 	if (dns_name_dynamic(&master))
10331 		dns_name_free(&master, zone->mctx);
10332  cleanup2:
10333 	dns_db_detachnode(zonedb, &node);
10334  cleanup1:
10335 	dns_db_closeversion(zonedb, &version, ISC_FALSE);
10336 	dns_db_detach(&zonedb);
10337 }
10338 
10339 /***
10340  *** Private
10341  ***/
10342 
10343 static inline isc_result_t
save_nsrrset(dns_message_t * message,dns_name_t * name,dns_db_t * db,dns_dbversion_t * version)10344 save_nsrrset(dns_message_t *message, dns_name_t *name,
10345 	     dns_db_t *db, dns_dbversion_t *version)
10346 {
10347 	dns_rdataset_t *nsrdataset = NULL;
10348 	dns_rdataset_t *rdataset = NULL;
10349 	dns_dbnode_t *node = NULL;
10350 	dns_rdata_ns_t ns;
10351 	isc_result_t result;
10352 	dns_rdata_t rdata = DNS_RDATA_INIT;
10353 
10354 	/*
10355 	 * Extract NS RRset from message.
10356 	 */
10357 	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
10358 				      dns_rdatatype_ns, dns_rdatatype_none,
10359 				      NULL, &nsrdataset);
10360 	if (result != ISC_R_SUCCESS)
10361 		goto fail;
10362 
10363 	/*
10364 	 * Add NS rdataset.
10365 	 */
10366 	result = dns_db_findnode(db, name, ISC_TRUE, &node);
10367 	if (result != ISC_R_SUCCESS)
10368 		goto fail;
10369 	result = dns_db_addrdataset(db, node, version, 0,
10370 				    nsrdataset, 0, NULL);
10371 	dns_db_detachnode(db, &node);
10372 	if (result != ISC_R_SUCCESS)
10373 		goto fail;
10374 	/*
10375 	 * Add glue rdatasets.
10376 	 */
10377 	for (result = dns_rdataset_first(nsrdataset);
10378 	     result == ISC_R_SUCCESS;
10379 	     result = dns_rdataset_next(nsrdataset)) {
10380 		dns_rdataset_current(nsrdataset, &rdata);
10381 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
10382 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10383 		dns_rdata_reset(&rdata);
10384 		if (!dns_name_issubdomain(&ns.name, name))
10385 			continue;
10386 		rdataset = NULL;
10387 		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10388 					      &ns.name, dns_rdatatype_aaaa,
10389 					      dns_rdatatype_none, NULL,
10390 					      &rdataset);
10391 		if (result == ISC_R_SUCCESS) {
10392 			result = dns_db_findnode(db, &ns.name,
10393 						 ISC_TRUE, &node);
10394 			if (result != ISC_R_SUCCESS)
10395 				goto fail;
10396 			result = dns_db_addrdataset(db, node, version, 0,
10397 						    rdataset, 0, NULL);
10398 			dns_db_detachnode(db, &node);
10399 			if (result != ISC_R_SUCCESS)
10400 				goto fail;
10401 		}
10402 		rdataset = NULL;
10403 		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10404 					      &ns.name, dns_rdatatype_a,
10405 					      dns_rdatatype_none, NULL,
10406 					      &rdataset);
10407 		if (result == ISC_R_SUCCESS) {
10408 			result = dns_db_findnode(db, &ns.name,
10409 						 ISC_TRUE, &node);
10410 			if (result != ISC_R_SUCCESS)
10411 				goto fail;
10412 			result = dns_db_addrdataset(db, node, version, 0,
10413 						    rdataset, 0, NULL);
10414 			dns_db_detachnode(db, &node);
10415 			if (result != ISC_R_SUCCESS)
10416 				goto fail;
10417 		}
10418 	}
10419 	if (result != ISC_R_NOMORE)
10420 		goto fail;
10421 
10422 	return (ISC_R_SUCCESS);
10423 
10424 fail:
10425 	return (result);
10426 }
10427 
10428 static void
stub_callback(isc_task_t * task,isc_event_t * event)10429 stub_callback(isc_task_t *task, isc_event_t *event) {
10430 	const char me[] = "stub_callback";
10431 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
10432 	dns_stub_t *stub = NULL;
10433 	dns_message_t *msg = NULL;
10434 	dns_zone_t *zone = NULL;
10435 	char master[ISC_SOCKADDR_FORMATSIZE];
10436 	char source[ISC_SOCKADDR_FORMATSIZE];
10437 	isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
10438 	isc_result_t result;
10439 	isc_time_t now;
10440 	isc_boolean_t exiting = ISC_FALSE;
10441 	isc_interval_t i;
10442 	unsigned int j, soacount;
10443 
10444 	stub = revent->ev_arg;
10445 	INSIST(DNS_STUB_VALID(stub));
10446 
10447 	UNUSED(task);
10448 
10449 	zone = stub->zone;
10450 
10451 	ENTER;
10452 
10453 	TIME_NOW(&now);
10454 
10455 	LOCK_ZONE(zone);
10456 
10457 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10458 		zone_debuglog(zone, me, 1, "exiting");
10459 		exiting = ISC_TRUE;
10460 		goto next_master;
10461 	}
10462 
10463 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10464 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10465 
10466 	if (revent->result != ISC_R_SUCCESS) {
10467 		if (revent->result == ISC_R_TIMEDOUT &&
10468 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10469 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10470 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
10471 				     "refreshing stub: timeout retrying "
10472 				     " without EDNS master %s (source %s)",
10473 				     master, source);
10474 			goto same_master;
10475 		}
10476 		dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
10477 					   &zone->sourceaddr, &now);
10478 		dns_zone_log(zone, ISC_LOG_INFO,
10479 			     "could not refresh stub from master %s"
10480 			     " (source %s): %s", master, source,
10481 			     dns_result_totext(revent->result));
10482 		goto next_master;
10483 	}
10484 
10485 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10486 	if (result != ISC_R_SUCCESS)
10487 		goto next_master;
10488 
10489 	result = dns_request_getresponse(revent->request, msg, 0);
10490 	if (result != ISC_R_SUCCESS)
10491 		goto next_master;
10492 
10493 	/*
10494 	 * Unexpected rcode.
10495 	 */
10496 	if (msg->rcode != dns_rcode_noerror) {
10497 		char rcode[128];
10498 		isc_buffer_t rb;
10499 
10500 		isc_buffer_init(&rb, rcode, sizeof(rcode));
10501 		(void)dns_rcode_totext(msg->rcode, &rb);
10502 
10503 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10504 		    (msg->rcode == dns_rcode_servfail ||
10505 		     msg->rcode == dns_rcode_notimp ||
10506 		     msg->rcode == dns_rcode_formerr)) {
10507 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
10508 				     "refreshing stub: rcode (%.*s) retrying "
10509 				     "without EDNS master %s (source %s)",
10510 				     (int)rb.used, rcode, master, source);
10511 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10512 			goto same_master;
10513 		}
10514 
10515 		dns_zone_log(zone, ISC_LOG_INFO,
10516 			     "refreshing stub: "
10517 			     "unexpected rcode (%.*s) from %s (source %s)",
10518 			     (int)rb.used, rcode, master, source);
10519 		goto next_master;
10520 	}
10521 
10522 	/*
10523 	 * We need complete messages.
10524 	 */
10525 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10526 		if (dns_request_usedtcp(revent->request)) {
10527 			dns_zone_log(zone, ISC_LOG_INFO,
10528 				     "refreshing stub: truncated TCP "
10529 				     "response from master %s (source %s)",
10530 				     master, source);
10531 			goto next_master;
10532 		}
10533 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10534 		goto same_master;
10535 	}
10536 
10537 	/*
10538 	 * If non-auth log and next master.
10539 	 */
10540 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10541 		dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10542 			     "non-authoritative answer from "
10543 			     "master %s (source %s)", master, source);
10544 		goto next_master;
10545 	}
10546 
10547 	/*
10548 	 * Sanity checks.
10549 	 */
10550 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10551 	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
10552 
10553 	if (cnamecnt != 0) {
10554 		dns_zone_log(zone, ISC_LOG_INFO,
10555 			     "refreshing stub: unexpected CNAME response "
10556 			     "from master %s (source %s)", master, source);
10557 		goto next_master;
10558 	}
10559 
10560 	if (nscnt == 0) {
10561 		dns_zone_log(zone, ISC_LOG_INFO,
10562 			     "refreshing stub: no NS records in response "
10563 			     "from master %s (source %s)", master, source);
10564 		goto next_master;
10565 	}
10566 
10567 	/*
10568 	 * Save answer.
10569 	 */
10570 	result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
10571 	if (result != ISC_R_SUCCESS) {
10572 		dns_zone_log(zone, ISC_LOG_INFO,
10573 			     "refreshing stub: unable to save NS records "
10574 			     "from master %s (source %s)", master, source);
10575 		goto next_master;
10576 	}
10577 
10578 	/*
10579 	 * Tidy up.
10580 	 */
10581 	dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
10582 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
10583 	if (zone->db == NULL)
10584 		zone_attachdb(zone, stub->db);
10585 	result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
10586 				  &refresh, &retry, &expire, NULL, NULL);
10587 	if (result == ISC_R_SUCCESS && soacount > 0U) {
10588 		zone->refresh = RANGE(refresh, zone->minrefresh,
10589 				      zone->maxrefresh);
10590 		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
10591 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
10592 				     DNS_MAX_EXPIRE);
10593 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10594 	}
10595 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
10596 	dns_db_detach(&stub->db);
10597 
10598 	dns_message_destroy(&msg);
10599 	isc_event_free(&event);
10600 	dns_request_destroy(&zone->request);
10601 
10602 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10603 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10604 	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10605 	isc_interval_set(&i, zone->expire, 0);
10606 	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10607 
10608 	if (zone->masterfile != NULL)
10609 		zone_needdump(zone, 0);
10610 
10611 	zone_settimer(zone, &now);
10612 	goto free_stub;
10613 
10614  next_master:
10615 	if (stub->version != NULL)
10616 		dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
10617 	if (stub->db != NULL)
10618 		dns_db_detach(&stub->db);
10619 	if (msg != NULL)
10620 		dns_message_destroy(&msg);
10621 	isc_event_free(&event);
10622 	dns_request_destroy(&zone->request);
10623 	/*
10624 	 * Skip to next failed / untried master.
10625 	 */
10626 	do {
10627 		zone->curmaster++;
10628 	} while (zone->curmaster < zone->masterscnt &&
10629 		 zone->mastersok[zone->curmaster]);
10630 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10631 	if (exiting || zone->curmaster >= zone->masterscnt) {
10632 		isc_boolean_t done = ISC_TRUE;
10633 		if (!exiting &&
10634 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10635 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10636 			/*
10637 			 * Did we get a good answer from all the masters?
10638 			 */
10639 			for (j = 0; j < zone->masterscnt; j++)
10640 				if (zone->mastersok[j] == ISC_FALSE) {
10641 					done = ISC_FALSE;
10642 					break;
10643 				}
10644 		} else
10645 			done = ISC_TRUE;
10646 		if (!done) {
10647 			zone->curmaster = 0;
10648 			/*
10649 			 * Find the next failed master.
10650 			 */
10651 			while (zone->curmaster < zone->masterscnt &&
10652 			       zone->mastersok[zone->curmaster])
10653 				zone->curmaster++;
10654 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10655 		} else {
10656 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10657 
10658 			zone_settimer(zone, &now);
10659 			goto free_stub;
10660 		}
10661 	}
10662 	queue_soa_query(zone);
10663 	goto free_stub;
10664 
10665  same_master:
10666 	if (msg != NULL)
10667 		dns_message_destroy(&msg);
10668 	isc_event_free(&event);
10669 	dns_request_destroy(&zone->request);
10670 	ns_query(zone, NULL, stub);
10671 	UNLOCK_ZONE(zone);
10672 	goto done;
10673 
10674  free_stub:
10675 	UNLOCK_ZONE(zone);
10676 	stub->magic = 0;
10677 	dns_zone_idetach(&stub->zone);
10678 	INSIST(stub->db == NULL);
10679 	INSIST(stub->version == NULL);
10680 	isc_mem_put(stub->mctx, stub, sizeof(*stub));
10681 
10682  done:
10683 	INSIST(event == NULL);
10684 	return;
10685 }
10686 
10687 /*
10688  * An SOA query has finished (successfully or not).
10689  */
10690 static void
refresh_callback(isc_task_t * task,isc_event_t * event)10691 refresh_callback(isc_task_t *task, isc_event_t *event) {
10692 	const char me[] = "refresh_callback";
10693 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
10694 	dns_zone_t *zone;
10695 	dns_message_t *msg = NULL;
10696 	isc_uint32_t soacnt, cnamecnt, soacount, nscount;
10697 	isc_time_t now;
10698 	char master[ISC_SOCKADDR_FORMATSIZE];
10699 	char source[ISC_SOCKADDR_FORMATSIZE];
10700 	dns_rdataset_t *rdataset = NULL;
10701 	dns_rdata_t rdata = DNS_RDATA_INIT;
10702 	dns_rdata_soa_t soa;
10703 	isc_result_t result;
10704 	isc_uint32_t serial, oldserial = 0;
10705 	unsigned int j;
10706 	isc_boolean_t do_queue_xfrin = ISC_FALSE;
10707 
10708 	zone = revent->ev_arg;
10709 	INSIST(DNS_ZONE_VALID(zone));
10710 
10711 	UNUSED(task);
10712 
10713 	ENTER;
10714 
10715 	TIME_NOW(&now);
10716 
10717 	LOCK_ZONE(zone);
10718 
10719 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10720 		isc_event_free(&event);
10721 		dns_request_destroy(&zone->request);
10722 		goto detach;
10723 	}
10724 
10725 	/*
10726 	 * if timeout log and next master;
10727 	 */
10728 
10729 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10730 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10731 
10732 	if (revent->result != ISC_R_SUCCESS) {
10733 		if (revent->result == ISC_R_TIMEDOUT &&
10734 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10735 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10736 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
10737 				     "refresh: timeout retrying without EDNS "
10738 				     "master %s (source %s)", master, source);
10739 			goto same_master;
10740 		}
10741 		if (revent->result == ISC_R_TIMEDOUT &&
10742 		    !dns_request_usedtcp(revent->request)) {
10743 			dns_zone_log(zone, ISC_LOG_INFO,
10744 				     "refresh: retry limit for "
10745 				     "master %s exceeded (source %s)",
10746 				     master, source);
10747 			/* Try with slave with TCP. */
10748 			if ((zone->type == dns_zone_slave ||
10749 			     zone->type == dns_zone_redirect) &&
10750 			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
10751 				if (!dns_zonemgr_unreachable(zone->zmgr,
10752 							     &zone->masteraddr,
10753 							     &zone->sourceaddr,
10754 							     &now))
10755 				{
10756 					DNS_ZONE_SETFLAG(zone,
10757 						     DNS_ZONEFLG_SOABEFOREAXFR);
10758 					goto tcp_transfer;
10759 				}
10760 				dns_zone_log(zone, ISC_LOG_DEBUG(1),
10761 					     "refresh: skipped tcp fallback "
10762 					     "as master %s (source %s) is "
10763 					     "unreachable (cached)",
10764 					      master, source);
10765 			}
10766 		} else
10767 			dns_zone_log(zone, ISC_LOG_INFO,
10768 				     "refresh: failure trying master "
10769 				     "%s (source %s): %s", master, source,
10770 				     dns_result_totext(revent->result));
10771 		goto next_master;
10772 	}
10773 
10774 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10775 	if (result != ISC_R_SUCCESS)
10776 		goto next_master;
10777 	result = dns_request_getresponse(revent->request, msg, 0);
10778 	if (result != ISC_R_SUCCESS) {
10779 		dns_zone_log(zone, ISC_LOG_INFO,
10780 			     "refresh: failure trying master "
10781 			     "%s (source %s): %s", master, source,
10782 			     dns_result_totext(result));
10783 		goto next_master;
10784 	}
10785 
10786 	/*
10787 	 * Unexpected rcode.
10788 	 */
10789 	if (msg->rcode != dns_rcode_noerror) {
10790 		char rcode[128];
10791 		isc_buffer_t rb;
10792 
10793 		isc_buffer_init(&rb, rcode, sizeof(rcode));
10794 		(void)dns_rcode_totext(msg->rcode, &rb);
10795 
10796 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10797 		    (msg->rcode == dns_rcode_servfail ||
10798 		     msg->rcode == dns_rcode_notimp ||
10799 		     msg->rcode == dns_rcode_formerr)) {
10800 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
10801 				     "refresh: rcode (%.*s) retrying without "
10802 				     "EDNS master %s (source %s)",
10803 				     (int)rb.used, rcode, master, source);
10804 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10805 			goto same_master;
10806 		}
10807 		dns_zone_log(zone, ISC_LOG_INFO,
10808 			     "refresh: unexpected rcode (%.*s) from "
10809 			     "master %s (source %s)", (int)rb.used, rcode,
10810 			     master, source);
10811 		/*
10812 		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
10813 		 */
10814 		if (msg->rcode == dns_rcode_refused &&
10815 		    (zone->type == dns_zone_slave ||
10816 		     zone->type == dns_zone_redirect))
10817 			goto tcp_transfer;
10818 		goto next_master;
10819 	}
10820 
10821 	/*
10822 	 * If truncated punt to zone transfer which will query again.
10823 	 */
10824 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10825 		if (zone->type == dns_zone_slave ||
10826 		    zone->type == dns_zone_redirect) {
10827 			dns_zone_log(zone, ISC_LOG_INFO,
10828 				     "refresh: truncated UDP answer, "
10829 				     "initiating TCP zone xfer "
10830 				     "for master %s (source %s)",
10831 				     master, source);
10832 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
10833 			goto tcp_transfer;
10834 		} else {
10835 			INSIST(zone->type == dns_zone_stub);
10836 			if (dns_request_usedtcp(revent->request)) {
10837 				dns_zone_log(zone, ISC_LOG_INFO,
10838 					     "refresh: truncated TCP response "
10839 					     "from master %s (source %s)",
10840 					     master, source);
10841 				goto next_master;
10842 			}
10843 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10844 			goto same_master;
10845 		}
10846 	}
10847 
10848 	/*
10849 	 * if non-auth log and next master;
10850 	 */
10851 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10852 		dns_zone_log(zone, ISC_LOG_INFO,
10853 			     "refresh: non-authoritative answer from "
10854 			     "master %s (source %s)", master, source);
10855 		goto next_master;
10856 	}
10857 
10858 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10859 	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
10860 	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
10861 	soacount = message_count(msg, DNS_SECTION_AUTHORITY,
10862 				 dns_rdatatype_soa);
10863 
10864 	/*
10865 	 * There should not be a CNAME record at top of zone.
10866 	 */
10867 	if (cnamecnt != 0) {
10868 		dns_zone_log(zone, ISC_LOG_INFO,
10869 			     "refresh: CNAME at top of zone "
10870 			     "in master %s (source %s)", master, source);
10871 		goto next_master;
10872 	}
10873 
10874 	/*
10875 	 * if referral log and next master;
10876 	 */
10877 	if (soacnt == 0 && soacount == 0 && nscount != 0) {
10878 		dns_zone_log(zone, ISC_LOG_INFO,
10879 			     "refresh: referral response "
10880 			     "from master %s (source %s)", master, source);
10881 		goto next_master;
10882 	}
10883 
10884 	/*
10885 	 * if nodata log and next master;
10886 	 */
10887 	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
10888 		dns_zone_log(zone, ISC_LOG_INFO,
10889 			     "refresh: NODATA response "
10890 			     "from master %s (source %s)", master, source);
10891 		goto next_master;
10892 	}
10893 
10894 	/*
10895 	 * Only one soa at top of zone.
10896 	 */
10897 	if (soacnt != 1) {
10898 		dns_zone_log(zone, ISC_LOG_INFO,
10899 			     "refresh: answer SOA count (%d) != 1 "
10900 			     "from master %s (source %s)",
10901 			     soacnt, master, source);
10902 		goto next_master;
10903 	}
10904 
10905 	/*
10906 	 * Extract serial
10907 	 */
10908 	rdataset = NULL;
10909 	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
10910 				      dns_rdatatype_soa, dns_rdatatype_none,
10911 				      NULL, &rdataset);
10912 	if (result != ISC_R_SUCCESS) {
10913 		dns_zone_log(zone, ISC_LOG_INFO,
10914 			     "refresh: unable to get SOA record "
10915 			     "from master %s (source %s)", master, source);
10916 		goto next_master;
10917 	}
10918 
10919 	result = dns_rdataset_first(rdataset);
10920 	if (result != ISC_R_SUCCESS) {
10921 		dns_zone_log(zone, ISC_LOG_INFO,
10922 			     "refresh: dns_rdataset_first() failed");
10923 		goto next_master;
10924 	}
10925 
10926 	dns_rdataset_current(rdataset, &rdata);
10927 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
10928 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
10929 
10930 	serial = soa.serial;
10931 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10932 		unsigned int dbsoacount;
10933 		result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
10934 					  &oldserial, NULL, NULL, NULL, NULL,
10935 					  NULL);
10936 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10937 		RUNTIME_CHECK(dbsoacount > 0U);
10938 		zone_debuglog(zone, me, 1, "serial: new %u, old %u",
10939 			      serial, oldserial);
10940 	} else
10941 		zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
10942 			      serial);
10943 
10944 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
10945 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
10946 	    isc_serial_gt(serial, oldserial)) {
10947 		if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
10948 					    &zone->sourceaddr, &now))
10949 		{
10950 			dns_zone_log(zone, ISC_LOG_INFO,
10951 				     "refresh: skipping %s as master %s "
10952 				     "(source %s) is unreachable (cached)",
10953 				     (zone->type == dns_zone_slave ||
10954 				      zone->type == dns_zone_redirect) ?
10955 				     "zone transfer" : "NS query",
10956 				     master, source);
10957 			goto next_master;
10958 		}
10959  tcp_transfer:
10960 		isc_event_free(&event);
10961 		dns_request_destroy(&zone->request);
10962 		if (zone->type == dns_zone_slave ||
10963 		    zone->type == dns_zone_redirect) {
10964 			do_queue_xfrin = ISC_TRUE;
10965 		} else {
10966 			INSIST(zone->type == dns_zone_stub);
10967 			ns_query(zone, rdataset, NULL);
10968 		}
10969 		if (msg != NULL)
10970 			dns_message_destroy(&msg);
10971 	} else if (isc_serial_eq(soa.serial, oldserial)) {
10972 		if (zone->masterfile != NULL) {
10973 			result = ISC_R_FAILURE;
10974 			if (zone->journal != NULL)
10975 				result = isc_file_settime(zone->journal, &now);
10976 			if (result == ISC_R_SUCCESS &&
10977 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10978 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10979 				result = isc_file_settime(zone->masterfile,
10980 							  &now);
10981 			} else if (result != ISC_R_SUCCESS)
10982 				result = isc_file_settime(zone->masterfile,
10983 							  &now);
10984 			/* Someone removed the file from underneath us! */
10985 			if (result == ISC_R_FILENOTFOUND) {
10986 				zone_needdump(zone, DNS_DUMP_DELAY);
10987 			} else if (result != ISC_R_SUCCESS)
10988 				dns_zone_log(zone, ISC_LOG_ERROR,
10989 					     "refresh: could not set file "
10990 					     "modification time of '%s': %s",
10991 					     zone->masterfile,
10992 					     dns_result_totext(result));
10993 		}
10994 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10995 		DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10996 		zone->mastersok[zone->curmaster] = ISC_TRUE;
10997 		goto next_master;
10998 	} else {
10999 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
11000 			dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
11001 				     "received from master %s < ours (%u)",
11002 				     soa.serial, master, oldserial);
11003 		else
11004 			zone_debuglog(zone, me, 1, "ahead");
11005 		zone->mastersok[zone->curmaster] = ISC_TRUE;
11006 		goto next_master;
11007 	}
11008 	if (msg != NULL)
11009 		dns_message_destroy(&msg);
11010 	goto detach;
11011 
11012  next_master:
11013 	if (msg != NULL)
11014 		dns_message_destroy(&msg);
11015 	isc_event_free(&event);
11016 	dns_request_destroy(&zone->request);
11017 	/*
11018 	 * Skip to next failed / untried master.
11019 	 */
11020 	do {
11021 		zone->curmaster++;
11022 	} while (zone->curmaster < zone->masterscnt &&
11023 		 zone->mastersok[zone->curmaster]);
11024 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11025 	if (zone->curmaster >= zone->masterscnt) {
11026 		isc_boolean_t done = ISC_TRUE;
11027 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
11028 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11029 			/*
11030 			 * Did we get a good answer from all the masters?
11031 			 */
11032 			for (j = 0; j < zone->masterscnt; j++)
11033 				if (zone->mastersok[j] == ISC_FALSE) {
11034 					done = ISC_FALSE;
11035 					break;
11036 				}
11037 		} else
11038 			done = ISC_TRUE;
11039 		if (!done) {
11040 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11041 			zone->curmaster = 0;
11042 			/*
11043 			 * Find the next failed master.
11044 			 */
11045 			while (zone->curmaster < zone->masterscnt &&
11046 			       zone->mastersok[zone->curmaster])
11047 				zone->curmaster++;
11048 			goto requeue;
11049 		}
11050 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11051 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
11052 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11053 			zone->refreshtime = now;
11054 		}
11055 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11056 		zone_settimer(zone, &now);
11057 		goto detach;
11058 	}
11059 
11060  requeue:
11061 	queue_soa_query(zone);
11062 	goto detach;
11063 
11064  same_master:
11065 	if (msg != NULL)
11066 		dns_message_destroy(&msg);
11067 	isc_event_free(&event);
11068 	dns_request_destroy(&zone->request);
11069 	queue_soa_query(zone);
11070 
11071  detach:
11072 	UNLOCK_ZONE(zone);
11073 	if (do_queue_xfrin)
11074 		queue_xfrin(zone);
11075 	dns_zone_idetach(&zone);
11076 	return;
11077 }
11078 
11079 static void
queue_soa_query(dns_zone_t * zone)11080 queue_soa_query(dns_zone_t *zone) {
11081 	const char me[] = "queue_soa_query";
11082 	isc_event_t *e;
11083 	dns_zone_t *dummy = NULL;
11084 	isc_result_t result;
11085 
11086 	ENTER;
11087 	/*
11088 	 * Locked by caller
11089 	 */
11090 	REQUIRE(LOCKED_ZONE(zone));
11091 
11092 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11093 		cancel_refresh(zone);
11094 		return;
11095 	}
11096 
11097 	e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
11098 			       soa_query, zone, sizeof(isc_event_t));
11099 	if (e == NULL) {
11100 		cancel_refresh(zone);
11101 		return;
11102 	}
11103 
11104 	/*
11105 	 * Attach so that we won't clean up
11106 	 * until the event is delivered.
11107 	 */
11108 	zone_iattach(zone, &dummy);
11109 
11110 	e->ev_arg = zone;
11111 	e->ev_sender = NULL;
11112 	result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
11113 	if (result != ISC_R_SUCCESS) {
11114 		zone_idetach(&dummy);
11115 		isc_event_free(&e);
11116 		cancel_refresh(zone);
11117 	}
11118 }
11119 
11120 static inline isc_result_t
create_query(dns_zone_t * zone,dns_rdatatype_t rdtype,dns_message_t ** messagep)11121 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
11122 	     dns_message_t **messagep)
11123 {
11124 	dns_message_t *message = NULL;
11125 	dns_name_t *qname = NULL;
11126 	dns_rdataset_t *qrdataset = NULL;
11127 	isc_result_t result;
11128 
11129 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11130 				    &message);
11131 	if (result != ISC_R_SUCCESS)
11132 		goto cleanup;
11133 
11134 	message->opcode = dns_opcode_query;
11135 	message->rdclass = zone->rdclass;
11136 
11137 	result = dns_message_gettempname(message, &qname);
11138 	if (result != ISC_R_SUCCESS)
11139 		goto cleanup;
11140 
11141 	result = dns_message_gettemprdataset(message, &qrdataset);
11142 	if (result != ISC_R_SUCCESS)
11143 		goto cleanup;
11144 
11145 	/*
11146 	 * Make question.
11147 	 */
11148 	dns_name_init(qname, NULL);
11149 	dns_name_clone(&zone->origin, qname);
11150 	dns_rdataset_init(qrdataset);
11151 	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
11152 	ISC_LIST_APPEND(qname->list, qrdataset, link);
11153 	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
11154 
11155 	*messagep = message;
11156 	return (ISC_R_SUCCESS);
11157 
11158  cleanup:
11159 	if (qname != NULL)
11160 		dns_message_puttempname(message, &qname);
11161 	if (qrdataset != NULL)
11162 		dns_message_puttemprdataset(message, &qrdataset);
11163 	if (message != NULL)
11164 		dns_message_destroy(&message);
11165 	return (result);
11166 }
11167 
11168 static isc_result_t
add_opt(dns_message_t * message,isc_uint16_t udpsize,isc_boolean_t reqnsid)11169 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
11170 	isc_result_t result;
11171 	dns_rdataset_t *rdataset = NULL;
11172 	dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
11173 	int count = 0;
11174 
11175 	/* Set EDNS options if applicable */
11176 	if (reqnsid) {
11177 		INSIST(count < DNS_EDNSOPTIONS);
11178 		ednsopts[count].code = DNS_OPT_NSID;
11179 		ednsopts[count].length = 0;
11180 		ednsopts[count].value = NULL;
11181 		count++;
11182 	}
11183 	result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
11184 				      ednsopts, count);
11185 	if (result != ISC_R_SUCCESS)
11186 		return (result);
11187 
11188 	return (dns_message_setopt(message, rdataset));
11189 }
11190 
11191 static void
soa_query(isc_task_t * task,isc_event_t * event)11192 soa_query(isc_task_t *task, isc_event_t *event) {
11193 	const char me[] = "soa_query";
11194 	isc_result_t result = ISC_R_FAILURE;
11195 	dns_message_t *message = NULL;
11196 	dns_zone_t *zone = event->ev_arg;
11197 	dns_zone_t *dummy = NULL;
11198 	isc_netaddr_t masterip;
11199 	dns_tsigkey_t *key = NULL;
11200 	isc_uint32_t options;
11201 	isc_boolean_t cancel = ISC_TRUE;
11202 	int timeout;
11203 	isc_boolean_t have_xfrsource, reqnsid;
11204 	isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11205 
11206 	REQUIRE(DNS_ZONE_VALID(zone));
11207 
11208 	UNUSED(task);
11209 
11210 	ENTER;
11211 
11212 	LOCK_ZONE(zone);
11213 	if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
11214 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11215 	    zone->view->requestmgr == NULL) {
11216 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11217 			cancel = ISC_FALSE;
11218 		goto cleanup;
11219 	}
11220 
11221  again:
11222 	result = create_query(zone, dns_rdatatype_soa, &message);
11223 	if (result != ISC_R_SUCCESS)
11224 		goto cleanup;
11225 
11226 	INSIST(zone->masterscnt > 0);
11227 	INSIST(zone->curmaster < zone->masterscnt);
11228 
11229 	zone->masteraddr = zone->masters[zone->curmaster];
11230 
11231 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11232 	/*
11233 	 * First, look for a tsig key in the master statement, then
11234 	 * try for a server key.
11235 	 */
11236 	if ((zone->masterkeynames != NULL) &&
11237 	    (zone->masterkeynames[zone->curmaster] != NULL)) {
11238 		dns_view_t *view = dns_zone_getview(zone);
11239 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11240 		result = dns_view_gettsig(view, keyname, &key);
11241 		if (result != ISC_R_SUCCESS) {
11242 			char namebuf[DNS_NAME_FORMATSIZE];
11243 			dns_name_format(keyname, namebuf, sizeof(namebuf));
11244 			dns_zone_log(zone, ISC_LOG_ERROR,
11245 				     "unable to find key: %s", namebuf);
11246 			goto skip_master;
11247 		}
11248 	}
11249 	if (key == NULL) {
11250 		result = dns_view_getpeertsig(zone->view, &masterip, &key);
11251 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11252 			char addrbuf[ISC_NETADDR_FORMATSIZE];
11253 			isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
11254 			dns_zone_log(zone, ISC_LOG_ERROR,
11255 				     "unable to find TSIG key for %s", addrbuf);
11256 			goto skip_master;
11257 		}
11258 	}
11259 
11260 	have_xfrsource = ISC_FALSE;
11261 	reqnsid = zone->view->requestnsid;
11262 	if (zone->view->peers != NULL) {
11263 		dns_peer_t *peer = NULL;
11264 		isc_boolean_t edns;
11265 		result = dns_peerlist_peerbyaddr(zone->view->peers,
11266 						 &masterip, &peer);
11267 		if (result == ISC_R_SUCCESS) {
11268 			result = dns_peer_getsupportedns(peer, &edns);
11269 			if (result == ISC_R_SUCCESS && !edns)
11270 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11271 			result = dns_peer_gettransfersource(peer,
11272 							    &zone->sourceaddr);
11273 			if (result == ISC_R_SUCCESS)
11274 				have_xfrsource = ISC_TRUE;
11275 			if (zone->view->resolver != NULL)
11276 				udpsize =
11277 				  dns_resolver_getudpsize(zone->view->resolver);
11278 			(void)dns_peer_getudpsize(peer, &udpsize);
11279 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
11280 		}
11281 	}
11282 
11283 	switch (isc_sockaddr_pf(&zone->masteraddr)) {
11284 	case PF_INET:
11285 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11286 			if (isc_sockaddr_equal(&zone->altxfrsource4,
11287 					       &zone->xfrsource4))
11288 				goto skip_master;
11289 			zone->sourceaddr = zone->altxfrsource4;
11290 		} else if (!have_xfrsource)
11291 			zone->sourceaddr = zone->xfrsource4;
11292 		break;
11293 	case PF_INET6:
11294 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11295 			if (isc_sockaddr_equal(&zone->altxfrsource6,
11296 					       &zone->xfrsource6))
11297 				goto skip_master;
11298 			zone->sourceaddr = zone->altxfrsource6;
11299 		} else if (!have_xfrsource)
11300 			zone->sourceaddr = zone->xfrsource6;
11301 		break;
11302 	default:
11303 		result = ISC_R_NOTIMPLEMENTED;
11304 		goto cleanup;
11305 	}
11306 
11307 	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
11308 		  DNS_REQUESTOPT_TCP : 0;
11309 
11310 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11311 		result = add_opt(message, udpsize, reqnsid);
11312 		if (result != ISC_R_SUCCESS)
11313 			zone_debuglog(zone, me, 1,
11314 				      "unable to add opt record: %s",
11315 				      dns_result_totext(result));
11316 	}
11317 
11318 	zone_iattach(zone, &dummy);
11319 	timeout = 15;
11320 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11321 		timeout = 30;
11322 	result = dns_request_createvia2(zone->view->requestmgr, message,
11323 					&zone->sourceaddr, &zone->masteraddr,
11324 					options, key, timeout * 3, timeout,
11325 					zone->task, refresh_callback, zone,
11326 					&zone->request);
11327 	if (result != ISC_R_SUCCESS) {
11328 		zone_idetach(&dummy);
11329 		zone_debuglog(zone, me, 1,
11330 			      "dns_request_createvia4() failed: %s",
11331 			      dns_result_totext(result));
11332 		goto skip_master;
11333 	} else {
11334 		if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
11335 			inc_stats(zone, dns_zonestatscounter_soaoutv4);
11336 		else
11337 			inc_stats(zone, dns_zonestatscounter_soaoutv6);
11338 	}
11339 	cancel = ISC_FALSE;
11340 
11341  cleanup:
11342 	if (key != NULL)
11343 		dns_tsigkey_detach(&key);
11344 	if (result != ISC_R_SUCCESS)
11345 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11346 	if (message != NULL)
11347 		dns_message_destroy(&message);
11348 	if (cancel)
11349 		cancel_refresh(zone);
11350 	isc_event_free(&event);
11351 	UNLOCK_ZONE(zone);
11352 	dns_zone_idetach(&zone);
11353 	return;
11354 
11355  skip_master:
11356 	if (key != NULL)
11357 		dns_tsigkey_detach(&key);
11358 	dns_message_destroy(&message);
11359 	/*
11360 	 * Skip to next failed / untried master.
11361 	 */
11362 	do {
11363 		zone->curmaster++;
11364 	} while (zone->curmaster < zone->masterscnt &&
11365 		 zone->mastersok[zone->curmaster]);
11366 	if (zone->curmaster < zone->masterscnt)
11367 		goto again;
11368 	zone->curmaster = 0;
11369 	goto cleanup;
11370 }
11371 
11372 static void
ns_query(dns_zone_t * zone,dns_rdataset_t * soardataset,dns_stub_t * stub)11373 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
11374 	const char me[] = "ns_query";
11375 	isc_result_t result;
11376 	dns_message_t *message = NULL;
11377 	isc_netaddr_t masterip;
11378 	dns_tsigkey_t *key = NULL;
11379 	dns_dbnode_t *node = NULL;
11380 	int timeout;
11381 	isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
11382 	isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11383 
11384 	REQUIRE(DNS_ZONE_VALID(zone));
11385 	REQUIRE(LOCKED_ZONE(zone));
11386 	REQUIRE((soardataset != NULL && stub == NULL) ||
11387 		(soardataset == NULL && stub != NULL));
11388 	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
11389 
11390 	ENTER;
11391 
11392 	if (stub == NULL) {
11393 		stub = isc_mem_get(zone->mctx, sizeof(*stub));
11394 		if (stub == NULL)
11395 			goto cleanup;
11396 		stub->magic = STUB_MAGIC;
11397 		stub->mctx = zone->mctx;
11398 		stub->zone = NULL;
11399 		stub->db = NULL;
11400 		stub->version = NULL;
11401 
11402 		/*
11403 		 * Attach so that the zone won't disappear from under us.
11404 		 */
11405 		zone_iattach(zone, &stub->zone);
11406 
11407 		/*
11408 		 * If a db exists we will update it, otherwise we create a
11409 		 * new one and attach it to the zone once we have the NS
11410 		 * RRset and glue.
11411 		 */
11412 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11413 		if (zone->db != NULL) {
11414 			dns_db_attach(zone->db, &stub->db);
11415 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11416 		} else {
11417 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11418 
11419 			INSIST(zone->db_argc >= 1);
11420 			result = dns_db_create(zone->mctx, zone->db_argv[0],
11421 					       &zone->origin, dns_dbtype_stub,
11422 					       zone->rdclass,
11423 					       zone->db_argc - 1,
11424 					       zone->db_argv + 1,
11425 					       &stub->db);
11426 			if (result != ISC_R_SUCCESS) {
11427 				dns_zone_log(zone, ISC_LOG_ERROR,
11428 					     "refreshing stub: "
11429 					     "could not create "
11430 					     "database: %s",
11431 					     dns_result_totext(result));
11432 				goto cleanup;
11433 			}
11434 			dns_db_settask(stub->db, zone->task);
11435 		}
11436 
11437 		result = dns_db_newversion(stub->db, &stub->version);
11438 		if (result != ISC_R_SUCCESS) {
11439 			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11440 				     "dns_db_newversion() failed: %s",
11441 				     dns_result_totext(result));
11442 			goto cleanup;
11443 		}
11444 
11445 		/*
11446 		 * Update SOA record.
11447 		 */
11448 		result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
11449 					 &node);
11450 		if (result != ISC_R_SUCCESS) {
11451 			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11452 				     "dns_db_findnode() failed: %s",
11453 				     dns_result_totext(result));
11454 			goto cleanup;
11455 		}
11456 
11457 		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
11458 					    soardataset, 0, NULL);
11459 		dns_db_detachnode(stub->db, &node);
11460 		if (result != ISC_R_SUCCESS) {
11461 			dns_zone_log(zone, ISC_LOG_INFO,
11462 				     "refreshing stub: "
11463 				     "dns_db_addrdataset() failed: %s",
11464 				     dns_result_totext(result));
11465 			goto cleanup;
11466 		}
11467 	}
11468 
11469 	/*
11470 	 * XXX Optimisation: Create message when zone is setup and reuse.
11471 	 */
11472 	result = create_query(zone, dns_rdatatype_ns, &message);
11473 	INSIST(result == ISC_R_SUCCESS);
11474 
11475 	INSIST(zone->masterscnt > 0);
11476 	INSIST(zone->curmaster < zone->masterscnt);
11477 	zone->masteraddr = zone->masters[zone->curmaster];
11478 
11479 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11480 	/*
11481 	 * First, look for a tsig key in the master statement, then
11482 	 * try for a server key.
11483 	 */
11484 	if ((zone->masterkeynames != NULL) &&
11485 	    (zone->masterkeynames[zone->curmaster] != NULL)) {
11486 		dns_view_t *view = dns_zone_getview(zone);
11487 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11488 		result = dns_view_gettsig(view, keyname, &key);
11489 		if (result != ISC_R_SUCCESS) {
11490 			char namebuf[DNS_NAME_FORMATSIZE];
11491 			dns_name_format(keyname, namebuf, sizeof(namebuf));
11492 			dns_zone_log(zone, ISC_LOG_ERROR,
11493 				     "unable to find key: %s", namebuf);
11494 		}
11495 	}
11496 	if (key == NULL)
11497 		(void)dns_view_getpeertsig(zone->view, &masterip, &key);
11498 
11499 	reqnsid = zone->view->requestnsid;
11500 	if (zone->view->peers != NULL) {
11501 		dns_peer_t *peer = NULL;
11502 		isc_boolean_t edns;
11503 		result = dns_peerlist_peerbyaddr(zone->view->peers,
11504 						 &masterip, &peer);
11505 		if (result == ISC_R_SUCCESS) {
11506 			result = dns_peer_getsupportedns(peer, &edns);
11507 			if (result == ISC_R_SUCCESS && !edns)
11508 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11509 			result = dns_peer_gettransfersource(peer,
11510 							    &zone->sourceaddr);
11511 			if (result == ISC_R_SUCCESS)
11512 				have_xfrsource = ISC_TRUE;
11513 			if (zone->view->resolver != NULL)
11514 				udpsize =
11515 				  dns_resolver_getudpsize(zone->view->resolver);
11516 			(void)dns_peer_getudpsize(peer, &udpsize);
11517 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
11518 		}
11519 
11520 	}
11521 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11522 		result = add_opt(message, udpsize, reqnsid);
11523 		if (result != ISC_R_SUCCESS)
11524 			zone_debuglog(zone, me, 1,
11525 				      "unable to add opt record: %s",
11526 				      dns_result_totext(result));
11527 	}
11528 
11529 	/*
11530 	 * Always use TCP so that we shouldn't truncate in additional section.
11531 	 */
11532 	switch (isc_sockaddr_pf(&zone->masteraddr)) {
11533 	case PF_INET:
11534 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11535 			zone->sourceaddr = zone->altxfrsource4;
11536 		else if (!have_xfrsource)
11537 			zone->sourceaddr = zone->xfrsource4;
11538 		break;
11539 	case PF_INET6:
11540 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11541 			zone->sourceaddr = zone->altxfrsource6;
11542 		else if (!have_xfrsource)
11543 			zone->sourceaddr = zone->xfrsource6;
11544 		break;
11545 	default:
11546 		result = ISC_R_NOTIMPLEMENTED;
11547 		POST(result);
11548 		goto cleanup;
11549 	}
11550 	timeout = 15;
11551 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11552 		timeout = 30;
11553 	result = dns_request_createvia2(zone->view->requestmgr, message,
11554 					&zone->sourceaddr, &zone->masteraddr,
11555 					DNS_REQUESTOPT_TCP, key, timeout * 3,
11556 					timeout, zone->task, stub_callback,
11557 					stub, &zone->request);
11558 	if (result != ISC_R_SUCCESS) {
11559 		zone_debuglog(zone, me, 1,
11560 			      "dns_request_createvia() failed: %s",
11561 			      dns_result_totext(result));
11562 		goto cleanup;
11563 	}
11564 	dns_message_destroy(&message);
11565 	goto unlock;
11566 
11567  cleanup:
11568 	cancel_refresh(zone);
11569 	if (stub != NULL) {
11570 		stub->magic = 0;
11571 		if (stub->version != NULL)
11572 			dns_db_closeversion(stub->db, &stub->version,
11573 					    ISC_FALSE);
11574 		if (stub->db != NULL)
11575 			dns_db_detach(&stub->db);
11576 		if (stub->zone != NULL)
11577 			zone_idetach(&stub->zone);
11578 		isc_mem_put(stub->mctx, stub, sizeof(*stub));
11579 	}
11580 	if (message != NULL)
11581 		dns_message_destroy(&message);
11582  unlock:
11583 	if (key != NULL)
11584 		dns_tsigkey_detach(&key);
11585 	return;
11586 }
11587 
11588 /*
11589  * Handle the control event.  Note that although this event causes the zone
11590  * to shut down, it is not a shutdown event in the sense of the task library.
11591  */
11592 static void
zone_shutdown(isc_task_t * task,isc_event_t * event)11593 zone_shutdown(isc_task_t *task, isc_event_t *event) {
11594 	dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
11595 	isc_boolean_t free_needed, linked = ISC_FALSE;
11596 	dns_zone_t *raw = NULL, *secure = NULL;
11597 
11598 	UNUSED(task);
11599 	REQUIRE(DNS_ZONE_VALID(zone));
11600 	INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
11601 	INSIST(isc_refcount_current(&zone->erefs) == 0);
11602 
11603 	zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
11604 
11605 	/*
11606 	 * Stop things being restarted after we cancel them below.
11607 	 */
11608 	LOCK_ZONE(zone);
11609 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
11610 	UNLOCK_ZONE(zone);
11611 
11612 	/*
11613 	 * If we were waiting for xfrin quota, step out of
11614 	 * the queue.
11615 	 * If there's no zone manager, we can't be waiting for the
11616 	 * xfrin quota
11617 	 */
11618 	if (zone->zmgr != NULL) {
11619 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11620 		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
11621 			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
11622 					statelink);
11623 			linked = ISC_TRUE;
11624 			zone->statelist = NULL;
11625 		}
11626 		if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
11627 			ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
11628 					statelink);
11629 			zone->statelist = NULL;
11630 			zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
11631 		}
11632 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11633 	}
11634 
11635 	/*
11636 	 * In task context, no locking required.  See zone_xfrdone().
11637 	 */
11638 	if (zone->xfr != NULL)
11639 		dns_xfrin_shutdown(zone->xfr);
11640 
11641 	/* Safe to release the zone now */
11642 	if (zone->zmgr != NULL)
11643 		dns_zonemgr_releasezone(zone->zmgr, zone);
11644 
11645 	LOCK_ZONE(zone);
11646 	if (linked) {
11647 		INSIST(zone->irefs > 0);
11648 		zone->irefs--;
11649 	}
11650 	if (zone->request != NULL) {
11651 		dns_request_cancel(zone->request);
11652 	}
11653 
11654 	if (zone->readio != NULL)
11655 		zonemgr_cancelio(zone->readio);
11656 
11657 	if (zone->lctx != NULL)
11658 		dns_loadctx_cancel(zone->lctx);
11659 
11660 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11661 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11662 		if (zone->writeio != NULL)
11663 			zonemgr_cancelio(zone->writeio);
11664 
11665 		if (zone->dctx != NULL)
11666 			dns_dumpctx_cancel(zone->dctx);
11667 	}
11668 
11669 	notify_cancel(zone);
11670 
11671 	forward_cancel(zone);
11672 
11673 	if (zone->timer != NULL) {
11674 		isc_timer_detach(&zone->timer);
11675 		INSIST(zone->irefs > 0);
11676 		zone->irefs--;
11677 	}
11678 
11679 	/*
11680 	 * We have now canceled everything set the flag to allow exit_check()
11681 	 * to succeed.	We must not unlock between setting this flag and
11682 	 * calling exit_check().
11683 	 */
11684 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
11685 	free_needed = exit_check(zone);
11686 	if (inline_secure(zone)) {
11687 		raw = zone->raw;
11688 		zone->raw = NULL;
11689 	}
11690 	if (inline_raw(zone)) {
11691 		secure = zone->secure;
11692 		zone->secure = NULL;
11693 	}
11694 	UNLOCK_ZONE(zone);
11695 	if (raw != NULL)
11696 		dns_zone_detach(&raw);
11697 	if (secure != NULL)
11698 		dns_zone_idetach(&secure);
11699 	if (free_needed)
11700 		zone_free(zone);
11701 }
11702 
11703 static void
zone_timer(isc_task_t * task,isc_event_t * event)11704 zone_timer(isc_task_t *task, isc_event_t *event) {
11705 	const char me[] = "zone_timer";
11706 	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
11707 
11708 	UNUSED(task);
11709 	REQUIRE(DNS_ZONE_VALID(zone));
11710 
11711 	ENTER;
11712 
11713 	zone_maintenance(zone);
11714 
11715 	isc_event_free(&event);
11716 }
11717 
11718 static void
zone_settimer(dns_zone_t * zone,isc_time_t * now)11719 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
11720 	const char me[] = "zone_settimer";
11721 	isc_time_t next;
11722 	isc_result_t result;
11723 
11724 	ENTER;
11725 	REQUIRE(DNS_ZONE_VALID(zone));
11726 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11727 		return;
11728 
11729 	isc_time_settoepoch(&next);
11730 
11731 	switch (zone->type) {
11732 	case dns_zone_redirect:
11733 		if (zone->masters != NULL)
11734 			goto treat_as_slave;
11735 		/* FALLTHROUGH */
11736 
11737 	case dns_zone_master:
11738 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11739 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
11740 			next = zone->notifytime;
11741 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11742 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11743 			INSIST(!isc_time_isepoch(&zone->dumptime));
11744 			if (isc_time_isepoch(&next) ||
11745 			    isc_time_compare(&zone->dumptime, &next) < 0)
11746 				next = zone->dumptime;
11747 		}
11748 		if (zone->type == dns_zone_redirect)
11749 			break;
11750 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
11751 		    !isc_time_isepoch(&zone->refreshkeytime)) {
11752 			if (isc_time_isepoch(&next) ||
11753 			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
11754 				next = zone->refreshkeytime;
11755 		}
11756 		if (!isc_time_isepoch(&zone->resigntime)) {
11757 			if (isc_time_isepoch(&next) ||
11758 			    isc_time_compare(&zone->resigntime, &next) < 0)
11759 				next = zone->resigntime;
11760 		}
11761 		if (!isc_time_isepoch(&zone->keywarntime)) {
11762 			if (isc_time_isepoch(&next) ||
11763 			    isc_time_compare(&zone->keywarntime, &next) < 0)
11764 				next = zone->keywarntime;
11765 		}
11766 		if (!isc_time_isepoch(&zone->signingtime)) {
11767 			if (isc_time_isepoch(&next) ||
11768 			    isc_time_compare(&zone->signingtime, &next) < 0)
11769 				next = zone->signingtime;
11770 		}
11771 		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
11772 			if (isc_time_isepoch(&next) ||
11773 			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
11774 				next = zone->nsec3chaintime;
11775 		}
11776 		break;
11777 
11778 	case dns_zone_slave:
11779 	treat_as_slave:
11780 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11781 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
11782 			next = zone->notifytime;
11783 		/* FALLTHROUGH */
11784 
11785 	case dns_zone_stub:
11786 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
11787 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
11788 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
11789 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
11790 			INSIST(!isc_time_isepoch(&zone->refreshtime));
11791 			if (isc_time_isepoch(&next) ||
11792 			    isc_time_compare(&zone->refreshtime, &next) < 0)
11793 				next = zone->refreshtime;
11794 		}
11795 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11796 		    !isc_time_isepoch(&zone->expiretime)) {
11797 			if (isc_time_isepoch(&next) ||
11798 			     isc_time_compare(&zone->expiretime, &next) < 0)
11799 				next = zone->expiretime;
11800 		}
11801 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11802 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11803 			INSIST(!isc_time_isepoch(&zone->dumptime));
11804 			if (isc_time_isepoch(&next) ||
11805 			    isc_time_compare(&zone->dumptime, &next) < 0)
11806 				next = zone->dumptime;
11807 		}
11808 		break;
11809 
11810 	case dns_zone_key:
11811 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11812 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11813 			INSIST(!isc_time_isepoch(&zone->dumptime));
11814 			if (isc_time_isepoch(&next) ||
11815 			    isc_time_compare(&zone->dumptime, &next) < 0)
11816 				next = zone->dumptime;
11817 		}
11818 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
11819 			if (isc_time_isepoch(&next) ||
11820 			    (!isc_time_isepoch(&zone->refreshkeytime) &&
11821 			    isc_time_compare(&zone->refreshkeytime, &next) < 0))
11822 				next = zone->refreshkeytime;
11823 		}
11824 		break;
11825 
11826 	default:
11827 		break;
11828 	}
11829 
11830 	if (isc_time_isepoch(&next)) {
11831 		zone_debuglog(zone, me, 10, "settimer inactive");
11832 		result = isc_timer_reset(zone->timer, isc_timertype_inactive,
11833 					  NULL, NULL, ISC_TRUE);
11834 		if (result != ISC_R_SUCCESS)
11835 			dns_zone_log(zone, ISC_LOG_ERROR,
11836 				     "could not deactivate zone timer: %s",
11837 				     isc_result_totext(result));
11838 	} else {
11839 		if (isc_time_compare(&next, now) <= 0)
11840 			next = *now;
11841 		result = isc_timer_reset(zone->timer, isc_timertype_once,
11842 					 &next, NULL, ISC_TRUE);
11843 		if (result != ISC_R_SUCCESS)
11844 			dns_zone_log(zone, ISC_LOG_ERROR,
11845 				     "could not reset zone timer: %s",
11846 				     isc_result_totext(result));
11847 	}
11848 }
11849 
11850 static void
cancel_refresh(dns_zone_t * zone)11851 cancel_refresh(dns_zone_t *zone) {
11852 	const char me[] = "cancel_refresh";
11853 	isc_time_t now;
11854 
11855 	/*
11856 	 * 'zone' locked by caller.
11857 	 */
11858 
11859 	REQUIRE(DNS_ZONE_VALID(zone));
11860 	REQUIRE(LOCKED_ZONE(zone));
11861 
11862 	ENTER;
11863 
11864 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11865 	TIME_NOW(&now);
11866 	zone_settimer(zone, &now);
11867 }
11868 
11869 static isc_result_t
notify_createmessage(dns_zone_t * zone,unsigned int flags,dns_message_t ** messagep)11870 notify_createmessage(dns_zone_t *zone, unsigned int flags,
11871 		     dns_message_t **messagep)
11872 {
11873 	dns_db_t *zonedb = NULL;
11874 	dns_dbnode_t *node = NULL;
11875 	dns_dbversion_t *version = NULL;
11876 	dns_message_t *message = NULL;
11877 	dns_rdataset_t rdataset;
11878 	dns_rdata_t rdata = DNS_RDATA_INIT;
11879 
11880 	dns_name_t *tempname = NULL;
11881 	dns_rdata_t *temprdata = NULL;
11882 	dns_rdatalist_t *temprdatalist = NULL;
11883 	dns_rdataset_t *temprdataset = NULL;
11884 
11885 	isc_result_t result;
11886 	isc_region_t r;
11887 	isc_buffer_t *b = NULL;
11888 
11889 	REQUIRE(DNS_ZONE_VALID(zone));
11890 	REQUIRE(messagep != NULL && *messagep == NULL);
11891 
11892 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11893 				    &message);
11894 	if (result != ISC_R_SUCCESS)
11895 		return (result);
11896 
11897 	message->opcode = dns_opcode_notify;
11898 	message->flags |= DNS_MESSAGEFLAG_AA;
11899 	message->rdclass = zone->rdclass;
11900 
11901 	result = dns_message_gettempname(message, &tempname);
11902 	if (result != ISC_R_SUCCESS)
11903 		goto cleanup;
11904 
11905 	result = dns_message_gettemprdataset(message, &temprdataset);
11906 	if (result != ISC_R_SUCCESS)
11907 		goto cleanup;
11908 
11909 	/*
11910 	 * Make question.
11911 	 */
11912 	dns_name_init(tempname, NULL);
11913 	dns_name_clone(&zone->origin, tempname);
11914 	dns_rdataset_init(temprdataset);
11915 	dns_rdataset_makequestion(temprdataset, zone->rdclass,
11916 				  dns_rdatatype_soa);
11917 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
11918 	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
11919 	tempname = NULL;
11920 	temprdataset = NULL;
11921 
11922 	if ((flags & DNS_NOTIFY_NOSOA) != 0)
11923 		goto done;
11924 
11925 	result = dns_message_gettempname(message, &tempname);
11926 	if (result != ISC_R_SUCCESS)
11927 		goto soa_cleanup;
11928 	result = dns_message_gettemprdata(message, &temprdata);
11929 	if (result != ISC_R_SUCCESS)
11930 		goto soa_cleanup;
11931 	result = dns_message_gettemprdataset(message, &temprdataset);
11932 	if (result != ISC_R_SUCCESS)
11933 		goto soa_cleanup;
11934 	result = dns_message_gettemprdatalist(message, &temprdatalist);
11935 	if (result != ISC_R_SUCCESS)
11936 		goto soa_cleanup;
11937 
11938 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11939 	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
11940 	dns_db_attach(zone->db, &zonedb);
11941 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11942 
11943 	dns_name_init(tempname, NULL);
11944 	dns_name_clone(&zone->origin, tempname);
11945 	dns_db_currentversion(zonedb, &version);
11946 	result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
11947 	if (result != ISC_R_SUCCESS)
11948 		goto soa_cleanup;
11949 
11950 	dns_rdataset_init(&rdataset);
11951 	result = dns_db_findrdataset(zonedb, node, version,
11952 				     dns_rdatatype_soa,
11953 				     dns_rdatatype_none, 0, &rdataset,
11954 				     NULL);
11955 	if (result != ISC_R_SUCCESS)
11956 		goto soa_cleanup;
11957 	result = dns_rdataset_first(&rdataset);
11958 	if (result != ISC_R_SUCCESS)
11959 		goto soa_cleanup;
11960 	dns_rdataset_current(&rdataset, &rdata);
11961 	dns_rdata_toregion(&rdata, &r);
11962 	result = isc_buffer_allocate(zone->mctx, &b, r.length);
11963 	if (result != ISC_R_SUCCESS)
11964 		goto soa_cleanup;
11965 	isc_buffer_putmem(b, r.base, r.length);
11966 	isc_buffer_usedregion(b, &r);
11967 	dns_rdata_init(temprdata);
11968 	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
11969 	dns_message_takebuffer(message, &b);
11970 	result = dns_rdataset_next(&rdataset);
11971 	dns_rdataset_disassociate(&rdataset);
11972 	if (result != ISC_R_NOMORE)
11973 		goto soa_cleanup;
11974 	temprdatalist->rdclass = rdata.rdclass;
11975 	temprdatalist->type = rdata.type;
11976 	temprdatalist->ttl = rdataset.ttl;
11977 	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
11978 
11979 	dns_rdataset_init(temprdataset);
11980 	result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
11981 	if (result != ISC_R_SUCCESS)
11982 		goto soa_cleanup;
11983 
11984 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
11985 	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
11986 	temprdatalist = NULL;
11987 	temprdataset = NULL;
11988 	temprdata = NULL;
11989 	tempname = NULL;
11990 
11991  soa_cleanup:
11992 	if (node != NULL)
11993 		dns_db_detachnode(zonedb, &node);
11994 	if (version != NULL)
11995 		dns_db_closeversion(zonedb, &version, ISC_FALSE);
11996 	if (zonedb != NULL)
11997 		dns_db_detach(&zonedb);
11998 	if (tempname != NULL)
11999 		dns_message_puttempname(message, &tempname);
12000 	if (temprdata != NULL)
12001 		dns_message_puttemprdata(message, &temprdata);
12002 	if (temprdataset != NULL)
12003 		dns_message_puttemprdataset(message, &temprdataset);
12004 	if (temprdatalist != NULL)
12005 		dns_message_puttemprdatalist(message, &temprdatalist);
12006 
12007  done:
12008 	*messagep = message;
12009 	return (ISC_R_SUCCESS);
12010 
12011  cleanup:
12012 	if (tempname != NULL)
12013 		dns_message_puttempname(message, &tempname);
12014 	if (temprdataset != NULL)
12015 		dns_message_puttemprdataset(message, &temprdataset);
12016 	dns_message_destroy(&message);
12017 	return (result);
12018 }
12019 
12020 isc_result_t
dns_zone_notifyreceive(dns_zone_t * zone,isc_sockaddr_t * from,dns_message_t * msg)12021 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
12022 		       dns_message_t *msg)
12023 {
12024 	unsigned int i;
12025 	dns_rdata_soa_t soa;
12026 	dns_rdataset_t *rdataset = NULL;
12027 	dns_rdata_t rdata = DNS_RDATA_INIT;
12028 	isc_result_t result;
12029 	char fromtext[ISC_SOCKADDR_FORMATSIZE];
12030 	int match = 0;
12031 	isc_netaddr_t netaddr;
12032 	isc_sockaddr_t local, remote;
12033 	dns_tsigkey_t *tsigkey;
12034 	dns_name_t *tsig;
12035 
12036 	REQUIRE(DNS_ZONE_VALID(zone));
12037 
12038 	/*
12039 	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
12040 	 * ROLLOVER.
12041 	 *
12042 	 * SOA:	RFC1996
12043 	 * Check that 'from' is a valid notify source, (zone->masters).
12044 	 *	Return DNS_R_REFUSED if not.
12045 	 *
12046 	 * If the notify message contains a serial number check it
12047 	 * against the zones serial and return if <= current serial
12048 	 *
12049 	 * If a refresh check is progress, if so just record the
12050 	 * fact we received a NOTIFY and from where and return.
12051 	 * We will perform a new refresh check when the current one
12052 	 * completes. Return ISC_R_SUCCESS.
12053 	 *
12054 	 * Otherwise initiate a refresh check using 'from' as the
12055 	 * first address to check.  Return ISC_R_SUCCESS.
12056 	 */
12057 
12058 	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
12059 
12060 	/*
12061 	 * Notify messages are processed by the raw zone.
12062 	 */
12063 	LOCK_ZONE(zone);
12064 	if (inline_secure(zone)) {
12065 		result = dns_zone_notifyreceive(zone->raw, from, msg);
12066 		UNLOCK_ZONE(zone);
12067 		return (result);
12068 	}
12069 	/*
12070 	 *  We only handle NOTIFY (SOA) at the present.
12071 	 */
12072 	if (isc_sockaddr_pf(from) == PF_INET)
12073 		inc_stats(zone, dns_zonestatscounter_notifyinv4);
12074 	else
12075 		inc_stats(zone, dns_zonestatscounter_notifyinv6);
12076 	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
12077 	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
12078 				 dns_rdatatype_soa, dns_rdatatype_none,
12079 				 NULL, NULL) != ISC_R_SUCCESS) {
12080 		UNLOCK_ZONE(zone);
12081 		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
12082 			dns_zone_log(zone, ISC_LOG_NOTICE,
12083 				     "NOTIFY with no "
12084 				     "question section from: %s", fromtext);
12085 			return (DNS_R_FORMERR);
12086 		}
12087 		dns_zone_log(zone, ISC_LOG_NOTICE,
12088 			     "NOTIFY zone does not match");
12089 		return (DNS_R_NOTIMP);
12090 	}
12091 
12092 	/*
12093 	 * If we are a master zone just succeed.
12094 	 */
12095 	if (zone->type == dns_zone_master) {
12096 		UNLOCK_ZONE(zone);
12097 		return (ISC_R_SUCCESS);
12098 	}
12099 
12100 	isc_netaddr_fromsockaddr(&netaddr, from);
12101 	for (i = 0; i < zone->masterscnt; i++) {
12102 		if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
12103 			break;
12104 		if (zone->view->aclenv.match_mapped &&
12105 		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
12106 		    isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
12107 			isc_netaddr_t na1, na2;
12108 			isc_netaddr_fromv4mapped(&na1, &netaddr);
12109 			isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
12110 			if (isc_netaddr_equal(&na1, &na2))
12111 				break;
12112 		}
12113 	}
12114 
12115 	/*
12116 	 * Accept notify requests from non masters if they are on
12117 	 * 'zone->notify_acl'.
12118 	 */
12119 	tsigkey = dns_message_gettsigkey(msg);
12120 	tsig = dns_tsigkey_identity(tsigkey);
12121 	if (i >= zone->masterscnt && zone->notify_acl != NULL &&
12122 	    dns_acl_match(&netaddr, tsig, zone->notify_acl,
12123 			  &zone->view->aclenv,
12124 			  &match, NULL) == ISC_R_SUCCESS &&
12125 	    match > 0)
12126 	{
12127 		/* Accept notify. */
12128 	} else if (i >= zone->masterscnt) {
12129 		UNLOCK_ZONE(zone);
12130 		dns_zone_log(zone, ISC_LOG_INFO,
12131 			     "refused notify from non-master: %s", fromtext);
12132 		inc_stats(zone, dns_zonestatscounter_notifyrej);
12133 		return (DNS_R_REFUSED);
12134 	}
12135 
12136 	/*
12137 	 * If the zone is loaded and there are answers check the serial
12138 	 * to see if we need to do a refresh.  Do not worry about this
12139 	 * check if we are a dialup zone as we use the notify request
12140 	 * to trigger a refresh check.
12141 	 */
12142 	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
12143 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
12144 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
12145 		result = dns_message_findname(msg, DNS_SECTION_ANSWER,
12146 					      &zone->origin,
12147 					      dns_rdatatype_soa,
12148 					      dns_rdatatype_none, NULL,
12149 					      &rdataset);
12150 		if (result == ISC_R_SUCCESS)
12151 			result = dns_rdataset_first(rdataset);
12152 		if (result == ISC_R_SUCCESS) {
12153 			isc_uint32_t serial = 0, oldserial;
12154 			unsigned int soacount;
12155 
12156 			dns_rdataset_current(rdataset, &rdata);
12157 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
12158 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
12159 			serial = soa.serial;
12160 			/*
12161 			 * The following should safely be performed without DB
12162 			 * lock and succeed in this context.
12163 			 */
12164 			result = zone_get_from_db(zone, zone->db, NULL,
12165 						  &soacount, &oldserial, NULL,
12166 						  NULL, NULL, NULL, NULL);
12167 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
12168 			RUNTIME_CHECK(soacount > 0U);
12169 			if (isc_serial_le(serial, oldserial)) {
12170 				dns_zone_log(zone,
12171 					     ISC_LOG_INFO,
12172 					     "notify from %s: "
12173 					     "zone is up to date",
12174 					     fromtext);
12175 				UNLOCK_ZONE(zone);
12176 				return (ISC_R_SUCCESS);
12177 			}
12178 		}
12179 	}
12180 
12181 	/*
12182 	 * If we got this far and there was a refresh in progress just
12183 	 * let it complete.  Record where we got the notify from so we
12184 	 * can perform a refresh check when the current one completes
12185 	 */
12186 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
12187 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12188 		zone->notifyfrom = *from;
12189 		UNLOCK_ZONE(zone);
12190 		dns_zone_log(zone, ISC_LOG_INFO,
12191 			     "notify from %s: refresh in progress, "
12192 			     "refresh check queued",
12193 			     fromtext);
12194 		return (ISC_R_SUCCESS);
12195 	}
12196 	zone->notifyfrom = *from;
12197 	remote = zone->masteraddr;
12198 	local = zone->sourceaddr;
12199 	UNLOCK_ZONE(zone);
12200 	dns_zonemgr_unreachabledel(zone->zmgr, &remote, &local);
12201 	dns_zone_refresh(zone);
12202 	return (ISC_R_SUCCESS);
12203 }
12204 
12205 void
dns_zone_setnotifyacl(dns_zone_t * zone,dns_acl_t * acl)12206 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
12207 
12208 	REQUIRE(DNS_ZONE_VALID(zone));
12209 
12210 	LOCK_ZONE(zone);
12211 	if (zone->notify_acl != NULL)
12212 		dns_acl_detach(&zone->notify_acl);
12213 	dns_acl_attach(acl, &zone->notify_acl);
12214 	UNLOCK_ZONE(zone);
12215 }
12216 
12217 void
dns_zone_setqueryacl(dns_zone_t * zone,dns_acl_t * acl)12218 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
12219 
12220 	REQUIRE(DNS_ZONE_VALID(zone));
12221 
12222 	LOCK_ZONE(zone);
12223 	if (zone->query_acl != NULL)
12224 		dns_acl_detach(&zone->query_acl);
12225 	dns_acl_attach(acl, &zone->query_acl);
12226 	UNLOCK_ZONE(zone);
12227 }
12228 
12229 void
dns_zone_setqueryonacl(dns_zone_t * zone,dns_acl_t * acl)12230 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
12231 
12232 	REQUIRE(DNS_ZONE_VALID(zone));
12233 
12234 	LOCK_ZONE(zone);
12235 	if (zone->queryon_acl != NULL)
12236 		dns_acl_detach(&zone->queryon_acl);
12237 	dns_acl_attach(acl, &zone->queryon_acl);
12238 	UNLOCK_ZONE(zone);
12239 }
12240 
12241 void
dns_zone_setupdateacl(dns_zone_t * zone,dns_acl_t * acl)12242 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
12243 
12244 	REQUIRE(DNS_ZONE_VALID(zone));
12245 
12246 	LOCK_ZONE(zone);
12247 	if (zone->update_acl != NULL)
12248 		dns_acl_detach(&zone->update_acl);
12249 	dns_acl_attach(acl, &zone->update_acl);
12250 	UNLOCK_ZONE(zone);
12251 }
12252 
12253 void
dns_zone_setforwardacl(dns_zone_t * zone,dns_acl_t * acl)12254 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
12255 
12256 	REQUIRE(DNS_ZONE_VALID(zone));
12257 
12258 	LOCK_ZONE(zone);
12259 	if (zone->forward_acl != NULL)
12260 		dns_acl_detach(&zone->forward_acl);
12261 	dns_acl_attach(acl, &zone->forward_acl);
12262 	UNLOCK_ZONE(zone);
12263 }
12264 
12265 void
dns_zone_setxfracl(dns_zone_t * zone,dns_acl_t * acl)12266 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
12267 
12268 	REQUIRE(DNS_ZONE_VALID(zone));
12269 
12270 	LOCK_ZONE(zone);
12271 	if (zone->xfr_acl != NULL)
12272 		dns_acl_detach(&zone->xfr_acl);
12273 	dns_acl_attach(acl, &zone->xfr_acl);
12274 	UNLOCK_ZONE(zone);
12275 }
12276 
12277 dns_acl_t *
dns_zone_getnotifyacl(dns_zone_t * zone)12278 dns_zone_getnotifyacl(dns_zone_t *zone) {
12279 
12280 	REQUIRE(DNS_ZONE_VALID(zone));
12281 
12282 	return (zone->notify_acl);
12283 }
12284 
12285 dns_acl_t *
dns_zone_getqueryacl(dns_zone_t * zone)12286 dns_zone_getqueryacl(dns_zone_t *zone) {
12287 
12288 	REQUIRE(DNS_ZONE_VALID(zone));
12289 
12290 	return (zone->query_acl);
12291 }
12292 
12293 dns_acl_t *
dns_zone_getqueryonacl(dns_zone_t * zone)12294 dns_zone_getqueryonacl(dns_zone_t *zone) {
12295 
12296 	REQUIRE(DNS_ZONE_VALID(zone));
12297 
12298 	return (zone->queryon_acl);
12299 }
12300 
12301 dns_acl_t *
dns_zone_getupdateacl(dns_zone_t * zone)12302 dns_zone_getupdateacl(dns_zone_t *zone) {
12303 
12304 	REQUIRE(DNS_ZONE_VALID(zone));
12305 
12306 	return (zone->update_acl);
12307 }
12308 
12309 dns_acl_t *
dns_zone_getforwardacl(dns_zone_t * zone)12310 dns_zone_getforwardacl(dns_zone_t *zone) {
12311 
12312 	REQUIRE(DNS_ZONE_VALID(zone));
12313 
12314 	return (zone->forward_acl);
12315 }
12316 
12317 dns_acl_t *
dns_zone_getxfracl(dns_zone_t * zone)12318 dns_zone_getxfracl(dns_zone_t *zone) {
12319 
12320 	REQUIRE(DNS_ZONE_VALID(zone));
12321 
12322 	return (zone->xfr_acl);
12323 }
12324 
12325 void
dns_zone_clearupdateacl(dns_zone_t * zone)12326 dns_zone_clearupdateacl(dns_zone_t *zone) {
12327 
12328 	REQUIRE(DNS_ZONE_VALID(zone));
12329 
12330 	LOCK_ZONE(zone);
12331 	if (zone->update_acl != NULL)
12332 		dns_acl_detach(&zone->update_acl);
12333 	UNLOCK_ZONE(zone);
12334 }
12335 
12336 void
dns_zone_clearforwardacl(dns_zone_t * zone)12337 dns_zone_clearforwardacl(dns_zone_t *zone) {
12338 
12339 	REQUIRE(DNS_ZONE_VALID(zone));
12340 
12341 	LOCK_ZONE(zone);
12342 	if (zone->forward_acl != NULL)
12343 		dns_acl_detach(&zone->forward_acl);
12344 	UNLOCK_ZONE(zone);
12345 }
12346 
12347 void
dns_zone_clearnotifyacl(dns_zone_t * zone)12348 dns_zone_clearnotifyacl(dns_zone_t *zone) {
12349 
12350 	REQUIRE(DNS_ZONE_VALID(zone));
12351 
12352 	LOCK_ZONE(zone);
12353 	if (zone->notify_acl != NULL)
12354 		dns_acl_detach(&zone->notify_acl);
12355 	UNLOCK_ZONE(zone);
12356 }
12357 
12358 void
dns_zone_clearqueryacl(dns_zone_t * zone)12359 dns_zone_clearqueryacl(dns_zone_t *zone) {
12360 
12361 	REQUIRE(DNS_ZONE_VALID(zone));
12362 
12363 	LOCK_ZONE(zone);
12364 	if (zone->query_acl != NULL)
12365 		dns_acl_detach(&zone->query_acl);
12366 	UNLOCK_ZONE(zone);
12367 }
12368 
12369 void
dns_zone_clearqueryonacl(dns_zone_t * zone)12370 dns_zone_clearqueryonacl(dns_zone_t *zone) {
12371 
12372 	REQUIRE(DNS_ZONE_VALID(zone));
12373 
12374 	LOCK_ZONE(zone);
12375 	if (zone->queryon_acl != NULL)
12376 		dns_acl_detach(&zone->queryon_acl);
12377 	UNLOCK_ZONE(zone);
12378 }
12379 
12380 void
dns_zone_clearxfracl(dns_zone_t * zone)12381 dns_zone_clearxfracl(dns_zone_t *zone) {
12382 
12383 	REQUIRE(DNS_ZONE_VALID(zone));
12384 
12385 	LOCK_ZONE(zone);
12386 	if (zone->xfr_acl != NULL)
12387 		dns_acl_detach(&zone->xfr_acl);
12388 	UNLOCK_ZONE(zone);
12389 }
12390 
12391 isc_boolean_t
dns_zone_getupdatedisabled(dns_zone_t * zone)12392 dns_zone_getupdatedisabled(dns_zone_t *zone) {
12393 	REQUIRE(DNS_ZONE_VALID(zone));
12394 	return (zone->update_disabled);
12395 
12396 }
12397 
12398 void
dns_zone_setupdatedisabled(dns_zone_t * zone,isc_boolean_t state)12399 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
12400 	REQUIRE(DNS_ZONE_VALID(zone));
12401 	zone->update_disabled = state;
12402 }
12403 
12404 isc_boolean_t
dns_zone_getzeronosoattl(dns_zone_t * zone)12405 dns_zone_getzeronosoattl(dns_zone_t *zone) {
12406 	REQUIRE(DNS_ZONE_VALID(zone));
12407 	return (zone->zero_no_soa_ttl);
12408 
12409 }
12410 
12411 void
dns_zone_setzeronosoattl(dns_zone_t * zone,isc_boolean_t state)12412 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
12413 	REQUIRE(DNS_ZONE_VALID(zone));
12414 	zone->zero_no_soa_ttl = state;
12415 }
12416 
12417 void
dns_zone_setchecknames(dns_zone_t * zone,dns_severity_t severity)12418 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
12419 
12420 	REQUIRE(DNS_ZONE_VALID(zone));
12421 
12422 	zone->check_names = severity;
12423 }
12424 
12425 dns_severity_t
dns_zone_getchecknames(dns_zone_t * zone)12426 dns_zone_getchecknames(dns_zone_t *zone) {
12427 
12428 	REQUIRE(DNS_ZONE_VALID(zone));
12429 
12430 	return (zone->check_names);
12431 }
12432 
12433 void
dns_zone_setjournalsize(dns_zone_t * zone,isc_int32_t size)12434 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
12435 
12436 	REQUIRE(DNS_ZONE_VALID(zone));
12437 
12438 	zone->journalsize = size;
12439 }
12440 
12441 isc_int32_t
dns_zone_getjournalsize(dns_zone_t * zone)12442 dns_zone_getjournalsize(dns_zone_t *zone) {
12443 
12444 	REQUIRE(DNS_ZONE_VALID(zone));
12445 
12446 	return (zone->journalsize);
12447 }
12448 
12449 static void
zone_namerd_tostr(dns_zone_t * zone,char * buf,size_t length)12450 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
12451 	isc_result_t result = ISC_R_FAILURE;
12452 	isc_buffer_t buffer;
12453 
12454 	REQUIRE(buf != NULL);
12455 	REQUIRE(length > 1U);
12456 
12457 	/*
12458 	 * Leave space for terminating '\0'.
12459 	 */
12460 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12461 	if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
12462 		if (dns_name_dynamic(&zone->origin))
12463 			result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12464 		if (result != ISC_R_SUCCESS &&
12465 		    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12466 			isc_buffer_putstr(&buffer, "<UNKNOWN>");
12467 
12468 		if (isc_buffer_availablelength(&buffer) > 0)
12469 			isc_buffer_putstr(&buffer, "/");
12470 		(void)dns_rdataclass_totext(zone->rdclass, &buffer);
12471 	}
12472 
12473 	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
12474 	    strcmp(zone->view->name, "_default") != 0 &&
12475 	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
12476 		isc_buffer_putstr(&buffer, "/");
12477 		isc_buffer_putstr(&buffer, zone->view->name);
12478 	}
12479 	if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
12480 		isc_buffer_putstr(&buffer, " (signed)");
12481 	if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
12482 		isc_buffer_putstr(&buffer, " (unsigned)");
12483 
12484 	buf[isc_buffer_usedlength(&buffer)] = '\0';
12485 }
12486 
12487 static void
zone_name_tostr(dns_zone_t * zone,char * buf,size_t length)12488 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
12489 	isc_result_t result = ISC_R_FAILURE;
12490 	isc_buffer_t buffer;
12491 
12492 	REQUIRE(buf != NULL);
12493 	REQUIRE(length > 1U);
12494 
12495 	/*
12496 	 * Leave space for terminating '\0'.
12497 	 */
12498 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12499 	if (dns_name_dynamic(&zone->origin))
12500 		result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12501 	if (result != ISC_R_SUCCESS &&
12502 	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12503 		isc_buffer_putstr(&buffer, "<UNKNOWN>");
12504 
12505 	buf[isc_buffer_usedlength(&buffer)] = '\0';
12506 }
12507 
12508 static void
zone_rdclass_tostr(dns_zone_t * zone,char * buf,size_t length)12509 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
12510 	isc_buffer_t buffer;
12511 
12512 	REQUIRE(buf != NULL);
12513 	REQUIRE(length > 1U);
12514 
12515 	/*
12516 	 * Leave space for terminating '\0'.
12517 	 */
12518 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12519 	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
12520 
12521 	buf[isc_buffer_usedlength(&buffer)] = '\0';
12522 }
12523 
12524 static void
zone_viewname_tostr(dns_zone_t * zone,char * buf,size_t length)12525 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
12526 	isc_buffer_t buffer;
12527 
12528 	REQUIRE(buf != NULL);
12529 	REQUIRE(length > 1U);
12530 
12531 
12532 	/*
12533 	 * Leave space for terminating '\0'.
12534 	 */
12535 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12536 
12537 	if (zone->view == NULL) {
12538 		isc_buffer_putstr(&buffer, "_none");
12539 	} else if (strlen(zone->view->name)
12540 		   < isc_buffer_availablelength(&buffer)) {
12541 		isc_buffer_putstr(&buffer, zone->view->name);
12542 	} else {
12543 		isc_buffer_putstr(&buffer, "_toolong");
12544 	}
12545 
12546 	buf[isc_buffer_usedlength(&buffer)] = '\0';
12547 }
12548 
12549 void
dns_zone_name(dns_zone_t * zone,char * buf,size_t length)12550 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
12551 	REQUIRE(DNS_ZONE_VALID(zone));
12552 	REQUIRE(buf != NULL);
12553 	zone_namerd_tostr(zone, buf, length);
12554 }
12555 
12556 void
dns_zone_nameonly(dns_zone_t * zone,char * buf,size_t length)12557 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
12558 	REQUIRE(DNS_ZONE_VALID(zone));
12559 	REQUIRE(buf != NULL);
12560 	zone_name_tostr(zone, buf, length);
12561 }
12562 
12563 static void
notify_log(dns_zone_t * zone,int level,const char * fmt,...)12564 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12565 	va_list ap;
12566 	char message[4096];
12567 
12568 	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12569 		return;
12570 
12571 	va_start(ap, fmt);
12572 	vsnprintf(message, sizeof(message), fmt, ap);
12573 	va_end(ap);
12574 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
12575 		      level, "zone %s: %s", zone->strnamerd, message);
12576 }
12577 
12578 void
dns_zone_logc(dns_zone_t * zone,isc_logcategory_t * category,int level,const char * fmt,...)12579 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
12580 	      int level, const char *fmt, ...) {
12581 	va_list ap;
12582 	char message[4096];
12583 
12584 	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12585 		return;
12586 
12587 	va_start(ap, fmt);
12588 	vsnprintf(message, sizeof(message), fmt, ap);
12589 	va_end(ap);
12590 	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
12591 		      level, "%s%s: %s", (zone->type == dns_zone_key) ?
12592 		      "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12593 		      "redirect-zone" : "zone ", zone->strnamerd, message);
12594 }
12595 
12596 void
dns_zone_log(dns_zone_t * zone,int level,const char * fmt,...)12597 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12598 	va_list ap;
12599 	char message[4096];
12600 
12601 	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12602 		return;
12603 
12604 	va_start(ap, fmt);
12605 	vsnprintf(message, sizeof(message), fmt, ap);
12606 	va_end(ap);
12607 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12608 		      level, "%s%s: %s", (zone->type == dns_zone_key) ?
12609 		      "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12610 		      "redirect-zone" : "zone ", zone->strnamerd, message);
12611 }
12612 
12613 static void
zone_debuglog(dns_zone_t * zone,const char * me,int debuglevel,const char * fmt,...)12614 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
12615 	      const char *fmt, ...)
12616 {
12617 	va_list ap;
12618 	char message[4096];
12619 	int level = ISC_LOG_DEBUG(debuglevel);
12620 	const char *zstr;
12621 
12622 	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12623 		return;
12624 
12625 	va_start(ap, fmt);
12626 	vsnprintf(message, sizeof(message), fmt, ap);
12627 	va_end(ap);
12628 
12629 	switch (zone->type) {
12630 	case dns_zone_key:
12631 		zstr = "managed-keys-zone";
12632 		break;
12633 	case dns_zone_redirect:
12634 		zstr = "redirect-zone";
12635 		break;
12636 	default:
12637 		zstr = "zone";
12638 	}
12639 
12640 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12641 		      level, "%s: %s %s: %s", me, zstr, zone->strnamerd,
12642 		      message);
12643 }
12644 
12645 static int
message_count(dns_message_t * msg,dns_section_t section,dns_rdatatype_t type)12646 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
12647 {
12648 	isc_result_t result;
12649 	dns_name_t *name;
12650 	dns_rdataset_t *curr;
12651 	int count = 0;
12652 
12653 	result = dns_message_firstname(msg, section);
12654 	while (result == ISC_R_SUCCESS) {
12655 		name = NULL;
12656 		dns_message_currentname(msg, section, &name);
12657 
12658 		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
12659 		     curr = ISC_LIST_PREV(curr, link)) {
12660 			if (curr->type == type)
12661 				count++;
12662 		}
12663 		result = dns_message_nextname(msg, section);
12664 	}
12665 
12666 	return (count);
12667 }
12668 
12669 void
dns_zone_setmaxxfrin(dns_zone_t * zone,isc_uint32_t maxxfrin)12670 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
12671 	REQUIRE(DNS_ZONE_VALID(zone));
12672 
12673 	zone->maxxfrin = maxxfrin;
12674 }
12675 
12676 isc_uint32_t
dns_zone_getmaxxfrin(dns_zone_t * zone)12677 dns_zone_getmaxxfrin(dns_zone_t *zone) {
12678 	REQUIRE(DNS_ZONE_VALID(zone));
12679 
12680 	return (zone->maxxfrin);
12681 }
12682 
12683 void
dns_zone_setmaxxfrout(dns_zone_t * zone,isc_uint32_t maxxfrout)12684 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
12685 	REQUIRE(DNS_ZONE_VALID(zone));
12686 	zone->maxxfrout = maxxfrout;
12687 }
12688 
12689 isc_uint32_t
dns_zone_getmaxxfrout(dns_zone_t * zone)12690 dns_zone_getmaxxfrout(dns_zone_t *zone) {
12691 	REQUIRE(DNS_ZONE_VALID(zone));
12692 
12693 	return (zone->maxxfrout);
12694 }
12695 
12696 dns_zonetype_t
dns_zone_gettype(dns_zone_t * zone)12697 dns_zone_gettype(dns_zone_t *zone) {
12698 	REQUIRE(DNS_ZONE_VALID(zone));
12699 
12700 	return (zone->type);
12701 }
12702 
12703 dns_name_t *
dns_zone_getorigin(dns_zone_t * zone)12704 dns_zone_getorigin(dns_zone_t *zone) {
12705 	REQUIRE(DNS_ZONE_VALID(zone));
12706 
12707 	return (&zone->origin);
12708 }
12709 
12710 void
dns_zone_settask(dns_zone_t * zone,isc_task_t * task)12711 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
12712 	REQUIRE(DNS_ZONE_VALID(zone));
12713 
12714 	LOCK_ZONE(zone);
12715 	if (zone->task != NULL)
12716 		isc_task_detach(&zone->task);
12717 	isc_task_attach(task, &zone->task);
12718 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12719 	if (zone->db != NULL)
12720 		dns_db_settask(zone->db, zone->task);
12721 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12722 	UNLOCK_ZONE(zone);
12723 }
12724 
12725 void
dns_zone_gettask(dns_zone_t * zone,isc_task_t ** target)12726 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
12727 	REQUIRE(DNS_ZONE_VALID(zone));
12728 	isc_task_attach(zone->task, target);
12729 }
12730 
12731 void
dns_zone_setidlein(dns_zone_t * zone,isc_uint32_t idlein)12732 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
12733 	REQUIRE(DNS_ZONE_VALID(zone));
12734 
12735 	if (idlein == 0)
12736 		idlein = DNS_DEFAULT_IDLEIN;
12737 	zone->idlein = idlein;
12738 }
12739 
12740 isc_uint32_t
dns_zone_getidlein(dns_zone_t * zone)12741 dns_zone_getidlein(dns_zone_t *zone) {
12742 	REQUIRE(DNS_ZONE_VALID(zone));
12743 
12744 	return (zone->idlein);
12745 }
12746 
12747 void
dns_zone_setidleout(dns_zone_t * zone,isc_uint32_t idleout)12748 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
12749 	REQUIRE(DNS_ZONE_VALID(zone));
12750 
12751 	zone->idleout = idleout;
12752 }
12753 
12754 isc_uint32_t
dns_zone_getidleout(dns_zone_t * zone)12755 dns_zone_getidleout(dns_zone_t *zone) {
12756 	REQUIRE(DNS_ZONE_VALID(zone));
12757 
12758 	return (zone->idleout);
12759 }
12760 
12761 static void
notify_done(isc_task_t * task,isc_event_t * event)12762 notify_done(isc_task_t *task, isc_event_t *event) {
12763 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
12764 	dns_notify_t *notify;
12765 	isc_result_t result;
12766 	dns_message_t *message = NULL;
12767 	isc_buffer_t buf;
12768 	char rcode[128];
12769 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12770 
12771 	UNUSED(task);
12772 
12773 	notify = event->ev_arg;
12774 	REQUIRE(DNS_NOTIFY_VALID(notify));
12775 	INSIST(task == notify->zone->task);
12776 
12777 	isc_buffer_init(&buf, rcode, sizeof(rcode));
12778 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12779 
12780 	result = revent->result;
12781 	if (result == ISC_R_SUCCESS)
12782 		result = dns_message_create(notify->zone->mctx,
12783 					    DNS_MESSAGE_INTENTPARSE, &message);
12784 	if (result == ISC_R_SUCCESS)
12785 		result = dns_request_getresponse(revent->request, message,
12786 					DNS_MESSAGEPARSE_PRESERVEORDER);
12787 	if (result == ISC_R_SUCCESS)
12788 		result = dns_rcode_totext(message->rcode, &buf);
12789 	if (result == ISC_R_SUCCESS)
12790 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12791 			   "notify response from %s: %.*s",
12792 			   addrbuf, (int)buf.used, rcode);
12793 	else
12794 		notify_log(notify->zone, ISC_LOG_DEBUG(2),
12795 			   "notify to %s failed: %s", addrbuf,
12796 			   dns_result_totext(result));
12797 
12798 	/*
12799 	 * Old bind's return formerr if they see a soa record.	Retry w/o
12800 	 * the soa if we see a formerr and had sent a SOA.
12801 	 */
12802 	isc_event_free(&event);
12803 	if (message != NULL && message->rcode == dns_rcode_formerr &&
12804 	    (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
12805 		isc_boolean_t startup;
12806 
12807 		notify->flags |= DNS_NOTIFY_NOSOA;
12808 		dns_request_destroy(&notify->request);
12809 		startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
12810 		result = notify_send_queue(notify, startup);
12811 		if (result != ISC_R_SUCCESS)
12812 			notify_destroy(notify, ISC_FALSE);
12813 	} else {
12814 		if (result == ISC_R_TIMEDOUT)
12815 			notify_log(notify->zone, ISC_LOG_DEBUG(1),
12816 				   "notify to %s: retries exceeded", addrbuf);
12817 		notify_destroy(notify, ISC_FALSE);
12818 	}
12819 	if (message != NULL)
12820 		dns_message_destroy(&message);
12821 }
12822 
12823 struct secure_event {
12824 	isc_event_t e;
12825 	dns_db_t *db;
12826 	isc_uint32_t serial;
12827 };
12828 
12829 static void
update_log_cb(void * arg,dns_zone_t * zone,int level,const char * message)12830 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
12831 	UNUSED(arg);
12832 	dns_zone_log(zone, level, "%s", message);
12833 }
12834 
12835 static isc_result_t
sync_secure_journal(dns_zone_t * zone,dns_zone_t * raw,dns_journal_t * journal,isc_uint32_t start,isc_uint32_t end,dns_difftuple_t ** soatuplep,dns_diff_t * diff)12836 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
12837 		    isc_uint32_t start, isc_uint32_t end,
12838 		    dns_difftuple_t **soatuplep, dns_diff_t *diff)
12839 {
12840 	isc_result_t result;
12841 	dns_difftuple_t *tuple = NULL;
12842 	dns_diffop_t op = DNS_DIFFOP_ADD;
12843 	int n_soa = 0;
12844 
12845 	REQUIRE(soatuplep != NULL);
12846 
12847 	if (start == end)
12848 		return (DNS_R_UNCHANGED);
12849 
12850 	CHECK(dns_journal_iter_init(journal, start, end));
12851 	for (result = dns_journal_first_rr(journal);
12852 	     result == ISC_R_SUCCESS;
12853 	     result = dns_journal_next_rr(journal))
12854 	{
12855 		dns_name_t *name = NULL;
12856 		isc_uint32_t ttl;
12857 		dns_rdata_t *rdata = NULL;
12858 		dns_journal_current_rr(journal, &name, &ttl, &rdata);
12859 
12860 		if (rdata->type == dns_rdatatype_soa) {
12861 			n_soa++;
12862 			if (n_soa == 2) {
12863 				/*
12864 				 * Save the latest raw SOA record.
12865 				 */
12866 				if (*soatuplep != NULL)
12867 					dns_difftuple_free(soatuplep);
12868 				CHECK(dns_difftuple_create(diff->mctx,
12869 							   DNS_DIFFOP_ADD,
12870 							   name, ttl, rdata,
12871 							   soatuplep));
12872 			}
12873 			if (n_soa == 3)
12874 				n_soa = 1;
12875 			continue;
12876 		}
12877 
12878 		/* Sanity. */
12879 		if (n_soa == 0) {
12880 			dns_zone_log(raw, ISC_LOG_ERROR,
12881 				     "corrupt journal file: '%s'\n",
12882 				     raw->journal);
12883 			return (ISC_R_FAILURE);
12884 		}
12885 
12886 		if (zone->privatetype != 0 &&
12887 		    rdata->type == zone->privatetype)
12888 			continue;
12889 
12890 		if (rdata->type == dns_rdatatype_nsec ||
12891 		    rdata->type == dns_rdatatype_rrsig ||
12892 		    rdata->type == dns_rdatatype_nsec3 ||
12893 		    rdata->type == dns_rdatatype_dnskey ||
12894 		    rdata->type == dns_rdatatype_nsec3param)
12895 			continue;
12896 
12897 		op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
12898 
12899 		CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
12900 					   &tuple));
12901 		dns_diff_appendminimal(diff, &tuple);
12902 	}
12903 	if (result == ISC_R_NOMORE)
12904 		result = ISC_R_SUCCESS;
12905 
12906  failure:
12907 	return(result);
12908 }
12909 
12910 static isc_result_t
sync_secure_db(dns_zone_t * seczone,dns_zone_t * raw,dns_db_t * secdb,dns_dbversion_t * secver,dns_difftuple_t ** soatuple,dns_diff_t * diff)12911 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
12912 	       dns_dbversion_t *secver, dns_difftuple_t **soatuple,
12913 	       dns_diff_t *diff)
12914 {
12915 	isc_result_t result;
12916 	dns_db_t *rawdb = NULL;
12917 	dns_dbversion_t *rawver = NULL;
12918 	dns_difftuple_t *tuple = NULL, *next;
12919 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
12920 	dns_rdata_soa_t oldsoa, newsoa;
12921 
12922 	REQUIRE(DNS_ZONE_VALID(seczone));
12923 	REQUIRE(soatuple != NULL && *soatuple == NULL);
12924 
12925 	if (!seczone->sourceserialset)
12926 		return (DNS_R_UNCHANGED);
12927 
12928 	dns_db_attach(raw->db, &rawdb);
12929 	dns_db_currentversion(rawdb, &rawver);
12930 	result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
12931 	dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
12932 	dns_db_detach(&rawdb);
12933 
12934 	if (result != ISC_R_SUCCESS)
12935 		return (result);
12936 
12937 	for (tuple = ISC_LIST_HEAD(diff->tuples);
12938 	     tuple != NULL;
12939 	     tuple = next)
12940 	{
12941 		next = ISC_LIST_NEXT(tuple, link);
12942 		if (tuple->rdata.type == dns_rdatatype_nsec ||
12943 		    tuple->rdata.type == dns_rdatatype_rrsig ||
12944 		    tuple->rdata.type == dns_rdatatype_dnskey ||
12945 		    tuple->rdata.type == dns_rdatatype_nsec3 ||
12946 		    tuple->rdata.type == dns_rdatatype_nsec3param)
12947 		{
12948 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
12949 			dns_difftuple_free(&tuple);
12950 			continue;
12951 		}
12952 		if (tuple->rdata.type == dns_rdatatype_soa) {
12953 			if (tuple->op == DNS_DIFFOP_DEL) {
12954 				INSIST(oldtuple == NULL);
12955 				oldtuple = tuple;
12956 			}
12957 			if (tuple->op == DNS_DIFFOP_ADD) {
12958 				INSIST(newtuple == NULL);
12959 				newtuple = tuple;
12960 			}
12961 		}
12962 	}
12963 
12964 	if (oldtuple != NULL && newtuple != NULL) {
12965 
12966 		result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
12967 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
12968 
12969 		result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
12970 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
12971 
12972 		/*
12973 		 * If the SOA records are the same except for the serial
12974 		 * remove them from the diff.
12975 		 */
12976 		if (oldsoa.refresh == newsoa.refresh &&
12977 		    oldsoa.retry == newsoa.retry &&
12978 		    oldsoa.minimum == newsoa.minimum &&
12979 		    oldsoa.expire == newsoa.expire &&
12980 		    dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
12981 		    dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
12982 			ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12983 			dns_difftuple_free(&oldtuple);
12984 			ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12985 			dns_difftuple_free(&newtuple);
12986 		}
12987 	}
12988 
12989 	if (ISC_LIST_EMPTY(diff->tuples))
12990 		return (DNS_R_UNCHANGED);
12991 
12992 	/*
12993 	 * If there are still SOA records in the diff they can now be removed
12994 	 * saving the new SOA record.
12995 	 */
12996 	if (oldtuple != NULL) {
12997 		ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12998 		dns_difftuple_free(&oldtuple);
12999 	}
13000 
13001 	if (newtuple != NULL) {
13002 		ISC_LIST_UNLINK(diff->tuples, newtuple, link);
13003 		*soatuple = newtuple;
13004 	}
13005 
13006 	return (ISC_R_SUCCESS);
13007 }
13008 
13009 static void
receive_secure_serial(isc_task_t * task,isc_event_t * event)13010 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
13011 	static char me[] = "receive_secure_serial";
13012 	isc_result_t result = ISC_R_SUCCESS;
13013 	dns_journal_t *rjournal = NULL;
13014 	dns_journal_t *sjournal = NULL;
13015 	isc_uint32_t start, end;
13016 	dns_zone_t *zone;
13017 	dns_difftuple_t *tuple = NULL, *soatuple = NULL;
13018 	dns_update_log_t log = { update_log_cb, NULL };
13019 	isc_time_t timenow;
13020 
13021 	UNUSED(task);
13022 
13023 	zone = event->ev_arg;
13024 	end = ((struct secure_event *)event)->serial;
13025 
13026 	ENTER;
13027 
13028 	LOCK_ZONE(zone);
13029 
13030 	/*
13031 	 * If we are already processing a receive secure serial event
13032 	 * for the zone, just queue the new one and exit.
13033 	 */
13034 	if (zone->rss_event != NULL && zone->rss_event != event) {
13035 		ISC_LIST_APPEND(zone->rss_events, event, ev_link);
13036 		UNLOCK_ZONE(zone);
13037 		return;
13038 	}
13039 
13040  nextevent:
13041 	if (zone->rss_event != NULL) {
13042 		INSIST(zone->rss_event == event);
13043 		UNLOCK_ZONE(zone);
13044 	} else {
13045 		zone->rss_event = event;
13046 		dns_diff_init(zone->mctx, &zone->rss_diff);
13047 
13048 		/*
13049 		 * zone->db may be NULL, if the load from disk failed.
13050 		 */
13051 		result = ISC_R_SUCCESS;
13052 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13053 		if (zone->db != NULL)
13054 			dns_db_attach(zone->db, &zone->rss_db);
13055 		else
13056 			result = ISC_R_FAILURE;
13057 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13058 
13059 		if (result == ISC_R_SUCCESS && zone->raw != NULL)
13060 			dns_zone_attach(zone->raw, &zone->rss_raw);
13061 		else
13062 			result = ISC_R_FAILURE;
13063 
13064 		UNLOCK_ZONE(zone);
13065 
13066 		CHECK(result);
13067 
13068 		/*
13069 		 * We first attempt to sync the raw zone to the secure zone
13070 		 * by using the raw zone's journal, applying all the deltas
13071 		 * from the latest source-serial of the secure zone up to
13072 		 * the current serial number of the raw zone.
13073 		 *
13074 		 * If that fails, then we'll fall back to a direct comparison
13075 		 * between raw and secure zones.
13076 		 */
13077 		CHECK(dns_journal_open(zone->rss_raw->mctx,
13078 				       zone->rss_raw->journal,
13079 				       DNS_JOURNAL_WRITE, &rjournal));
13080 
13081 		result = dns_journal_open(zone->mctx, zone->journal,
13082 					  DNS_JOURNAL_READ, &sjournal);
13083 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
13084 			goto failure;
13085 
13086 		if (!dns_journal_get_sourceserial(rjournal, &start)) {
13087 			start = dns_journal_first_serial(rjournal);
13088 			dns_journal_set_sourceserial(rjournal, start);
13089 		}
13090 		if (sjournal != NULL) {
13091 			isc_uint32_t serial;
13092 			/*
13093 			 * We read the secure journal first, if that
13094 			 * exists use its value provided it is greater
13095 			 * that from the raw journal.
13096 			 */
13097 			if (dns_journal_get_sourceserial(sjournal, &serial)) {
13098 				if (isc_serial_gt(serial, start))
13099 					start = serial;
13100 			}
13101 			dns_journal_destroy(&sjournal);
13102 		}
13103 
13104 		dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
13105 		CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
13106 
13107 		/*
13108 		 * Try to apply diffs from the raw zone's journal to the secure
13109 		 * zone.  If that fails, we recover by syncing up the databases
13110 		 * directly.
13111 		 */
13112 		result = sync_secure_journal(zone, zone->rss_raw, rjournal,
13113 					     start, end, &soatuple,
13114 					     &zone->rss_diff);
13115 		if (result == DNS_R_UNCHANGED)
13116 			goto failure;
13117 		else if (result != ISC_R_SUCCESS)
13118 			CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
13119 					     zone->rss_oldver, &soatuple,
13120 					     &zone->rss_diff));
13121 
13122 		CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
13123 				     zone->rss_newver));
13124 
13125 		if (soatuple != NULL) {
13126 			isc_uint32_t oldserial, newserial, desired;
13127 
13128 			CHECK(dns_db_createsoatuple(zone->rss_db,
13129 						    zone->rss_oldver,
13130 						    zone->rss_diff.mctx,
13131 						    DNS_DIFFOP_DEL, &tuple));
13132 			oldserial = dns_soa_getserial(&tuple->rdata);
13133 			newserial = desired =
13134 				    dns_soa_getserial(&soatuple->rdata);
13135 			if (!isc_serial_gt(newserial, oldserial)) {
13136 				newserial = oldserial + 1;
13137 				if (newserial == 0)
13138 					newserial++;
13139 				dns_soa_setserial(newserial, &soatuple->rdata);
13140 			}
13141 			CHECK(do_one_tuple(&tuple, zone->rss_db,
13142 					   zone->rss_newver, &zone->rss_diff));
13143 			CHECK(do_one_tuple(&soatuple, zone->rss_db,
13144 					   zone->rss_newver, &zone->rss_diff));
13145 			dns_zone_log(zone, ISC_LOG_INFO,
13146 				     "serial %u (unsigned %u)",
13147 				     newserial, desired);
13148 		} else
13149 			CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
13150 						&zone->rss_diff, zone->mctx,
13151 						zone->updatemethod));
13152 
13153 	}
13154 	result = dns_update_signaturesinc(&log, zone, zone->rss_db,
13155 					  zone->rss_oldver, zone->rss_newver,
13156 					  &zone->rss_diff,
13157 					  zone->sigvalidityinterval,
13158 					  &zone->rss_state);
13159 	if (result == DNS_R_CONTINUE) {
13160 		if (rjournal != NULL)
13161 			dns_journal_destroy(&rjournal);
13162 		isc_task_send(task, &event);
13163 		fprintf(stderr, "looping on dns_update_signaturesinc\n");
13164 		return;
13165 	}
13166 	if (result != ISC_R_SUCCESS)
13167 		goto failure;
13168 
13169 	if (rjournal == NULL)
13170 		CHECK(dns_journal_open(zone->rss_raw->mctx,
13171 				       zone->rss_raw->journal,
13172 				       DNS_JOURNAL_WRITE, &rjournal));
13173 	CHECK(zone_journal(zone, &zone->rss_diff, &end,
13174 			   "receive_secure_serial"));
13175 
13176 	dns_journal_set_sourceserial(rjournal, end);
13177 	dns_journal_commit(rjournal);
13178 
13179 	LOCK_ZONE(zone);
13180 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13181 
13182 	zone->sourceserial = end;
13183 	zone->sourceserialset = ISC_TRUE;
13184 	zone_needdump(zone, DNS_DUMP_DELAY);
13185 
13186 	TIME_NOW(&timenow);
13187 	zone_settimer(zone, &timenow);
13188 	UNLOCK_ZONE(zone);
13189 
13190 	dns_db_closeversion(zone->rss_db, &zone->rss_oldver, ISC_FALSE);
13191 	dns_db_closeversion(zone->rss_db, &zone->rss_newver, ISC_TRUE);
13192 
13193  failure:
13194 	isc_event_free(&zone->rss_event);
13195 	event = ISC_LIST_HEAD(zone->rss_events);
13196 
13197 	if (zone->rss_raw != NULL)
13198 		dns_zone_detach(&zone->rss_raw);
13199 	if (result != ISC_R_SUCCESS)
13200 		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
13201 			     dns_result_totext(result));
13202 	if (tuple != NULL)
13203 		dns_difftuple_free(&tuple);
13204 	if (soatuple != NULL)
13205 		dns_difftuple_free(&soatuple);
13206 	if (zone->rss_db != NULL) {
13207 		if (zone->rss_oldver != NULL)
13208 			dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
13209 					    ISC_FALSE);
13210 		if (zone->rss_newver != NULL)
13211 			dns_db_closeversion(zone->rss_db, &zone->rss_newver,
13212 					    ISC_FALSE);
13213 		dns_db_detach(&zone->rss_db);
13214 	}
13215 	INSIST(zone->rss_oldver == NULL);
13216 	INSIST(zone->rss_newver == NULL);
13217 	if (rjournal != NULL)
13218 		dns_journal_destroy(&rjournal);
13219 	dns_diff_clear(&zone->rss_diff);
13220 
13221 	if (event != NULL) {
13222 		LOCK_ZONE(zone);
13223 		INSIST(zone->irefs > 1);
13224 		zone->irefs--;
13225 		goto nextevent;
13226 	}
13227 	dns_zone_idetach(&zone);
13228 }
13229 
13230 static isc_result_t
zone_send_secureserial(dns_zone_t * zone,isc_uint32_t serial)13231 zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) {
13232 	isc_event_t *e;
13233 	dns_zone_t *dummy = NULL;
13234 
13235 	e = isc_event_allocate(zone->secure->mctx, zone,
13236 			       DNS_EVENT_ZONESECURESERIAL,
13237 			       receive_secure_serial, zone->secure,
13238 			       sizeof(struct secure_event));
13239 	if (e == NULL)
13240 		return (ISC_R_NOMEMORY);
13241 	((struct secure_event *)e)->serial = serial;
13242 	INSIST(LOCKED_ZONE(zone->secure));
13243 	zone_iattach(zone->secure, &dummy);
13244 	isc_task_send(zone->secure->task, &e);
13245 
13246 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
13247 	return (ISC_R_SUCCESS);
13248 }
13249 
13250 static isc_result_t
checkandaddsoa(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdataset_t * rdataset,isc_uint32_t oldserial)13251 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
13252 	       dns_rdataset_t *rdataset, isc_uint32_t oldserial)
13253 {
13254 	dns_rdata_soa_t soa;
13255 	dns_rdata_t rdata = DNS_RDATA_INIT;
13256 	dns_rdatalist_t temprdatalist;
13257 	dns_rdataset_t temprdataset;
13258 	isc_buffer_t b;
13259 	isc_result_t result;
13260 	unsigned char buf[DNS_SOA_BUFFERSIZE];
13261 
13262 	result = dns_rdataset_first(rdataset);
13263 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
13264 	dns_rdataset_current(rdataset, &rdata);
13265 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
13266 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
13267 
13268 	if (isc_serial_gt(soa.serial, oldserial))
13269 		return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
13270 					   NULL));
13271 	/*
13272 	 * Always bump the serial.
13273 	 */
13274 	oldserial++;
13275 	if (oldserial == 0)
13276 		oldserial++;
13277 	soa.serial = oldserial;
13278 
13279 	/*
13280 	 * Construct a replacement rdataset.
13281 	 */
13282 	dns_rdata_reset(&rdata);
13283 	isc_buffer_init(&b, buf, sizeof(buf));
13284 	result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
13285 				      dns_rdatatype_soa, &soa, &b);
13286 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
13287 	dns_rdatalist_init(&temprdatalist);
13288 	temprdatalist.rdclass = rdata.rdclass;
13289 	temprdatalist.type = rdata.type;
13290 	temprdatalist.ttl = rdataset->ttl;
13291 	ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
13292 
13293 	dns_rdataset_init(&temprdataset);
13294 	result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
13295 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
13296 	return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
13297 				   0, NULL));
13298 }
13299 
13300 /*
13301  * This function should populate an nsec3paramlist_t with the
13302  * nsecparam_t data from a zone.
13303  */
13304 static isc_result_t
save_nsec3param(dns_zone_t * zone,nsec3paramlist_t * nsec3list)13305 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
13306 	isc_result_t result;
13307 	dns_dbnode_t *node = NULL;
13308 	dns_rdataset_t rdataset, prdataset;
13309 	dns_dbversion_t *version = NULL;
13310 	nsec3param_t *nsec3param = NULL;
13311 	nsec3param_t *nsec3p = NULL;
13312 	nsec3param_t *next;
13313 	dns_db_t *db = NULL;
13314 	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
13315 
13316 	REQUIRE(DNS_ZONE_VALID(zone));
13317 	REQUIRE(nsec3list != NULL);
13318 	REQUIRE(ISC_LIST_EMPTY(*nsec3list));
13319 
13320 	dns_rdataset_init(&rdataset);
13321 	dns_rdataset_init(&prdataset);
13322 
13323 	dns_db_attach(zone->db, &db);
13324 	CHECK(dns_db_getoriginnode(db, &node));
13325 
13326 	dns_db_currentversion(db, &version);
13327 	result = dns_db_findrdataset(db, node, version,
13328 				     dns_rdatatype_nsec3param,
13329 				     dns_rdatatype_none, 0, &rdataset, NULL);
13330 
13331 	if (result != ISC_R_SUCCESS)
13332 		goto getprivate;
13333 
13334 	/*
13335 	 * walk nsec3param rdataset making a list of parameters (note that
13336 	 * multiple simultaneous nsec3 chains are annoyingly legal -- this
13337 	 * is why we use an nsec3list, even tho we will usually only have
13338 	 * one)
13339 	 */
13340 	for (result = dns_rdataset_first(&rdataset);
13341 	     result == ISC_R_SUCCESS;
13342 	     result = dns_rdataset_next(&rdataset))
13343 	{
13344 		dns_rdata_t rdata = DNS_RDATA_INIT;
13345 		dns_rdata_t private = DNS_RDATA_INIT;
13346 
13347 		dns_rdataset_current(&rdataset, &rdata);
13348 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13349 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13350 			      "looping through nsec3param data");
13351 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13352 		if (nsec3param == NULL)
13353 			CHECK(ISC_R_NOMEMORY);
13354 		ISC_LINK_INIT(nsec3param, link);
13355 
13356 		/*
13357 		 * now transfer the data from the rdata to
13358 		 * the nsec3param
13359 		 */
13360 		dns_nsec3param_toprivate(&rdata, &private,
13361 					 zone->privatetype, nsec3param->data,
13362 					 sizeof(nsec3param->data));
13363 		nsec3param->length = private.length;
13364 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13365 	}
13366 
13367  getprivate:
13368 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
13369 				     dns_rdatatype_none, 0, &prdataset, NULL);
13370 	if (result != ISC_R_SUCCESS)
13371 		goto done;
13372 
13373 	/*
13374 	 * walk private type records, converting them to nsec3 parameters
13375 	 * using dns_nsec3param_fromprivate(), do the right thing based on
13376 	 * CREATE and REMOVE flags
13377 	 */
13378 	for (result = dns_rdataset_first(&prdataset);
13379 	     result == ISC_R_SUCCESS;
13380 	     result = dns_rdataset_next(&prdataset))
13381 	{
13382 		dns_rdata_t rdata = DNS_RDATA_INIT;
13383 		dns_rdata_t private = DNS_RDATA_INIT;
13384 
13385 		dns_rdataset_current(&prdataset, &private);
13386 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13387 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13388 			      "looping through nsec3param private data");
13389 
13390 		/*
13391 		 * Do we have a valid private record?
13392 		 */
13393 		if (!dns_nsec3param_fromprivate(&private, &rdata,
13394 						buf, sizeof(buf)))
13395 			continue;
13396 
13397 		/*
13398 		 * Remove any NSEC3PARAM records scheduled to be removed.
13399 		 */
13400 		if (NSEC3REMOVE(rdata.data[1])) {
13401 			/*
13402 			 * Zero out the flags.
13403 			 */
13404 			rdata.data[1] = 0;
13405 
13406 			for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13407 			     nsec3p != NULL;
13408 			     nsec3p = next)
13409 			{
13410 				next = ISC_LIST_NEXT(nsec3p, link);
13411 
13412 				if (nsec3p->length == rdata.length + 1 &&
13413 				    memcmp(rdata.data, nsec3p->data + 1,
13414 					   nsec3p->length - 1) == 0) {
13415 					ISC_LIST_UNLINK(*nsec3list,
13416 							nsec3p, link);
13417 					isc_mem_put(zone->mctx, nsec3p,
13418 						    sizeof(nsec3param_t));
13419 				}
13420 			}
13421 			continue;
13422 		}
13423 
13424 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13425 		if (nsec3param == NULL)
13426 			CHECK(ISC_R_NOMEMORY);
13427 		ISC_LINK_INIT(nsec3param, link);
13428 
13429 		/*
13430 		 * Copy the remaining private records so the nsec/nsec3
13431 		 * chain gets created.
13432 		 */
13433 		INSIST(private.length <= sizeof(nsec3param->data));
13434 		memmove(nsec3param->data, private.data, private.length);
13435 		nsec3param->length = private.length;
13436 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13437 	}
13438 
13439  done:
13440 	if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
13441 		result = ISC_R_SUCCESS;
13442 
13443  failure:
13444 	if (node != NULL)
13445 		dns_db_detachnode(db, &node);
13446 	if (version != NULL)
13447 		dns_db_closeversion(db, &version, ISC_FALSE);
13448 	if (db != NULL)
13449 		dns_db_detach(&db);
13450 	if (dns_rdataset_isassociated(&rdataset))
13451 		dns_rdataset_disassociate(&rdataset);
13452 	if (dns_rdataset_isassociated(&prdataset))
13453 		dns_rdataset_disassociate(&prdataset);
13454 	return (result);
13455 }
13456 
13457 /*
13458  * Walk the list of the nsec3 chains desired for the zone, converting
13459  * parameters to private type records using dns_nsec3param_toprivate(),
13460  * and insert them into the new zone db.
13461  */
13462 static isc_result_t
restore_nsec3param(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * version,nsec3paramlist_t * nsec3list)13463 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
13464 		   nsec3paramlist_t *nsec3list)
13465 {
13466 	isc_result_t result;
13467 	dns_diff_t diff;
13468 	dns_rdata_t rdata;
13469 	nsec3param_t *nsec3p = NULL;
13470 	nsec3param_t *next;
13471 
13472 	REQUIRE(DNS_ZONE_VALID(zone));
13473 	REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
13474 
13475 	dns_diff_init(zone->mctx, &diff);
13476 
13477 	/*
13478 	 * Loop through the list of private-type records, set the INITIAL
13479 	 * and CREATE flags, and the add the record to the apex of the tree
13480 	 * in db.
13481 	 */
13482 	for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13483 	     nsec3p != NULL;
13484 	     nsec3p = next)
13485 	{
13486 		next = ISC_LIST_NEXT(nsec3p, link);
13487 		dns_rdata_init(&rdata);
13488 		nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
13489 		rdata.length = nsec3p->length;
13490 		rdata.data = nsec3p->data;
13491 		rdata.type = zone->privatetype;
13492 		rdata.rdclass = zone->rdclass;
13493 		CHECK(update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
13494 				    &zone->origin, 0, &rdata));
13495 	}
13496 
13497 	result = ISC_R_SUCCESS;
13498 
13499 failure:
13500 	for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13501 	     nsec3p != NULL;
13502 	     nsec3p = next)
13503 	{
13504 		next = ISC_LIST_NEXT(nsec3p, link);
13505 		ISC_LIST_UNLINK(*nsec3list, nsec3p, link);
13506 		isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
13507 	}
13508 
13509 	dns_diff_clear(&diff);
13510 	return (result);
13511 }
13512 
13513 static void
receive_secure_db(isc_task_t * task,isc_event_t * event)13514 receive_secure_db(isc_task_t *task, isc_event_t *event) {
13515 	isc_result_t result;
13516 	dns_zone_t *zone;
13517 	dns_db_t *rawdb, *db = NULL;
13518 	dns_dbnode_t *rawnode = NULL, *node = NULL;
13519 	dns_fixedname_t fname;
13520 	dns_name_t *name;
13521 	dns_dbiterator_t *dbiterator = NULL;
13522 	dns_rdatasetiter_t *rdsit = NULL;
13523 	dns_rdataset_t rdataset;
13524 	dns_dbversion_t *version = NULL;
13525 	isc_time_t loadtime;
13526 	unsigned int oldserial = 0;
13527 	isc_boolean_t have_oldserial = ISC_FALSE;
13528 	nsec3paramlist_t nsec3list;
13529 
13530 	UNUSED(task);
13531 
13532 	ISC_LIST_INIT(nsec3list);
13533 
13534 	zone = event->ev_arg;
13535 	rawdb = ((struct secure_event *)event)->db;
13536 	isc_event_free(&event);
13537 
13538 	dns_fixedname_init(&fname);
13539 	name = dns_fixedname_name(&fname);
13540 	dns_rdataset_init(&rdataset);
13541 
13542 	LOCK_ZONE(zone);
13543 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
13544 		result = ISC_R_SHUTTINGDOWN;
13545 		goto failure;
13546 	}
13547 
13548 	TIME_NOW(&loadtime);
13549 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13550 	if (zone->db != NULL) {
13551 		result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
13552 		if (result == ISC_R_SUCCESS)
13553 			have_oldserial = ISC_TRUE;
13554 
13555 		/*
13556 		 * assemble nsec3parameters from the old zone, and set a flag
13557 		 * if any are found
13558 		 */
13559 		result = save_nsec3param(zone, &nsec3list);
13560 		if (result != ISC_R_SUCCESS) {
13561 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13562 			goto failure;
13563 		}
13564 	}
13565 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13566 
13567 	result = dns_db_create(zone->mctx, zone->db_argv[0],
13568 			       &zone->origin, dns_dbtype_zone, zone->rdclass,
13569 			       zone->db_argc - 1, zone->db_argv + 1, &db);
13570 	if (result != ISC_R_SUCCESS)
13571 		goto failure;
13572 
13573 	result = dns_db_newversion(db, &version);
13574 	if (result != ISC_R_SUCCESS)
13575 		goto failure;
13576 
13577 	result = dns_db_createiterator(rawdb, 0, &dbiterator);
13578 	if (result != ISC_R_SUCCESS)
13579 		goto failure;
13580 
13581 	for (result = dns_dbiterator_first(dbiterator);
13582 	     result == ISC_R_SUCCESS;
13583 	     result = dns_dbiterator_next(dbiterator)) {
13584 		result = dns_dbiterator_current(dbiterator, &rawnode, name);
13585 		if (result != ISC_R_SUCCESS)
13586 			continue;
13587 
13588 		result = dns_db_findnode(db, name, ISC_TRUE, &node);
13589 		if (result != ISC_R_SUCCESS)
13590 			goto failure;
13591 
13592 		result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
13593 		if (result != ISC_R_SUCCESS)
13594 			goto failure;
13595 
13596 		for (result = dns_rdatasetiter_first(rdsit);
13597 		     result == ISC_R_SUCCESS;
13598 		     result = dns_rdatasetiter_next(rdsit)) {
13599 			dns_rdatasetiter_current(rdsit, &rdataset);
13600 			if (rdataset.type == dns_rdatatype_nsec ||
13601 			    rdataset.type == dns_rdatatype_rrsig ||
13602 			    rdataset.type == dns_rdatatype_nsec3 ||
13603 			    rdataset.type == dns_rdatatype_dnskey ||
13604 			    rdataset.type == dns_rdatatype_nsec3param) {
13605 				dns_rdataset_disassociate(&rdataset);
13606 				continue;
13607 			}
13608 			if (rdataset.type == dns_rdatatype_soa &&
13609 			    have_oldserial) {
13610 				result = checkandaddsoa(db, node, version,
13611 							&rdataset, oldserial);
13612 			} else
13613 				result = dns_db_addrdataset(db, node, version,
13614 							    0, &rdataset, 0,
13615 							    NULL);
13616 			if (result != ISC_R_SUCCESS)
13617 				goto failure;
13618 
13619 			dns_rdataset_disassociate(&rdataset);
13620 		}
13621 		dns_rdatasetiter_destroy(&rdsit);
13622 		dns_db_detachnode(rawdb, &rawnode);
13623 		dns_db_detachnode(db, &node);
13624 	}
13625 
13626 	/*
13627 	 * Call restore_nsec3param() to create private-type records from
13628 	 * the old nsec3 parameters and insert them into db
13629 	 */
13630 	if (!ISC_LIST_EMPTY(nsec3list))
13631 		restore_nsec3param(zone, db, version, &nsec3list);
13632 
13633 	dns_db_closeversion(db, &version, ISC_TRUE);
13634 
13635 	/*
13636 	 * Lock hierarchy: zmgr, zone, raw.
13637 	 */
13638 	INSIST(zone != zone->raw);
13639 	LOCK_ZONE(zone->raw);
13640 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13641 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
13642 	zone_needdump(zone, 0); /* XXXMPA */
13643 	UNLOCK_ZONE(zone->raw);
13644 
13645  failure:
13646 	UNLOCK_ZONE(zone);
13647 	if (result != ISC_R_SUCCESS)
13648 		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
13649 			     dns_result_totext(result));
13650 
13651 	while (!ISC_LIST_EMPTY(nsec3list)) {
13652 		nsec3param_t *nsec3p;
13653 		nsec3p = ISC_LIST_HEAD(nsec3list);
13654 		ISC_LIST_UNLINK(nsec3list, nsec3p, link);
13655 		isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
13656 	}
13657 	if (dns_rdataset_isassociated(&rdataset))
13658 		dns_rdataset_disassociate(&rdataset);
13659 	if (db != NULL) {
13660 		if (node != NULL)
13661 			dns_db_detachnode(db, &node);
13662 		if (version != NULL)
13663 			dns_db_closeversion(db, &version, ISC_FALSE);
13664 		dns_db_detach(&db);
13665 	}
13666 	if (rawnode != NULL)
13667 		dns_db_detachnode(rawdb, &rawnode);
13668 	dns_db_detach(&rawdb);
13669 	if (dbiterator != NULL)
13670 		dns_dbiterator_destroy(&dbiterator);
13671 	dns_zone_idetach(&zone);
13672 
13673 	INSIST(version == NULL);
13674 }
13675 
13676 static isc_result_t
zone_send_securedb(dns_zone_t * zone,dns_db_t * db)13677 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
13678 	isc_event_t *e;
13679 	dns_db_t *dummy = NULL;
13680 	dns_zone_t *secure = NULL;
13681 
13682 	e = isc_event_allocate(zone->secure->mctx, zone,
13683 			       DNS_EVENT_ZONESECUREDB,
13684 			       receive_secure_db, zone->secure,
13685 			       sizeof(struct secure_event));
13686 	if (e == NULL)
13687 		return (ISC_R_NOMEMORY);
13688 	dns_db_attach(db, &dummy);
13689 	((struct secure_event *)e)->db = dummy;
13690 	INSIST(LOCKED_ZONE(zone->secure));
13691 	zone_iattach(zone->secure, &secure);
13692 	isc_task_send(zone->secure->task, &e);
13693 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
13694 	return (ISC_R_SUCCESS);
13695 }
13696 
13697 isc_result_t
dns_zone_replacedb(dns_zone_t * zone,dns_db_t * db,isc_boolean_t dump)13698 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13699 	isc_result_t result;
13700 	dns_zone_t *secure = NULL;
13701 
13702 	REQUIRE(DNS_ZONE_VALID(zone));
13703  again:
13704 	LOCK_ZONE(zone);
13705 	if (inline_raw(zone)) {
13706 		secure = zone->secure;
13707 		INSIST(secure != zone);
13708 		TRYLOCK_ZONE(result, secure);
13709 		if (result != ISC_R_SUCCESS) {
13710 			UNLOCK_ZONE(zone);
13711 			secure = NULL;
13712 #if ISC_PLATFORM_USETHREADS
13713 			isc_thread_yield();
13714 #endif
13715 			goto again;
13716 		}
13717 	}
13718 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13719 	result = zone_replacedb(zone, db, dump);
13720 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13721 	if (secure != NULL)
13722 		UNLOCK_ZONE(secure);
13723 	UNLOCK_ZONE(zone);
13724 	return (result);
13725 }
13726 
13727 static isc_result_t
zone_replacedb(dns_zone_t * zone,dns_db_t * db,isc_boolean_t dump)13728 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13729 	dns_dbversion_t *ver;
13730 	isc_result_t result;
13731 	unsigned int soacount = 0;
13732 	unsigned int nscount = 0;
13733 
13734 	/*
13735 	 * 'zone' and 'zonedb' locked by caller.
13736 	 */
13737 	REQUIRE(DNS_ZONE_VALID(zone));
13738 	REQUIRE(LOCKED_ZONE(zone));
13739 	if (inline_raw(zone))
13740 		REQUIRE(LOCKED_ZONE(zone->secure));
13741 
13742 	result = zone_get_from_db(zone, db, &nscount, &soacount,
13743 				  NULL, NULL, NULL, NULL, NULL, NULL);
13744 	if (result == ISC_R_SUCCESS) {
13745 		if (soacount != 1) {
13746 			dns_zone_log(zone, ISC_LOG_ERROR,
13747 				     "has %d SOA records", soacount);
13748 			result = DNS_R_BADZONE;
13749 		}
13750 		if (nscount == 0 && zone->type != dns_zone_key) {
13751 			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
13752 			result = DNS_R_BADZONE;
13753 		}
13754 		if (result != ISC_R_SUCCESS)
13755 			return (result);
13756 	} else {
13757 		dns_zone_log(zone, ISC_LOG_ERROR,
13758 			    "retrieving SOA and NS records failed: %s",
13759 			    dns_result_totext(result));
13760 		return (result);
13761 	}
13762 
13763 	result = check_nsec3param(zone, db);
13764 	if (result != ISC_R_SUCCESS)
13765 		return (result);
13766 
13767 	ver = NULL;
13768 	dns_db_currentversion(db, &ver);
13769 
13770 	/*
13771 	 * The initial version of a slave zone is always dumped;
13772 	 * subsequent versions may be journaled instead if this
13773 	 * is enabled in the configuration.
13774 	 */
13775 	if (zone->db != NULL && zone->journal != NULL &&
13776 	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
13777 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
13778 	{
13779 		isc_uint32_t serial, oldserial;
13780 
13781 		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
13782 
13783 		result = dns_db_getsoaserial(db, ver, &serial);
13784 		if (result != ISC_R_SUCCESS) {
13785 			dns_zone_log(zone, ISC_LOG_ERROR,
13786 				     "ixfr-from-differences: unable to get "
13787 				     "new serial");
13788 			goto fail;
13789 		}
13790 
13791 		/*
13792 		 * This is checked in zone_postload() for master zones.
13793 		 */
13794 		result = zone_get_from_db(zone, zone->db, NULL, &soacount,
13795 					  &oldserial, NULL, NULL, NULL, NULL,
13796 					  NULL);
13797 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
13798 		RUNTIME_CHECK(soacount > 0U);
13799 		if ((zone->type == dns_zone_slave ||
13800 		     (zone->type == dns_zone_redirect &&
13801 		      zone->masters != NULL))
13802 		    && !isc_serial_gt(serial, oldserial)) {
13803 			isc_uint32_t serialmin, serialmax;
13804 			serialmin = (oldserial + 1) & 0xffffffffU;
13805 			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
13806 			dns_zone_log(zone, ISC_LOG_ERROR,
13807 				     "ixfr-from-differences: failed: "
13808 				     "new serial (%u) out of range [%u - %u]",
13809 				     serial, serialmin, serialmax);
13810 			result = ISC_R_RANGE;
13811 			goto fail;
13812 		}
13813 
13814 		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
13815 				     zone->journal);
13816 		if (result != ISC_R_SUCCESS)
13817 			goto fail;
13818 		if (dump)
13819 			zone_needdump(zone, DNS_DUMP_DELAY);
13820 		else if (zone->journalsize != -1) {
13821 			result = dns_journal_compact(zone->mctx, zone->journal,
13822 						     serial, zone->journalsize);
13823 			switch (result) {
13824 			case ISC_R_SUCCESS:
13825 			case ISC_R_NOSPACE:
13826 			case ISC_R_NOTFOUND:
13827 				dns_zone_log(zone, ISC_LOG_DEBUG(3),
13828 					     "dns_journal_compact: %s",
13829 					     dns_result_totext(result));
13830 				break;
13831 			default:
13832 				dns_zone_log(zone, ISC_LOG_ERROR,
13833 					     "dns_journal_compact failed: %s",
13834 					     dns_result_totext(result));
13835 				break;
13836 			}
13837 		}
13838 		if (zone->type == dns_zone_master && inline_raw(zone))
13839 			zone_send_secureserial(zone, serial);
13840 	} else {
13841 		if (dump && zone->masterfile != NULL) {
13842 			/*
13843 			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
13844 			 * to keep the old masterfile.
13845 			 */
13846 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
13847 			    remove(zone->masterfile) < 0 && errno != ENOENT) {
13848 				char strbuf[ISC_STRERRORSIZE];
13849 				isc__strerror(errno, strbuf, sizeof(strbuf));
13850 				isc_log_write(dns_lctx,
13851 					      DNS_LOGCATEGORY_GENERAL,
13852 					      DNS_LOGMODULE_ZONE,
13853 					      ISC_LOG_WARNING,
13854 					      "unable to remove masterfile "
13855 					      "'%s': '%s'",
13856 					      zone->masterfile, strbuf);
13857 			}
13858 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
13859 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
13860 			else
13861 				zone_needdump(zone, 0);
13862 		}
13863 		if (dump && zone->journal != NULL) {
13864 			/*
13865 			 * The in-memory database just changed, and
13866 			 * because 'dump' is set, it didn't change by
13867 			 * being loaded from disk.  Also, we have not
13868 			 * journaled diffs for this change.
13869 			 * Therefore, the on-disk journal is missing
13870 			 * the deltas for this change.	Since it can
13871 			 * no longer be used to bring the zone
13872 			 * up-to-date, it is useless and should be
13873 			 * removed.
13874 			 */
13875 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13876 				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13877 				      "removing journal file");
13878 			if (remove(zone->journal) < 0 && errno != ENOENT) {
13879 				char strbuf[ISC_STRERRORSIZE];
13880 				isc__strerror(errno, strbuf, sizeof(strbuf));
13881 				isc_log_write(dns_lctx,
13882 					      DNS_LOGCATEGORY_GENERAL,
13883 					      DNS_LOGMODULE_ZONE,
13884 					      ISC_LOG_WARNING,
13885 					      "unable to remove journal "
13886 					      "'%s': '%s'",
13887 					      zone->journal, strbuf);
13888 			}
13889 		}
13890 
13891 		if (inline_raw(zone))
13892 			zone_send_securedb(zone, db);
13893 	}
13894 
13895 	dns_db_closeversion(db, &ver, ISC_FALSE);
13896 
13897 	dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
13898 
13899 	if (zone->db != NULL)
13900 		zone_detachdb(zone);
13901 	zone_attachdb(zone, db);
13902 	dns_db_settask(zone->db, zone->task);
13903 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
13904 	return (ISC_R_SUCCESS);
13905 
13906  fail:
13907 	dns_db_closeversion(db, &ver, ISC_FALSE);
13908 	return (result);
13909 }
13910 
13911 /* The caller must hold the dblock as a writer. */
13912 static inline void
zone_attachdb(dns_zone_t * zone,dns_db_t * db)13913 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
13914 	REQUIRE(zone->db == NULL && db != NULL);
13915 
13916 	dns_db_attach(db, &zone->db);
13917 	if (zone->acache != NULL) {
13918 		isc_result_t result;
13919 		result = dns_acache_setdb(zone->acache, db);
13920 		if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
13921 			UNEXPECTED_ERROR(__FILE__, __LINE__,
13922 					 "dns_acache_setdb() failed: %s",
13923 					 isc_result_totext(result));
13924 		}
13925 	}
13926 }
13927 
13928 /* The caller must hold the dblock as a writer. */
13929 static inline void
zone_detachdb(dns_zone_t * zone)13930 zone_detachdb(dns_zone_t *zone) {
13931 	REQUIRE(zone->db != NULL);
13932 
13933 	if (zone->acache != NULL)
13934 		(void)dns_acache_putdb(zone->acache, zone->db);
13935 	dns_db_detach(&zone->db);
13936 }
13937 
13938 static void
zone_xfrdone(dns_zone_t * zone,isc_result_t result)13939 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
13940 	isc_time_t now;
13941 	isc_boolean_t again = ISC_FALSE;
13942 	unsigned int soacount;
13943 	unsigned int nscount;
13944 	isc_uint32_t serial, refresh, retry, expire, minimum;
13945 	isc_result_t xfrresult = result;
13946 	isc_boolean_t free_needed;
13947 	dns_zone_t *secure = NULL;
13948 
13949 	REQUIRE(DNS_ZONE_VALID(zone));
13950 
13951 	dns_zone_log(zone, ISC_LOG_DEBUG(1),
13952 		     "zone transfer finished: %s", dns_result_totext(result));
13953 
13954 	/*
13955 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
13956 	 * could result in a deadlock due to a LOR so we will spin if we
13957 	 * can't obtain the both locks.
13958 	 */
13959  again:
13960 	LOCK_ZONE(zone);
13961 	if (inline_raw(zone)) {
13962 		secure = zone->secure;
13963 		INSIST(secure != zone);
13964 		TRYLOCK_ZONE(result, secure);
13965 		if (result != ISC_R_SUCCESS) {
13966 			UNLOCK_ZONE(zone);
13967 			secure = NULL;
13968 #if ISC_PLATFORM_USETHREADS
13969 			isc_thread_yield();
13970 #endif
13971 			goto again;
13972 		}
13973 	}
13974 
13975 	INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
13976 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13977 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
13978 
13979 	TIME_NOW(&now);
13980 	switch (result) {
13981 	case ISC_R_SUCCESS:
13982 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13983 		/*FALLTHROUGH*/
13984 	case DNS_R_UPTODATE:
13985 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13986 		/*
13987 		 * Has the zone expired underneath us?
13988 		 */
13989 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13990 		if (zone->db == NULL) {
13991 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13992 			goto same_master;
13993 		}
13994 
13995 		/*
13996 		 * Update the zone structure's data from the actual
13997 		 * SOA received.
13998 		 */
13999 		nscount = 0;
14000 		soacount = 0;
14001 		INSIST(zone->db != NULL);
14002 		result = zone_get_from_db(zone, zone->db, &nscount,
14003 					  &soacount, &serial, &refresh,
14004 					  &retry, &expire, &minimum, NULL);
14005 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14006 		if (result == ISC_R_SUCCESS) {
14007 			if (soacount != 1)
14008 				dns_zone_log(zone, ISC_LOG_ERROR,
14009 					     "transferred zone "
14010 					     "has %d SOA record%s", soacount,
14011 					     (soacount != 0) ? "s" : "");
14012 			if (nscount == 0) {
14013 				dns_zone_log(zone, ISC_LOG_ERROR,
14014 					     "transferred zone "
14015 					     "has no NS records");
14016 				if (DNS_ZONE_FLAG(zone,
14017 						  DNS_ZONEFLG_HAVETIMERS)) {
14018 					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
14019 					zone->retry = DNS_ZONE_DEFAULTRETRY;
14020 				}
14021 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
14022 				zone_unload(zone);
14023 				goto next_master;
14024 			}
14025 			zone->refresh = RANGE(refresh, zone->minrefresh,
14026 					      zone->maxrefresh);
14027 			zone->retry = RANGE(retry, zone->minretry,
14028 					    zone->maxretry);
14029 			zone->expire = RANGE(expire,
14030 					     zone->refresh + zone->retry,
14031 					     DNS_MAX_EXPIRE);
14032 			zone->minimum = minimum;
14033 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
14034 		}
14035 
14036 		/*
14037 		 * Set our next update/expire times.
14038 		 */
14039 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
14040 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
14041 			zone->refreshtime = now;
14042 			DNS_ZONE_TIME_ADD(&now, zone->expire,
14043 					  &zone->expiretime);
14044 		} else {
14045 			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
14046 					    &zone->refreshtime);
14047 			DNS_ZONE_TIME_ADD(&now, zone->expire,
14048 					  &zone->expiretime);
14049 		}
14050 		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
14051 			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
14052 			if (zone->tsigkey != NULL) {
14053 				char namebuf[DNS_NAME_FORMATSIZE];
14054 				dns_name_format(&zone->tsigkey->name, namebuf,
14055 						sizeof(namebuf));
14056 				snprintf(buf, sizeof(buf), ": TSIG '%s'",
14057 					 namebuf);
14058 			} else
14059 				buf[0] = '\0';
14060 			dns_zone_log(zone, ISC_LOG_INFO,
14061 				     "transferred serial %u%s",
14062 				     serial, buf);
14063 			if (inline_raw(zone))
14064 				zone_send_secureserial(zone, serial);
14065 		}
14066 
14067 		/*
14068 		 * This is not necessary if we just performed a AXFR
14069 		 * however it is necessary for an IXFR / UPTODATE and
14070 		 * won't hurt with an AXFR.
14071 		 */
14072 		if (zone->masterfile != NULL || zone->journal != NULL) {
14073 			unsigned int delay = DNS_DUMP_DELAY;
14074 
14075 			result = ISC_R_FAILURE;
14076 			if (zone->journal != NULL)
14077 				result = isc_file_settime(zone->journal, &now);
14078 			if (result != ISC_R_SUCCESS &&
14079 			    zone->masterfile != NULL)
14080 				result = isc_file_settime(zone->masterfile,
14081 							  &now);
14082 
14083 			if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
14084 			    result == ISC_R_FILENOTFOUND)
14085 				delay = 0;
14086 
14087 			if ((result == ISC_R_SUCCESS ||
14088 			    result == ISC_R_FILENOTFOUND) &&
14089 			    zone->masterfile != NULL)
14090 				zone_needdump(zone, delay);
14091 			else if (result != ISC_R_SUCCESS)
14092 				dns_zone_log(zone, ISC_LOG_ERROR,
14093 					     "transfer: could not set file "
14094 					     "modification time of '%s': %s",
14095 					     zone->masterfile,
14096 					     dns_result_totext(result));
14097 		}
14098 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
14099 		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
14100 		break;
14101 
14102 	case DNS_R_BADIXFR:
14103 		/* Force retry with AXFR. */
14104 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
14105 		goto same_master;
14106 
14107 	default:
14108 	next_master:
14109 		/*
14110 		 * Skip to next failed / untried master.
14111 		 */
14112 		do {
14113 			zone->curmaster++;
14114 		} while (zone->curmaster < zone->masterscnt &&
14115 			 zone->mastersok[zone->curmaster]);
14116 		/* FALLTHROUGH */
14117 	same_master:
14118 		if (zone->curmaster >= zone->masterscnt) {
14119 			zone->curmaster = 0;
14120 			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
14121 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14122 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
14123 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14124 				while (zone->curmaster < zone->masterscnt &&
14125 				       zone->mastersok[zone->curmaster])
14126 					zone->curmaster++;
14127 				again = ISC_TRUE;
14128 			} else
14129 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14130 		} else {
14131 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
14132 			again = ISC_TRUE;
14133 		}
14134 		inc_stats(zone, dns_zonestatscounter_xfrfail);
14135 		break;
14136 	}
14137 	zone_settimer(zone, &now);
14138 
14139 	/*
14140 	 * If creating the transfer object failed, zone->xfr is NULL.
14141 	 * Otherwise, we are called as the done callback of a zone
14142 	 * transfer object that just entered its shutting-down
14143 	 * state.  Since we are no longer responsible for shutting
14144 	 * it down, we can detach our reference.
14145 	 */
14146 	if (zone->xfr != NULL)
14147 		dns_xfrin_detach(&zone->xfr);
14148 
14149 	if (zone->tsigkey != NULL)
14150 		dns_tsigkey_detach(&zone->tsigkey);
14151 
14152 	/*
14153 	 * Handle any deferred journal compaction.
14154 	 */
14155 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
14156 		result = dns_journal_compact(zone->mctx, zone->journal,
14157 					     zone->compact_serial,
14158 					     zone->journalsize);
14159 		switch (result) {
14160 		case ISC_R_SUCCESS:
14161 		case ISC_R_NOSPACE:
14162 		case ISC_R_NOTFOUND:
14163 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
14164 				     "dns_journal_compact: %s",
14165 				     dns_result_totext(result));
14166 			break;
14167 		default:
14168 			dns_zone_log(zone, ISC_LOG_ERROR,
14169 				     "dns_journal_compact failed: %s",
14170 				     dns_result_totext(result));
14171 			break;
14172 		}
14173 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
14174 	}
14175 
14176 	if (secure != NULL)
14177 		UNLOCK_ZONE(secure);
14178 	/*
14179 	 * This transfer finishing freed up a transfer quota slot.
14180 	 * Let any other zones waiting for quota have it.
14181 	 */
14182 	if (zone->zmgr != NULL &&
14183 	    zone->statelist == &zone->zmgr->xfrin_in_progress) {
14184 		UNLOCK_ZONE(zone);
14185 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14186 		ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
14187 		zone->statelist = NULL;
14188 		zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
14189 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14190 		LOCK_ZONE(zone);
14191 	}
14192 
14193 	/*
14194 	 * Retry with a different server if necessary.
14195 	 */
14196 	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
14197 		queue_soa_query(zone);
14198 
14199 	INSIST(zone->irefs > 0);
14200 	zone->irefs--;
14201 	free_needed = exit_check(zone);
14202 	UNLOCK_ZONE(zone);
14203 	if (free_needed)
14204 		zone_free(zone);
14205 }
14206 
14207 static void
zone_loaddone(void * arg,isc_result_t result)14208 zone_loaddone(void *arg, isc_result_t result) {
14209 	static char me[] = "zone_loaddone";
14210 	dns_load_t *load = arg;
14211 	dns_zone_t *zone;
14212 	isc_result_t tresult;
14213 	dns_zone_t *secure = NULL;
14214 
14215 	REQUIRE(DNS_LOAD_VALID(load));
14216 	zone = load->zone;
14217 
14218 	ENTER;
14219 
14220 	tresult = dns_db_endload(load->db, &load->callbacks.add_private);
14221 	if (tresult != ISC_R_SUCCESS &&
14222 	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
14223 		result = tresult;
14224 
14225 	/*
14226 	 * Lock hierarchy: zmgr, zone, raw.
14227 	 */
14228  again:
14229 	LOCK_ZONE(zone);
14230 	if (inline_secure(zone))
14231 		LOCK_ZONE(zone->raw);
14232 	else if (inline_raw(zone)) {
14233 		secure = zone->secure;
14234 		TRYLOCK_ZONE(result, secure);
14235 		if (result != ISC_R_SUCCESS) {
14236 			UNLOCK_ZONE(zone);
14237 			secure = NULL;
14238 #if ISC_PLATFORM_USETHREADS
14239 			isc_thread_yield();
14240 #endif
14241 			goto again;
14242 		}
14243 	}
14244 	(void)zone_postload(zone, load->db, load->loadtime, result);
14245 	zonemgr_putio(&zone->readio);
14246 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
14247 	zone_idetach(&load->callbacks.zone);
14248 	/*
14249 	 * Leave the zone frozen if the reload fails.
14250 	 */
14251 	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
14252 	     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
14253 		zone->update_disabled = ISC_FALSE;
14254 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
14255 	if (inline_secure(zone))
14256 		UNLOCK_ZONE(zone->raw);
14257 	else if (secure != NULL)
14258 		UNLOCK_ZONE(secure);
14259 	UNLOCK_ZONE(zone);
14260 
14261 	load->magic = 0;
14262 	dns_db_detach(&load->db);
14263 	if (load->zone->lctx != NULL)
14264 		dns_loadctx_detach(&load->zone->lctx);
14265 	dns_zone_idetach(&load->zone);
14266 	isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
14267 }
14268 
14269 void
dns_zone_getssutable(dns_zone_t * zone,dns_ssutable_t ** table)14270 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
14271 	REQUIRE(DNS_ZONE_VALID(zone));
14272 	REQUIRE(table != NULL);
14273 	REQUIRE(*table == NULL);
14274 
14275 	LOCK_ZONE(zone);
14276 	if (zone->ssutable != NULL)
14277 		dns_ssutable_attach(zone->ssutable, table);
14278 	UNLOCK_ZONE(zone);
14279 }
14280 
14281 void
dns_zone_setssutable(dns_zone_t * zone,dns_ssutable_t * table)14282 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
14283 	REQUIRE(DNS_ZONE_VALID(zone));
14284 
14285 	LOCK_ZONE(zone);
14286 	if (zone->ssutable != NULL)
14287 		dns_ssutable_detach(&zone->ssutable);
14288 	if (table != NULL)
14289 		dns_ssutable_attach(table, &zone->ssutable);
14290 	UNLOCK_ZONE(zone);
14291 }
14292 
14293 void
dns_zone_setsigvalidityinterval(dns_zone_t * zone,isc_uint32_t interval)14294 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
14295 	REQUIRE(DNS_ZONE_VALID(zone));
14296 
14297 	zone->sigvalidityinterval = interval;
14298 }
14299 
14300 isc_uint32_t
dns_zone_getsigvalidityinterval(dns_zone_t * zone)14301 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
14302 	REQUIRE(DNS_ZONE_VALID(zone));
14303 
14304 	return (zone->sigvalidityinterval);
14305 }
14306 
14307 void
dns_zone_setsigresigninginterval(dns_zone_t * zone,isc_uint32_t interval)14308 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
14309 	isc_time_t now;
14310 
14311 	REQUIRE(DNS_ZONE_VALID(zone));
14312 
14313 	LOCK_ZONE(zone);
14314 	zone->sigresigninginterval = interval;
14315 	set_resigntime(zone);
14316 	if (zone->task != NULL) {
14317 		TIME_NOW(&now);
14318 		zone_settimer(zone, &now);
14319 	}
14320 	UNLOCK_ZONE(zone);
14321 }
14322 
14323 isc_uint32_t
dns_zone_getsigresigninginterval(dns_zone_t * zone)14324 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
14325 	REQUIRE(DNS_ZONE_VALID(zone));
14326 
14327 	return (zone->sigresigninginterval);
14328 }
14329 
14330 static void
queue_xfrin(dns_zone_t * zone)14331 queue_xfrin(dns_zone_t *zone) {
14332 	const char me[] = "queue_xfrin";
14333 	isc_result_t result;
14334 	dns_zonemgr_t *zmgr = zone->zmgr;
14335 
14336 	ENTER;
14337 
14338 	INSIST(zone->statelist == NULL);
14339 
14340 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14341 	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
14342 	LOCK_ZONE(zone);
14343 	zone->irefs++;
14344 	UNLOCK_ZONE(zone);
14345 	zone->statelist = &zmgr->waiting_for_xfrin;
14346 	result = zmgr_start_xfrin_ifquota(zmgr, zone);
14347 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14348 
14349 	if (result == ISC_R_QUOTA) {
14350 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14351 			      "zone transfer deferred due to quota");
14352 	} else if (result != ISC_R_SUCCESS) {
14353 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
14354 			      "starting zone transfer: %s",
14355 			      isc_result_totext(result));
14356 	}
14357 }
14358 
14359 /*
14360  * This event callback is called when a zone has received
14361  * any necessary zone transfer quota.  This is the time
14362  * to go ahead and start the transfer.
14363  */
14364 static void
got_transfer_quota(isc_task_t * task,isc_event_t * event)14365 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
14366 	isc_result_t result = ISC_R_SUCCESS;
14367 	dns_peer_t *peer = NULL;
14368 	char master[ISC_SOCKADDR_FORMATSIZE];
14369 	char source[ISC_SOCKADDR_FORMATSIZE];
14370 	dns_rdatatype_t xfrtype;
14371 	dns_zone_t *zone = event->ev_arg;
14372 	isc_netaddr_t masterip;
14373 	isc_sockaddr_t sourceaddr;
14374 	isc_sockaddr_t masteraddr;
14375 	isc_time_t now;
14376 	const char *soa_before = "";
14377 	isc_boolean_t loaded;
14378 
14379 	UNUSED(task);
14380 
14381 	INSIST(task == zone->task);
14382 
14383 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14384 		result = ISC_R_CANCELED;
14385 		goto cleanup;
14386 	}
14387 
14388 	TIME_NOW(&now);
14389 
14390 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
14391 	if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
14392 				    &zone->sourceaddr, &now))
14393 	{
14394 		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14395 		dns_zone_log(zone, ISC_LOG_INFO,
14396 			     "got_transfer_quota: skipping zone transfer as "
14397 			     "master %s (source %s) is unreachable (cached)",
14398 			     master, source);
14399 		result = ISC_R_CANCELED;
14400 		goto cleanup;
14401 	}
14402 
14403 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14404 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
14405 
14406 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14407 		soa_before = "SOA before ";
14408 	/*
14409 	 * Decide whether we should request IXFR or AXFR.
14410 	 */
14411 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14412 	loaded = ISC_TF(zone->db != NULL);
14413 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14414 
14415 	if (!loaded) {
14416 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
14417 			     "no database exists yet, requesting AXFR of "
14418 			     "initial version from %s", master);
14419 		xfrtype = dns_rdatatype_axfr;
14420 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
14421 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
14422 			     "forced reload, requesting AXFR of "
14423 			     "initial version from %s", master);
14424 		xfrtype = dns_rdatatype_axfr;
14425 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
14426 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
14427 			     "retrying with AXFR from %s due to "
14428 			     "previous IXFR failure", master);
14429 		xfrtype = dns_rdatatype_axfr;
14430 		LOCK_ZONE(zone);
14431 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
14432 		UNLOCK_ZONE(zone);
14433 	} else {
14434 		isc_boolean_t use_ixfr = ISC_TRUE;
14435 		if (peer != NULL)
14436 			result = dns_peer_getrequestixfr(peer, &use_ixfr);
14437 		if (peer == NULL || result != ISC_R_SUCCESS)
14438 			use_ixfr = zone->requestixfr;
14439 		if (use_ixfr == ISC_FALSE) {
14440 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14441 				     "IXFR disabled, requesting %sAXFR from %s",
14442 				     soa_before, master);
14443 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14444 				xfrtype = dns_rdatatype_soa;
14445 			else
14446 				xfrtype = dns_rdatatype_axfr;
14447 		} else {
14448 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14449 				     "requesting IXFR from %s", master);
14450 			xfrtype = dns_rdatatype_ixfr;
14451 		}
14452 	}
14453 
14454 	/*
14455 	 * Determine if we should attempt to sign the request with TSIG.
14456 	 */
14457 	result = ISC_R_NOTFOUND;
14458 	/*
14459 	 * First, look for a tsig key in the master statement, then
14460 	 * try for a server key.
14461 	 */
14462 	if ((zone->masterkeynames != NULL) &&
14463 	    (zone->masterkeynames[zone->curmaster] != NULL)) {
14464 		dns_view_t *view = dns_zone_getview(zone);
14465 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14466 		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
14467 	}
14468 	if (zone->tsigkey == NULL)
14469 		result = dns_view_getpeertsig(zone->view, &masterip,
14470 					      &zone->tsigkey);
14471 
14472 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14473 		dns_zone_log(zone, ISC_LOG_ERROR,
14474 			     "could not get TSIG key for zone transfer: %s",
14475 			     isc_result_totext(result));
14476 	}
14477 
14478 	LOCK_ZONE(zone);
14479 	masteraddr = zone->masteraddr;
14480 	sourceaddr = zone->sourceaddr;
14481 	UNLOCK_ZONE(zone);
14482 	INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
14483 	result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
14484 				   zone->tsigkey, zone->mctx,
14485 				   zone->zmgr->timermgr, zone->zmgr->socketmgr,
14486 				   zone->task, zone_xfrdone, &zone->xfr);
14487 	if (result == ISC_R_SUCCESS) {
14488 		LOCK_ZONE(zone);
14489 		if (xfrtype == dns_rdatatype_axfr) {
14490 			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14491 				inc_stats(zone, dns_zonestatscounter_axfrreqv4);
14492 			else
14493 				inc_stats(zone, dns_zonestatscounter_axfrreqv6);
14494 		} else if (xfrtype == dns_rdatatype_ixfr) {
14495 			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14496 				inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
14497 			else
14498 				inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
14499 		}
14500 		UNLOCK_ZONE(zone);
14501 	}
14502  cleanup:
14503 	/*
14504 	 * Any failure in this function is handled like a failed
14505 	 * zone transfer.  This ensures that we get removed from
14506 	 * zmgr->xfrin_in_progress.
14507 	 */
14508 	if (result != ISC_R_SUCCESS)
14509 		zone_xfrdone(zone, result);
14510 
14511 	isc_event_free(&event);
14512 }
14513 
14514 /*
14515  * Update forwarding support.
14516  */
14517 
14518 static void
forward_destroy(dns_forward_t * forward)14519 forward_destroy(dns_forward_t *forward) {
14520 
14521 	forward->magic = 0;
14522 	if (forward->request != NULL)
14523 		dns_request_destroy(&forward->request);
14524 	if (forward->msgbuf != NULL)
14525 		isc_buffer_free(&forward->msgbuf);
14526 	if (forward->zone != NULL) {
14527 		LOCK(&forward->zone->lock);
14528 		if (ISC_LINK_LINKED(forward, link))
14529 			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
14530 		UNLOCK(&forward->zone->lock);
14531 		dns_zone_idetach(&forward->zone);
14532 	}
14533 	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
14534 }
14535 
14536 static isc_result_t
sendtomaster(dns_forward_t * forward)14537 sendtomaster(dns_forward_t *forward) {
14538 	isc_result_t result;
14539 	isc_sockaddr_t src;
14540 
14541 	LOCK_ZONE(forward->zone);
14542 
14543 	if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
14544 		UNLOCK_ZONE(forward->zone);
14545 		return (ISC_R_CANCELED);
14546 	}
14547 
14548 	if (forward->which >= forward->zone->masterscnt) {
14549 		UNLOCK_ZONE(forward->zone);
14550 		return (ISC_R_NOMORE);
14551 	}
14552 
14553 	forward->addr = forward->zone->masters[forward->which];
14554 	/*
14555 	 * Always use TCP regardless of whether the original update
14556 	 * used TCP.
14557 	 * XXX The timeout may but a bit small if we are far down a
14558 	 * transfer graph and the master has to try several masters.
14559 	 */
14560 	switch (isc_sockaddr_pf(&forward->addr)) {
14561 	case PF_INET:
14562 		src = forward->zone->xfrsource4;
14563 		break;
14564 	case PF_INET6:
14565 		src = forward->zone->xfrsource6;
14566 		break;
14567 	default:
14568 		result = ISC_R_NOTIMPLEMENTED;
14569 		goto unlock;
14570 	}
14571 	result = dns_request_createraw(forward->zone->view->requestmgr,
14572 				       forward->msgbuf,
14573 				       &src, &forward->addr,
14574 				       forward->options, 15 /* XXX */,
14575 				       forward->zone->task,
14576 				       forward_callback, forward,
14577 				       &forward->request);
14578 	if (result == ISC_R_SUCCESS) {
14579 		if (!ISC_LINK_LINKED(forward, link))
14580 			ISC_LIST_APPEND(forward->zone->forwards, forward, link);
14581 	}
14582 
14583  unlock:
14584 	UNLOCK_ZONE(forward->zone);
14585 	return (result);
14586 }
14587 
14588 static void
forward_callback(isc_task_t * task,isc_event_t * event)14589 forward_callback(isc_task_t *task, isc_event_t *event) {
14590 	const char me[] = "forward_callback";
14591 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
14592 	dns_message_t *msg = NULL;
14593 	char master[ISC_SOCKADDR_FORMATSIZE];
14594 	isc_result_t result;
14595 	dns_forward_t *forward;
14596 	dns_zone_t *zone;
14597 
14598 	UNUSED(task);
14599 
14600 	forward = revent->ev_arg;
14601 	INSIST(DNS_FORWARD_VALID(forward));
14602 	zone = forward->zone;
14603 	INSIST(DNS_ZONE_VALID(zone));
14604 
14605 	ENTER;
14606 
14607 	isc_sockaddr_format(&forward->addr, master, sizeof(master));
14608 
14609 	if (revent->result != ISC_R_SUCCESS) {
14610 		dns_zone_log(zone, ISC_LOG_INFO,
14611 			     "could not forward dynamic update to %s: %s",
14612 			     master, dns_result_totext(revent->result));
14613 		goto next_master;
14614 	}
14615 
14616 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
14617 	if (result != ISC_R_SUCCESS)
14618 		goto next_master;
14619 
14620 	result = dns_request_getresponse(revent->request, msg,
14621 					 DNS_MESSAGEPARSE_PRESERVEORDER |
14622 					 DNS_MESSAGEPARSE_CLONEBUFFER);
14623 	if (result != ISC_R_SUCCESS)
14624 		goto next_master;
14625 
14626 	switch (msg->rcode) {
14627 	/*
14628 	 * Pass these rcodes back to client.
14629 	 */
14630 	case dns_rcode_noerror:
14631 	case dns_rcode_yxdomain:
14632 	case dns_rcode_yxrrset:
14633 	case dns_rcode_nxrrset:
14634 	case dns_rcode_refused:
14635 	case dns_rcode_nxdomain: {
14636 		char rcode[128];
14637 		isc_buffer_t rb;
14638 
14639 		isc_buffer_init(&rb, rcode, sizeof(rcode));
14640 		(void)dns_rcode_totext(msg->rcode, &rb);
14641 		dns_zone_log(zone, ISC_LOG_INFO,
14642 			     "forwarded dynamic update: "
14643 			     "master %s returned: %.*s",
14644 			     master, (int)rb.used, rcode);
14645 		break;
14646 	}
14647 
14648 	/* These should not occur if the masters/zone are valid. */
14649 	case dns_rcode_notzone:
14650 	case dns_rcode_notauth: {
14651 		char rcode[128];
14652 		isc_buffer_t rb;
14653 
14654 		isc_buffer_init(&rb, rcode, sizeof(rcode));
14655 		(void)dns_rcode_totext(msg->rcode, &rb);
14656 		dns_zone_log(zone, ISC_LOG_WARNING,
14657 			     "forwarding dynamic update: "
14658 			     "unexpected response: master %s returned: %.*s",
14659 			     master, (int)rb.used, rcode);
14660 		goto next_master;
14661 	}
14662 
14663 	/* Try another server for these rcodes. */
14664 	case dns_rcode_formerr:
14665 	case dns_rcode_servfail:
14666 	case dns_rcode_notimp:
14667 	case dns_rcode_badvers:
14668 	default:
14669 		goto next_master;
14670 	}
14671 
14672 	/* call callback */
14673 	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
14674 	msg = NULL;
14675 	dns_request_destroy(&forward->request);
14676 	forward_destroy(forward);
14677 	isc_event_free(&event);
14678 	return;
14679 
14680  next_master:
14681 	if (msg != NULL)
14682 		dns_message_destroy(&msg);
14683 	isc_event_free(&event);
14684 	forward->which++;
14685 	dns_request_destroy(&forward->request);
14686 	result = sendtomaster(forward);
14687 	if (result != ISC_R_SUCCESS) {
14688 		/* call callback */
14689 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
14690 			     "exhausted dynamic update forwarder list");
14691 		(forward->callback)(forward->callback_arg, result, NULL);
14692 		forward_destroy(forward);
14693 	}
14694 }
14695 
14696 isc_result_t
dns_zone_forwardupdate(dns_zone_t * zone,dns_message_t * msg,dns_updatecallback_t callback,void * callback_arg)14697 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
14698 		       dns_updatecallback_t callback, void *callback_arg)
14699 {
14700 	dns_forward_t *forward;
14701 	isc_result_t result;
14702 	isc_region_t *mr;
14703 
14704 	REQUIRE(DNS_ZONE_VALID(zone));
14705 	REQUIRE(msg != NULL);
14706 	REQUIRE(callback != NULL);
14707 
14708 	forward = isc_mem_get(zone->mctx, sizeof(*forward));
14709 	if (forward == NULL)
14710 		return (ISC_R_NOMEMORY);
14711 
14712 	forward->request = NULL;
14713 	forward->zone = NULL;
14714 	forward->msgbuf = NULL;
14715 	forward->which = 0;
14716 	forward->mctx = 0;
14717 	forward->callback = callback;
14718 	forward->callback_arg = callback_arg;
14719 	ISC_LINK_INIT(forward, link);
14720 	forward->magic = FORWARD_MAGIC;
14721 	forward->options = DNS_REQUESTOPT_TCP;
14722 	/*
14723 	 * If we have a SIG(0) signed message we need to preserve the
14724 	 * query id as that is included in the SIG(0) computation.
14725 	 */
14726 	if (msg->sig0 != NULL)
14727 		forward->options |= DNS_REQUESTOPT_FIXEDID;
14728 
14729 	mr = dns_message_getrawmessage(msg);
14730 	if (mr == NULL) {
14731 		result = ISC_R_UNEXPECTEDEND;
14732 		goto cleanup;
14733 	}
14734 
14735 	result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
14736 	if (result != ISC_R_SUCCESS)
14737 		goto cleanup;
14738 	result = isc_buffer_copyregion(forward->msgbuf, mr);
14739 	if (result != ISC_R_SUCCESS)
14740 		goto cleanup;
14741 
14742 	isc_mem_attach(zone->mctx, &forward->mctx);
14743 	dns_zone_iattach(zone, &forward->zone);
14744 	result = sendtomaster(forward);
14745 
14746  cleanup:
14747 	if (result != ISC_R_SUCCESS) {
14748 		forward_destroy(forward);
14749 	}
14750 	return (result);
14751 }
14752 
14753 isc_result_t
dns_zone_next(dns_zone_t * zone,dns_zone_t ** next)14754 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
14755 	REQUIRE(DNS_ZONE_VALID(zone));
14756 	REQUIRE(next != NULL && *next == NULL);
14757 
14758 	*next = ISC_LIST_NEXT(zone, link);
14759 	if (*next == NULL)
14760 		return (ISC_R_NOMORE);
14761 	else
14762 		return (ISC_R_SUCCESS);
14763 }
14764 
14765 isc_result_t
dns_zone_first(dns_zonemgr_t * zmgr,dns_zone_t ** first)14766 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
14767 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14768 	REQUIRE(first != NULL && *first == NULL);
14769 
14770 	*first = ISC_LIST_HEAD(zmgr->zones);
14771 	if (*first == NULL)
14772 		return (ISC_R_NOMORE);
14773 	else
14774 		return (ISC_R_SUCCESS);
14775 }
14776 
14777 /***
14778  ***	Zone manager.
14779  ***/
14780 
14781 isc_result_t
dns_zonemgr_create(isc_mem_t * mctx,isc_taskmgr_t * taskmgr,isc_timermgr_t * timermgr,isc_socketmgr_t * socketmgr,dns_zonemgr_t ** zmgrp)14782 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
14783 		   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
14784 		   dns_zonemgr_t **zmgrp)
14785 {
14786 	dns_zonemgr_t *zmgr;
14787 	isc_result_t result;
14788 
14789 	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
14790 	if (zmgr == NULL)
14791 		return (ISC_R_NOMEMORY);
14792 	zmgr->mctx = NULL;
14793 	zmgr->refs = 1;
14794 	isc_mem_attach(mctx, &zmgr->mctx);
14795 	zmgr->taskmgr = taskmgr;
14796 	zmgr->timermgr = timermgr;
14797 	zmgr->socketmgr = socketmgr;
14798 	zmgr->zonetasks = NULL;
14799 	zmgr->loadtasks = NULL;
14800 	zmgr->mctxpool = NULL;
14801 	zmgr->task = NULL;
14802 	zmgr->notifyrl = NULL;
14803 	zmgr->refreshrl = NULL;
14804 	zmgr->startupnotifyrl = NULL;
14805 	zmgr->startuprefreshrl = NULL;
14806 	ISC_LIST_INIT(zmgr->zones);
14807 	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
14808 	ISC_LIST_INIT(zmgr->xfrin_in_progress);
14809 	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
14810 	result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
14811 	if (result != ISC_R_SUCCESS)
14812 		goto free_mem;
14813 
14814 	zmgr->transfersin = 10;
14815 	zmgr->transfersperns = 2;
14816 
14817 	/* Unreachable lock. */
14818 	result = isc_rwlock_init(&zmgr->urlock, 0, 0);
14819 	if (result != ISC_R_SUCCESS)
14820 		goto free_rwlock;
14821 
14822 	/* Create a single task for queueing of SOA queries. */
14823 	result = isc_task_create(taskmgr, 1, &zmgr->task);
14824 	if (result != ISC_R_SUCCESS)
14825 		goto free_urlock;
14826 
14827 	isc_task_setname(zmgr->task, "zmgr", zmgr);
14828 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14829 					&zmgr->notifyrl);
14830 	if (result != ISC_R_SUCCESS)
14831 		goto free_task;
14832 
14833 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14834 					&zmgr->refreshrl);
14835 	if (result != ISC_R_SUCCESS)
14836 		goto free_notifyrl;
14837 
14838 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14839 					&zmgr->startupnotifyrl);
14840 	if (result != ISC_R_SUCCESS)
14841 		goto free_refreshrl;
14842 
14843 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14844 					&zmgr->startuprefreshrl);
14845 	if (result != ISC_R_SUCCESS)
14846 		goto free_startupnotifyrl;
14847 
14848 	/* default to 20 refresh queries / notifies per second. */
14849 	setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
14850 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
14851 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
14852 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
14853 
14854 	zmgr->iolimit = 1;
14855 	zmgr->ioactive = 0;
14856 	ISC_LIST_INIT(zmgr->high);
14857 	ISC_LIST_INIT(zmgr->low);
14858 
14859 	result = isc_mutex_init(&zmgr->iolock);
14860 	if (result != ISC_R_SUCCESS)
14861 		goto free_startuprefreshrl;
14862 
14863 	zmgr->magic = ZONEMGR_MAGIC;
14864 
14865 	*zmgrp = zmgr;
14866 	return (ISC_R_SUCCESS);
14867 
14868 #if 0
14869  free_iolock:
14870 	DESTROYLOCK(&zmgr->iolock);
14871 #endif
14872  free_startuprefreshrl:
14873 	isc_ratelimiter_detach(&zmgr->startuprefreshrl);
14874  free_startupnotifyrl:
14875 	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
14876  free_refreshrl:
14877 	isc_ratelimiter_detach(&zmgr->refreshrl);
14878  free_notifyrl:
14879 	isc_ratelimiter_detach(&zmgr->notifyrl);
14880  free_task:
14881 	isc_task_detach(&zmgr->task);
14882  free_urlock:
14883 	isc_rwlock_destroy(&zmgr->urlock);
14884  free_rwlock:
14885 	isc_rwlock_destroy(&zmgr->rwlock);
14886  free_mem:
14887 	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14888 	isc_mem_detach(&mctx);
14889 	return (result);
14890 }
14891 
14892 isc_result_t
dns_zonemgr_createzone(dns_zonemgr_t * zmgr,dns_zone_t ** zonep)14893 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
14894 	isc_result_t result;
14895 	isc_mem_t *mctx = NULL;
14896 	dns_zone_t *zone = NULL;
14897 	void *item;
14898 
14899 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14900 	REQUIRE(zonep != NULL && *zonep == NULL);
14901 
14902 	if (zmgr->mctxpool == NULL)
14903 		return (ISC_R_FAILURE);
14904 
14905 	item = isc_pool_get(zmgr->mctxpool);
14906 	if (item == NULL)
14907 		return (ISC_R_FAILURE);
14908 
14909 	isc_mem_attach((isc_mem_t *) item, &mctx);
14910 	result = dns_zone_create(&zone, mctx);
14911 	isc_mem_detach(&mctx);
14912 
14913 	if (result == ISC_R_SUCCESS)
14914 		*zonep = zone;
14915 
14916 	return (result);
14917 }
14918 
14919 isc_result_t
dns_zonemgr_managezone(dns_zonemgr_t * zmgr,dns_zone_t * zone)14920 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14921 	isc_result_t result;
14922 
14923 	REQUIRE(DNS_ZONE_VALID(zone));
14924 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14925 
14926 	if (zmgr->zonetasks == NULL)
14927 		return (ISC_R_FAILURE);
14928 
14929 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14930 	LOCK_ZONE(zone);
14931 	REQUIRE(zone->task == NULL);
14932 	REQUIRE(zone->timer == NULL);
14933 	REQUIRE(zone->zmgr == NULL);
14934 
14935 	isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
14936 	isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
14937 
14938 	/*
14939 	 * Set the task name.  The tag will arbitrarily point to one
14940 	 * of the zones sharing the task (in practice, the one
14941 	 * to be managed last).
14942 	 */
14943 	isc_task_setname(zone->task, "zone", zone);
14944 	isc_task_setname(zone->loadtask, "loadzone", zone);
14945 
14946 	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
14947 				  NULL, NULL,
14948 				  zone->task, zone_timer, zone,
14949 				  &zone->timer);
14950 
14951 	if (result != ISC_R_SUCCESS)
14952 		goto cleanup_tasks;
14953 
14954 	/*
14955 	 * The timer "holds" a iref.
14956 	 */
14957 	zone->irefs++;
14958 	INSIST(zone->irefs != 0);
14959 
14960 	ISC_LIST_APPEND(zmgr->zones, zone, link);
14961 	zone->zmgr = zmgr;
14962 	zmgr->refs++;
14963 
14964 	goto unlock;
14965 
14966  cleanup_tasks:
14967 	isc_task_detach(&zone->loadtask);
14968 	isc_task_detach(&zone->task);
14969 
14970  unlock:
14971 	UNLOCK_ZONE(zone);
14972 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14973 	return (result);
14974 }
14975 
14976 void
dns_zonemgr_releasezone(dns_zonemgr_t * zmgr,dns_zone_t * zone)14977 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14978 	isc_boolean_t free_now = ISC_FALSE;
14979 
14980 	REQUIRE(DNS_ZONE_VALID(zone));
14981 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14982 	REQUIRE(zone->zmgr == zmgr);
14983 
14984 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14985 	LOCK_ZONE(zone);
14986 
14987 	ISC_LIST_UNLINK(zmgr->zones, zone, link);
14988 	zone->zmgr = NULL;
14989 	zmgr->refs--;
14990 	if (zmgr->refs == 0)
14991 		free_now = ISC_TRUE;
14992 
14993 	UNLOCK_ZONE(zone);
14994 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14995 
14996 	if (free_now)
14997 		zonemgr_free(zmgr);
14998 	ENSURE(zone->zmgr == NULL);
14999 }
15000 
15001 void
dns_zonemgr_attach(dns_zonemgr_t * source,dns_zonemgr_t ** target)15002 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
15003 	REQUIRE(DNS_ZONEMGR_VALID(source));
15004 	REQUIRE(target != NULL && *target == NULL);
15005 
15006 	RWLOCK(&source->rwlock, isc_rwlocktype_write);
15007 	REQUIRE(source->refs > 0);
15008 	source->refs++;
15009 	INSIST(source->refs > 0);
15010 	RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
15011 	*target = source;
15012 }
15013 
15014 void
dns_zonemgr_detach(dns_zonemgr_t ** zmgrp)15015 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
15016 	dns_zonemgr_t *zmgr;
15017 	isc_boolean_t free_now = ISC_FALSE;
15018 
15019 	REQUIRE(zmgrp != NULL);
15020 	zmgr = *zmgrp;
15021 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15022 
15023 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15024 	zmgr->refs--;
15025 	if (zmgr->refs == 0)
15026 		free_now = ISC_TRUE;
15027 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15028 
15029 	if (free_now)
15030 		zonemgr_free(zmgr);
15031 	*zmgrp = NULL;
15032 }
15033 
15034 isc_result_t
dns_zonemgr_forcemaint(dns_zonemgr_t * zmgr)15035 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
15036 	dns_zone_t *p;
15037 
15038 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15039 
15040 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15041 	for (p = ISC_LIST_HEAD(zmgr->zones);
15042 	     p != NULL;
15043 	     p = ISC_LIST_NEXT(p, link))
15044 	{
15045 		dns_zone_maintenance(p);
15046 	}
15047 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15048 
15049 	/*
15050 	 * Recent configuration changes may have increased the
15051 	 * amount of available transfers quota.  Make sure any
15052 	 * transfers currently blocked on quota get started if
15053 	 * possible.
15054 	 */
15055 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15056 	zmgr_resume_xfrs(zmgr, ISC_TRUE);
15057 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15058 	return (ISC_R_SUCCESS);
15059 }
15060 
15061 void
dns_zonemgr_resumexfrs(dns_zonemgr_t * zmgr)15062 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
15063 
15064 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15065 
15066 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15067 	zmgr_resume_xfrs(zmgr, ISC_TRUE);
15068 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15069 }
15070 
15071 void
dns_zonemgr_shutdown(dns_zonemgr_t * zmgr)15072 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
15073 	dns_zone_t *zone;
15074 
15075 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15076 
15077 	isc_ratelimiter_shutdown(zmgr->notifyrl);
15078 	isc_ratelimiter_shutdown(zmgr->refreshrl);
15079 	isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
15080 	isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
15081 
15082 	if (zmgr->task != NULL)
15083 		isc_task_destroy(&zmgr->task);
15084 	if (zmgr->zonetasks != NULL)
15085 		isc_taskpool_destroy(&zmgr->zonetasks);
15086 	if (zmgr->loadtasks != NULL)
15087 		isc_taskpool_destroy(&zmgr->loadtasks);
15088 	if (zmgr->mctxpool != NULL)
15089 		isc_pool_destroy(&zmgr->mctxpool);
15090 
15091 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15092 	for (zone = ISC_LIST_HEAD(zmgr->zones);
15093 	     zone != NULL;
15094 	     zone = ISC_LIST_NEXT(zone, link))
15095 	{
15096 		LOCK_ZONE(zone);
15097 		forward_cancel(zone);
15098 		UNLOCK_ZONE(zone);
15099 	}
15100 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15101 }
15102 
15103 static isc_result_t
mctxinit(void ** target,void * arg)15104 mctxinit(void **target, void *arg) {
15105 	isc_result_t result;
15106 	isc_mem_t *mctx = NULL;
15107 
15108 	UNUSED(arg);
15109 
15110 	REQUIRE(target != NULL && *target == NULL);
15111 
15112 	result = isc_mem_create(0, 0, &mctx);
15113 	if (result != ISC_R_SUCCESS)
15114 		return (result);
15115 	isc_mem_setname(mctx, "zonemgr-pool", NULL);
15116 
15117 	*target = mctx;
15118 	return (ISC_R_SUCCESS);
15119 }
15120 
15121 static void
mctxfree(void ** target)15122 mctxfree(void **target) {
15123 	isc_mem_t *mctx = *(isc_mem_t **) target;
15124 	isc_mem_detach(&mctx);
15125 	*target = NULL;
15126 }
15127 
15128 #define ZONES_PER_TASK 100
15129 #define ZONES_PER_MCTX 1000
15130 
15131 isc_result_t
dns_zonemgr_setsize(dns_zonemgr_t * zmgr,int num_zones)15132 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
15133 	isc_result_t result;
15134 	int ntasks = num_zones / ZONES_PER_TASK;
15135 	int nmctx = num_zones / ZONES_PER_MCTX;
15136 	isc_taskpool_t *pool = NULL;
15137 	isc_pool_t *mctxpool = NULL;
15138 
15139 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15140 
15141 	/*
15142 	 * For anything fewer than 1000 zones we use 10 tasks in
15143 	 * the task pools.  More than that, and we'll scale at one
15144 	 * task per 100 zones.  Similarly, for anything smaller than
15145 	 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
15146 	 */
15147 	if (ntasks < 10)
15148 		ntasks = 10;
15149 	if (nmctx < 2)
15150 		nmctx = 2;
15151 
15152 	/* Create or resize the zone task pools. */
15153 	if (zmgr->zonetasks == NULL)
15154 		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
15155 					     ntasks, 2, &pool);
15156 	else
15157 		result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
15158 
15159 	if (result == ISC_R_SUCCESS)
15160 		zmgr->zonetasks = pool;
15161 
15162 	pool = NULL;
15163 	if (zmgr->loadtasks == NULL)
15164 		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
15165 					     ntasks, 2, &pool);
15166 	else
15167 		result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
15168 
15169 	if (result == ISC_R_SUCCESS)
15170 		zmgr->loadtasks = pool;
15171 
15172 #ifdef BIND9
15173 	/*
15174 	 * We always set all tasks in the zone-load task pool to
15175 	 * privileged.  This prevents other tasks in the system from
15176 	 * running while the server task manager is in privileged
15177 	 * mode.
15178 	 *
15179 	 * NOTE: If we start using task privileges for any other
15180 	 * part of the system than zone tasks, then this will need to be
15181 	 * revisted.  In that case we'd want to turn on privileges for
15182 	 * zone tasks only when we were loading, and turn them off the
15183 	 * rest of the time.  For now, however, it's okay to just
15184 	 * set it and forget it.
15185 	 */
15186 	isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
15187 #endif
15188 
15189 	/* Create or resize the zone memory context pool. */
15190 	if (zmgr->mctxpool == NULL)
15191 		result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
15192 					 mctxinit, NULL, &mctxpool);
15193 	else
15194 		result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
15195 
15196 	if (result == ISC_R_SUCCESS)
15197 		zmgr->mctxpool = mctxpool;
15198 
15199 	return (result);
15200 }
15201 
15202 static void
zonemgr_free(dns_zonemgr_t * zmgr)15203 zonemgr_free(dns_zonemgr_t *zmgr) {
15204 	isc_mem_t *mctx;
15205 
15206 	INSIST(zmgr->refs == 0);
15207 	INSIST(ISC_LIST_EMPTY(zmgr->zones));
15208 
15209 	zmgr->magic = 0;
15210 
15211 	DESTROYLOCK(&zmgr->iolock);
15212 	isc_ratelimiter_detach(&zmgr->notifyrl);
15213 	isc_ratelimiter_detach(&zmgr->refreshrl);
15214 	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
15215 	isc_ratelimiter_detach(&zmgr->startuprefreshrl);
15216 
15217 	isc_rwlock_destroy(&zmgr->urlock);
15218 	isc_rwlock_destroy(&zmgr->rwlock);
15219 	mctx = zmgr->mctx;
15220 	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
15221 	isc_mem_detach(&mctx);
15222 }
15223 
15224 void
dns_zonemgr_settransfersin(dns_zonemgr_t * zmgr,isc_uint32_t value)15225 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
15226 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15227 
15228 	zmgr->transfersin = value;
15229 }
15230 
15231 isc_uint32_t
dns_zonemgr_getttransfersin(dns_zonemgr_t * zmgr)15232 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
15233 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15234 
15235 	return (zmgr->transfersin);
15236 }
15237 
15238 void
dns_zonemgr_settransfersperns(dns_zonemgr_t * zmgr,isc_uint32_t value)15239 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
15240 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15241 
15242 	zmgr->transfersperns = value;
15243 }
15244 
15245 isc_uint32_t
dns_zonemgr_getttransfersperns(dns_zonemgr_t * zmgr)15246 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
15247 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15248 
15249 	return (zmgr->transfersperns);
15250 }
15251 
15252 /*
15253  * Try to start a new incoming zone transfer to fill a quota
15254  * slot that was just vacated.
15255  *
15256  * Requires:
15257  *	The zone manager is locked by the caller.
15258  */
15259 static void
zmgr_resume_xfrs(dns_zonemgr_t * zmgr,isc_boolean_t multi)15260 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
15261 	dns_zone_t *zone;
15262 	dns_zone_t *next;
15263 
15264 	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
15265 	     zone != NULL;
15266 	     zone = next)
15267 	{
15268 		isc_result_t result;
15269 		next = ISC_LIST_NEXT(zone, statelink);
15270 		result = zmgr_start_xfrin_ifquota(zmgr, zone);
15271 		if (result == ISC_R_SUCCESS) {
15272 			if (multi)
15273 				continue;
15274 			/*
15275 			 * We successfully filled the slot.  We're done.
15276 			 */
15277 			break;
15278 		} else if (result == ISC_R_QUOTA) {
15279 			/*
15280 			 * Not enough quota.  This is probably the per-server
15281 			 * quota, because we usually get called when a unit of
15282 			 * global quota has just been freed.  Try the next
15283 			 * zone, it may succeed if it uses another master.
15284 			 */
15285 			continue;
15286 		} else {
15287 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
15288 				     "starting zone transfer: %s",
15289 				     isc_result_totext(result));
15290 			break;
15291 		}
15292 	}
15293 }
15294 
15295 /*
15296  * Try to start an incoming zone transfer for 'zone', quota permitting.
15297  *
15298  * Requires:
15299  *	The zone manager is locked by the caller.
15300  *
15301  * Returns:
15302  *	ISC_R_SUCCESS	There was enough quota and we attempted to
15303  *			start a transfer.  zone_xfrdone() has been or will
15304  *			be called.
15305  *	ISC_R_QUOTA	Not enough quota.
15306  *	Others		Failure.
15307  */
15308 static isc_result_t
zmgr_start_xfrin_ifquota(dns_zonemgr_t * zmgr,dns_zone_t * zone)15309 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15310 	dns_peer_t *peer = NULL;
15311 	isc_netaddr_t masterip;
15312 	isc_uint32_t nxfrsin, nxfrsperns;
15313 	dns_zone_t *x;
15314 	isc_uint32_t maxtransfersin, maxtransfersperns;
15315 	isc_event_t *e;
15316 
15317 	/*
15318 	 * If we are exiting just pretend we got quota so the zone will
15319 	 * be cleaned up in the zone's task context.
15320 	 */
15321 	LOCK_ZONE(zone);
15322 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15323 		UNLOCK_ZONE(zone);
15324 		goto gotquota;
15325 	}
15326 
15327 	/*
15328 	 * Find any configured information about the server we'd
15329 	 * like to transfer this zone from.
15330 	 */
15331 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
15332 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
15333 	UNLOCK_ZONE(zone);
15334 
15335 	/*
15336 	 * Determine the total maximum number of simultaneous
15337 	 * transfers allowed, and the maximum for this specific
15338 	 * master.
15339 	 */
15340 	maxtransfersin = zmgr->transfersin;
15341 	maxtransfersperns = zmgr->transfersperns;
15342 	if (peer != NULL)
15343 		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
15344 
15345 	/*
15346 	 * Count the total number of transfers that are in progress,
15347 	 * and the number of transfers in progress from this master.
15348 	 * We linearly scan a list of all transfers; if this turns
15349 	 * out to be too slow, we could hash on the master address.
15350 	 */
15351 	nxfrsin = nxfrsperns = 0;
15352 	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15353 	     x != NULL;
15354 	     x = ISC_LIST_NEXT(x, statelink))
15355 	{
15356 		isc_netaddr_t xip;
15357 
15358 		LOCK_ZONE(x);
15359 		isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
15360 		UNLOCK_ZONE(x);
15361 
15362 		nxfrsin++;
15363 		if (isc_netaddr_equal(&xip, &masterip))
15364 			nxfrsperns++;
15365 	}
15366 
15367 	/* Enforce quota. */
15368 	if (nxfrsin >= maxtransfersin)
15369 		return (ISC_R_QUOTA);
15370 
15371 	if (nxfrsperns >= maxtransfersperns)
15372 		return (ISC_R_QUOTA);
15373 
15374  gotquota:
15375 	/*
15376 	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
15377 	 * list and send it an event to let it start the actual transfer in the
15378 	 * context of its own task.
15379 	 */
15380 	e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
15381 			       got_transfer_quota, zone, sizeof(isc_event_t));
15382 	if (e == NULL)
15383 		return (ISC_R_NOMEMORY);
15384 
15385 	LOCK_ZONE(zone);
15386 	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
15387 	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
15388 	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
15389 	zone->statelist = &zmgr->xfrin_in_progress;
15390 	isc_task_send(zone->task, &e);
15391 	dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
15392 	UNLOCK_ZONE(zone);
15393 
15394 	return (ISC_R_SUCCESS);
15395 }
15396 
15397 void
dns_zonemgr_setiolimit(dns_zonemgr_t * zmgr,isc_uint32_t iolimit)15398 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
15399 
15400 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15401 	REQUIRE(iolimit > 0);
15402 
15403 	zmgr->iolimit = iolimit;
15404 }
15405 
15406 isc_uint32_t
dns_zonemgr_getiolimit(dns_zonemgr_t * zmgr)15407 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
15408 
15409 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15410 
15411 	return (zmgr->iolimit);
15412 }
15413 
15414 /*
15415  * Get permission to request a file handle from the OS.
15416  * An event will be sent to action when one is available.
15417  * There are two queues available (high and low), the high
15418  * queue will be serviced before the low one.
15419  *
15420  * zonemgr_putio() must be called after the event is delivered to
15421  * 'action'.
15422  */
15423 
15424 static isc_result_t
zonemgr_getio(dns_zonemgr_t * zmgr,isc_boolean_t high,isc_task_t * task,isc_taskaction_t action,void * arg,dns_io_t ** iop)15425 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
15426 	      isc_task_t *task, isc_taskaction_t action, void *arg,
15427 	      dns_io_t **iop)
15428 {
15429 	dns_io_t *io;
15430 	isc_boolean_t queue;
15431 
15432 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15433 	REQUIRE(iop != NULL && *iop == NULL);
15434 
15435 	io = isc_mem_get(zmgr->mctx, sizeof(*io));
15436 	if (io == NULL)
15437 		return (ISC_R_NOMEMORY);
15438 
15439 	io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
15440 				       action, arg, sizeof(*io->event));
15441 	if (io->event == NULL) {
15442 		isc_mem_put(zmgr->mctx, io, sizeof(*io));
15443 		return (ISC_R_NOMEMORY);
15444 	}
15445 
15446 	io->zmgr = zmgr;
15447 	io->high = high;
15448 	io->task = NULL;
15449 	isc_task_attach(task, &io->task);
15450 	ISC_LINK_INIT(io, link);
15451 	io->magic = IO_MAGIC;
15452 
15453 	LOCK(&zmgr->iolock);
15454 	zmgr->ioactive++;
15455 	queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
15456 	if (queue) {
15457 		if (io->high)
15458 			ISC_LIST_APPEND(zmgr->high, io, link);
15459 		else
15460 			ISC_LIST_APPEND(zmgr->low, io, link);
15461 	}
15462 	UNLOCK(&zmgr->iolock);
15463 	*iop = io;
15464 
15465 	if (!queue)
15466 		isc_task_send(io->task, &io->event);
15467 	return (ISC_R_SUCCESS);
15468 }
15469 
15470 static void
zonemgr_putio(dns_io_t ** iop)15471 zonemgr_putio(dns_io_t **iop) {
15472 	dns_io_t *io;
15473 	dns_io_t *next;
15474 	dns_zonemgr_t *zmgr;
15475 
15476 	REQUIRE(iop != NULL);
15477 	io = *iop;
15478 	REQUIRE(DNS_IO_VALID(io));
15479 
15480 	*iop = NULL;
15481 
15482 	INSIST(!ISC_LINK_LINKED(io, link));
15483 	INSIST(io->event == NULL);
15484 
15485 	zmgr = io->zmgr;
15486 	isc_task_detach(&io->task);
15487 	io->magic = 0;
15488 	isc_mem_put(zmgr->mctx, io, sizeof(*io));
15489 
15490 	LOCK(&zmgr->iolock);
15491 	INSIST(zmgr->ioactive > 0);
15492 	zmgr->ioactive--;
15493 	next = HEAD(zmgr->high);
15494 	if (next == NULL)
15495 		next = HEAD(zmgr->low);
15496 	if (next != NULL) {
15497 		if (next->high)
15498 			ISC_LIST_UNLINK(zmgr->high, next, link);
15499 		else
15500 			ISC_LIST_UNLINK(zmgr->low, next, link);
15501 		INSIST(next->event != NULL);
15502 	}
15503 	UNLOCK(&zmgr->iolock);
15504 	if (next != NULL)
15505 		isc_task_send(next->task, &next->event);
15506 }
15507 
15508 static void
zonemgr_cancelio(dns_io_t * io)15509 zonemgr_cancelio(dns_io_t *io) {
15510 	isc_boolean_t send_event = ISC_FALSE;
15511 
15512 	REQUIRE(DNS_IO_VALID(io));
15513 
15514 	/*
15515 	 * If we are queued to be run then dequeue.
15516 	 */
15517 	LOCK(&io->zmgr->iolock);
15518 	if (ISC_LINK_LINKED(io, link)) {
15519 		if (io->high)
15520 			ISC_LIST_UNLINK(io->zmgr->high, io, link);
15521 		else
15522 			ISC_LIST_UNLINK(io->zmgr->low, io, link);
15523 
15524 		send_event = ISC_TRUE;
15525 		INSIST(io->event != NULL);
15526 	}
15527 	UNLOCK(&io->zmgr->iolock);
15528 	if (send_event) {
15529 		io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
15530 		isc_task_send(io->task, &io->event);
15531 	}
15532 }
15533 
15534 static void
zone_saveunique(dns_zone_t * zone,const char * path,const char * templat)15535 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
15536 	char *buf;
15537 	int buflen;
15538 	isc_result_t result;
15539 
15540 	buflen = strlen(path) + strlen(templat) + 2;
15541 
15542 	buf = isc_mem_get(zone->mctx, buflen);
15543 	if (buf == NULL)
15544 		return;
15545 
15546 	result = isc_file_template(path, templat, buf, buflen);
15547 	if (result != ISC_R_SUCCESS)
15548 		goto cleanup;
15549 
15550 	result = isc_file_renameunique(path, buf);
15551 	if (result != ISC_R_SUCCESS)
15552 		goto cleanup;
15553 
15554 	dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
15555 		     "renaming file to '%s' for failure analysis and "
15556 		     "retransferring.", path, buf);
15557 
15558  cleanup:
15559 	isc_mem_put(zone->mctx, buf, buflen);
15560 }
15561 
15562 #if 0
15563 /* Hook for ondestroy notification from a database. */
15564 
15565 static void
15566 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
15567 	dns_db_t *db = event->sender;
15568 	UNUSED(task);
15569 
15570 	isc_event_free(&event);
15571 
15572 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15573 		      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15574 		      "database (%p) destroyed", (void*) db);
15575 }
15576 #endif
15577 
15578 static void
setrl(isc_ratelimiter_t * rl,unsigned int * rate,unsigned int value)15579 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
15580 	isc_interval_t interval;
15581 	isc_uint32_t s, ns;
15582 	isc_uint32_t pertic;
15583 	isc_result_t result;
15584 
15585 	if (value == 0)
15586 		value = 1;
15587 
15588 	if (value == 1) {
15589 		s = 1;
15590 		ns = 0;
15591 		pertic = 1;
15592 	} else if (value <= 10) {
15593 		s = 0;
15594 		ns = 1000000000 / value;
15595 		pertic = 1;
15596 	} else {
15597 		s = 0;
15598 		ns = (1000000000 / value) * 10;
15599 		pertic = 10;
15600 	}
15601 
15602 	isc_interval_set(&interval, s, ns);
15603 
15604 	result = isc_ratelimiter_setinterval(rl, &interval);
15605 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
15606 	isc_ratelimiter_setpertic(rl, pertic);
15607 
15608 	*rate = value;
15609 }
15610 
15611 void
dns_zonemgr_setserialqueryrate(dns_zonemgr_t * zmgr,unsigned int value)15612 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
15613 
15614 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15615 
15616 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
15617 
15618 	/* Seperately controlled in BIND 9.11.x */
15619 	setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
15620 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
15621 
15622 	/* XXXMPA seperate out once we have the code to support this. */
15623 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
15624 }
15625 
15626 unsigned int
dns_zonemgr_getserialqueryrate(dns_zonemgr_t * zmgr)15627 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
15628 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15629 
15630 	return (zmgr->serialqueryrate);
15631 }
15632 
15633 isc_boolean_t
dns_zonemgr_unreachable(dns_zonemgr_t * zmgr,isc_sockaddr_t * remote,isc_sockaddr_t * local,isc_time_t * now)15634 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15635 			isc_sockaddr_t *local, isc_time_t *now)
15636 {
15637 	unsigned int i;
15638 	isc_rwlocktype_t locktype;
15639 	isc_result_t result;
15640 	isc_uint32_t seconds = isc_time_seconds(now);
15641 	isc_uint32_t count = 0;
15642 
15643 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15644 
15645 	locktype = isc_rwlocktype_read;
15646 	RWLOCK(&zmgr->urlock, locktype);
15647 	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15648 		if (zmgr->unreachable[i].expire >= seconds &&
15649 		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15650 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
15651 			result = isc_rwlock_tryupgrade(&zmgr->urlock);
15652 			if (result == ISC_R_SUCCESS) {
15653 				locktype = isc_rwlocktype_write;
15654 				zmgr->unreachable[i].last = seconds;
15655 				count = zmgr->unreachable[i].count;
15656 			}
15657 			break;
15658 		}
15659 	}
15660 	RWUNLOCK(&zmgr->urlock, locktype);
15661 	return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
15662 }
15663 
15664 void
dns_zonemgr_unreachabledel(dns_zonemgr_t * zmgr,isc_sockaddr_t * remote,isc_sockaddr_t * local)15665 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15666 			   isc_sockaddr_t *local)
15667 {
15668 	unsigned int i;
15669 	isc_rwlocktype_t locktype;
15670 	isc_result_t result;
15671 
15672 	char master[ISC_SOCKADDR_FORMATSIZE];
15673 	char source[ISC_SOCKADDR_FORMATSIZE];
15674 
15675 	isc_sockaddr_format(remote, master, sizeof(master));
15676 	isc_sockaddr_format(local, source, sizeof(source));
15677 
15678 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15679 
15680 	locktype = isc_rwlocktype_read;
15681 	RWLOCK(&zmgr->urlock, locktype);
15682 	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15683 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15684 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
15685 			if (zmgr->unreachable[i].expire == 0)
15686 				break;
15687 			result = isc_rwlock_tryupgrade(&zmgr->urlock);
15688 			if (result == ISC_R_SUCCESS) {
15689 				locktype = isc_rwlocktype_write;
15690 				zmgr->unreachable[i].expire = 0;
15691 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15692 					      DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
15693 					      "master %s (source %s) deleted "
15694 					      "from unreachable cache",
15695 					      master, source);
15696 			}
15697 			break;
15698 		}
15699 	}
15700 	RWUNLOCK(&zmgr->urlock, locktype);
15701 }
15702 
15703 void
dns_zonemgr_unreachableadd(dns_zonemgr_t * zmgr,isc_sockaddr_t * remote,isc_sockaddr_t * local,isc_time_t * now)15704 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15705 			   isc_sockaddr_t *local, isc_time_t *now)
15706 {
15707 	isc_uint32_t seconds = isc_time_seconds(now);
15708 	isc_uint32_t last = seconds;
15709 	unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
15710 
15711 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15712 
15713 	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
15714 	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15715 		/* Existing entry? */
15716 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15717 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
15718 			break;
15719 		/* Empty slot? */
15720 		if (zmgr->unreachable[i].expire < seconds)
15721 			slot = i;
15722 		/* Least recently used slot? */
15723 		if (zmgr->unreachable[i].last < last) {
15724 			last = zmgr->unreachable[i].last;
15725 			oldest = i;
15726 		}
15727 	}
15728 	if (i < UNREACH_CHACHE_SIZE) {
15729 		/*
15730 		 * Found a existing entry.  Update the expire timer and
15731 		 * last usage timestamps.
15732 		 */
15733 		zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
15734 		zmgr->unreachable[i].last = seconds;
15735 		if (zmgr->unreachable[i].expire < seconds)
15736 			zmgr->unreachable[i].count = 1;
15737 		else
15738 			zmgr->unreachable[i].count++;
15739 	} else if (slot != UNREACH_CHACHE_SIZE) {
15740 		/*
15741 		 * Found a empty slot. Add a new entry to the cache.
15742 		 */
15743 		zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
15744 		zmgr->unreachable[slot].last = seconds;
15745 		zmgr->unreachable[slot].remote = *remote;
15746 		zmgr->unreachable[slot].local = *local;
15747 		zmgr->unreachable[slot].count = 1;
15748 	} else {
15749 		/*
15750 		 * Replace the least recently used entry in the cache.
15751 		 */
15752 		zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
15753 		zmgr->unreachable[oldest].last = seconds;
15754 		zmgr->unreachable[oldest].remote = *remote;
15755 		zmgr->unreachable[oldest].local = *local;
15756 		zmgr->unreachable[oldest].count = 1;
15757 	}
15758 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
15759 }
15760 
15761 void
dns_zone_forcereload(dns_zone_t * zone)15762 dns_zone_forcereload(dns_zone_t *zone) {
15763 	REQUIRE(DNS_ZONE_VALID(zone));
15764 
15765 	if (zone->type == dns_zone_master ||
15766 	    (zone->type == dns_zone_redirect && zone->masters == NULL))
15767 		return;
15768 
15769 	LOCK_ZONE(zone);
15770 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
15771 	UNLOCK_ZONE(zone);
15772 	dns_zone_refresh(zone);
15773 }
15774 
15775 isc_boolean_t
dns_zone_isforced(dns_zone_t * zone)15776 dns_zone_isforced(dns_zone_t *zone) {
15777 	REQUIRE(DNS_ZONE_VALID(zone));
15778 
15779 	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
15780 }
15781 
15782 isc_result_t
dns_zone_setstatistics(dns_zone_t * zone,isc_boolean_t on)15783 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
15784 	/*
15785 	 * This function is obsoleted.
15786 	 */
15787 	UNUSED(zone);
15788 	UNUSED(on);
15789 	return (ISC_R_NOTIMPLEMENTED);
15790 }
15791 
15792 isc_uint64_t *
dns_zone_getstatscounters(dns_zone_t * zone)15793 dns_zone_getstatscounters(dns_zone_t *zone) {
15794 	/*
15795 	 * This function is obsoleted.
15796 	 */
15797 	UNUSED(zone);
15798 	return (NULL);
15799 }
15800 
15801 void
dns_zone_setstats(dns_zone_t * zone,isc_stats_t * stats)15802 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
15803 	REQUIRE(DNS_ZONE_VALID(zone));
15804 	REQUIRE(zone->stats == NULL);
15805 
15806 	LOCK_ZONE(zone);
15807 	zone->stats = NULL;
15808 	isc_stats_attach(stats, &zone->stats);
15809 	UNLOCK_ZONE(zone);
15810 }
15811 
15812 void
dns_zone_setrequeststats(dns_zone_t * zone,isc_stats_t * stats)15813 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
15814 
15815 	REQUIRE(DNS_ZONE_VALID(zone));
15816 
15817 	LOCK_ZONE(zone);
15818 	if (zone->requeststats_on && stats == NULL)
15819 		zone->requeststats_on = ISC_FALSE;
15820 	else if (!zone->requeststats_on && stats != NULL) {
15821 		if (zone->requeststats == NULL) {
15822 			isc_stats_attach(stats, &zone->requeststats);
15823 			zone->requeststats_on = ISC_TRUE;
15824 		}
15825 	}
15826 	UNLOCK_ZONE(zone);
15827 }
15828 
15829 #ifdef NEWSTATS
15830 void
dns_zone_setrcvquerystats(dns_zone_t * zone,dns_stats_t * stats)15831 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
15832 
15833 	REQUIRE(DNS_ZONE_VALID(zone));
15834 
15835 	LOCK_ZONE(zone);
15836 	if (zone->requeststats_on && stats != NULL) {
15837 		if (zone->rcvquerystats == NULL) {
15838 			dns_stats_attach(stats, &zone->rcvquerystats);
15839 			zone->requeststats_on = ISC_TRUE;
15840 		}
15841 	}
15842 	UNLOCK_ZONE(zone);
15843 }
15844 #endif
15845 
15846 isc_stats_t *
dns_zone_getrequeststats(dns_zone_t * zone)15847 dns_zone_getrequeststats(dns_zone_t *zone) {
15848 	/*
15849 	 * We don't lock zone for efficiency reason.  This is not catastrophic
15850 	 * because requeststats must always be valid when requeststats_on is
15851 	 * true.
15852 	 * Some counters may be incremented while requeststats_on is becoming
15853 	 * false, or some cannot be incremented just after the statistics are
15854 	 * installed, but it shouldn't matter much in practice.
15855 	 */
15856 	if (zone->requeststats_on)
15857 		return (zone->requeststats);
15858 	else
15859 		return (NULL);
15860 }
15861 
15862 #ifdef NEWSTATS
15863 /*
15864  * Return the received query stats bucket
15865  * see note from dns_zone_getrequeststats()
15866  */
15867 dns_stats_t *
dns_zone_getrcvquerystats(dns_zone_t * zone)15868 dns_zone_getrcvquerystats(dns_zone_t *zone) {
15869 	if (zone->requeststats_on)
15870 		return (zone->rcvquerystats);
15871 	else
15872 		return (NULL);
15873 }
15874 #endif
15875 
15876 void
dns_zone_dialup(dns_zone_t * zone)15877 dns_zone_dialup(dns_zone_t *zone) {
15878 
15879 	REQUIRE(DNS_ZONE_VALID(zone));
15880 
15881 	zone_debuglog(zone, "dns_zone_dialup", 3,
15882 		      "notify = %d, refresh = %d",
15883 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
15884 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
15885 
15886 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
15887 		dns_zone_notify(zone);
15888 	if (zone->type != dns_zone_master && zone->masters != NULL &&
15889 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
15890 		dns_zone_refresh(zone);
15891 }
15892 
15893 void
dns_zone_setdialup(dns_zone_t * zone,dns_dialuptype_t dialup)15894 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
15895 	REQUIRE(DNS_ZONE_VALID(zone));
15896 
15897 	LOCK_ZONE(zone);
15898 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
15899 			 DNS_ZONEFLG_DIALREFRESH |
15900 			 DNS_ZONEFLG_NOREFRESH);
15901 	switch (dialup) {
15902 	case dns_dialuptype_no:
15903 		break;
15904 	case dns_dialuptype_yes:
15905 		DNS_ZONE_SETFLAG(zone,	(DNS_ZONEFLG_DIALNOTIFY |
15906 				 DNS_ZONEFLG_DIALREFRESH |
15907 				 DNS_ZONEFLG_NOREFRESH));
15908 		break;
15909 	case dns_dialuptype_notify:
15910 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15911 		break;
15912 	case dns_dialuptype_notifypassive:
15913 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15914 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15915 		break;
15916 	case dns_dialuptype_refresh:
15917 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
15918 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15919 		break;
15920 	case dns_dialuptype_passive:
15921 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15922 		break;
15923 	default:
15924 		INSIST(0);
15925 	}
15926 	UNLOCK_ZONE(zone);
15927 }
15928 
15929 isc_result_t
dns_zone_setkeydirectory(dns_zone_t * zone,const char * directory)15930 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
15931 	isc_result_t result = ISC_R_SUCCESS;
15932 
15933 	REQUIRE(DNS_ZONE_VALID(zone));
15934 
15935 	LOCK_ZONE(zone);
15936 	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
15937 	UNLOCK_ZONE(zone);
15938 
15939 	return (result);
15940 }
15941 
15942 const char *
dns_zone_getkeydirectory(dns_zone_t * zone)15943 dns_zone_getkeydirectory(dns_zone_t *zone) {
15944 	REQUIRE(DNS_ZONE_VALID(zone));
15945 
15946 	return (zone->keydirectory);
15947 }
15948 
15949 unsigned int
dns_zonemgr_getcount(dns_zonemgr_t * zmgr,int state)15950 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
15951 	dns_zone_t *zone;
15952 	unsigned int count = 0;
15953 
15954 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15955 
15956 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15957 	switch (state) {
15958 	case DNS_ZONESTATE_XFERRUNNING:
15959 		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15960 		     zone != NULL;
15961 		     zone = ISC_LIST_NEXT(zone, statelink))
15962 			count++;
15963 		break;
15964 	case DNS_ZONESTATE_XFERDEFERRED:
15965 		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
15966 		     zone != NULL;
15967 		     zone = ISC_LIST_NEXT(zone, statelink))
15968 			count++;
15969 		break;
15970 	case DNS_ZONESTATE_SOAQUERY:
15971 		for (zone = ISC_LIST_HEAD(zmgr->zones);
15972 		     zone != NULL;
15973 		     zone = ISC_LIST_NEXT(zone, link))
15974 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
15975 				count++;
15976 		break;
15977 	case DNS_ZONESTATE_ANY:
15978 		for (zone = ISC_LIST_HEAD(zmgr->zones);
15979 		     zone != NULL;
15980 		     zone = ISC_LIST_NEXT(zone, link)) {
15981 			dns_view_t *view = zone->view;
15982 			if (view != NULL && strcmp(view->name, "_bind") == 0)
15983 				continue;
15984 			count++;
15985 		}
15986 		break;
15987 	default:
15988 		INSIST(0);
15989 	}
15990 
15991 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15992 
15993 	return (count);
15994 }
15995 
15996 isc_result_t
dns_zone_checknames(dns_zone_t * zone,dns_name_t * name,dns_rdata_t * rdata)15997 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
15998 	isc_boolean_t ok = ISC_TRUE;
15999 	isc_boolean_t fail = ISC_FALSE;
16000 	char namebuf[DNS_NAME_FORMATSIZE];
16001 	char namebuf2[DNS_NAME_FORMATSIZE];
16002 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
16003 	int level = ISC_LOG_WARNING;
16004 	dns_name_t bad;
16005 
16006 	REQUIRE(DNS_ZONE_VALID(zone));
16007 
16008 	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
16009 	    rdata->type != dns_rdatatype_nsec3)
16010 		return (ISC_R_SUCCESS);
16011 
16012 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
16013 	    rdata->type == dns_rdatatype_nsec3) {
16014 		level = ISC_LOG_ERROR;
16015 		fail = ISC_TRUE;
16016 	}
16017 
16018 	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
16019 	if (!ok) {
16020 		dns_name_format(name, namebuf, sizeof(namebuf));
16021 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
16022 		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
16023 			     dns_result_totext(DNS_R_BADOWNERNAME));
16024 		if (fail)
16025 			return (DNS_R_BADOWNERNAME);
16026 	}
16027 
16028 	dns_name_init(&bad, NULL);
16029 	ok = dns_rdata_checknames(rdata, name, &bad);
16030 	if (!ok) {
16031 		dns_name_format(name, namebuf, sizeof(namebuf));
16032 		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
16033 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
16034 		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
16035 			     namebuf2, dns_result_totext(DNS_R_BADNAME));
16036 		if (fail)
16037 			return (DNS_R_BADNAME);
16038 	}
16039 
16040 	return (ISC_R_SUCCESS);
16041 }
16042 
16043 void
dns_zone_setcheckmx(dns_zone_t * zone,dns_checkmxfunc_t checkmx)16044 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
16045 	REQUIRE(DNS_ZONE_VALID(zone));
16046 	zone->checkmx = checkmx;
16047 }
16048 
16049 void
dns_zone_setchecksrv(dns_zone_t * zone,dns_checksrvfunc_t checksrv)16050 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
16051 	REQUIRE(DNS_ZONE_VALID(zone));
16052 	zone->checksrv = checksrv;
16053 }
16054 
16055 void
dns_zone_setcheckns(dns_zone_t * zone,dns_checknsfunc_t checkns)16056 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
16057 	REQUIRE(DNS_ZONE_VALID(zone));
16058 	zone->checkns = checkns;
16059 }
16060 
16061 void
dns_zone_setisself(dns_zone_t * zone,dns_isselffunc_t isself,void * arg)16062 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
16063 	REQUIRE(DNS_ZONE_VALID(zone));
16064 
16065 	LOCK_ZONE(zone);
16066 	zone->isself = isself;
16067 	zone->isselfarg = arg;
16068 	UNLOCK_ZONE(zone);
16069 }
16070 
16071 void
dns_zone_setnotifydelay(dns_zone_t * zone,isc_uint32_t delay)16072 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
16073 	REQUIRE(DNS_ZONE_VALID(zone));
16074 
16075 	LOCK_ZONE(zone);
16076 	zone->notifydelay = delay;
16077 	UNLOCK_ZONE(zone);
16078 }
16079 
16080 isc_uint32_t
dns_zone_getnotifydelay(dns_zone_t * zone)16081 dns_zone_getnotifydelay(dns_zone_t *zone) {
16082 	REQUIRE(DNS_ZONE_VALID(zone));
16083 
16084 	return (zone->notifydelay);
16085 }
16086 
16087 isc_result_t
dns_zone_signwithkey(dns_zone_t * zone,dns_secalg_t algorithm,isc_uint16_t keyid,isc_boolean_t delete)16088 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
16089 		     isc_uint16_t keyid, isc_boolean_t delete)
16090 {
16091 	isc_result_t result;
16092 	REQUIRE(DNS_ZONE_VALID(zone));
16093 
16094 	dns_zone_log(zone, ISC_LOG_NOTICE,
16095 		     "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
16096 		     algorithm, keyid);
16097 	LOCK_ZONE(zone);
16098 	result = zone_signwithkey(zone, algorithm, keyid, delete);
16099 	UNLOCK_ZONE(zone);
16100 
16101 	return (result);
16102 }
16103 
16104 static const char *hex = "0123456789ABCDEF";
16105 
16106 isc_result_t
dns_zone_addnsec3chain(dns_zone_t * zone,dns_rdata_nsec3param_t * nsec3param)16107 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
16108 	isc_result_t result;
16109 	char salt[255*2+1];
16110 	unsigned int i, j;
16111 
16112 	REQUIRE(DNS_ZONE_VALID(zone));
16113 
16114 	if (nsec3param->salt_length != 0) {
16115 		INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
16116 		for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
16117 			salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
16118 			salt[j++] = hex[nsec3param->salt[i] & 0xf];
16119 		}
16120 		salt[j] = '\0';
16121 	} else
16122 		strcpy(salt, "-");
16123 	dns_zone_log(zone, ISC_LOG_NOTICE,
16124 		     "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
16125 		     nsec3param->hash, nsec3param->iterations,
16126 		     salt);
16127 	LOCK_ZONE(zone);
16128 	result = zone_addnsec3chain(zone, nsec3param);
16129 	UNLOCK_ZONE(zone);
16130 
16131 	return (result);
16132 }
16133 
16134 void
dns_zone_setnodes(dns_zone_t * zone,isc_uint32_t nodes)16135 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
16136 	REQUIRE(DNS_ZONE_VALID(zone));
16137 
16138 	if (nodes == 0)
16139 		nodes = 1;
16140 	zone->nodes = nodes;
16141 }
16142 
16143 void
dns_zone_setsignatures(dns_zone_t * zone,isc_uint32_t signatures)16144 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
16145 	REQUIRE(DNS_ZONE_VALID(zone));
16146 
16147 	/*
16148 	 * We treat signatures as a signed value so explicitly
16149 	 * limit its range here.
16150 	 */
16151 	if (signatures > ISC_INT32_MAX)
16152 		signatures = ISC_INT32_MAX;
16153 	else if (signatures == 0)
16154 		signatures = 1;
16155 	zone->signatures = signatures;
16156 }
16157 
16158 isc_uint32_t
dns_zone_getsignatures(dns_zone_t * zone)16159 dns_zone_getsignatures(dns_zone_t *zone) {
16160 	REQUIRE(DNS_ZONE_VALID(zone));
16161 	return (zone->signatures);
16162 }
16163 
16164 void
dns_zone_setprivatetype(dns_zone_t * zone,dns_rdatatype_t type)16165 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
16166 	REQUIRE(DNS_ZONE_VALID(zone));
16167 	zone->privatetype = type;
16168 }
16169 
16170 dns_rdatatype_t
dns_zone_getprivatetype(dns_zone_t * zone)16171 dns_zone_getprivatetype(dns_zone_t *zone) {
16172 	REQUIRE(DNS_ZONE_VALID(zone));
16173 	return (zone->privatetype);
16174 }
16175 
16176 static isc_result_t
zone_signwithkey(dns_zone_t * zone,dns_secalg_t algorithm,isc_uint16_t keyid,isc_boolean_t delete)16177 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
16178 		 isc_boolean_t delete)
16179 {
16180 	dns_signing_t *signing;
16181 	dns_signing_t *current;
16182 	isc_result_t result = ISC_R_SUCCESS;
16183 	isc_time_t now;
16184 	dns_db_t *db = NULL;
16185 
16186 	signing = isc_mem_get(zone->mctx, sizeof *signing);
16187 	if (signing == NULL)
16188 		return (ISC_R_NOMEMORY);
16189 
16190 	signing->magic = 0;
16191 	signing->db  = NULL;
16192 	signing->dbiterator = NULL;
16193 	signing->algorithm = algorithm;
16194 	signing->keyid = keyid;
16195 	signing->delete = delete;
16196 	signing->done = ISC_FALSE;
16197 
16198 	TIME_NOW(&now);
16199 
16200 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16201 	if (zone->db != NULL)
16202 		dns_db_attach(zone->db, &db);
16203 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16204 
16205 	if (db == NULL) {
16206 		result = ISC_R_NOTFOUND;
16207 		goto cleanup;
16208 	}
16209 
16210 	dns_db_attach(db, &signing->db);
16211 
16212 	for (current = ISC_LIST_HEAD(zone->signing);
16213 	     current != NULL;
16214 	     current = ISC_LIST_NEXT(current, link)) {
16215 		if (current->db == signing->db &&
16216 		    current->algorithm == signing->algorithm &&
16217 		    current->keyid == signing->keyid) {
16218 			if (current->delete != signing->delete)
16219 				current->done = ISC_TRUE;
16220 			else
16221 				goto cleanup;
16222 		}
16223 	}
16224 
16225 	result = dns_db_createiterator(signing->db, 0,
16226 				       &signing->dbiterator);
16227 
16228 	if (result == ISC_R_SUCCESS)
16229 		result = dns_dbiterator_first(signing->dbiterator);
16230 	if (result == ISC_R_SUCCESS) {
16231 		dns_dbiterator_pause(signing->dbiterator);
16232 		ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
16233 		signing = NULL;
16234 		if (isc_time_isepoch(&zone->signingtime)) {
16235 			zone->signingtime = now;
16236 			if (zone->task != NULL)
16237 				zone_settimer(zone, &now);
16238 		}
16239 	}
16240 
16241  cleanup:
16242 	if (signing != NULL) {
16243 		if (signing->db != NULL)
16244 			dns_db_detach(&signing->db);
16245 		if (signing->dbiterator != NULL)
16246 			dns_dbiterator_destroy(&signing->dbiterator);
16247 		isc_mem_put(zone->mctx, signing, sizeof *signing);
16248 	}
16249 	if (db != NULL)
16250 		dns_db_detach(&db);
16251 	return (result);
16252 }
16253 
16254 static void
logmsg(const char * format,...)16255 logmsg(const char *format, ...) {
16256 	va_list args;
16257 	va_start(args, format);
16258 	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
16259 		       ISC_LOG_DEBUG(1), format, args);
16260 	va_end(args);
16261 }
16262 
16263 static void
clear_keylist(dns_dnsseckeylist_t * list,isc_mem_t * mctx)16264 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
16265 	dns_dnsseckey_t *key;
16266 	while (!ISC_LIST_EMPTY(*list)) {
16267 		key = ISC_LIST_HEAD(*list);
16268 		ISC_LIST_UNLINK(*list, key, link);
16269 		dns_dnsseckey_destroy(mctx, &key);
16270 	}
16271 }
16272 
16273 /* Called once; *timep should be set to the current time. */
16274 static isc_result_t
next_keyevent(dst_key_t * key,isc_stdtime_t * timep)16275 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
16276 	isc_result_t result;
16277 	isc_stdtime_t now, then = 0, event;
16278 	int i;
16279 
16280 	now = *timep;
16281 
16282 	for (i = 0; i <= DST_MAX_TIMES; i++) {
16283 		result = dst_key_gettime(key, i, &event);
16284 		if (result == ISC_R_SUCCESS && event > now &&
16285 		    (then == 0 || event < then))
16286 			then = event;
16287 	}
16288 
16289 	if (then != 0) {
16290 		*timep = then;
16291 		return (ISC_R_SUCCESS);
16292 	}
16293 
16294 	return (ISC_R_NOTFOUND);
16295 }
16296 
16297 static isc_result_t
rr_exists(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,const dns_rdata_t * rdata,isc_boolean_t * flag)16298 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
16299 	  const dns_rdata_t *rdata, isc_boolean_t *flag)
16300 {
16301 	dns_rdataset_t rdataset;
16302 	dns_dbnode_t *node = NULL;
16303 	isc_result_t result;
16304 
16305 	dns_rdataset_init(&rdataset);
16306 	if (rdata->type == dns_rdatatype_nsec3)
16307 		CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
16308 	else
16309 		CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
16310 	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
16311 				     (isc_stdtime_t) 0, &rdataset, NULL);
16312 	if (result == ISC_R_NOTFOUND) {
16313 		*flag = ISC_FALSE;
16314 		result = ISC_R_SUCCESS;
16315 		goto failure;
16316 	}
16317 
16318 	for (result = dns_rdataset_first(&rdataset);
16319 	     result == ISC_R_SUCCESS;
16320 	     result = dns_rdataset_next(&rdataset)) {
16321 		dns_rdata_t myrdata = DNS_RDATA_INIT;
16322 		dns_rdataset_current(&rdataset, &myrdata);
16323 		if (!dns_rdata_compare(&myrdata, rdata))
16324 			break;
16325 	}
16326 	dns_rdataset_disassociate(&rdataset);
16327 	if (result == ISC_R_SUCCESS) {
16328 		*flag = ISC_TRUE;
16329 	} else if (result == ISC_R_NOMORE) {
16330 		*flag = ISC_FALSE;
16331 		result = ISC_R_SUCCESS;
16332 	}
16333 
16334  failure:
16335 	if (node != NULL)
16336 		dns_db_detachnode(db, &node);
16337 	return (result);
16338 }
16339 
16340 /*
16341  * Add records to signal the state of signing or of key removal.
16342  */
16343 static isc_result_t
add_signing_records(dns_db_t * db,dns_rdatatype_t privatetype,dns_dbversion_t * ver,dns_diff_t * diff,isc_boolean_t sign_all)16344 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
16345 		    dns_dbversion_t *ver, dns_diff_t *diff,
16346 		    isc_boolean_t sign_all)
16347 {
16348 	dns_difftuple_t *tuple, *newtuple = NULL;
16349 	dns_rdata_dnskey_t dnskey;
16350 	dns_rdata_t rdata = DNS_RDATA_INIT;
16351 	isc_boolean_t flag;
16352 	isc_region_t r;
16353 	isc_result_t result = ISC_R_SUCCESS;
16354 	isc_uint16_t keyid;
16355 	unsigned char buf[5];
16356 	dns_name_t *name = dns_db_origin(db);
16357 
16358 	for (tuple = ISC_LIST_HEAD(diff->tuples);
16359 	     tuple != NULL;
16360 	     tuple = ISC_LIST_NEXT(tuple, link)) {
16361 		if (tuple->rdata.type != dns_rdatatype_dnskey)
16362 			continue;
16363 
16364 		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
16365 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
16366 		if ((dnskey.flags &
16367 		     (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
16368 			 != DNS_KEYOWNER_ZONE)
16369 			continue;
16370 
16371 		dns_rdata_toregion(&tuple->rdata, &r);
16372 
16373 		keyid = dst_region_computeid(&r, dnskey.algorithm);
16374 
16375 		buf[0] = dnskey.algorithm;
16376 		buf[1] = (keyid & 0xff00) >> 8;
16377 		buf[2] = (keyid & 0xff);
16378 		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
16379 		buf[4] = 0;
16380 		rdata.data = buf;
16381 		rdata.length = sizeof(buf);
16382 		rdata.type = privatetype;
16383 		rdata.rdclass = tuple->rdata.rdclass;
16384 
16385 		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
16386 			CHECK(rr_exists(db, ver, name, &rdata, &flag));
16387 			if (flag)
16388 				continue;
16389 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
16390 						   name, 0, &rdata, &newtuple));
16391 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
16392 			INSIST(newtuple == NULL);
16393 		}
16394 
16395 		/*
16396 		 * Remove any record which says this operation has already
16397 		 * completed.
16398 		 */
16399 		buf[4] = 1;
16400 		CHECK(rr_exists(db, ver, name, &rdata, &flag));
16401 		if (flag) {
16402 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
16403 						   name, 0, &rdata, &newtuple));
16404 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
16405 			INSIST(newtuple == NULL);
16406 		}
16407 	}
16408  failure:
16409 	return (result);
16410 }
16411 
16412 static isc_result_t
sign_apex(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff,zonediff_t * zonediff)16413 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16414 	  dns_diff_t *diff, zonediff_t *zonediff)
16415 {
16416 	isc_result_t result;
16417 	isc_stdtime_t now, inception, soaexpire;
16418 	isc_boolean_t check_ksk, keyset_kskonly;
16419 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
16420 	unsigned int nkeys = 0, i;
16421 	dns_difftuple_t *tuple;
16422 
16423 	result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
16424 				zone_keys, &nkeys);
16425 	if (result != ISC_R_SUCCESS) {
16426 		dns_zone_log(zone, ISC_LOG_ERROR,
16427 			     "sign_apex:find_zone_keys -> %s",
16428 			     dns_result_totext(result));
16429 		return (result);
16430 	}
16431 
16432 	isc_stdtime_get(&now);
16433 	inception = now - 3600;	/* Allow for clock skew. */
16434 	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
16435 
16436 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16437 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
16438 
16439 	/*
16440 	 * See if update_sigs will update DNSKEY signature and if not
16441 	 * cause them to sign so that so that newly activated keys
16442 	 * are used.
16443 	 */
16444 	for (tuple = ISC_LIST_HEAD(diff->tuples);
16445 	     tuple != NULL;
16446 	     tuple = ISC_LIST_NEXT(tuple, link)) {
16447 		if (tuple->rdata.type == dns_rdatatype_dnskey &&
16448 		    dns_name_equal(&tuple->name, &zone->origin))
16449 			break;
16450 	}
16451 
16452 	if (tuple == NULL) {
16453 		result = del_sigs(zone, db, ver, &zone->origin,
16454 				  dns_rdatatype_dnskey, zonediff,
16455 				  zone_keys, nkeys, now, ISC_FALSE);
16456 		if (result != ISC_R_SUCCESS) {
16457 			dns_zone_log(zone, ISC_LOG_ERROR,
16458 				     "sign_apex:del_sigs -> %s",
16459 				     dns_result_totext(result));
16460 			goto failure;
16461 		}
16462 		result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
16463 				  zonediff->diff, zone_keys, nkeys, zone->mctx,
16464 				  inception, soaexpire, check_ksk,
16465 				  keyset_kskonly);
16466 		if (result != ISC_R_SUCCESS) {
16467 			dns_zone_log(zone, ISC_LOG_ERROR,
16468 				     "sign_apex:add_sigs -> %s",
16469 				     dns_result_totext(result));
16470 			goto failure;
16471 		}
16472 	}
16473 
16474 	result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
16475 			     inception, soaexpire, now, check_ksk,
16476 			     keyset_kskonly, zonediff);
16477 
16478 	if (result != ISC_R_SUCCESS) {
16479 		dns_zone_log(zone, ISC_LOG_ERROR,
16480 			     "sign_apex:update_sigs -> %s",
16481 			     dns_result_totext(result));
16482 		goto failure;
16483 	}
16484 
16485  failure:
16486 	for (i = 0; i < nkeys; i++)
16487 		dst_key_free(&zone_keys[i]);
16488 	return (result);
16489 }
16490 
16491 /*
16492  * Prevent the zone entering a inconsistent state where
16493  * NSEC only DNSKEYs are present with NSEC3 chains.
16494  * See update.c:check_dnssec()
16495  */
16496 static isc_boolean_t
dnskey_sane(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff)16497 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16498 	    dns_diff_t *diff)
16499 {
16500 	isc_result_t result;
16501 	dns_difftuple_t *tuple;
16502 	isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
16503 	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
16504 
16505 	/* Scan the tuples for an NSEC-only DNSKEY */
16506 	for (tuple = ISC_LIST_HEAD(diff->tuples);
16507 	     tuple != NULL;
16508 	     tuple = ISC_LIST_NEXT(tuple, link)) {
16509 		isc_uint8_t alg;
16510 		if (tuple->rdata.type != dns_rdatatype_dnskey ||
16511 		    tuple->op != DNS_DIFFOP_ADD)
16512 			continue;
16513 
16514 		alg = tuple->rdata.data[3];
16515 		if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
16516 		    alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
16517 			nseconly = ISC_TRUE;
16518 			break;
16519 		}
16520 	}
16521 
16522 	/* Check existing DB for NSEC-only DNSKEY */
16523 	if (!nseconly) {
16524 		result = dns_nsec_nseconly(db, ver, &nseconly);
16525 		if (result == ISC_R_NOTFOUND)
16526 			result = ISC_R_SUCCESS;
16527 		CHECK(result);
16528 	}
16529 
16530 	/* Check existing DB for NSEC3 */
16531 	if (!nsec3)
16532 		CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
16533 					privatetype, &nsec3));
16534 
16535 	/* Refuse to allow NSEC3 with NSEC-only keys */
16536 	if (nseconly && nsec3) {
16537 		dns_zone_log(zone, ISC_LOG_ERROR,
16538 			   "NSEC only DNSKEYs and NSEC3 chains not allowed");
16539 		goto failure;
16540 	}
16541 
16542 	return (ISC_TRUE);
16543 
16544  failure:
16545 	return (ISC_FALSE);
16546 }
16547 
16548 static isc_result_t
clean_nsec3param(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff)16549 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16550 		 dns_diff_t *diff)
16551 {
16552 	isc_result_t result;
16553 	dns_dbnode_t *node = NULL;
16554 	dns_rdataset_t rdataset;
16555 
16556 	dns_rdataset_init(&rdataset);
16557 	CHECK(dns_db_getoriginnode(db, &node));
16558 
16559 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16560 				     dns_rdatatype_none, 0, &rdataset, NULL);
16561 	if (dns_rdataset_isassociated(&rdataset))
16562 		dns_rdataset_disassociate(&rdataset);
16563 	if (result != ISC_R_NOTFOUND)
16564 		goto failure;
16565 
16566 	result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
16567 
16568  failure:
16569 	if (node != NULL)
16570 		dns_db_detachnode(db, &node);
16571 	return (result);
16572 }
16573 
16574 /*
16575  * Given an RRSIG rdataset and an algorithm, determine whether there
16576  * are any signatures using that algorithm.
16577  */
16578 static isc_boolean_t
signed_with_alg(dns_rdataset_t * rdataset,dns_secalg_t alg)16579 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
16580 	dns_rdata_t rdata = DNS_RDATA_INIT;
16581 	dns_rdata_rrsig_t rrsig;
16582 	isc_result_t result;
16583 
16584 	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
16585 	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
16586 		return (ISC_FALSE);
16587 	}
16588 
16589 	for (result = dns_rdataset_first(rdataset);
16590 	     result == ISC_R_SUCCESS;
16591 	     result = dns_rdataset_next(rdataset))
16592 	{
16593 		dns_rdataset_current(rdataset, &rdata);
16594 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
16595 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
16596 		dns_rdata_reset(&rdata);
16597 		if (rrsig.algorithm == alg)
16598 			return (ISC_TRUE);
16599 	}
16600 
16601 	return (ISC_FALSE);
16602 }
16603 
16604 static isc_result_t
add_chains(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff)16605 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16606 	   dns_diff_t *diff)
16607 {
16608 	dns_name_t *origin;
16609 	isc_boolean_t build_nsec3;
16610 	isc_result_t result;
16611 
16612 	origin = dns_db_origin(db);
16613 	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
16614 				 &build_nsec3));
16615 	if (build_nsec3)
16616 		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
16617 					   ISC_FALSE, zone->privatetype, diff));
16618 	CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
16619 
16620  failure:
16621 	return (result);
16622 }
16623 
16624 static void
zone_rekey(dns_zone_t * zone)16625 zone_rekey(dns_zone_t *zone) {
16626 	isc_result_t result;
16627 	dns_db_t *db = NULL;
16628 	dns_dbnode_t *node = NULL;
16629 	dns_dbversion_t *ver = NULL;
16630 	dns_rdataset_t soaset, soasigs, keyset, keysigs;
16631 	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
16632 	dns_dnsseckey_t *key;
16633 	dns_diff_t diff, _sig_diff;
16634 	zonediff_t zonediff;
16635 	isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
16636 	isc_boolean_t newalg = ISC_FALSE;
16637 	isc_boolean_t fullsign;
16638 	dns_ttl_t ttl = 3600;
16639 	const char *dir;
16640 	isc_mem_t *mctx;
16641 	isc_stdtime_t now;
16642 	isc_time_t timenow;
16643 	isc_interval_t ival;
16644 	char timebuf[80];
16645 
16646 	REQUIRE(DNS_ZONE_VALID(zone));
16647 
16648 	ISC_LIST_INIT(dnskeys);
16649 	ISC_LIST_INIT(keys);
16650 	ISC_LIST_INIT(rmkeys);
16651 	dns_rdataset_init(&soaset);
16652 	dns_rdataset_init(&soasigs);
16653 	dns_rdataset_init(&keyset);
16654 	dns_rdataset_init(&keysigs);
16655 	dir = dns_zone_getkeydirectory(zone);
16656 	mctx = zone->mctx;
16657 	dns_diff_init(mctx, &diff);
16658 	dns_diff_init(mctx, &_sig_diff);
16659 	zonediff_init(&zonediff, &_sig_diff);
16660 
16661 	CHECK(dns_zone_getdb(zone, &db));
16662 	CHECK(dns_db_newversion(db, &ver));
16663 	CHECK(dns_db_getoriginnode(db, &node));
16664 
16665 	TIME_NOW(&timenow);
16666 	now = isc_time_seconds(&timenow);
16667 
16668 	dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
16669 
16670 	/* Get the SOA record's TTL */
16671 	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
16672 				  dns_rdatatype_none, 0, &soaset, &soasigs));
16673 	ttl = soaset.ttl;
16674 	dns_rdataset_disassociate(&soaset);
16675 
16676 	/* Get the DNSKEY rdataset */
16677 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16678 				     dns_rdatatype_none, 0, &keyset, &keysigs);
16679 	if (result == ISC_R_SUCCESS) {
16680 		ttl = keyset.ttl;
16681 		CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
16682 						     mctx, &keyset,
16683 						     &keysigs, &soasigs,
16684 						     ISC_FALSE, ISC_FALSE,
16685 						     &dnskeys));
16686 	} else if (result != ISC_R_NOTFOUND)
16687 		goto failure;
16688 
16689 	/*
16690 	 * True when called from "rndc sign".  Indicates the zone should be
16691 	 * fully signed now.
16692 	 */
16693 	fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
16694 
16695 	result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
16696 	if (result == ISC_R_SUCCESS) {
16697 		isc_boolean_t check_ksk;
16698 		check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16699 
16700 		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
16701 					       &zone->origin, ttl, &diff,
16702 					       ISC_TF(!check_ksk),
16703 					       mctx, logmsg);
16704 
16705 		/* Keys couldn't be updated for some reason;
16706 		 * try again later. */
16707 		if (result != ISC_R_SUCCESS) {
16708 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
16709 				     "couldn't update zone keys: %s",
16710 				     isc_result_totext(result));
16711 			goto failure;
16712 		}
16713 
16714 		/*
16715 		 * See if any pre-existing keys have newly become active;
16716 		 * also, see if any new key is for a new algorithm, as in that
16717 		 * event, we need to sign the zone fully.  (If there's a new
16718 		 * key, but it's for an already-existing algorithm, then
16719 		 * the zone signing can be handled incrementally.)
16720 		 */
16721 		for (key = ISC_LIST_HEAD(dnskeys);
16722 		     key != NULL;
16723 		     key = ISC_LIST_NEXT(key, link)) {
16724 			if (!key->first_sign)
16725 				continue;
16726 
16727 			newactive = ISC_TRUE;
16728 
16729 			if (!dns_rdataset_isassociated(&keysigs)) {
16730 				newalg = ISC_TRUE;
16731 				break;
16732 			}
16733 
16734 			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
16735 				/*
16736 				 * This isn't a new algorithm; clear
16737 				 * first_sign so we won't sign the
16738 				 * whole zone with this key later
16739 				 */
16740 				key->first_sign = ISC_FALSE;
16741 			} else {
16742 				newalg = ISC_TRUE;
16743 				break;
16744 			}
16745 		}
16746 
16747 		if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
16748 		    dnskey_sane(zone, db, ver, &diff)) {
16749 			CHECK(dns_diff_apply(&diff, db, ver));
16750 			CHECK(clean_nsec3param(zone, db, ver, &diff));
16751 			CHECK(add_signing_records(db, zone->privatetype,
16752 						  ver, &diff,
16753 						  ISC_TF(newalg || fullsign)));
16754 			CHECK(update_soa_serial(db, ver, &diff, mctx,
16755 						zone->updatemethod));
16756 			CHECK(add_chains(zone, db, ver, &diff));
16757 			CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
16758 			CHECK(zone_journal(zone, zonediff.diff, NULL,
16759 					   "zone_rekey"));
16760 			commit = ISC_TRUE;
16761 		}
16762 	}
16763 
16764 	dns_db_closeversion(db, &ver, ISC_TRUE);
16765 
16766 	if (commit) {
16767 		dns_difftuple_t *tuple;
16768 
16769 		LOCK_ZONE(zone);
16770 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16771 
16772 		zone_needdump(zone, DNS_DUMP_DELAY);
16773 
16774 		zone_settimer(zone, &timenow);
16775 
16776 		/* Remove any signatures from removed keys.  */
16777 		if (!ISC_LIST_EMPTY(rmkeys)) {
16778 			for (key = ISC_LIST_HEAD(rmkeys);
16779 			     key != NULL;
16780 			     key = ISC_LIST_NEXT(key, link)) {
16781 				result = zone_signwithkey(zone,
16782 							  dst_key_alg(key->key),
16783 							  dst_key_id(key->key),
16784 							  ISC_TRUE);
16785 				if (result != ISC_R_SUCCESS) {
16786 					dns_zone_log(zone, ISC_LOG_ERROR,
16787 					     "zone_signwithkey failed: %s",
16788 					     dns_result_totext(result));
16789 				}
16790 			}
16791 		}
16792 
16793 		if (fullsign) {
16794 			/*
16795 			 * "rndc sign" was called, so we now sign the zone
16796 			 * with all active keys, whether they're new or not.
16797 			 */
16798 			for (key = ISC_LIST_HEAD(dnskeys);
16799 			     key != NULL;
16800 			     key = ISC_LIST_NEXT(key, link)) {
16801 				if (!key->force_sign && !key->hint_sign)
16802 					continue;
16803 
16804 				result = zone_signwithkey(zone,
16805 							  dst_key_alg(key->key),
16806 							  dst_key_id(key->key),
16807 							  ISC_FALSE);
16808 				if (result != ISC_R_SUCCESS) {
16809 					dns_zone_log(zone, ISC_LOG_ERROR,
16810 					     "zone_signwithkey failed: %s",
16811 					     dns_result_totext(result));
16812 				}
16813 			}
16814 		} else if (newalg) {
16815 			/*
16816 			 * We haven't been told to sign fully, but a new
16817 			 * algorithm was added to the DNSKEY.  We sign
16818 			 * the full zone, but only with newly active
16819 			 * keys.
16820 			 */
16821 			for (key = ISC_LIST_HEAD(dnskeys);
16822 			     key != NULL;
16823 			     key = ISC_LIST_NEXT(key, link)) {
16824 				if (!key->first_sign)
16825 					continue;
16826 
16827 				result = zone_signwithkey(zone,
16828 							  dst_key_alg(key->key),
16829 							  dst_key_id(key->key),
16830 							  ISC_FALSE);
16831 				if (result != ISC_R_SUCCESS) {
16832 					dns_zone_log(zone, ISC_LOG_ERROR,
16833 					     "zone_signwithkey failed: %s",
16834 					     dns_result_totext(result));
16835 				}
16836 			}
16837 		}
16838 
16839 		/*
16840 		 * Clear fullsign flag, if it was set, so we don't do
16841 		 * another full signing next time
16842 		 */
16843 		zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
16844 
16845 		/*
16846 		 * Cause the zone to add/delete NSEC3 chains for the
16847 		 * deferred NSEC3PARAM changes.
16848 		 */
16849 		for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
16850 		     tuple != NULL;
16851 		     tuple = ISC_LIST_NEXT(tuple, link)) {
16852 			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16853 			dns_rdata_t rdata = DNS_RDATA_INIT;
16854 			dns_rdata_nsec3param_t nsec3param;
16855 
16856 			if (tuple->rdata.type != zone->privatetype ||
16857 			    tuple->op != DNS_DIFFOP_ADD)
16858 				continue;
16859 
16860 			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
16861 							buf, sizeof(buf)))
16862 				continue;
16863 			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
16864 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
16865 			if (nsec3param.flags == 0)
16866 				continue;
16867 
16868 			result = zone_addnsec3chain(zone, &nsec3param);
16869 			if (result != ISC_R_SUCCESS) {
16870 				dns_zone_log(zone, ISC_LOG_ERROR,
16871 					     "zone_addnsec3chain failed: %s",
16872 					     dns_result_totext(result));
16873 			}
16874 		}
16875 
16876 		/*
16877 		 * Activate any NSEC3 chain updates that may have
16878 		 * been scheduled before this rekey.
16879 		 */
16880 		if (fullsign || newalg)
16881 			resume_addnsec3chain(zone);
16882 
16883 		/*
16884 		 * Schedule the next resigning event
16885 		 */
16886 		set_resigntime(zone);
16887 		UNLOCK_ZONE(zone);
16888 	}
16889 
16890 	isc_time_settoepoch(&zone->refreshkeytime);
16891 
16892 	/*
16893 	 * If we're doing key maintenance, set the key refresh timer to
16894 	 * the next scheduled key event or to 'dnssec-loadkeys-interval'
16895 	 * seconds in the future, whichever is sooner.
16896 	 */
16897 	if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
16898 		isc_time_t timethen;
16899 		isc_stdtime_t then;
16900 
16901 		LOCK_ZONE(zone);
16902 		DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
16903 				  &timethen);
16904 		zone->refreshkeytime = timethen;
16905 		UNLOCK_ZONE(zone);
16906 
16907 		for (key = ISC_LIST_HEAD(dnskeys);
16908 		     key != NULL;
16909 		     key = ISC_LIST_NEXT(key, link)) {
16910 			then = now;
16911 			result = next_keyevent(key->key, &then);
16912 			if (result != ISC_R_SUCCESS)
16913 				continue;
16914 
16915 			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
16916 			LOCK_ZONE(zone);
16917 			if (isc_time_compare(&timethen,
16918 					     &zone->refreshkeytime) < 0) {
16919 				zone->refreshkeytime = timethen;
16920 			}
16921 			UNLOCK_ZONE(zone);
16922 		}
16923 
16924 		zone_settimer(zone, &timenow);
16925 
16926 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
16927 		dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
16928 	}
16929 
16930  done:
16931 	dns_diff_clear(&diff);
16932 	dns_diff_clear(&_sig_diff);
16933 
16934 	clear_keylist(&dnskeys, mctx);
16935 	clear_keylist(&keys, mctx);
16936 	clear_keylist(&rmkeys, mctx);
16937 
16938 	if (ver != NULL)
16939 		dns_db_closeversion(db, &ver, ISC_FALSE);
16940 	if (dns_rdataset_isassociated(&keyset))
16941 		dns_rdataset_disassociate(&keyset);
16942 	if (dns_rdataset_isassociated(&keysigs))
16943 		dns_rdataset_disassociate(&keysigs);
16944 	if (dns_rdataset_isassociated(&soasigs))
16945 		dns_rdataset_disassociate(&soasigs);
16946 	if (node != NULL)
16947 		dns_db_detachnode(db, &node);
16948 	if (db != NULL)
16949 		dns_db_detach(&db);
16950 
16951 	INSIST(ver == NULL);
16952 	return;
16953 
16954  failure:
16955 	/*
16956 	 * Something went wrong; try again in ten minutes or
16957 	 * after a key refresh interval, whichever is shorter.
16958 	 */
16959 	isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
16960 	isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
16961 	goto done;
16962 }
16963 
16964 void
dns_zone_rekey(dns_zone_t * zone,isc_boolean_t fullsign)16965 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
16966 	isc_time_t now;
16967 
16968 	if (zone->type == dns_zone_master && zone->task != NULL) {
16969 		LOCK_ZONE(zone);
16970 
16971 		if (fullsign)
16972 			zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
16973 
16974 		TIME_NOW(&now);
16975 		zone->refreshkeytime = now;
16976 		zone_settimer(zone, &now);
16977 
16978 		UNLOCK_ZONE(zone);
16979 	}
16980 }
16981 
16982 isc_result_t
dns_zone_nscheck(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * version,unsigned int * errors)16983 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
16984 		 unsigned int *errors)
16985 {
16986 	isc_result_t result;
16987 	dns_dbnode_t *node = NULL;
16988 
16989 	REQUIRE(DNS_ZONE_VALID(zone));
16990 	REQUIRE(errors != NULL);
16991 
16992 	result = dns_db_getoriginnode(db, &node);
16993 	if (result != ISC_R_SUCCESS)
16994 		return (result);
16995 	result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
16996 				  ISC_FALSE);
16997 	dns_db_detachnode(db, &node);
16998 	return (result);
16999 }
17000 
17001 isc_result_t
dns_zone_cdscheck(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * version)17002 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
17003 	isc_result_t result;
17004 	dns_dbnode_t *node = NULL;
17005 	dns_rdataset_t dnskey, cds, cdnskey;
17006 	unsigned char buffer[DNS_DS_BUFFERSIZE];
17007 	unsigned char algorithms[256];
17008 	unsigned int i;
17009 
17010 	REQUIRE(DNS_ZONE_VALID(zone));
17011 
17012 	result = dns_db_getoriginnode(db, &node);
17013 	if (result != ISC_R_SUCCESS)
17014 		return (result);
17015 
17016 	dns_rdataset_init(&cds);
17017 	dns_rdataset_init(&dnskey);
17018 	dns_rdataset_init(&cdnskey);
17019 
17020 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
17021 				     dns_rdatatype_none, 0, &cds, NULL);
17022 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
17023 		goto failure;
17024 
17025 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
17026 				     dns_rdatatype_none, 0, &cdnskey, NULL);
17027 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
17028 		goto failure;
17029 
17030 	if (!dns_rdataset_isassociated(&cds) &&
17031 	    !dns_rdataset_isassociated(&cdnskey)) {
17032 		result = ISC_R_SUCCESS;
17033 		goto failure;
17034 	}
17035 
17036 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
17037 				     dns_rdatatype_none, 0, &dnskey, NULL);
17038 	if (result == ISC_R_NOTFOUND) {
17039 		if (dns_rdataset_isassociated(&cds))
17040 			result = DNS_R_BADCDS;
17041 		else
17042 			result = DNS_R_BADCDNSKEY;
17043 		goto failure;
17044 	}
17045 	if (result != ISC_R_SUCCESS)
17046 		goto failure;
17047 
17048 	/*
17049 	 * For each DNSSEC algorithm in the CDS RRset there must be
17050 	 * a matching DNSKEY record.
17051 	 */
17052 	if (dns_rdataset_isassociated(&cds)) {
17053 		memset(algorithms, 0, sizeof(algorithms));
17054 		for (result = dns_rdataset_first(&cds);
17055 		     result == ISC_R_SUCCESS;
17056 		     result = dns_rdataset_next(&cds)) {
17057 			dns_rdata_t crdata = DNS_RDATA_INIT;
17058 			dns_rdata_cds_t structcds;
17059 
17060 			dns_rdataset_current(&cds, &crdata);
17061 			CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
17062 			if (algorithms[structcds.algorithm] == 0)
17063 				algorithms[structcds.algorithm] = 1;
17064 			for (result = dns_rdataset_first(&dnskey);
17065 			     result == ISC_R_SUCCESS;
17066 			     result = dns_rdataset_next(&dnskey)) {
17067 				dns_rdata_t rdata = DNS_RDATA_INIT;
17068 				dns_rdata_t dsrdata = DNS_RDATA_INIT;
17069 
17070 				dns_rdataset_current(&dnskey, &rdata);
17071 				CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
17072 							structcds.digest_type,
17073 							buffer, &dsrdata));
17074 				if (crdata.length == dsrdata.length &&
17075 				    memcmp(crdata.data, dsrdata.data,
17076 					   dsrdata.length) == 0) {
17077 					algorithms[structcds.algorithm] = 2;
17078 				}
17079 			}
17080 			if (result != ISC_R_NOMORE)
17081 				goto failure;
17082 		}
17083 		for (i = 0; i < sizeof(algorithms); i++) {
17084 			if (algorithms[i] == 1) {
17085 				result = DNS_R_BADCDNSKEY;
17086 				goto failure;
17087 			}
17088 		}
17089 	}
17090 
17091 	/*
17092 	 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
17093 	 * a matching DNSKEY record.
17094 	 */
17095 	if (dns_rdataset_isassociated(&cdnskey)) {
17096 		memset(algorithms, 0, sizeof(algorithms));
17097 		for (result = dns_rdataset_first(&cdnskey);
17098 		     result == ISC_R_SUCCESS;
17099 		     result = dns_rdataset_next(&cdnskey)) {
17100 			dns_rdata_t crdata = DNS_RDATA_INIT;
17101 			dns_rdata_cdnskey_t structcdnskey;
17102 
17103 			dns_rdataset_current(&cdnskey, &crdata);
17104 			CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
17105 						 NULL));
17106 			if (algorithms[structcdnskey.algorithm] == 0)
17107 				algorithms[structcdnskey.algorithm] = 1;
17108 			for (result = dns_rdataset_first(&dnskey);
17109 			     result == ISC_R_SUCCESS;
17110 			     result = dns_rdataset_next(&dnskey)) {
17111 				dns_rdata_t rdata = DNS_RDATA_INIT;
17112 
17113 				dns_rdataset_current(&dnskey, &rdata);
17114 				if (crdata.length == rdata.length &&
17115 				    memcmp(crdata.data, rdata.data,
17116 					   rdata.length) == 0) {
17117 					algorithms[structcdnskey.algorithm] = 2;
17118 				}
17119 			}
17120 			if (result != ISC_R_NOMORE)
17121 				goto failure;
17122 		}
17123 		for (i = 0; i < sizeof(algorithms); i++) {
17124 			if (algorithms[i] == 1) {
17125 				result = DNS_R_BADCDS;
17126 				goto failure;
17127 			}
17128 		}
17129 	}
17130 	result = ISC_R_SUCCESS;
17131 
17132  failure:
17133 	if (dns_rdataset_isassociated(&cds))
17134 		dns_rdataset_disassociate(&cds);
17135 	if (dns_rdataset_isassociated(&dnskey))
17136 		dns_rdataset_disassociate(&dnskey);
17137 	if (dns_rdataset_isassociated(&cdnskey))
17138 		dns_rdataset_disassociate(&cdnskey);
17139 	dns_db_detachnode(db, &node);
17140 	return (result);
17141 }
17142 
17143 void
dns_zone_setadded(dns_zone_t * zone,isc_boolean_t added)17144 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
17145 	REQUIRE(DNS_ZONE_VALID(zone));
17146 	LOCK_ZONE(zone);
17147 	zone->added = added;
17148 	UNLOCK_ZONE(zone);
17149 }
17150 
17151 isc_boolean_t
dns_zone_getadded(dns_zone_t * zone)17152 dns_zone_getadded(dns_zone_t *zone) {
17153 	REQUIRE(DNS_ZONE_VALID(zone));
17154 	return (zone->added);
17155 }
17156 
17157 isc_result_t
dns_zone_dlzpostload(dns_zone_t * zone,dns_db_t * db)17158 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
17159 {
17160 	isc_time_t loadtime;
17161 	isc_result_t result;
17162 	dns_zone_t *secure = NULL;
17163 
17164 	TIME_NOW(&loadtime);
17165 
17166 	/*
17167 	 * Lock hierarchy: zmgr, zone, raw.
17168 	 */
17169  again:
17170 	LOCK_ZONE(zone);
17171 	if (inline_secure(zone))
17172 		LOCK_ZONE(zone->raw);
17173 	else if (inline_raw(zone)) {
17174 		secure = zone->secure;
17175 		TRYLOCK_ZONE(result, secure);
17176 		if (result != ISC_R_SUCCESS) {
17177 			UNLOCK_ZONE(zone);
17178 			secure = NULL;
17179 #if ISC_PLATFORM_USETHREADS
17180 			isc_thread_yield();
17181 #endif
17182 			goto again;
17183 		}
17184 	}
17185 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
17186 	if (inline_secure(zone))
17187 		UNLOCK_ZONE(zone->raw);
17188 	else if (secure != NULL)
17189 		UNLOCK_ZONE(secure);
17190 	UNLOCK_ZONE(zone);
17191 	return result;
17192 }
17193 
17194 isc_result_t
dns_zone_setrefreshkeyinterval(dns_zone_t * zone,isc_uint32_t interval)17195 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
17196 	REQUIRE(DNS_ZONE_VALID(zone));
17197 	if (interval == 0)
17198 		return (ISC_R_RANGE);
17199 	/* Maximum value: 24 hours (3600 minutes) */
17200 	if (interval > (24 * 60))
17201 		interval = (24 * 60);
17202 	/* Multiply by 60 for seconds */
17203 	zone->refreshkeyinterval = interval * 60;
17204 	return (ISC_R_SUCCESS);
17205 }
17206 
17207 void
dns_zone_setrequestixfr(dns_zone_t * zone,isc_boolean_t flag)17208 dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) {
17209 	REQUIRE(DNS_ZONE_VALID(zone));
17210 	zone->requestixfr = flag;
17211 }
17212 
17213 isc_boolean_t
dns_zone_getrequestixfr(dns_zone_t * zone)17214 dns_zone_getrequestixfr(dns_zone_t *zone) {
17215 	REQUIRE(DNS_ZONE_VALID(zone));
17216 	return (zone->requestixfr);
17217 }
17218 
17219 void
dns_zone_setserialupdatemethod(dns_zone_t * zone,dns_updatemethod_t method)17220 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
17221 	REQUIRE(DNS_ZONE_VALID(zone));
17222 	zone->updatemethod = method;
17223 }
17224 
17225 dns_updatemethod_t
dns_zone_getserialupdatemethod(dns_zone_t * zone)17226 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
17227 	REQUIRE(DNS_ZONE_VALID(zone));
17228 	return(zone->updatemethod);
17229 }
17230 
17231 /*
17232  * Lock hierarchy: zmgr, zone, raw.
17233  */
17234 isc_result_t
dns_zone_link(dns_zone_t * zone,dns_zone_t * raw)17235 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
17236 	isc_result_t result;
17237 	dns_zonemgr_t *zmgr;
17238 
17239 	REQUIRE(DNS_ZONE_VALID(zone));
17240 	REQUIRE(zone->zmgr != NULL);
17241 	REQUIRE(zone->task != NULL);
17242 	REQUIRE(zone->loadtask != NULL);
17243 	REQUIRE(zone->raw == NULL);
17244 
17245 	REQUIRE(DNS_ZONE_VALID(raw));
17246 	REQUIRE(raw->zmgr == NULL);
17247 	REQUIRE(raw->task == NULL);
17248 	REQUIRE(raw->loadtask == NULL);
17249 	REQUIRE(raw->secure == NULL);
17250 
17251 	/*
17252 	 * Lock hierarchy: zmgr, zone, raw.
17253 	 */
17254 	zmgr = zone->zmgr;
17255 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17256 	LOCK_ZONE(zone);
17257 	LOCK_ZONE(raw);
17258 
17259 	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
17260 				  NULL, NULL, zone->task, zone_timer, raw,
17261 				  &raw->timer);
17262 	if (result != ISC_R_SUCCESS)
17263 		goto unlock;
17264 
17265 	/*
17266 	 * The timer "holds" a iref.
17267 	 */
17268 	raw->irefs++;
17269 	INSIST(raw->irefs != 0);
17270 
17271 
17272 	/* dns_zone_attach(raw, &zone->raw); */
17273 	isc_refcount_increment(&raw->erefs, NULL);
17274 	zone->raw = raw;
17275 
17276 	/* dns_zone_iattach(zone,  &raw->secure); */
17277 	zone_iattach(zone, &raw->secure);
17278 
17279 	isc_task_attach(zone->task, &raw->task);
17280 	isc_task_attach(zone->loadtask, &raw->loadtask);
17281 
17282 	ISC_LIST_APPEND(zmgr->zones, raw, link);
17283 	raw->zmgr = zmgr;
17284 	zmgr->refs++;
17285 
17286  unlock:
17287 	UNLOCK_ZONE(raw);
17288 	UNLOCK_ZONE(zone);
17289 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17290 	return (result);
17291 }
17292 
17293 void
dns_zone_getraw(dns_zone_t * zone,dns_zone_t ** raw)17294 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
17295 	REQUIRE(DNS_ZONE_VALID(zone));
17296 	REQUIRE(raw != NULL && *raw == NULL);
17297 
17298 	LOCK(&zone->lock);
17299 	if (zone->raw != NULL)
17300 		dns_zone_attach(zone->raw, raw);
17301 	UNLOCK(&zone->lock);
17302 }
17303 
17304 struct keydone {
17305 	isc_event_t event;
17306 	isc_boolean_t all;
17307 	unsigned char data[5];
17308 };
17309 
17310 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
17311 
17312 static void
keydone(isc_task_t * task,isc_event_t * event)17313 keydone(isc_task_t *task, isc_event_t *event) {
17314 	const char *me = "keydone";
17315 	isc_boolean_t commit = ISC_FALSE;
17316 	isc_result_t result;
17317 	dns_rdata_t rdata = DNS_RDATA_INIT;
17318 	dns_dbversion_t *oldver = NULL, *newver = NULL;
17319 	dns_zone_t *zone;
17320 	dns_db_t *db = NULL;
17321 	dns_dbnode_t *node = NULL;
17322 	dns_rdataset_t rdataset;
17323 	dns_diff_t diff;
17324 	struct keydone *kd = (struct keydone *)event;
17325 	dns_update_log_t log = { update_log_cb, NULL };
17326 	isc_boolean_t clear_pending = ISC_FALSE;
17327 
17328 	UNUSED(task);
17329 
17330 	zone = event->ev_arg;
17331 	INSIST(DNS_ZONE_VALID(zone));
17332 
17333 	ENTER;
17334 
17335 	dns_rdataset_init(&rdataset);
17336 	dns_diff_init(zone->mctx, &diff);
17337 
17338 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17339 	if (zone->db != NULL) {
17340 		dns_db_attach(zone->db, &db);
17341 		dns_db_currentversion(db, &oldver);
17342 		result = dns_db_newversion(db, &newver);
17343 		if (result != ISC_R_SUCCESS) {
17344 			dns_zone_log(zone, ISC_LOG_ERROR,
17345 				     "keydone:dns_db_newversion -> %s",
17346 				     dns_result_totext(result));
17347 			goto failure;
17348 		}
17349 	}
17350 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17351 	if (db == NULL)
17352 		goto failure;
17353 
17354 	result = dns_db_getoriginnode(db, &node);
17355 	if (result != ISC_R_SUCCESS)
17356 		goto failure;
17357 
17358 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
17359 				     dns_rdatatype_none, 0, &rdataset, NULL);
17360 	if (result == ISC_R_NOTFOUND) {
17361 		INSIST(!dns_rdataset_isassociated(&rdataset));
17362 		goto failure;
17363 	}
17364 	if (result != ISC_R_SUCCESS) {
17365 		INSIST(!dns_rdataset_isassociated(&rdataset));
17366 		goto failure;
17367 	}
17368 
17369 	for (result = dns_rdataset_first(&rdataset);
17370 	     result == ISC_R_SUCCESS;
17371 	     result = dns_rdataset_next(&rdataset)) {
17372 		isc_boolean_t found = ISC_FALSE;
17373 
17374 		dns_rdataset_current(&rdataset, &rdata);
17375 
17376 		if (kd->all) {
17377 			if (rdata.length == 5 && rdata.data[0] != 0 &&
17378 			       rdata.data[3] == 0 && rdata.data[4] == 1)
17379 				found = ISC_TRUE;
17380 			else if (rdata.data[0] == 0 &&
17381 				 (rdata.data[2] & PENDINGFLAGS) != 0) {
17382 				found = ISC_TRUE;
17383 				clear_pending = ISC_TRUE;
17384 			}
17385 		} else if (rdata.length == 5 &&
17386 			   memcmp(rdata.data, kd->data, 5) == 0)
17387 			found = ISC_TRUE;
17388 
17389 		if (found)
17390 			CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
17391 					    &zone->origin, rdataset.ttl,
17392 					    &rdata));
17393 		dns_rdata_reset(&rdata);
17394 	}
17395 
17396 	if (!ISC_LIST_EMPTY(diff.tuples)) {
17397 		/* Write changes to journal file. */
17398 		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
17399 					zone->updatemethod));
17400 
17401 		result = dns_update_signatures(&log, zone, db,
17402 					       oldver, newver, &diff,
17403 					       zone->sigvalidityinterval);
17404 		if (!clear_pending)
17405 			CHECK(result);
17406 
17407 		CHECK(zone_journal(zone, &diff, NULL, "keydone"));
17408 		commit = ISC_TRUE;
17409 
17410 		LOCK_ZONE(zone);
17411 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
17412 		zone_needdump(zone, 30);
17413 		UNLOCK_ZONE(zone);
17414 	}
17415 
17416  failure:
17417 	if (dns_rdataset_isassociated(&rdataset))
17418 		dns_rdataset_disassociate(&rdataset);
17419 	if (db != NULL) {
17420 		if (node != NULL)
17421 			dns_db_detachnode(db, &node);
17422 		if (oldver != NULL)
17423 			dns_db_closeversion(db, &oldver, ISC_FALSE);
17424 		if (newver != NULL)
17425 			dns_db_closeversion(db, &newver, commit);
17426 		dns_db_detach(&db);
17427 	}
17428 	dns_diff_clear(&diff);
17429 	isc_event_free(&event);
17430 	dns_zone_idetach(&zone);
17431 
17432 	INSIST(oldver == NULL);
17433 	INSIST(newver == NULL);
17434 }
17435 
17436 isc_result_t
dns_zone_keydone(dns_zone_t * zone,const char * keystr)17437 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
17438 	isc_result_t result = ISC_R_SUCCESS;
17439 	isc_event_t *e;
17440 	isc_buffer_t b;
17441 	dns_zone_t *dummy = NULL;
17442 	struct keydone *kd;
17443 
17444 	REQUIRE(DNS_ZONE_VALID(zone));
17445 
17446 	LOCK_ZONE(zone);
17447 
17448 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
17449 			       zone, sizeof(struct keydone));
17450 	if (e == NULL) {
17451 		result = ISC_R_NOMEMORY;
17452 		goto failure;
17453 	}
17454 
17455 	kd = (struct keydone *) e;
17456 	if (strcasecmp(keystr, "all") == 0)
17457 		kd->all = ISC_TRUE;
17458 	else {
17459 		isc_textregion_t r;
17460 		const char *algstr;
17461 		dns_keytag_t keyid;
17462 		dns_secalg_t alg;
17463 		size_t n;
17464 
17465 		kd->all = ISC_FALSE;
17466 
17467 		n = sscanf(keystr, "%hd/", &keyid);
17468 		if (n == 0U)
17469 			CHECK(ISC_R_FAILURE);
17470 
17471 		algstr = strchr(keystr, '/');
17472 		if (algstr != NULL)
17473 			algstr++;
17474 		else
17475 			CHECK(ISC_R_FAILURE);
17476 
17477 		n = sscanf(algstr, "%hhd", &alg);
17478 		if (n == 0U) {
17479 			DE_CONST(algstr, r.base);
17480 			r.length = strlen(algstr);
17481 			CHECK(dns_secalg_fromtext(&alg, &r));
17482 		}
17483 
17484 		/* construct a private-type rdata */
17485 		isc_buffer_init(&b, kd->data, sizeof(kd->data));
17486 		isc_buffer_putuint8(&b, alg);
17487 		isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
17488 		isc_buffer_putuint8(&b, (keyid & 0xff));
17489 		isc_buffer_putuint8(&b, 0);
17490 		isc_buffer_putuint8(&b, 1);
17491 	}
17492 
17493 	zone_iattach(zone, &dummy);
17494 	isc_task_send(zone->task, &e);
17495 
17496  failure:
17497 	if (e != NULL)
17498 		isc_event_free(&e);
17499 	UNLOCK_ZONE(zone);
17500 	return (result);
17501 }
17502 
17503 static void
setnsec3param(isc_task_t * task,isc_event_t * event)17504 setnsec3param(isc_task_t *task, isc_event_t *event) {
17505 	const char *me = "setnsec3param";
17506 	isc_boolean_t commit = ISC_FALSE;
17507 	isc_result_t result;
17508 	dns_dbversion_t *oldver = NULL, *newver = NULL;
17509 	dns_zone_t *zone;
17510 	dns_db_t *db = NULL;
17511 	dns_dbnode_t *node = NULL;
17512 	dns_rdataset_t prdataset, nrdataset;
17513 	dns_diff_t diff;
17514 	struct np3event *npe = (struct np3event *)event;
17515 	nsec3param_t *np;
17516 	dns_update_log_t log = { update_log_cb, NULL };
17517 	dns_rdata_t rdata;
17518 	isc_boolean_t nseconly;
17519 	isc_boolean_t exists = ISC_FALSE;
17520 
17521 	UNUSED(task);
17522 
17523 	zone = event->ev_arg;
17524 	INSIST(DNS_ZONE_VALID(zone));
17525 
17526 	ENTER;
17527 
17528 	np = &npe->params;
17529 
17530 	dns_rdataset_init(&prdataset);
17531 	dns_rdataset_init(&nrdataset);
17532 	dns_diff_init(zone->mctx, &diff);
17533 
17534 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17535 	if (zone->db != NULL) {
17536 		dns_db_attach(zone->db, &db);
17537 		dns_db_currentversion(db, &oldver);
17538 		result = dns_db_newversion(db, &newver);
17539 		if (result != ISC_R_SUCCESS) {
17540 			dns_zone_log(zone, ISC_LOG_ERROR,
17541 				     "setnsec3param:dns_db_newversion -> %s",
17542 				     dns_result_totext(result));
17543 			goto failure;
17544 		}
17545 	}
17546 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17547 	if (db == NULL)
17548 		goto failure;
17549 
17550 	CHECK(dns_db_getoriginnode(db, &node));
17551 
17552 	/*
17553 	 * Does a private-type record already exist for this chain?
17554 	 */
17555 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
17556 				     dns_rdatatype_none, 0, &prdataset, NULL);
17557 	if (result == ISC_R_SUCCESS) {
17558 		for (result = dns_rdataset_first(&prdataset);
17559 		     result == ISC_R_SUCCESS;
17560 		     result = dns_rdataset_next(&prdataset)) {
17561 			dns_rdata_init(&rdata);
17562 			dns_rdataset_current(&prdataset, &rdata);
17563 
17564 			if (np->length == rdata.length &&
17565 			    memcmp(rdata.data, np->data, np->length) == 0) {
17566 				exists = ISC_TRUE;
17567 				break;
17568 			}
17569 		}
17570 	} else if (result != ISC_R_NOTFOUND) {
17571 		INSIST(!dns_rdataset_isassociated(&prdataset));
17572 		goto failure;
17573 	}
17574 
17575 	/*
17576 	 * Does the chain already exist?
17577 	 */
17578 	result = dns_db_findrdataset(db, node, newver,
17579 				     dns_rdatatype_nsec3param,
17580 				     dns_rdatatype_none, 0, &nrdataset, NULL);
17581 	if (result == ISC_R_SUCCESS) {
17582 		for (result = dns_rdataset_first(&nrdataset);
17583 		     result == ISC_R_SUCCESS;
17584 		     result = dns_rdataset_next(&nrdataset)) {
17585 			dns_rdata_init(&rdata);
17586 			dns_rdataset_current(&nrdataset, &rdata);
17587 
17588 			if (np->length == (rdata.length + 1) &&
17589 			    memcmp(rdata.data, np->data + 1,
17590 				   np->length - 1) == 0)
17591 			{
17592 				exists = ISC_TRUE;
17593 				break;
17594 			}
17595 		}
17596 	} else if (result != ISC_R_NOTFOUND) {
17597 		INSIST(!dns_rdataset_isassociated(&nrdataset));
17598 		goto failure;
17599 	}
17600 
17601 
17602 	/*
17603 	 * We need to remove any existing NSEC3 chains.
17604 	 */
17605 	if (!exists && np->replace && (np->length != 0 || np->nsec))
17606 		CHECK(dns_nsec3param_deletechains(db, newver, zone,
17607 						  !np->nsec, &diff));
17608 
17609 	if (!exists && np->length != 0) {
17610 		/*
17611 		 * We're creating an NSEC3 chain.
17612 		 *
17613 		 * If the zone is not currently capable of supporting
17614 		 * an NSEC3 chain, add the INITIAL flag, so these
17615 		 * parameters can be used later when NSEC3 becomes
17616 		 * available.
17617 		 */
17618 		dns_rdata_init(&rdata);
17619 
17620 		np->data[2] |= DNS_NSEC3FLAG_CREATE;
17621 		result = dns_nsec_nseconly(db, newver, &nseconly);
17622 		if (result == ISC_R_NOTFOUND || nseconly)
17623 			np->data[2] |= DNS_NSEC3FLAG_INITIAL;
17624 
17625 		rdata.length = np->length;
17626 		rdata.data = np->data;
17627 		rdata.type = zone->privatetype;
17628 		rdata.rdclass = zone->rdclass;
17629 		CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
17630 				    &zone->origin, 0, &rdata));
17631 	}
17632 
17633 	if (!ISC_LIST_EMPTY(diff.tuples)) {
17634 		/* Write changes to journal file. */
17635 		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
17636 					zone->updatemethod));
17637 		result = dns_update_signatures(&log, zone, db,
17638 					       oldver, newver, &diff,
17639 					       zone->sigvalidityinterval);
17640 		if (result != ISC_R_NOTFOUND)
17641 			CHECK(result);
17642 		CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
17643 		commit = ISC_TRUE;
17644 
17645 		LOCK_ZONE(zone);
17646 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
17647 		zone_needdump(zone, 30);
17648 		UNLOCK_ZONE(zone);
17649 	}
17650 
17651  failure:
17652 	if (dns_rdataset_isassociated(&prdataset))
17653 		dns_rdataset_disassociate(&prdataset);
17654 	if (dns_rdataset_isassociated(&nrdataset))
17655 		dns_rdataset_disassociate(&nrdataset);
17656 	if (node != NULL)
17657 		dns_db_detachnode(db, &node);
17658 	if (oldver != NULL)
17659 		dns_db_closeversion(db, &oldver, ISC_FALSE);
17660 	if (newver != NULL)
17661 		dns_db_closeversion(db, &newver, commit);
17662 	if (db != NULL)
17663 		dns_db_detach(&db);
17664 	if (commit)
17665 		resume_addnsec3chain(zone);
17666 	dns_diff_clear(&diff);
17667 	isc_event_free(&event);
17668 	dns_zone_idetach(&zone);
17669 
17670 	INSIST(oldver == NULL);
17671 	INSIST(newver == NULL);
17672 }
17673 
17674 isc_result_t
dns_zone_setnsec3param(dns_zone_t * zone,isc_uint8_t hash,isc_uint8_t flags,isc_uint16_t iter,isc_uint8_t saltlen,unsigned char * salt,isc_boolean_t replace)17675 dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
17676 		       isc_uint16_t iter, isc_uint8_t saltlen,
17677 		       unsigned char *salt, isc_boolean_t replace)
17678 {
17679 	isc_result_t result = ISC_R_SUCCESS;
17680 	dns_rdata_nsec3param_t param;
17681 	dns_rdata_t nrdata = DNS_RDATA_INIT;
17682 	dns_rdata_t prdata = DNS_RDATA_INIT;
17683 	unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
17684 	struct np3event *npe;
17685 	nsec3param_t *np;
17686 	dns_zone_t *dummy = NULL;
17687 	isc_buffer_t b;
17688 	isc_event_t *e;
17689 
17690 	REQUIRE(DNS_ZONE_VALID(zone));
17691 	REQUIRE(salt != NULL);
17692 
17693 	LOCK_ZONE(zone);
17694 
17695 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
17696 			       setnsec3param, zone, sizeof(struct np3event));
17697 	if (e == NULL) {
17698 		result = ISC_R_NOMEMORY;
17699 		goto failure;
17700 	}
17701 
17702 	npe = (struct np3event *) e;
17703 	np = &npe->params;
17704 
17705 	np->replace = replace;
17706 	if (hash == 0) {
17707 		np->length = 0;
17708 		np->nsec = ISC_TRUE;
17709 	} else {
17710 		param.common.rdclass = zone->rdclass;
17711 		param.common.rdtype = dns_rdatatype_nsec3param;
17712 		ISC_LINK_INIT(&param.common, link);
17713 		param.mctx = NULL;
17714 		param.hash = hash;
17715 		param.flags = flags;
17716 		param.iterations = iter;
17717 		param.salt_length = saltlen;
17718 		param.salt = salt;
17719 		isc_buffer_init(&b, nbuf, sizeof(nbuf));
17720 		CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
17721 					   dns_rdatatype_nsec3param,
17722 					   &param, &b));
17723 		dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
17724 					 np->data, sizeof(np->data));
17725 		np->length = prdata.length;
17726 	}
17727 
17728 	zone_iattach(zone, &dummy);
17729 	isc_task_send(zone->task, &e);
17730 
17731  failure:
17732 	if (e != NULL)
17733 		isc_event_free(&e);
17734 	UNLOCK_ZONE(zone);
17735 	return (result);
17736 }
17737 
17738 void
dns_zone_setstatlevel(dns_zone_t * zone,dns_zonestat_level_t level)17739 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
17740 	REQUIRE(DNS_ZONE_VALID(zone));
17741 
17742 	zone->statlevel = level;
17743 }
17744 
17745 dns_zonestat_level_t
dns_zone_getstatlevel(dns_zone_t * zone)17746 dns_zone_getstatlevel(dns_zone_t *zone) {
17747 	REQUIRE(DNS_ZONE_VALID(zone));
17748 
17749 	return (zone->statlevel);
17750 }
17751