zone.c 380 KB
Newer Older
1
/*
Automatic Updater's avatar
Automatic Updater committed
2
 * Copyright (C) 2004-2011  Internet Systems Consortium, Inc. ("ISC")
Mark Andrews's avatar
Mark Andrews committed
3
 * Copyright (C) 1999-2003  Internet Software Consortium.
4
 *
Automatic Updater's avatar
Automatic Updater committed
5
 * Permission to use, copy, modify, and/or distribute this software for any
6
7
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
8
 *
Mark Andrews's avatar
Mark Andrews committed
9
10
11
12
13
14
15
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
16
17
 */

Automatic Updater's avatar
Automatic Updater committed
18
/* $Id: zone.c,v 1.610 2011/05/19 23:47:17 tbox Exp $ */
19
20

/*! \file */
21
22

#include <config.h>
Mark Andrews's avatar
Mark Andrews committed
23
#include <errno.h>
24

25
#include <isc/file.h>
26
#include <isc/mutex.h>
Mark Andrews's avatar
Mark Andrews committed
27
#include <isc/print.h>
28
#include <isc/random.h>
Mark Andrews's avatar
Mark Andrews committed
29
#include <isc/ratelimiter.h>
30
#include <isc/refcount.h>
31
#include <isc/rwlock.h>
32
#include <isc/serial.h>
Mark Andrews's avatar
Mark Andrews committed
33
#include <isc/strerror.h>
34
#include <isc/stats.h>
35
#include <isc/stdtime.h>
36
#include <isc/string.h>
37
#include <isc/taskpool.h>
38
#include <isc/timer.h>
Michael Graff's avatar
Michael Graff committed
39
#include <isc/util.h>
40

41
#include <dns/acache.h>
42
#include <dns/acl.h>
Mark Andrews's avatar
Mark Andrews committed
43
#include <dns/adb.h>
44
#include <dns/callbacks.h>
45
#include <dns/db.h>
46
#include <dns/dbiterator.h>
47
#include <dns/dnssec.h>
48
#include <dns/events.h>
49
#include <dns/journal.h>
50
51
#include <dns/keydata.h>
#include <dns/keytable.h>
52
#include <dns/keyvalues.h>
53
#include <dns/log.h>
54
#include <dns/master.h>
Mark Andrews's avatar
Mark Andrews committed
55
#include <dns/masterdump.h>
56
#include <dns/message.h>
57
#include <dns/name.h>
58
#include <dns/nsec.h>
59
#include <dns/nsec3.h>
60
#include <dns/peer.h>
61
#include <dns/private.h>
62
#include <dns/rbt.h>
63
#include <dns/rcode.h>
64
#include <dns/rdataclass.h>
65
#include <dns/rdatalist.h>
66
#include <dns/rdataset.h>
67
#include <dns/rdatasetiter.h>
Brian Wellington's avatar
Brian Wellington committed
68
#include <dns/rdatastruct.h>
69
#include <dns/rdatatype.h>
Mark Andrews's avatar
Mark Andrews committed
70
#include <dns/request.h>
71
72
#include <dns/resolver.h>
#include <dns/result.h>
73
#include <dns/rriterator.h>
74
#include <dns/soa.h>
75
#include <dns/ssu.h>
76
#include <dns/stats.h>
77
#include <dns/tsig.h>
78
#include <dns/xfrin.h>
79
#include <dns/zone.h>
80

81
82
#include <dst/dst.h>

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#define ZONE_MAGIC			ISC_MAGIC('Z', 'O', 'N', 'E')
#define DNS_ZONE_VALID(zone)		ISC_MAGIC_VALID(zone, ZONE_MAGIC)

#define NOTIFY_MAGIC			ISC_MAGIC('N', 't', 'f', 'y')
#define DNS_NOTIFY_VALID(notify)	ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)

#define STUB_MAGIC			ISC_MAGIC('S', 't', 'u', 'b')
#define DNS_STUB_VALID(stub)		ISC_MAGIC_VALID(stub, STUB_MAGIC)

#define ZONEMGR_MAGIC			ISC_MAGIC('Z', 'm', 'g', 'r')
#define DNS_ZONEMGR_VALID(stub)		ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)

#define LOAD_MAGIC			ISC_MAGIC('L', 'o', 'a', 'd')
#define DNS_LOAD_VALID(load)		ISC_MAGIC_VALID(load, LOAD_MAGIC)

#define FORWARD_MAGIC			ISC_MAGIC('F', 'o', 'r', 'w')
#define DNS_FORWARD_VALID(load)		ISC_MAGIC_VALID(load, FORWARD_MAGIC)

#define IO_MAGIC			ISC_MAGIC('Z', 'm', 'I', 'O')
#define DNS_IO_VALID(load)		ISC_MAGIC_VALID(load, IO_MAGIC)

104
/*%
105
106
107
108
 * Ensure 'a' is at least 'min' but not more than 'max'.
 */
#define RANGE(a, min, max) \
		(((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
109

110
111
#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)

Scott Mann's avatar
Scott Mann committed
112
113
114
115
116
117
118
/*%
 * Key flags
 */
#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
#define ALG(x) dst_key_alg(x)

119
120
121
/*
 * Default values.
 */
122
123
124
#define DNS_DEFAULT_IDLEIN 3600		/*%< 1 hour */
#define DNS_DEFAULT_IDLEOUT 3600	/*%< 1 hour */
#define MAX_XFER_TIME (2*3600)		/*%< Documented default is 2 hours */
Scott Mann's avatar
Scott Mann committed
125
#define RESIGN_DELAY 3600		/*%< 1 hour */
Mark Andrews's avatar
Mark Andrews committed
126

127
#ifndef DNS_MAX_EXPIRE
128
#define DNS_MAX_EXPIRE	14515200	/*%< 24 weeks */
129
#endif
Mark Andrews's avatar
Mark Andrews committed
130

131
#ifndef DNS_DUMP_DELAY
132
#define DNS_DUMP_DELAY 900		/*%< 15 minutes */
133
134
#endif

135
136
typedef struct dns_notify dns_notify_t;
typedef struct dns_stub dns_stub_t;
137
typedef struct dns_load dns_load_t;
138
typedef struct dns_forward dns_forward_t;
139
140
typedef struct dns_io dns_io_t;
typedef ISC_LIST(dns_io_t) dns_iolist_t;
141
142
typedef struct dns_signing dns_signing_t;
typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
143
144
typedef struct dns_nsec3chain dns_nsec3chain_t;
typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
145
typedef struct dns_keyfetch dns_keyfetch_t;
146

147
148
149
#define DNS_ZONE_CHECKLOCK
#ifdef DNS_ZONE_CHECKLOCK
#define LOCK_ZONE(z) \
Mark Andrews's avatar
Mark Andrews committed
150
151
152
153
	 do { LOCK(&(z)->lock); \
	      INSIST((z)->locked == ISC_FALSE); \
	     (z)->locked = ISC_TRUE; \
		} while (0)
154
155
#define UNLOCK_ZONE(z) \
	do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
Mark Andrews's avatar
Mark Andrews committed
156
#define LOCKED_ZONE(z) ((z)->locked)
157
158
159
160
161
162
#else
#define LOCK_ZONE(z) LOCK(&(z)->lock)
#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
#define LOCKED_ZONE(z) ISC_TRUE
#endif

163
164
165
166
167
168
169
170
171
172
173
174
#ifdef ISC_RWLOCK_USEATOMIC
#define ZONEDB_INITLOCK(l)	isc_rwlock_init((l), 0, 0)
#define ZONEDB_DESTROYLOCK(l)	isc_rwlock_destroy(l)
#define ZONEDB_LOCK(l, t)	RWLOCK((l), (t))
#define ZONEDB_UNLOCK(l, t)	RWUNLOCK((l), (t))
#else
#define ZONEDB_INITLOCK(l)	isc_mutex_init(l)
#define ZONEDB_DESTROYLOCK(l)	DESTROYLOCK(l)
#define ZONEDB_LOCK(l, t)	LOCK(l)
#define ZONEDB_UNLOCK(l, t)	UNLOCK(l)
#endif

175
176
177
178
struct dns_zone {
	/* Unlocked */
	unsigned int		magic;
	isc_mutex_t		lock;
179
180
181
#ifdef DNS_ZONE_CHECKLOCK
	isc_boolean_t		locked;
#endif
182
	isc_mem_t		*mctx;
183
	isc_refcount_t		erefs;
184

185
186
187
188
189
190
191
#ifdef ISC_RWLOCK_USEATOMIC
	isc_rwlock_t		dblock;
#else
	isc_mutex_t		dblock;
#endif
	dns_db_t		*db;		/* Locked by dblock */

192
	/* Locked */
193
194
	dns_zonemgr_t		*zmgr;
	ISC_LINK(dns_zone_t)	link;		/* Used by zmgr. */
195
	isc_timer_t		*timer;
196
	unsigned int		irefs;
197
	dns_name_t		origin;
Mark Andrews's avatar
Mark Andrews committed
198
	char			*masterfile;
199
	dns_masterformat_t	masterformat;
200
	char			*journal;
201
	isc_int32_t		journalsize;
202
203
204
205
206
	dns_rdataclass_t	rdclass;
	dns_zonetype_t		type;
	unsigned int		flags;
	unsigned int		options;
	unsigned int		db_argc;
207
	char			**db_argv;
208
209
210
	isc_time_t		expiretime;
	isc_time_t		refreshtime;
	isc_time_t		dumptime;
211
	isc_time_t		loadtime;
212
	isc_time_t		notifytime;
213
214
215
	isc_time_t		resigntime;
	isc_time_t		keywarntime;
	isc_time_t		signingtime;
216
	isc_time_t		nsec3chaintime;
217
	isc_time_t		refreshkeytime;
218
	isc_uint32_t		refreshkeyinterval;
219
	isc_uint32_t		refreshkeycount;
220
221
222
223
	isc_uint32_t		refresh;
	isc_uint32_t		retry;
	isc_uint32_t		expire;
	isc_uint32_t		minimum;
224
	isc_stdtime_t		key_expiry;
Scott Mann's avatar
Scott Mann committed
225
	isc_stdtime_t		log_key_expired_timer;
226
	char			*keydirectory;
227
228
229
230
231
232

	isc_uint32_t		maxrefresh;
	isc_uint32_t		minrefresh;
	isc_uint32_t		maxretry;
	isc_uint32_t		minretry;

233
	isc_sockaddr_t		*masters;
David Lawrence's avatar
tabify    
David Lawrence committed
234
	dns_name_t		**masterkeynames;
235
	isc_boolean_t		*mastersok;
236
237
	unsigned int		masterscnt;
	unsigned int		curmaster;
Mark Andrews's avatar
Mark Andrews committed
238
	isc_sockaddr_t		masteraddr;
239
	dns_notifytype_t	notifytype;
240
	isc_sockaddr_t		*notify;
241
	dns_name_t		**notifykeynames;
242
243
	unsigned int		notifycnt;
	isc_sockaddr_t		notifyfrom;
244
	isc_task_t		*task;
245
246
247
248
249
250
251
	isc_sockaddr_t		notifysrc4;
	isc_sockaddr_t		notifysrc6;
	isc_sockaddr_t		xfrsource4;
	isc_sockaddr_t		xfrsource6;
	isc_sockaddr_t		altxfrsource4;
	isc_sockaddr_t		altxfrsource6;
	isc_sockaddr_t		sourceaddr;
Mark Andrews's avatar
Mark Andrews committed
252
	dns_xfrin_ctx_t		*xfr;		/* task locked */
253
	dns_tsigkey_t		*tsigkey;	/* key used for xfr */
254
	/* Access Control Lists */
255
	dns_acl_t		*update_acl;
256
	dns_acl_t		*forward_acl;
257
	dns_acl_t		*notify_acl;
258
	dns_acl_t		*query_acl;
259
	dns_acl_t		*queryon_acl;
260
	dns_acl_t		*xfr_acl;
261
	isc_boolean_t		update_disabled;
262
	isc_boolean_t		zero_no_soa_ttl;
263
	dns_severity_t		check_names;
264
	ISC_LIST(dns_notify_t)	notifies;
Mark Andrews's avatar
Mark Andrews committed
265
	dns_request_t		*request;
266
	dns_loadctx_t		*lctx;
267
	dns_io_t		*readio;
268
269
	dns_dumpctx_t		*dctx;
	dns_io_t		*writeio;
Mark Andrews's avatar
Mark Andrews committed
270
271
	isc_uint32_t		maxxfrin;
	isc_uint32_t		maxxfrout;
272
273
	isc_uint32_t		idlein;
	isc_uint32_t		idleout;
274
	isc_event_t		ctlevent;
275
	dns_ssutable_t		*ssutable;
276
	isc_uint32_t		sigvalidityinterval;
277
	isc_uint32_t		sigresigninginterval;
278
	dns_view_t		*view;
279
	dns_acache_t		*acache;
280
281
282
	dns_checkmxfunc_t	checkmx;
	dns_checksrvfunc_t	checksrv;
	dns_checknsfunc_t	checkns;
283
	/*%
284
	 * Zones in certain states such as "waiting for zone transfer"
285
286
287
288
289
	 * or "zone transfer in progress" are kept on per-state linked lists
	 * in the zone manager using the 'statelink' field.  The 'statelist'
	 * field points at the list the zone is currently on.  It the zone
	 * is not on any such list, statelist is NULL.
	 */
290
	ISC_LINK(dns_zone_t)	statelink;
David Lawrence's avatar
tabify    
David Lawrence committed
291
	dns_zonelist_t		*statelist;
292
	/*%
293
	 * Statistics counters about zone management.
294
	 */
295
	isc_stats_t		*stats;
296
297
298
299
	/*%
	 * Optional per-zone statistics counters.  Counted outside of this
	 * module.
	 */
300
301
	isc_boolean_t		requeststats_on;
	isc_stats_t		*requeststats;
302
	isc_uint32_t		notifydelay;
303
304
	dns_isselffunc_t	isself;
	void			*isselfarg;
305
306
307
308
309

	char *			strnamerd;
	char *			strname;
	char *			strrdclass;
	char *			strviewname;
310
311
312
313
314

	/*%
	 * Serial number for deferred journal compaction.
	 */
	isc_uint32_t		compact_serial;
315
316
317
	/*%
	 * Keys that are signing the zone for the first time.
	 */
318
319
	dns_signinglist_t	signing;
	dns_nsec3chainlist_t	nsec3chain;
320
321
322
323
324
325
	/*%
	 * Signing / re-signing quantum stopping parameters.
	 */
	isc_uint32_t		signatures;
	isc_uint32_t		nodes;
	dns_rdatatype_t		privatetype;
326
327
328
329
330

	/*%
	 * Autosigning/key-maintenance options
	 */
	isc_uint32_t		keyopts;
331
332
333
334
335

	/*%
	 * True if added by "rndc addzone"
	 */
	isc_boolean_t           added;
336
337
338
339
340

	/*%
	 * whether a rpz radix was needed when last loaded
	 */
	isc_boolean_t           rpz_zone;
341
342
};

343
#define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
344
345
346
347
348
349
350
351
#define DNS_ZONE_SETFLAG(z,f) do { \
		INSIST(LOCKED_ZONE(z)); \
		(z)->flags |= (f); \
		} while (0)
#define DNS_ZONE_CLRFLAG(z,f) do { \
		INSIST(LOCKED_ZONE(z)); \
		(z)->flags &= ~(f); \
		} while (0)
352
	/* XXX MPA these may need to go back into zone.h */
353
354
355
356
357
358
359
360
361
362
#define DNS_ZONEFLG_REFRESH	0x00000001U	/*%< refresh check in progress */
#define DNS_ZONEFLG_NEEDDUMP	0x00000002U	/*%< zone need consolidation */
#define DNS_ZONEFLG_USEVC	0x00000004U	/*%< use tcp for refresh query */
#define DNS_ZONEFLG_DUMPING	0x00000008U	/*%< a dump is in progress */
#define DNS_ZONEFLG_HASINCLUDE	0x00000010U	/*%< $INCLUDE in zone file */
#define DNS_ZONEFLG_LOADED	0x00000020U	/*%< database has loaded */
#define DNS_ZONEFLG_EXITING	0x00000040U	/*%< zone is being destroyed */
#define DNS_ZONEFLG_EXPIRED	0x00000080U	/*%< zone has expired */
#define DNS_ZONEFLG_NEEDREFRESH	0x00000100U	/*%< refresh check needed */
#define DNS_ZONEFLG_UPTODATE	0x00000200U	/*%< zone contents are
363
						 * uptodate */
364
#define DNS_ZONEFLG_NEEDNOTIFY	0x00000400U	/*%< need to send out notify
Mark Andrews's avatar
Mark Andrews committed
365
						 * messages */
366
#define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U	/*%< generate a journal diff on
367
						 * reload */
368
#define DNS_ZONEFLG_NOMASTERS	0x00001000U	/*%< an attempt to refresh a
369
						 * zone with no masters
Francis Dupont's avatar
Francis Dupont committed
370
						 * occurred */
371
372
#define DNS_ZONEFLG_LOADING	0x00002000U	/*%< load from disk in progress*/
#define DNS_ZONEFLG_HAVETIMERS	0x00004000U	/*%< timer values have been set
373
374
375
						 * from SOA (if not set, we
						 * are still using
						 * default timer values) */
376
#define DNS_ZONEFLG_FORCEXFER	0x00008000U	/*%< Force a zone xfer */
Mark Andrews's avatar
Mark Andrews committed
377
378
379
#define DNS_ZONEFLG_NOREFRESH	0x00010000U
#define DNS_ZONEFLG_DIALNOTIFY	0x00020000U
#define DNS_ZONEFLG_DIALREFRESH	0x00040000U
380
#define DNS_ZONEFLG_SHUTDOWN	0x00080000U
381
#define DNS_ZONEFLAG_NOIXFR	0x00100000U	/*%< IXFR failed, force AXFR */
382
#define DNS_ZONEFLG_FLUSH	0x00200000U
383
#define DNS_ZONEFLG_NOEDNS	0x00400000U
384
#define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
385
#define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
386
#define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
387
388
#define DNS_ZONEFLG_REFRESHING	0x04000000U	/*%< Refreshing keydata */
#define DNS_ZONEFLG_THAW	0x08000000U
389
/* #define DNS_ZONEFLG_XXXXX	0x10000000U   XXXMPA unused. */
390
#define DNS_ZONEFLG_NODELAY	0x20000000U
391

Mark Andrews's avatar
Mark Andrews committed
392
#define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
393
#define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
394

395
396
/* Flags for zone_load() */
#define DNS_ZONELOADFLAG_NOSTAT	0x00000001U	/* Do not stat() master files */
397
398
#define DNS_ZONELOADFLAG_THAW	0x00000002U	/* Thaw the zone on successful
						   load. */
399

400
401
402
#define UNREACH_CHACHE_SIZE	10U
#define UNREACH_HOLD_TIME	600	/* 10 minutes */

403
404
405
406
407
#define CHECK(op) \
	do { result = (op); \
		if (result != ISC_R_SUCCESS) goto failure; \
	} while (0)

408
409
410
411
412
413
414
struct dns_unreachable {
	isc_sockaddr_t	remote;
	isc_sockaddr_t	local;
	isc_uint32_t	expire;
	isc_uint32_t	last;
};

415
struct dns_zonemgr {
416
	unsigned int		magic;
417
	isc_mem_t *		mctx;
Mark Andrews's avatar
Mark Andrews committed
418
	int			refs;		/* Locked by rwlock */
419
420
	isc_taskmgr_t *		taskmgr;
	isc_timermgr_t *	timermgr;
421
	isc_socketmgr_t *	socketmgr;
422
	isc_taskpool_t *	zonetasks;
423
	isc_task_t *		task;
424
	isc_ratelimiter_t *	rl;
425
	isc_rwlock_t		rwlock;
426
427
	isc_mutex_t		iolock;

428
	/* Locked by rwlock. */
429
430
431
	dns_zonelist_t		zones;
	dns_zonelist_t		waiting_for_xfrin;
	dns_zonelist_t		xfrin_in_progress;
432

433
	/* Configuration data. */
434
435
	isc_uint32_t		transfersin;
	isc_uint32_t		transfersperns;
436
	unsigned int		serialqueryrate;
437
438
439
440
441
442

	/* Locked by iolock */
	isc_uint32_t		iolimit;
	isc_uint32_t		ioactive;
	dns_iolist_t		high;
	dns_iolist_t		low;
Automatic Updater's avatar
Automatic Updater committed
443

444
445
446
	/* Locked by rwlock. */
	/* LRU cache */
	struct dns_unreachable	unreachable[UNREACH_CHACHE_SIZE];
447
448
};

449
/*%
Mark Andrews's avatar
Mark Andrews committed
450
451
 * Hold notify state.
 */
452
struct dns_notify {
453
	unsigned int		magic;
Mark Andrews's avatar
Mark Andrews committed
454
	unsigned int		flags;
455
	isc_mem_t		*mctx;
Mark Andrews's avatar
Mark Andrews committed
456
457
458
459
	dns_zone_t		*zone;
	dns_adbfind_t		*find;
	dns_request_t		*request;
	dns_name_t		ns;
460
	isc_sockaddr_t		dst;
461
	dns_tsigkey_t		*key;
462
463
464
	ISC_LINK(dns_notify_t)	link;
};

Mark Andrews's avatar
Mark Andrews committed
465
466
#define DNS_NOTIFY_NOSOA	0x0001U

467
/*%
468
469
470
471
472
473
 *	dns_stub holds state while performing a 'stub' transfer.
 *	'db' is the zone's 'db' or a new one if this is the initial
 *	transfer.
 */

struct dns_stub {
474
	unsigned int		magic;
David Lawrence's avatar
tabify    
David Lawrence committed
475
	isc_mem_t		*mctx;
476
477
478
	dns_zone_t		*zone;
	dns_db_t		*db;
	dns_dbversion_t		*version;
Mark Andrews's avatar
Mark Andrews committed
479
480
};

481
/*%
482
483
484
 *	Hold load state.
 */
struct dns_load {
485
	unsigned int		magic;
486
487
488
489
490
491
492
	isc_mem_t		*mctx;
	dns_zone_t		*zone;
	dns_db_t		*db;
	isc_time_t		loadtime;
	dns_rdatacallbacks_t	callbacks;
};

493
/*%
494
495
496
 *	Hold forward state.
 */
struct dns_forward {
497
	unsigned int		magic;
498
499
500
501
502
503
504
	isc_mem_t		*mctx;
	dns_zone_t		*zone;
	isc_buffer_t		*msgbuf;
	dns_request_t		*request;
	isc_uint32_t		which;
	isc_sockaddr_t		addr;
	dns_updatecallback_t	callback;
Mark Andrews's avatar
Mark Andrews committed
505
	void			*callback_arg;
506
507
};

508
/*%
509
510
511
 *	Hold IO request state.
 */
struct dns_io {
512
	unsigned int	magic;
513
514
515
516
517
518
519
	dns_zonemgr_t	*zmgr;
	isc_boolean_t	high;
	isc_task_t	*task;
	ISC_LINK(dns_io_t) link;
	isc_event_t	*event;
};

520
521
/*%
 *	Hold state for when we are signing a zone with a new
522
 *	DNSKEY as result of an update.
523
524
 */
struct dns_signing {
525
	unsigned int		magic;
526
527
528
529
	dns_db_t		*db;
	dns_dbiterator_t	*dbiterator;
	dns_secalg_t		algorithm;
	isc_uint16_t		keyid;
530
531
	isc_boolean_t		delete;
	isc_boolean_t		done;
532
533
534
	ISC_LINK(dns_signing_t)	link;
};

535
struct dns_nsec3chain {
536
	unsigned int			magic;
537
538
539
540
541
	dns_db_t			*db;
	dns_dbiterator_t		*dbiterator;
	dns_rdata_nsec3param_t		nsec3param;
	unsigned char			salt[255];
	isc_boolean_t			done;
542
543
544
	isc_boolean_t			seen_nsec;
	isc_boolean_t			delete_nsec;
	isc_boolean_t			save_delete_nsec;
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
	ISC_LINK(dns_nsec3chain_t)	link;
};
/*%<
 * 'dbiterator' contains a iterator for the database.  If we are creating
 * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
 * iterated.
 *
 * 'nsec3param' contains the parameters of the NSEC3 chain being created
 * or removed.
 *
 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
 *
 * 'seen_nsec' will be set to true if, while iterating the zone to create a
 * NSEC3 chain, a NSEC record is seen.
 *
 * 'delete_nsec' will be set to true if, at the completion of the creation
 * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
 * are in the process of deleting the NSEC chain.
 *
 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
 * so it can be recovered in the event of a error.
 */

569
570
571
572
573
574
575
576
577
578
579
580
581
struct dns_keyfetch {
	dns_fixedname_t name;
	dns_rdataset_t keydataset;
	dns_rdataset_t dnskeyset;
	dns_rdataset_t dnskeysigset;
	dns_zone_t *zone;
	dns_db_t *db;
	dns_fetch_t *fetch;
};

#define HOUR 3600
#define DAY (24*HOUR)
#define MONTH (30*DAY)
582

583
584
#define SEND_BUFFER_SIZE 2048

585
static void zone_settimer(dns_zone_t *, isc_time_t *);
586
static void cancel_refresh(dns_zone_t *);
587
static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
588
589
590
			  const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
     ISC_FORMAT_PRINTF(3, 4);
591
static void queue_xfrin(dns_zone_t *zone);
592
593
594
595
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);
Mark Andrews's avatar
Mark Andrews committed
596
597
static void zone_unload(dns_zone_t *zone);
static void zone_expire(dns_zone_t *zone);
598
static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
599
static void zone_idetach(dns_zone_t **zonep);
Mark Andrews's avatar
Mark Andrews committed
600
static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
Brian Wellington's avatar
Brian Wellington committed
601
				   isc_boolean_t dump);
602
603
static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
static inline void zone_detachdb(dns_zone_t *zone);
604
static isc_result_t default_journal(dns_zone_t *zone);
605
static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
606
607
static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
				  isc_time_t loadtime, isc_result_t result);
608
static void zone_needdump(dns_zone_t *zone, unsigned int delay);
609
static void zone_shutdown(isc_task_t *, isc_event_t *);
610
611
612
static void zone_loaddone(void *arg, isc_result_t result);
static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
				   isc_time_t loadtime);
613
614
615
616
static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
617
618
619
620
621
622

#if 0
/* ondestroy example */
static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
#endif

623
static void refresh_callback(isc_task_t *, isc_event_t *);
624
static void stub_callback(isc_task_t *, isc_event_t *);
625
626
static void queue_soa_query(dns_zone_t *zone);
static void soa_query(isc_task_t *, isc_event_t *);
627
628
static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
		     dns_stub_t *stub);
629
630
static int message_count(dns_message_t *msg, dns_section_t section,
			 dns_rdatatype_t type);
631
static void notify_cancel(dns_zone_t *zone);
632
633
static void notify_find_address(dns_notify_t *notify);
static void notify_send(dns_notify_t *notify);
Mark Andrews's avatar
Mark Andrews committed
634
635
636
static isc_result_t notify_createmessage(dns_zone_t *zone,
					 unsigned int flags,
					 dns_message_t **messagep);
Mark Andrews's avatar
Mark Andrews committed
637
static void notify_done(isc_task_t *task, isc_event_t *event);
638
static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
639
static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
640
static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
David Lawrence's avatar
David Lawrence committed
641
642
static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
					     dns_zone_t *zone);
643
static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
644
static void zonemgr_free(dns_zonemgr_t *zmgr);
645
646
647
648
649
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);
static void zonemgr_putio(dns_io_t **iop);
static void zonemgr_cancelio(dns_io_t *io);
650

651
static isc_result_t
652
zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
653
654
		 unsigned int *soacount, isc_uint32_t *serial,
		 isc_uint32_t *refresh, isc_uint32_t *retry,
655
		 isc_uint32_t *expire, isc_uint32_t *minimum,
656
		 unsigned int *errors);
657

658
static void zone_freedbargs(dns_zone_t *zone);
659
static void forward_callback(isc_task_t *task, isc_event_t *event);
660
661
static void zone_saveunique(dns_zone_t *zone, const char *path,
			    const char *templat);
662
static void zone_maintenance(dns_zone_t *zone);
663
static void zone_notify(dns_zone_t *zone, isc_time_t *now);
664
static void dump_done(void *arg, isc_result_t result);
665
666
667
668
static isc_boolean_t dns_zonemgr_unreachable(dns_zonemgr_t *zmgr,
					     isc_sockaddr_t *remote,
					     isc_sockaddr_t *local,
					     isc_time_t *now);
669
static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
670
				     isc_uint16_t keyid, isc_boolean_t delete);
671
672
673
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);
674
static void zone_rekey(dns_zone_t *zone);
Scott Mann's avatar
Scott Mann committed
675
676
static isc_boolean_t delsig_ok(dns_rdata_rrsig_t *rrsig_ptr,
			       dst_key_t **keys, unsigned int nkeys);
677

678
#define ENTER zone_debuglog(zone, me, 1, "enter")
679

680
681
static const unsigned int dbargc_default = 1;
static const char *dbargv_default[] = { "rbt" };
682

683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
#define DNS_ZONE_JITTER_ADD(a, b, c) \
	do { \
		isc_interval_t _i; \
		isc_uint32_t _j; \
		_j = isc_random_jitter((b), (b)/4); \
		isc_interval_set(&_i, _j, 0); \
		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
			dns_zone_log(zone, ISC_LOG_WARNING, \
				     "epoch approaching: upgrade required: " \
				     "now + %s failed", #b); \
			isc_interval_set(&_i, _j/2, 0); \
			(void)isc_time_add((a), &_i, (c)); \
		} \
	} while (0)

#define DNS_ZONE_TIME_ADD(a, b, c) \
	do { \
		isc_interval_t _i; \
		isc_interval_set(&_i, (b), 0); \
		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
			dns_zone_log(zone, ISC_LOG_WARNING, \
				     "epoch approaching: upgrade required: " \
				     "now + %s failed", #b); \
			isc_interval_set(&_i, (b)/2, 0); \
			(void)isc_time_add((a), &_i, (c)); \
		} \
	} while (0)

711
712
713
714
/*%
 * Increment resolver-related statistics counters.  Zone must be locked.
 */
static inline void
715
inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
716
	if (zone->stats != NULL)
717
		isc_stats_increment(zone->stats, counter);
718
719
}

720
721
722
723
/***
 ***	Public functions.
 ***/

724
isc_result_t
725
dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
Andreas Gustafsson's avatar
Andreas Gustafsson committed
726
	isc_result_t result;
727
	dns_zone_t *zone;
728
	isc_time_t now;
729

730
731
732
	REQUIRE(zonep != NULL && *zonep == NULL);
	REQUIRE(mctx != NULL);

733
	TIME_NOW(&now);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
734
	zone = isc_mem_get(mctx, sizeof(*zone));
735
	if (zone == NULL)
736
		return (ISC_R_NOMEMORY);
737

738
739
740
	zone->mctx = NULL;
	isc_mem_attach(mctx, &zone->mctx);

Andreas Gustafsson's avatar
Andreas Gustafsson committed
741
	result = isc_mutex_init(&zone->lock);
742
	if (result != ISC_R_SUCCESS)
743
744
745
		goto free_zone;

	result = ZONEDB_INITLOCK(&zone->dblock);
746
	if (result != ISC_R_SUCCESS)
747
		goto free_mutex;
748
749

	/* XXX MPA check that all elements are initialised */
750
751
752
#ifdef DNS_ZONE_CHECKLOCK
	zone->locked = ISC_FALSE;
#endif
Mark Andrews's avatar
Mark Andrews committed
753
	zone->db = NULL;
754
755
	zone->zmgr = NULL;
	ISC_LINK_INIT(zone, link);
756
757
758
	result = isc_refcount_init(&zone->erefs, 1);	/* Implicit attach. */
	if (result != ISC_R_SUCCESS)
		goto free_dblock;
759
	zone->irefs = 0;
760
	dns_name_init(&zone->origin, NULL);
761
762
763
764
	zone->strnamerd = NULL;
	zone->strname = NULL;
	zone->strrdclass = NULL;
	zone->strviewname = NULL;
765
	zone->masterfile = NULL;
766
	zone->masterformat = dns_masterformat_none;
767
	zone->keydirectory = NULL;
768
	zone->journalsize = -1;
769
	zone->journal = NULL;
770
771
772
	zone->rdclass = dns_rdataclass_none;
	zone->type = dns_zone_none;
	zone->flags = 0;
773
	zone->options = 0;
774
	zone->keyopts = 0;
775
776
	zone->db_argc = 0;
	zone->db_argv = NULL;
777
778
779
	isc_time_settoepoch(&zone->expiretime);
	isc_time_settoepoch(&zone->refreshtime);
	isc_time_settoepoch(&zone->dumptime);
780
	isc_time_settoepoch(&zone->loadtime);
781
	zone->notifytime = now;
782
783
784
	isc_time_settoepoch(&zone->resigntime);
	isc_time_settoepoch(&zone->keywarntime);
	isc_time_settoepoch(&zone->signingtime);
785
	isc_time_settoepoch(&zone->nsec3chaintime);
786
	isc_time_settoepoch(&zone->refreshkeytime);
787
	zone->refreshkeyinterval = 0;
788
	zone->refreshkeycount = 0;
789
790
	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
	zone->retry = DNS_ZONE_DEFAULTRETRY;
791
792
	zone->expire = 0;
	zone->minimum = 0;
793
794
795
796
	zone->maxrefresh = DNS_ZONE_MAXREFRESH;
	zone->minrefresh = DNS_ZONE_MINREFRESH;
	zone->maxretry = DNS_ZONE_MAXRETRY;
	zone->minretry = DNS_ZONE_MINRETRY;
797
	zone->masters = NULL;
Michael Sawyer's avatar
Michael Sawyer committed
798
	zone->masterkeynames = NULL;
799
	zone->mastersok = NULL;
800
801
802
	zone->masterscnt = 0;
	zone->curmaster = 0;
	zone->notify = NULL;
803
	zone->notifykeynames = NULL;
804
	zone->notifytype = dns_notifytype_yes;
805
806
807
	zone->notifycnt = 0;
	zone->task = NULL;
	zone->update_acl = NULL;
808
	zone->forward_acl = NULL;
809
	zone->notify_acl = NULL;
810
	zone->query_acl = NULL;
811
	zone->queryon_acl = NULL;
812
	zone->xfr_acl = NULL;
813
	zone->update_disabled = ISC_FALSE;
814
	zone->zero_no_soa_ttl = ISC_TRUE;
815
	zone->check_names = dns_severity_ignore;
Mark Andrews's avatar
Mark Andrews committed
816
	zone->request = NULL;
817
	zone->lctx = NULL;
818
	zone->readio = NULL;
819
820
	zone->dctx = NULL;
	zone->writeio = NULL;
821
	zone->timer = NULL;
822
823
	zone->idlein = DNS_DEFAULT_IDLEIN;
	zone->idleout = DNS_DEFAULT_IDLEOUT;
Scott Mann's avatar
Scott Mann committed
824
	zone->log_key_expired_timer = 0;
Mark Andrews's avatar
Mark Andrews committed
825
	ISC_LIST_INIT(zone->notifies);
826
827
	isc_sockaddr_any(&zone->notifysrc4);
	isc_sockaddr_any6(&zone->notifysrc6);
828
829
	isc_sockaddr_any(&zone->xfrsource4);
	isc_sockaddr_any6(&zone->xfrsource6);
830
831
	isc_sockaddr_any(&zone->altxfrsource4);
	isc_sockaddr_any6(&zone->altxfrsource6);
832
	zone->xfr = NULL;
833
	zone->tsigkey = NULL;
Mark Andrews's avatar
Mark Andrews committed
834
835
	zone->maxxfrin = MAX_XFER_TIME;
	zone->maxxfrout = MAX_XFER_TIME;
836
	zone->ssutable = NULL;
837
	zone->sigvalidityinterval = 30 * 24 * 3600;
838
	zone->sigresigninginterval = 7 * 24 * 3600;
839
	zone->view = NULL;
840
	zone->acache = NULL;
841
842
843
	zone->checkmx = NULL;
	zone->checksrv = NULL;
	zone->checkns = NULL;
844
845
	ISC_LINK_INIT(zone, statelink);
	zone->statelist = NULL;
846
847
848
	zone->stats = NULL;
	zone->requeststats_on = ISC_FALSE;
	zone->requeststats = NULL;
849
	zone->notifydelay = 5;
850
851
	zone->isself = NULL;
	zone->isselfarg = NULL;
852
	ISC_LIST_INIT(zone->signing);
853
	ISC_LIST_INIT(zone->nsec3chain);
854
855
856
	zone->signatures = 10;
	zone->nodes = 100;
	zone->privatetype = (dns_rdatatype_t)0xffffU;
857
	zone->added = ISC_FALSE;
858
	zone->rpz_zone = ISC_FALSE;
859

860
	zone->magic = ZONE_MAGIC;
861
862

	/* Must be after magic is set. */
863
	result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
864
	if (result != ISC_R_SUCCESS)
865
		goto free_erefs;
Mark Andrews's avatar
Mark Andrews committed
866

867
868
869
	ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
		       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
		       NULL, NULL);
870
	*zonep = zone;
871
	return (ISC_R_SUCCESS);
872

873
874
875
876
 free_erefs:
	isc_refcount_decrement(&zone->erefs, NULL);
	isc_refcount_destroy(&zone->erefs);

877
878
879
 free_dblock:
	ZONEDB_DESTROYLOCK(&zone->dblock);

880
 free_mutex:
881
	DESTROYLOCK(&zone->lock);
882
883

 free_zone:
884
885
	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
	return (result);
886
887
}

888
889
890
891
/*
 * Free a zone.  Because we require that there be no more
 * outstanding events or references, no locking is necessary.
 */
892
893
static void
zone_free(dns_zone_t *zone) {
Mark Andrews's avatar
Mark Andrews committed
894
	isc_mem_t *mctx = NULL;
895
	dns_signing_t *signing;
896
	dns_nsec3chain_t *nsec3chain;
897

898
	REQUIRE(DNS_ZONE_VALID(zone));
899
	REQUIRE(isc_refcount_current(&zone->erefs) == 0);
900
	REQUIRE(zone->irefs == 0);
901
	REQUIRE(!LOCKED_ZONE(zone));
902
	REQUIRE(zone->timer == NULL);
903

904
905
906
	/*
	 * Managed objects.  Order is important.
	 */
907
908
	if (zone->request != NULL)
		dns_request_destroy(&zone->request); /* XXXMPA */
909
	INSIST(zone->readio == NULL);
910
	INSIST(zone->statelist == NULL);
911
	INSIST(zone->writeio == NULL);
912

913
	if (zone->task != NULL)
914
		isc_task_detach(&zone->task);
915
	if (zone->zmgr != NULL)
916
		dns_zonemgr_releasezone(zone->zmgr, zone);
917

918
	/* Unmanaged objects */
919
920
921
922
923
924
925
926
	for (signing = ISC_LIST_HEAD(zone->signing);
	     signing != NULL;
	     signing = ISC_LIST_HEAD(zone->signing)) {
		ISC_LIST_UNLINK(zone->signing, signing, link);
		dns_db_detach(&signing->db);
		dns_dbiterator_destroy(&signing->dbiterator);
		isc_mem_put(zone->mctx, signing, sizeof *signing);
	}
927
928
929
930
931
932
933
934
	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
	     nsec3chain != NULL;
	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
		dns_db_detach(&nsec3chain->db);
		dns_dbiterator_destroy(&nsec3chain->dbiterator);
		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
	}
935
936
937
	if (zone->masterfile != NULL)
		isc_mem_free(zone->mctx, zone->masterfile);
	zone->masterfile = NULL;
938
939
940
	if (zone->keydirectory != NULL)
		isc_mem_free(zone->mctx, zone->keydirectory);
	zone->keydirectory = NULL;
941
	zone->journalsize = -1;
942
943
944
	if (zone->journal != NULL)
		isc_mem_free(zone->mctx, zone->journal);
	zone->journal = NULL;
945
	if (zone->stats != NULL)
946
		isc_stats_detach(&zone->stats);
947
	if (zone->requeststats != NULL)
948
		isc_stats_detach(&zone->requeststats);
Mark Andrews's avatar
Mark Andrews committed
949
	if (zone->db != NULL)
950
951
952
		zone_detachdb(zone);
	if (zone->acache != NULL)
		dns_acache_detach(&zone->acache);
953
	zone_freedbargs(zone);
954
955
956
957
	RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
		      == ISC_R_SUCCESS);
	RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
		      == ISC_R_SUCCESS);
958
	zone->check_names = dns_severity_ignore;
959
	if (zone->update_acl != NULL)
960
		dns_acl_detach(&zone->update_acl);
961
962
	if (zone->forward_acl != NULL)
		dns_acl_detach(&zone->forward_acl);
963
964
	if (zone->notify_acl != NULL)
		dns_acl_detach(&zone->notify_acl);
965
	if (zone->query_acl != NULL)
966
		dns_acl_detach(&zone->query_acl);
967
968
	if (zone->queryon_acl != NULL)
		dns_acl_detach(&zone->queryon_acl);
969
	if (zone->xfr_acl != NULL)
970
		dns_acl_detach(&zone->xfr_acl);
971
972
	if (dns_name_dynamic(&zone->origin))
		dns_name_free(&zone->origin, zone->mctx);
973
974
975
976
977
978
979
980
	if (zone->strnamerd != NULL)
		isc_mem_free(zone->mctx, zone->strnamerd);
	if (zone->strname != NULL)
		isc_mem_free(zone->mctx, zone->strname);
	if (zone->strrdclass != NULL)
		isc_mem_free(zone->mctx, zone->strrdclass);
	if (zone->strviewname != NULL)
		isc_mem_free(zone->mctx, zone->strviewname);
981
	if (zone->ssutable != NULL)
982
		dns_ssutable_detach(&zone->ssutable);
983
984

	/* last stuff */
985
	ZONEDB_DESTROYLOCK(&zone->dblock);
986
	DESTROYLOCK(&zone->lock);
987
	isc_refcount_destroy(&zone->erefs);
988
	zone->magic = 0;
Mark Andrews's avatar
Mark Andrews committed
989
	mctx = zone->mctx;
Andreas Gustafsson's avatar
Andreas Gustafsson committed
990
	isc_mem_put(mctx, zone, sizeof(*zone));
Mark Andrews's avatar
Mark Andrews committed
991
	isc_mem_detach(&mctx);
992
993
994