vendor/BIND: Update to 9.5.2-P3
[dragonfly.git] / contrib / bind / lib / dns / zone.c
blob39c4a64bc7e251b1fa46f2aa5b1dd519e7dd5b5d
1 /*
2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
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.
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.
18 /* $Id: zone.c,v 1.470.12.12 2009/07/11 04:28:14 marka Exp $ */
20 /*! \file */
22 #include <config.h>
23 #include <errno.h>
25 #include <isc/file.h>
26 #include <isc/mutex.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/strerror.h>
34 #include <isc/stats.h>
35 #include <isc/string.h>
36 #include <isc/taskpool.h>
37 #include <isc/timer.h>
38 #include <isc/util.h>
40 #include <dns/acache.h>
41 #include <dns/acl.h>
42 #include <dns/adb.h>
43 #include <dns/callbacks.h>
44 #include <dns/db.h>
45 #include <dns/dbiterator.h>
46 #include <dns/events.h>
47 #include <dns/journal.h>
48 #include <dns/log.h>
49 #include <dns/master.h>
50 #include <dns/masterdump.h>
51 #include <dns/message.h>
52 #include <dns/name.h>
53 #include <dns/peer.h>
54 #include <dns/rcode.h>
55 #include <dns/rdataclass.h>
56 #include <dns/rdatalist.h>
57 #include <dns/rdataset.h>
58 #include <dns/rdatastruct.h>
59 #include <dns/rdatatype.h>
60 #include <dns/request.h>
61 #include <dns/resolver.h>
62 #include <dns/result.h>
63 #include <dns/stats.h>
64 #include <dns/ssu.h>
65 #include <dns/tsig.h>
66 #include <dns/xfrin.h>
67 #include <dns/zone.h>
69 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
70 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
72 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
73 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
75 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
76 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
78 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
79 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
81 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
82 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
84 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
85 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
87 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
88 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
90 /*%
91 * Ensure 'a' is at least 'min' but not more than 'max'.
93 #define RANGE(a, min, max) \
94 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
97 * Default values.
99 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
100 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
101 #define MAX_XFER_TIME (2*3600) /*%< Documented default is 2 hours */
103 #ifndef DNS_MAX_EXPIRE
104 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
105 #endif
107 #ifndef DNS_DUMP_DELAY
108 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
109 #endif
111 typedef struct dns_notify dns_notify_t;
112 typedef struct dns_stub dns_stub_t;
113 typedef struct dns_load dns_load_t;
114 typedef struct dns_forward dns_forward_t;
115 typedef struct dns_io dns_io_t;
116 typedef ISC_LIST(dns_io_t) dns_iolist_t;
118 #define DNS_ZONE_CHECKLOCK
119 #ifdef DNS_ZONE_CHECKLOCK
120 #define LOCK_ZONE(z) \
121 do { LOCK(&(z)->lock); \
122 INSIST((z)->locked == ISC_FALSE); \
123 (z)->locked = ISC_TRUE; \
124 } while (0)
125 #define UNLOCK_ZONE(z) \
126 do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
127 #define LOCKED_ZONE(z) ((z)->locked)
128 #else
129 #define LOCK_ZONE(z) LOCK(&(z)->lock)
130 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
131 #define LOCKED_ZONE(z) ISC_TRUE
132 #endif
134 #ifdef ISC_RWLOCK_USEATOMIC
135 #define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
136 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
137 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
138 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
139 #else
140 #define ZONEDB_INITLOCK(l) isc_mutex_init(l)
141 #define ZONEDB_DESTROYLOCK(l) DESTROYLOCK(l)
142 #define ZONEDB_LOCK(l, t) LOCK(l)
143 #define ZONEDB_UNLOCK(l, t) UNLOCK(l)
144 #endif
146 struct dns_zone {
147 /* Unlocked */
148 unsigned int magic;
149 isc_mutex_t lock;
150 #ifdef DNS_ZONE_CHECKLOCK
151 isc_boolean_t locked;
152 #endif
153 isc_mem_t *mctx;
154 isc_refcount_t erefs;
156 #ifdef ISC_RWLOCK_USEATOMIC
157 isc_rwlock_t dblock;
158 #else
159 isc_mutex_t dblock;
160 #endif
161 dns_db_t *db; /* Locked by dblock */
163 /* Locked */
164 dns_zonemgr_t *zmgr;
165 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
166 isc_timer_t *timer;
167 unsigned int irefs;
168 dns_name_t origin;
169 char *masterfile;
170 dns_masterformat_t masterformat;
171 char *journal;
172 isc_int32_t journalsize;
173 dns_rdataclass_t rdclass;
174 dns_zonetype_t type;
175 unsigned int flags;
176 unsigned int options;
177 unsigned int db_argc;
178 char **db_argv;
179 isc_time_t expiretime;
180 isc_time_t refreshtime;
181 isc_time_t dumptime;
182 isc_time_t loadtime;
183 isc_time_t notifytime;
184 isc_uint32_t serial;
185 isc_uint32_t refresh;
186 isc_uint32_t retry;
187 isc_uint32_t expire;
188 isc_uint32_t minimum;
189 char *keydirectory;
191 isc_uint32_t maxrefresh;
192 isc_uint32_t minrefresh;
193 isc_uint32_t maxretry;
194 isc_uint32_t minretry;
196 isc_sockaddr_t *masters;
197 dns_name_t **masterkeynames;
198 isc_boolean_t *mastersok;
199 unsigned int masterscnt;
200 unsigned int curmaster;
201 isc_sockaddr_t masteraddr;
202 dns_notifytype_t notifytype;
203 isc_sockaddr_t *notify;
204 unsigned int notifycnt;
205 isc_sockaddr_t notifyfrom;
206 isc_task_t *task;
207 isc_sockaddr_t notifysrc4;
208 isc_sockaddr_t notifysrc6;
209 isc_sockaddr_t xfrsource4;
210 isc_sockaddr_t xfrsource6;
211 isc_sockaddr_t altxfrsource4;
212 isc_sockaddr_t altxfrsource6;
213 isc_sockaddr_t sourceaddr;
214 dns_xfrin_ctx_t *xfr; /* task locked */
215 dns_tsigkey_t *tsigkey; /* key used for xfr */
216 /* Access Control Lists */
217 dns_acl_t *update_acl;
218 dns_acl_t *forward_acl;
219 dns_acl_t *notify_acl;
220 dns_acl_t *query_acl;
221 dns_acl_t *queryon_acl;
222 dns_acl_t *xfr_acl;
223 isc_boolean_t update_disabled;
224 isc_boolean_t zero_no_soa_ttl;
225 dns_severity_t check_names;
226 ISC_LIST(dns_notify_t) notifies;
227 dns_request_t *request;
228 dns_loadctx_t *lctx;
229 dns_io_t *readio;
230 dns_dumpctx_t *dctx;
231 dns_io_t *writeio;
232 isc_uint32_t maxxfrin;
233 isc_uint32_t maxxfrout;
234 isc_uint32_t idlein;
235 isc_uint32_t idleout;
236 isc_event_t ctlevent;
237 dns_ssutable_t *ssutable;
238 isc_uint32_t sigvalidityinterval;
239 dns_view_t *view;
240 dns_acache_t *acache;
241 dns_checkmxfunc_t checkmx;
242 dns_checksrvfunc_t checksrv;
243 dns_checknsfunc_t checkns;
245 * Zones in certain states such as "waiting for zone transfer"
246 * or "zone transfer in progress" are kept on per-state linked lists
247 * in the zone manager using the 'statelink' field. The 'statelist'
248 * field points at the list the zone is currently on. It the zone
249 * is not on any such list, statelist is NULL.
251 ISC_LINK(dns_zone_t) statelink;
252 dns_zonelist_t *statelist;
254 * Statistics counters about zone management.
256 isc_stats_t *stats;
258 * Optional per-zone statistics counters. Counted outside of this
259 * module.
261 isc_boolean_t requeststats_on;
262 isc_stats_t *requeststats;
263 isc_uint32_t notifydelay;
264 dns_isselffunc_t isself;
265 void *isselfarg;
267 char * strnamerd;
268 char * strname;
269 char * strrdclass;
270 char * strviewname;
273 * Serial number for deferred journal compaction.
275 isc_uint32_t compact_serial;
278 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
279 #define DNS_ZONE_SETFLAG(z,f) do { \
280 INSIST(LOCKED_ZONE(z)); \
281 (z)->flags |= (f); \
282 } while (0)
283 #define DNS_ZONE_CLRFLAG(z,f) do { \
284 INSIST(LOCKED_ZONE(z)); \
285 (z)->flags &= ~(f); \
286 } while (0)
287 /* XXX MPA these may need to go back into zone.h */
288 #define DNS_ZONEFLG_REFRESH 0x00000001U /*%< refresh check in progress */
289 #define DNS_ZONEFLG_NEEDDUMP 0x00000002U /*%< zone need consolidation */
290 #define DNS_ZONEFLG_USEVC 0x00000004U /*%< use tcp for refresh query */
291 #define DNS_ZONEFLG_DUMPING 0x00000008U /*%< a dump is in progress */
292 #define DNS_ZONEFLG_HASINCLUDE 0x00000010U /*%< $INCLUDE in zone file */
293 #define DNS_ZONEFLG_LOADED 0x00000020U /*%< database has loaded */
294 #define DNS_ZONEFLG_EXITING 0x00000040U /*%< zone is being destroyed */
295 #define DNS_ZONEFLG_EXPIRED 0x00000080U /*%< zone has expired */
296 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U /*%< refresh check needed */
297 #define DNS_ZONEFLG_UPTODATE 0x00000200U /*%< zone contents are
298 * uptodate */
299 #define DNS_ZONEFLG_NEEDNOTIFY 0x00000400U /*%< need to send out notify
300 * messages */
301 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U /*%< generate a journal diff on
302 * reload */
303 #define DNS_ZONEFLG_NOMASTERS 0x00001000U /*%< an attempt to refresh a
304 * zone with no masters
305 * occurred */
306 #define DNS_ZONEFLG_LOADING 0x00002000U /*%< load from disk in progress*/
307 #define DNS_ZONEFLG_HAVETIMERS 0x00004000U /*%< timer values have been set
308 * from SOA (if not set, we
309 * are still using
310 * default timer values) */
311 #define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */
312 #define DNS_ZONEFLG_NOREFRESH 0x00010000U
313 #define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
314 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
315 #define DNS_ZONEFLG_SHUTDOWN 0x00080000U
316 #define DNS_ZONEFLAG_NOIXFR 0x00100000U /*%< IXFR failed, force AXFR */
317 #define DNS_ZONEFLG_FLUSH 0x00200000U
318 #define DNS_ZONEFLG_NOEDNS 0x00400000U
319 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
320 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
321 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
322 #define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */
323 #define DNS_ZONEFLG_THAW 0x08000000U
325 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
327 /* Flags for zone_load() */
328 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
329 #define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful
330 load. */
332 #define UNREACH_CHACHE_SIZE 10U
333 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
335 struct dns_unreachable {
336 isc_sockaddr_t remote;
337 isc_sockaddr_t local;
338 isc_uint32_t expire;
339 isc_uint32_t last;
342 struct dns_zonemgr {
343 unsigned int magic;
344 isc_mem_t * mctx;
345 int refs; /* Locked by rwlock */
346 isc_taskmgr_t * taskmgr;
347 isc_timermgr_t * timermgr;
348 isc_socketmgr_t * socketmgr;
349 isc_taskpool_t * zonetasks;
350 isc_task_t * task;
351 isc_ratelimiter_t * rl;
352 isc_rwlock_t rwlock;
353 isc_mutex_t iolock;
355 /* Locked by rwlock. */
356 dns_zonelist_t zones;
357 dns_zonelist_t waiting_for_xfrin;
358 dns_zonelist_t xfrin_in_progress;
360 /* Configuration data. */
361 isc_uint32_t transfersin;
362 isc_uint32_t transfersperns;
363 unsigned int serialqueryrate;
365 /* Locked by iolock */
366 isc_uint32_t iolimit;
367 isc_uint32_t ioactive;
368 dns_iolist_t high;
369 dns_iolist_t low;
371 /* Locked by rwlock. */
372 /* LRU cache */
373 struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
377 * Hold notify state.
379 struct dns_notify {
380 unsigned int magic;
381 unsigned int flags;
382 isc_mem_t *mctx;
383 dns_zone_t *zone;
384 dns_adbfind_t *find;
385 dns_request_t *request;
386 dns_name_t ns;
387 isc_sockaddr_t dst;
388 ISC_LINK(dns_notify_t) link;
391 #define DNS_NOTIFY_NOSOA 0x0001U
394 * dns_stub holds state while performing a 'stub' transfer.
395 * 'db' is the zone's 'db' or a new one if this is the initial
396 * transfer.
399 struct dns_stub {
400 unsigned int magic;
401 isc_mem_t *mctx;
402 dns_zone_t *zone;
403 dns_db_t *db;
404 dns_dbversion_t *version;
408 * Hold load state.
410 struct dns_load {
411 unsigned int magic;
412 isc_mem_t *mctx;
413 dns_zone_t *zone;
414 dns_db_t *db;
415 isc_time_t loadtime;
416 dns_rdatacallbacks_t callbacks;
420 * Hold forward state.
422 struct dns_forward {
423 unsigned int magic;
424 isc_mem_t *mctx;
425 dns_zone_t *zone;
426 isc_buffer_t *msgbuf;
427 dns_request_t *request;
428 isc_uint32_t which;
429 isc_sockaddr_t addr;
430 dns_updatecallback_t callback;
431 void *callback_arg;
435 * Hold IO request state.
437 struct dns_io {
438 unsigned int magic;
439 dns_zonemgr_t *zmgr;
440 isc_boolean_t high;
441 isc_task_t *task;
442 ISC_LINK(dns_io_t) link;
443 isc_event_t *event;
446 #define SEND_BUFFER_SIZE 2048
448 static void zone_settimer(dns_zone_t *, isc_time_t *);
449 static void cancel_refresh(dns_zone_t *);
450 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
451 const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
452 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
453 ISC_FORMAT_PRINTF(3, 4);
454 static void queue_xfrin(dns_zone_t *zone);
455 static void zone_unload(dns_zone_t *zone);
456 static void zone_expire(dns_zone_t *zone);
457 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
458 static void zone_idetach(dns_zone_t **zonep);
459 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
460 isc_boolean_t dump);
461 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
462 static inline void zone_detachdb(dns_zone_t *zone);
463 static isc_result_t default_journal(dns_zone_t *zone);
464 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
465 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
466 isc_time_t loadtime, isc_result_t result);
467 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
468 static void zone_shutdown(isc_task_t *, isc_event_t *);
469 static void zone_loaddone(void *arg, isc_result_t result);
470 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
471 isc_time_t loadtime);
472 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
473 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
474 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
475 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
477 #if 0
478 /* ondestroy example */
479 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
480 #endif
482 static void refresh_callback(isc_task_t *, isc_event_t *);
483 static void stub_callback(isc_task_t *, isc_event_t *);
484 static void queue_soa_query(dns_zone_t *zone);
485 static void soa_query(isc_task_t *, isc_event_t *);
486 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
487 dns_stub_t *stub);
488 static int message_count(dns_message_t *msg, dns_section_t section,
489 dns_rdatatype_t type);
490 static void notify_cancel(dns_zone_t *zone);
491 static void notify_find_address(dns_notify_t *notify);
492 static void notify_send(dns_notify_t *notify);
493 static isc_result_t notify_createmessage(dns_zone_t *zone,
494 unsigned int flags,
495 dns_message_t **messagep);
496 static void notify_done(isc_task_t *task, isc_event_t *event);
497 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
498 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
499 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
500 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
501 dns_zone_t *zone);
502 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
503 static void zonemgr_free(dns_zonemgr_t *zmgr);
504 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
505 isc_task_t *task, isc_taskaction_t action,
506 void *arg, dns_io_t **iop);
507 static void zonemgr_putio(dns_io_t **iop);
508 static void zonemgr_cancelio(dns_io_t *io);
510 static isc_result_t
511 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
512 unsigned int *soacount, isc_uint32_t *serial,
513 isc_uint32_t *refresh, isc_uint32_t *retry,
514 isc_uint32_t *expire, isc_uint32_t *minimum,
515 unsigned int *errors);
517 static void zone_freedbargs(dns_zone_t *zone);
518 static void forward_callback(isc_task_t *task, isc_event_t *event);
519 static void zone_saveunique(dns_zone_t *zone, const char *path,
520 const char *templat);
521 static void zone_maintenance(dns_zone_t *zone);
522 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
523 static void dump_done(void *arg, isc_result_t result);
524 static isc_boolean_t dns_zonemgr_unreachable(dns_zonemgr_t *zmgr,
525 isc_sockaddr_t *remote,
526 isc_sockaddr_t *local,
527 isc_time_t *now);
529 #define ENTER zone_debuglog(zone, me, 1, "enter")
531 static const unsigned int dbargc_default = 1;
532 static const char *dbargv_default[] = { "rbt" };
534 #define DNS_ZONE_JITTER_ADD(a, b, c) \
535 do { \
536 isc_interval_t _i; \
537 isc_uint32_t _j; \
538 _j = isc_random_jitter((b), (b)/4); \
539 isc_interval_set(&_i, _j, 0); \
540 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
541 dns_zone_log(zone, ISC_LOG_WARNING, \
542 "epoch approaching: upgrade required: " \
543 "now + %s failed", #b); \
544 isc_interval_set(&_i, _j/2, 0); \
545 (void)isc_time_add((a), &_i, (c)); \
547 } while (0)
549 #define DNS_ZONE_TIME_ADD(a, b, c) \
550 do { \
551 isc_interval_t _i; \
552 isc_interval_set(&_i, (b), 0); \
553 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
554 dns_zone_log(zone, ISC_LOG_WARNING, \
555 "epoch approaching: upgrade required: " \
556 "now + %s failed", #b); \
557 isc_interval_set(&_i, (b)/2, 0); \
558 (void)isc_time_add((a), &_i, (c)); \
560 } while (0)
563 * Increment resolver-related statistics counters. Zone must be locked.
565 static inline void
566 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
567 if (zone->stats != NULL)
568 isc_stats_increment(zone->stats, counter);
571 /***
572 *** Public functions.
573 ***/
575 isc_result_t
576 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
577 isc_result_t result;
578 dns_zone_t *zone;
579 isc_time_t now;
581 REQUIRE(zonep != NULL && *zonep == NULL);
582 REQUIRE(mctx != NULL);
584 TIME_NOW(&now);
585 zone = isc_mem_get(mctx, sizeof(*zone));
586 if (zone == NULL)
587 return (ISC_R_NOMEMORY);
589 zone->mctx = NULL;
590 isc_mem_attach(mctx, &zone->mctx);
592 result = isc_mutex_init(&zone->lock);
593 if (result != ISC_R_SUCCESS)
594 goto free_zone;
596 result = ZONEDB_INITLOCK(&zone->dblock);
597 if (result != ISC_R_SUCCESS)
598 goto free_mutex;
600 /* XXX MPA check that all elements are initialised */
601 #ifdef DNS_ZONE_CHECKLOCK
602 zone->locked = ISC_FALSE;
603 #endif
604 zone->db = NULL;
605 zone->zmgr = NULL;
606 ISC_LINK_INIT(zone, link);
607 result = isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
608 if (result != ISC_R_SUCCESS)
609 goto free_dblock;
610 zone->irefs = 0;
611 dns_name_init(&zone->origin, NULL);
612 zone->strnamerd = NULL;
613 zone->strname = NULL;
614 zone->strrdclass = NULL;
615 zone->strviewname = NULL;
616 zone->masterfile = NULL;
617 zone->masterformat = dns_masterformat_none;
618 zone->keydirectory = NULL;
619 zone->journalsize = -1;
620 zone->journal = NULL;
621 zone->rdclass = dns_rdataclass_none;
622 zone->type = dns_zone_none;
623 zone->flags = 0;
624 zone->options = 0;
625 zone->db_argc = 0;
626 zone->db_argv = NULL;
627 isc_time_settoepoch(&zone->expiretime);
628 isc_time_settoepoch(&zone->refreshtime);
629 isc_time_settoepoch(&zone->dumptime);
630 isc_time_settoepoch(&zone->loadtime);
631 zone->notifytime = now;
632 zone->serial = 0;
633 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
634 zone->retry = DNS_ZONE_DEFAULTRETRY;
635 zone->expire = 0;
636 zone->minimum = 0;
637 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
638 zone->minrefresh = DNS_ZONE_MINREFRESH;
639 zone->maxretry = DNS_ZONE_MAXRETRY;
640 zone->minretry = DNS_ZONE_MINRETRY;
641 zone->masters = NULL;
642 zone->masterkeynames = NULL;
643 zone->mastersok = NULL;
644 zone->masterscnt = 0;
645 zone->curmaster = 0;
646 zone->notify = NULL;
647 zone->notifytype = dns_notifytype_yes;
648 zone->notifycnt = 0;
649 zone->task = NULL;
650 zone->update_acl = NULL;
651 zone->forward_acl = NULL;
652 zone->notify_acl = NULL;
653 zone->query_acl = NULL;
654 zone->queryon_acl = NULL;
655 zone->xfr_acl = NULL;
656 zone->update_disabled = ISC_FALSE;
657 zone->zero_no_soa_ttl = ISC_TRUE;
658 zone->check_names = dns_severity_ignore;
659 zone->request = NULL;
660 zone->lctx = NULL;
661 zone->readio = NULL;
662 zone->dctx = NULL;
663 zone->writeio = NULL;
664 zone->timer = NULL;
665 zone->idlein = DNS_DEFAULT_IDLEIN;
666 zone->idleout = DNS_DEFAULT_IDLEOUT;
667 ISC_LIST_INIT(zone->notifies);
668 isc_sockaddr_any(&zone->notifysrc4);
669 isc_sockaddr_any6(&zone->notifysrc6);
670 isc_sockaddr_any(&zone->xfrsource4);
671 isc_sockaddr_any6(&zone->xfrsource6);
672 isc_sockaddr_any(&zone->altxfrsource4);
673 isc_sockaddr_any6(&zone->altxfrsource6);
674 zone->xfr = NULL;
675 zone->tsigkey = NULL;
676 zone->maxxfrin = MAX_XFER_TIME;
677 zone->maxxfrout = MAX_XFER_TIME;
678 zone->ssutable = NULL;
679 zone->sigvalidityinterval = 30 * 24 * 3600;
680 zone->view = NULL;
681 zone->acache = NULL;
682 zone->checkmx = NULL;
683 zone->checksrv = NULL;
684 zone->checkns = NULL;
685 ISC_LINK_INIT(zone, statelink);
686 zone->statelist = NULL;
687 zone->stats = NULL;
688 zone->requeststats_on = ISC_FALSE;
689 zone->requeststats = NULL;
690 zone->notifydelay = 5;
691 zone->isself = NULL;
692 zone->isselfarg = NULL;
694 zone->magic = ZONE_MAGIC;
696 /* Must be after magic is set. */
697 result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
698 if (result != ISC_R_SUCCESS)
699 goto free_erefs;
701 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
702 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
703 NULL, NULL);
704 *zonep = zone;
705 return (ISC_R_SUCCESS);
707 free_erefs:
708 isc_refcount_decrement(&zone->erefs, NULL);
709 isc_refcount_destroy(&zone->erefs);
711 free_dblock:
712 ZONEDB_DESTROYLOCK(&zone->dblock);
714 free_mutex:
715 DESTROYLOCK(&zone->lock);
717 free_zone:
718 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
719 return (result);
723 * Free a zone. Because we require that there be no more
724 * outstanding events or references, no locking is necessary.
726 static void
727 zone_free(dns_zone_t *zone) {
728 isc_mem_t *mctx = NULL;
730 REQUIRE(DNS_ZONE_VALID(zone));
731 REQUIRE(isc_refcount_current(&zone->erefs) == 0);
732 REQUIRE(zone->irefs == 0);
733 REQUIRE(!LOCKED_ZONE(zone));
734 REQUIRE(zone->timer == NULL);
737 * Managed objects. Order is important.
739 if (zone->request != NULL)
740 dns_request_destroy(&zone->request); /* XXXMPA */
741 INSIST(zone->readio == NULL);
742 INSIST(zone->statelist == NULL);
743 INSIST(zone->writeio == NULL);
745 if (zone->task != NULL)
746 isc_task_detach(&zone->task);
747 if (zone->zmgr != NULL)
748 dns_zonemgr_releasezone(zone->zmgr, zone);
750 /* Unmanaged objects */
751 if (zone->masterfile != NULL)
752 isc_mem_free(zone->mctx, zone->masterfile);
753 zone->masterfile = NULL;
754 if (zone->keydirectory != NULL)
755 isc_mem_free(zone->mctx, zone->keydirectory);
756 zone->keydirectory = NULL;
757 zone->journalsize = -1;
758 if (zone->journal != NULL)
759 isc_mem_free(zone->mctx, zone->journal);
760 zone->journal = NULL;
761 if (zone->stats != NULL)
762 isc_stats_detach(&zone->stats);
763 if (zone->requeststats != NULL)
764 isc_stats_detach(&zone->requeststats);
765 if (zone->db != NULL)
766 zone_detachdb(zone);
767 if (zone->acache != NULL)
768 dns_acache_detach(&zone->acache);
769 zone_freedbargs(zone);
770 RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
771 == ISC_R_SUCCESS);
772 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
773 == ISC_R_SUCCESS);
774 zone->check_names = dns_severity_ignore;
775 if (zone->update_acl != NULL)
776 dns_acl_detach(&zone->update_acl);
777 if (zone->forward_acl != NULL)
778 dns_acl_detach(&zone->forward_acl);
779 if (zone->notify_acl != NULL)
780 dns_acl_detach(&zone->notify_acl);
781 if (zone->query_acl != NULL)
782 dns_acl_detach(&zone->query_acl);
783 if (zone->queryon_acl != NULL)
784 dns_acl_detach(&zone->queryon_acl);
785 if (zone->xfr_acl != NULL)
786 dns_acl_detach(&zone->xfr_acl);
787 if (dns_name_dynamic(&zone->origin))
788 dns_name_free(&zone->origin, zone->mctx);
789 if (zone->strnamerd != NULL)
790 isc_mem_free(zone->mctx, zone->strnamerd);
791 if (zone->strname != NULL)
792 isc_mem_free(zone->mctx, zone->strname);
793 if (zone->strrdclass != NULL)
794 isc_mem_free(zone->mctx, zone->strrdclass);
795 if (zone->strviewname != NULL)
796 isc_mem_free(zone->mctx, zone->strviewname);
797 if (zone->ssutable != NULL)
798 dns_ssutable_detach(&zone->ssutable);
800 /* last stuff */
801 ZONEDB_DESTROYLOCK(&zone->dblock);
802 DESTROYLOCK(&zone->lock);
803 isc_refcount_destroy(&zone->erefs);
804 zone->magic = 0;
805 mctx = zone->mctx;
806 isc_mem_put(mctx, zone, sizeof(*zone));
807 isc_mem_detach(&mctx);
811 * Single shot.
813 void
814 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
815 char namebuf[1024];
817 REQUIRE(DNS_ZONE_VALID(zone));
818 REQUIRE(rdclass != dns_rdataclass_none);
821 * Test and set.
823 LOCK_ZONE(zone);
824 REQUIRE(zone->rdclass == dns_rdataclass_none ||
825 zone->rdclass == rdclass);
826 zone->rdclass = rdclass;
828 if (zone->strnamerd != NULL)
829 isc_mem_free(zone->mctx, zone->strnamerd);
830 if (zone->strrdclass != NULL)
831 isc_mem_free(zone->mctx, zone->strrdclass);
833 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
834 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
835 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
836 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
838 UNLOCK_ZONE(zone);
841 dns_rdataclass_t
842 dns_zone_getclass(dns_zone_t *zone) {
843 REQUIRE(DNS_ZONE_VALID(zone));
845 return (zone->rdclass);
848 void
849 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
850 REQUIRE(DNS_ZONE_VALID(zone));
852 LOCK_ZONE(zone);
853 zone->notifytype = notifytype;
854 UNLOCK_ZONE(zone);
857 isc_uint32_t
858 dns_zone_getserial(dns_zone_t *zone) {
859 isc_uint32_t serial;
861 REQUIRE(DNS_ZONE_VALID(zone));
863 LOCK_ZONE(zone);
864 serial = zone->serial;
865 UNLOCK_ZONE(zone);
867 return (serial);
871 * Single shot.
873 void
874 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
876 REQUIRE(DNS_ZONE_VALID(zone));
877 REQUIRE(type != dns_zone_none);
880 * Test and set.
882 LOCK_ZONE(zone);
883 REQUIRE(zone->type == dns_zone_none || zone->type == type);
884 zone->type = type;
885 UNLOCK_ZONE(zone);
888 static void
889 zone_freedbargs(dns_zone_t *zone) {
890 unsigned int i;
892 /* Free the old database argument list. */
893 if (zone->db_argv != NULL) {
894 for (i = 0; i < zone->db_argc; i++)
895 isc_mem_free(zone->mctx, zone->db_argv[i]);
896 isc_mem_put(zone->mctx, zone->db_argv,
897 zone->db_argc * sizeof(*zone->db_argv));
899 zone->db_argc = 0;
900 zone->db_argv = NULL;
903 isc_result_t
904 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
905 size_t size = 0;
906 unsigned int i;
907 isc_result_t result = ISC_R_SUCCESS;
908 void *mem;
909 char **tmp, *tmp2;
911 REQUIRE(DNS_ZONE_VALID(zone));
912 REQUIRE(argv != NULL && *argv == NULL);
914 LOCK_ZONE(zone);
915 size = (zone->db_argc + 1) * sizeof(char *);
916 for (i = 0; i < zone->db_argc; i++)
917 size += strlen(zone->db_argv[i]) + 1;
918 mem = isc_mem_allocate(mctx, size);
919 if (mem != NULL) {
920 tmp = mem;
921 tmp2 = mem;
922 tmp2 += (zone->db_argc + 1) * sizeof(char *);
923 for (i = 0; i < zone->db_argc; i++) {
924 *tmp++ = tmp2;
925 strcpy(tmp2, zone->db_argv[i]);
926 tmp2 += strlen(tmp2) + 1;
928 *tmp = NULL;
929 } else
930 result = ISC_R_NOMEMORY;
931 UNLOCK_ZONE(zone);
932 *argv = mem;
933 return (result);
936 isc_result_t
937 dns_zone_setdbtype(dns_zone_t *zone,
938 unsigned int dbargc, const char * const *dbargv) {
939 isc_result_t result = ISC_R_SUCCESS;
940 char **new = NULL;
941 unsigned int i;
943 REQUIRE(DNS_ZONE_VALID(zone));
944 REQUIRE(dbargc >= 1);
945 REQUIRE(dbargv != NULL);
947 LOCK_ZONE(zone);
949 /* Set up a new database argument list. */
950 new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
951 if (new == NULL)
952 goto nomem;
953 for (i = 0; i < dbargc; i++)
954 new[i] = NULL;
955 for (i = 0; i < dbargc; i++) {
956 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
957 if (new[i] == NULL)
958 goto nomem;
961 /* Free the old list. */
962 zone_freedbargs(zone);
964 zone->db_argc = dbargc;
965 zone->db_argv = new;
966 result = ISC_R_SUCCESS;
967 goto unlock;
969 nomem:
970 if (new != NULL) {
971 for (i = 0; i < dbargc; i++)
972 if (new[i] != NULL)
973 isc_mem_free(zone->mctx, new[i]);
974 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
976 result = ISC_R_NOMEMORY;
978 unlock:
979 UNLOCK_ZONE(zone);
980 return (result);
983 void
984 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
985 char namebuf[1024];
986 REQUIRE(DNS_ZONE_VALID(zone));
988 LOCK_ZONE(zone);
989 if (zone->view != NULL)
990 dns_view_weakdetach(&zone->view);
991 dns_view_weakattach(view, &zone->view);
993 if (zone->strviewname != NULL)
994 isc_mem_free(zone->mctx, zone->strviewname);
995 if (zone->strnamerd != NULL)
996 isc_mem_free(zone->mctx, zone->strnamerd);
998 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
999 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1000 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1001 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1003 UNLOCK_ZONE(zone);
1007 dns_view_t *
1008 dns_zone_getview(dns_zone_t *zone) {
1009 REQUIRE(DNS_ZONE_VALID(zone));
1011 return (zone->view);
1015 isc_result_t
1016 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1017 isc_result_t result;
1018 char namebuf[1024];
1020 REQUIRE(DNS_ZONE_VALID(zone));
1021 REQUIRE(origin != NULL);
1023 LOCK_ZONE(zone);
1024 if (dns_name_dynamic(&zone->origin)) {
1025 dns_name_free(&zone->origin, zone->mctx);
1026 dns_name_init(&zone->origin, NULL);
1028 result = dns_name_dup(origin, zone->mctx, &zone->origin);
1030 if (zone->strnamerd != NULL)
1031 isc_mem_free(zone->mctx, zone->strnamerd);
1032 if (zone->strname != NULL)
1033 isc_mem_free(zone->mctx, zone->strname);
1035 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1036 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1037 zone_name_tostr(zone, namebuf, sizeof namebuf);
1038 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1040 UNLOCK_ZONE(zone);
1041 return (result);
1044 void
1045 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1046 REQUIRE(DNS_ZONE_VALID(zone));
1047 REQUIRE(acache != NULL);
1049 LOCK_ZONE(zone);
1050 if (zone->acache != NULL)
1051 dns_acache_detach(&zone->acache);
1052 dns_acache_attach(acache, &zone->acache);
1053 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1054 if (zone->db != NULL) {
1055 isc_result_t result;
1058 * If the zone reuses an existing DB, the DB needs to be
1059 * set in the acache explicitly. We can safely ignore the
1060 * case where the DB is already set. If other error happens,
1061 * the acache will not work effectively.
1063 result = dns_acache_setdb(acache, zone->db);
1064 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1065 UNEXPECTED_ERROR(__FILE__, __LINE__,
1066 "dns_acache_setdb() failed: %s",
1067 isc_result_totext(result));
1070 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1071 UNLOCK_ZONE(zone);
1074 static isc_result_t
1075 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1076 char *copy;
1078 if (value != NULL) {
1079 copy = isc_mem_strdup(zone->mctx, value);
1080 if (copy == NULL)
1081 return (ISC_R_NOMEMORY);
1082 } else {
1083 copy = NULL;
1086 if (*field != NULL)
1087 isc_mem_free(zone->mctx, *field);
1089 *field = copy;
1090 return (ISC_R_SUCCESS);
1093 isc_result_t
1094 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1095 return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1098 isc_result_t
1099 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1100 dns_masterformat_t format) {
1101 isc_result_t result = ISC_R_SUCCESS;
1103 REQUIRE(DNS_ZONE_VALID(zone));
1105 LOCK_ZONE(zone);
1106 result = dns_zone_setstring(zone, &zone->masterfile, file);
1107 if (result == ISC_R_SUCCESS) {
1108 zone->masterformat = format;
1109 result = default_journal(zone);
1111 UNLOCK_ZONE(zone);
1113 return (result);
1116 const char *
1117 dns_zone_getfile(dns_zone_t *zone) {
1118 REQUIRE(DNS_ZONE_VALID(zone));
1120 return (zone->masterfile);
1123 static isc_result_t
1124 default_journal(dns_zone_t *zone) {
1125 isc_result_t result;
1126 char *journal;
1128 REQUIRE(DNS_ZONE_VALID(zone));
1129 REQUIRE(LOCKED_ZONE(zone));
1131 if (zone->masterfile != NULL) {
1132 /* Calculate string length including '\0'. */
1133 int len = strlen(zone->masterfile) + sizeof(".jnl");
1134 journal = isc_mem_allocate(zone->mctx, len);
1135 if (journal == NULL)
1136 return (ISC_R_NOMEMORY);
1137 strcpy(journal, zone->masterfile);
1138 strcat(journal, ".jnl");
1139 } else {
1140 journal = NULL;
1142 result = dns_zone_setstring(zone, &zone->journal, journal);
1143 if (journal != NULL)
1144 isc_mem_free(zone->mctx, journal);
1145 return (result);
1148 isc_result_t
1149 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1150 isc_result_t result = ISC_R_SUCCESS;
1152 REQUIRE(DNS_ZONE_VALID(zone));
1154 LOCK_ZONE(zone);
1155 result = dns_zone_setstring(zone, &zone->journal, journal);
1156 UNLOCK_ZONE(zone);
1158 return (result);
1161 char *
1162 dns_zone_getjournal(dns_zone_t *zone) {
1163 REQUIRE(DNS_ZONE_VALID(zone));
1165 return (zone->journal);
1169 * Return true iff the zone is "dynamic", in the sense that the zone's
1170 * master file (if any) is written by the server, rather than being
1171 * updated manually and read by the server.
1173 * This is true for slave zones, stub zones, and zones that allow
1174 * dynamic updates either by having an update policy ("ssutable")
1175 * or an "allow-update" ACL with a value other than exactly "{ none; }".
1177 static isc_boolean_t
1178 zone_isdynamic(dns_zone_t *zone) {
1179 REQUIRE(DNS_ZONE_VALID(zone));
1181 return (ISC_TF(zone->type == dns_zone_slave ||
1182 zone->type == dns_zone_stub ||
1183 (!zone->update_disabled && zone->ssutable != NULL) ||
1184 (!zone->update_disabled && zone->update_acl != NULL &&
1185 !dns_acl_isnone(zone->update_acl))));
1189 static isc_result_t
1190 zone_load(dns_zone_t *zone, unsigned int flags) {
1191 isc_result_t result;
1192 isc_time_t now;
1193 isc_time_t loadtime, filetime;
1194 dns_db_t *db = NULL;
1196 REQUIRE(DNS_ZONE_VALID(zone));
1198 LOCK_ZONE(zone);
1199 TIME_NOW(&now);
1201 INSIST(zone->type != dns_zone_none);
1203 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1204 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1205 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1206 result = DNS_R_CONTINUE;
1207 goto cleanup;
1210 if (zone->db != NULL && zone->masterfile == NULL) {
1212 * The zone has no master file configured, but it already
1213 * has a database. It could be the built-in
1214 * version.bind. CH zone, a zone with a persistent
1215 * database being reloaded, or maybe a zone that
1216 * used to have a master file but whose configuration
1217 * was changed so that it no longer has one. Do nothing.
1219 result = ISC_R_SUCCESS;
1220 goto cleanup;
1223 if (zone->db != NULL && zone_isdynamic(zone)) {
1225 * This is a slave, stub, or dynamically updated
1226 * zone being reloaded. Do nothing - the database
1227 * we already have is guaranteed to be up-to-date.
1229 if (zone->type == dns_zone_master)
1230 result = DNS_R_DYNAMIC;
1231 else
1232 result = ISC_R_SUCCESS;
1233 goto cleanup;
1238 * Store the current time before the zone is loaded, so that if the
1239 * file changes between the time of the load and the time that
1240 * zone->loadtime is set, then the file will still be reloaded
1241 * the next time dns_zone_load is called.
1243 TIME_NOW(&loadtime);
1246 * Don't do the load if the file that stores the zone is older
1247 * than the last time the zone was loaded. If the zone has not
1248 * been loaded yet, zone->loadtime will be the epoch.
1250 if (zone->masterfile != NULL) {
1252 * The file is already loaded. If we are just doing a
1253 * "rndc reconfig", we are done.
1255 if (!isc_time_isepoch(&zone->loadtime) &&
1256 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1257 result = ISC_R_SUCCESS;
1258 goto cleanup;
1261 result = isc_file_getmodtime(zone->masterfile, &filetime);
1262 if (result == ISC_R_SUCCESS) {
1263 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1264 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1265 isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1266 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1267 "skipping load: master file "
1268 "older than last load");
1269 result = DNS_R_UPTODATE;
1270 goto cleanup;
1272 loadtime = filetime;
1276 INSIST(zone->db_argc >= 1);
1279 * Built in zones don't need to be reloaded.
1281 if (zone->type == dns_zone_master &&
1282 strcmp(zone->db_argv[0], "_builtin") == 0 &&
1283 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1284 result = ISC_R_SUCCESS;
1285 goto cleanup;
1288 if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
1289 (strcmp(zone->db_argv[0], "rbt") == 0 ||
1290 strcmp(zone->db_argv[0], "rbt64") == 0)) {
1291 if (zone->masterfile == NULL ||
1292 !isc_file_exists(zone->masterfile)) {
1293 if (zone->masterfile != NULL) {
1294 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1295 "no master file");
1297 zone->refreshtime = now;
1298 if (zone->task != NULL)
1299 zone_settimer(zone, &now);
1300 result = ISC_R_SUCCESS;
1301 goto cleanup;
1305 dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1307 result = dns_db_create(zone->mctx, zone->db_argv[0],
1308 &zone->origin, (zone->type == dns_zone_stub) ?
1309 dns_dbtype_stub : dns_dbtype_zone,
1310 zone->rdclass,
1311 zone->db_argc - 1, zone->db_argv + 1,
1312 &db);
1314 if (result != ISC_R_SUCCESS) {
1315 dns_zone_log(zone, ISC_LOG_ERROR,
1316 "loading zone: creating database: %s",
1317 isc_result_totext(result));
1318 goto cleanup;
1320 dns_db_settask(db, zone->task);
1322 if (! dns_db_ispersistent(db)) {
1323 if (zone->masterfile != NULL) {
1324 result = zone_startload(db, zone, loadtime);
1325 } else {
1326 result = DNS_R_NOMASTERFILE;
1327 if (zone->type == dns_zone_master) {
1328 dns_zone_log(zone, ISC_LOG_ERROR,
1329 "loading zone: "
1330 "no master file configured");
1331 goto cleanup;
1333 dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1334 "no master file configured: continuing");
1338 if (result == DNS_R_CONTINUE) {
1339 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1340 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1341 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1342 goto cleanup;
1345 result = zone_postload(zone, db, loadtime, result);
1347 cleanup:
1348 UNLOCK_ZONE(zone);
1349 if (db != NULL)
1350 dns_db_detach(&db);
1351 return (result);
1354 isc_result_t
1355 dns_zone_load(dns_zone_t *zone) {
1356 return (zone_load(zone, 0));
1359 isc_result_t
1360 dns_zone_loadnew(dns_zone_t *zone) {
1361 return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1364 isc_result_t
1365 dns_zone_loadandthaw(dns_zone_t *zone) {
1366 isc_result_t result;
1368 result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1369 switch (result) {
1370 case DNS_R_CONTINUE:
1371 /* Deferred thaw. */
1372 break;
1373 case ISC_R_SUCCESS:
1374 case DNS_R_UPTODATE:
1375 case DNS_R_SEENINCLUDE:
1376 zone->update_disabled = ISC_FALSE;
1377 break;
1378 case DNS_R_NOMASTERFILE:
1379 zone->update_disabled = ISC_FALSE;
1380 break;
1381 default:
1382 /* Error, remain in disabled state. */
1383 break;
1385 return (result);
1388 static void
1389 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1390 dns_load_t *load = event->ev_arg;
1391 isc_result_t result = ISC_R_SUCCESS;
1392 unsigned int options;
1394 REQUIRE(DNS_LOAD_VALID(load));
1396 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1397 result = ISC_R_CANCELED;
1398 isc_event_free(&event);
1399 if (result == ISC_R_CANCELED)
1400 goto fail;
1402 options = DNS_MASTER_ZONE;
1403 if (load->zone->type == dns_zone_slave)
1404 options |= DNS_MASTER_SLAVE;
1405 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNS))
1406 options |= DNS_MASTER_CHECKNS;
1407 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_FATALNS))
1408 options |= DNS_MASTER_FATALNS;
1409 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNAMES))
1410 options |= DNS_MASTER_CHECKNAMES;
1411 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1412 options |= DNS_MASTER_CHECKNAMESFAIL;
1413 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKMX))
1414 options |= DNS_MASTER_CHECKMX;
1415 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKMXFAIL))
1416 options |= DNS_MASTER_CHECKMXFAIL;
1417 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKWILDCARD))
1418 options |= DNS_MASTER_CHECKWILDCARD;
1419 result = dns_master_loadfileinc2(load->zone->masterfile,
1420 dns_db_origin(load->db),
1421 dns_db_origin(load->db),
1422 load->zone->rdclass,
1423 options,
1424 &load->callbacks, task,
1425 zone_loaddone, load,
1426 &load->zone->lctx, load->zone->mctx,
1427 load->zone->masterformat);
1428 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1429 result != DNS_R_SEENINCLUDE)
1430 goto fail;
1431 return;
1433 fail:
1434 zone_loaddone(load, result);
1437 static void
1438 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1439 const char me[] = "zone_gotwritehandle";
1440 dns_zone_t *zone = event->ev_arg;
1441 isc_result_t result = ISC_R_SUCCESS;
1442 dns_dbversion_t *version = NULL;
1444 REQUIRE(DNS_ZONE_VALID(zone));
1445 INSIST(task == zone->task);
1446 ENTER;
1448 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1449 result = ISC_R_CANCELED;
1450 isc_event_free(&event);
1451 if (result == ISC_R_CANCELED)
1452 goto fail;
1454 LOCK_ZONE(zone);
1455 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1456 dns_db_currentversion(zone->db, &version);
1457 result = dns_master_dumpinc2(zone->mctx, zone->db, version,
1458 &dns_master_style_default,
1459 zone->masterfile, zone->task, dump_done,
1460 zone, &zone->dctx, zone->masterformat);
1461 dns_db_closeversion(zone->db, &version, ISC_FALSE);
1462 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1463 UNLOCK_ZONE(zone);
1464 if (result != DNS_R_CONTINUE)
1465 goto fail;
1466 return;
1468 fail:
1469 dump_done(zone, result);
1472 static isc_result_t
1473 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1474 dns_load_t *load;
1475 isc_result_t result;
1476 isc_result_t tresult;
1477 unsigned int options;
1479 options = DNS_MASTER_ZONE;
1480 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1481 options |= DNS_MASTER_MANYERRORS;
1482 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1483 options |= DNS_MASTER_CHECKNS;
1484 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1485 options |= DNS_MASTER_FATALNS;
1486 if (zone->type == dns_zone_slave)
1487 options |= DNS_MASTER_SLAVE;
1488 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1489 options |= DNS_MASTER_CHECKNAMES;
1490 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1491 options |= DNS_MASTER_CHECKNAMESFAIL;
1492 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1493 options |= DNS_MASTER_CHECKMX;
1494 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1495 options |= DNS_MASTER_CHECKMXFAIL;
1496 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1497 options |= DNS_MASTER_CHECKWILDCARD;
1499 if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1500 load = isc_mem_get(zone->mctx, sizeof(*load));
1501 if (load == NULL)
1502 return (ISC_R_NOMEMORY);
1504 load->mctx = NULL;
1505 load->zone = NULL;
1506 load->db = NULL;
1507 load->loadtime = loadtime;
1508 load->magic = LOAD_MAGIC;
1510 isc_mem_attach(zone->mctx, &load->mctx);
1511 zone_iattach(zone, &load->zone);
1512 dns_db_attach(db, &load->db);
1513 dns_rdatacallbacks_init(&load->callbacks);
1514 result = dns_db_beginload(db, &load->callbacks.add,
1515 &load->callbacks.add_private);
1516 if (result != ISC_R_SUCCESS)
1517 goto cleanup;
1518 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1519 zone_gotreadhandle, load,
1520 &zone->readio);
1521 if (result != ISC_R_SUCCESS) {
1523 * We can't report multiple errors so ignore
1524 * the result of dns_db_endload().
1526 (void)dns_db_endload(load->db,
1527 &load->callbacks.add_private);
1528 goto cleanup;
1529 } else
1530 result = DNS_R_CONTINUE;
1531 } else {
1532 dns_rdatacallbacks_t callbacks;
1534 dns_rdatacallbacks_init(&callbacks);
1535 result = dns_db_beginload(db, &callbacks.add,
1536 &callbacks.add_private);
1537 if (result != ISC_R_SUCCESS)
1538 return (result);
1539 result = dns_master_loadfile2(zone->masterfile, &zone->origin,
1540 &zone->origin, zone->rdclass,
1541 options, &callbacks, zone->mctx,
1542 zone->masterformat);
1543 tresult = dns_db_endload(db, &callbacks.add_private);
1544 if (result == ISC_R_SUCCESS)
1545 result = tresult;
1548 return (result);
1550 cleanup:
1551 load->magic = 0;
1552 dns_db_detach(&load->db);
1553 zone_idetach(&load->zone);
1554 isc_mem_detach(&load->mctx);
1555 isc_mem_put(zone->mctx, load, sizeof(*load));
1556 return (result);
1559 static isc_boolean_t
1560 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1561 dns_name_t *owner)
1563 isc_result_t result;
1564 char ownerbuf[DNS_NAME_FORMATSIZE];
1565 char namebuf[DNS_NAME_FORMATSIZE];
1566 char altbuf[DNS_NAME_FORMATSIZE];
1567 dns_fixedname_t fixed;
1568 dns_name_t *foundname;
1569 int level;
1572 * Outside of zone.
1574 if (!dns_name_issubdomain(name, &zone->origin)) {
1575 if (zone->checkmx != NULL)
1576 return ((zone->checkmx)(zone, name, owner));
1577 return (ISC_TRUE);
1580 if (zone->type == dns_zone_master)
1581 level = ISC_LOG_ERROR;
1582 else
1583 level = ISC_LOG_WARNING;
1585 dns_fixedname_init(&fixed);
1586 foundname = dns_fixedname_name(&fixed);
1588 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1589 0, 0, NULL, foundname, NULL, NULL);
1590 if (result == ISC_R_SUCCESS)
1591 return (ISC_TRUE);
1593 if (result == DNS_R_NXRRSET) {
1594 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1595 0, 0, NULL, foundname, NULL, NULL);
1596 if (result == ISC_R_SUCCESS)
1597 return (ISC_TRUE);
1600 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1601 dns_name_format(name, namebuf, sizeof namebuf);
1602 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1603 result == DNS_R_EMPTYNAME) {
1604 dns_zone_log(zone, level,
1605 "%s/MX '%s' has no address records (A or AAAA)",
1606 ownerbuf, namebuf);
1607 /* XXX950 make fatal for 9.5.0. */
1608 return (ISC_TRUE);
1611 if (result == DNS_R_CNAME) {
1612 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1613 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1614 level = ISC_LOG_WARNING;
1615 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1616 dns_zone_log(zone, level,
1617 "%s/MX '%s' is a CNAME (illegal)",
1618 ownerbuf, namebuf);
1619 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1622 if (result == DNS_R_DNAME) {
1623 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1624 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1625 level = ISC_LOG_WARNING;
1626 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
1627 dns_name_format(foundname, altbuf, sizeof altbuf);
1628 dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
1629 " '%s' (illegal)", ownerbuf, namebuf,
1630 altbuf);
1632 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1635 if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
1636 return ((zone->checkmx)(zone, name, owner));
1638 return (ISC_TRUE);
1641 static isc_boolean_t
1642 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1643 dns_name_t *owner)
1645 isc_result_t result;
1646 char ownerbuf[DNS_NAME_FORMATSIZE];
1647 char namebuf[DNS_NAME_FORMATSIZE];
1648 char altbuf[DNS_NAME_FORMATSIZE];
1649 dns_fixedname_t fixed;
1650 dns_name_t *foundname;
1651 int level;
1654 * "." means the services does not exist.
1656 if (dns_name_equal(name, dns_rootname))
1657 return (ISC_TRUE);
1660 * Outside of zone.
1662 if (!dns_name_issubdomain(name, &zone->origin)) {
1663 if (zone->checksrv != NULL)
1664 return ((zone->checksrv)(zone, name, owner));
1665 return (ISC_TRUE);
1668 if (zone->type == dns_zone_master)
1669 level = ISC_LOG_ERROR;
1670 else
1671 level = ISC_LOG_WARNING;
1673 dns_fixedname_init(&fixed);
1674 foundname = dns_fixedname_name(&fixed);
1676 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1677 0, 0, NULL, foundname, NULL, NULL);
1678 if (result == ISC_R_SUCCESS)
1679 return (ISC_TRUE);
1681 if (result == DNS_R_NXRRSET) {
1682 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1683 0, 0, NULL, foundname, NULL, NULL);
1684 if (result == ISC_R_SUCCESS)
1685 return (ISC_TRUE);
1688 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1689 dns_name_format(name, namebuf, sizeof namebuf);
1690 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1691 result == DNS_R_EMPTYNAME) {
1692 dns_zone_log(zone, level,
1693 "%s/SRV '%s' has no address records (A or AAAA)",
1694 ownerbuf, namebuf);
1695 /* XXX950 make fatal for 9.5.0. */
1696 return (ISC_TRUE);
1699 if (result == DNS_R_CNAME) {
1700 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1701 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1702 level = ISC_LOG_WARNING;
1703 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1704 dns_zone_log(zone, level,
1705 "%s/SRV '%s' is a CNAME (illegal)",
1706 ownerbuf, namebuf);
1707 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1710 if (result == DNS_R_DNAME) {
1711 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1712 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1713 level = ISC_LOG_WARNING;
1714 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
1715 dns_name_format(foundname, altbuf, sizeof altbuf);
1716 dns_zone_log(zone, level, "%s/SRV '%s' is below a "
1717 "DNAME '%s' (illegal)", ownerbuf, namebuf,
1718 altbuf);
1720 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1723 if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
1724 return ((zone->checksrv)(zone, name, owner));
1726 return (ISC_TRUE);
1729 static isc_boolean_t
1730 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1731 dns_name_t *owner)
1733 isc_boolean_t answer = ISC_TRUE;
1734 isc_result_t result, tresult;
1735 char ownerbuf[DNS_NAME_FORMATSIZE];
1736 char namebuf[DNS_NAME_FORMATSIZE];
1737 char altbuf[DNS_NAME_FORMATSIZE];
1738 dns_fixedname_t fixed;
1739 dns_name_t *foundname;
1740 dns_rdataset_t a;
1741 dns_rdataset_t aaaa;
1742 int level;
1745 * Outside of zone.
1747 if (!dns_name_issubdomain(name, &zone->origin)) {
1748 if (zone->checkns != NULL)
1749 return ((zone->checkns)(zone, name, owner, NULL, NULL));
1750 return (ISC_TRUE);
1753 if (zone->type == dns_zone_master)
1754 level = ISC_LOG_ERROR;
1755 else
1756 level = ISC_LOG_WARNING;
1758 dns_fixedname_init(&fixed);
1759 foundname = dns_fixedname_name(&fixed);
1760 dns_rdataset_init(&a);
1761 dns_rdataset_init(&aaaa);
1763 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1764 DNS_DBFIND_GLUEOK, 0, NULL,
1765 foundname, &a, NULL);
1767 if (result == ISC_R_SUCCESS) {
1768 dns_rdataset_disassociate(&a);
1769 return (ISC_TRUE);
1770 } else if (result == DNS_R_DELEGATION)
1771 dns_rdataset_disassociate(&a);
1773 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
1774 result == DNS_R_GLUE) {
1775 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1776 DNS_DBFIND_GLUEOK, 0, NULL,
1777 foundname, &aaaa, NULL);
1778 if (tresult == ISC_R_SUCCESS) {
1779 dns_rdataset_disassociate(&aaaa);
1780 return (ISC_TRUE);
1782 if (tresult == DNS_R_DELEGATION)
1783 dns_rdataset_disassociate(&aaaa);
1784 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
1786 * Check glue against child zone.
1788 if (zone->checkns != NULL)
1789 answer = (zone->checkns)(zone, name, owner,
1790 &a, &aaaa);
1791 if (dns_rdataset_isassociated(&a))
1792 dns_rdataset_disassociate(&a);
1793 if (dns_rdataset_isassociated(&aaaa))
1794 dns_rdataset_disassociate(&aaaa);
1795 return (answer);
1797 } else
1798 tresult = result;
1800 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1801 dns_name_format(name, namebuf, sizeof namebuf);
1802 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1803 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
1804 const char *what;
1805 isc_boolean_t required = ISC_FALSE;
1806 if (dns_name_issubdomain(name, owner)) {
1807 what = "REQUIRED GLUE ";
1808 required = ISC_TRUE;
1809 } else if (result == DNS_R_DELEGATION)
1810 what = "SIBLING GLUE ";
1811 else
1812 what = "";
1814 if (result != DNS_R_DELEGATION || required ||
1815 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
1816 dns_zone_log(zone, level, "%s/NS '%s' has no %s"
1817 "address records (A or AAAA)",
1818 ownerbuf, namebuf, what);
1820 * Log missing address record.
1822 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
1823 (void)(zone->checkns)(zone, name, owner,
1824 &a, &aaaa);
1825 /* XXX950 make fatal for 9.5.0. */
1826 /* answer = ISC_FALSE; */
1828 } else if (result == DNS_R_CNAME) {
1829 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
1830 ownerbuf, namebuf);
1831 /* XXX950 make fatal for 9.5.0. */
1832 /* answer = ISC_FALSE; */
1833 } else if (result == DNS_R_DNAME) {
1834 dns_name_format(foundname, altbuf, sizeof altbuf);
1835 dns_zone_log(zone, level,
1836 "%s/NS '%s' is below a DNAME '%s' (illegal)",
1837 ownerbuf, namebuf, altbuf);
1838 /* XXX950 make fatal for 9.5.0. */
1839 /* answer = ISC_FALSE; */
1842 if (dns_rdataset_isassociated(&a))
1843 dns_rdataset_disassociate(&a);
1844 if (dns_rdataset_isassociated(&aaaa))
1845 dns_rdataset_disassociate(&aaaa);
1846 return (answer);
1849 static isc_boolean_t
1850 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
1851 dns_dbiterator_t *dbiterator = NULL;
1852 dns_dbnode_t *node = NULL;
1853 dns_rdataset_t rdataset;
1854 dns_fixedname_t fixed;
1855 dns_fixedname_t fixedbottom;
1856 dns_rdata_mx_t mx;
1857 dns_rdata_ns_t ns;
1858 dns_rdata_in_srv_t srv;
1859 dns_rdata_t rdata;
1860 dns_name_t *name;
1861 dns_name_t *bottom;
1862 isc_result_t result;
1863 isc_boolean_t ok = ISC_TRUE;
1865 dns_fixedname_init(&fixed);
1866 name = dns_fixedname_name(&fixed);
1867 dns_fixedname_init(&fixedbottom);
1868 bottom = dns_fixedname_name(&fixedbottom);
1869 dns_rdataset_init(&rdataset);
1870 dns_rdata_init(&rdata);
1872 result = dns_db_createiterator(db, ISC_FALSE, &dbiterator);
1873 if (result != ISC_R_SUCCESS)
1874 return (ISC_TRUE);
1876 result = dns_dbiterator_first(dbiterator);
1877 while (result == ISC_R_SUCCESS) {
1878 result = dns_dbiterator_current(dbiterator, &node, name);
1879 if (result != ISC_R_SUCCESS)
1880 goto cleanup;
1883 * Is this name visible in the zone?
1885 if (!dns_name_issubdomain(name, &zone->origin) ||
1886 (dns_name_countlabels(bottom) > 0 &&
1887 dns_name_issubdomain(name, bottom)))
1888 goto next;
1891 * Don't check the NS records at the origin.
1893 if (dns_name_equal(name, &zone->origin))
1894 goto checkmx;
1896 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
1897 0, 0, &rdataset, NULL);
1898 if (result != ISC_R_SUCCESS)
1899 goto checkmx;
1901 * Remember bottom of zone.
1903 dns_name_copy(name, bottom, NULL);
1905 result = dns_rdataset_first(&rdataset);
1906 while (result == ISC_R_SUCCESS) {
1907 dns_rdataset_current(&rdataset, &rdata);
1908 result = dns_rdata_tostruct(&rdata, &ns, NULL);
1909 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1910 if (!zone_check_glue(zone, db, &ns.name, name))
1911 ok = ISC_FALSE;
1912 dns_rdata_reset(&rdata);
1913 result = dns_rdataset_next(&rdataset);
1915 dns_rdataset_disassociate(&rdataset);
1917 checkmx:
1918 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
1919 0, 0, &rdataset, NULL);
1920 if (result != ISC_R_SUCCESS)
1921 goto checksrv;
1922 result = dns_rdataset_first(&rdataset);
1923 while (result == ISC_R_SUCCESS) {
1924 dns_rdataset_current(&rdataset, &rdata);
1925 result = dns_rdata_tostruct(&rdata, &mx, NULL);
1926 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1927 if (!zone_check_mx(zone, db, &mx.mx, name))
1928 ok = ISC_FALSE;
1929 dns_rdata_reset(&rdata);
1930 result = dns_rdataset_next(&rdataset);
1932 dns_rdataset_disassociate(&rdataset);
1934 checksrv:
1935 if (zone->rdclass != dns_rdataclass_in)
1936 goto next;
1937 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
1938 0, 0, &rdataset, NULL);
1939 if (result != ISC_R_SUCCESS)
1940 goto next;
1941 result = dns_rdataset_first(&rdataset);
1942 while (result == ISC_R_SUCCESS) {
1943 dns_rdataset_current(&rdataset, &rdata);
1944 result = dns_rdata_tostruct(&rdata, &srv, NULL);
1945 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1946 if (!zone_check_srv(zone, db, &srv.target, name))
1947 ok = ISC_FALSE;
1948 dns_rdata_reset(&rdata);
1949 result = dns_rdataset_next(&rdataset);
1951 dns_rdataset_disassociate(&rdataset);
1953 next:
1954 dns_db_detachnode(db, &node);
1955 result = dns_dbiterator_next(dbiterator);
1958 cleanup:
1959 if (node != NULL)
1960 dns_db_detachnode(db, &node);
1961 dns_dbiterator_destroy(&dbiterator);
1963 return (ok);
1967 * OpenSSL verification of RSA keys with exponent 3 is known to be
1968 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
1969 * if they are in use.
1971 static void
1972 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
1973 dns_dbnode_t *node = NULL;
1974 dns_dbversion_t *version = NULL;
1975 dns_rdata_dnskey_t dnskey;
1976 dns_rdata_t rdata = DNS_RDATA_INIT;
1977 dns_rdataset_t rdataset;
1978 isc_result_t result;
1979 isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
1980 const char *algorithm;
1982 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
1983 if (result != ISC_R_SUCCESS)
1984 goto cleanup;
1986 dns_db_currentversion(db, &version);
1987 dns_rdataset_init(&rdataset);
1988 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
1989 dns_rdatatype_none, 0, &rdataset, NULL);
1990 if (result != ISC_R_SUCCESS)
1991 goto cleanup;
1993 for (result = dns_rdataset_first(&rdataset);
1994 result == ISC_R_SUCCESS;
1995 result = dns_rdataset_next(&rdataset))
1997 dns_rdataset_current(&rdataset, &rdata);
1998 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1999 INSIST(result == ISC_R_SUCCESS);
2001 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2002 dnskey.algorithm == DST_ALG_RSAMD5) &&
2003 dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2004 dnskey.data[1] == 3)
2006 if (dnskey.algorithm == DST_ALG_RSASHA1) {
2007 logit = !foundrsa;
2008 foundrsa = ISC_TRUE;
2009 algorithm = "RSASHA1";
2010 } else {
2011 logit = !foundmd5;
2012 foundmd5 = ISC_TRUE;
2013 algorithm = "RSAMD5";
2015 if (logit)
2016 dns_zone_log(zone, ISC_LOG_WARNING,
2017 "weak %s (%u) key found "
2018 "(exponent=3)", algorithm,
2019 dnskey.algorithm);
2020 if (foundrsa && foundmd5)
2021 break;
2023 dns_rdata_reset(&rdata);
2025 dns_rdataset_disassociate(&rdataset);
2027 cleanup:
2028 if (node != NULL)
2029 dns_db_detachnode(db, &node);
2030 if (version != NULL)
2031 dns_db_closeversion(db, &version, ISC_FALSE);
2035 static isc_result_t
2036 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
2037 isc_result_t result)
2039 unsigned int soacount = 0;
2040 unsigned int nscount = 0;
2041 unsigned int errors = 0;
2042 isc_uint32_t serial, refresh, retry, expire, minimum;
2043 isc_time_t now;
2044 isc_boolean_t needdump = ISC_FALSE;
2045 isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
2047 TIME_NOW(&now);
2050 * Initiate zone transfer? We may need a error code that
2051 * indicates that the "permanent" form does not exist.
2052 * XXX better error feedback to log.
2054 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
2055 if (zone->type == dns_zone_slave ||
2056 zone->type == dns_zone_stub) {
2057 if (result == ISC_R_FILENOTFOUND)
2058 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2059 "no master file");
2060 else if (result != DNS_R_NOMASTERFILE)
2061 dns_zone_log(zone, ISC_LOG_ERROR,
2062 "loading from master file %s "
2063 "failed: %s",
2064 zone->masterfile,
2065 dns_result_totext(result));
2066 } else
2067 dns_zone_log(zone, ISC_LOG_ERROR,
2068 "loading from master file %s failed: %s",
2069 zone->masterfile,
2070 dns_result_totext(result));
2071 goto cleanup;
2074 dns_zone_log(zone, ISC_LOG_DEBUG(2),
2075 "number of nodes in database: %u",
2076 dns_db_nodecount(db));
2078 if (result == DNS_R_SEENINCLUDE)
2079 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
2080 else
2081 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
2084 * Apply update log, if any, on initial load.
2086 if (zone->journal != NULL &&
2087 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
2088 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2090 result = dns_journal_rollforward(zone->mctx, db,
2091 zone->journal);
2092 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
2093 result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
2094 result != ISC_R_RANGE) {
2095 dns_zone_log(zone, ISC_LOG_ERROR,
2096 "journal rollforward failed: %s",
2097 dns_result_totext(result));
2098 goto cleanup;
2100 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
2101 dns_zone_log(zone, ISC_LOG_ERROR,
2102 "journal rollforward failed: "
2103 "journal out of sync with zone");
2104 goto cleanup;
2106 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2107 "journal rollforward completed "
2108 "successfully: %s",
2109 dns_result_totext(result));
2110 if (result == ISC_R_SUCCESS)
2111 needdump = ISC_TRUE;
2114 zone->loadtime = loadtime;
2116 dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
2119 * Obtain ns, soa and cname counts for top of zone.
2121 INSIST(db != NULL);
2122 result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
2123 &refresh, &retry, &expire, &minimum,
2124 &errors);
2125 if (result != ISC_R_SUCCESS) {
2126 dns_zone_log(zone, ISC_LOG_ERROR,
2127 "could not find NS and/or SOA records");
2131 * Master / Slave / Stub zones require both NS and SOA records at
2132 * the top of the zone.
2135 switch (zone->type) {
2136 case dns_zone_master:
2137 case dns_zone_slave:
2138 case dns_zone_stub:
2139 if (soacount != 1) {
2140 dns_zone_log(zone, ISC_LOG_ERROR,
2141 "has %d SOA records", soacount);
2142 result = DNS_R_BADZONE;
2144 if (nscount == 0) {
2145 dns_zone_log(zone, ISC_LOG_ERROR,
2146 "has no NS records");
2147 result = DNS_R_BADZONE;
2149 if (result != ISC_R_SUCCESS)
2150 goto cleanup;
2151 if (zone->type == dns_zone_master && errors != 0) {
2152 result = DNS_R_BADZONE;
2153 goto cleanup;
2155 if (zone->type == dns_zone_master &&
2156 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
2157 !integrity_checks(zone, db)) {
2158 result = DNS_R_BADZONE;
2159 goto cleanup;
2162 if (zone->db != NULL) {
2164 * This is checked in zone_replacedb() for slave zones
2165 * as they don't reload from disk.
2167 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
2168 !isc_serial_gt(serial, zone->serial)) {
2169 isc_uint32_t serialmin, serialmax;
2171 INSIST(zone->type == dns_zone_master);
2173 serialmin = (zone->serial + 1) & 0xffffffffU;
2174 serialmax = (zone->serial + 0x7fffffffU) &
2175 0xffffffffU;
2176 dns_zone_log(zone, ISC_LOG_ERROR,
2177 "ixfr-from-differences: "
2178 "new serial (%u) out of range "
2179 "[%u - %u]", serial, serialmin,
2180 serialmax);
2181 result = DNS_R_BADZONE;
2182 goto cleanup;
2183 } else if (!isc_serial_ge(serial, zone->serial))
2184 dns_zone_log(zone, ISC_LOG_ERROR,
2185 "zone serial has gone backwards");
2186 else if (serial == zone->serial && !hasinclude)
2187 dns_zone_log(zone, ISC_LOG_ERROR,
2188 "zone serial unchanged. "
2189 "zone may fail to transfer "
2190 "to slaves.");
2192 zone->serial = serial;
2193 zone->refresh = RANGE(refresh,
2194 zone->minrefresh, zone->maxrefresh);
2195 zone->retry = RANGE(retry,
2196 zone->minretry, zone->maxretry);
2197 zone->expire = RANGE(expire, zone->refresh + zone->retry,
2198 DNS_MAX_EXPIRE);
2199 zone->minimum = minimum;
2200 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
2202 if (zone->type == dns_zone_slave ||
2203 zone->type == dns_zone_stub) {
2204 isc_time_t t;
2205 isc_uint32_t delay;
2207 result = isc_file_getmodtime(zone->journal, &t);
2208 if (result != ISC_R_SUCCESS)
2209 result = isc_file_getmodtime(zone->masterfile,
2210 &t);
2211 if (result == ISC_R_SUCCESS)
2212 DNS_ZONE_TIME_ADD(&t, zone->expire,
2213 &zone->expiretime);
2214 else
2215 DNS_ZONE_TIME_ADD(&now, zone->retry,
2216 &zone->expiretime);
2218 delay = isc_random_jitter(zone->retry,
2219 (zone->retry * 3) / 4);
2220 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
2221 if (isc_time_compare(&zone->refreshtime,
2222 &zone->expiretime) >= 0)
2223 zone->refreshtime = now;
2225 break;
2226 default:
2227 UNEXPECTED_ERROR(__FILE__, __LINE__,
2228 "unexpected zone type %d", zone->type);
2229 result = ISC_R_UNEXPECTED;
2230 goto cleanup;
2234 * Check for weak DNSKEY's.
2236 if (zone->type == dns_zone_master)
2237 zone_check_dnskeys(zone, db);
2239 #if 0
2240 /* destroy notification example. */
2242 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
2243 DNS_EVENT_DBDESTROYED,
2244 dns_zonemgr_dbdestroyed,
2245 zone,
2246 sizeof(isc_event_t));
2247 dns_db_ondestroy(db, zone->task, &e);
2249 #endif
2251 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2252 if (zone->db != NULL) {
2253 result = zone_replacedb(zone, db, ISC_FALSE);
2254 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2255 if (result != ISC_R_SUCCESS)
2256 goto cleanup;
2257 } else {
2258 zone_attachdb(zone, db);
2259 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2260 DNS_ZONE_SETFLAG(zone,
2261 DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
2263 result = ISC_R_SUCCESS;
2264 if (needdump)
2265 zone_needdump(zone, DNS_DUMP_DELAY);
2266 if (zone->task != NULL)
2267 zone_settimer(zone, &now);
2269 if (! dns_db_ispersistent(db))
2270 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s",
2271 zone->serial,
2272 dns_db_issecure(db) ? " (signed)" : "");
2274 return (result);
2276 cleanup:
2277 if (zone->type == dns_zone_slave ||
2278 zone->type == dns_zone_stub) {
2279 if (zone->journal != NULL)
2280 zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
2281 if (zone->masterfile != NULL)
2282 zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
2284 /* Mark the zone for immediate refresh. */
2285 zone->refreshtime = now;
2286 if (zone->task != NULL)
2287 zone_settimer(zone, &now);
2288 result = ISC_R_SUCCESS;
2290 return (result);
2293 static isc_boolean_t
2294 exit_check(dns_zone_t *zone) {
2296 REQUIRE(LOCKED_ZONE(zone));
2298 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
2299 zone->irefs == 0)
2302 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
2304 INSIST(isc_refcount_current(&zone->erefs) == 0);
2305 return (ISC_TRUE);
2307 return (ISC_FALSE);
2310 static isc_boolean_t
2311 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
2312 isc_result_t result;
2313 char namebuf[DNS_NAME_FORMATSIZE];
2314 char altbuf[DNS_NAME_FORMATSIZE];
2315 dns_fixedname_t fixed;
2316 dns_name_t *foundname;
2317 int level;
2319 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
2320 return (ISC_TRUE);
2322 if (zone->type == dns_zone_master)
2323 level = ISC_LOG_ERROR;
2324 else
2325 level = ISC_LOG_WARNING;
2327 dns_fixedname_init(&fixed);
2328 foundname = dns_fixedname_name(&fixed);
2330 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2331 0, 0, NULL, foundname, NULL, NULL);
2332 if (result == ISC_R_SUCCESS)
2333 return (ISC_TRUE);
2335 if (result == DNS_R_NXRRSET) {
2336 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2337 0, 0, NULL, foundname, NULL, NULL);
2338 if (result == ISC_R_SUCCESS)
2339 return (ISC_TRUE);
2342 dns_name_format(name, namebuf, sizeof namebuf);
2343 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2344 result == DNS_R_EMPTYNAME) {
2345 dns_zone_log(zone, level,
2346 "NS '%s' has no address records (A or AAAA)",
2347 namebuf);
2348 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2349 return (ISC_TRUE);
2352 if (result == DNS_R_CNAME) {
2353 dns_zone_log(zone, level, "NS '%s' is a CNAME (illegal)",
2354 namebuf);
2355 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2356 return (ISC_TRUE);
2359 if (result == DNS_R_DNAME) {
2360 dns_name_format(foundname, altbuf, sizeof altbuf);
2361 dns_zone_log(zone, level,
2362 "NS '%s' is below a DNAME '%s' (illegal)",
2363 namebuf, altbuf);
2364 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2365 return (ISC_TRUE);
2368 return (ISC_TRUE);
2371 static isc_result_t
2372 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
2373 dns_dbversion_t *version, unsigned int *nscount,
2374 unsigned int *errors)
2376 isc_result_t result;
2377 unsigned int count = 0;
2378 unsigned int ecount = 0;
2379 dns_rdataset_t rdataset;
2380 dns_rdata_t rdata;
2381 dns_rdata_ns_t ns;
2383 dns_rdataset_init(&rdataset);
2384 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
2385 dns_rdatatype_none, 0, &rdataset, NULL);
2386 if (result == ISC_R_NOTFOUND)
2387 goto success;
2388 if (result != ISC_R_SUCCESS)
2389 goto invalidate_rdataset;
2391 result = dns_rdataset_first(&rdataset);
2392 while (result == ISC_R_SUCCESS) {
2393 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
2394 (zone->type == dns_zone_master ||
2395 zone->type == dns_zone_slave)) {
2396 dns_rdata_init(&rdata);
2397 dns_rdataset_current(&rdataset, &rdata);
2398 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2399 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2400 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
2401 !zone_check_ns(zone, db, &ns.name))
2402 ecount++;
2404 count++;
2405 result = dns_rdataset_next(&rdataset);
2407 dns_rdataset_disassociate(&rdataset);
2409 success:
2410 if (nscount != NULL)
2411 *nscount = count;
2412 if (errors != NULL)
2413 *errors = ecount;
2415 result = ISC_R_SUCCESS;
2417 invalidate_rdataset:
2418 dns_rdataset_invalidate(&rdataset);
2420 return (result);
2423 static isc_result_t
2424 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
2425 unsigned int *soacount,
2426 isc_uint32_t *serial, isc_uint32_t *refresh,
2427 isc_uint32_t *retry, isc_uint32_t *expire,
2428 isc_uint32_t *minimum)
2430 isc_result_t result;
2431 unsigned int count;
2432 dns_rdataset_t rdataset;
2433 dns_rdata_t rdata = DNS_RDATA_INIT;
2434 dns_rdata_soa_t soa;
2436 dns_rdataset_init(&rdataset);
2437 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
2438 dns_rdatatype_none, 0, &rdataset, NULL);
2439 if (result == ISC_R_NOTFOUND) {
2440 if (soacount != NULL)
2441 *soacount = 0;
2442 if (serial != NULL)
2443 *serial = 0;
2444 if (refresh != NULL)
2445 *refresh = 0;
2446 if (retry != NULL)
2447 *retry = 0;
2448 if (expire != NULL)
2449 *expire = 0;
2450 if (minimum != NULL)
2451 *minimum = 0;
2452 result = ISC_R_SUCCESS;
2453 goto invalidate_rdataset;
2455 if (result != ISC_R_SUCCESS)
2456 goto invalidate_rdataset;
2458 count = 0;
2459 result = dns_rdataset_first(&rdataset);
2460 while (result == ISC_R_SUCCESS) {
2461 dns_rdata_init(&rdata);
2462 dns_rdataset_current(&rdataset, &rdata);
2463 count++;
2464 if (count == 1) {
2465 result = dns_rdata_tostruct(&rdata, &soa, NULL);
2466 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2469 result = dns_rdataset_next(&rdataset);
2470 dns_rdata_reset(&rdata);
2472 dns_rdataset_disassociate(&rdataset);
2474 if (soacount != NULL)
2475 *soacount = count;
2477 if (count > 0) {
2478 if (serial != NULL)
2479 *serial = soa.serial;
2480 if (refresh != NULL)
2481 *refresh = soa.refresh;
2482 if (retry != NULL)
2483 *retry = soa.retry;
2484 if (expire != NULL)
2485 *expire = soa.expire;
2486 if (minimum != NULL)
2487 *minimum = soa.minimum;
2490 result = ISC_R_SUCCESS;
2492 invalidate_rdataset:
2493 dns_rdataset_invalidate(&rdataset);
2495 return (result);
2499 * zone must be locked.
2501 static isc_result_t
2502 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
2503 unsigned int *soacount, isc_uint32_t *serial,
2504 isc_uint32_t *refresh, isc_uint32_t *retry,
2505 isc_uint32_t *expire, isc_uint32_t *minimum,
2506 unsigned int *errors)
2508 dns_dbversion_t *version;
2509 isc_result_t result;
2510 isc_result_t answer = ISC_R_SUCCESS;
2511 dns_dbnode_t *node;
2513 REQUIRE(db != NULL);
2514 REQUIRE(zone != NULL);
2516 version = NULL;
2517 dns_db_currentversion(db, &version);
2519 node = NULL;
2520 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2521 if (result != ISC_R_SUCCESS) {
2522 answer = result;
2523 goto closeversion;
2526 if (nscount != NULL || errors != NULL) {
2527 result = zone_count_ns_rr(zone, db, node, version,
2528 nscount, errors);
2529 if (result != ISC_R_SUCCESS)
2530 answer = result;
2533 if (soacount != NULL || serial != NULL || refresh != NULL
2534 || retry != NULL || expire != NULL || minimum != NULL) {
2535 result = zone_load_soa_rr(db, node, version, soacount,
2536 serial, refresh, retry, expire,
2537 minimum);
2538 if (result != ISC_R_SUCCESS)
2539 answer = result;
2542 dns_db_detachnode(db, &node);
2543 closeversion:
2544 dns_db_closeversion(db, &version, ISC_FALSE);
2546 return (answer);
2549 void
2550 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
2551 REQUIRE(DNS_ZONE_VALID(source));
2552 REQUIRE(target != NULL && *target == NULL);
2553 isc_refcount_increment(&source->erefs, NULL);
2554 *target = source;
2557 void
2558 dns_zone_detach(dns_zone_t **zonep) {
2559 dns_zone_t *zone;
2560 unsigned int refs;
2561 isc_boolean_t free_now = ISC_FALSE;
2563 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
2565 zone = *zonep;
2567 isc_refcount_decrement(&zone->erefs, &refs);
2569 if (refs == 0) {
2570 LOCK_ZONE(zone);
2572 * We just detached the last external reference.
2574 if (zone->task != NULL) {
2576 * This zone is being managed. Post
2577 * its control event and let it clean
2578 * up synchronously in the context of
2579 * its task.
2581 isc_event_t *ev = &zone->ctlevent;
2582 isc_task_send(zone->task, &ev);
2583 } else {
2585 * This zone is not being managed; it has
2586 * no task and can have no outstanding
2587 * events. Free it immediately.
2590 * Unmanaged zones should not have non-null views;
2591 * we have no way of detaching from the view here
2592 * without causing deadlock because this code is called
2593 * with the view already locked.
2595 INSIST(zone->view == NULL);
2596 free_now = ISC_TRUE;
2598 UNLOCK_ZONE(zone);
2600 *zonep = NULL;
2601 if (free_now)
2602 zone_free(zone);
2605 void
2606 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
2607 REQUIRE(DNS_ZONE_VALID(source));
2608 REQUIRE(target != NULL && *target == NULL);
2609 LOCK_ZONE(source);
2610 zone_iattach(source, target);
2611 UNLOCK_ZONE(source);
2614 static void
2615 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
2618 * 'source' locked by caller.
2620 REQUIRE(LOCKED_ZONE(source));
2621 REQUIRE(DNS_ZONE_VALID(source));
2622 REQUIRE(target != NULL && *target == NULL);
2623 INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
2624 source->irefs++;
2625 INSIST(source->irefs != 0);
2626 *target = source;
2629 static void
2630 zone_idetach(dns_zone_t **zonep) {
2631 dns_zone_t *zone;
2634 * 'zone' locked by caller.
2636 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
2637 zone = *zonep;
2638 REQUIRE(LOCKED_ZONE(*zonep));
2639 *zonep = NULL;
2641 INSIST(zone->irefs > 0);
2642 zone->irefs--;
2643 INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
2646 void
2647 dns_zone_idetach(dns_zone_t **zonep) {
2648 dns_zone_t *zone;
2649 isc_boolean_t free_needed;
2651 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
2652 zone = *zonep;
2653 *zonep = NULL;
2655 LOCK_ZONE(zone);
2656 INSIST(zone->irefs > 0);
2657 zone->irefs--;
2658 free_needed = exit_check(zone);
2659 UNLOCK_ZONE(zone);
2660 if (free_needed)
2661 zone_free(zone);
2664 isc_mem_t *
2665 dns_zone_getmctx(dns_zone_t *zone) {
2666 REQUIRE(DNS_ZONE_VALID(zone));
2668 return (zone->mctx);
2671 dns_zonemgr_t *
2672 dns_zone_getmgr(dns_zone_t *zone) {
2673 REQUIRE(DNS_ZONE_VALID(zone));
2675 return (zone->zmgr);
2678 void
2679 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
2680 REQUIRE(DNS_ZONE_VALID(zone));
2682 LOCK_ZONE(zone);
2683 if (value)
2684 DNS_ZONE_SETFLAG(zone, flags);
2685 else
2686 DNS_ZONE_CLRFLAG(zone, flags);
2687 UNLOCK_ZONE(zone);
2690 void
2691 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
2693 REQUIRE(DNS_ZONE_VALID(zone));
2695 LOCK_ZONE(zone);
2696 if (value)
2697 zone->options |= option;
2698 else
2699 zone->options &= ~option;
2700 UNLOCK_ZONE(zone);
2703 unsigned int
2704 dns_zone_getoptions(dns_zone_t *zone) {
2706 REQUIRE(DNS_ZONE_VALID(zone));
2708 return (zone->options);
2711 isc_result_t
2712 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
2713 REQUIRE(DNS_ZONE_VALID(zone));
2715 LOCK_ZONE(zone);
2716 zone->xfrsource4 = *xfrsource;
2717 UNLOCK_ZONE(zone);
2719 return (ISC_R_SUCCESS);
2722 isc_sockaddr_t *
2723 dns_zone_getxfrsource4(dns_zone_t *zone) {
2724 REQUIRE(DNS_ZONE_VALID(zone));
2725 return (&zone->xfrsource4);
2728 isc_result_t
2729 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
2730 REQUIRE(DNS_ZONE_VALID(zone));
2732 LOCK_ZONE(zone);
2733 zone->xfrsource6 = *xfrsource;
2734 UNLOCK_ZONE(zone);
2736 return (ISC_R_SUCCESS);
2739 isc_sockaddr_t *
2740 dns_zone_getxfrsource6(dns_zone_t *zone) {
2741 REQUIRE(DNS_ZONE_VALID(zone));
2742 return (&zone->xfrsource6);
2745 isc_result_t
2746 dns_zone_setaltxfrsource4(dns_zone_t *zone,
2747 const isc_sockaddr_t *altxfrsource)
2749 REQUIRE(DNS_ZONE_VALID(zone));
2751 LOCK_ZONE(zone);
2752 zone->altxfrsource4 = *altxfrsource;
2753 UNLOCK_ZONE(zone);
2755 return (ISC_R_SUCCESS);
2758 isc_sockaddr_t *
2759 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
2760 REQUIRE(DNS_ZONE_VALID(zone));
2761 return (&zone->altxfrsource4);
2764 isc_result_t
2765 dns_zone_setaltxfrsource6(dns_zone_t *zone,
2766 const isc_sockaddr_t *altxfrsource)
2768 REQUIRE(DNS_ZONE_VALID(zone));
2770 LOCK_ZONE(zone);
2771 zone->altxfrsource6 = *altxfrsource;
2772 UNLOCK_ZONE(zone);
2774 return (ISC_R_SUCCESS);
2777 isc_sockaddr_t *
2778 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
2779 REQUIRE(DNS_ZONE_VALID(zone));
2780 return (&zone->altxfrsource6);
2783 isc_result_t
2784 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
2785 REQUIRE(DNS_ZONE_VALID(zone));
2787 LOCK_ZONE(zone);
2788 zone->notifysrc4 = *notifysrc;
2789 UNLOCK_ZONE(zone);
2791 return (ISC_R_SUCCESS);
2794 isc_sockaddr_t *
2795 dns_zone_getnotifysrc4(dns_zone_t *zone) {
2796 REQUIRE(DNS_ZONE_VALID(zone));
2797 return (&zone->notifysrc4);
2800 isc_result_t
2801 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
2802 REQUIRE(DNS_ZONE_VALID(zone));
2804 LOCK_ZONE(zone);
2805 zone->notifysrc6 = *notifysrc;
2806 UNLOCK_ZONE(zone);
2808 return (ISC_R_SUCCESS);
2811 isc_sockaddr_t *
2812 dns_zone_getnotifysrc6(dns_zone_t *zone) {
2813 REQUIRE(DNS_ZONE_VALID(zone));
2814 return (&zone->notifysrc6);
2817 isc_result_t
2818 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
2819 isc_uint32_t count)
2821 isc_sockaddr_t *new;
2823 REQUIRE(DNS_ZONE_VALID(zone));
2824 REQUIRE(count == 0 || notify != NULL);
2826 LOCK_ZONE(zone);
2827 if (zone->notify != NULL) {
2828 isc_mem_put(zone->mctx, zone->notify,
2829 zone->notifycnt * sizeof(*new));
2830 zone->notify = NULL;
2831 zone->notifycnt = 0;
2833 if (count != 0) {
2834 new = isc_mem_get(zone->mctx, count * sizeof(*new));
2835 if (new == NULL) {
2836 UNLOCK_ZONE(zone);
2837 return (ISC_R_NOMEMORY);
2839 memcpy(new, notify, count * sizeof(*new));
2840 zone->notify = new;
2841 zone->notifycnt = count;
2843 UNLOCK_ZONE(zone);
2844 return (ISC_R_SUCCESS);
2847 isc_result_t
2848 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
2849 isc_uint32_t count)
2851 isc_result_t result;
2853 result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
2854 return (result);
2857 static isc_boolean_t
2858 same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
2859 isc_uint32_t count)
2861 unsigned int i;
2863 for (i = 0; i < count; i++)
2864 if (!isc_sockaddr_equal(&old[i], &new[i]))
2865 return (ISC_FALSE);
2866 return (ISC_TRUE);
2869 static isc_boolean_t
2870 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
2871 unsigned int i;
2873 if (old == NULL && new == NULL)
2874 return (ISC_TRUE);
2875 if (old == NULL || new == NULL)
2876 return (ISC_FALSE);
2878 for (i = 0; i < count; i++) {
2879 if (old[i] == NULL && new[i] == NULL)
2880 continue;
2881 if (old[i] == NULL || new[i] == NULL ||
2882 !dns_name_equal(old[i], new[i]))
2883 return (ISC_FALSE);
2885 return (ISC_TRUE);
2888 isc_result_t
2889 dns_zone_setmasterswithkeys(dns_zone_t *zone,
2890 const isc_sockaddr_t *masters,
2891 dns_name_t **keynames,
2892 isc_uint32_t count)
2894 isc_sockaddr_t *new;
2895 isc_result_t result = ISC_R_SUCCESS;
2896 dns_name_t **newname;
2897 isc_boolean_t *newok;
2898 unsigned int i;
2900 REQUIRE(DNS_ZONE_VALID(zone));
2901 REQUIRE(count == 0 || masters != NULL);
2902 if (keynames != NULL) {
2903 REQUIRE(count != 0);
2906 LOCK_ZONE(zone);
2908 * The refresh code assumes that 'masters' wouldn't change under it.
2909 * If it will change then kill off any current refresh in progress
2910 * and update the masters info. If it won't change then we can just
2911 * unlock and exit.
2913 if (count != zone->masterscnt ||
2914 !same_masters(zone->masters, masters, count) ||
2915 !same_keynames(zone->masterkeynames, keynames, count)) {
2916 if (zone->request != NULL)
2917 dns_request_cancel(zone->request);
2918 } else
2919 goto unlock;
2920 if (zone->masters != NULL) {
2921 isc_mem_put(zone->mctx, zone->masters,
2922 zone->masterscnt * sizeof(*new));
2923 zone->masters = NULL;
2925 if (zone->masterkeynames != NULL) {
2926 for (i = 0; i < zone->masterscnt; i++) {
2927 if (zone->masterkeynames[i] != NULL) {
2928 dns_name_free(zone->masterkeynames[i],
2929 zone->mctx);
2930 isc_mem_put(zone->mctx,
2931 zone->masterkeynames[i],
2932 sizeof(dns_name_t));
2933 zone->masterkeynames[i] = NULL;
2936 isc_mem_put(zone->mctx, zone->masterkeynames,
2937 zone->masterscnt * sizeof(dns_name_t *));
2938 zone->masterkeynames = NULL;
2940 if (zone->mastersok != NULL) {
2941 isc_mem_put(zone->mctx, zone->mastersok,
2942 zone->masterscnt * sizeof(isc_boolean_t));
2943 zone->mastersok = NULL;
2945 zone->masterscnt = 0;
2947 * If count == 0, don't allocate any space for masters, mastersok or
2948 * keynames so internally, those pointers are NULL if count == 0
2950 if (count == 0)
2951 goto unlock;
2954 * masters must contain count elements!
2956 new = isc_mem_get(zone->mctx, count * sizeof(*new));
2957 if (new == NULL) {
2958 result = ISC_R_NOMEMORY;
2959 goto unlock;
2961 memcpy(new, masters, count * sizeof(*new));
2964 * Similarly for mastersok.
2966 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
2967 if (newok == NULL) {
2968 result = ISC_R_NOMEMORY;
2969 isc_mem_put(zone->mctx, new, count * sizeof(*new));
2970 goto unlock;
2972 for (i = 0; i < count; i++)
2973 newok[i] = ISC_FALSE;
2976 * if keynames is non-NULL, it must contain count elements!
2978 newname = NULL;
2979 if (keynames != NULL) {
2980 newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
2981 if (newname == NULL) {
2982 result = ISC_R_NOMEMORY;
2983 isc_mem_put(zone->mctx, new, count * sizeof(*new));
2984 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
2985 goto unlock;
2987 for (i = 0; i < count; i++)
2988 newname[i] = NULL;
2989 for (i = 0; i < count; i++) {
2990 if (keynames[i] != NULL) {
2991 newname[i] = isc_mem_get(zone->mctx,
2992 sizeof(dns_name_t));
2993 if (newname[i] == NULL)
2994 goto allocfail;
2995 dns_name_init(newname[i], NULL);
2996 result = dns_name_dup(keynames[i], zone->mctx,
2997 newname[i]);
2998 if (result != ISC_R_SUCCESS) {
2999 allocfail:
3000 for (i = 0; i < count; i++)
3001 if (newname[i] != NULL)
3002 dns_name_free(
3003 newname[i],
3004 zone->mctx);
3005 isc_mem_put(zone->mctx, new,
3006 count * sizeof(*new));
3007 isc_mem_put(zone->mctx, newok,
3008 count * sizeof(*newok));
3009 isc_mem_put(zone->mctx, newname,
3010 count * sizeof(*newname));
3011 goto unlock;
3018 * Everything is ok so attach to the zone.
3020 zone->masters = new;
3021 zone->mastersok = newok;
3022 zone->masterkeynames = newname;
3023 zone->masterscnt = count;
3024 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
3026 unlock:
3027 UNLOCK_ZONE(zone);
3028 return (result);
3031 isc_result_t
3032 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
3033 isc_result_t result = ISC_R_SUCCESS;
3035 REQUIRE(DNS_ZONE_VALID(zone));
3037 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3038 if (zone->db == NULL)
3039 result = DNS_R_NOTLOADED;
3040 else
3041 dns_db_attach(zone->db, dpb);
3042 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3044 return (result);
3048 * Co-ordinates the starting of routine jobs.
3051 void
3052 dns_zone_maintenance(dns_zone_t *zone) {
3053 const char me[] = "dns_zone_maintenance";
3054 isc_time_t now;
3056 REQUIRE(DNS_ZONE_VALID(zone));
3057 ENTER;
3059 LOCK_ZONE(zone);
3060 TIME_NOW(&now);
3061 zone_settimer(zone, &now);
3062 UNLOCK_ZONE(zone);
3065 static inline isc_boolean_t
3066 was_dumping(dns_zone_t *zone) {
3067 isc_boolean_t dumping;
3069 REQUIRE(LOCKED_ZONE(zone));
3071 dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
3072 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
3073 if (!dumping) {
3074 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3075 isc_time_settoepoch(&zone->dumptime);
3077 return (dumping);
3080 static void
3081 zone_maintenance(dns_zone_t *zone) {
3082 const char me[] = "zone_maintenance";
3083 isc_time_t now;
3084 isc_result_t result;
3085 isc_boolean_t dumping;
3087 REQUIRE(DNS_ZONE_VALID(zone));
3088 ENTER;
3091 * Configuring the view of this zone may have
3092 * failed, for example because the config file
3093 * had a syntax error. In that case, the view
3094 * adb or resolver, and we had better not try
3095 * to do maintenance on it.
3097 if (zone->view == NULL || zone->view->adb == NULL)
3098 return;
3100 TIME_NOW(&now);
3103 * Expire check.
3105 switch (zone->type) {
3106 case dns_zone_slave:
3107 case dns_zone_stub:
3108 LOCK_ZONE(zone);
3109 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
3110 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3111 zone_expire(zone);
3112 zone->refreshtime = now;
3114 UNLOCK_ZONE(zone);
3115 break;
3116 default:
3117 break;
3121 * Up to date check.
3123 switch (zone->type) {
3124 case dns_zone_slave:
3125 case dns_zone_stub:
3126 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
3127 isc_time_compare(&now, &zone->refreshtime) >= 0)
3128 dns_zone_refresh(zone);
3129 break;
3130 default:
3131 break;
3135 * Do we need to consolidate the backing store?
3137 switch (zone->type) {
3138 case dns_zone_master:
3139 case dns_zone_slave:
3140 LOCK_ZONE(zone);
3141 if (zone->masterfile != NULL &&
3142 isc_time_compare(&now, &zone->dumptime) >= 0 &&
3143 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
3144 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
3145 dumping = was_dumping(zone);
3146 } else
3147 dumping = ISC_TRUE;
3148 UNLOCK_ZONE(zone);
3149 if (!dumping) {
3150 result = zone_dump(zone, ISC_TRUE); /* task locked */
3151 if (result != ISC_R_SUCCESS)
3152 dns_zone_log(zone, ISC_LOG_WARNING,
3153 "dump failed: %s",
3154 dns_result_totext(result));
3156 break;
3157 default:
3158 break;
3162 * Do we need to send out notify messages?
3164 switch (zone->type) {
3165 case dns_zone_master:
3166 case dns_zone_slave:
3167 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
3168 isc_time_compare(&now, &zone->notifytime) >= 0)
3169 zone_notify(zone, &now);
3170 break;
3171 default:
3172 break;
3174 zone_settimer(zone, &now);
3177 void
3178 dns_zone_markdirty(dns_zone_t *zone) {
3180 LOCK_ZONE(zone);
3181 zone_needdump(zone, DNS_DUMP_DELAY);
3182 UNLOCK_ZONE(zone);
3185 void
3186 dns_zone_expire(dns_zone_t *zone) {
3187 REQUIRE(DNS_ZONE_VALID(zone));
3189 LOCK_ZONE(zone);
3190 zone_expire(zone);
3191 UNLOCK_ZONE(zone);
3194 static void
3195 zone_expire(dns_zone_t *zone) {
3197 * 'zone' locked by caller.
3200 REQUIRE(LOCKED_ZONE(zone));
3202 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
3204 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
3205 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
3206 zone->retry = DNS_ZONE_DEFAULTRETRY;
3207 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
3208 zone_unload(zone);
3211 void
3212 dns_zone_refresh(dns_zone_t *zone) {
3213 isc_interval_t i;
3214 isc_uint32_t oldflags;
3215 unsigned int j;
3216 isc_result_t result;
3218 REQUIRE(DNS_ZONE_VALID(zone));
3220 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
3221 return;
3224 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
3225 * in progress at a time.
3228 LOCK_ZONE(zone);
3229 oldflags = zone->flags;
3230 if (zone->masterscnt == 0) {
3231 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
3232 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
3233 dns_zone_log(zone, ISC_LOG_ERROR,
3234 "cannot refresh: no masters");
3235 goto unlock;
3237 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
3238 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
3239 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
3240 if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
3241 goto unlock;
3244 * Set the next refresh time as if refresh check has failed.
3245 * Setting this to the retry time will do that. XXXMLG
3246 * If we are successful it will be reset using zone->refresh.
3248 isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
3250 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
3251 if (result |= ISC_R_SUCCESS)
3252 dns_zone_log(zone, ISC_LOG_WARNING,
3253 "isc_time_nowplusinterval() failed: %s",
3254 dns_result_totext(result));
3257 * When lacking user-specified timer values from the SOA,
3258 * do exponential backoff of the retry time up to a
3259 * maximum of six hours.
3261 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
3262 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
3264 zone->curmaster = 0;
3265 for (j = 0; j < zone->masterscnt; j++)
3266 zone->mastersok[j] = ISC_FALSE;
3267 /* initiate soa query */
3268 queue_soa_query(zone);
3269 unlock:
3270 UNLOCK_ZONE(zone);
3273 isc_result_t
3274 dns_zone_flush(dns_zone_t *zone) {
3275 isc_result_t result = ISC_R_SUCCESS;
3276 isc_boolean_t dumping;
3278 REQUIRE(DNS_ZONE_VALID(zone));
3280 LOCK_ZONE(zone);
3281 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
3282 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
3283 zone->masterfile != NULL) {
3284 result = ISC_R_ALREADYRUNNING;
3285 dumping = was_dumping(zone);
3286 } else
3287 dumping = ISC_TRUE;
3288 UNLOCK_ZONE(zone);
3289 if (!dumping)
3290 result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
3291 return (result);
3294 isc_result_t
3295 dns_zone_dump(dns_zone_t *zone) {
3296 isc_result_t result = ISC_R_ALREADYRUNNING;
3297 isc_boolean_t dumping;
3299 REQUIRE(DNS_ZONE_VALID(zone));
3301 LOCK_ZONE(zone);
3302 dumping = was_dumping(zone);
3303 UNLOCK_ZONE(zone);
3304 if (!dumping)
3305 result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
3306 return (result);
3309 static void
3310 zone_needdump(dns_zone_t *zone, unsigned int delay) {
3311 isc_time_t dumptime;
3312 isc_time_t now;
3315 * 'zone' locked by caller
3318 REQUIRE(DNS_ZONE_VALID(zone));
3319 REQUIRE(LOCKED_ZONE(zone));
3322 * Do we have a place to dump to and are we loaded?
3324 if (zone->masterfile == NULL ||
3325 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
3326 return;
3328 TIME_NOW(&now);
3329 /* add some noise */
3330 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
3332 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3333 if (isc_time_isepoch(&zone->dumptime) ||
3334 isc_time_compare(&zone->dumptime, &dumptime) > 0)
3335 zone->dumptime = dumptime;
3336 if (zone->task != NULL)
3337 zone_settimer(zone, &now);
3340 static void
3341 dump_done(void *arg, isc_result_t result) {
3342 const char me[] = "dump_done";
3343 dns_zone_t *zone = arg;
3344 dns_db_t *db;
3345 dns_dbversion_t *version;
3346 isc_boolean_t again = ISC_FALSE;
3347 isc_boolean_t compact = ISC_FALSE;
3348 isc_uint32_t serial;
3349 isc_result_t tresult;
3351 REQUIRE(DNS_ZONE_VALID(zone));
3353 ENTER;
3355 if (result == ISC_R_SUCCESS && zone->journal != NULL &&
3356 zone->journalsize != -1) {
3359 * We don't own these, zone->dctx must stay valid.
3361 db = dns_dumpctx_db(zone->dctx);
3362 version = dns_dumpctx_version(zone->dctx);
3364 tresult = dns_db_getsoaserial(db, version, &serial);
3366 * Note: we are task locked here so we can test
3367 * zone->xfr safely.
3369 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
3370 tresult = dns_journal_compact(zone->mctx,
3371 zone->journal,
3372 serial,
3373 zone->journalsize);
3374 switch (tresult) {
3375 case ISC_R_SUCCESS:
3376 case ISC_R_NOSPACE:
3377 case ISC_R_NOTFOUND:
3378 dns_zone_log(zone, ISC_LOG_DEBUG(3),
3379 "dns_journal_compact: %s",
3380 dns_result_totext(tresult));
3381 break;
3382 default:
3383 dns_zone_log(zone, ISC_LOG_ERROR,
3384 "dns_journal_compact failed: %s",
3385 dns_result_totext(tresult));
3386 break;
3388 } else if (tresult == ISC_R_SUCCESS) {
3389 compact = ISC_TRUE;
3390 zone->compact_serial = serial;
3394 LOCK_ZONE(zone);
3395 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
3396 if (compact)
3397 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
3398 if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
3400 * Try again in a short while.
3402 zone_needdump(zone, DNS_DUMP_DELAY);
3403 } else if (result == ISC_R_SUCCESS &&
3404 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
3405 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
3406 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3407 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3408 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
3409 isc_time_settoepoch(&zone->dumptime);
3410 again = ISC_TRUE;
3411 } else if (result == ISC_R_SUCCESS)
3412 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
3414 if (zone->dctx != NULL)
3415 dns_dumpctx_detach(&zone->dctx);
3416 zonemgr_putio(&zone->writeio);
3417 UNLOCK_ZONE(zone);
3418 if (again)
3419 (void)zone_dump(zone, ISC_FALSE);
3420 dns_zone_idetach(&zone);
3423 static isc_result_t
3424 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
3425 const char me[] = "zone_dump";
3426 isc_result_t result;
3427 dns_dbversion_t *version = NULL;
3428 isc_boolean_t again;
3429 dns_db_t *db = NULL;
3430 char *masterfile = NULL;
3431 dns_masterformat_t masterformat = dns_masterformat_none;
3434 * 'compact' MUST only be set if we are task locked.
3437 REQUIRE(DNS_ZONE_VALID(zone));
3438 ENTER;
3440 redo:
3441 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3442 if (zone->db != NULL)
3443 dns_db_attach(zone->db, &db);
3444 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3445 LOCK_ZONE(zone);
3446 if (zone->masterfile != NULL) {
3447 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
3448 masterformat = zone->masterformat;
3450 UNLOCK_ZONE(zone);
3451 if (db == NULL) {
3452 result = DNS_R_NOTLOADED;
3453 goto fail;
3455 if (masterfile == NULL) {
3456 result = DNS_R_NOMASTERFILE;
3457 goto fail;
3460 if (compact) {
3461 dns_zone_t *dummy = NULL;
3462 LOCK_ZONE(zone);
3463 zone_iattach(zone, &dummy);
3464 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
3465 zone_gotwritehandle, zone,
3466 &zone->writeio);
3467 if (result != ISC_R_SUCCESS)
3468 zone_idetach(&dummy);
3469 else
3470 result = DNS_R_CONTINUE;
3471 UNLOCK_ZONE(zone);
3472 } else {
3473 dns_db_currentversion(db, &version);
3474 result = dns_master_dump2(zone->mctx, db, version,
3475 &dns_master_style_default,
3476 masterfile, masterformat);
3477 dns_db_closeversion(db, &version, ISC_FALSE);
3479 fail:
3480 if (db != NULL)
3481 dns_db_detach(&db);
3482 if (masterfile != NULL)
3483 isc_mem_free(zone->mctx, masterfile);
3484 masterfile = NULL;
3486 if (result == DNS_R_CONTINUE)
3487 return (ISC_R_SUCCESS); /* XXXMPA */
3489 again = ISC_FALSE;
3490 LOCK_ZONE(zone);
3491 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
3492 if (result != ISC_R_SUCCESS) {
3494 * Try again in a short while.
3496 zone_needdump(zone, DNS_DUMP_DELAY);
3497 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
3498 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
3499 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3500 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3501 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
3502 isc_time_settoepoch(&zone->dumptime);
3503 again = ISC_TRUE;
3504 } else
3505 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
3506 UNLOCK_ZONE(zone);
3507 if (again)
3508 goto redo;
3510 return (result);
3513 static isc_result_t
3514 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
3515 dns_masterformat_t format)
3517 isc_result_t result;
3518 dns_dbversion_t *version = NULL;
3519 dns_db_t *db = NULL;
3521 REQUIRE(DNS_ZONE_VALID(zone));
3523 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3524 if (zone->db != NULL)
3525 dns_db_attach(zone->db, &db);
3526 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3527 if (db == NULL)
3528 return (DNS_R_NOTLOADED);
3530 dns_db_currentversion(db, &version);
3531 result = dns_master_dumptostream2(zone->mctx, db, version, style,
3532 format, fd);
3533 dns_db_closeversion(db, &version, ISC_FALSE);
3534 dns_db_detach(&db);
3535 return (result);
3538 isc_result_t
3539 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
3540 const dns_master_style_t *style) {
3541 return dumptostream(zone, fd, style, format);
3544 isc_result_t
3545 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
3546 return dumptostream(zone, fd, &dns_master_style_default,
3547 dns_masterformat_text);
3550 isc_result_t
3551 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
3552 return dumptostream(zone, fd, &dns_master_style_full,
3553 dns_masterformat_text);
3556 void
3557 dns_zone_unload(dns_zone_t *zone) {
3558 REQUIRE(DNS_ZONE_VALID(zone));
3560 LOCK_ZONE(zone);
3561 zone_unload(zone);
3562 UNLOCK_ZONE(zone);
3565 static void
3566 notify_cancel(dns_zone_t *zone) {
3567 dns_notify_t *notify;
3570 * 'zone' locked by caller.
3573 REQUIRE(LOCKED_ZONE(zone));
3575 for (notify = ISC_LIST_HEAD(zone->notifies);
3576 notify != NULL;
3577 notify = ISC_LIST_NEXT(notify, link)) {
3578 if (notify->find != NULL)
3579 dns_adb_cancelfind(notify->find);
3580 if (notify->request != NULL)
3581 dns_request_cancel(notify->request);
3585 static void
3586 zone_unload(dns_zone_t *zone) {
3589 * 'zone' locked by caller.
3592 REQUIRE(LOCKED_ZONE(zone));
3594 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
3595 zone_detachdb(zone);
3596 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3597 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
3598 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3601 void
3602 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
3603 REQUIRE(DNS_ZONE_VALID(zone));
3604 REQUIRE(val > 0);
3606 zone->minrefresh = val;
3609 void
3610 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
3611 REQUIRE(DNS_ZONE_VALID(zone));
3612 REQUIRE(val > 0);
3614 zone->maxrefresh = val;
3617 void
3618 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
3619 REQUIRE(DNS_ZONE_VALID(zone));
3620 REQUIRE(val > 0);
3622 zone->minretry = val;
3625 void
3626 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
3627 REQUIRE(DNS_ZONE_VALID(zone));
3628 REQUIRE(val > 0);
3630 zone->maxretry = val;
3633 static isc_boolean_t
3634 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
3635 dns_notify_t *notify;
3637 for (notify = ISC_LIST_HEAD(zone->notifies);
3638 notify != NULL;
3639 notify = ISC_LIST_NEXT(notify, link)) {
3640 if (notify->request != NULL)
3641 continue;
3642 if (name != NULL && dns_name_dynamic(&notify->ns) &&
3643 dns_name_equal(name, &notify->ns))
3644 return (ISC_TRUE);
3645 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
3646 return (ISC_TRUE);
3648 return (ISC_FALSE);
3651 static isc_boolean_t
3652 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
3653 dns_tsigkey_t *key = NULL;
3654 isc_sockaddr_t src;
3655 isc_sockaddr_t any;
3656 isc_boolean_t isself;
3657 isc_netaddr_t dstaddr;
3659 if (zone->view == NULL || zone->isself == NULL)
3660 return (ISC_FALSE);
3662 switch (isc_sockaddr_pf(dst)) {
3663 case PF_INET:
3664 src = zone->notifysrc4;
3665 isc_sockaddr_any(&any);
3666 break;
3667 case PF_INET6:
3668 src = zone->notifysrc6;
3669 isc_sockaddr_any6(&any);
3670 break;
3671 default:
3672 return (ISC_FALSE);
3676 * When sending from any the kernel will assign a source address
3677 * that matches the destination address.
3679 if (isc_sockaddr_eqaddr(&any, &src))
3680 src = *dst;
3682 isc_netaddr_fromsockaddr(&dstaddr, dst);
3683 (void)dns_view_getpeertsig(zone->view, &dstaddr, &key);
3684 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
3685 zone->isselfarg);
3686 if (key != NULL)
3687 dns_tsigkey_detach(&key);
3688 return (isself);
3691 static void
3692 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
3693 isc_mem_t *mctx;
3696 * Caller holds zone lock.
3698 REQUIRE(DNS_NOTIFY_VALID(notify));
3700 if (notify->zone != NULL) {
3701 if (!locked)
3702 LOCK_ZONE(notify->zone);
3703 REQUIRE(LOCKED_ZONE(notify->zone));
3704 if (ISC_LINK_LINKED(notify, link))
3705 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
3706 if (!locked)
3707 UNLOCK_ZONE(notify->zone);
3708 if (locked)
3709 zone_idetach(&notify->zone);
3710 else
3711 dns_zone_idetach(&notify->zone);
3713 if (notify->find != NULL)
3714 dns_adb_destroyfind(&notify->find);
3715 if (notify->request != NULL)
3716 dns_request_destroy(&notify->request);
3717 if (dns_name_dynamic(&notify->ns))
3718 dns_name_free(&notify->ns, notify->mctx);
3719 mctx = notify->mctx;
3720 isc_mem_put(notify->mctx, notify, sizeof(*notify));
3721 isc_mem_detach(&mctx);
3724 static isc_result_t
3725 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
3726 dns_notify_t *notify;
3728 REQUIRE(notifyp != NULL && *notifyp == NULL);
3730 notify = isc_mem_get(mctx, sizeof(*notify));
3731 if (notify == NULL)
3732 return (ISC_R_NOMEMORY);
3734 notify->mctx = NULL;
3735 isc_mem_attach(mctx, &notify->mctx);
3736 notify->flags = flags;
3737 notify->zone = NULL;
3738 notify->find = NULL;
3739 notify->request = NULL;
3740 isc_sockaddr_any(&notify->dst);
3741 dns_name_init(&notify->ns, NULL);
3742 ISC_LINK_INIT(notify, link);
3743 notify->magic = NOTIFY_MAGIC;
3744 *notifyp = notify;
3745 return (ISC_R_SUCCESS);
3749 * XXXAG should check for DNS_ZONEFLG_EXITING
3751 static void
3752 process_adb_event(isc_task_t *task, isc_event_t *ev) {
3753 dns_notify_t *notify;
3754 isc_eventtype_t result;
3756 UNUSED(task);
3758 notify = ev->ev_arg;
3759 REQUIRE(DNS_NOTIFY_VALID(notify));
3760 INSIST(task == notify->zone->task);
3761 result = ev->ev_type;
3762 isc_event_free(&ev);
3763 if (result == DNS_EVENT_ADBMOREADDRESSES) {
3764 dns_adb_destroyfind(&notify->find);
3765 notify_find_address(notify);
3766 return;
3768 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
3769 LOCK_ZONE(notify->zone);
3770 notify_send(notify);
3771 UNLOCK_ZONE(notify->zone);
3773 notify_destroy(notify, ISC_FALSE);
3776 static void
3777 notify_find_address(dns_notify_t *notify) {
3778 isc_result_t result;
3779 unsigned int options;
3781 REQUIRE(DNS_NOTIFY_VALID(notify));
3782 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
3783 DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
3785 if (notify->zone->view->adb == NULL)
3786 goto destroy;
3788 result = dns_adb_createfind(notify->zone->view->adb,
3789 notify->zone->task,
3790 process_adb_event, notify,
3791 &notify->ns, dns_rootname, 0,
3792 options, 0, NULL,
3793 notify->zone->view->dstport,
3794 &notify->find);
3796 /* Something failed? */
3797 if (result != ISC_R_SUCCESS)
3798 goto destroy;
3800 /* More addresses pending? */
3801 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
3802 return;
3804 /* We have as many addresses as we can get. */
3805 LOCK_ZONE(notify->zone);
3806 notify_send(notify);
3807 UNLOCK_ZONE(notify->zone);
3809 destroy:
3810 notify_destroy(notify, ISC_FALSE);
3814 static isc_result_t
3815 notify_send_queue(dns_notify_t *notify) {
3816 isc_event_t *e;
3817 isc_result_t result;
3819 e = isc_event_allocate(notify->mctx, NULL,
3820 DNS_EVENT_NOTIFYSENDTOADDR,
3821 notify_send_toaddr,
3822 notify, sizeof(isc_event_t));
3823 if (e == NULL)
3824 return (ISC_R_NOMEMORY);
3825 e->ev_arg = notify;
3826 e->ev_sender = NULL;
3827 result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
3828 notify->zone->task, &e);
3829 if (result != ISC_R_SUCCESS)
3830 isc_event_free(&e);
3831 return (result);
3834 static void
3835 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
3836 dns_notify_t *notify;
3837 isc_result_t result;
3838 dns_message_t *message = NULL;
3839 isc_netaddr_t dstip;
3840 dns_tsigkey_t *key = NULL;
3841 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
3842 isc_sockaddr_t src;
3843 int timeout;
3844 isc_boolean_t have_notifysource = ISC_FALSE;
3846 notify = event->ev_arg;
3847 REQUIRE(DNS_NOTIFY_VALID(notify));
3849 UNUSED(task);
3851 LOCK_ZONE(notify->zone);
3853 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
3854 result = ISC_R_CANCELED;
3855 goto cleanup;
3858 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
3859 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
3860 notify->zone->view->requestmgr == NULL ||
3861 notify->zone->db == NULL) {
3862 result = ISC_R_CANCELED;
3863 goto cleanup;
3867 * The raw IPv4 address should also exist. Don't send to the
3868 * mapped form.
3870 if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
3871 IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
3872 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
3873 notify_log(notify->zone, ISC_LOG_DEBUG(3),
3874 "notify: ignoring IPv6 mapped IPV4 address: %s",
3875 addrbuf);
3876 result = ISC_R_CANCELED;
3877 goto cleanup;
3880 result = notify_createmessage(notify->zone, notify->flags, &message);
3881 if (result != ISC_R_SUCCESS)
3882 goto cleanup;
3884 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
3885 (void)dns_view_getpeertsig(notify->zone->view, &dstip, &key);
3887 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
3888 notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
3889 addrbuf);
3890 if (notify->zone->view->peers != NULL) {
3891 dns_peer_t *peer = NULL;
3892 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
3893 &dstip, &peer);
3894 if (result == ISC_R_SUCCESS) {
3895 result = dns_peer_getnotifysource(peer, &src);
3896 if (result == ISC_R_SUCCESS)
3897 have_notifysource = ISC_TRUE;
3900 switch (isc_sockaddr_pf(&notify->dst)) {
3901 case PF_INET:
3902 if (!have_notifysource)
3903 src = notify->zone->notifysrc4;
3904 break;
3905 case PF_INET6:
3906 if (!have_notifysource)
3907 src = notify->zone->notifysrc6;
3908 break;
3909 default:
3910 result = ISC_R_NOTIMPLEMENTED;
3911 goto cleanup_key;
3913 timeout = 15;
3914 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
3915 timeout = 30;
3916 result = dns_request_createvia2(notify->zone->view->requestmgr,
3917 message, &src, &notify->dst, 0, key,
3918 timeout * 3, timeout,
3919 notify->zone->task, notify_done,
3920 notify, &notify->request);
3921 if (result == ISC_R_SUCCESS) {
3922 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
3923 inc_stats(notify->zone,
3924 dns_zonestatscounter_notifyoutv4);
3925 } else {
3926 inc_stats(notify->zone,
3927 dns_zonestatscounter_notifyoutv6);
3931 cleanup_key:
3932 if (key != NULL)
3933 dns_tsigkey_detach(&key);
3934 dns_message_destroy(&message);
3935 cleanup:
3936 UNLOCK_ZONE(notify->zone);
3937 if (result != ISC_R_SUCCESS)
3938 notify_destroy(notify, ISC_FALSE);
3939 isc_event_free(&event);
3942 static void
3943 notify_send(dns_notify_t *notify) {
3944 dns_adbaddrinfo_t *ai;
3945 isc_sockaddr_t dst;
3946 isc_result_t result;
3947 dns_notify_t *new = NULL;
3950 * Zone lock held by caller.
3952 REQUIRE(DNS_NOTIFY_VALID(notify));
3953 REQUIRE(LOCKED_ZONE(notify->zone));
3955 for (ai = ISC_LIST_HEAD(notify->find->list);
3956 ai != NULL;
3957 ai = ISC_LIST_NEXT(ai, publink)) {
3958 dst = ai->sockaddr;
3959 if (notify_isqueued(notify->zone, NULL, &dst))
3960 continue;
3961 if (notify_isself(notify->zone, &dst))
3962 continue;
3963 new = NULL;
3964 result = notify_create(notify->mctx,
3965 (notify->flags & DNS_NOTIFY_NOSOA),
3966 &new);
3967 if (result != ISC_R_SUCCESS)
3968 goto cleanup;
3969 zone_iattach(notify->zone, &new->zone);
3970 ISC_LIST_APPEND(new->zone->notifies, new, link);
3971 new->dst = dst;
3972 result = notify_send_queue(new);
3973 if (result != ISC_R_SUCCESS)
3974 goto cleanup;
3975 new = NULL;
3978 cleanup:
3979 if (new != NULL)
3980 notify_destroy(new, ISC_TRUE);
3983 void
3984 dns_zone_notify(dns_zone_t *zone) {
3985 isc_time_t now;
3987 REQUIRE(DNS_ZONE_VALID(zone));
3989 LOCK_ZONE(zone);
3990 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
3992 TIME_NOW(&now);
3993 zone_settimer(zone, &now);
3994 UNLOCK_ZONE(zone);
3997 static void
3998 zone_notify(dns_zone_t *zone, isc_time_t *now) {
3999 dns_dbnode_t *node = NULL;
4000 dns_db_t *zonedb = NULL;
4001 dns_dbversion_t *version = NULL;
4002 dns_name_t *origin = NULL;
4003 dns_name_t master;
4004 dns_rdata_ns_t ns;
4005 dns_rdata_soa_t soa;
4006 isc_uint32_t serial;
4007 dns_rdata_t rdata = DNS_RDATA_INIT;
4008 dns_rdataset_t nsrdset;
4009 dns_rdataset_t soardset;
4010 isc_result_t result;
4011 dns_notify_t *notify = NULL;
4012 unsigned int i;
4013 isc_sockaddr_t dst;
4014 isc_boolean_t isqueued;
4015 dns_notifytype_t notifytype;
4016 unsigned int flags = 0;
4017 isc_boolean_t loggednotify = ISC_FALSE;
4019 REQUIRE(DNS_ZONE_VALID(zone));
4021 LOCK_ZONE(zone);
4022 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
4023 notifytype = zone->notifytype;
4024 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
4025 UNLOCK_ZONE(zone);
4027 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4028 return;
4030 if (notifytype == dns_notifytype_no)
4031 return;
4033 if (notifytype == dns_notifytype_masteronly &&
4034 zone->type != dns_zone_master)
4035 return;
4037 origin = &zone->origin;
4040 * If the zone is dialup we are done as we don't want to send
4041 * the current soa so as to force a refresh query.
4043 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
4044 flags |= DNS_NOTIFY_NOSOA;
4047 * Get SOA RRset.
4049 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4050 if (zone->db != NULL)
4051 dns_db_attach(zone->db, &zonedb);
4052 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4053 if (zonedb == NULL)
4054 return;
4055 dns_db_currentversion(zonedb, &version);
4056 result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
4057 if (result != ISC_R_SUCCESS)
4058 goto cleanup1;
4060 dns_rdataset_init(&soardset);
4061 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
4062 dns_rdatatype_none, 0, &soardset, NULL);
4063 if (result != ISC_R_SUCCESS)
4064 goto cleanup2;
4067 * Find serial and master server's name.
4069 dns_name_init(&master, NULL);
4070 result = dns_rdataset_first(&soardset);
4071 if (result != ISC_R_SUCCESS)
4072 goto cleanup3;
4073 dns_rdataset_current(&soardset, &rdata);
4074 result = dns_rdata_tostruct(&rdata, &soa, NULL);
4075 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4076 dns_rdata_reset(&rdata);
4077 result = dns_name_dup(&soa.origin, zone->mctx, &master);
4078 serial = soa.serial;
4079 dns_rdataset_disassociate(&soardset);
4080 if (result != ISC_R_SUCCESS)
4081 goto cleanup3;
4084 * Enqueue notify requests for 'also-notify' servers.
4086 LOCK_ZONE(zone);
4087 for (i = 0; i < zone->notifycnt; i++) {
4088 dst = zone->notify[i];
4089 if (notify_isqueued(zone, NULL, &dst))
4090 continue;
4091 result = notify_create(zone->mctx, flags, &notify);
4092 if (result != ISC_R_SUCCESS)
4093 continue;
4094 zone_iattach(zone, &notify->zone);
4095 notify->dst = dst;
4096 ISC_LIST_APPEND(zone->notifies, notify, link);
4097 result = notify_send_queue(notify);
4098 if (result != ISC_R_SUCCESS)
4099 notify_destroy(notify, ISC_TRUE);
4100 if (!loggednotify) {
4101 notify_log(zone, ISC_LOG_INFO,
4102 "sending notifies (serial %u)",
4103 serial);
4104 loggednotify = ISC_TRUE;
4106 notify = NULL;
4108 UNLOCK_ZONE(zone);
4110 if (notifytype == dns_notifytype_explicit)
4111 goto cleanup3;
4114 * Process NS RRset to generate notifies.
4117 dns_rdataset_init(&nsrdset);
4118 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
4119 dns_rdatatype_none, 0, &nsrdset, NULL);
4120 if (result != ISC_R_SUCCESS)
4121 goto cleanup3;
4123 result = dns_rdataset_first(&nsrdset);
4124 while (result == ISC_R_SUCCESS) {
4125 dns_rdataset_current(&nsrdset, &rdata);
4126 result = dns_rdata_tostruct(&rdata, &ns, NULL);
4127 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4128 dns_rdata_reset(&rdata);
4130 * Don't notify the master server unless explicitly
4131 * configured to do so.
4133 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
4134 dns_name_compare(&master, &ns.name) == 0) {
4135 result = dns_rdataset_next(&nsrdset);
4136 continue;
4139 if (!loggednotify) {
4140 notify_log(zone, ISC_LOG_INFO,
4141 "sending notifies (serial %u)",
4142 serial);
4143 loggednotify = ISC_TRUE;
4146 LOCK_ZONE(zone);
4147 isqueued = notify_isqueued(zone, &ns.name, NULL);
4148 UNLOCK_ZONE(zone);
4149 if (isqueued) {
4150 result = dns_rdataset_next(&nsrdset);
4151 continue;
4153 result = notify_create(zone->mctx, flags, &notify);
4154 if (result != ISC_R_SUCCESS)
4155 continue;
4156 dns_zone_iattach(zone, &notify->zone);
4157 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
4158 if (result != ISC_R_SUCCESS) {
4159 LOCK_ZONE(zone);
4160 notify_destroy(notify, ISC_TRUE);
4161 UNLOCK_ZONE(zone);
4162 continue;
4164 LOCK_ZONE(zone);
4165 ISC_LIST_APPEND(zone->notifies, notify, link);
4166 UNLOCK_ZONE(zone);
4167 notify_find_address(notify);
4168 notify = NULL;
4169 result = dns_rdataset_next(&nsrdset);
4171 dns_rdataset_disassociate(&nsrdset);
4173 cleanup3:
4174 if (dns_name_dynamic(&master))
4175 dns_name_free(&master, zone->mctx);
4176 cleanup2:
4177 dns_db_detachnode(zonedb, &node);
4178 cleanup1:
4179 dns_db_closeversion(zonedb, &version, ISC_FALSE);
4180 dns_db_detach(&zonedb);
4183 /***
4184 *** Private
4185 ***/
4187 static inline isc_result_t
4188 save_nsrrset(dns_message_t *message, dns_name_t *name,
4189 dns_db_t *db, dns_dbversion_t *version)
4191 dns_rdataset_t *nsrdataset = NULL;
4192 dns_rdataset_t *rdataset = NULL;
4193 dns_dbnode_t *node = NULL;
4194 dns_rdata_ns_t ns;
4195 isc_result_t result;
4196 dns_rdata_t rdata = DNS_RDATA_INIT;
4199 * Extract NS RRset from message.
4201 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
4202 dns_rdatatype_ns, dns_rdatatype_none,
4203 NULL, &nsrdataset);
4204 if (result != ISC_R_SUCCESS)
4205 goto fail;
4208 * Add NS rdataset.
4210 result = dns_db_findnode(db, name, ISC_TRUE, &node);
4211 if (result != ISC_R_SUCCESS)
4212 goto fail;
4213 result = dns_db_addrdataset(db, node, version, 0,
4214 nsrdataset, 0, NULL);
4215 dns_db_detachnode(db, &node);
4216 if (result != ISC_R_SUCCESS)
4217 goto fail;
4219 * Add glue rdatasets.
4221 for (result = dns_rdataset_first(nsrdataset);
4222 result == ISC_R_SUCCESS;
4223 result = dns_rdataset_next(nsrdataset)) {
4224 dns_rdataset_current(nsrdataset, &rdata);
4225 result = dns_rdata_tostruct(&rdata, &ns, NULL);
4226 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4227 dns_rdata_reset(&rdata);
4228 if (!dns_name_issubdomain(&ns.name, name))
4229 continue;
4230 rdataset = NULL;
4231 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
4232 &ns.name, dns_rdatatype_aaaa,
4233 dns_rdatatype_none, NULL,
4234 &rdataset);
4235 if (result == ISC_R_SUCCESS) {
4236 result = dns_db_findnode(db, &ns.name,
4237 ISC_TRUE, &node);
4238 if (result != ISC_R_SUCCESS)
4239 goto fail;
4240 result = dns_db_addrdataset(db, node, version, 0,
4241 rdataset, 0, NULL);
4242 dns_db_detachnode(db, &node);
4243 if (result != ISC_R_SUCCESS)
4244 goto fail;
4246 rdataset = NULL;
4247 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
4248 &ns.name, dns_rdatatype_a,
4249 dns_rdatatype_none, NULL,
4250 &rdataset);
4251 if (result == ISC_R_SUCCESS) {
4252 result = dns_db_findnode(db, &ns.name,
4253 ISC_TRUE, &node);
4254 if (result != ISC_R_SUCCESS)
4255 goto fail;
4256 result = dns_db_addrdataset(db, node, version, 0,
4257 rdataset, 0, NULL);
4258 dns_db_detachnode(db, &node);
4259 if (result != ISC_R_SUCCESS)
4260 goto fail;
4263 if (result != ISC_R_NOMORE)
4264 goto fail;
4266 return (ISC_R_SUCCESS);
4268 fail:
4269 return (result);
4272 static void
4273 stub_callback(isc_task_t *task, isc_event_t *event) {
4274 const char me[] = "stub_callback";
4275 dns_requestevent_t *revent = (dns_requestevent_t *)event;
4276 dns_stub_t *stub = NULL;
4277 dns_message_t *msg = NULL;
4278 dns_zone_t *zone = NULL;
4279 char master[ISC_SOCKADDR_FORMATSIZE];
4280 char source[ISC_SOCKADDR_FORMATSIZE];
4281 isc_uint32_t nscnt, cnamecnt;
4282 isc_result_t result;
4283 isc_time_t now;
4284 isc_boolean_t exiting = ISC_FALSE;
4285 isc_interval_t i;
4286 unsigned int j;
4288 stub = revent->ev_arg;
4289 INSIST(DNS_STUB_VALID(stub));
4291 UNUSED(task);
4293 zone = stub->zone;
4295 ENTER;
4297 TIME_NOW(&now);
4299 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
4300 zone_debuglog(zone, me, 1, "exiting");
4301 exiting = ISC_TRUE;
4302 goto next_master;
4305 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
4306 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
4308 if (revent->result != ISC_R_SUCCESS) {
4309 if (revent->result == ISC_R_TIMEDOUT &&
4310 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
4311 LOCK_ZONE(zone);
4312 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4313 UNLOCK_ZONE(zone);
4314 dns_zone_log(zone, ISC_LOG_DEBUG(1),
4315 "refreshing stub: timeout retrying "
4316 " without EDNS master %s (source %s)",
4317 master, source);
4318 goto same_master;
4320 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
4321 &zone->sourceaddr, &now);
4322 dns_zone_log(zone, ISC_LOG_INFO,
4323 "could not refresh stub from master %s"
4324 " (source %s): %s", master, source,
4325 dns_result_totext(revent->result));
4326 goto next_master;
4329 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
4330 if (result != ISC_R_SUCCESS)
4331 goto next_master;
4333 result = dns_request_getresponse(revent->request, msg, 0);
4334 if (result != ISC_R_SUCCESS)
4335 goto next_master;
4338 * Unexpected rcode.
4340 if (msg->rcode != dns_rcode_noerror) {
4341 char rcode[128];
4342 isc_buffer_t rb;
4344 isc_buffer_init(&rb, rcode, sizeof(rcode));
4345 (void)dns_rcode_totext(msg->rcode, &rb);
4347 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
4348 (msg->rcode == dns_rcode_servfail ||
4349 msg->rcode == dns_rcode_notimp ||
4350 msg->rcode == dns_rcode_formerr)) {
4351 dns_zone_log(zone, ISC_LOG_DEBUG(1),
4352 "refreshing stub: rcode (%.*s) retrying "
4353 "without EDNS master %s (source %s)",
4354 (int)rb.used, rcode, master, source);
4355 LOCK_ZONE(zone);
4356 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4357 UNLOCK_ZONE(zone);
4358 goto same_master;
4361 dns_zone_log(zone, ISC_LOG_INFO,
4362 "refreshing stub: "
4363 "unexpected rcode (%.*s) from %s (source %s)",
4364 (int)rb.used, rcode, master, source);
4365 goto next_master;
4369 * We need complete messages.
4371 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
4372 if (dns_request_usedtcp(revent->request)) {
4373 dns_zone_log(zone, ISC_LOG_INFO,
4374 "refreshing stub: truncated TCP "
4375 "response from master %s (source %s)",
4376 master, source);
4377 goto next_master;
4379 LOCK_ZONE(zone);
4380 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
4381 UNLOCK_ZONE(zone);
4382 goto same_master;
4386 * If non-auth log and next master.
4388 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
4389 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
4390 "non-authoritative answer from "
4391 "master %s (source %s)", master, source);
4392 goto next_master;
4396 * Sanity checks.
4398 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
4399 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
4401 if (cnamecnt != 0) {
4402 dns_zone_log(zone, ISC_LOG_INFO,
4403 "refreshing stub: unexpected CNAME response "
4404 "from master %s (source %s)", master, source);
4405 goto next_master;
4408 if (nscnt == 0) {
4409 dns_zone_log(zone, ISC_LOG_INFO,
4410 "refreshing stub: no NS records in response "
4411 "from master %s (source %s)", master, source);
4412 goto next_master;
4416 * Save answer.
4418 result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
4419 if (result != ISC_R_SUCCESS) {
4420 dns_zone_log(zone, ISC_LOG_INFO,
4421 "refreshing stub: unable to save NS records "
4422 "from master %s (source %s)", master, source);
4423 goto next_master;
4427 * Tidy up.
4429 dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
4430 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4431 if (zone->db == NULL)
4432 zone_attachdb(zone, stub->db);
4433 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4434 dns_db_detach(&stub->db);
4436 if (zone->masterfile != NULL) {
4437 dns_zone_dump(zone);
4438 TIME_NOW(&zone->loadtime);
4441 dns_message_destroy(&msg);
4442 isc_event_free(&event);
4443 LOCK_ZONE(zone);
4444 dns_request_destroy(&zone->request);
4445 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4446 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
4447 isc_interval_set(&i, zone->expire, 0);
4448 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
4449 zone_settimer(zone, &now);
4450 UNLOCK_ZONE(zone);
4451 goto free_stub;
4453 next_master:
4454 if (stub->version != NULL)
4455 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
4456 if (stub->db != NULL)
4457 dns_db_detach(&stub->db);
4458 if (msg != NULL)
4459 dns_message_destroy(&msg);
4460 isc_event_free(&event);
4461 LOCK_ZONE(zone);
4462 dns_request_destroy(&zone->request);
4464 * Skip to next failed / untried master.
4466 do {
4467 zone->curmaster++;
4468 } while (zone->curmaster < zone->masterscnt &&
4469 zone->mastersok[zone->curmaster]);
4470 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
4471 if (exiting || zone->curmaster >= zone->masterscnt) {
4472 isc_boolean_t done = ISC_TRUE;
4473 if (!exiting &&
4474 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
4475 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
4477 * Did we get a good answer from all the masters?
4479 for (j = 0; j < zone->masterscnt; j++)
4480 if (zone->mastersok[j] == ISC_FALSE) {
4481 done = ISC_FALSE;
4482 break;
4484 } else
4485 done = ISC_TRUE;
4486 if (!done) {
4487 zone->curmaster = 0;
4489 * Find the next failed master.
4491 while (zone->curmaster < zone->masterscnt &&
4492 zone->mastersok[zone->curmaster])
4493 zone->curmaster++;
4494 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
4495 } else {
4496 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4498 zone_settimer(zone, &now);
4499 UNLOCK_ZONE(zone);
4500 goto free_stub;
4503 queue_soa_query(zone);
4504 UNLOCK_ZONE(zone);
4505 goto free_stub;
4507 same_master:
4508 if (msg != NULL)
4509 dns_message_destroy(&msg);
4510 isc_event_free(&event);
4511 LOCK_ZONE(zone);
4512 dns_request_destroy(&zone->request);
4513 UNLOCK_ZONE(zone);
4514 ns_query(zone, NULL, stub);
4515 goto done;
4517 free_stub:
4518 stub->magic = 0;
4519 dns_zone_idetach(&stub->zone);
4520 INSIST(stub->db == NULL);
4521 INSIST(stub->version == NULL);
4522 isc_mem_put(stub->mctx, stub, sizeof(*stub));
4524 done:
4525 INSIST(event == NULL);
4526 return;
4530 * An SOA query has finished (successfully or not).
4532 static void
4533 refresh_callback(isc_task_t *task, isc_event_t *event) {
4534 const char me[] = "refresh_callback";
4535 dns_requestevent_t *revent = (dns_requestevent_t *)event;
4536 dns_zone_t *zone;
4537 dns_message_t *msg = NULL;
4538 isc_uint32_t soacnt, cnamecnt, soacount, nscount;
4539 isc_time_t now;
4540 char master[ISC_SOCKADDR_FORMATSIZE];
4541 char source[ISC_SOCKADDR_FORMATSIZE];
4542 dns_rdataset_t *rdataset = NULL;
4543 dns_rdata_t rdata = DNS_RDATA_INIT;
4544 dns_rdata_soa_t soa;
4545 isc_result_t result;
4546 isc_uint32_t serial;
4547 unsigned int j;
4549 zone = revent->ev_arg;
4550 INSIST(DNS_ZONE_VALID(zone));
4552 UNUSED(task);
4554 ENTER;
4557 * if timeout log and next master;
4560 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
4561 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
4563 TIME_NOW(&now);
4565 if (revent->result != ISC_R_SUCCESS) {
4566 if (revent->result == ISC_R_TIMEDOUT &&
4567 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
4568 LOCK_ZONE(zone);
4569 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4570 UNLOCK_ZONE(zone);
4571 dns_zone_log(zone, ISC_LOG_DEBUG(1),
4572 "refresh: timeout retrying without EDNS "
4573 "master %s (source %s)", master, source);
4574 goto same_master;
4576 if (revent->result == ISC_R_TIMEDOUT &&
4577 !dns_request_usedtcp(revent->request)) {
4578 dns_zone_log(zone, ISC_LOG_INFO,
4579 "refresh: retry limit for "
4580 "master %s exceeded (source %s)",
4581 master, source);
4582 /* Try with slave with TCP. */
4583 if (zone->type == dns_zone_slave &&
4584 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
4585 if (!dns_zonemgr_unreachable(zone->zmgr,
4586 &zone->masteraddr,
4587 &zone->sourceaddr,
4588 &now)) {
4589 LOCK_ZONE(zone);
4590 DNS_ZONE_SETFLAG(zone,
4591 DNS_ZONEFLG_SOABEFOREAXFR);
4592 UNLOCK_ZONE(zone);
4593 goto tcp_transfer;
4595 dns_zone_log(zone, ISC_LOG_DEBUG(1),
4596 "refresh: skipped tcp fallback"
4597 "as master %s (source %s) is "
4598 "unreachable (cached)",
4599 master, source);
4601 } else
4602 dns_zone_log(zone, ISC_LOG_INFO,
4603 "refresh: failure trying master "
4604 "%s (source %s): %s", master, source,
4605 dns_result_totext(revent->result));
4606 goto next_master;
4609 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
4610 if (result != ISC_R_SUCCESS)
4611 goto next_master;
4612 result = dns_request_getresponse(revent->request, msg, 0);
4613 if (result != ISC_R_SUCCESS) {
4614 dns_zone_log(zone, ISC_LOG_INFO,
4615 "refresh: failure trying master "
4616 "%s (source %s): %s", master, source,
4617 dns_result_totext(result));
4618 goto next_master;
4622 * Unexpected rcode.
4624 if (msg->rcode != dns_rcode_noerror) {
4625 char rcode[128];
4626 isc_buffer_t rb;
4628 isc_buffer_init(&rb, rcode, sizeof(rcode));
4629 (void)dns_rcode_totext(msg->rcode, &rb);
4631 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
4632 (msg->rcode == dns_rcode_servfail ||
4633 msg->rcode == dns_rcode_notimp ||
4634 msg->rcode == dns_rcode_formerr)) {
4635 dns_zone_log(zone, ISC_LOG_DEBUG(1),
4636 "refresh: rcode (%.*s) retrying without "
4637 "EDNS master %s (source %s)",
4638 (int)rb.used, rcode, master, source);
4639 LOCK_ZONE(zone);
4640 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4641 UNLOCK_ZONE(zone);
4642 goto same_master;
4644 dns_zone_log(zone, ISC_LOG_INFO,
4645 "refresh: unexpected rcode (%.*s) from "
4646 "master %s (source %s)", (int)rb.used, rcode,
4647 master, source);
4649 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
4651 if (msg->rcode == dns_rcode_refused &&
4652 zone->type == dns_zone_slave)
4653 goto tcp_transfer;
4654 goto next_master;
4658 * If truncated punt to zone transfer which will query again.
4660 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
4661 if (zone->type == dns_zone_slave) {
4662 dns_zone_log(zone, ISC_LOG_INFO,
4663 "refresh: truncated UDP answer, "
4664 "initiating TCP zone xfer "
4665 "for master %s (source %s)",
4666 master, source);
4667 LOCK_ZONE(zone);
4668 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
4669 UNLOCK_ZONE(zone);
4670 goto tcp_transfer;
4671 } else {
4672 INSIST(zone->type == dns_zone_stub);
4673 if (dns_request_usedtcp(revent->request)) {
4674 dns_zone_log(zone, ISC_LOG_INFO,
4675 "refresh: truncated TCP response "
4676 "from master %s (source %s)",
4677 master, source);
4678 goto next_master;
4680 LOCK_ZONE(zone);
4681 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
4682 UNLOCK_ZONE(zone);
4683 goto same_master;
4688 * if non-auth log and next master;
4690 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
4691 dns_zone_log(zone, ISC_LOG_INFO,
4692 "refresh: non-authoritative answer from "
4693 "master %s (source %s)", master, source);
4694 goto next_master;
4697 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
4698 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
4699 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
4700 soacount = message_count(msg, DNS_SECTION_AUTHORITY,
4701 dns_rdatatype_soa);
4704 * There should not be a CNAME record at top of zone.
4706 if (cnamecnt != 0) {
4707 dns_zone_log(zone, ISC_LOG_INFO,
4708 "refresh: CNAME at top of zone "
4709 "in master %s (source %s)", master, source);
4710 goto next_master;
4714 * if referral log and next master;
4716 if (soacnt == 0 && soacount == 0 && nscount != 0) {
4717 dns_zone_log(zone, ISC_LOG_INFO,
4718 "refresh: referral response "
4719 "from master %s (source %s)", master, source);
4720 goto next_master;
4724 * if nodata log and next master;
4726 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
4727 dns_zone_log(zone, ISC_LOG_INFO,
4728 "refresh: NODATA response "
4729 "from master %s (source %s)", master, source);
4730 goto next_master;
4734 * Only one soa at top of zone.
4736 if (soacnt != 1) {
4737 dns_zone_log(zone, ISC_LOG_INFO,
4738 "refresh: answer SOA count (%d) != 1 "
4739 "from master %s (source %s)",
4740 soacnt, master, source);
4741 goto next_master;
4744 * Extract serial
4746 rdataset = NULL;
4747 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
4748 dns_rdatatype_soa, dns_rdatatype_none,
4749 NULL, &rdataset);
4750 if (result != ISC_R_SUCCESS) {
4751 dns_zone_log(zone, ISC_LOG_INFO,
4752 "refresh: unable to get SOA record "
4753 "from master %s (source %s)", master, source);
4754 goto next_master;
4757 result = dns_rdataset_first(rdataset);
4758 if (result != ISC_R_SUCCESS) {
4759 dns_zone_log(zone, ISC_LOG_INFO,
4760 "refresh: dns_rdataset_first() failed");
4761 goto next_master;
4764 dns_rdataset_current(rdataset, &rdata);
4765 result = dns_rdata_tostruct(&rdata, &soa, NULL);
4766 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4768 serial = soa.serial;
4770 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
4771 serial, zone->serial);
4772 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
4773 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
4774 isc_serial_gt(serial, zone->serial)) {
4775 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
4776 &zone->sourceaddr, &now)) {
4777 dns_zone_log(zone, ISC_LOG_INFO,
4778 "refresh: skipping %s as master %s "
4779 "(source %s) is unreachable (cached)",
4780 zone->type == dns_zone_slave ?
4781 "zone transfer" : "NS query",
4782 master, source);
4783 goto next_master;
4785 tcp_transfer:
4786 isc_event_free(&event);
4787 LOCK_ZONE(zone);
4788 dns_request_destroy(&zone->request);
4789 UNLOCK_ZONE(zone);
4790 if (zone->type == dns_zone_slave) {
4791 queue_xfrin(zone);
4792 } else {
4793 INSIST(zone->type == dns_zone_stub);
4794 ns_query(zone, rdataset, NULL);
4796 if (msg != NULL)
4797 dns_message_destroy(&msg);
4798 } else if (isc_serial_eq(soa.serial, zone->serial)) {
4799 if (zone->masterfile != NULL) {
4800 result = ISC_R_FAILURE;
4801 if (zone->journal != NULL)
4802 result = isc_file_settime(zone->journal, &now);
4803 if (result == ISC_R_SUCCESS &&
4804 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
4805 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
4806 result = isc_file_settime(zone->masterfile,
4807 &now);
4808 } else if (result != ISC_R_SUCCESS)
4809 result = isc_file_settime(zone->masterfile,
4810 &now);
4811 /* Someone removed the file from underneath us! */
4812 if (result == ISC_R_FILENOTFOUND) {
4813 LOCK_ZONE(zone);
4814 zone_needdump(zone, DNS_DUMP_DELAY);
4815 UNLOCK_ZONE(zone);
4816 } else if (result != ISC_R_SUCCESS)
4817 dns_zone_log(zone, ISC_LOG_ERROR,
4818 "refresh: could not set file "
4819 "modification time of '%s': %s",
4820 zone->masterfile,
4821 dns_result_totext(result));
4823 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
4824 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
4825 zone->mastersok[zone->curmaster] = ISC_TRUE;
4826 goto next_master;
4827 } else {
4828 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
4829 dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
4830 "received from master %s < ours (%u)",
4831 soa.serial, master, zone->serial);
4832 else
4833 zone_debuglog(zone, me, 1, "ahead");
4834 zone->mastersok[zone->curmaster] = ISC_TRUE;
4835 goto next_master;
4837 if (msg != NULL)
4838 dns_message_destroy(&msg);
4839 goto detach;
4841 next_master:
4842 if (msg != NULL)
4843 dns_message_destroy(&msg);
4844 isc_event_free(&event);
4845 LOCK_ZONE(zone);
4846 dns_request_destroy(&zone->request);
4848 * Skip to next failed / untried master.
4850 do {
4851 zone->curmaster++;
4852 } while (zone->curmaster < zone->masterscnt &&
4853 zone->mastersok[zone->curmaster]);
4854 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
4855 if (zone->curmaster >= zone->masterscnt) {
4856 isc_boolean_t done = ISC_TRUE;
4857 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
4858 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
4860 * Did we get a good answer from all the masters?
4862 for (j = 0; j < zone->masterscnt; j++)
4863 if (zone->mastersok[j] == ISC_FALSE) {
4864 done = ISC_FALSE;
4865 break;
4867 } else
4868 done = ISC_TRUE;
4869 if (!done) {
4870 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
4871 zone->curmaster = 0;
4873 * Find the next failed master.
4875 while (zone->curmaster < zone->masterscnt &&
4876 zone->mastersok[zone->curmaster])
4877 zone->curmaster++;
4878 goto requeue;
4880 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4881 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
4882 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
4883 zone->refreshtime = now;
4885 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
4886 zone_settimer(zone, &now);
4887 UNLOCK_ZONE(zone);
4888 goto detach;
4891 requeue:
4892 queue_soa_query(zone);
4893 UNLOCK_ZONE(zone);
4894 goto detach;
4896 same_master:
4897 if (msg != NULL)
4898 dns_message_destroy(&msg);
4899 isc_event_free(&event);
4900 LOCK_ZONE(zone);
4901 dns_request_destroy(&zone->request);
4902 queue_soa_query(zone);
4903 UNLOCK_ZONE(zone);
4905 detach:
4906 dns_zone_idetach(&zone);
4907 return;
4910 static void
4911 queue_soa_query(dns_zone_t *zone) {
4912 const char me[] = "queue_soa_query";
4913 isc_event_t *e;
4914 dns_zone_t *dummy = NULL;
4915 isc_result_t result;
4917 ENTER;
4919 * Locked by caller
4921 REQUIRE(LOCKED_ZONE(zone));
4923 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
4924 cancel_refresh(zone);
4925 return;
4928 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
4929 soa_query, zone, sizeof(isc_event_t));
4930 if (e == NULL) {
4931 cancel_refresh(zone);
4932 return;
4936 * Attach so that we won't clean up
4937 * until the event is delivered.
4939 zone_iattach(zone, &dummy);
4941 e->ev_arg = zone;
4942 e->ev_sender = NULL;
4943 result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
4944 if (result != ISC_R_SUCCESS) {
4945 zone_idetach(&dummy);
4946 isc_event_free(&e);
4947 cancel_refresh(zone);
4951 static inline isc_result_t
4952 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
4953 dns_message_t **messagep)
4955 dns_message_t *message = NULL;
4956 dns_name_t *qname = NULL;
4957 dns_rdataset_t *qrdataset = NULL;
4958 isc_result_t result;
4960 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
4961 &message);
4962 if (result != ISC_R_SUCCESS)
4963 goto cleanup;
4965 message->opcode = dns_opcode_query;
4966 message->rdclass = zone->rdclass;
4968 result = dns_message_gettempname(message, &qname);
4969 if (result != ISC_R_SUCCESS)
4970 goto cleanup;
4972 result = dns_message_gettemprdataset(message, &qrdataset);
4973 if (result != ISC_R_SUCCESS)
4974 goto cleanup;
4977 * Make question.
4979 dns_name_init(qname, NULL);
4980 dns_name_clone(&zone->origin, qname);
4981 dns_rdataset_init(qrdataset);
4982 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
4983 ISC_LIST_APPEND(qname->list, qrdataset, link);
4984 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
4986 *messagep = message;
4987 return (ISC_R_SUCCESS);
4989 cleanup:
4990 if (qname != NULL)
4991 dns_message_puttempname(message, &qname);
4992 if (qrdataset != NULL)
4993 dns_message_puttemprdataset(message, &qrdataset);
4994 if (message != NULL)
4995 dns_message_destroy(&message);
4996 return (result);
4999 static isc_result_t
5000 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
5001 dns_rdataset_t *rdataset = NULL;
5002 dns_rdatalist_t *rdatalist = NULL;
5003 dns_rdata_t *rdata = NULL;
5004 isc_result_t result;
5006 result = dns_message_gettemprdatalist(message, &rdatalist);
5007 if (result != ISC_R_SUCCESS)
5008 goto cleanup;
5009 result = dns_message_gettemprdata(message, &rdata);
5010 if (result != ISC_R_SUCCESS)
5011 goto cleanup;
5012 result = dns_message_gettemprdataset(message, &rdataset);
5013 if (result != ISC_R_SUCCESS)
5014 goto cleanup;
5015 dns_rdataset_init(rdataset);
5017 rdatalist->type = dns_rdatatype_opt;
5018 rdatalist->covers = 0;
5021 * Set Maximum UDP buffer size.
5023 rdatalist->rdclass = udpsize;
5026 * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
5028 rdatalist->ttl = 0;
5030 /* Set EDNS options if applicable */
5031 if (reqnsid) {
5032 unsigned char data[4];
5033 isc_buffer_t buf;
5035 isc_buffer_init(&buf, data, sizeof(data));
5036 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
5037 isc_buffer_putuint16(&buf, 0);
5038 rdata->data = data;
5039 rdata->length = sizeof(data);
5040 } else {
5041 rdata->data = NULL;
5042 rdata->length = 0;
5045 rdata->rdclass = rdatalist->rdclass;
5046 rdata->type = rdatalist->type;
5047 rdata->flags = 0;
5049 ISC_LIST_INIT(rdatalist->rdata);
5050 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
5051 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
5052 == ISC_R_SUCCESS);
5054 return (dns_message_setopt(message, rdataset));
5056 cleanup:
5057 if (rdatalist != NULL)
5058 dns_message_puttemprdatalist(message, &rdatalist);
5059 if (rdataset != NULL)
5060 dns_message_puttemprdataset(message, &rdataset);
5061 if (rdata != NULL)
5062 dns_message_puttemprdata(message, &rdata);
5064 return (result);
5067 static void
5068 soa_query(isc_task_t *task, isc_event_t *event) {
5069 const char me[] = "soa_query";
5070 isc_result_t result = ISC_R_FAILURE;
5071 dns_message_t *message = NULL;
5072 dns_zone_t *zone = event->ev_arg;
5073 dns_zone_t *dummy = NULL;
5074 isc_netaddr_t masterip;
5075 dns_tsigkey_t *key = NULL;
5076 isc_uint32_t options;
5077 isc_boolean_t cancel = ISC_TRUE;
5078 int timeout;
5079 isc_boolean_t have_xfrsource, reqnsid;
5080 isc_uint16_t udpsize = SEND_BUFFER_SIZE;
5082 REQUIRE(DNS_ZONE_VALID(zone));
5084 UNUSED(task);
5086 ENTER;
5088 LOCK_ZONE(zone);
5089 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
5090 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
5091 zone->view->requestmgr == NULL) {
5092 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
5093 cancel = ISC_FALSE;
5094 goto cleanup;
5098 * XXX Optimisation: Create message when zone is setup and reuse.
5100 result = create_query(zone, dns_rdatatype_soa, &message);
5101 if (result != ISC_R_SUCCESS)
5102 goto cleanup;
5104 again:
5105 INSIST(zone->masterscnt > 0);
5106 INSIST(zone->curmaster < zone->masterscnt);
5108 zone->masteraddr = zone->masters[zone->curmaster];
5110 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
5112 * First, look for a tsig key in the master statement, then
5113 * try for a server key.
5115 if ((zone->masterkeynames != NULL) &&
5116 (zone->masterkeynames[zone->curmaster] != NULL)) {
5117 dns_view_t *view = dns_zone_getview(zone);
5118 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
5119 result = dns_view_gettsig(view, keyname, &key);
5120 if (result != ISC_R_SUCCESS) {
5121 char namebuf[DNS_NAME_FORMATSIZE];
5122 dns_name_format(keyname, namebuf, sizeof(namebuf));
5123 dns_zone_log(zone, ISC_LOG_ERROR,
5124 "unable to find key: %s", namebuf);
5127 if (key == NULL)
5128 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
5130 have_xfrsource = ISC_FALSE;
5131 reqnsid = zone->view->requestnsid;
5132 if (zone->view->peers != NULL) {
5133 dns_peer_t *peer = NULL;
5134 isc_boolean_t edns;
5135 result = dns_peerlist_peerbyaddr(zone->view->peers,
5136 &masterip, &peer);
5137 if (result == ISC_R_SUCCESS) {
5138 result = dns_peer_getsupportedns(peer, &edns);
5139 if (result == ISC_R_SUCCESS && !edns)
5140 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
5141 result = dns_peer_gettransfersource(peer,
5142 &zone->sourceaddr);
5143 if (result == ISC_R_SUCCESS)
5144 have_xfrsource = ISC_TRUE;
5145 if (zone->view->resolver != NULL)
5146 udpsize =
5147 dns_resolver_getudpsize(zone->view->resolver);
5148 (void)dns_peer_getudpsize(peer, &udpsize);
5149 (void)dns_peer_getrequestnsid(peer, &reqnsid);
5153 switch (isc_sockaddr_pf(&zone->masteraddr)) {
5154 case PF_INET:
5155 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
5156 if (isc_sockaddr_equal(&zone->altxfrsource4,
5157 &zone->xfrsource4))
5158 goto skip_master;
5159 zone->sourceaddr = zone->altxfrsource4;
5160 } else if (!have_xfrsource)
5161 zone->sourceaddr = zone->xfrsource4;
5162 break;
5163 case PF_INET6:
5164 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
5165 if (isc_sockaddr_equal(&zone->altxfrsource6,
5166 &zone->xfrsource6))
5167 goto skip_master;
5168 zone->sourceaddr = zone->altxfrsource6;
5169 } else if (!have_xfrsource)
5170 zone->sourceaddr = zone->xfrsource6;
5171 break;
5172 default:
5173 result = ISC_R_NOTIMPLEMENTED;
5174 goto cleanup;
5177 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
5178 DNS_REQUESTOPT_TCP : 0;
5180 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
5181 result = add_opt(message, udpsize, reqnsid);
5182 if (result != ISC_R_SUCCESS)
5183 zone_debuglog(zone, me, 1,
5184 "unable to add opt record: %s",
5185 dns_result_totext(result));
5188 zone_iattach(zone, &dummy);
5189 timeout = 15;
5190 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
5191 timeout = 30;
5192 result = dns_request_createvia2(zone->view->requestmgr, message,
5193 &zone->sourceaddr, &zone->masteraddr,
5194 options, key, timeout * 3, timeout,
5195 zone->task, refresh_callback, zone,
5196 &zone->request);
5197 if (result != ISC_R_SUCCESS) {
5198 zone_idetach(&dummy);
5199 zone_debuglog(zone, me, 1,
5200 "dns_request_createvia2() failed: %s",
5201 dns_result_totext(result));
5202 goto cleanup;
5203 } else {
5204 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
5205 inc_stats(zone, dns_zonestatscounter_soaoutv4);
5206 else
5207 inc_stats(zone, dns_zonestatscounter_soaoutv6);
5209 cancel = ISC_FALSE;
5211 cleanup:
5212 if (key != NULL)
5213 dns_tsigkey_detach(&key);
5214 if (result != ISC_R_SUCCESS)
5215 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
5216 if (message != NULL)
5217 dns_message_destroy(&message);
5218 if (cancel)
5219 cancel_refresh(zone);
5220 isc_event_free(&event);
5221 UNLOCK_ZONE(zone);
5222 dns_zone_idetach(&zone);
5223 return;
5225 skip_master:
5226 if (key != NULL)
5227 dns_tsigkey_detach(&key);
5229 * Skip to next failed / untried master.
5231 do {
5232 zone->curmaster++;
5233 } while (zone->curmaster < zone->masterscnt &&
5234 zone->mastersok[zone->curmaster]);
5235 if (zone->curmaster < zone->masterscnt)
5236 goto again;
5237 zone->curmaster = 0;
5238 goto cleanup;
5241 static void
5242 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
5243 const char me[] = "ns_query";
5244 isc_result_t result;
5245 dns_message_t *message = NULL;
5246 isc_netaddr_t masterip;
5247 dns_tsigkey_t *key = NULL;
5248 dns_dbnode_t *node = NULL;
5249 int timeout;
5250 isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
5251 isc_uint16_t udpsize = SEND_BUFFER_SIZE;
5253 REQUIRE(DNS_ZONE_VALID(zone));
5254 REQUIRE((soardataset != NULL && stub == NULL) ||
5255 (soardataset == NULL && stub != NULL));
5256 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
5258 ENTER;
5260 LOCK_ZONE(zone);
5261 if (stub == NULL) {
5262 stub = isc_mem_get(zone->mctx, sizeof(*stub));
5263 if (stub == NULL)
5264 goto cleanup;
5265 stub->magic = STUB_MAGIC;
5266 stub->mctx = zone->mctx;
5267 stub->zone = NULL;
5268 stub->db = NULL;
5269 stub->version = NULL;
5272 * Attach so that the zone won't disappear from under us.
5274 zone_iattach(zone, &stub->zone);
5277 * If a db exists we will update it, otherwise we create a
5278 * new one and attach it to the zone once we have the NS
5279 * RRset and glue.
5281 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5282 if (zone->db != NULL) {
5283 dns_db_attach(zone->db, &stub->db);
5284 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5285 } else {
5286 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5288 INSIST(zone->db_argc >= 1);
5289 result = dns_db_create(zone->mctx, zone->db_argv[0],
5290 &zone->origin, dns_dbtype_stub,
5291 zone->rdclass,
5292 zone->db_argc - 1,
5293 zone->db_argv + 1,
5294 &stub->db);
5295 if (result != ISC_R_SUCCESS) {
5296 dns_zone_log(zone, ISC_LOG_ERROR,
5297 "refreshing stub: "
5298 "could not create "
5299 "database: %s",
5300 dns_result_totext(result));
5301 goto cleanup;
5303 dns_db_settask(stub->db, zone->task);
5306 dns_db_newversion(stub->db, &stub->version);
5309 * Update SOA record.
5311 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
5312 &node);
5313 if (result != ISC_R_SUCCESS) {
5314 dns_zone_log(zone, ISC_LOG_INFO,
5315 "refreshing stub: "
5316 "dns_db_findnode() failed: %s",
5317 dns_result_totext(result));
5318 goto cleanup;
5321 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
5322 soardataset, 0, NULL);
5323 dns_db_detachnode(stub->db, &node);
5324 if (result != ISC_R_SUCCESS) {
5325 dns_zone_log(zone, ISC_LOG_INFO,
5326 "refreshing stub: "
5327 "dns_db_addrdataset() failed: %s",
5328 dns_result_totext(result));
5329 goto cleanup;
5334 * XXX Optimisation: Create message when zone is setup and reuse.
5336 result = create_query(zone, dns_rdatatype_ns, &message);
5338 INSIST(zone->masterscnt > 0);
5339 INSIST(zone->curmaster < zone->masterscnt);
5340 zone->masteraddr = zone->masters[zone->curmaster];
5342 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
5344 * First, look for a tsig key in the master statement, then
5345 * try for a server key.
5347 if ((zone->masterkeynames != NULL) &&
5348 (zone->masterkeynames[zone->curmaster] != NULL)) {
5349 dns_view_t *view = dns_zone_getview(zone);
5350 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
5351 result = dns_view_gettsig(view, keyname, &key);
5352 if (result != ISC_R_SUCCESS) {
5353 char namebuf[DNS_NAME_FORMATSIZE];
5354 dns_name_format(keyname, namebuf, sizeof(namebuf));
5355 dns_zone_log(zone, ISC_LOG_ERROR,
5356 "unable to find key: %s", namebuf);
5359 if (key == NULL)
5360 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
5362 reqnsid = zone->view->requestnsid;
5363 if (zone->view->peers != NULL) {
5364 dns_peer_t *peer = NULL;
5365 isc_boolean_t edns;
5366 result = dns_peerlist_peerbyaddr(zone->view->peers,
5367 &masterip, &peer);
5368 if (result == ISC_R_SUCCESS) {
5369 result = dns_peer_getsupportedns(peer, &edns);
5370 if (result == ISC_R_SUCCESS && !edns)
5371 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
5372 result = dns_peer_gettransfersource(peer,
5373 &zone->sourceaddr);
5374 if (result == ISC_R_SUCCESS)
5375 have_xfrsource = ISC_TRUE;
5376 if (zone->view->resolver != NULL)
5377 udpsize =
5378 dns_resolver_getudpsize(zone->view->resolver);
5379 (void)dns_peer_getudpsize(peer, &udpsize);
5380 (void)dns_peer_getrequestnsid(peer, &reqnsid);
5384 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
5385 result = add_opt(message, udpsize, reqnsid);
5386 if (result != ISC_R_SUCCESS)
5387 zone_debuglog(zone, me, 1,
5388 "unable to add opt record: %s",
5389 dns_result_totext(result));
5393 * Always use TCP so that we shouldn't truncate in additional section.
5395 switch (isc_sockaddr_pf(&zone->masteraddr)) {
5396 case PF_INET:
5397 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
5398 zone->sourceaddr = zone->altxfrsource4;
5399 else if (!have_xfrsource)
5400 zone->sourceaddr = zone->xfrsource4;
5401 break;
5402 case PF_INET6:
5403 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
5404 zone->sourceaddr = zone->altxfrsource6;
5405 else if (!have_xfrsource)
5406 zone->sourceaddr = zone->xfrsource6;
5407 break;
5408 default:
5409 result = ISC_R_NOTIMPLEMENTED;
5410 goto cleanup;
5412 timeout = 15;
5413 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
5414 timeout = 30;
5415 result = dns_request_createvia2(zone->view->requestmgr, message,
5416 &zone->sourceaddr, &zone->masteraddr,
5417 DNS_REQUESTOPT_TCP, key, timeout * 3,
5418 timeout, zone->task, stub_callback,
5419 stub, &zone->request);
5420 if (result != ISC_R_SUCCESS) {
5421 zone_debuglog(zone, me, 1,
5422 "dns_request_createvia() failed: %s",
5423 dns_result_totext(result));
5424 goto cleanup;
5426 dns_message_destroy(&message);
5427 goto unlock;
5429 cleanup:
5430 cancel_refresh(zone);
5431 if (stub != NULL) {
5432 stub->magic = 0;
5433 if (stub->version != NULL)
5434 dns_db_closeversion(stub->db, &stub->version,
5435 ISC_FALSE);
5436 if (stub->db != NULL)
5437 dns_db_detach(&stub->db);
5438 if (stub->zone != NULL)
5439 zone_idetach(&stub->zone);
5440 isc_mem_put(stub->mctx, stub, sizeof(*stub));
5442 if (message != NULL)
5443 dns_message_destroy(&message);
5444 unlock:
5445 if (key != NULL)
5446 dns_tsigkey_detach(&key);
5447 UNLOCK_ZONE(zone);
5448 return;
5452 * Handle the control event. Note that although this event causes the zone
5453 * to shut down, it is not a shutdown event in the sense of the task library.
5455 static void
5456 zone_shutdown(isc_task_t *task, isc_event_t *event) {
5457 dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
5458 isc_boolean_t free_needed, linked = ISC_FALSE;
5460 UNUSED(task);
5461 REQUIRE(DNS_ZONE_VALID(zone));
5462 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
5463 INSIST(isc_refcount_current(&zone->erefs) == 0);
5464 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
5467 * Stop things being restarted after we cancel them below.
5469 LOCK_ZONE(zone);
5470 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
5471 UNLOCK_ZONE(zone);
5474 * If we were waiting for xfrin quota, step out of
5475 * the queue.
5476 * If there's no zone manager, we can't be waiting for the
5477 * xfrin quota
5479 if (zone->zmgr != NULL) {
5480 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
5481 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
5482 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
5483 statelink);
5484 linked = ISC_TRUE;
5485 zone->statelist = NULL;
5487 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
5491 * In task context, no locking required. See zone_xfrdone().
5493 if (zone->xfr != NULL)
5494 dns_xfrin_shutdown(zone->xfr);
5496 LOCK_ZONE(zone);
5497 if (linked) {
5498 INSIST(zone->irefs > 0);
5499 zone->irefs--;
5501 if (zone->request != NULL) {
5502 dns_request_cancel(zone->request);
5505 if (zone->readio != NULL)
5506 zonemgr_cancelio(zone->readio);
5508 if (zone->lctx != NULL)
5509 dns_loadctx_cancel(zone->lctx);
5511 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
5512 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
5513 if (zone->writeio != NULL)
5514 zonemgr_cancelio(zone->writeio);
5516 if (zone->dctx != NULL)
5517 dns_dumpctx_cancel(zone->dctx);
5520 notify_cancel(zone);
5522 if (zone->timer != NULL) {
5523 isc_timer_detach(&zone->timer);
5524 INSIST(zone->irefs > 0);
5525 zone->irefs--;
5528 if (zone->view != NULL)
5529 dns_view_weakdetach(&zone->view);
5532 * We have now canceled everything set the flag to allow exit_check()
5533 * to succeed. We must not unlock between setting this flag and
5534 * calling exit_check().
5536 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
5537 free_needed = exit_check(zone);
5538 UNLOCK_ZONE(zone);
5539 if (free_needed)
5540 zone_free(zone);
5543 static void
5544 zone_timer(isc_task_t *task, isc_event_t *event) {
5545 const char me[] = "zone_timer";
5546 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
5548 UNUSED(task);
5549 REQUIRE(DNS_ZONE_VALID(zone));
5551 ENTER;
5553 zone_maintenance(zone);
5555 isc_event_free(&event);
5558 static void
5559 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
5560 const char me[] = "zone_settimer";
5561 isc_time_t next;
5562 isc_result_t result;
5564 REQUIRE(DNS_ZONE_VALID(zone));
5565 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
5566 return;
5568 isc_time_settoepoch(&next);
5570 switch (zone->type) {
5571 case dns_zone_master:
5572 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
5573 next = zone->notifytime;
5574 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
5575 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
5576 INSIST(!isc_time_isepoch(&zone->dumptime));
5577 if (isc_time_isepoch(&next) ||
5578 isc_time_compare(&zone->dumptime, &next) < 0)
5579 next = zone->dumptime;
5581 break;
5583 case dns_zone_slave:
5584 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
5585 next = zone->notifytime;
5586 /*FALLTHROUGH*/
5588 case dns_zone_stub:
5589 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
5590 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
5591 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
5592 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
5593 INSIST(!isc_time_isepoch(&zone->refreshtime));
5594 if (isc_time_isepoch(&next) ||
5595 isc_time_compare(&zone->refreshtime, &next) < 0)
5596 next = zone->refreshtime;
5598 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
5599 INSIST(!isc_time_isepoch(&zone->expiretime));
5600 if (isc_time_isepoch(&next) ||
5601 isc_time_compare(&zone->expiretime, &next) < 0)
5602 next = zone->expiretime;
5604 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
5605 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
5606 INSIST(!isc_time_isepoch(&zone->dumptime));
5607 if (isc_time_isepoch(&next) ||
5608 isc_time_compare(&zone->dumptime, &next) < 0)
5609 next = zone->dumptime;
5611 break;
5613 default:
5614 break;
5617 if (isc_time_isepoch(&next)) {
5618 zone_debuglog(zone, me, 10, "settimer inactive");
5619 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
5620 NULL, NULL, ISC_TRUE);
5621 if (result != ISC_R_SUCCESS)
5622 dns_zone_log(zone, ISC_LOG_ERROR,
5623 "could not deactivate zone timer: %s",
5624 isc_result_totext(result));
5625 } else {
5626 if (isc_time_compare(&next, now) <= 0)
5627 next = *now;
5628 result = isc_timer_reset(zone->timer, isc_timertype_once,
5629 &next, NULL, ISC_TRUE);
5630 if (result != ISC_R_SUCCESS)
5631 dns_zone_log(zone, ISC_LOG_ERROR,
5632 "could not reset zone timer: %s",
5633 isc_result_totext(result));
5637 static void
5638 cancel_refresh(dns_zone_t *zone) {
5639 const char me[] = "cancel_refresh";
5640 isc_time_t now;
5643 * 'zone' locked by caller.
5646 REQUIRE(DNS_ZONE_VALID(zone));
5647 REQUIRE(LOCKED_ZONE(zone));
5649 ENTER;
5651 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
5652 TIME_NOW(&now);
5653 zone_settimer(zone, &now);
5656 static isc_result_t
5657 notify_createmessage(dns_zone_t *zone, unsigned int flags,
5658 dns_message_t **messagep)
5660 dns_db_t *zonedb = NULL;
5661 dns_dbnode_t *node = NULL;
5662 dns_dbversion_t *version = NULL;
5663 dns_message_t *message = NULL;
5664 dns_rdataset_t rdataset;
5665 dns_rdata_t rdata = DNS_RDATA_INIT;
5667 dns_name_t *tempname = NULL;
5668 dns_rdata_t *temprdata = NULL;
5669 dns_rdatalist_t *temprdatalist = NULL;
5670 dns_rdataset_t *temprdataset = NULL;
5672 isc_result_t result;
5673 isc_region_t r;
5674 isc_buffer_t *b = NULL;
5676 REQUIRE(DNS_ZONE_VALID(zone));
5677 REQUIRE(messagep != NULL && *messagep == NULL);
5679 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
5680 &message);
5681 if (result != ISC_R_SUCCESS)
5682 return (result);
5684 message->opcode = dns_opcode_notify;
5685 message->flags |= DNS_MESSAGEFLAG_AA;
5686 message->rdclass = zone->rdclass;
5688 result = dns_message_gettempname(message, &tempname);
5689 if (result != ISC_R_SUCCESS)
5690 goto cleanup;
5692 result = dns_message_gettemprdataset(message, &temprdataset);
5693 if (result != ISC_R_SUCCESS)
5694 goto cleanup;
5697 * Make question.
5699 dns_name_init(tempname, NULL);
5700 dns_name_clone(&zone->origin, tempname);
5701 dns_rdataset_init(temprdataset);
5702 dns_rdataset_makequestion(temprdataset, zone->rdclass,
5703 dns_rdatatype_soa);
5704 ISC_LIST_APPEND(tempname->list, temprdataset, link);
5705 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
5706 tempname = NULL;
5707 temprdataset = NULL;
5709 if ((flags & DNS_NOTIFY_NOSOA) != 0)
5710 goto done;
5712 result = dns_message_gettempname(message, &tempname);
5713 if (result != ISC_R_SUCCESS)
5714 goto soa_cleanup;
5715 result = dns_message_gettemprdata(message, &temprdata);
5716 if (result != ISC_R_SUCCESS)
5717 goto soa_cleanup;
5718 result = dns_message_gettemprdataset(message, &temprdataset);
5719 if (result != ISC_R_SUCCESS)
5720 goto soa_cleanup;
5721 result = dns_message_gettemprdatalist(message, &temprdatalist);
5722 if (result != ISC_R_SUCCESS)
5723 goto soa_cleanup;
5725 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5726 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
5727 dns_db_attach(zone->db, &zonedb);
5728 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5730 dns_name_init(tempname, NULL);
5731 dns_name_clone(&zone->origin, tempname);
5732 dns_db_currentversion(zonedb, &version);
5733 result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
5734 if (result != ISC_R_SUCCESS)
5735 goto soa_cleanup;
5737 dns_rdataset_init(&rdataset);
5738 result = dns_db_findrdataset(zonedb, node, version,
5739 dns_rdatatype_soa,
5740 dns_rdatatype_none, 0, &rdataset,
5741 NULL);
5742 if (result != ISC_R_SUCCESS)
5743 goto soa_cleanup;
5744 result = dns_rdataset_first(&rdataset);
5745 if (result != ISC_R_SUCCESS)
5746 goto soa_cleanup;
5747 dns_rdataset_current(&rdataset, &rdata);
5748 dns_rdata_toregion(&rdata, &r);
5749 result = isc_buffer_allocate(zone->mctx, &b, r.length);
5750 if (result != ISC_R_SUCCESS)
5751 goto soa_cleanup;
5752 isc_buffer_putmem(b, r.base, r.length);
5753 isc_buffer_usedregion(b, &r);
5754 dns_rdata_init(temprdata);
5755 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
5756 dns_message_takebuffer(message, &b);
5757 result = dns_rdataset_next(&rdataset);
5758 dns_rdataset_disassociate(&rdataset);
5759 if (result != ISC_R_NOMORE)
5760 goto soa_cleanup;
5761 temprdatalist->rdclass = rdata.rdclass;
5762 temprdatalist->type = rdata.type;
5763 temprdatalist->covers = 0;
5764 temprdatalist->ttl = rdataset.ttl;
5765 ISC_LIST_INIT(temprdatalist->rdata);
5766 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
5768 dns_rdataset_init(temprdataset);
5769 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
5770 if (result != ISC_R_SUCCESS)
5771 goto soa_cleanup;
5773 ISC_LIST_APPEND(tempname->list, temprdataset, link);
5774 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
5775 temprdatalist = NULL;
5776 temprdataset = NULL;
5777 temprdata = NULL;
5778 tempname = NULL;
5780 soa_cleanup:
5781 if (node != NULL)
5782 dns_db_detachnode(zonedb, &node);
5783 if (version != NULL)
5784 dns_db_closeversion(zonedb, &version, ISC_FALSE);
5785 if (zonedb != NULL)
5786 dns_db_detach(&zonedb);
5787 if (tempname != NULL)
5788 dns_message_puttempname(message, &tempname);
5789 if (temprdata != NULL)
5790 dns_message_puttemprdata(message, &temprdata);
5791 if (temprdataset != NULL)
5792 dns_message_puttemprdataset(message, &temprdataset);
5793 if (temprdatalist != NULL)
5794 dns_message_puttemprdatalist(message, &temprdatalist);
5796 done:
5797 *messagep = message;
5798 return (ISC_R_SUCCESS);
5800 cleanup:
5801 if (tempname != NULL)
5802 dns_message_puttempname(message, &tempname);
5803 if (temprdataset != NULL)
5804 dns_message_puttemprdataset(message, &temprdataset);
5805 dns_message_destroy(&message);
5806 return (result);
5809 isc_result_t
5810 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
5811 dns_message_t *msg)
5813 unsigned int i;
5814 dns_rdata_soa_t soa;
5815 dns_rdataset_t *rdataset = NULL;
5816 dns_rdata_t rdata = DNS_RDATA_INIT;
5817 isc_result_t result;
5818 char fromtext[ISC_SOCKADDR_FORMATSIZE];
5819 int match = 0;
5820 isc_netaddr_t netaddr;
5822 REQUIRE(DNS_ZONE_VALID(zone));
5825 * If type != T_SOA return DNS_R_REFUSED. We don't yet support
5826 * ROLLOVER.
5828 * SOA: RFC1996
5829 * Check that 'from' is a valid notify source, (zone->masters).
5830 * Return DNS_R_REFUSED if not.
5832 * If the notify message contains a serial number check it
5833 * against the zones serial and return if <= current serial
5835 * If a refresh check is progress, if so just record the
5836 * fact we received a NOTIFY and from where and return.
5837 * We will perform a new refresh check when the current one
5838 * completes. Return ISC_R_SUCCESS.
5840 * Otherwise initiate a refresh check using 'from' as the
5841 * first address to check. Return ISC_R_SUCCESS.
5844 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
5847 * We only handle NOTIFY (SOA) at the present.
5849 LOCK_ZONE(zone);
5850 if (isc_sockaddr_pf(from) == PF_INET)
5851 inc_stats(zone, dns_zonestatscounter_notifyinv4);
5852 else
5853 inc_stats(zone, dns_zonestatscounter_notifyinv6);
5854 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
5855 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
5856 dns_rdatatype_soa, dns_rdatatype_none,
5857 NULL, NULL) != ISC_R_SUCCESS) {
5858 UNLOCK_ZONE(zone);
5859 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
5860 dns_zone_log(zone, ISC_LOG_NOTICE,
5861 "NOTIFY with no "
5862 "question section from: %s", fromtext);
5863 return (DNS_R_FORMERR);
5865 dns_zone_log(zone, ISC_LOG_NOTICE,
5866 "NOTIFY zone does not match");
5867 return (DNS_R_NOTIMP);
5871 * If we are a master zone just succeed.
5873 if (zone->type == dns_zone_master) {
5874 UNLOCK_ZONE(zone);
5875 return (ISC_R_SUCCESS);
5878 isc_netaddr_fromsockaddr(&netaddr, from);
5879 for (i = 0; i < zone->masterscnt; i++) {
5880 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
5881 break;
5882 if (zone->view->aclenv.match_mapped &&
5883 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
5884 isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
5885 isc_netaddr_t na1, na2;
5886 isc_netaddr_fromv4mapped(&na1, &netaddr);
5887 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
5888 if (isc_netaddr_equal(&na1, &na2))
5889 break;
5894 * Accept notify requests from non masters if they are on
5895 * 'zone->notify_acl'.
5897 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
5898 dns_acl_match(&netaddr, NULL, zone->notify_acl,
5899 &zone->view->aclenv,
5900 &match, NULL) == ISC_R_SUCCESS &&
5901 match > 0)
5903 /* Accept notify. */
5904 } else if (i >= zone->masterscnt) {
5905 UNLOCK_ZONE(zone);
5906 dns_zone_log(zone, ISC_LOG_INFO,
5907 "refused notify from non-master: %s", fromtext);
5908 inc_stats(zone, dns_zonestatscounter_notifyrej);
5909 return (DNS_R_REFUSED);
5913 * If the zone is loaded and there are answers check the serial
5914 * to see if we need to do a refresh. Do not worry about this
5915 * check if we are a dialup zone as we use the notify request
5916 * to trigger a refresh check.
5918 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
5919 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
5920 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
5921 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
5922 &zone->origin,
5923 dns_rdatatype_soa,
5924 dns_rdatatype_none, NULL,
5925 &rdataset);
5926 if (result == ISC_R_SUCCESS)
5927 result = dns_rdataset_first(rdataset);
5928 if (result == ISC_R_SUCCESS) {
5929 isc_uint32_t serial = 0;
5931 dns_rdataset_current(rdataset, &rdata);
5932 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5933 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5934 serial = soa.serial;
5935 if (isc_serial_le(serial, zone->serial)) {
5936 dns_zone_log(zone, ISC_LOG_INFO,
5937 "notify from %s: "
5938 "zone is up to date",
5939 fromtext);
5940 UNLOCK_ZONE(zone);
5941 return (ISC_R_SUCCESS);
5947 * If we got this far and there was a refresh in progress just
5948 * let it complete. Record where we got the notify from so we
5949 * can perform a refresh check when the current one completes
5951 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
5952 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
5953 zone->notifyfrom = *from;
5954 UNLOCK_ZONE(zone);
5955 dns_zone_log(zone, ISC_LOG_INFO,
5956 "notify from %s: refresh in progress, "
5957 "refresh check queued",
5958 fromtext);
5959 return (ISC_R_SUCCESS);
5961 zone->notifyfrom = *from;
5962 UNLOCK_ZONE(zone);
5963 dns_zone_refresh(zone);
5964 return (ISC_R_SUCCESS);
5967 void
5968 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
5970 REQUIRE(DNS_ZONE_VALID(zone));
5972 LOCK_ZONE(zone);
5973 if (zone->notify_acl != NULL)
5974 dns_acl_detach(&zone->notify_acl);
5975 dns_acl_attach(acl, &zone->notify_acl);
5976 UNLOCK_ZONE(zone);
5979 void
5980 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
5982 REQUIRE(DNS_ZONE_VALID(zone));
5984 LOCK_ZONE(zone);
5985 if (zone->query_acl != NULL)
5986 dns_acl_detach(&zone->query_acl);
5987 dns_acl_attach(acl, &zone->query_acl);
5988 UNLOCK_ZONE(zone);
5991 void
5992 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
5994 REQUIRE(DNS_ZONE_VALID(zone));
5996 LOCK_ZONE(zone);
5997 if (zone->queryon_acl != NULL)
5998 dns_acl_detach(&zone->queryon_acl);
5999 dns_acl_attach(acl, &zone->queryon_acl);
6000 UNLOCK_ZONE(zone);
6003 void
6004 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
6006 REQUIRE(DNS_ZONE_VALID(zone));
6008 LOCK_ZONE(zone);
6009 if (zone->update_acl != NULL)
6010 dns_acl_detach(&zone->update_acl);
6011 dns_acl_attach(acl, &zone->update_acl);
6012 UNLOCK_ZONE(zone);
6015 void
6016 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
6018 REQUIRE(DNS_ZONE_VALID(zone));
6020 LOCK_ZONE(zone);
6021 if (zone->forward_acl != NULL)
6022 dns_acl_detach(&zone->forward_acl);
6023 dns_acl_attach(acl, &zone->forward_acl);
6024 UNLOCK_ZONE(zone);
6027 void
6028 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
6030 REQUIRE(DNS_ZONE_VALID(zone));
6032 LOCK_ZONE(zone);
6033 if (zone->xfr_acl != NULL)
6034 dns_acl_detach(&zone->xfr_acl);
6035 dns_acl_attach(acl, &zone->xfr_acl);
6036 UNLOCK_ZONE(zone);
6039 dns_acl_t *
6040 dns_zone_getnotifyacl(dns_zone_t *zone) {
6042 REQUIRE(DNS_ZONE_VALID(zone));
6044 return (zone->notify_acl);
6047 dns_acl_t *
6048 dns_zone_getqueryacl(dns_zone_t *zone) {
6050 REQUIRE(DNS_ZONE_VALID(zone));
6052 return (zone->query_acl);
6055 dns_acl_t *
6056 dns_zone_getqueryonacl(dns_zone_t *zone) {
6058 REQUIRE(DNS_ZONE_VALID(zone));
6060 return (zone->queryon_acl);
6063 dns_acl_t *
6064 dns_zone_getupdateacl(dns_zone_t *zone) {
6066 REQUIRE(DNS_ZONE_VALID(zone));
6068 return (zone->update_acl);
6071 dns_acl_t *
6072 dns_zone_getforwardacl(dns_zone_t *zone) {
6074 REQUIRE(DNS_ZONE_VALID(zone));
6076 return (zone->forward_acl);
6079 dns_acl_t *
6080 dns_zone_getxfracl(dns_zone_t *zone) {
6082 REQUIRE(DNS_ZONE_VALID(zone));
6084 return (zone->xfr_acl);
6087 void
6088 dns_zone_clearupdateacl(dns_zone_t *zone) {
6090 REQUIRE(DNS_ZONE_VALID(zone));
6092 LOCK_ZONE(zone);
6093 if (zone->update_acl != NULL)
6094 dns_acl_detach(&zone->update_acl);
6095 UNLOCK_ZONE(zone);
6098 void
6099 dns_zone_clearforwardacl(dns_zone_t *zone) {
6101 REQUIRE(DNS_ZONE_VALID(zone));
6103 LOCK_ZONE(zone);
6104 if (zone->forward_acl != NULL)
6105 dns_acl_detach(&zone->forward_acl);
6106 UNLOCK_ZONE(zone);
6109 void
6110 dns_zone_clearnotifyacl(dns_zone_t *zone) {
6112 REQUIRE(DNS_ZONE_VALID(zone));
6114 LOCK_ZONE(zone);
6115 if (zone->notify_acl != NULL)
6116 dns_acl_detach(&zone->notify_acl);
6117 UNLOCK_ZONE(zone);
6120 void
6121 dns_zone_clearqueryacl(dns_zone_t *zone) {
6123 REQUIRE(DNS_ZONE_VALID(zone));
6125 LOCK_ZONE(zone);
6126 if (zone->query_acl != NULL)
6127 dns_acl_detach(&zone->query_acl);
6128 UNLOCK_ZONE(zone);
6131 void
6132 dns_zone_clearqueryonacl(dns_zone_t *zone) {
6134 REQUIRE(DNS_ZONE_VALID(zone));
6136 LOCK_ZONE(zone);
6137 if (zone->queryon_acl != NULL)
6138 dns_acl_detach(&zone->queryon_acl);
6139 UNLOCK_ZONE(zone);
6142 void
6143 dns_zone_clearxfracl(dns_zone_t *zone) {
6145 REQUIRE(DNS_ZONE_VALID(zone));
6147 LOCK_ZONE(zone);
6148 if (zone->xfr_acl != NULL)
6149 dns_acl_detach(&zone->xfr_acl);
6150 UNLOCK_ZONE(zone);
6153 isc_boolean_t
6154 dns_zone_getupdatedisabled(dns_zone_t *zone) {
6155 REQUIRE(DNS_ZONE_VALID(zone));
6156 return (zone->update_disabled);
6160 void
6161 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
6162 REQUIRE(DNS_ZONE_VALID(zone));
6163 zone->update_disabled = state;
6166 isc_boolean_t
6167 dns_zone_getzeronosoattl(dns_zone_t *zone) {
6168 REQUIRE(DNS_ZONE_VALID(zone));
6169 return (zone->zero_no_soa_ttl);
6173 void
6174 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
6175 REQUIRE(DNS_ZONE_VALID(zone));
6176 zone->zero_no_soa_ttl = state;
6179 void
6180 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
6182 REQUIRE(DNS_ZONE_VALID(zone));
6184 zone->check_names = severity;
6187 dns_severity_t
6188 dns_zone_getchecknames(dns_zone_t *zone) {
6190 REQUIRE(DNS_ZONE_VALID(zone));
6192 return (zone->check_names);
6195 void
6196 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
6198 REQUIRE(DNS_ZONE_VALID(zone));
6200 zone->journalsize = size;
6203 isc_int32_t
6204 dns_zone_getjournalsize(dns_zone_t *zone) {
6206 REQUIRE(DNS_ZONE_VALID(zone));
6208 return (zone->journalsize);
6211 static void
6212 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
6213 isc_result_t result = ISC_R_FAILURE;
6214 isc_buffer_t buffer;
6216 REQUIRE(buf != NULL);
6217 REQUIRE(length > 1U);
6220 * Leave space for terminating '\0'.
6222 isc_buffer_init(&buffer, buf, length - 1);
6223 if (dns_name_dynamic(&zone->origin))
6224 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
6225 if (result != ISC_R_SUCCESS &&
6226 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
6227 isc_buffer_putstr(&buffer, "<UNKNOWN>");
6229 if (isc_buffer_availablelength(&buffer) > 0)
6230 isc_buffer_putstr(&buffer, "/");
6231 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
6233 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
6234 strcmp(zone->view->name, "_default") != 0 &&
6235 strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
6236 isc_buffer_putstr(&buffer, "/");
6237 isc_buffer_putstr(&buffer, zone->view->name);
6240 buf[isc_buffer_usedlength(&buffer)] = '\0';
6243 static void
6244 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
6245 isc_result_t result = ISC_R_FAILURE;
6246 isc_buffer_t buffer;
6248 REQUIRE(buf != NULL);
6249 REQUIRE(length > 1U);
6252 * Leave space for terminating '\0'.
6254 isc_buffer_init(&buffer, buf, length - 1);
6255 if (dns_name_dynamic(&zone->origin))
6256 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
6257 if (result != ISC_R_SUCCESS &&
6258 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
6259 isc_buffer_putstr(&buffer, "<UNKNOWN>");
6261 buf[isc_buffer_usedlength(&buffer)] = '\0';
6264 static void
6265 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
6266 isc_buffer_t buffer;
6268 REQUIRE(buf != NULL);
6269 REQUIRE(length > 1U);
6272 * Leave space for terminating '\0'.
6274 isc_buffer_init(&buffer, buf, length - 1);
6275 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
6277 buf[isc_buffer_usedlength(&buffer)] = '\0';
6280 static void
6281 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
6282 isc_buffer_t buffer;
6284 REQUIRE(buf != NULL);
6285 REQUIRE(length > 1U);
6289 * Leave space for terminating '\0'.
6291 isc_buffer_init(&buffer, buf, length - 1);
6293 if (zone->view == NULL) {
6294 isc_buffer_putstr(&buffer, "_none");
6295 } else if (strlen(zone->view->name)
6296 < isc_buffer_availablelength(&buffer)) {
6297 isc_buffer_putstr(&buffer, zone->view->name);
6298 } else {
6299 isc_buffer_putstr(&buffer, "_toolong");
6302 buf[isc_buffer_usedlength(&buffer)] = '\0';
6305 void
6306 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
6307 REQUIRE(DNS_ZONE_VALID(zone));
6308 REQUIRE(buf != NULL);
6309 zone_namerd_tostr(zone, buf, length);
6312 static void
6313 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
6314 va_list ap;
6315 char message[4096];
6317 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
6318 return;
6320 va_start(ap, fmt);
6321 vsnprintf(message, sizeof(message), fmt, ap);
6322 va_end(ap);
6323 isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
6324 level, "zone %s: %s", zone->strnamerd, message);
6327 void
6328 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
6329 int level, const char *fmt, ...) {
6330 va_list ap;
6331 char message[4096];
6333 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
6334 return;
6336 va_start(ap, fmt);
6337 vsnprintf(message, sizeof(message), fmt, ap);
6338 va_end(ap);
6339 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
6340 level, "zone %s: %s", zone->strnamerd, message);
6343 void
6344 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
6345 va_list ap;
6346 char message[4096];
6348 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
6349 return;
6351 va_start(ap, fmt);
6352 vsnprintf(message, sizeof(message), fmt, ap);
6353 va_end(ap);
6354 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
6355 level, "zone %s: %s", zone->strnamerd, message);
6358 static void
6359 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
6360 const char *fmt, ...)
6362 va_list ap;
6363 char message[4096];
6364 int level = ISC_LOG_DEBUG(debuglevel);
6366 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
6367 return;
6369 va_start(ap, fmt);
6370 vsnprintf(message, sizeof(message), fmt, ap);
6371 va_end(ap);
6372 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
6373 level, "%s: zone %s: %s", me, zone->strnamerd, message);
6376 static int
6377 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
6379 isc_result_t result;
6380 dns_name_t *name;
6381 dns_rdataset_t *curr;
6382 int count = 0;
6384 result = dns_message_firstname(msg, section);
6385 while (result == ISC_R_SUCCESS) {
6386 name = NULL;
6387 dns_message_currentname(msg, section, &name);
6389 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
6390 curr = ISC_LIST_PREV(curr, link)) {
6391 if (curr->type == type)
6392 count++;
6394 result = dns_message_nextname(msg, section);
6397 return (count);
6400 void
6401 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
6402 REQUIRE(DNS_ZONE_VALID(zone));
6404 zone->maxxfrin = maxxfrin;
6407 isc_uint32_t
6408 dns_zone_getmaxxfrin(dns_zone_t *zone) {
6409 REQUIRE(DNS_ZONE_VALID(zone));
6411 return (zone->maxxfrin);
6414 void
6415 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
6416 REQUIRE(DNS_ZONE_VALID(zone));
6417 zone->maxxfrout = maxxfrout;
6420 isc_uint32_t
6421 dns_zone_getmaxxfrout(dns_zone_t *zone) {
6422 REQUIRE(DNS_ZONE_VALID(zone));
6424 return (zone->maxxfrout);
6427 dns_zonetype_t
6428 dns_zone_gettype(dns_zone_t *zone) {
6429 REQUIRE(DNS_ZONE_VALID(zone));
6431 return (zone->type);
6434 dns_name_t *
6435 dns_zone_getorigin(dns_zone_t *zone) {
6436 REQUIRE(DNS_ZONE_VALID(zone));
6438 return (&zone->origin);
6441 void
6442 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
6443 REQUIRE(DNS_ZONE_VALID(zone));
6445 LOCK_ZONE(zone);
6446 if (zone->task != NULL)
6447 isc_task_detach(&zone->task);
6448 isc_task_attach(task, &zone->task);
6449 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6450 if (zone->db != NULL)
6451 dns_db_settask(zone->db, zone->task);
6452 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6453 UNLOCK_ZONE(zone);
6456 void
6457 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
6458 REQUIRE(DNS_ZONE_VALID(zone));
6459 isc_task_attach(zone->task, target);
6462 void
6463 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
6464 REQUIRE(DNS_ZONE_VALID(zone));
6466 if (idlein == 0)
6467 idlein = DNS_DEFAULT_IDLEIN;
6468 zone->idlein = idlein;
6471 isc_uint32_t
6472 dns_zone_getidlein(dns_zone_t *zone) {
6473 REQUIRE(DNS_ZONE_VALID(zone));
6475 return (zone->idlein);
6478 void
6479 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
6480 REQUIRE(DNS_ZONE_VALID(zone));
6482 zone->idleout = idleout;
6485 isc_uint32_t
6486 dns_zone_getidleout(dns_zone_t *zone) {
6487 REQUIRE(DNS_ZONE_VALID(zone));
6489 return (zone->idleout);
6492 static void
6493 notify_done(isc_task_t *task, isc_event_t *event) {
6494 dns_requestevent_t *revent = (dns_requestevent_t *)event;
6495 dns_notify_t *notify;
6496 isc_result_t result;
6497 dns_message_t *message = NULL;
6498 isc_buffer_t buf;
6499 char rcode[128];
6500 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6502 UNUSED(task);
6504 notify = event->ev_arg;
6505 REQUIRE(DNS_NOTIFY_VALID(notify));
6506 INSIST(task == notify->zone->task);
6508 isc_buffer_init(&buf, rcode, sizeof(rcode));
6509 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
6511 result = revent->result;
6512 if (result == ISC_R_SUCCESS)
6513 result = dns_message_create(notify->zone->mctx,
6514 DNS_MESSAGE_INTENTPARSE, &message);
6515 if (result == ISC_R_SUCCESS)
6516 result = dns_request_getresponse(revent->request, message,
6517 DNS_MESSAGEPARSE_PRESERVEORDER);
6518 if (result == ISC_R_SUCCESS)
6519 result = dns_rcode_totext(message->rcode, &buf);
6520 if (result == ISC_R_SUCCESS)
6521 notify_log(notify->zone, ISC_LOG_DEBUG(3),
6522 "notify response from %s: %.*s",
6523 addrbuf, (int)buf.used, rcode);
6524 else
6525 notify_log(notify->zone, ISC_LOG_DEBUG(2),
6526 "notify to %s failed: %s", addrbuf,
6527 dns_result_totext(result));
6530 * Old bind's return formerr if they see a soa record. Retry w/o
6531 * the soa if we see a formerr and had sent a SOA.
6533 isc_event_free(&event);
6534 if (message != NULL && message->rcode == dns_rcode_formerr &&
6535 (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
6536 notify->flags |= DNS_NOTIFY_NOSOA;
6537 dns_request_destroy(&notify->request);
6538 result = notify_send_queue(notify);
6539 if (result != ISC_R_SUCCESS)
6540 notify_destroy(notify, ISC_FALSE);
6541 } else {
6542 if (result == ISC_R_TIMEDOUT)
6543 notify_log(notify->zone, ISC_LOG_DEBUG(1),
6544 "notify to %s: retries exceeded", addrbuf);
6545 notify_destroy(notify, ISC_FALSE);
6547 if (message != NULL)
6548 dns_message_destroy(&message);
6551 isc_result_t
6552 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
6553 isc_result_t result;
6555 REQUIRE(DNS_ZONE_VALID(zone));
6556 LOCK_ZONE(zone);
6557 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6558 result = zone_replacedb(zone, db, dump);
6559 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6560 UNLOCK_ZONE(zone);
6561 return (result);
6564 static isc_result_t
6565 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
6566 dns_dbversion_t *ver;
6567 isc_result_t result;
6568 unsigned int soacount = 0;
6569 unsigned int nscount = 0;
6572 * 'zone' and 'zonedb' locked by caller.
6574 REQUIRE(DNS_ZONE_VALID(zone));
6575 REQUIRE(LOCKED_ZONE(zone));
6577 result = zone_get_from_db(zone, db, &nscount, &soacount,
6578 NULL, NULL, NULL, NULL, NULL, NULL);
6579 if (result == ISC_R_SUCCESS) {
6580 if (soacount != 1) {
6581 dns_zone_log(zone, ISC_LOG_ERROR,
6582 "has %d SOA records", soacount);
6583 result = DNS_R_BADZONE;
6585 if (nscount == 0) {
6586 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
6587 result = DNS_R_BADZONE;
6589 if (result != ISC_R_SUCCESS)
6590 return (result);
6591 } else {
6592 dns_zone_log(zone, ISC_LOG_ERROR,
6593 "retrieving SOA and NS records failed: %s",
6594 dns_result_totext(result));
6595 return (result);
6598 ver = NULL;
6599 dns_db_currentversion(db, &ver);
6602 * The initial version of a slave zone is always dumped;
6603 * subsequent versions may be journaled instead if this
6604 * is enabled in the configuration.
6606 if (zone->db != NULL && zone->journal != NULL &&
6607 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
6608 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
6609 isc_uint32_t serial;
6611 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
6613 result = dns_db_getsoaserial(db, ver, &serial);
6614 if (result != ISC_R_SUCCESS) {
6615 dns_zone_log(zone, ISC_LOG_ERROR,
6616 "ixfr-from-differences: unable to get "
6617 "new serial");
6618 goto fail;
6622 * This is checked in zone_postload() for master zones.
6624 if (zone->type == dns_zone_slave &&
6625 !isc_serial_gt(serial, zone->serial)) {
6626 isc_uint32_t serialmin, serialmax;
6627 serialmin = (zone->serial + 1) & 0xffffffffU;
6628 serialmax = (zone->serial + 0x7fffffffU) & 0xffffffffU;
6629 dns_zone_log(zone, ISC_LOG_ERROR,
6630 "ixfr-from-differences: failed: "
6631 "new serial (%u) out of range [%u - %u]",
6632 serial, serialmin, serialmax);
6633 result = ISC_R_RANGE;
6634 goto fail;
6637 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
6638 zone->journal);
6639 if (result != ISC_R_SUCCESS)
6640 goto fail;
6641 if (dump)
6642 zone_needdump(zone, DNS_DUMP_DELAY);
6643 else if (zone->journalsize != -1) {
6644 result = dns_journal_compact(zone->mctx, zone->journal,
6645 serial, zone->journalsize);
6646 switch (result) {
6647 case ISC_R_SUCCESS:
6648 case ISC_R_NOSPACE:
6649 case ISC_R_NOTFOUND:
6650 dns_zone_log(zone, ISC_LOG_DEBUG(3),
6651 "dns_journal_compact: %s",
6652 dns_result_totext(result));
6653 break;
6654 default:
6655 dns_zone_log(zone, ISC_LOG_ERROR,
6656 "dns_journal_compact failed: %s",
6657 dns_result_totext(result));
6658 break;
6661 } else {
6662 if (dump && zone->masterfile != NULL) {
6663 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
6664 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
6665 "dumping new zone version");
6666 result = dns_db_dump2(db, ver, zone->masterfile,
6667 zone->masterformat);
6668 if (result != ISC_R_SUCCESS)
6669 goto fail;
6672 * Update the time the zone was updated, so
6673 * dns_zone_load can avoid loading it when
6674 * the server is reloaded. If isc_time_now
6675 * fails for some reason, all that happens is
6676 * the timestamp is not updated.
6678 TIME_NOW(&zone->loadtime);
6681 if (dump && zone->journal != NULL) {
6683 * The in-memory database just changed, and
6684 * because 'dump' is set, it didn't change by
6685 * being loaded from disk. Also, we have not
6686 * journaled diffs for this change.
6687 * Therefore, the on-disk journal is missing
6688 * the deltas for this change. Since it can
6689 * no longer be used to bring the zone
6690 * up-to-date, it is useless and should be
6691 * removed.
6693 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
6694 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
6695 "removing journal file");
6696 if (remove(zone->journal) < 0 && errno != ENOENT) {
6697 char strbuf[ISC_STRERRORSIZE];
6698 isc__strerror(errno, strbuf, sizeof(strbuf));
6699 isc_log_write(dns_lctx,
6700 DNS_LOGCATEGORY_GENERAL,
6701 DNS_LOGMODULE_ZONE,
6702 ISC_LOG_WARNING,
6703 "unable to remove journal "
6704 "'%s': '%s'",
6705 zone->journal, strbuf);
6710 dns_db_closeversion(db, &ver, ISC_FALSE);
6712 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
6713 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
6714 "replacing zone database");
6716 if (zone->db != NULL)
6717 zone_detachdb(zone);
6718 zone_attachdb(zone, db);
6719 dns_db_settask(zone->db, zone->task);
6720 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
6721 return (ISC_R_SUCCESS);
6723 fail:
6724 dns_db_closeversion(db, &ver, ISC_FALSE);
6725 return (result);
6728 /* The caller must hold the dblock as a writer. */
6729 static inline void
6730 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
6731 REQUIRE(zone->db == NULL && db != NULL);
6733 dns_db_attach(db, &zone->db);
6734 if (zone->acache != NULL) {
6735 isc_result_t result;
6736 result = dns_acache_setdb(zone->acache, db);
6737 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
6738 UNEXPECTED_ERROR(__FILE__, __LINE__,
6739 "dns_acache_setdb() failed: %s",
6740 isc_result_totext(result));
6745 /* The caller must hold the dblock as a writer. */
6746 static inline void
6747 zone_detachdb(dns_zone_t *zone) {
6748 REQUIRE(zone->db != NULL);
6750 if (zone->acache != NULL)
6751 (void)dns_acache_putdb(zone->acache, zone->db);
6752 dns_db_detach(&zone->db);
6755 static void
6756 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
6757 isc_time_t now;
6758 isc_boolean_t again = ISC_FALSE;
6759 unsigned int soacount;
6760 unsigned int nscount;
6761 isc_uint32_t serial, refresh, retry, expire, minimum;
6762 isc_result_t xfrresult = result;
6763 isc_boolean_t free_needed;
6765 REQUIRE(DNS_ZONE_VALID(zone));
6767 dns_zone_log(zone, ISC_LOG_DEBUG(1),
6768 "zone transfer finished: %s", dns_result_totext(result));
6770 LOCK_ZONE(zone);
6771 INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
6772 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
6773 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
6775 TIME_NOW(&now);
6776 switch (result) {
6777 case ISC_R_SUCCESS:
6778 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6779 /*FALLTHROUGH*/
6780 case DNS_R_UPTODATE:
6781 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
6783 * Has the zone expired underneath us?
6785 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6786 if (zone->db == NULL) {
6787 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6788 goto same_master;
6792 * Update the zone structure's data from the actual
6793 * SOA received.
6795 nscount = 0;
6796 soacount = 0;
6797 INSIST(zone->db != NULL);
6798 result = zone_get_from_db(zone, zone->db, &nscount,
6799 &soacount, &serial, &refresh,
6800 &retry, &expire, &minimum, NULL);
6801 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6802 if (result == ISC_R_SUCCESS) {
6803 if (soacount != 1)
6804 dns_zone_log(zone, ISC_LOG_ERROR,
6805 "transferred zone "
6806 "has %d SOA record%s", soacount,
6807 (soacount != 0) ? "s" : "");
6808 if (nscount == 0) {
6809 dns_zone_log(zone, ISC_LOG_ERROR,
6810 "transferred zone "
6811 "has no NS records");
6812 if (DNS_ZONE_FLAG(zone,
6813 DNS_ZONEFLG_HAVETIMERS)) {
6814 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
6815 zone->retry = DNS_ZONE_DEFAULTRETRY;
6817 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
6818 zone_unload(zone);
6819 goto next_master;
6821 zone->serial = serial;
6822 zone->refresh = RANGE(refresh, zone->minrefresh,
6823 zone->maxrefresh);
6824 zone->retry = RANGE(retry, zone->minretry,
6825 zone->maxretry);
6826 zone->expire = RANGE(expire,
6827 zone->refresh + zone->retry,
6828 DNS_MAX_EXPIRE);
6829 zone->minimum = minimum;
6830 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
6834 * Set our next update/expire times.
6836 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
6837 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
6838 zone->refreshtime = now;
6839 DNS_ZONE_TIME_ADD(&now, zone->expire,
6840 &zone->expiretime);
6841 } else {
6842 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
6843 &zone->refreshtime);
6844 DNS_ZONE_TIME_ADD(&now, zone->expire,
6845 &zone->expiretime);
6847 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
6848 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
6849 if (zone->tsigkey != NULL) {
6850 char namebuf[DNS_NAME_FORMATSIZE];
6851 dns_name_format(&zone->tsigkey->name, namebuf,
6852 sizeof(namebuf));
6853 snprintf(buf, sizeof(buf), ": TSIG '%s'",
6854 namebuf);
6855 } else
6856 buf[0] = '\0';
6857 dns_zone_log(zone, ISC_LOG_INFO,
6858 "transferred serial %u%s",
6859 zone->serial, buf);
6863 * This is not necessary if we just performed a AXFR
6864 * however it is necessary for an IXFR / UPTODATE and
6865 * won't hurt with an AXFR.
6867 if (zone->masterfile != NULL || zone->journal != NULL) {
6868 result = ISC_R_FAILURE;
6869 if (zone->journal != NULL)
6870 result = isc_file_settime(zone->journal, &now);
6871 if (result != ISC_R_SUCCESS &&
6872 zone->masterfile != NULL)
6873 result = isc_file_settime(zone->masterfile,
6874 &now);
6875 /* Someone removed the file from underneath us! */
6876 if (result == ISC_R_FILENOTFOUND &&
6877 zone->masterfile != NULL)
6878 zone_needdump(zone, DNS_DUMP_DELAY);
6879 else if (result != ISC_R_SUCCESS)
6880 dns_zone_log(zone, ISC_LOG_ERROR,
6881 "transfer: could not set file "
6882 "modification time of '%s': %s",
6883 zone->masterfile,
6884 dns_result_totext(result));
6887 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
6888 break;
6890 case DNS_R_BADIXFR:
6891 /* Force retry with AXFR. */
6892 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
6893 goto same_master;
6895 default:
6896 next_master:
6898 * Skip to next failed / untried master.
6900 do {
6901 zone->curmaster++;
6902 } while (zone->curmaster < zone->masterscnt &&
6903 zone->mastersok[zone->curmaster]);
6904 /* FALLTHROUGH */
6905 same_master:
6906 if (zone->curmaster >= zone->masterscnt) {
6907 zone->curmaster = 0;
6908 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
6909 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
6910 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
6911 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
6912 while (zone->curmaster < zone->masterscnt &&
6913 zone->mastersok[zone->curmaster])
6914 zone->curmaster++;
6915 again = ISC_TRUE;
6916 } else
6917 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
6918 } else {
6919 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
6920 again = ISC_TRUE;
6922 inc_stats(zone, dns_zonestatscounter_xfrfail);
6923 break;
6925 zone_settimer(zone, &now);
6928 * If creating the transfer object failed, zone->xfr is NULL.
6929 * Otherwise, we are called as the done callback of a zone
6930 * transfer object that just entered its shutting-down
6931 * state. Since we are no longer responsible for shutting
6932 * it down, we can detach our reference.
6934 if (zone->xfr != NULL)
6935 dns_xfrin_detach(&zone->xfr);
6937 if (zone->tsigkey != NULL)
6938 dns_tsigkey_detach(&zone->tsigkey);
6941 * Handle any deferred journal compaction.
6943 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
6944 result = dns_journal_compact(zone->mctx, zone->journal,
6945 zone->compact_serial,
6946 zone->journalsize);
6947 switch (result) {
6948 case ISC_R_SUCCESS:
6949 case ISC_R_NOSPACE:
6950 case ISC_R_NOTFOUND:
6951 dns_zone_log(zone, ISC_LOG_DEBUG(3),
6952 "dns_journal_compact: %s",
6953 dns_result_totext(result));
6954 break;
6955 default:
6956 dns_zone_log(zone, ISC_LOG_ERROR,
6957 "dns_journal_compact failed: %s",
6958 dns_result_totext(result));
6959 break;
6961 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
6965 * This transfer finishing freed up a transfer quota slot.
6966 * Let any other zones waiting for quota have it.
6968 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
6969 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
6970 zone->statelist = NULL;
6971 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
6972 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
6975 * Retry with a different server if necessary.
6977 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
6978 queue_soa_query(zone);
6980 INSIST(zone->irefs > 0);
6981 zone->irefs--;
6982 free_needed = exit_check(zone);
6983 UNLOCK_ZONE(zone);
6984 if (free_needed)
6985 zone_free(zone);
6988 static void
6989 zone_loaddone(void *arg, isc_result_t result) {
6990 static char me[] = "zone_loaddone";
6991 dns_load_t *load = arg;
6992 dns_zone_t *zone;
6993 isc_result_t tresult;
6995 REQUIRE(DNS_LOAD_VALID(load));
6996 zone = load->zone;
6998 ENTER;
7000 tresult = dns_db_endload(load->db, &load->callbacks.add_private);
7001 if (tresult != ISC_R_SUCCESS &&
7002 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
7003 result = tresult;
7005 LOCK_ZONE(load->zone);
7006 (void)zone_postload(load->zone, load->db, load->loadtime, result);
7007 zonemgr_putio(&load->zone->readio);
7008 DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
7010 * Leave the zone frozen if the reload fails.
7012 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
7013 DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW))
7014 zone->update_disabled = ISC_FALSE;
7015 DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW);
7016 UNLOCK_ZONE(load->zone);
7018 load->magic = 0;
7019 dns_db_detach(&load->db);
7020 if (load->zone->lctx != NULL)
7021 dns_loadctx_detach(&load->zone->lctx);
7022 dns_zone_idetach(&load->zone);
7023 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
7026 void
7027 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
7028 REQUIRE(DNS_ZONE_VALID(zone));
7029 REQUIRE(table != NULL);
7030 REQUIRE(*table == NULL);
7032 LOCK_ZONE(zone);
7033 if (zone->ssutable != NULL)
7034 dns_ssutable_attach(zone->ssutable, table);
7035 UNLOCK_ZONE(zone);
7038 void
7039 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
7040 REQUIRE(DNS_ZONE_VALID(zone));
7042 LOCK_ZONE(zone);
7043 if (zone->ssutable != NULL)
7044 dns_ssutable_detach(&zone->ssutable);
7045 if (table != NULL)
7046 dns_ssutable_attach(table, &zone->ssutable);
7047 UNLOCK_ZONE(zone);
7050 void
7051 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
7052 REQUIRE(DNS_ZONE_VALID(zone));
7054 zone->sigvalidityinterval = interval;
7057 isc_uint32_t
7058 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
7059 REQUIRE(DNS_ZONE_VALID(zone));
7061 return (zone->sigvalidityinterval);
7064 static void
7065 queue_xfrin(dns_zone_t *zone) {
7066 const char me[] = "queue_xfrin";
7067 isc_result_t result;
7068 dns_zonemgr_t *zmgr = zone->zmgr;
7070 ENTER;
7072 INSIST(zone->statelist == NULL);
7074 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7075 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
7076 LOCK_ZONE(zone);
7077 zone->irefs++;
7078 UNLOCK_ZONE(zone);
7079 zone->statelist = &zmgr->waiting_for_xfrin;
7080 result = zmgr_start_xfrin_ifquota(zmgr, zone);
7081 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7083 if (result == ISC_R_QUOTA) {
7084 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
7085 "zone transfer deferred due to quota");
7086 } else if (result != ISC_R_SUCCESS) {
7087 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
7088 "starting zone transfer: %s",
7089 isc_result_totext(result));
7094 * This event callback is called when a zone has received
7095 * any necessary zone transfer quota. This is the time
7096 * to go ahead and start the transfer.
7098 static void
7099 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
7100 isc_result_t result;
7101 dns_peer_t *peer = NULL;
7102 char master[ISC_SOCKADDR_FORMATSIZE];
7103 char source[ISC_SOCKADDR_FORMATSIZE];
7104 dns_rdatatype_t xfrtype;
7105 dns_zone_t *zone = event->ev_arg;
7106 isc_netaddr_t masterip;
7107 isc_sockaddr_t sourceaddr;
7108 isc_sockaddr_t masteraddr;
7109 isc_time_t now;
7111 UNUSED(task);
7113 INSIST(task == zone->task);
7115 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
7116 result = ISC_R_CANCELED;
7117 goto cleanup;
7120 TIME_NOW(&now);
7122 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
7123 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
7124 &zone->sourceaddr, &now)) {
7125 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
7126 dns_zone_log(zone, ISC_LOG_INFO,
7127 "got_transfer_quota: skipping zone transfer as "
7128 "master %s (source %s) is unreachable (cached)",
7129 master, source);
7130 result = ISC_R_CANCELED;
7131 goto cleanup;
7134 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
7135 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
7138 * Decide whether we should request IXFR or AXFR.
7140 if (zone->db == NULL) {
7141 dns_zone_log(zone, ISC_LOG_DEBUG(1),
7142 "no database exists yet, requesting AXFR of "
7143 "initial version from %s", master);
7144 xfrtype = dns_rdatatype_axfr;
7145 } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
7146 dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
7147 "set, requesting AXFR from %s", master);
7148 xfrtype = dns_rdatatype_axfr;
7149 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
7150 dns_zone_log(zone, ISC_LOG_DEBUG(1),
7151 "forced reload, requesting AXFR of "
7152 "initial version from %s", master);
7153 xfrtype = dns_rdatatype_axfr;
7154 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
7155 dns_zone_log(zone, ISC_LOG_DEBUG(1),
7156 "retrying with AXFR from %s due to "
7157 "previous IXFR failure", master);
7158 xfrtype = dns_rdatatype_axfr;
7159 LOCK_ZONE(zone);
7160 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
7161 UNLOCK_ZONE(zone);
7162 } else {
7163 isc_boolean_t use_ixfr = ISC_TRUE;
7164 if (peer != NULL &&
7165 dns_peer_getrequestixfr(peer, &use_ixfr) ==
7166 ISC_R_SUCCESS) {
7167 ; /* Using peer setting */
7168 } else {
7169 use_ixfr = zone->view->requestixfr;
7171 if (use_ixfr == ISC_FALSE) {
7172 dns_zone_log(zone, ISC_LOG_DEBUG(1),
7173 "IXFR disabled, requesting AXFR from %s",
7174 master);
7175 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
7176 xfrtype = dns_rdatatype_soa;
7177 else
7178 xfrtype = dns_rdatatype_axfr;
7179 } else {
7180 dns_zone_log(zone, ISC_LOG_DEBUG(1),
7181 "requesting IXFR from %s", master);
7182 xfrtype = dns_rdatatype_ixfr;
7187 * Determine if we should attempt to sign the request with TSIG.
7189 result = ISC_R_NOTFOUND;
7191 * First, look for a tsig key in the master statement, then
7192 * try for a server key.
7194 if ((zone->masterkeynames != NULL) &&
7195 (zone->masterkeynames[zone->curmaster] != NULL)) {
7196 dns_view_t *view = dns_zone_getview(zone);
7197 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
7198 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
7200 if (zone->tsigkey == NULL)
7201 result = dns_view_getpeertsig(zone->view, &masterip,
7202 &zone->tsigkey);
7204 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
7205 dns_zone_log(zone, ISC_LOG_ERROR,
7206 "could not get TSIG key for zone transfer: %s",
7207 isc_result_totext(result));
7210 LOCK_ZONE(zone);
7211 masteraddr = zone->masteraddr;
7212 sourceaddr = zone->sourceaddr;
7213 UNLOCK_ZONE(zone);
7214 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
7215 result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
7216 zone->tsigkey, zone->mctx,
7217 zone->zmgr->timermgr, zone->zmgr->socketmgr,
7218 zone->task, zone_xfrdone, &zone->xfr);
7219 if (result == ISC_R_SUCCESS) {
7220 LOCK_ZONE(zone);
7221 if (xfrtype == dns_rdatatype_axfr) {
7222 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
7223 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
7224 else
7225 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
7226 } else if (xfrtype == dns_rdatatype_ixfr) {
7227 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
7228 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
7229 else
7230 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
7232 UNLOCK_ZONE(zone);
7234 cleanup:
7236 * Any failure in this function is handled like a failed
7237 * zone transfer. This ensures that we get removed from
7238 * zmgr->xfrin_in_progress.
7240 if (result != ISC_R_SUCCESS)
7241 zone_xfrdone(zone, result);
7243 isc_event_free(&event);
7247 * Update forwarding support.
7250 static void
7251 forward_destroy(dns_forward_t *forward) {
7253 forward->magic = 0;
7254 if (forward->request != NULL)
7255 dns_request_destroy(&forward->request);
7256 if (forward->msgbuf != NULL)
7257 isc_buffer_free(&forward->msgbuf);
7258 if (forward->zone != NULL)
7259 dns_zone_idetach(&forward->zone);
7260 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
7263 static isc_result_t
7264 sendtomaster(dns_forward_t *forward) {
7265 isc_result_t result;
7266 isc_sockaddr_t src;
7268 LOCK_ZONE(forward->zone);
7269 if (forward->which >= forward->zone->masterscnt) {
7270 UNLOCK_ZONE(forward->zone);
7271 return (ISC_R_NOMORE);
7274 forward->addr = forward->zone->masters[forward->which];
7276 * Always use TCP regardless of whether the original update
7277 * used TCP.
7278 * XXX The timeout may but a bit small if we are far down a
7279 * transfer graph and the master has to try several masters.
7281 switch (isc_sockaddr_pf(&forward->addr)) {
7282 case PF_INET:
7283 src = forward->zone->xfrsource4;
7284 break;
7285 case PF_INET6:
7286 src = forward->zone->xfrsource6;
7287 break;
7288 default:
7289 result = ISC_R_NOTIMPLEMENTED;
7290 goto unlock;
7292 result = dns_request_createraw(forward->zone->view->requestmgr,
7293 forward->msgbuf,
7294 &src, &forward->addr,
7295 DNS_REQUESTOPT_TCP, 15 /* XXX */,
7296 forward->zone->task,
7297 forward_callback, forward,
7298 &forward->request);
7299 unlock:
7300 UNLOCK_ZONE(forward->zone);
7301 return (result);
7304 static void
7305 forward_callback(isc_task_t *task, isc_event_t *event) {
7306 const char me[] = "forward_callback";
7307 dns_requestevent_t *revent = (dns_requestevent_t *)event;
7308 dns_message_t *msg = NULL;
7309 char master[ISC_SOCKADDR_FORMATSIZE];
7310 isc_result_t result;
7311 dns_forward_t *forward;
7312 dns_zone_t *zone;
7314 UNUSED(task);
7316 forward = revent->ev_arg;
7317 INSIST(DNS_FORWARD_VALID(forward));
7318 zone = forward->zone;
7319 INSIST(DNS_ZONE_VALID(zone));
7321 ENTER;
7323 isc_sockaddr_format(&forward->addr, master, sizeof(master));
7325 if (revent->result != ISC_R_SUCCESS) {
7326 dns_zone_log(zone, ISC_LOG_INFO,
7327 "could not forward dynamic update to %s: %s",
7328 master, dns_result_totext(revent->result));
7329 goto next_master;
7332 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
7333 if (result != ISC_R_SUCCESS)
7334 goto next_master;
7336 result = dns_request_getresponse(revent->request, msg,
7337 DNS_MESSAGEPARSE_PRESERVEORDER |
7338 DNS_MESSAGEPARSE_CLONEBUFFER);
7339 if (result != ISC_R_SUCCESS)
7340 goto next_master;
7342 switch (msg->rcode) {
7344 * Pass these rcodes back to client.
7346 case dns_rcode_noerror:
7347 case dns_rcode_yxdomain:
7348 case dns_rcode_yxrrset:
7349 case dns_rcode_nxrrset:
7350 case dns_rcode_refused:
7351 case dns_rcode_nxdomain:
7352 break;
7354 /* These should not occur if the masters/zone are valid. */
7355 case dns_rcode_notzone:
7356 case dns_rcode_notauth: {
7357 char rcode[128];
7358 isc_buffer_t rb;
7360 isc_buffer_init(&rb, rcode, sizeof(rcode));
7361 (void)dns_rcode_totext(msg->rcode, &rb);
7362 dns_zone_log(zone, ISC_LOG_WARNING,
7363 "forwarding dynamic update: "
7364 "unexpected response: master %s returned: %.*s",
7365 master, (int)rb.used, rcode);
7366 goto next_master;
7369 /* Try another server for these rcodes. */
7370 case dns_rcode_formerr:
7371 case dns_rcode_servfail:
7372 case dns_rcode_notimp:
7373 case dns_rcode_badvers:
7374 default:
7375 goto next_master;
7378 /* call callback */
7379 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
7380 msg = NULL;
7381 dns_request_destroy(&forward->request);
7382 forward_destroy(forward);
7383 isc_event_free(&event);
7384 return;
7386 next_master:
7387 if (msg != NULL)
7388 dns_message_destroy(&msg);
7389 isc_event_free(&event);
7390 forward->which++;
7391 dns_request_destroy(&forward->request);
7392 result = sendtomaster(forward);
7393 if (result != ISC_R_SUCCESS) {
7394 /* call callback */
7395 dns_zone_log(zone, ISC_LOG_DEBUG(3),
7396 "exhausted dynamic update forwarder list");
7397 (forward->callback)(forward->callback_arg, result, NULL);
7398 forward_destroy(forward);
7402 isc_result_t
7403 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
7404 dns_updatecallback_t callback, void *callback_arg)
7406 dns_forward_t *forward;
7407 isc_result_t result;
7408 isc_region_t *mr;
7410 REQUIRE(DNS_ZONE_VALID(zone));
7411 REQUIRE(msg != NULL);
7412 REQUIRE(callback != NULL);
7414 forward = isc_mem_get(zone->mctx, sizeof(*forward));
7415 if (forward == NULL)
7416 return (ISC_R_NOMEMORY);
7418 forward->request = NULL;
7419 forward->zone = NULL;
7420 forward->msgbuf = NULL;
7421 forward->which = 0;
7422 forward->mctx = 0;
7423 forward->callback = callback;
7424 forward->callback_arg = callback_arg;
7425 forward->magic = FORWARD_MAGIC;
7427 mr = dns_message_getrawmessage(msg);
7428 if (mr == NULL) {
7429 result = ISC_R_UNEXPECTEDEND;
7430 goto cleanup;
7433 result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
7434 if (result != ISC_R_SUCCESS)
7435 goto cleanup;
7436 result = isc_buffer_copyregion(forward->msgbuf, mr);
7437 if (result != ISC_R_SUCCESS)
7438 goto cleanup;
7440 isc_mem_attach(zone->mctx, &forward->mctx);
7441 dns_zone_iattach(zone, &forward->zone);
7442 result = sendtomaster(forward);
7444 cleanup:
7445 if (result != ISC_R_SUCCESS) {
7446 forward_destroy(forward);
7448 return (result);
7451 isc_result_t
7452 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
7453 REQUIRE(DNS_ZONE_VALID(zone));
7454 REQUIRE(next != NULL && *next == NULL);
7456 *next = ISC_LIST_NEXT(zone, link);
7457 if (*next == NULL)
7458 return (ISC_R_NOMORE);
7459 else
7460 return (ISC_R_SUCCESS);
7463 isc_result_t
7464 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
7465 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7466 REQUIRE(first != NULL && *first == NULL);
7468 *first = ISC_LIST_HEAD(zmgr->zones);
7469 if (*first == NULL)
7470 return (ISC_R_NOMORE);
7471 else
7472 return (ISC_R_SUCCESS);
7475 /***
7476 *** Zone manager.
7477 ***/
7479 isc_result_t
7480 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
7481 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
7482 dns_zonemgr_t **zmgrp)
7484 dns_zonemgr_t *zmgr;
7485 isc_result_t result;
7486 isc_interval_t interval;
7488 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
7489 if (zmgr == NULL)
7490 return (ISC_R_NOMEMORY);
7491 zmgr->mctx = NULL;
7492 zmgr->refs = 1;
7493 isc_mem_attach(mctx, &zmgr->mctx);
7494 zmgr->taskmgr = taskmgr;
7495 zmgr->timermgr = timermgr;
7496 zmgr->socketmgr = socketmgr;
7497 zmgr->zonetasks = NULL;
7498 zmgr->task = NULL;
7499 zmgr->rl = NULL;
7500 ISC_LIST_INIT(zmgr->zones);
7501 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
7502 ISC_LIST_INIT(zmgr->xfrin_in_progress);
7503 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
7504 result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
7505 if (result != ISC_R_SUCCESS)
7506 goto free_mem;
7508 zmgr->transfersin = 10;
7509 zmgr->transfersperns = 2;
7511 /* Create the zone task pool. */
7512 result = isc_taskpool_create(taskmgr, mctx,
7513 8 /* XXX */, 2, &zmgr->zonetasks);
7514 if (result != ISC_R_SUCCESS)
7515 goto free_rwlock;
7517 /* Create a single task for queueing of SOA queries. */
7518 result = isc_task_create(taskmgr, 1, &zmgr->task);
7519 if (result != ISC_R_SUCCESS)
7520 goto free_taskpool;
7521 isc_task_setname(zmgr->task, "zmgr", zmgr);
7522 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
7523 &zmgr->rl);
7524 if (result != ISC_R_SUCCESS)
7525 goto free_task;
7526 /* default to 20 refresh queries / notifies per second. */
7527 isc_interval_set(&interval, 0, 1000000000/2);
7528 result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
7529 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7530 isc_ratelimiter_setpertic(zmgr->rl, 10);
7532 zmgr->iolimit = 1;
7533 zmgr->ioactive = 0;
7534 ISC_LIST_INIT(zmgr->high);
7535 ISC_LIST_INIT(zmgr->low);
7537 result = isc_mutex_init(&zmgr->iolock);
7538 if (result != ISC_R_SUCCESS)
7539 goto free_rl;
7541 zmgr->magic = ZONEMGR_MAGIC;
7543 *zmgrp = zmgr;
7544 return (ISC_R_SUCCESS);
7546 #if 0
7547 free_iolock:
7548 DESTROYLOCK(&zmgr->iolock);
7549 #endif
7550 free_rl:
7551 isc_ratelimiter_detach(&zmgr->rl);
7552 free_task:
7553 isc_task_detach(&zmgr->task);
7554 free_taskpool:
7555 isc_taskpool_destroy(&zmgr->zonetasks);
7556 free_rwlock:
7557 isc_rwlock_destroy(&zmgr->rwlock);
7558 free_mem:
7559 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
7560 isc_mem_detach(&mctx);
7561 return (result);
7564 isc_result_t
7565 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
7566 isc_result_t result;
7568 REQUIRE(DNS_ZONE_VALID(zone));
7569 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7571 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7572 LOCK_ZONE(zone);
7573 REQUIRE(zone->task == NULL);
7574 REQUIRE(zone->timer == NULL);
7575 REQUIRE(zone->zmgr == NULL);
7577 isc_taskpool_gettask(zmgr->zonetasks,
7578 dns_name_hash(dns_zone_getorigin(zone),
7579 ISC_FALSE),
7580 &zone->task);
7583 * Set the task name. The tag will arbitrarily point to one
7584 * of the zones sharing the task (in practice, the one
7585 * to be managed last).
7587 isc_task_setname(zone->task, "zone", zone);
7589 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
7590 NULL, NULL,
7591 zone->task, zone_timer, zone,
7592 &zone->timer);
7594 if (result != ISC_R_SUCCESS)
7595 goto cleanup_task;
7598 * The timer "holds" a iref.
7600 zone->irefs++;
7601 INSIST(zone->irefs != 0);
7603 ISC_LIST_APPEND(zmgr->zones, zone, link);
7604 zone->zmgr = zmgr;
7605 zmgr->refs++;
7607 goto unlock;
7609 cleanup_task:
7610 isc_task_detach(&zone->task);
7612 unlock:
7613 UNLOCK_ZONE(zone);
7614 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7615 return (result);
7618 void
7619 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
7620 isc_boolean_t free_now = ISC_FALSE;
7622 REQUIRE(DNS_ZONE_VALID(zone));
7623 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7624 REQUIRE(zone->zmgr == zmgr);
7626 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7627 LOCK_ZONE(zone);
7629 ISC_LIST_UNLINK(zmgr->zones, zone, link);
7630 zone->zmgr = NULL;
7631 zmgr->refs--;
7632 if (zmgr->refs == 0)
7633 free_now = ISC_TRUE;
7635 UNLOCK_ZONE(zone);
7636 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7638 if (free_now)
7639 zonemgr_free(zmgr);
7640 ENSURE(zone->zmgr == NULL);
7643 void
7644 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
7645 REQUIRE(DNS_ZONEMGR_VALID(source));
7646 REQUIRE(target != NULL && *target == NULL);
7648 RWLOCK(&source->rwlock, isc_rwlocktype_write);
7649 REQUIRE(source->refs > 0);
7650 source->refs++;
7651 INSIST(source->refs > 0);
7652 RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
7653 *target = source;
7656 void
7657 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
7658 dns_zonemgr_t *zmgr;
7659 isc_boolean_t free_now = ISC_FALSE;
7661 REQUIRE(zmgrp != NULL);
7662 zmgr = *zmgrp;
7663 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7665 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7666 zmgr->refs--;
7667 if (zmgr->refs == 0)
7668 free_now = ISC_TRUE;
7669 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7671 if (free_now)
7672 zonemgr_free(zmgr);
7675 isc_result_t
7676 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
7677 dns_zone_t *p;
7679 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7681 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
7682 for (p = ISC_LIST_HEAD(zmgr->zones);
7683 p != NULL;
7684 p = ISC_LIST_NEXT(p, link))
7686 dns_zone_maintenance(p);
7688 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
7691 * Recent configuration changes may have increased the
7692 * amount of available transfers quota. Make sure any
7693 * transfers currently blocked on quota get started if
7694 * possible.
7696 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7697 zmgr_resume_xfrs(zmgr, ISC_TRUE);
7698 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7699 return (ISC_R_SUCCESS);
7702 void
7703 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
7705 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7707 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7708 zmgr_resume_xfrs(zmgr, ISC_TRUE);
7709 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7712 void
7713 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
7714 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7716 isc_ratelimiter_shutdown(zmgr->rl);
7718 if (zmgr->task != NULL)
7719 isc_task_destroy(&zmgr->task);
7720 if (zmgr->zonetasks != NULL)
7721 isc_taskpool_destroy(&zmgr->zonetasks);
7724 static void
7725 zonemgr_free(dns_zonemgr_t *zmgr) {
7726 isc_mem_t *mctx;
7728 INSIST(zmgr->refs == 0);
7729 INSIST(ISC_LIST_EMPTY(zmgr->zones));
7731 zmgr->magic = 0;
7733 DESTROYLOCK(&zmgr->iolock);
7734 isc_ratelimiter_detach(&zmgr->rl);
7736 isc_rwlock_destroy(&zmgr->rwlock);
7737 mctx = zmgr->mctx;
7738 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
7739 isc_mem_detach(&mctx);
7742 void
7743 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
7744 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7746 zmgr->transfersin = value;
7749 isc_uint32_t
7750 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
7751 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7753 return (zmgr->transfersin);
7756 void
7757 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
7758 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7760 zmgr->transfersperns = value;
7763 isc_uint32_t
7764 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
7765 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7767 return (zmgr->transfersperns);
7771 * Try to start a new incoming zone transfer to fill a quota
7772 * slot that was just vacated.
7774 * Requires:
7775 * The zone manager is locked by the caller.
7777 static void
7778 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
7779 dns_zone_t *zone;
7780 dns_zone_t *next;
7782 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
7783 zone != NULL;
7784 zone = next)
7786 isc_result_t result;
7787 next = ISC_LIST_NEXT(zone, statelink);
7788 result = zmgr_start_xfrin_ifquota(zmgr, zone);
7789 if (result == ISC_R_SUCCESS) {
7790 if (multi)
7791 continue;
7793 * We successfully filled the slot. We're done.
7795 break;
7796 } else if (result == ISC_R_QUOTA) {
7798 * Not enough quota. This is probably the per-server
7799 * quota, because we usually get called when a unit of
7800 * global quota has just been freed. Try the next
7801 * zone, it may succeed if it uses another master.
7803 continue;
7804 } else {
7805 dns_zone_log(zone, ISC_LOG_DEBUG(1),
7806 "starting zone transfer: %s",
7807 isc_result_totext(result));
7808 break;
7814 * Try to start an incoming zone transfer for 'zone', quota permitting.
7816 * Requires:
7817 * The zone manager is locked by the caller.
7819 * Returns:
7820 * ISC_R_SUCCESS There was enough quota and we attempted to
7821 * start a transfer. zone_xfrdone() has been or will
7822 * be called.
7823 * ISC_R_QUOTA Not enough quota.
7824 * Others Failure.
7826 static isc_result_t
7827 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
7828 dns_peer_t *peer = NULL;
7829 isc_netaddr_t masterip;
7830 isc_uint32_t nxfrsin, nxfrsperns;
7831 dns_zone_t *x;
7832 isc_uint32_t maxtransfersin, maxtransfersperns;
7833 isc_event_t *e;
7836 * Find any configured information about the server we'd
7837 * like to transfer this zone from.
7839 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
7840 (void)dns_peerlist_peerbyaddr(zone->view->peers,
7841 &masterip, &peer);
7844 * Determine the total maximum number of simultaneous
7845 * transfers allowed, and the maximum for this specific
7846 * master.
7848 maxtransfersin = zmgr->transfersin;
7849 maxtransfersperns = zmgr->transfersperns;
7850 if (peer != NULL)
7851 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
7854 * Count the total number of transfers that are in progress,
7855 * and the number of transfers in progress from this master.
7856 * We linearly scan a list of all transfers; if this turns
7857 * out to be too slow, we could hash on the master address.
7859 nxfrsin = nxfrsperns = 0;
7860 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
7861 x != NULL;
7862 x = ISC_LIST_NEXT(x, statelink))
7864 isc_netaddr_t xip;
7865 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
7866 nxfrsin++;
7867 if (isc_netaddr_equal(&xip, &masterip))
7868 nxfrsperns++;
7871 /* Enforce quota. */
7872 if (nxfrsin >= maxtransfersin)
7873 return (ISC_R_QUOTA);
7875 if (nxfrsperns >= maxtransfersperns)
7876 return (ISC_R_QUOTA);
7879 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
7880 * list and send it an event to let it start the actual transfer in the
7881 * context of its own task.
7883 e = isc_event_allocate(zmgr->mctx, zmgr,
7884 DNS_EVENT_ZONESTARTXFRIN,
7885 got_transfer_quota, zone,
7886 sizeof(isc_event_t));
7887 if (e == NULL)
7888 return (ISC_R_NOMEMORY);
7890 LOCK_ZONE(zone);
7891 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
7892 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
7893 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
7894 zone->statelist = &zmgr->xfrin_in_progress;
7895 isc_task_send(zone->task, &e);
7896 dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
7897 UNLOCK_ZONE(zone);
7899 return (ISC_R_SUCCESS);
7902 void
7903 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
7905 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7906 REQUIRE(iolimit > 0);
7908 zmgr->iolimit = iolimit;
7911 isc_uint32_t
7912 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
7914 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7916 return (zmgr->iolimit);
7920 * Get permission to request a file handle from the OS.
7921 * An event will be sent to action when one is available.
7922 * There are two queues available (high and low), the high
7923 * queue will be serviced before the low one.
7925 * zonemgr_putio() must be called after the event is delivered to
7926 * 'action'.
7929 static isc_result_t
7930 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
7931 isc_task_t *task, isc_taskaction_t action, void *arg,
7932 dns_io_t **iop)
7934 dns_io_t *io;
7935 isc_boolean_t queue;
7937 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7938 REQUIRE(iop != NULL && *iop == NULL);
7940 io = isc_mem_get(zmgr->mctx, sizeof(*io));
7941 if (io == NULL)
7942 return (ISC_R_NOMEMORY);
7943 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
7944 action, arg, sizeof(*io->event));
7945 if (io->event == NULL) {
7946 isc_mem_put(zmgr->mctx, io, sizeof(*io));
7947 return (ISC_R_NOMEMORY);
7949 io->zmgr = zmgr;
7950 io->high = high;
7951 io->task = NULL;
7952 isc_task_attach(task, &io->task);
7953 ISC_LINK_INIT(io, link);
7954 io->magic = IO_MAGIC;
7956 LOCK(&zmgr->iolock);
7957 zmgr->ioactive++;
7958 queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
7959 if (queue) {
7960 if (io->high)
7961 ISC_LIST_APPEND(zmgr->high, io, link);
7962 else
7963 ISC_LIST_APPEND(zmgr->low, io, link);
7965 UNLOCK(&zmgr->iolock);
7966 *iop = io;
7968 if (!queue) {
7969 isc_task_send(io->task, &io->event);
7971 return (ISC_R_SUCCESS);
7974 static void
7975 zonemgr_putio(dns_io_t **iop) {
7976 dns_io_t *io;
7977 dns_io_t *next;
7978 dns_zonemgr_t *zmgr;
7980 REQUIRE(iop != NULL);
7981 io = *iop;
7982 REQUIRE(DNS_IO_VALID(io));
7984 *iop = NULL;
7986 INSIST(!ISC_LINK_LINKED(io, link));
7987 INSIST(io->event == NULL);
7989 zmgr = io->zmgr;
7990 isc_task_detach(&io->task);
7991 io->magic = 0;
7992 isc_mem_put(zmgr->mctx, io, sizeof(*io));
7994 LOCK(&zmgr->iolock);
7995 INSIST(zmgr->ioactive > 0);
7996 zmgr->ioactive--;
7997 next = HEAD(zmgr->high);
7998 if (next == NULL)
7999 next = HEAD(zmgr->low);
8000 if (next != NULL) {
8001 if (next->high)
8002 ISC_LIST_UNLINK(zmgr->high, next, link);
8003 else
8004 ISC_LIST_UNLINK(zmgr->low, next, link);
8005 INSIST(next->event != NULL);
8007 UNLOCK(&zmgr->iolock);
8008 if (next != NULL)
8009 isc_task_send(next->task, &next->event);
8012 static void
8013 zonemgr_cancelio(dns_io_t *io) {
8014 isc_boolean_t send_event = ISC_FALSE;
8016 REQUIRE(DNS_IO_VALID(io));
8019 * If we are queued to be run then dequeue.
8021 LOCK(&io->zmgr->iolock);
8022 if (ISC_LINK_LINKED(io, link)) {
8023 if (io->high)
8024 ISC_LIST_UNLINK(io->zmgr->high, io, link);
8025 else
8026 ISC_LIST_UNLINK(io->zmgr->low, io, link);
8028 send_event = ISC_TRUE;
8029 INSIST(io->event != NULL);
8031 UNLOCK(&io->zmgr->iolock);
8032 if (send_event) {
8033 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
8034 isc_task_send(io->task, &io->event);
8038 static void
8039 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
8040 char *buf;
8041 int buflen;
8042 isc_result_t result;
8044 buflen = strlen(path) + strlen(templat) + 2;
8046 buf = isc_mem_get(zone->mctx, buflen);
8047 if (buf == NULL)
8048 return;
8050 result = isc_file_template(path, templat, buf, buflen);
8051 if (result != ISC_R_SUCCESS)
8052 goto cleanup;
8054 result = isc_file_renameunique(path, buf);
8055 if (result != ISC_R_SUCCESS)
8056 goto cleanup;
8058 dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'",
8059 path, buf);
8061 cleanup:
8062 isc_mem_put(zone->mctx, buf, buflen);
8065 #if 0
8066 /* Hook for ondestroy notification from a database. */
8068 static void
8069 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
8070 dns_db_t *db = event->sender;
8071 UNUSED(task);
8073 isc_event_free(&event);
8075 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
8076 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
8077 "database (%p) destroyed", (void*) db);
8079 #endif
8081 void
8082 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
8083 isc_interval_t interval;
8084 isc_uint32_t s, ns;
8085 isc_uint32_t pertic;
8086 isc_result_t result;
8088 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
8090 if (value == 0)
8091 value = 1;
8093 if (value == 1) {
8094 s = 1;
8095 ns = 0;
8096 pertic = 1;
8097 } else if (value <= 10) {
8098 s = 0;
8099 ns = 1000000000 / value;
8100 pertic = 1;
8101 } else {
8102 s = 0;
8103 ns = (1000000000 / value) * 10;
8104 pertic = 10;
8107 isc_interval_set(&interval, s, ns);
8108 result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
8109 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8110 isc_ratelimiter_setpertic(zmgr->rl, pertic);
8112 zmgr->serialqueryrate = value;
8115 unsigned int
8116 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
8117 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
8119 return (zmgr->serialqueryrate);
8122 static isc_boolean_t
8123 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
8124 isc_sockaddr_t *local, isc_time_t *now)
8126 unsigned int i;
8127 isc_rwlocktype_t locktype;
8128 isc_result_t result;
8129 isc_uint32_t seconds = isc_time_seconds(now);
8131 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
8133 locktype = isc_rwlocktype_read;
8134 RWLOCK(&zmgr->rwlock, locktype);
8135 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
8136 if (zmgr->unreachable[i].expire >= seconds &&
8137 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
8138 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
8139 result = isc_rwlock_tryupgrade(&zmgr->rwlock);
8140 if (result == ISC_R_SUCCESS) {
8141 locktype = isc_rwlocktype_write;
8142 zmgr->unreachable[i].last = seconds;
8144 break;
8147 RWUNLOCK(&zmgr->rwlock, locktype);
8148 return (ISC_TF(i < UNREACH_CHACHE_SIZE));
8151 void
8152 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
8153 isc_sockaddr_t *local, isc_time_t *now)
8155 isc_uint32_t seconds = isc_time_seconds(now);
8156 isc_uint32_t last = seconds;
8157 unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
8159 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
8161 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
8162 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
8163 /* Existing entry? */
8164 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
8165 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
8166 break;
8167 /* Empty slot? */
8168 if (zmgr->unreachable[i].expire < seconds)
8169 slot = i;
8170 /* Least recently used slot? */
8171 if (zmgr->unreachable[i].last < last) {
8172 last = zmgr->unreachable[i].last;
8173 oldest = i;
8176 if (i < UNREACH_CHACHE_SIZE) {
8178 * Found a existing entry. Update the expire timer and
8179 * last usage timestamps.
8181 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
8182 zmgr->unreachable[i].last = seconds;
8183 } else if (slot != UNREACH_CHACHE_SIZE) {
8185 * Found a empty slot. Add a new entry to the cache.
8187 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
8188 zmgr->unreachable[slot].last = seconds;
8189 zmgr->unreachable[slot].remote = *remote;
8190 zmgr->unreachable[slot].local = *local;
8191 } else {
8193 * Replace the least recently used entry in the cache.
8195 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
8196 zmgr->unreachable[oldest].last = seconds;
8197 zmgr->unreachable[oldest].remote = *remote;
8198 zmgr->unreachable[oldest].local = *local;
8200 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
8203 void
8204 dns_zone_forcereload(dns_zone_t *zone) {
8205 REQUIRE(DNS_ZONE_VALID(zone));
8207 if (zone->type == dns_zone_master)
8208 return;
8210 LOCK_ZONE(zone);
8211 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
8212 UNLOCK_ZONE(zone);
8213 dns_zone_refresh(zone);
8216 isc_boolean_t
8217 dns_zone_isforced(dns_zone_t *zone) {
8218 REQUIRE(DNS_ZONE_VALID(zone));
8220 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
8223 isc_result_t
8224 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
8226 * This function is obsoleted.
8228 UNUSED(zone);
8229 UNUSED(on);
8230 return (ISC_R_NOTIMPLEMENTED);
8233 isc_uint64_t *
8234 dns_zone_getstatscounters(dns_zone_t *zone) {
8236 * This function is obsoleted.
8238 UNUSED(zone);
8239 return (NULL);
8242 void
8243 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
8244 REQUIRE(DNS_ZONE_VALID(zone));
8245 REQUIRE(zone->stats == NULL);
8247 LOCK_ZONE(zone);
8248 zone->stats = NULL;
8249 isc_stats_attach(stats, &zone->stats);
8250 UNLOCK_ZONE(zone);
8253 void
8254 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
8255 REQUIRE(DNS_ZONE_VALID(zone));
8257 LOCK_ZONE(zone);
8258 if (zone->requeststats_on && stats == NULL)
8259 zone->requeststats_on = ISC_FALSE;
8260 else if (!zone->requeststats_on && stats != NULL) {
8261 if (zone->requeststats == NULL) {
8262 isc_stats_attach(stats, &zone->requeststats);
8263 zone->requeststats_on = ISC_TRUE;
8266 UNLOCK_ZONE(zone);
8268 return;
8271 isc_stats_t *
8272 dns_zone_getrequeststats(dns_zone_t *zone) {
8274 * We don't lock zone for efficiency reason. This is not catastrophic
8275 * because requeststats must always be valid when requeststats_on is
8276 * true.
8277 * Some counters may be incremented while requeststats_on is becoming
8278 * false, or some cannot be incremented just after the statistics are
8279 * installed, but it shouldn't matter much in practice.
8281 if (zone->requeststats_on)
8282 return (zone->requeststats);
8283 else
8284 return (NULL);
8287 void
8288 dns_zone_dialup(dns_zone_t *zone) {
8290 REQUIRE(DNS_ZONE_VALID(zone));
8292 zone_debuglog(zone, "dns_zone_dialup", 3,
8293 "notify = %d, refresh = %d",
8294 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
8295 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
8297 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
8298 dns_zone_notify(zone);
8299 if (zone->type != dns_zone_master &&
8300 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
8301 dns_zone_refresh(zone);
8304 void
8305 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
8306 REQUIRE(DNS_ZONE_VALID(zone));
8308 LOCK_ZONE(zone);
8309 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
8310 DNS_ZONEFLG_DIALREFRESH |
8311 DNS_ZONEFLG_NOREFRESH);
8312 switch (dialup) {
8313 case dns_dialuptype_no:
8314 break;
8315 case dns_dialuptype_yes:
8316 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
8317 DNS_ZONEFLG_DIALREFRESH |
8318 DNS_ZONEFLG_NOREFRESH));
8319 break;
8320 case dns_dialuptype_notify:
8321 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
8322 break;
8323 case dns_dialuptype_notifypassive:
8324 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
8325 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
8326 break;
8327 case dns_dialuptype_refresh:
8328 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
8329 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
8330 break;
8331 case dns_dialuptype_passive:
8332 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
8333 break;
8334 default:
8335 INSIST(0);
8337 UNLOCK_ZONE(zone);
8340 isc_result_t
8341 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
8342 isc_result_t result = ISC_R_SUCCESS;
8344 REQUIRE(DNS_ZONE_VALID(zone));
8346 LOCK_ZONE(zone);
8347 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
8348 UNLOCK_ZONE(zone);
8350 return (result);
8353 const char *
8354 dns_zone_getkeydirectory(dns_zone_t *zone) {
8355 REQUIRE(DNS_ZONE_VALID(zone));
8357 return (zone->keydirectory);
8360 unsigned int
8361 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
8362 dns_zone_t *zone;
8363 unsigned int count = 0;
8365 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
8367 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
8368 switch (state) {
8369 case DNS_ZONESTATE_XFERRUNNING:
8370 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
8371 zone != NULL;
8372 zone = ISC_LIST_NEXT(zone, statelink))
8373 count++;
8374 break;
8375 case DNS_ZONESTATE_XFERDEFERRED:
8376 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
8377 zone != NULL;
8378 zone = ISC_LIST_NEXT(zone, statelink))
8379 count++;
8380 break;
8381 case DNS_ZONESTATE_SOAQUERY:
8382 for (zone = ISC_LIST_HEAD(zmgr->zones);
8383 zone != NULL;
8384 zone = ISC_LIST_NEXT(zone, link))
8385 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
8386 count++;
8387 break;
8388 case DNS_ZONESTATE_ANY:
8389 for (zone = ISC_LIST_HEAD(zmgr->zones);
8390 zone != NULL;
8391 zone = ISC_LIST_NEXT(zone, link)) {
8392 dns_view_t *view = zone->view;
8393 if (view != NULL && strcmp(view->name, "_bind") == 0)
8394 continue;
8395 count++;
8397 break;
8398 default:
8399 INSIST(0);
8402 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
8404 return (count);
8407 isc_result_t
8408 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
8409 isc_boolean_t ok = ISC_TRUE;
8410 isc_boolean_t fail = ISC_FALSE;
8411 char namebuf[DNS_NAME_FORMATSIZE];
8412 char namebuf2[DNS_NAME_FORMATSIZE];
8413 char typebuf[DNS_RDATATYPE_FORMATSIZE];
8414 int level = ISC_LOG_WARNING;
8415 dns_name_t bad;
8417 REQUIRE(DNS_ZONE_VALID(zone));
8419 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
8420 return (ISC_R_SUCCESS);
8422 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
8423 level = ISC_LOG_ERROR;
8424 fail = ISC_TRUE;
8427 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
8428 if (!ok) {
8429 dns_name_format(name, namebuf, sizeof(namebuf));
8430 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
8431 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
8432 dns_result_totext(DNS_R_BADOWNERNAME));
8433 if (fail)
8434 return (DNS_R_BADOWNERNAME);
8437 dns_name_init(&bad, NULL);
8438 ok = dns_rdata_checknames(rdata, name, &bad);
8439 if (!ok) {
8440 dns_name_format(name, namebuf, sizeof(namebuf));
8441 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
8442 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
8443 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
8444 namebuf2, dns_result_totext(DNS_R_BADNAME));
8445 if (fail)
8446 return (DNS_R_BADNAME);
8449 return (ISC_R_SUCCESS);
8452 void
8453 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
8454 REQUIRE(DNS_ZONE_VALID(zone));
8455 zone->checkmx = checkmx;
8458 void
8459 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
8460 REQUIRE(DNS_ZONE_VALID(zone));
8461 zone->checksrv = checksrv;
8464 void
8465 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
8466 REQUIRE(DNS_ZONE_VALID(zone));
8467 zone->checkns = checkns;
8470 void
8471 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
8472 REQUIRE(DNS_ZONE_VALID(zone));
8474 LOCK_ZONE(zone);
8475 zone->isself = isself;
8476 zone->isselfarg = arg;
8477 UNLOCK_ZONE(zone);
8480 void
8481 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
8482 REQUIRE(DNS_ZONE_VALID(zone));
8484 LOCK_ZONE(zone);
8485 zone->notifydelay = delay;
8486 UNLOCK_ZONE(zone);
8489 isc_uint32_t
8490 dns_zone_getnotifydelay(dns_zone_t *zone) {
8491 REQUIRE(DNS_ZONE_VALID(zone));
8493 return (zone->notifydelay);