Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / zone.c
blob10d4a0253a53fc6f5aa34dd72664ef8eff99f59b
1 /*
2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.333.2.33 2004/06/04 02:41:39 marka Exp $ */
20 #include <config.h>
22 #include <isc/file.h>
23 #include <isc/mutex.h>
24 #include <isc/print.h>
25 #include <isc/random.h>
26 #include <isc/ratelimiter.h>
27 #include <isc/refcount.h>
28 #include <isc/serial.h>
29 #include <isc/string.h>
30 #include <isc/taskpool.h>
31 #include <isc/timer.h>
32 #include <isc/util.h>
34 #include <dns/acl.h>
35 #include <dns/adb.h>
36 #include <dns/callbacks.h>
37 #include <dns/db.h>
38 #include <dns/events.h>
39 #include <dns/journal.h>
40 #include <dns/log.h>
41 #include <dns/master.h>
42 #include <dns/masterdump.h>
43 #include <dns/message.h>
44 #include <dns/name.h>
45 #include <dns/peer.h>
46 #include <dns/rcode.h>
47 #include <dns/rdataclass.h>
48 #include <dns/rdatalist.h>
49 #include <dns/rdataset.h>
50 #include <dns/rdatastruct.h>
51 #include <dns/request.h>
52 #include <dns/resolver.h>
53 #include <dns/result.h>
54 #include <dns/stats.h>
55 #include <dns/ssu.h>
56 #include <dns/tsig.h>
57 #include <dns/xfrin.h>
58 #include <dns/zone.h>
60 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
61 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
63 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
64 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
66 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
67 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
69 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
70 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
72 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
73 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
75 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
76 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
78 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
79 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
82 * Ensure 'a' is at least 'min' but not more than 'max'.
84 #define RANGE(a, min, max) \
85 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
88 * Default values.
90 #define DNS_DEFAULT_IDLEIN 3600 /* 1 hour */
91 #define DNS_DEFAULT_IDLEOUT 3600 /* 1 hour */
92 #define MAX_XFER_TIME (2*3600) /* Documented default is 2 hours */
94 #ifndef DNS_MAX_EXPIRE
95 #define DNS_MAX_EXPIRE 14515200 /* 24 weeks */
96 #endif
98 #ifndef DNS_DUMP_DELAY
99 #define DNS_DUMP_DELAY 900 /* 15 minutes */
100 #endif
102 typedef struct dns_notify dns_notify_t;
103 typedef struct dns_stub dns_stub_t;
104 typedef struct dns_load dns_load_t;
105 typedef struct dns_forward dns_forward_t;
106 typedef struct dns_io dns_io_t;
107 typedef ISC_LIST(dns_io_t) dns_iolist_t;
109 #define DNS_ZONE_CHECKLOCK
110 #ifdef DNS_ZONE_CHECKLOCK
111 #define LOCK_ZONE(z) \
112 do { LOCK(&(z)->lock); \
113 INSIST((z)->locked == ISC_FALSE); \
114 (z)->locked = ISC_TRUE; \
115 } while (0)
116 #define UNLOCK_ZONE(z) \
117 do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
118 #define LOCKED_ZONE(z) ((z)->locked)
119 #else
120 #define LOCK_ZONE(z) LOCK(&(z)->lock)
121 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
122 #define LOCKED_ZONE(z) ISC_TRUE
123 #endif
125 struct dns_zone {
126 /* Unlocked */
127 unsigned int magic;
128 isc_mutex_t lock;
129 #ifdef DNS_ZONE_CHECKLOCK
130 isc_boolean_t locked;
131 #endif
132 isc_mem_t *mctx;
133 isc_refcount_t erefs;
135 /* Locked */
136 dns_db_t *db;
137 dns_zonemgr_t *zmgr;
138 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
139 isc_timer_t *timer;
140 unsigned int irefs;
141 dns_name_t origin;
142 char *masterfile;
143 char *journal;
144 isc_int32_t journalsize;
145 dns_rdataclass_t rdclass;
146 dns_zonetype_t type;
147 unsigned int flags;
148 unsigned int options;
149 unsigned int db_argc;
150 char **db_argv;
151 isc_time_t expiretime;
152 isc_time_t refreshtime;
153 isc_time_t dumptime;
154 isc_time_t loadtime;
155 isc_uint32_t serial;
156 isc_uint32_t refresh;
157 isc_uint32_t retry;
158 isc_uint32_t expire;
159 isc_uint32_t minimum;
161 isc_uint32_t maxrefresh;
162 isc_uint32_t minrefresh;
163 isc_uint32_t maxretry;
164 isc_uint32_t minretry;
166 isc_sockaddr_t *masters;
167 dns_name_t **masterkeynames;
168 unsigned int masterscnt;
169 unsigned int curmaster;
170 unsigned int refreshcnt;
171 isc_sockaddr_t masteraddr;
172 dns_notifytype_t notifytype;
173 isc_sockaddr_t *notify;
174 unsigned int notifycnt;
175 isc_sockaddr_t notifyfrom;
176 isc_task_t *task;
177 isc_sockaddr_t notifysrc4;
178 isc_sockaddr_t notifysrc6;
179 isc_sockaddr_t xfrsource4;
180 isc_sockaddr_t xfrsource6;
181 dns_xfrin_ctx_t *xfr; /* task locked */
182 /* Access Control Lists */
183 dns_acl_t *update_acl;
184 dns_acl_t *forward_acl;
185 dns_acl_t *notify_acl;
186 dns_acl_t *query_acl;
187 dns_acl_t *xfr_acl;
188 dns_severity_t check_names;
189 ISC_LIST(dns_notify_t) notifies;
190 dns_request_t *request;
191 dns_loadctx_t *lctx;
192 dns_io_t *readio;
193 isc_uint32_t maxxfrin;
194 isc_uint32_t maxxfrout;
195 isc_uint32_t idlein;
196 isc_uint32_t idleout;
197 isc_boolean_t diff_on_reload;
198 isc_event_t ctlevent;
199 dns_ssutable_t *ssutable;
200 isc_uint32_t sigvalidityinterval;
201 dns_view_t *view;
203 * Zones in certain states such as "waiting for zone transfer"
204 * or "zone transfer in progress" are kept on per-state linked lists
205 * in the zone manager using the 'statelink' field. The 'statelist'
206 * field points at the list the zone is currently on. It the zone
207 * is not on any such list, statelist is NULL.
209 ISC_LINK(dns_zone_t) statelink;
210 dns_zonelist_t *statelist;
212 * Optional per-zone statistics counters (NULL if not present).
214 isc_uint64_t *counters;
217 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
218 #define DNS_ZONE_SETFLAG(z,f) do { \
219 INSIST(LOCKED_ZONE(z)); \
220 (z)->flags |= (f); \
221 } while (0)
222 #define DNS_ZONE_CLRFLAG(z,f) do { \
223 INSIST(LOCKED_ZONE(z)); \
224 (z)->flags &= ~(f); \
225 } while (0)
226 /* XXX MPA these may need to go back into zone.h */
227 #define DNS_ZONEFLG_REFRESH 0x00000001U /* refresh check in progress */
228 #define DNS_ZONEFLG_NEEDDUMP 0x00000002U /* zone need consolidation */
229 #define DNS_ZONEFLG_USEVC 0x00000004U /* use tcp for refresh query */
230 #define DNS_ZONEFLG_DUMPING 0x00000008U /* a dump is in progress */
231 #define DNS_ZONEFLG_HASINCLUDE 0x00000010U /* $INCLUDE in zone file */
232 #define DNS_ZONEFLG_LOADED 0x00000020U /* database has loaded */
233 #define DNS_ZONEFLG_EXITING 0x00000040U /* zone is being destroyed */
234 #define DNS_ZONEFLG_EXPIRED 0x00000080U /* zone has expired */
235 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U /* refresh check needed */
236 #define DNS_ZONEFLG_UPTODATE 0x00000200U /* zone contents are
237 * uptodate */
238 #define DNS_ZONEFLG_NEEDNOTIFY 0x00000400U /* need to send out notify
239 * messages */
240 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U /* generate a journal diff on
241 * reload */
242 #define DNS_ZONEFLG_NOMASTERS 0x00001000U /* an attempt to refresh a
243 * zone with no masters
244 * occured */
245 #define DNS_ZONEFLG_LOADING 0x00002000U /* load from disk in progress*/
246 #define DNS_ZONEFLG_HAVETIMERS 0x00004000U /* timer values have been set
247 * from SOA (if not set, we
248 * are still using
249 * default timer values) */
250 #define DNS_ZONEFLG_FORCEXFER 0x00008000U /* Force a zone xfer */
251 #define DNS_ZONEFLG_NOREFRESH 0x00010000U
252 #define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
253 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
254 #define DNS_ZONEFLG_SHUTDOWN 0x00080000U
255 #define DNS_ZONEFLAG_NOIXFR 0x00100000U /* IXFR failed, force AXFR */
256 #define DNS_ZONEFLG_FLUSH 0x00200000U
258 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
260 /* Flags for zone_load() */
261 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
263 struct dns_zonemgr {
264 unsigned int magic;
265 isc_mem_t * mctx;
266 int refs; /* Locked by rwlock */
267 isc_taskmgr_t * taskmgr;
268 isc_timermgr_t * timermgr;
269 isc_socketmgr_t * socketmgr;
270 isc_taskpool_t * zonetasks;
271 isc_task_t * task;
272 isc_ratelimiter_t * rl;
273 isc_rwlock_t rwlock;
274 isc_mutex_t iolock;
276 /* Locked by rwlock. */
277 dns_zonelist_t zones;
278 dns_zonelist_t waiting_for_xfrin;
279 dns_zonelist_t xfrin_in_progress;
281 /* Configuration data. */
282 isc_uint32_t transfersin;
283 isc_uint32_t transfersperns;
284 unsigned int serialqueryrate;
286 /* Locked by iolock */
287 isc_uint32_t iolimit;
288 isc_uint32_t ioactive;
289 dns_iolist_t high;
290 dns_iolist_t low;
294 * Hold notify state.
296 struct dns_notify {
297 unsigned int magic;
298 unsigned int flags;
299 isc_mem_t *mctx;
300 dns_zone_t *zone;
301 dns_adbfind_t *find;
302 dns_request_t *request;
303 dns_name_t ns;
304 isc_sockaddr_t dst;
305 unsigned int attempt;
306 ISC_LINK(dns_notify_t) link;
309 #define DNS_NOTIFY_NOSOA 0x0001U
312 * dns_stub holds state while performing a 'stub' transfer.
313 * 'db' is the zone's 'db' or a new one if this is the initial
314 * transfer.
317 struct dns_stub {
318 unsigned int magic;
319 isc_mem_t *mctx;
320 dns_zone_t *zone;
321 dns_db_t *db;
322 dns_dbversion_t *version;
326 * Hold load state.
328 struct dns_load {
329 unsigned int magic;
330 isc_mem_t *mctx;
331 dns_zone_t *zone;
332 dns_db_t *db;
333 isc_time_t loadtime;
334 dns_rdatacallbacks_t callbacks;
338 * Hold forward state.
340 struct dns_forward {
341 unsigned int magic;
342 isc_mem_t *mctx;
343 dns_zone_t *zone;
344 isc_buffer_t *msgbuf;
345 dns_request_t *request;
346 isc_uint32_t which;
347 isc_sockaddr_t addr;
348 dns_updatecallback_t callback;
349 void *callback_arg;
353 * Hold IO request state.
355 struct dns_io {
356 unsigned int magic;
357 dns_zonemgr_t *zmgr;
358 isc_boolean_t high;
359 isc_task_t *task;
360 ISC_LINK(dns_io_t) link;
361 isc_event_t *event;
364 static void zone_settimer(dns_zone_t *, isc_time_t *);
365 static void cancel_refresh(dns_zone_t *);
366 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
367 const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
368 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
369 ISC_FORMAT_PRINTF(3, 4);
370 static void queue_xfrin(dns_zone_t *zone);
371 static void zone_unload(dns_zone_t *zone);
372 static void zone_expire(dns_zone_t *zone);
373 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
374 static void zone_idetach(dns_zone_t **zonep);
375 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
376 isc_boolean_t dump);
377 static isc_result_t default_journal(dns_zone_t *zone);
378 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
379 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
380 isc_time_t loadtime, isc_result_t result);
381 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
382 static void zone_shutdown(isc_task_t *, isc_event_t *);
383 static void zone_loaddone(void *arg, isc_result_t result);
384 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
385 isc_time_t loadtime);
387 #if 0
388 /* ondestroy example */
389 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
390 #endif
392 static void refresh_callback(isc_task_t *, isc_event_t *);
393 static void stub_callback(isc_task_t *, isc_event_t *);
394 static void queue_soa_query(dns_zone_t *zone);
395 static void soa_query(isc_task_t *, isc_event_t *);
396 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
397 dns_stub_t *stub);
398 static int message_count(dns_message_t *msg, dns_section_t section,
399 dns_rdatatype_t type);
400 static void notify_cancel(dns_zone_t *zone);
401 static void notify_find_address(dns_notify_t *notify);
402 static void notify_send(dns_notify_t *notify);
403 static isc_result_t notify_createmessage(dns_zone_t *zone,
404 unsigned int flags,
405 dns_message_t **messagep);
406 static void notify_done(isc_task_t *task, isc_event_t *event);
407 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
408 static isc_result_t zone_dump(dns_zone_t *);
409 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
410 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
411 dns_zone_t *zone);
412 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
413 static void zonemgr_free(dns_zonemgr_t *zmgr);
414 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
415 isc_task_t *task, isc_taskaction_t action,
416 void *arg, dns_io_t **iop);
417 static void zonemgr_putio(dns_io_t **iop);
418 static void zonemgr_cancelio(dns_io_t *io);
420 static isc_result_t
421 zone_get_from_db(dns_db_t *db, dns_name_t *origin, unsigned int *nscount,
422 unsigned int *soacount, isc_uint32_t *serial,
423 isc_uint32_t *refresh, isc_uint32_t *retry,
424 isc_uint32_t *expire, isc_uint32_t *minimum);
426 static void zone_freedbargs(dns_zone_t *zone);
427 static void forward_callback(isc_task_t *task, isc_event_t *event);
428 static void zone_saveunique(dns_zone_t *zone, const char *path,
429 const char *templat);
430 static void zone_maintenance(dns_zone_t *zone);
431 static void zone_notify(dns_zone_t *zone);
433 #define ENTER zone_debuglog(zone, me, 1, "enter")
435 static const unsigned int dbargc_default = 1;
436 static const char *dbargv_default[] = { "rbt" };
438 /***
439 *** Public functions.
440 ***/
442 isc_result_t
443 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
444 isc_result_t result;
445 dns_zone_t *zone;
447 REQUIRE(zonep != NULL && *zonep == NULL);
448 REQUIRE(mctx != NULL);
450 zone = isc_mem_get(mctx, sizeof *zone);
451 if (zone == NULL)
452 return (ISC_R_NOMEMORY);
454 result = isc_mutex_init(&zone->lock);
455 if (result != ISC_R_SUCCESS) {
456 isc_mem_put(mctx, zone, sizeof *zone);
457 UNEXPECTED_ERROR(__FILE__, __LINE__,
458 "isc_mutex_init() failed: %s",
459 isc_result_totext(result));
460 return (ISC_R_UNEXPECTED);
463 /* XXX MPA check that all elements are initialised */
464 zone->mctx = NULL;
465 #ifdef DNS_ZONE_CHECKLOCK
466 zone->locked = ISC_FALSE;
467 #endif
468 isc_mem_attach(mctx, &zone->mctx);
469 zone->db = NULL;
470 zone->zmgr = NULL;
471 ISC_LINK_INIT(zone, link);
472 isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
473 zone->irefs = 0;
474 dns_name_init(&zone->origin, NULL);
475 zone->masterfile = NULL;
476 zone->journalsize = -1;
477 zone->journal = NULL;
478 zone->rdclass = dns_rdataclass_none;
479 zone->type = dns_zone_none;
480 zone->flags = 0;
481 zone->options = 0;
482 zone->db_argc = 0;
483 zone->db_argv = NULL;
484 isc_time_settoepoch(&zone->expiretime);
485 isc_time_settoepoch(&zone->refreshtime);
486 isc_time_settoepoch(&zone->dumptime);
487 isc_time_settoepoch(&zone->loadtime);
488 zone->serial = 0;
489 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
490 zone->retry = DNS_ZONE_DEFAULTRETRY;
491 zone->expire = 0;
492 zone->minimum = 0;
493 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
494 zone->minrefresh = DNS_ZONE_MINREFRESH;
495 zone->maxretry = DNS_ZONE_MAXRETRY;
496 zone->minretry = DNS_ZONE_MINRETRY;
497 zone->masters = NULL;
498 zone->masterkeynames = NULL;
499 zone->masterscnt = 0;
500 zone->curmaster = 0;
501 zone->refreshcnt = 0;
502 zone->notify = NULL;
503 zone->notifytype = dns_notifytype_yes;
504 zone->notifycnt = 0;
505 zone->task = NULL;
506 zone->update_acl = NULL;
507 zone->forward_acl = NULL;
508 zone->notify_acl = NULL;
509 zone->query_acl = NULL;
510 zone->xfr_acl = NULL;
511 zone->check_names = dns_severity_ignore;
512 zone->request = NULL;
513 zone->lctx = NULL;
514 zone->readio = NULL;
515 zone->timer = NULL;
516 zone->idlein = DNS_DEFAULT_IDLEIN;
517 zone->idleout = DNS_DEFAULT_IDLEOUT;
518 ISC_LIST_INIT(zone->notifies);
519 isc_sockaddr_any(&zone->notifysrc4);
520 isc_sockaddr_any6(&zone->notifysrc6);
521 isc_sockaddr_any(&zone->xfrsource4);
522 isc_sockaddr_any6(&zone->xfrsource6);
523 zone->xfr = NULL;
524 zone->maxxfrin = MAX_XFER_TIME;
525 zone->maxxfrout = MAX_XFER_TIME;
526 zone->diff_on_reload = ISC_FALSE;
527 zone->ssutable = NULL;
528 zone->sigvalidityinterval = 30 * 24 * 3600;
529 zone->view = NULL;
530 ISC_LINK_INIT(zone, statelink);
531 zone->statelist = NULL;
532 zone->counters = NULL;
534 zone->magic = ZONE_MAGIC;
536 /* Must be after magic is set. */
537 result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
538 if (result != ISC_R_SUCCESS)
539 goto free_mutex;
541 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
542 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
543 NULL, NULL);
544 *zonep = zone;
545 return (ISC_R_SUCCESS);
547 free_mutex:
548 DESTROYLOCK(&zone->lock);
549 return (ISC_R_NOMEMORY);
553 * Free a zone. Because we require that there be no more
554 * outstanding events or references, no locking is necessary.
556 static void
557 zone_free(dns_zone_t *zone) {
558 isc_mem_t *mctx = NULL;
560 REQUIRE(DNS_ZONE_VALID(zone));
561 REQUIRE(isc_refcount_current(&zone->erefs) == 0);
562 REQUIRE(zone->irefs == 0);
563 REQUIRE(!LOCKED_ZONE(zone));
564 REQUIRE(zone->timer == NULL);
567 * Managed objects. Order is important.
569 if (zone->request != NULL)
570 dns_request_destroy(&zone->request); /* XXXMPA */
571 INSIST(zone->readio == NULL);
572 INSIST(zone->statelist == NULL);
574 if (zone->task != NULL)
575 isc_task_detach(&zone->task);
576 if (zone->zmgr)
577 dns_zonemgr_releasezone(zone->zmgr, zone);
579 /* Unmanaged objects */
580 if (zone->masterfile != NULL)
581 isc_mem_free(zone->mctx, zone->masterfile);
582 zone->masterfile = NULL;
583 zone->journalsize = -1;
584 if (zone->journal != NULL)
585 isc_mem_free(zone->mctx, zone->journal);
586 zone->journal = NULL;
587 if (zone->counters != NULL)
588 dns_stats_freecounters(zone->mctx, &zone->counters);
589 if (zone->db != NULL)
590 dns_db_detach(&zone->db);
591 zone_freedbargs(zone);
592 dns_zone_setmasterswithkeys(zone, NULL, NULL, 0);
593 dns_zone_setalsonotify(zone, NULL, 0);
594 zone->check_names = dns_severity_ignore;
595 if (zone->update_acl != NULL)
596 dns_acl_detach(&zone->update_acl);
597 if (zone->forward_acl != NULL)
598 dns_acl_detach(&zone->forward_acl);
599 if (zone->notify_acl != NULL)
600 dns_acl_detach(&zone->notify_acl);
601 if (zone->query_acl != NULL)
602 dns_acl_detach(&zone->query_acl);
603 if (zone->xfr_acl != NULL)
604 dns_acl_detach(&zone->xfr_acl);
605 if (dns_name_dynamic(&zone->origin))
606 dns_name_free(&zone->origin, zone->mctx);
607 if (zone->ssutable != NULL)
608 dns_ssutable_detach(&zone->ssutable);
610 /* last stuff */
611 DESTROYLOCK(&zone->lock);
612 isc_refcount_destroy(&zone->erefs);
613 zone->magic = 0;
614 mctx = zone->mctx;
615 isc_mem_put(mctx, zone, sizeof *zone);
616 isc_mem_detach(&mctx);
620 * Single shot.
622 void
623 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
625 REQUIRE(DNS_ZONE_VALID(zone));
626 REQUIRE(rdclass != dns_rdataclass_none);
629 * Test and set.
631 LOCK_ZONE(zone);
632 REQUIRE(zone->rdclass == dns_rdataclass_none ||
633 zone->rdclass == rdclass);
634 zone->rdclass = rdclass;
635 UNLOCK_ZONE(zone);
638 dns_rdataclass_t
639 dns_zone_getclass(dns_zone_t *zone){
640 REQUIRE(DNS_ZONE_VALID(zone));
642 return (zone->rdclass);
645 void
646 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
647 REQUIRE(DNS_ZONE_VALID(zone));
649 LOCK_ZONE(zone);
650 zone->notifytype = notifytype;
651 UNLOCK_ZONE(zone);
655 * Single shot.
657 void
658 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
660 REQUIRE(DNS_ZONE_VALID(zone));
661 REQUIRE(type != dns_zone_none);
664 * Test and set.
666 LOCK_ZONE(zone);
667 REQUIRE(zone->type == dns_zone_none || zone->type == type);
668 zone->type = type;
669 UNLOCK_ZONE(zone);
672 static void
673 zone_freedbargs(dns_zone_t *zone) {
674 unsigned int i;
676 /* Free the old database argument list. */
677 if (zone->db_argv != NULL) {
678 for (i = 0; i < zone->db_argc; i++)
679 isc_mem_free(zone->mctx, zone->db_argv[i]);
680 isc_mem_put(zone->mctx, zone->db_argv,
681 zone->db_argc * sizeof *zone->db_argv);
683 zone->db_argc = 0;
684 zone->db_argv = NULL;
687 isc_result_t
688 dns_zone_setdbtype(dns_zone_t *zone,
689 unsigned int dbargc, const char * const *dbargv) {
690 isc_result_t result = ISC_R_SUCCESS;
691 char **new = NULL;
692 unsigned int i;
694 REQUIRE(DNS_ZONE_VALID(zone));
695 REQUIRE(dbargc >= 1);
696 REQUIRE(dbargv != NULL);
698 LOCK_ZONE(zone);
700 /* Set up a new database argument list. */
701 new = isc_mem_get(zone->mctx, dbargc * sizeof *new);
702 if (new == NULL)
703 goto nomem;
704 for (i = 0; i < dbargc; i++)
705 new[i] = NULL;
706 for (i = 0; i < dbargc; i++) {
707 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
708 if (new[i] == NULL)
709 goto nomem;
712 /* Free the old list. */
713 zone_freedbargs(zone);
715 zone->db_argc = dbargc;
716 zone->db_argv = new;
717 result = ISC_R_SUCCESS;
718 goto unlock;
720 nomem:
721 if (new != NULL) {
722 for (i = 0; i < dbargc; i++) {
723 if (zone->db_argv[i] != NULL)
724 isc_mem_free(zone->mctx, new[i]);
725 isc_mem_put(zone->mctx, new,
726 dbargc * sizeof *new);
729 result = ISC_R_NOMEMORY;
731 unlock:
732 UNLOCK_ZONE(zone);
733 return (result);
736 void
737 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
738 REQUIRE(DNS_ZONE_VALID(zone));
740 LOCK_ZONE(zone);
741 if (zone->view != NULL)
742 dns_view_weakdetach(&zone->view);
743 dns_view_weakattach(view, &zone->view);
744 UNLOCK_ZONE(zone);
748 dns_view_t *
749 dns_zone_getview(dns_zone_t *zone) {
750 REQUIRE(DNS_ZONE_VALID(zone));
752 return (zone->view);
756 isc_result_t
757 dns_zone_setorigin(dns_zone_t *zone, dns_name_t *origin) {
758 isc_result_t result;
760 REQUIRE(DNS_ZONE_VALID(zone));
761 REQUIRE(origin != NULL);
763 LOCK_ZONE(zone);
764 if (dns_name_dynamic(&zone->origin)) {
765 dns_name_free(&zone->origin, zone->mctx);
766 dns_name_init(&zone->origin, NULL);
768 result = dns_name_dup(origin, zone->mctx, &zone->origin);
769 UNLOCK_ZONE(zone);
770 return (result);
774 static isc_result_t
775 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
776 char *copy;
778 if (value != NULL) {
779 copy = isc_mem_strdup(zone->mctx, value);
780 if (copy == NULL)
781 return (ISC_R_NOMEMORY);
782 } else {
783 copy = NULL;
786 if (*field != NULL)
787 isc_mem_free(zone->mctx, *field);
789 *field = copy;
790 return (ISC_R_SUCCESS);
793 isc_result_t
794 dns_zone_setfile(dns_zone_t *zone, const char *file) {
795 isc_result_t result = ISC_R_SUCCESS;
797 REQUIRE(DNS_ZONE_VALID(zone));
799 LOCK_ZONE(zone);
800 result = dns_zone_setstring(zone, &zone->masterfile, file);
801 if (result == ISC_R_SUCCESS)
802 result = default_journal(zone);
803 UNLOCK_ZONE(zone);
805 return (result);
808 const char *
809 dns_zone_getfile(dns_zone_t *zone) {
810 REQUIRE(DNS_ZONE_VALID(zone));
812 return (zone->masterfile);
815 static isc_result_t
816 default_journal(dns_zone_t *zone) {
817 isc_result_t result;
818 char *journal;
820 REQUIRE(DNS_ZONE_VALID(zone));
821 REQUIRE(LOCKED_ZONE(zone));
823 if (zone->masterfile != NULL) {
824 /* Calculate string length including '\0'. */
825 int len = strlen(zone->masterfile) + sizeof ".jnl";
826 journal = isc_mem_allocate(zone->mctx, len);
827 if (journal == NULL)
828 return (ISC_R_NOMEMORY);
829 strcpy(journal, zone->masterfile);
830 strcat(journal, ".jnl");
831 } else {
832 journal = NULL;
834 result = dns_zone_setstring(zone, &zone->journal, journal);
835 if (journal != NULL)
836 isc_mem_free(zone->mctx, journal);
837 return (result);
840 isc_result_t
841 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
842 isc_result_t result = ISC_R_SUCCESS;
844 REQUIRE(DNS_ZONE_VALID(zone));
846 LOCK_ZONE(zone);
847 result = dns_zone_setstring(zone, &zone->journal, journal);
848 UNLOCK_ZONE(zone);
850 return (result);
853 char *
854 dns_zone_getjournal(dns_zone_t *zone) {
855 REQUIRE(DNS_ZONE_VALID(zone));
857 return (zone->journal);
861 * Return true iff the zone is "dynamic", in the sense that the zone's
862 * master file (if any) is written by the server, rather than being
863 * updated manually and read by the server.
865 * This is true for slave zones, stub zones, and zones that allow
866 * dynamic updates either by having an update policy ("ssutable")
867 * or an "allow-update" ACL with a value other than exactly "{ none; }".
869 static isc_boolean_t
870 zone_isdynamic(dns_zone_t *zone) {
871 REQUIRE(DNS_ZONE_VALID(zone));
873 return (ISC_TF(zone->type == dns_zone_slave ||
874 zone->type == dns_zone_stub ||
875 zone->ssutable != NULL ||
876 (zone->update_acl != NULL &&
877 ! (zone->update_acl->length == 1 &&
878 zone->update_acl->elements[0].negative == ISC_TRUE
880 zone->update_acl->elements[0].type ==
881 dns_aclelementtype_any))));
885 static isc_result_t
886 zone_load(dns_zone_t *zone, unsigned int flags) {
887 isc_result_t result;
888 isc_time_t now;
889 isc_time_t loadtime, filetime;
890 dns_db_t *db = NULL;
892 REQUIRE(DNS_ZONE_VALID(zone));
894 LOCK_ZONE(zone);
895 isc_time_now(&now);
897 INSIST(zone->type != dns_zone_none);
899 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
900 result = ISC_R_SUCCESS;
901 goto cleanup;
904 if (zone->db != NULL && zone->masterfile == NULL) {
906 * The zone has no master file configured, but it already
907 * has a database. It could be the built-in
908 * version.bind. CH zone, a zone with a persistent
909 * database being reloaded, or maybe a zone that
910 * used to have a master file but whose configuration
911 * was changed so that it no longer has one. Do nothing.
913 result = ISC_R_SUCCESS;
914 goto cleanup;
917 if (zone->db != NULL && zone_isdynamic(zone)) {
919 * This is a slave, stub, or dynamically updated
920 * zone being reloaded. Do nothing - the database
921 * we already have is guaranteed to be up-to-date.
923 if (zone->type == dns_zone_master)
924 result = DNS_R_DYNAMIC;
925 else
926 result = ISC_R_SUCCESS;
927 goto cleanup;
931 * Don't do the load if the file that stores the zone is older
932 * than the last time the zone was loaded. If the zone has not
933 * been loaded yet, zone->loadtime will be the epoch.
935 if (zone->masterfile != NULL && ! isc_time_isepoch(&zone->loadtime)) {
937 * The file is already loaded. If we are just doing a
938 * "rndc reconfig", we are done.
940 if ((flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
941 result = ISC_R_SUCCESS;
942 goto cleanup;
944 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE)) {
945 result = isc_file_getmodtime(zone->masterfile,
946 &filetime);
947 if (result == ISC_R_SUCCESS &&
948 isc_time_compare(&filetime, &zone->loadtime) < 0) {
949 dns_zone_log(zone, ISC_LOG_DEBUG(1),
950 "skipping load: master file older "
951 "than last load");
952 result = ISC_R_SUCCESS;
953 goto cleanup;
958 INSIST(zone->db_argc >= 1);
960 if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
961 (strcmp(zone->db_argv[0], "rbt") == 0 ||
962 strcmp(zone->db_argv[0], "rbt64") == 0)) {
963 if (zone->masterfile == NULL ||
964 !isc_file_exists(zone->masterfile)) {
965 if (zone->masterfile != NULL)
966 dns_zone_log(zone, ISC_LOG_DEBUG(1),
967 "no master file");
968 zone->refreshtime = now;
969 if (zone->task != NULL)
970 zone_settimer(zone, &now);
971 result = ISC_R_SUCCESS;
972 goto cleanup;
976 dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
979 * Store the current time before the zone is loaded, so that if the
980 * file changes between the time of the load and the time that
981 * zone->loadtime is set, then the file will still be reloaded
982 * the next time dns_zone_load is called.
984 result = isc_time_now(&loadtime);
985 if (result != ISC_R_SUCCESS)
986 goto cleanup;
988 result = dns_db_create(zone->mctx, zone->db_argv[0],
989 &zone->origin, (zone->type == dns_zone_stub) ?
990 dns_dbtype_stub : dns_dbtype_zone,
991 zone->rdclass,
992 zone->db_argc - 1, zone->db_argv + 1,
993 &db);
995 if (result != ISC_R_SUCCESS) {
996 dns_zone_log(zone, ISC_LOG_ERROR,
997 "loading zone: creating database: %s",
998 isc_result_totext(result));
999 goto cleanup;
1001 dns_db_settask(db, zone->task);
1003 if (! dns_db_ispersistent(db)) {
1004 if (zone->masterfile != NULL) {
1005 result = zone_startload(db, zone, loadtime);
1006 } else {
1007 result = DNS_R_NOMASTERFILE;
1008 if (zone->type == dns_zone_master) {
1009 dns_zone_log(zone, ISC_LOG_ERROR,
1010 "loading zone: "
1011 "no master file configured");
1012 goto cleanup;
1014 dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1015 "no master file configured: continuing");
1019 if (result == DNS_R_CONTINUE) {
1020 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1021 result = ISC_R_SUCCESS;
1022 goto cleanup;
1025 result = zone_postload(zone, db, loadtime, result);
1027 cleanup:
1028 UNLOCK_ZONE(zone);
1029 if (db != NULL)
1030 dns_db_detach(&db);
1031 return (result);
1034 isc_result_t
1035 dns_zone_load(dns_zone_t *zone) {
1036 return (zone_load(zone, 0));
1039 isc_result_t
1040 dns_zone_loadnew(dns_zone_t *zone) {
1041 return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1044 static void
1045 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1046 dns_load_t *load = event->ev_arg;
1047 isc_result_t result = ISC_R_SUCCESS;
1048 unsigned int options;
1050 REQUIRE(DNS_LOAD_VALID(load));
1052 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1053 result = ISC_R_CANCELED;
1054 isc_event_free(&event);
1055 if (result == ISC_R_CANCELED)
1056 goto fail;
1058 options = DNS_MASTER_ZONE;
1059 if (load->zone->type == dns_zone_slave)
1060 options |= DNS_MASTER_SLAVE;
1061 result = dns_master_loadfileinc(load->zone->masterfile,
1062 dns_db_origin(load->db),
1063 dns_db_origin(load->db),
1064 load->zone->rdclass,
1065 options,
1066 &load->callbacks, task,
1067 zone_loaddone, load,
1068 &load->zone->lctx, load->zone->mctx);
1069 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1070 result != DNS_R_SEENINCLUDE)
1071 goto fail;
1072 return;
1074 fail:
1075 zone_loaddone(load, result);
1078 static isc_result_t
1079 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1080 dns_load_t *load;
1081 isc_result_t result;
1082 isc_result_t tresult;
1083 unsigned int options;
1085 options = DNS_MASTER_ZONE;
1086 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1087 options |= DNS_MASTER_MANYERRORS;
1088 if (zone->type == dns_zone_slave)
1089 options |= DNS_MASTER_SLAVE;
1090 if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1091 load = isc_mem_get(zone->mctx, sizeof(*load));
1092 if (load == NULL)
1093 return (ISC_R_NOMEMORY);
1095 load->mctx = NULL;
1096 load->zone = NULL;
1097 load->db = NULL;
1098 load->loadtime = loadtime;
1099 load->magic = LOAD_MAGIC;
1101 isc_mem_attach(zone->mctx, &load->mctx);
1102 zone_iattach(zone, &load->zone);
1103 dns_db_attach(db, &load->db);
1104 dns_rdatacallbacks_init(&load->callbacks);
1105 result = dns_db_beginload(db, &load->callbacks.add,
1106 &load->callbacks.add_private);
1107 if (result != ISC_R_SUCCESS)
1108 goto cleanup;
1109 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1110 zone_gotreadhandle, load,
1111 &zone->readio);
1112 if (result != ISC_R_SUCCESS) {
1113 tresult = dns_db_endload(load->db,
1114 &load->callbacks.add_private);
1115 if (result == ISC_R_SUCCESS)
1116 result = tresult;
1117 goto cleanup;
1118 } else
1119 result = DNS_R_CONTINUE;
1120 } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
1121 dns_rdatacallbacks_t callbacks;
1123 dns_rdatacallbacks_init(&callbacks);
1124 result = dns_db_beginload(db, &callbacks.add,
1125 &callbacks.add_private);
1126 if (result != ISC_R_SUCCESS)
1127 return (result);
1128 result = dns_master_loadfile(zone->masterfile, &zone->origin,
1129 &zone->origin, zone->rdclass,
1130 options, &callbacks, zone->mctx);
1131 tresult = dns_db_endload(db, &callbacks.add_private);
1132 if (result == ISC_R_SUCCESS)
1133 result = tresult;
1134 } else {
1135 result = dns_db_load(db, zone->masterfile);
1138 return (result);
1140 cleanup:
1141 load->magic = 0;
1142 dns_db_detach(&load->db);
1143 zone_idetach(&load->zone);
1144 isc_mem_detach(&load->mctx);
1145 isc_mem_put(zone->mctx, load, sizeof(*load));
1146 return (result);
1149 static isc_result_t
1150 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
1151 isc_result_t result)
1153 unsigned int soacount = 0;
1154 unsigned int nscount = 0;
1155 isc_uint32_t serial, refresh, retry, expire, minimum;
1156 isc_time_t now;
1157 isc_boolean_t needdump = ISC_FALSE;
1159 isc_time_now(&now);
1162 * Initiate zone transfer? We may need a error code that
1163 * indicates that the "permanent" form does not exist.
1164 * XXX better error feedback to log.
1166 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
1167 if (zone->type == dns_zone_slave ||
1168 zone->type == dns_zone_stub) {
1169 if (result == ISC_R_FILENOTFOUND)
1170 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1171 "no master file");
1172 else if (result != DNS_R_NOMASTERFILE)
1173 dns_zone_log(zone, ISC_LOG_ERROR,
1174 "loading master file %s: %s",
1175 zone->masterfile,
1176 dns_result_totext(result));
1177 } else
1178 dns_zone_log(zone, ISC_LOG_ERROR,
1179 "loading master file %s: %s",
1180 zone->masterfile,
1181 dns_result_totext(result));
1182 goto cleanup;
1185 dns_zone_log(zone, ISC_LOG_DEBUG(2),
1186 "number of nodes in database: %u",
1187 dns_db_nodecount(db));
1188 zone->loadtime = loadtime;
1190 dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
1192 if (result == DNS_R_SEENINCLUDE)
1193 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1194 else
1195 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1197 * Apply update log, if any.
1199 if (zone->journal != NULL &&
1200 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE)) {
1201 result = dns_journal_rollforward(zone->mctx, db,
1202 zone->journal);
1203 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
1204 result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
1205 result != ISC_R_RANGE) {
1206 dns_zone_log(zone, ISC_LOG_ERROR,
1207 "journal rollforward failed: %s",
1208 dns_result_totext(result));
1209 goto cleanup;
1211 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
1212 dns_zone_log(zone, ISC_LOG_ERROR,
1213 "journal rollforward failed: "
1214 "journal out of sync with zone");
1215 goto cleanup;
1217 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1218 "journal rollforward completed "
1219 "successfully: %s",
1220 dns_result_totext(result));
1221 if (result == ISC_R_SUCCESS)
1222 needdump = ISC_TRUE;
1226 * Obtain ns and soa counts for top of zone.
1228 nscount = 0;
1229 soacount = 0;
1230 INSIST(db != NULL);
1231 result = zone_get_from_db(db, &zone->origin, &nscount,
1232 &soacount, &serial, &refresh, &retry,
1233 &expire, &minimum);
1234 if (result != ISC_R_SUCCESS) {
1235 dns_zone_log(zone, ISC_LOG_ERROR,
1236 "could not find NS and/or SOA records");
1240 * Master / Slave / Stub zones require both NS and SOA records at
1241 * the top of the zone.
1244 switch (zone->type) {
1245 case dns_zone_master:
1246 case dns_zone_slave:
1247 case dns_zone_stub:
1248 if (soacount != 1) {
1249 dns_zone_log(zone, ISC_LOG_ERROR,
1250 "has %d SOA records", soacount);
1251 result = DNS_R_BADZONE;
1253 if (nscount == 0) {
1254 dns_zone_log(zone, ISC_LOG_ERROR,
1255 "has no NS records");
1256 result = DNS_R_BADZONE;
1258 if (result != ISC_R_SUCCESS)
1259 goto cleanup;
1260 if (zone->db != NULL) {
1261 if (!isc_serial_ge(serial, zone->serial)) {
1262 dns_zone_log(zone, ISC_LOG_ERROR,
1263 "zone serial has gone backwards");
1266 zone->serial = serial;
1267 zone->refresh = RANGE(refresh,
1268 zone->minrefresh, zone->maxrefresh);
1269 zone->retry = RANGE(retry,
1270 zone->minretry, zone->maxretry);
1271 zone->expire = RANGE(expire, zone->refresh + zone->retry,
1272 DNS_MAX_EXPIRE);
1273 zone->minimum = minimum;
1274 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
1276 if (zone->type == dns_zone_slave ||
1277 zone->type == dns_zone_stub) {
1278 isc_time_t t;
1279 isc_interval_t i;
1280 unsigned int delay;
1282 result = isc_file_getmodtime(zone->journal, &t);
1283 if (result != ISC_R_SUCCESS)
1284 result = isc_file_getmodtime(zone->masterfile,
1285 &t);
1287 if (result == ISC_R_SUCCESS) {
1288 isc_interval_set(&i, zone->expire, 0);
1289 isc_time_add(&t, &i, &zone->expiretime);
1290 } else {
1291 isc_interval_set(&i, zone->retry, 0);
1292 isc_time_add(&now, &i, &zone->expiretime);
1294 delay = isc_random_jitter(zone->retry,
1295 (zone->retry * 3) / 4);
1296 isc_interval_set(&i, delay, 0);
1297 isc_time_add(&now, &i, &zone->refreshtime);
1298 if (isc_time_compare(&zone->refreshtime,
1299 &zone->expiretime) >= 0)
1300 zone->refreshtime = now;
1302 break;
1303 default:
1304 UNEXPECTED_ERROR(__FILE__, __LINE__,
1305 "unexpected zone type %d", zone->type);
1306 result = ISC_R_UNEXPECTED;
1307 goto cleanup;
1311 #if 0
1312 /* destroy notification example. */
1314 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
1315 DNS_EVENT_DBDESTROYED,
1316 dns_zonemgr_dbdestroyed,
1317 zone,
1318 sizeof(isc_event_t));
1319 dns_db_ondestroy(db, zone->task, &e);
1321 #endif
1323 if (zone->db != NULL) {
1324 result = zone_replacedb(zone, db, ISC_FALSE);
1325 if (result != ISC_R_SUCCESS)
1326 goto cleanup;
1327 } else {
1328 dns_db_attach(db, &zone->db);
1329 DNS_ZONE_SETFLAG(zone,
1330 DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
1332 result = ISC_R_SUCCESS;
1333 if (needdump)
1334 zone_needdump(zone, DNS_DUMP_DELAY);
1335 if (zone->task != NULL)
1336 zone_settimer(zone, &now);
1337 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u", zone->serial);
1338 return (result);
1340 cleanup:
1341 if (zone->type == dns_zone_slave ||
1342 zone->type == dns_zone_stub) {
1343 if (zone->journal != NULL)
1344 zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
1345 if (zone->masterfile != NULL)
1346 zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
1348 /* Mark the zone for immediate refresh. */
1349 zone->refreshtime = now;
1350 if (zone->task != NULL)
1351 zone_settimer(zone, &now);
1352 result = ISC_R_SUCCESS;
1354 return (result);
1357 static isc_boolean_t
1358 exit_check(dns_zone_t *zone) {
1360 REQUIRE(LOCKED_ZONE(zone));
1362 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
1363 zone->irefs == 0)
1366 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
1368 INSIST(isc_refcount_current(&zone->erefs) == 0);
1369 return (ISC_TRUE);
1371 return (ISC_FALSE);
1374 static isc_result_t
1375 zone_count_ns_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1376 unsigned int *nscount)
1378 isc_result_t result;
1379 unsigned int count;
1380 dns_rdataset_t rdataset;
1382 REQUIRE(nscount != NULL);
1384 dns_rdataset_init(&rdataset);
1385 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
1386 dns_rdatatype_none, 0, &rdataset, NULL);
1387 if (result == ISC_R_NOTFOUND) {
1388 *nscount = 0;
1389 result = ISC_R_SUCCESS;
1390 goto invalidate_rdataset;
1392 else if (result != ISC_R_SUCCESS)
1393 goto invalidate_rdataset;
1395 count = 0;
1396 result = dns_rdataset_first(&rdataset);
1397 while (result == ISC_R_SUCCESS) {
1398 count++;
1399 result = dns_rdataset_next(&rdataset);
1401 dns_rdataset_disassociate(&rdataset);
1403 *nscount = count;
1404 result = ISC_R_SUCCESS;
1406 invalidate_rdataset:
1407 dns_rdataset_invalidate(&rdataset);
1409 return (result);
1412 static isc_result_t
1413 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1414 unsigned int *soacount,
1415 isc_uint32_t *serial, isc_uint32_t *refresh,
1416 isc_uint32_t *retry, isc_uint32_t *expire,
1417 isc_uint32_t *minimum)
1419 isc_result_t result;
1420 unsigned int count;
1421 dns_rdataset_t rdataset;
1422 dns_rdata_t rdata = DNS_RDATA_INIT;
1423 dns_rdata_soa_t soa;
1425 dns_rdataset_init(&rdataset);
1426 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
1427 dns_rdatatype_none, 0, &rdataset, NULL);
1428 if (result != ISC_R_SUCCESS)
1429 goto invalidate_rdataset;
1431 count = 0;
1432 result = dns_rdataset_first(&rdataset);
1433 while (result == ISC_R_SUCCESS) {
1434 dns_rdata_init(&rdata);
1435 dns_rdataset_current(&rdataset, &rdata);
1436 count++;
1437 if (count == 1)
1438 dns_rdata_tostruct(&rdata, &soa, NULL);
1440 result = dns_rdataset_next(&rdataset);
1441 dns_rdata_reset(&rdata);
1443 dns_rdataset_disassociate(&rdataset);
1445 if (soacount != NULL)
1446 *soacount = count;
1448 if (count > 0) {
1449 if (serial != NULL)
1450 *serial = soa.serial;
1451 if (refresh != NULL)
1452 *refresh = soa.refresh;
1453 if (retry != NULL)
1454 *retry = soa.retry;
1455 if (expire != NULL)
1456 *expire = soa.expire;
1457 if (minimum != NULL)
1458 *minimum = soa.minimum;
1461 result = ISC_R_SUCCESS;
1463 invalidate_rdataset:
1464 dns_rdataset_invalidate(&rdataset);
1466 return (result);
1470 * zone must be locked.
1472 static isc_result_t
1473 zone_get_from_db(dns_db_t *db, dns_name_t *origin, unsigned int *nscount,
1474 unsigned int *soacount, isc_uint32_t *serial,
1475 isc_uint32_t *refresh, isc_uint32_t *retry,
1476 isc_uint32_t *expire, isc_uint32_t *minimum)
1478 dns_dbversion_t *version;
1479 isc_result_t result;
1480 isc_result_t answer = ISC_R_SUCCESS;
1481 dns_dbnode_t *node;
1483 REQUIRE(db != NULL);
1484 REQUIRE(origin != NULL);
1486 version = NULL;
1487 dns_db_currentversion(db, &version);
1489 node = NULL;
1490 result = dns_db_findnode(db, origin, ISC_FALSE, &node);
1491 if (result != ISC_R_SUCCESS) {
1492 answer = result;
1493 goto closeversion;
1496 if (nscount != NULL) {
1497 result = zone_count_ns_rr(db, node, version, nscount);
1498 if (result != ISC_R_SUCCESS)
1499 answer = result;
1502 if (soacount != NULL || serial != NULL || refresh != NULL
1503 || retry != NULL || expire != NULL || minimum != NULL) {
1504 result = zone_load_soa_rr(db, node, version, soacount,
1505 serial, refresh, retry, expire,
1506 minimum);
1507 if (result != ISC_R_SUCCESS)
1508 answer = result;
1511 dns_db_detachnode(db, &node);
1512 closeversion:
1513 dns_db_closeversion(db, &version, ISC_FALSE);
1515 return (answer);
1518 void
1519 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
1520 REQUIRE(DNS_ZONE_VALID(source));
1521 REQUIRE(target != NULL && *target == NULL);
1522 isc_refcount_increment(&source->erefs, NULL);
1523 *target = source;
1526 void
1527 dns_zone_detach(dns_zone_t **zonep) {
1528 dns_zone_t *zone;
1529 unsigned int refs;
1530 isc_boolean_t free_now = ISC_FALSE;
1532 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1534 zone = *zonep;
1536 isc_refcount_decrement(&zone->erefs, &refs);
1538 if (refs == 0) {
1539 LOCK_ZONE(zone);
1541 * We just detached the last external reference.
1543 if (zone->task != NULL) {
1545 * This zone is being managed. Post
1546 * its control event and let it clean
1547 * up synchronously in the context of
1548 * its task.
1550 isc_event_t *ev = &zone->ctlevent;
1551 isc_task_send(zone->task, &ev);
1552 } else {
1554 * This zone is not being managed; it has
1555 * no task and can have no outstanding
1556 * events. Free it immediately.
1559 * Unmanaged zones should not have non-null views;
1560 * we have no way of detaching from the view here
1561 * without causing deadlock because this code is called
1562 * with the view already locked.
1564 INSIST(zone->view == NULL);
1565 free_now = ISC_TRUE;
1567 UNLOCK_ZONE(zone);
1569 *zonep = NULL;
1570 if (free_now)
1571 zone_free(zone);
1574 void
1575 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
1576 REQUIRE(DNS_ZONE_VALID(source));
1577 REQUIRE(target != NULL && *target == NULL);
1578 LOCK_ZONE(source);
1579 zone_iattach(source, target);
1580 UNLOCK_ZONE(source);
1583 static void
1584 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
1587 * 'source' locked by caller.
1589 REQUIRE(LOCKED_ZONE(source));
1590 REQUIRE(DNS_ZONE_VALID(source));
1591 REQUIRE(target != NULL && *target == NULL);
1592 INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
1593 source->irefs++;
1594 INSIST(source->irefs != 0);
1595 *target = source;
1598 static void
1599 zone_idetach(dns_zone_t **zonep) {
1600 dns_zone_t *zone;
1603 * 'zone' locked by caller.
1605 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1606 zone = *zonep;
1607 REQUIRE(LOCKED_ZONE(*zonep));
1608 *zonep = NULL;
1610 INSIST(zone->irefs > 0);
1611 zone->irefs--;
1612 INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
1615 void
1616 dns_zone_idetach(dns_zone_t **zonep) {
1617 dns_zone_t *zone;
1618 isc_boolean_t free_needed;
1620 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1621 zone = *zonep;
1622 *zonep = NULL;
1624 LOCK_ZONE(zone);
1625 INSIST(zone->irefs > 0);
1626 zone->irefs--;
1627 free_needed = exit_check(zone);
1628 UNLOCK_ZONE(zone);
1629 if (free_needed)
1630 zone_free(zone);
1633 isc_mem_t *
1634 dns_zone_getmctx(dns_zone_t *zone) {
1635 REQUIRE(DNS_ZONE_VALID(zone));
1637 return (zone->mctx);
1640 dns_zonemgr_t *
1641 dns_zone_getmgr(dns_zone_t *zone) {
1642 REQUIRE(DNS_ZONE_VALID(zone));
1644 return (zone->zmgr);
1647 void
1648 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
1649 REQUIRE(DNS_ZONE_VALID(zone));
1651 LOCK_ZONE(zone);
1652 if (value)
1653 DNS_ZONE_SETFLAG(zone, flags);
1654 else
1655 DNS_ZONE_CLRFLAG(zone, flags);
1656 UNLOCK_ZONE(zone);
1659 void
1660 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
1662 REQUIRE(DNS_ZONE_VALID(zone));
1664 LOCK_ZONE(zone);
1665 if (value)
1666 zone->options |= option;
1667 else
1668 zone->options &= ~option;
1669 UNLOCK_ZONE(zone);
1672 unsigned int
1673 dns_zone_getoptions(dns_zone_t *zone) {
1675 REQUIRE(DNS_ZONE_VALID(zone));
1677 return (zone->options);
1680 isc_result_t
1681 dns_zone_setxfrsource4(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
1682 REQUIRE(DNS_ZONE_VALID(zone));
1684 LOCK_ZONE(zone);
1685 zone->xfrsource4 = *xfrsource;
1686 UNLOCK_ZONE(zone);
1688 return (ISC_R_SUCCESS);
1691 isc_sockaddr_t *
1692 dns_zone_getxfrsource4(dns_zone_t *zone) {
1693 REQUIRE(DNS_ZONE_VALID(zone));
1694 return (&zone->xfrsource4);
1697 isc_result_t
1698 dns_zone_setxfrsource6(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
1699 REQUIRE(DNS_ZONE_VALID(zone));
1701 LOCK_ZONE(zone);
1702 zone->xfrsource6 = *xfrsource;
1703 UNLOCK_ZONE(zone);
1705 return (ISC_R_SUCCESS);
1708 isc_sockaddr_t *
1709 dns_zone_getxfrsource6(dns_zone_t *zone) {
1710 REQUIRE(DNS_ZONE_VALID(zone));
1711 return (&zone->xfrsource6);
1714 isc_result_t
1715 dns_zone_setnotifysrc4(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
1716 REQUIRE(DNS_ZONE_VALID(zone));
1718 LOCK_ZONE(zone);
1719 zone->notifysrc4 = *notifysrc;
1720 UNLOCK_ZONE(zone);
1722 return (ISC_R_SUCCESS);
1725 isc_sockaddr_t *
1726 dns_zone_getnotifysrc4(dns_zone_t *zone) {
1727 REQUIRE(DNS_ZONE_VALID(zone));
1728 return (&zone->notifysrc4);
1731 isc_result_t
1732 dns_zone_setnotifysrc6(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
1733 REQUIRE(DNS_ZONE_VALID(zone));
1735 LOCK_ZONE(zone);
1736 zone->notifysrc6 = *notifysrc;
1737 UNLOCK_ZONE(zone);
1739 return (ISC_R_SUCCESS);
1742 isc_sockaddr_t *
1743 dns_zone_getnotifysrc6(dns_zone_t *zone) {
1744 REQUIRE(DNS_ZONE_VALID(zone));
1745 return (&zone->notifysrc6);
1748 isc_result_t
1749 dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *notify,
1750 isc_uint32_t count)
1752 isc_sockaddr_t *new;
1754 REQUIRE(DNS_ZONE_VALID(zone));
1755 REQUIRE(count == 0 || notify != NULL);
1757 LOCK_ZONE(zone);
1758 if (zone->notify != NULL) {
1759 isc_mem_put(zone->mctx, zone->notify,
1760 zone->notifycnt * sizeof *new);
1761 zone->notify = NULL;
1762 zone->notifycnt = 0;
1764 if (count != 0) {
1765 new = isc_mem_get(zone->mctx, count * sizeof *new);
1766 if (new == NULL) {
1767 UNLOCK_ZONE(zone);
1768 return (ISC_R_NOMEMORY);
1770 memcpy(new, notify, count * sizeof *new);
1771 zone->notify = new;
1772 zone->notifycnt = count;
1774 UNLOCK_ZONE(zone);
1775 return (ISC_R_SUCCESS);
1778 isc_result_t
1779 dns_zone_setmasters(dns_zone_t *zone, isc_sockaddr_t *masters,
1780 isc_uint32_t count)
1782 isc_result_t result;
1784 result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
1785 return (result);
1788 isc_result_t
1789 dns_zone_setmasterswithkeys(dns_zone_t *zone, isc_sockaddr_t *masters,
1790 dns_name_t **keynames, isc_uint32_t count)
1792 isc_sockaddr_t *new;
1793 isc_result_t result = ISC_R_SUCCESS;
1794 dns_name_t **newname;
1795 unsigned int i;
1797 REQUIRE(DNS_ZONE_VALID(zone));
1798 REQUIRE(count == 0 || masters != NULL);
1799 if (keynames != NULL) {
1800 REQUIRE(count != 0);
1803 LOCK_ZONE(zone);
1804 if (zone->masters != NULL) {
1805 isc_mem_put(zone->mctx, zone->masters,
1806 zone->masterscnt * sizeof *new);
1807 zone->masters = NULL;
1809 if (zone->masterkeynames != NULL) {
1810 for (i = 0; i < zone->masterscnt; i++) {
1811 if (zone->masterkeynames[i] != NULL) {
1812 dns_name_free(zone->masterkeynames[i],
1813 zone->mctx);
1814 isc_mem_put(zone->mctx,
1815 zone->masterkeynames[i],
1816 sizeof(dns_name_t));
1817 zone->masterkeynames[i] = NULL;
1820 isc_mem_put(zone->mctx, zone->masterkeynames,
1821 zone->masterscnt * sizeof(dns_name_t *));
1822 zone->masterkeynames = NULL;
1824 zone->masterscnt = 0;
1826 * If count == 0, don't allocate any space for masters or keynames
1827 * so internally, those pointers are NULL if count == 0
1829 if (count == 0)
1830 goto unlock;
1833 * masters must countain count elements!
1835 new = isc_mem_get(zone->mctx,
1836 count * sizeof(isc_sockaddr_t));
1837 if (new == NULL) {
1838 result = ISC_R_NOMEMORY;
1839 goto unlock;
1841 memcpy(new, masters, count * sizeof *new);
1842 zone->masters = new;
1843 zone->masterscnt = count;
1844 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
1847 * if keynames is non-NULL, it must contain count elements!
1849 if (keynames != NULL) {
1850 newname = isc_mem_get(zone->mctx,
1851 count * sizeof(dns_name_t *));
1852 if (newname == NULL) {
1853 result = ISC_R_NOMEMORY;
1854 isc_mem_put(zone->mctx, zone->masters,
1855 count * sizeof *new);
1856 goto unlock;
1858 for (i = 0; i < count; i++)
1859 newname[i] = NULL;
1860 for (i = 0; i < count; i++) {
1861 if (keynames[i] != NULL) {
1862 newname[i] = isc_mem_get(zone->mctx,
1863 sizeof(dns_name_t));
1864 if (newname[i] == NULL)
1865 goto allocfail;
1866 dns_name_init(newname[i], NULL);
1867 result = dns_name_dup(keynames[i], zone->mctx,
1868 newname[i]);
1869 if (result != ISC_R_SUCCESS) {
1870 allocfail:
1871 for (i = 0; i < count; i++)
1872 if (newname[i] != NULL)
1873 dns_name_free(
1874 newname[i],
1875 zone->mctx);
1876 isc_mem_put(zone->mctx, zone->masters,
1877 count * sizeof *new);
1878 isc_mem_put(zone->mctx, newname,
1879 count * sizeof *newname);
1880 goto unlock;
1884 zone->masterkeynames = newname;
1886 unlock:
1887 UNLOCK_ZONE(zone);
1888 return (result);
1891 isc_result_t
1892 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
1893 isc_result_t result = ISC_R_SUCCESS;
1895 REQUIRE(DNS_ZONE_VALID(zone));
1897 LOCK_ZONE(zone);
1898 if (zone->db == NULL)
1899 result = DNS_R_NOTLOADED;
1900 else
1901 dns_db_attach(zone->db, dpb);
1902 UNLOCK_ZONE(zone);
1904 return (result);
1908 * Co-ordinates the starting of routine jobs.
1911 void
1912 dns_zone_maintenance(dns_zone_t *zone) {
1913 const char me[] = "dns_zone_maintenance";
1914 isc_time_t now;
1916 REQUIRE(DNS_ZONE_VALID(zone));
1917 ENTER;
1919 LOCK_ZONE(zone);
1920 isc_time_now(&now);
1921 zone_settimer(zone, &now);
1922 UNLOCK_ZONE(zone);
1925 static inline isc_boolean_t
1926 was_dumping(dns_zone_t *zone) {
1927 isc_boolean_t dumping;
1929 REQUIRE(LOCKED_ZONE(zone));
1931 dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
1932 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
1933 if (!dumping) {
1934 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
1935 isc_time_settoepoch(&zone->dumptime);
1937 return (dumping);
1940 static void
1941 zone_maintenance(dns_zone_t *zone) {
1942 const char me[] = "zone_maintenance";
1943 isc_time_t now;
1944 isc_result_t result;
1945 isc_boolean_t dumping;
1947 REQUIRE(DNS_ZONE_VALID(zone));
1948 ENTER;
1951 * Configuring the view of this zone may have
1952 * failed, for example because the config file
1953 * had a syntax error. In that case, the view
1954 * adb or resolver, and we had better not try
1955 * to do maintenance on it.
1957 if (zone->view == NULL || zone->view->adb == NULL)
1958 return;
1960 isc_time_now(&now);
1963 * Expire check.
1965 switch (zone->type) {
1966 case dns_zone_slave:
1967 case dns_zone_stub:
1968 LOCK_ZONE(zone);
1969 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
1970 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1971 zone_expire(zone);
1972 zone->refreshtime = now;
1974 UNLOCK_ZONE(zone);
1975 break;
1976 default:
1977 break;
1981 * Up to date check.
1983 switch (zone->type) {
1984 case dns_zone_slave:
1985 case dns_zone_stub:
1986 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
1987 isc_time_compare(&now, &zone->refreshtime) >= 0)
1988 dns_zone_refresh(zone);
1989 break;
1990 default:
1991 break;
1995 * Do we need to consolidate the backing store?
1997 switch (zone->type) {
1998 case dns_zone_master:
1999 case dns_zone_slave:
2000 LOCK_ZONE(zone);
2001 if (zone->masterfile != NULL &&
2002 isc_time_compare(&now, &zone->dumptime) >= 0 &&
2003 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2004 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
2005 dumping = was_dumping(zone);
2006 } else
2007 dumping = ISC_TRUE;
2008 UNLOCK_ZONE(zone);
2009 if (!dumping) {
2010 result = zone_dump(zone);
2011 if (result != ISC_R_SUCCESS)
2012 dns_zone_log(zone, ISC_LOG_WARNING,
2013 "dump failed: %s",
2014 dns_result_totext(result));
2016 break;
2017 default:
2018 break;
2022 * Do we need to send out notify messages?
2024 switch (zone->type) {
2025 case dns_zone_master:
2026 case dns_zone_slave:
2027 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
2028 zone_notify(zone);
2029 break;
2030 default:
2031 break;
2033 zone_settimer(zone, &now);
2036 void
2037 dns_zone_markdirty(dns_zone_t *zone) {
2039 LOCK_ZONE(zone);
2040 zone_needdump(zone, DNS_DUMP_DELAY);
2041 UNLOCK_ZONE(zone);
2044 void
2045 dns_zone_expire(dns_zone_t *zone) {
2046 REQUIRE(DNS_ZONE_VALID(zone));
2048 LOCK_ZONE(zone);
2049 zone_expire(zone);
2050 UNLOCK_ZONE(zone);
2053 static void
2054 zone_expire(dns_zone_t *zone) {
2056 * 'zone' locked by caller.
2059 REQUIRE(LOCKED_ZONE(zone));
2061 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
2063 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
2064 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
2065 zone->retry = DNS_ZONE_DEFAULTRETRY;
2066 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
2067 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2068 zone_unload(zone);
2071 void
2072 dns_zone_refresh(dns_zone_t *zone) {
2073 isc_interval_t i;
2074 isc_uint32_t oldflags;
2076 REQUIRE(DNS_ZONE_VALID(zone));
2078 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
2079 return;
2082 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
2083 * in progress at a time.
2086 LOCK_ZONE(zone);
2087 oldflags = zone->flags;
2088 if (zone->masterscnt == 0) {
2089 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
2090 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
2091 dns_zone_log(zone, ISC_LOG_ERROR,
2092 "cannot refresh: no masters");
2093 goto unlock;
2095 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
2096 if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
2097 goto unlock;
2100 * Set the next refresh time as if refresh check has failed.
2101 * Setting this to the retry time will do that. XXXMLG
2102 * If we are successful it will be reset using zone->refresh.
2104 isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
2106 isc_time_nowplusinterval(&zone->refreshtime, &i);
2109 * When lacking user-specified timer values from the SOA,
2110 * do exponential backoff of the retry time up to a
2111 * maximum of six hours.
2113 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
2114 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
2116 zone->curmaster = 0;
2117 zone->refreshcnt = 0;
2118 /* initiate soa query */
2119 queue_soa_query(zone);
2120 unlock:
2121 UNLOCK_ZONE(zone);
2124 isc_result_t
2125 dns_zone_flush(dns_zone_t *zone) {
2126 isc_result_t result = ISC_R_ALREADYRUNNING;
2127 isc_boolean_t dumping;
2129 REQUIRE(DNS_ZONE_VALID(zone));
2131 LOCK_ZONE(zone);
2132 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
2133 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
2134 zone->masterfile != NULL)
2135 dumping = was_dumping(zone);
2136 else
2137 dumping = ISC_TRUE;
2138 UNLOCK_ZONE(zone);
2139 if (!dumping)
2140 result = zone_dump(zone);
2141 return (result);
2144 isc_result_t
2145 dns_zone_dump(dns_zone_t *zone) {
2146 isc_result_t result = ISC_R_ALREADYRUNNING;
2147 isc_boolean_t dumping;
2149 REQUIRE(DNS_ZONE_VALID(zone));
2151 LOCK_ZONE(zone);
2152 dumping = was_dumping(zone);
2153 UNLOCK_ZONE(zone);
2154 if (!dumping)
2155 result = zone_dump(zone);
2156 return (result);
2159 static void
2160 zone_needdump(dns_zone_t *zone, unsigned int delay) {
2161 isc_time_t dumptime;
2162 isc_time_t now;
2163 isc_interval_t i;
2166 * 'zone' locked by caller
2169 REQUIRE(DNS_ZONE_VALID(zone));
2170 REQUIRE(LOCKED_ZONE(zone));
2173 * Do we have a place to dump to and are we loaded?
2175 if (zone->masterfile == NULL ||
2176 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
2177 return;
2179 isc_interval_set(&i, delay, 0);
2180 isc_time_now(&now);
2181 isc_time_add(&now, &i, &dumptime);
2183 /* add some noise */
2184 delay = isc_random_jitter(delay, delay/4);
2186 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2187 if (isc_time_isepoch(&zone->dumptime) ||
2188 isc_time_compare(&zone->dumptime, &dumptime) > 0)
2189 zone->dumptime = dumptime;
2190 if (zone->task != NULL)
2191 zone_settimer(zone, &now);
2194 static isc_result_t
2195 zone_dump(dns_zone_t *zone) {
2196 isc_result_t result;
2197 dns_dbversion_t *version = NULL;
2198 isc_boolean_t again;
2199 dns_db_t *db = NULL;
2200 char *masterfile = NULL;
2202 REQUIRE(DNS_ZONE_VALID(zone));
2204 redo:
2205 LOCK_ZONE(zone);
2206 if (zone->db != NULL)
2207 dns_db_attach(zone->db, &db);
2208 if (zone->masterfile != NULL)
2209 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
2210 UNLOCK_ZONE(zone);
2211 if (db == NULL) {
2212 result = DNS_R_NOTLOADED;
2213 goto fail;
2215 if (masterfile == NULL) {
2216 result = DNS_R_NOMASTERFILE;
2217 goto fail;
2219 dns_db_currentversion(db, &version);
2221 result = dns_master_dump(zone->mctx, db, version,
2222 &dns_master_style_default, masterfile);
2224 dns_db_closeversion(db, &version, ISC_FALSE);
2225 fail:
2226 if (db != NULL)
2227 dns_db_detach(&db);
2228 if (masterfile != NULL)
2229 isc_mem_free(zone->mctx, masterfile);
2230 masterfile = NULL;
2232 again = ISC_FALSE;
2233 LOCK_ZONE(zone);
2234 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
2235 if (result != ISC_R_SUCCESS) {
2237 * Try again in a short while.
2239 zone_needdump(zone, DNS_DUMP_DELAY);
2240 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
2241 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
2242 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
2243 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2244 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
2245 isc_time_settoepoch(&zone->dumptime);
2246 again = ISC_TRUE;
2248 UNLOCK_ZONE(zone);
2249 if (again)
2250 goto redo;
2252 return (result);
2255 isc_result_t
2256 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
2257 isc_result_t result;
2258 dns_dbversion_t *version = NULL;
2259 dns_db_t *db = NULL;
2261 REQUIRE(DNS_ZONE_VALID(zone));
2263 LOCK_ZONE(zone);
2264 if (zone->db != NULL)
2265 dns_db_attach(zone->db, &db);
2266 UNLOCK_ZONE(zone);
2267 if (db == NULL)
2268 return (DNS_R_NOTLOADED);
2270 dns_db_currentversion(db, &version);
2271 result = dns_master_dumptostream(zone->mctx, db, version,
2272 &dns_master_style_default, fd);
2273 dns_db_closeversion(db, &version, ISC_FALSE);
2274 dns_db_detach(&db);
2275 return (result);
2278 void
2279 dns_zone_unload(dns_zone_t *zone) {
2280 REQUIRE(DNS_ZONE_VALID(zone));
2282 LOCK_ZONE(zone);
2283 zone_unload(zone);
2284 UNLOCK_ZONE(zone);
2287 static void
2288 notify_cancel(dns_zone_t *zone) {
2289 dns_notify_t *notify;
2292 * 'zone' locked by caller.
2295 REQUIRE(LOCKED_ZONE(zone));
2297 for (notify = ISC_LIST_HEAD(zone->notifies);
2298 notify != NULL;
2299 notify = ISC_LIST_NEXT(notify, link)) {
2300 if (notify->find != NULL)
2301 dns_adb_cancelfind(notify->find);
2302 if (notify->request != NULL)
2303 dns_request_cancel(notify->request);
2307 static void
2308 zone_unload(dns_zone_t *zone) {
2311 * 'zone' locked by caller.
2314 REQUIRE(LOCKED_ZONE(zone));
2316 dns_db_detach(&zone->db);
2317 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
2320 void
2321 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
2322 REQUIRE(DNS_ZONE_VALID(zone));
2323 REQUIRE(val > 0);
2325 zone->minrefresh = val;
2328 void
2329 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
2330 REQUIRE(DNS_ZONE_VALID(zone));
2331 REQUIRE(val > 0);
2333 zone->maxrefresh = val;
2336 void
2337 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
2338 REQUIRE(DNS_ZONE_VALID(zone));
2339 REQUIRE(val > 0);
2341 zone->minretry = val;
2344 void
2345 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
2346 REQUIRE(DNS_ZONE_VALID(zone));
2347 REQUIRE(val > 0);
2349 zone->maxretry = val;
2352 static isc_boolean_t
2353 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
2354 dns_notify_t *notify;
2356 for (notify = ISC_LIST_HEAD(zone->notifies);
2357 notify != NULL;
2358 notify = ISC_LIST_NEXT(notify, link)) {
2359 if (notify->request != NULL)
2360 continue;
2361 if (name != NULL && dns_name_dynamic(&notify->ns) &&
2362 dns_name_equal(name, &notify->ns))
2363 return (ISC_TRUE);
2364 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
2365 return (ISC_TRUE);
2367 return (ISC_FALSE);
2370 static void
2371 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
2372 isc_mem_t *mctx;
2375 * Caller holds zone lock.
2377 REQUIRE(DNS_NOTIFY_VALID(notify));
2379 if (notify->zone != NULL) {
2380 if (!locked)
2381 LOCK_ZONE(notify->zone);
2382 REQUIRE(LOCKED_ZONE(notify->zone));
2383 if (ISC_LINK_LINKED(notify, link))
2384 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
2385 if (!locked)
2386 UNLOCK_ZONE(notify->zone);
2387 if (locked)
2388 zone_idetach(&notify->zone);
2389 else
2390 dns_zone_idetach(&notify->zone);
2392 if (notify->find != NULL)
2393 dns_adb_destroyfind(&notify->find);
2394 if (notify->request != NULL)
2395 dns_request_destroy(&notify->request);
2396 if (dns_name_dynamic(&notify->ns))
2397 dns_name_free(&notify->ns, notify->mctx);
2398 mctx = notify->mctx;
2399 isc_mem_put(notify->mctx, notify, sizeof *notify);
2400 isc_mem_detach(&mctx);
2403 static isc_result_t
2404 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
2405 dns_notify_t *notify;
2407 REQUIRE(notifyp != NULL && *notifyp == NULL);
2409 notify = isc_mem_get(mctx, sizeof *notify);
2410 if (notify == NULL)
2411 return (ISC_R_NOMEMORY);
2413 notify->mctx = NULL;
2414 isc_mem_attach(mctx, &notify->mctx);
2415 notify->flags = flags;
2416 notify->zone = NULL;
2417 notify->find = NULL;
2418 notify->request = NULL;
2419 isc_sockaddr_any(&notify->dst);
2420 dns_name_init(&notify->ns, NULL);
2421 notify->attempt = 0;
2422 ISC_LINK_INIT(notify, link);
2423 notify->magic = NOTIFY_MAGIC;
2424 *notifyp = notify;
2425 return (ISC_R_SUCCESS);
2429 * XXXAG should check for DNS_ZONEFLG_EXITING
2431 static void
2432 process_adb_event(isc_task_t *task, isc_event_t *ev) {
2433 dns_notify_t *notify;
2434 isc_eventtype_t result;
2436 UNUSED(task);
2438 notify = ev->ev_arg;
2439 REQUIRE(DNS_NOTIFY_VALID(notify));
2440 INSIST(task == notify->zone->task);
2441 result = ev->ev_type;
2442 isc_event_free(&ev);
2443 if (result == DNS_EVENT_ADBMOREADDRESSES) {
2444 dns_adb_destroyfind(&notify->find);
2445 notify_find_address(notify);
2446 return;
2448 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
2449 LOCK_ZONE(notify->zone);
2450 notify_send(notify);
2451 UNLOCK_ZONE(notify->zone);
2453 notify_destroy(notify, ISC_FALSE);
2456 static void
2457 notify_find_address(dns_notify_t *notify) {
2458 isc_result_t result;
2459 unsigned int options;
2461 REQUIRE(DNS_NOTIFY_VALID(notify));
2462 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
2463 DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
2465 if (notify->zone->view->adb == NULL)
2466 goto destroy;
2468 result = dns_adb_createfind(notify->zone->view->adb,
2469 notify->zone->task,
2470 process_adb_event, notify,
2471 &notify->ns, dns_rootname,
2472 options, 0, NULL,
2473 notify->zone->view->dstport,
2474 &notify->find);
2476 /* Something failed? */
2477 if (result != ISC_R_SUCCESS)
2478 goto destroy;
2480 /* More addresses pending? */
2481 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
2482 return;
2484 /* We have as many addresses as we can get. */
2485 LOCK_ZONE(notify->zone);
2486 notify_send(notify);
2487 UNLOCK_ZONE(notify->zone);
2489 destroy:
2490 notify_destroy(notify, ISC_FALSE);
2494 static isc_result_t
2495 notify_send_queue(dns_notify_t *notify) {
2496 isc_event_t *e;
2497 isc_result_t result;
2499 e = isc_event_allocate(notify->mctx, NULL,
2500 DNS_EVENT_NOTIFYSENDTOADDR,
2501 notify_send_toaddr,
2502 notify, sizeof(isc_event_t));
2503 if (e == NULL)
2504 return (ISC_R_NOMEMORY);
2505 e->ev_arg = notify;
2506 e->ev_sender = NULL;
2507 result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
2508 notify->zone->task, &e);
2509 if (result != ISC_R_SUCCESS)
2510 isc_event_free(&e);
2511 return (result);
2514 static void
2515 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
2516 dns_notify_t *notify;
2517 isc_result_t result;
2518 dns_message_t *message = NULL;
2519 isc_netaddr_t dstip;
2520 dns_tsigkey_t *key = NULL;
2521 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2522 isc_sockaddr_t src;
2523 int timeout;
2525 notify = event->ev_arg;
2526 REQUIRE(DNS_NOTIFY_VALID(notify));
2528 UNUSED(task);
2530 LOCK_ZONE(notify->zone);
2532 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
2533 result = ISC_R_CANCELED;
2534 goto cleanup;
2537 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
2538 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
2539 notify->zone->view->requestmgr == NULL ||
2540 notify->zone->db == NULL) {
2541 result = ISC_R_CANCELED;
2542 goto cleanup;
2545 result = notify_createmessage(notify->zone, notify->flags, &message);
2546 if (result != ISC_R_SUCCESS)
2547 goto cleanup;
2549 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
2550 (void)dns_view_getpeertsig(notify->zone->view, &dstip, &key);
2552 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
2553 notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
2554 addrbuf);
2555 switch (isc_sockaddr_pf(&notify->dst)) {
2556 case PF_INET:
2557 src = notify->zone->notifysrc4;
2558 break;
2559 case PF_INET6:
2560 src = notify->zone->notifysrc6;
2561 break;
2562 default:
2563 result = ISC_R_NOTIMPLEMENTED;
2564 goto cleanup_key;
2566 timeout = 15;
2567 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
2568 timeout = 30;
2569 result = dns_request_createvia(notify->zone->view->requestmgr, message,
2570 &src, &notify->dst, 0, key, timeout,
2571 notify->zone->task,
2572 notify_done, notify,
2573 &notify->request);
2574 cleanup_key:
2575 if (key != NULL)
2576 dns_tsigkey_detach(&key);
2577 dns_message_destroy(&message);
2578 cleanup:
2579 UNLOCK_ZONE(notify->zone);
2580 if (result != ISC_R_SUCCESS)
2581 notify_destroy(notify, ISC_FALSE);
2582 isc_event_free(&event);
2585 static void
2586 notify_send(dns_notify_t *notify) {
2587 dns_adbaddrinfo_t *ai;
2588 isc_sockaddr_t dst;
2589 isc_result_t result;
2590 dns_notify_t *new = NULL;
2593 * Zone lock held by caller.
2595 REQUIRE(DNS_NOTIFY_VALID(notify));
2596 REQUIRE(LOCKED_ZONE(notify->zone));
2598 for (ai = ISC_LIST_HEAD(notify->find->list);
2599 ai != NULL;
2600 ai = ISC_LIST_NEXT(ai, publink)) {
2601 dst = ai->sockaddr;
2602 if (notify_isqueued(notify->zone, NULL, &dst))
2603 continue;
2604 new = NULL;
2605 result = notify_create(notify->mctx,
2606 (notify->flags & DNS_NOTIFY_NOSOA),
2607 &new);
2608 if (result != ISC_R_SUCCESS)
2609 goto cleanup;
2610 zone_iattach(notify->zone, &new->zone);
2611 ISC_LIST_APPEND(new->zone->notifies, new, link);
2612 new->dst = dst;
2613 result = notify_send_queue(new);
2614 if (result != ISC_R_SUCCESS)
2615 goto cleanup;
2616 new = NULL;
2619 cleanup:
2620 if (new != NULL)
2621 notify_destroy(new, ISC_TRUE);
2624 void
2625 dns_zone_notify(dns_zone_t *zone) {
2626 isc_time_t now;
2628 REQUIRE(DNS_ZONE_VALID(zone));
2630 LOCK_ZONE(zone);
2631 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
2633 isc_time_now(&now);
2634 zone_settimer(zone, &now);
2635 UNLOCK_ZONE(zone);
2638 static void
2639 zone_notify(dns_zone_t *zone) {
2640 dns_dbnode_t *node = NULL;
2641 dns_dbversion_t *version = NULL;
2642 dns_name_t *origin = NULL;
2643 dns_name_t master;
2644 dns_rdata_ns_t ns;
2645 dns_rdata_soa_t soa;
2646 isc_uint32_t serial;
2647 dns_rdata_t rdata = DNS_RDATA_INIT;
2648 dns_rdataset_t nsrdset;
2649 dns_rdataset_t soardset;
2650 isc_result_t result;
2651 dns_notify_t *notify = NULL;
2652 unsigned int i;
2653 isc_sockaddr_t dst;
2654 isc_boolean_t isqueued;
2655 dns_notifytype_t notifytype;
2656 unsigned int flags = 0;
2657 isc_boolean_t loggednotify = ISC_FALSE;
2659 REQUIRE(DNS_ZONE_VALID(zone));
2661 LOCK_ZONE(zone);
2662 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
2663 notifytype = zone->notifytype;
2664 UNLOCK_ZONE(zone);
2666 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2667 return;
2669 if (notifytype == dns_notifytype_no)
2670 return;
2672 origin = &zone->origin;
2675 * If the zone is dialup we are done as we don't want to send
2676 * the current soa so as to force a refresh query.
2678 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
2679 flags |= DNS_NOTIFY_NOSOA;
2682 * Get SOA RRset.
2684 dns_db_currentversion(zone->db, &version);
2685 result = dns_db_findnode(zone->db, origin, ISC_FALSE, &node);
2686 if (result != ISC_R_SUCCESS)
2687 goto cleanup1;
2689 dns_rdataset_init(&soardset);
2690 result = dns_db_findrdataset(zone->db, node, version,
2691 dns_rdatatype_soa,
2692 dns_rdatatype_none, 0, &soardset, NULL);
2693 if (result != ISC_R_SUCCESS)
2694 goto cleanup2;
2697 * Find serial and master server's name.
2699 dns_name_init(&master, NULL);
2700 result = dns_rdataset_first(&soardset);
2701 if (result != ISC_R_SUCCESS)
2702 goto cleanup3;
2703 dns_rdataset_current(&soardset, &rdata);
2704 result = dns_rdata_tostruct(&rdata, &soa, NULL);
2705 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2706 dns_rdata_reset(&rdata);
2707 result = dns_name_dup(&soa.origin, zone->mctx, &master);
2708 serial = soa.serial;
2709 dns_rdataset_disassociate(&soardset);
2710 if (result != ISC_R_SUCCESS)
2711 goto cleanup3;
2714 * Enqueue notify requests for 'also-notify' servers.
2716 LOCK_ZONE(zone);
2717 for (i = 0; i < zone->notifycnt; i++) {
2718 dst = zone->notify[i];
2719 if (notify_isqueued(zone, NULL, &dst))
2720 continue;
2721 result = notify_create(zone->mctx, flags, &notify);
2722 if (result != ISC_R_SUCCESS)
2723 continue;
2724 zone_iattach(zone, &notify->zone);
2725 notify->dst = dst;
2726 ISC_LIST_APPEND(zone->notifies, notify, link);
2727 result = notify_send_queue(notify);
2728 if (result != ISC_R_SUCCESS)
2729 notify_destroy(notify, ISC_TRUE);
2730 if (!loggednotify) {
2731 notify_log(zone, ISC_LOG_INFO,
2732 "sending notifies (serial %u)",
2733 serial);
2734 loggednotify = ISC_TRUE;
2736 notify = NULL;
2738 UNLOCK_ZONE(zone);
2740 if (notifytype == dns_notifytype_explicit)
2741 goto cleanup3;
2744 * Process NS RRset to generate notifies.
2747 dns_rdataset_init(&nsrdset);
2748 result = dns_db_findrdataset(zone->db, node, version,
2749 dns_rdatatype_ns,
2750 dns_rdatatype_none, 0, &nsrdset, NULL);
2751 if (result != ISC_R_SUCCESS)
2752 goto cleanup3;
2754 result = dns_rdataset_first(&nsrdset);
2755 while (result == ISC_R_SUCCESS) {
2756 dns_rdataset_current(&nsrdset, &rdata);
2757 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2758 dns_rdata_reset(&rdata);
2759 if (result != ISC_R_SUCCESS)
2760 continue;
2762 * don't notify the master server.
2764 if (dns_name_compare(&master, &ns.name) == 0) {
2765 result = dns_rdataset_next(&nsrdset);
2766 continue;
2769 if (!loggednotify) {
2770 notify_log(zone, ISC_LOG_INFO,
2771 "sending notifies (serial %u)",
2772 serial);
2773 loggednotify = ISC_TRUE;
2776 LOCK_ZONE(zone);
2777 isqueued = notify_isqueued(zone, &ns.name, NULL);
2778 UNLOCK_ZONE(zone);
2779 if (isqueued) {
2780 result = dns_rdataset_next(&nsrdset);
2781 continue;
2783 result = notify_create(zone->mctx, flags, &notify);
2784 if (result != ISC_R_SUCCESS)
2785 continue;
2786 dns_zone_iattach(zone, &notify->zone);
2787 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
2788 if (result != ISC_R_SUCCESS) {
2789 LOCK_ZONE(zone);
2790 notify_destroy(notify, ISC_TRUE);
2791 UNLOCK_ZONE(zone);
2792 continue;
2794 LOCK_ZONE(zone);
2795 ISC_LIST_APPEND(zone->notifies, notify, link);
2796 UNLOCK_ZONE(zone);
2797 notify_find_address(notify);
2798 notify = NULL;
2799 result = dns_rdataset_next(&nsrdset);
2801 dns_rdataset_disassociate(&nsrdset);
2803 cleanup3:
2804 if (dns_name_dynamic(&master))
2805 dns_name_free(&master, zone->mctx);
2806 cleanup2:
2807 dns_db_detachnode(zone->db, &node);
2808 cleanup1:
2809 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2812 /***
2813 *** Private
2814 ***/
2816 static inline isc_result_t
2817 save_nsrrset(dns_message_t *message, dns_name_t *name,
2818 dns_db_t *db, dns_dbversion_t *version)
2820 dns_rdataset_t *nsrdataset = NULL;
2821 dns_rdataset_t *rdataset = NULL;
2822 dns_dbnode_t *node = NULL;
2823 dns_rdata_ns_t ns;
2824 isc_result_t result;
2825 dns_rdata_t rdata = DNS_RDATA_INIT;
2828 * Extract NS RRset from message.
2830 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
2831 dns_rdatatype_ns, dns_rdatatype_none,
2832 NULL, &nsrdataset);
2833 if (result != ISC_R_SUCCESS)
2834 goto fail;
2837 * Add NS rdataset.
2839 result = dns_db_findnode(db, name, ISC_TRUE, &node);
2840 if (result != ISC_R_SUCCESS)
2841 goto fail;
2842 result = dns_db_addrdataset(db, node, version, 0,
2843 nsrdataset, 0, NULL);
2844 dns_db_detachnode(db, &node);
2845 if (result != ISC_R_SUCCESS)
2846 goto fail;
2848 * Add glue rdatasets.
2850 for (result = dns_rdataset_first(nsrdataset);
2851 result == ISC_R_SUCCESS;
2852 result = dns_rdataset_next(nsrdataset)) {
2853 dns_rdataset_current(nsrdataset, &rdata);
2854 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2855 dns_rdata_reset(&rdata);
2856 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2857 if (!dns_name_issubdomain(&ns.name, name))
2858 continue;
2859 rdataset = NULL;
2860 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
2861 &ns.name, dns_rdatatype_a6,
2862 dns_rdatatype_none, NULL,
2863 &rdataset);
2864 if (result == ISC_R_SUCCESS) {
2865 result = dns_db_findnode(db, &ns.name,
2866 ISC_TRUE, &node);
2867 if (result != ISC_R_SUCCESS)
2868 goto fail;
2869 result = dns_db_addrdataset(db, node, version, 0,
2870 rdataset, 0, NULL);
2871 dns_db_detachnode(db, &node);
2872 if (result != ISC_R_SUCCESS)
2873 goto fail;
2875 rdataset = NULL;
2876 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
2877 &ns.name, dns_rdatatype_aaaa,
2878 dns_rdatatype_none, NULL,
2879 &rdataset);
2880 if (result == ISC_R_SUCCESS) {
2881 result = dns_db_findnode(db, &ns.name,
2882 ISC_TRUE, &node);
2883 if (result != ISC_R_SUCCESS)
2884 goto fail;
2885 result = dns_db_addrdataset(db, node, version, 0,
2886 rdataset, 0, NULL);
2887 dns_db_detachnode(db, &node);
2888 if (result != ISC_R_SUCCESS)
2889 goto fail;
2891 rdataset = NULL;
2892 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
2893 &ns.name, dns_rdatatype_a,
2894 dns_rdatatype_none, NULL,
2895 &rdataset);
2896 if (result == ISC_R_SUCCESS) {
2897 result = dns_db_findnode(db, &ns.name,
2898 ISC_TRUE, &node);
2899 if (result != ISC_R_SUCCESS)
2900 goto fail;
2901 result = dns_db_addrdataset(db, node, version, 0,
2902 rdataset, 0, NULL);
2903 dns_db_detachnode(db, &node);
2904 if (result != ISC_R_SUCCESS)
2905 goto fail;
2908 if (result != ISC_R_NOMORE)
2909 goto fail;
2911 return (ISC_R_SUCCESS);
2913 fail:
2914 return (result);
2917 static void
2918 stub_callback(isc_task_t *task, isc_event_t *event) {
2919 const char me[] = "stub_callback";
2920 dns_requestevent_t *revent = (dns_requestevent_t *)event;
2921 dns_stub_t *stub = NULL;
2922 dns_message_t *msg = NULL;
2923 dns_zone_t *zone = NULL;
2924 char master[ISC_SOCKADDR_FORMATSIZE];
2925 isc_uint32_t nscnt, cnamecnt;
2926 isc_result_t result;
2927 isc_time_t now;
2928 isc_boolean_t exiting = ISC_FALSE;
2929 isc_interval_t i;
2931 stub = revent->ev_arg;
2932 INSIST(DNS_STUB_VALID(stub));
2934 UNUSED(task);
2936 zone = stub->zone;
2938 ENTER;
2940 isc_time_now(&now);
2942 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
2943 zone_debuglog(zone, me, 1, "exiting");
2944 exiting = ISC_TRUE;
2945 goto next_master;
2948 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
2950 if (revent->result != ISC_R_SUCCESS) {
2951 dns_zone_log(zone, ISC_LOG_INFO,
2952 "could not refresh stub from master %s: %s",
2953 master, dns_result_totext(revent->result));
2954 goto next_master;
2957 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
2958 if (result != ISC_R_SUCCESS)
2959 goto next_master;
2961 result = dns_request_getresponse(revent->request, msg, 0);
2962 if (result != ISC_R_SUCCESS)
2963 goto next_master;
2966 * Unexpected rcode.
2968 if (msg->rcode != dns_rcode_noerror) {
2969 char rcode[128];
2970 isc_buffer_t rb;
2972 isc_buffer_init(&rb, rcode, sizeof(rcode));
2973 dns_rcode_totext(msg->rcode, &rb);
2975 dns_zone_log(zone, ISC_LOG_INFO,
2976 "refreshing stub: "
2977 "unexpected rcode (%.*s) from %s",
2978 (int)rb.used, rcode, master);
2979 goto next_master;
2983 * We need complete messages.
2985 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
2986 if (dns_request_usedtcp(revent->request)) {
2987 dns_zone_log(zone, ISC_LOG_INFO,
2988 "refreshing stub: "
2989 "truncated TCP response from master %s",
2990 master);
2991 goto next_master;
2993 LOCK_ZONE(zone);
2994 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
2995 UNLOCK_ZONE(zone);
2996 goto same_master;
3000 * If non-auth log and next master.
3002 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
3003 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
3004 "non-authoritative answer from master %s",
3005 master);
3006 goto next_master;
3010 * Sanity checks.
3012 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
3013 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
3015 if (cnamecnt != 0) {
3016 dns_zone_log(zone, ISC_LOG_INFO,
3017 "refreshing stub: unexpected CNAME response "
3018 "from master %s", master);
3019 goto next_master;
3022 if (nscnt == 0) {
3023 dns_zone_log(zone, ISC_LOG_INFO,
3024 "refreshing stub: no NS records in response "
3025 "from master %s", master);
3026 goto next_master;
3030 * Save answer.
3032 result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
3033 if (result != ISC_R_SUCCESS) {
3034 dns_zone_log(zone, ISC_LOG_INFO,
3035 "refreshing stub: unable to save NS records "
3036 "from master %s", master);
3037 goto next_master;
3041 * Tidy up.
3043 dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
3044 LOCK_ZONE(zone);
3045 if (zone->db == NULL)
3046 dns_db_attach(stub->db, &zone->db);
3047 UNLOCK_ZONE(zone);
3048 dns_db_detach(&stub->db);
3050 if (zone->masterfile != NULL) {
3051 dns_zone_dump(zone);
3052 (void)isc_time_now(&zone->loadtime);
3055 dns_message_destroy(&msg);
3056 isc_event_free(&event);
3057 LOCK_ZONE(zone);
3058 dns_request_destroy(&zone->request);
3059 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3060 isc_interval_set(&i, isc_random_jitter(zone->refresh,
3061 zone->refresh / 4), 0);
3062 isc_time_add(&now, &i, &zone->refreshtime);
3063 isc_interval_set(&i, zone->expire, 0);
3064 isc_time_add(&now, &i, &zone->expiretime);
3065 zone_settimer(zone, &now);
3066 UNLOCK_ZONE(zone);
3067 goto free_stub;
3069 next_master:
3070 if (stub->version != NULL)
3071 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
3072 if (stub->db != NULL)
3073 dns_db_detach(&stub->db);
3074 if (msg != NULL)
3075 dns_message_destroy(&msg);
3076 isc_event_free(&event);
3077 LOCK_ZONE(zone);
3078 dns_request_destroy(&zone->request);
3079 zone->curmaster++;
3080 zone->refreshcnt = 0;
3081 if (exiting || zone->curmaster >= zone->masterscnt) {
3082 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3084 zone_settimer(zone, &now);
3085 UNLOCK_ZONE(zone);
3086 goto free_stub;
3088 queue_soa_query(zone);
3089 UNLOCK_ZONE(zone);
3090 goto free_stub;
3092 same_master:
3093 if (msg != NULL)
3094 dns_message_destroy(&msg);
3095 isc_event_free(&event);
3096 LOCK_ZONE(zone);
3097 dns_request_destroy(&zone->request);
3098 UNLOCK_ZONE(zone);
3099 ns_query(zone, NULL, stub);
3100 goto done;
3102 free_stub:
3103 stub->magic = 0;
3104 dns_zone_idetach(&stub->zone);
3105 INSIST(stub->db == NULL);
3106 INSIST(stub->version == NULL);
3107 isc_mem_put(stub->mctx, stub, sizeof(*stub));
3109 done:
3110 INSIST(event == NULL);
3111 return;
3115 * An SOA query has finished (successfully or not).
3117 static void
3118 refresh_callback(isc_task_t *task, isc_event_t *event) {
3119 const char me[] = "refresh_callback";
3120 dns_requestevent_t *revent = (dns_requestevent_t *)event;
3121 dns_zone_t *zone;
3122 dns_message_t *msg = NULL;
3123 isc_uint32_t soacnt, cnamecnt, soacount, nscount;
3124 isc_time_t now;
3125 char master[ISC_SOCKADDR_FORMATSIZE];
3126 dns_rdataset_t *rdataset;
3127 dns_rdata_t rdata = DNS_RDATA_INIT;
3128 dns_rdata_soa_t soa;
3129 isc_result_t result;
3130 isc_uint32_t serial;
3131 isc_interval_t i;
3133 zone = revent->ev_arg;
3134 INSIST(DNS_ZONE_VALID(zone));
3136 UNUSED(task);
3138 ENTER;
3141 * if timeout log and next master;
3144 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
3146 isc_time_now(&now);
3148 if (revent->result != ISC_R_SUCCESS) {
3149 dns_zone_log(zone, ISC_LOG_INFO,
3150 "refresh: failure trying master %s: %s",
3151 master, dns_result_totext(revent->result));
3152 if (revent->result == ISC_R_TIMEDOUT &&
3153 !dns_request_usedtcp(revent->request)) {
3154 if (zone->refreshcnt < 3)
3155 goto same_master;
3156 dns_zone_log(zone, ISC_LOG_INFO,
3157 "refresh: retry limit for "
3158 "master %s exceeded",
3159 master);
3161 goto next_master;
3164 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3165 if (result != ISC_R_SUCCESS)
3166 goto next_master;
3167 result = dns_request_getresponse(revent->request, msg, 0);
3168 if (result != ISC_R_SUCCESS) {
3169 dns_zone_log(zone, ISC_LOG_INFO,
3170 "refresh: failure trying master %s: %s",
3171 master, dns_result_totext(result));
3172 goto next_master;
3176 * Unexpected rcode.
3178 if (msg->rcode != dns_rcode_noerror) {
3179 char rcode[128];
3180 isc_buffer_t rb;
3182 isc_buffer_init(&rb, rcode, sizeof(rcode));
3183 dns_rcode_totext(msg->rcode, &rb);
3185 dns_zone_log(zone, ISC_LOG_INFO,
3186 "refresh: unexpected rcode (%.*s) from master %s",
3187 (int)rb.used, rcode, master);
3188 goto next_master;
3192 * If truncated punt to zone transfer which will query again.
3194 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
3195 if (zone->type == dns_zone_slave) {
3196 dns_zone_log(zone, ISC_LOG_INFO,
3197 "refresh: truncated UDP answer, "
3198 "initiating TCP zone xfer "
3199 "for master %s",
3200 master);
3201 goto tcp_transfer;
3202 } else {
3203 INSIST(zone->type == dns_zone_stub);
3204 if (dns_request_usedtcp(revent->request)) {
3205 dns_zone_log(zone, ISC_LOG_INFO,
3206 "refresh: truncated TCP response "
3207 "from master %s",
3208 master);
3209 goto next_master;
3211 LOCK_ZONE(zone);
3212 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
3213 UNLOCK_ZONE(zone);
3214 goto same_master;
3219 * if non-auth log and next master;
3221 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
3222 dns_zone_log(zone, ISC_LOG_INFO,
3223 "refresh: non-authoritative answer from "
3224 "master %s", master);
3225 goto next_master;
3228 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
3229 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
3230 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
3231 soacount = message_count(msg, DNS_SECTION_AUTHORITY,
3232 dns_rdatatype_soa);
3235 * There should not be a CNAME record at top of zone.
3237 if (cnamecnt != 0) {
3238 dns_zone_log(zone, ISC_LOG_INFO,
3239 "refresh: CNAME at top of zone "
3240 "in master %s", master);
3241 goto next_master;
3245 * if referral log and next master;
3247 if (soacnt == 0 && soacount == 0 && nscount != 0) {
3248 dns_zone_log(zone, ISC_LOG_INFO,
3249 "refresh: referral response "
3250 "from master %s", master);
3251 goto next_master;
3255 * if nodata log and next master;
3257 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
3258 dns_zone_log(zone, ISC_LOG_INFO,
3259 "refresh: NODATA response "
3260 "from master %s", master);
3261 goto next_master;
3265 * Only one soa at top of zone.
3267 if (soacnt != 1) {
3268 dns_zone_log(zone, ISC_LOG_INFO,
3269 "refresh: answer SOA count (%d) != 1 "
3270 "from master %s",
3271 soacnt, master);
3272 goto next_master;
3275 * Extract serial
3277 rdataset = NULL;
3278 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
3279 dns_rdatatype_soa, dns_rdatatype_none,
3280 NULL, &rdataset);
3281 if (result != ISC_R_SUCCESS) {
3282 dns_zone_log(zone, ISC_LOG_INFO,
3283 "refresh: unable to get SOA record "
3284 "from master %s", master);
3285 goto next_master;
3288 result = dns_rdataset_first(rdataset);
3289 if (result != ISC_R_SUCCESS) {
3290 dns_zone_log(zone, ISC_LOG_INFO,
3291 "refresh: dns_rdataset_first() failed");
3292 goto next_master;
3295 dns_rdataset_current(rdataset, &rdata);
3296 result = dns_rdata_tostruct(&rdata, &soa, NULL);
3297 if (result != ISC_R_SUCCESS) {
3298 dns_zone_log(zone, ISC_LOG_INFO,
3299 "refresh: dns_rdata_tostruct() failed");
3300 goto next_master;
3303 serial = soa.serial;
3305 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
3306 serial, zone->serial);
3307 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
3308 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
3309 isc_serial_gt(serial, zone->serial)) {
3310 tcp_transfer:
3311 isc_event_free(&event);
3312 LOCK_ZONE(zone);
3313 dns_request_destroy(&zone->request);
3314 UNLOCK_ZONE(zone);
3315 if (zone->type == dns_zone_slave) {
3316 queue_xfrin(zone);
3317 } else {
3318 INSIST(zone->type == dns_zone_stub);
3319 ns_query(zone, rdataset, NULL);
3321 if (msg != NULL)
3322 dns_message_destroy(&msg);
3323 } else if (isc_serial_eq(soa.serial, zone->serial)) {
3324 if (zone->masterfile != NULL) {
3325 result = ISC_R_FAILURE;
3326 if (zone->journal != NULL)
3327 result = isc_file_settime(zone->journal, &now);
3328 if (result != ISC_R_SUCCESS)
3329 result = isc_file_settime(zone->masterfile,
3330 &now);
3331 if (result != ISC_R_SUCCESS)
3332 dns_zone_log(zone, ISC_LOG_ERROR,
3333 "refresh: could not set file "
3334 "modification time of '%s': %s",
3335 zone->masterfile,
3336 dns_result_totext(result));
3338 isc_interval_set(&i, isc_random_jitter(zone->refresh,
3339 zone->refresh / 4), 0);
3340 isc_time_add(&now, &i, &zone->refreshtime);
3341 isc_interval_set(&i, zone->expire, 0);
3342 isc_time_add(&now, &i, &zone->expiretime);
3343 goto next_master;
3344 } else {
3345 zone_debuglog(zone, me, 1, "ahead");
3346 goto next_master;
3348 if (msg != NULL)
3349 dns_message_destroy(&msg);
3350 goto detach;
3352 next_master:
3353 if (msg != NULL)
3354 dns_message_destroy(&msg);
3355 isc_event_free(&event);
3356 LOCK_ZONE(zone);
3357 dns_request_destroy(&zone->request);
3358 zone->curmaster++;
3359 zone->refreshcnt = 0;
3360 if (zone->curmaster >= zone->masterscnt) {
3361 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3362 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
3363 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
3364 zone->refreshtime = now;
3366 zone_settimer(zone, &now);
3367 UNLOCK_ZONE(zone);
3368 goto detach;
3370 queue_soa_query(zone);
3371 UNLOCK_ZONE(zone);
3372 goto detach;
3374 same_master:
3375 zone->refreshcnt++;
3376 if (msg != NULL)
3377 dns_message_destroy(&msg);
3378 isc_event_free(&event);
3379 LOCK_ZONE(zone);
3380 dns_request_destroy(&zone->request);
3381 queue_soa_query(zone);
3382 UNLOCK_ZONE(zone);
3383 detach:
3384 dns_zone_idetach(&zone);
3385 return;
3388 static void
3389 queue_soa_query(dns_zone_t *zone) {
3390 const char me[] = "queue_soa_query";
3391 isc_event_t *e;
3392 dns_zone_t *dummy = NULL;
3393 isc_result_t result;
3395 ENTER;
3397 * Locked by caller
3399 REQUIRE(LOCKED_ZONE(zone));
3401 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
3402 cancel_refresh(zone);
3403 return;
3406 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
3407 soa_query, zone, sizeof(isc_event_t));
3408 if (e == NULL) {
3409 cancel_refresh(zone);
3410 return;
3414 * Attach so that we won't clean up
3415 * until the event is delivered.
3417 zone_iattach(zone, &dummy);
3419 e->ev_arg = zone;
3420 e->ev_sender = NULL;
3421 result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
3422 if (result != ISC_R_SUCCESS) {
3423 zone_idetach(&dummy);
3424 isc_event_free(&e);
3425 cancel_refresh(zone);
3429 static inline isc_result_t
3430 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
3431 dns_message_t **messagep)
3433 dns_message_t *message = NULL;
3434 dns_name_t *qname = NULL;
3435 dns_rdataset_t *qrdataset = NULL;
3436 isc_result_t result;
3438 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
3439 &message);
3440 if (result != ISC_R_SUCCESS)
3441 goto cleanup;
3443 message->opcode = dns_opcode_query;
3444 message->rdclass = zone->rdclass;
3446 result = dns_message_gettempname(message, &qname);
3447 if (result != ISC_R_SUCCESS)
3448 goto cleanup;
3450 result = dns_message_gettemprdataset(message, &qrdataset);
3451 if (result != ISC_R_SUCCESS)
3452 goto cleanup;
3455 * Make question.
3457 dns_name_init(qname, NULL);
3458 dns_name_clone(&zone->origin, qname);
3459 dns_rdataset_init(qrdataset);
3460 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
3461 ISC_LIST_APPEND(qname->list, qrdataset, link);
3462 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
3464 *messagep = message;
3465 return (ISC_R_SUCCESS);
3467 cleanup:
3468 if (qname != NULL)
3469 dns_message_puttempname(message, &qname);
3470 if (qrdataset != NULL)
3471 dns_message_puttemprdataset(message, &qrdataset);
3472 if (message != NULL)
3473 dns_message_destroy(&message);
3474 return (result);
3477 static void
3478 soa_query(isc_task_t *task, isc_event_t *event) {
3479 const char me[] = "soa_query";
3480 isc_result_t result;
3481 dns_message_t *message = NULL;
3482 dns_zone_t *zone = event->ev_arg;
3483 dns_zone_t *dummy = NULL;
3484 isc_netaddr_t masterip;
3485 dns_tsigkey_t *key = NULL;
3486 isc_uint32_t options;
3487 isc_sockaddr_t src;
3488 isc_boolean_t cancel = ISC_TRUE;
3489 int timeout;
3491 REQUIRE(DNS_ZONE_VALID(zone));
3493 UNUSED(task);
3495 ENTER;
3497 LOCK_ZONE(zone);
3498 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
3499 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
3500 zone->view->requestmgr == NULL) {
3501 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
3502 cancel = ISC_FALSE;
3503 goto cleanup;
3507 * XXX Optimisation: Create message when zone is setup and reuse.
3509 result = create_query(zone, dns_rdatatype_soa, &message);
3510 if (result != ISC_R_SUCCESS)
3511 goto cleanup;
3513 INSIST(zone->masterscnt > 0);
3514 INSIST(zone->curmaster < zone->masterscnt);
3515 zone->masteraddr = zone->masters[zone->curmaster];
3517 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
3519 * First, look for a tsig key in the master statement, then
3520 * try for a server key.
3522 if ((zone->masterkeynames != NULL) &&
3523 (zone->masterkeynames[zone->curmaster] != NULL)) {
3524 dns_view_t *view = dns_zone_getview(zone);
3525 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
3526 result = dns_view_gettsig(view, keyname, &key);
3527 if (result != ISC_R_SUCCESS) {
3528 char namebuf[DNS_NAME_FORMATSIZE];
3529 dns_name_format(keyname, namebuf, sizeof(namebuf));
3530 dns_zone_log(zone, ISC_LOG_ERROR,
3531 "unable to find key: %s", namebuf);
3534 if (key == NULL)
3535 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
3537 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
3538 DNS_REQUESTOPT_TCP : 0;
3539 switch (isc_sockaddr_pf(&zone->masteraddr)) {
3540 case PF_INET:
3541 src = zone->xfrsource4;
3542 break;
3543 case PF_INET6:
3544 src = zone->xfrsource6;
3545 break;
3546 default:
3547 result = ISC_R_NOTIMPLEMENTED;
3548 goto cleanup;
3550 zone_iattach(zone, &dummy);
3551 timeout = 15;
3552 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
3553 timeout = 30;
3554 result = dns_request_createvia(zone->view->requestmgr, message,
3555 &src, &zone->masteraddr, options, key,
3556 timeout, zone->task,
3557 refresh_callback, zone, &zone->request);
3558 if (result != ISC_R_SUCCESS) {
3559 zone_idetach(&dummy);
3560 zone_debuglog(zone, me, 1,
3561 "dns_request_createvia() failed: %s",
3562 dns_result_totext(result));
3563 goto cleanup;
3565 cancel = ISC_FALSE;
3567 cleanup:
3568 if (key != NULL)
3569 dns_tsigkey_detach(&key);
3570 if (message != NULL)
3571 dns_message_destroy(&message);
3572 if (cancel)
3573 cancel_refresh(zone);
3574 isc_event_free(&event);
3575 UNLOCK_ZONE(zone);
3576 dns_zone_idetach(&zone);
3577 return;
3580 static void
3581 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
3582 const char me[] = "ns_query";
3583 isc_result_t result;
3584 dns_message_t *message = NULL;
3585 isc_netaddr_t masterip;
3586 dns_tsigkey_t *key = NULL;
3587 dns_dbnode_t *node = NULL;
3588 isc_sockaddr_t src;
3589 int timeout;
3591 REQUIRE(DNS_ZONE_VALID(zone));
3592 REQUIRE((soardataset != NULL && stub == NULL) ||
3593 (soardataset == NULL && stub != NULL));
3594 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
3596 ENTER;
3598 LOCK_ZONE(zone);
3599 if (stub == NULL) {
3600 stub = isc_mem_get(zone->mctx, sizeof *stub);
3601 if (stub == NULL)
3602 goto cleanup;
3603 stub->magic = STUB_MAGIC;
3604 stub->mctx = zone->mctx;
3605 stub->zone = NULL;
3606 stub->db = NULL;
3607 stub->version = NULL;
3610 * Attach so that the zone won't disappear from under us.
3612 zone_iattach(zone, &stub->zone);
3615 * If a db exists we will update it, otherwise we create a
3616 * new one and attach it to the zone once we have the NS
3617 * RRset and glue.
3619 if (zone->db != NULL)
3620 dns_db_attach(zone->db, &stub->db);
3621 else {
3622 INSIST(zone->db_argc >= 1);
3623 result = dns_db_create(zone->mctx, zone->db_argv[0],
3624 &zone->origin, dns_dbtype_stub,
3625 zone->rdclass,
3626 zone->db_argc - 1,
3627 zone->db_argv + 1,
3628 &stub->db);
3629 if (result != ISC_R_SUCCESS) {
3630 dns_zone_log(zone, ISC_LOG_ERROR,
3631 "refreshing stub: "
3632 "could not create "
3633 "database: %s",
3634 dns_result_totext(result));
3635 goto cleanup;
3637 dns_db_settask(stub->db, zone->task);
3640 dns_db_newversion(stub->db, &stub->version);
3643 * Update SOA record.
3645 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
3646 &node);
3647 if (result != ISC_R_SUCCESS) {
3648 dns_zone_log(zone, ISC_LOG_INFO,
3649 "refreshing stub: "
3650 "dns_db_findnode() failed: %s",
3651 dns_result_totext(result));
3652 goto cleanup;
3655 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
3656 soardataset, 0, NULL);
3657 dns_db_detachnode(stub->db, &node);
3658 if (result != ISC_R_SUCCESS) {
3659 dns_zone_log(zone, ISC_LOG_INFO,
3660 "refreshing stub: "
3661 "dns_db_addrdataset() failed: %s",
3662 dns_result_totext(result));
3663 goto cleanup;
3668 * XXX Optimisation: Create message when zone is setup and reuse.
3670 result = create_query(zone, dns_rdatatype_ns, &message);
3672 INSIST(zone->masterscnt > 0);
3673 INSIST(zone->curmaster < zone->masterscnt);
3674 zone->masteraddr = zone->masters[zone->curmaster];
3676 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
3678 * First, look for a tsig key in the master statement, then
3679 * try for a server key.
3681 if ((zone->masterkeynames != NULL) &&
3682 (zone->masterkeynames[zone->curmaster] != NULL)) {
3683 dns_view_t *view = dns_zone_getview(zone);
3684 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
3685 result = dns_view_gettsig(view, keyname, &key);
3686 if (result != ISC_R_SUCCESS) {
3687 char namebuf[DNS_NAME_FORMATSIZE];
3688 dns_name_format(keyname, namebuf, sizeof(namebuf));
3689 dns_zone_log(zone, ISC_LOG_ERROR,
3690 "unable to find key: %s", namebuf);
3693 if (key == NULL)
3694 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
3697 * Always use TCP so that we shouldn't truncate in additional section.
3699 switch (isc_sockaddr_pf(&zone->masteraddr)) {
3700 case PF_INET:
3701 src = zone->xfrsource4;
3702 break;
3703 case PF_INET6:
3704 src = zone->xfrsource6;
3705 break;
3706 default:
3707 result = ISC_R_NOTIMPLEMENTED;
3708 goto cleanup;
3710 timeout = 15;
3711 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
3712 timeout = 30;
3713 result = dns_request_createvia(zone->view->requestmgr, message,
3714 &src, &zone->masteraddr,
3715 DNS_REQUESTOPT_TCP, key, timeout,
3716 zone->task, stub_callback, stub,
3717 &zone->request);
3718 if (result != ISC_R_SUCCESS) {
3719 zone_debuglog(zone, me, 1,
3720 "dns_request_createvia() failed: %s",
3721 dns_result_totext(result));
3722 goto cleanup;
3724 dns_message_destroy(&message);
3725 goto unlock;
3727 cleanup:
3728 cancel_refresh(zone);
3729 if (stub != NULL) {
3730 stub->magic = 0;
3731 if (stub->version != NULL)
3732 dns_db_closeversion(stub->db, &stub->version,
3733 ISC_FALSE);
3734 if (stub->db != NULL)
3735 dns_db_detach(&stub->db);
3736 if (stub->zone != NULL)
3737 zone_idetach(&stub->zone);
3738 isc_mem_put(stub->mctx, stub, sizeof(*stub));
3740 if (message != NULL)
3741 dns_message_destroy(&message);
3742 unlock:
3743 if (key != NULL)
3744 dns_tsigkey_detach(&key);
3745 UNLOCK_ZONE(zone);
3746 return;
3750 * Handle the control event. Note that although this event causes the zone
3751 * to shut down, it is not a shutdown event in the sense of the task library.
3753 static void
3754 zone_shutdown(isc_task_t *task, isc_event_t *event) {
3755 dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
3756 isc_boolean_t free_needed, linked = ISC_FALSE;
3758 UNUSED(task);
3759 REQUIRE(DNS_ZONE_VALID(zone));
3760 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
3761 INSIST(isc_refcount_current(&zone->erefs) == 0);
3762 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
3765 * Stop things being restarted after we cancel them below.
3767 LOCK_ZONE(zone);
3768 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
3769 UNLOCK_ZONE(zone);
3772 * If we were waiting for xfrin quota, step out of
3773 * the queue.
3774 * If there's no zone manager, we can't be waiting for the
3775 * xfrin quota
3777 if (zone->zmgr != NULL) {
3778 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
3779 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
3780 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
3781 statelink);
3782 linked = ISC_TRUE;
3783 zone->statelist = NULL;
3785 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
3789 * In task context, no locking required. See zone_xfrdone().
3791 if (zone->xfr != NULL)
3792 dns_xfrin_shutdown(zone->xfr);
3794 LOCK_ZONE(zone);
3795 if (linked) {
3796 INSIST(zone->irefs > 0);
3797 zone->irefs--;
3799 if (zone->request != NULL) {
3800 dns_request_cancel(zone->request);
3803 if (zone->readio != NULL)
3804 zonemgr_cancelio(zone->readio);
3806 if (zone->lctx != NULL)
3807 dns_loadctx_cancel(zone->lctx);
3809 notify_cancel(zone);
3811 if (zone->timer != NULL) {
3812 isc_timer_detach(&zone->timer);
3813 INSIST(zone->irefs > 0);
3814 zone->irefs--;
3817 if (zone->view != NULL)
3818 dns_view_weakdetach(&zone->view);
3821 * We have now canceled everything set the flag to allow exit_check()
3822 * to succeed. We must not unlock between setting this flag and
3823 * calling exit_check().
3825 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
3826 free_needed = exit_check(zone);
3827 UNLOCK_ZONE(zone);
3828 if (free_needed)
3829 zone_free(zone);
3832 static void
3833 zone_timer(isc_task_t *task, isc_event_t *event) {
3834 const char me[] = "zone_timer";
3835 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
3837 UNUSED(task);
3838 REQUIRE(DNS_ZONE_VALID(zone));
3840 ENTER;
3842 zone_maintenance(zone);
3844 isc_event_free(&event);
3847 static void
3848 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
3849 const char me[] = "zone_settimer";
3850 isc_time_t next;
3851 isc_result_t result;
3853 REQUIRE(DNS_ZONE_VALID(zone));
3854 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
3855 return;
3857 isc_time_settoepoch(&next);
3859 switch (zone->type) {
3860 case dns_zone_master:
3861 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
3862 next = *now;
3863 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
3864 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
3865 INSIST(!isc_time_isepoch(&zone->dumptime));
3866 if (isc_time_isepoch(&next) ||
3867 isc_time_compare(&zone->dumptime, &next) < 0)
3868 next = zone->dumptime;
3870 break;
3872 case dns_zone_slave:
3873 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
3874 next = *now;
3875 /*FALLTHROUGH*/
3877 case dns_zone_stub:
3878 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
3879 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
3880 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
3881 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
3882 INSIST(!isc_time_isepoch(&zone->refreshtime));
3883 if (isc_time_isepoch(&next) ||
3884 isc_time_compare(&zone->refreshtime, &next) < 0)
3885 next = zone->refreshtime;
3887 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3888 INSIST(!isc_time_isepoch(&zone->expiretime));
3889 if (isc_time_isepoch(&next) ||
3890 isc_time_compare(&zone->expiretime, &next) < 0)
3891 next = zone->expiretime;
3893 break;
3895 default:
3896 break;
3899 if (isc_time_isepoch(&next)) {
3900 zone_debuglog(zone, me, 10, "settimer inactive");
3901 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
3902 NULL, NULL, ISC_TRUE);
3903 if (result != ISC_R_SUCCESS)
3904 dns_zone_log(zone, ISC_LOG_ERROR,
3905 "could not deactivate zone timer: %s",
3906 isc_result_totext(result));
3907 } else {
3908 if (isc_time_compare(&next, now) <= 0)
3909 next = *now;
3910 result = isc_timer_reset(zone->timer, isc_timertype_once,
3911 &next, NULL, ISC_TRUE);
3912 if (result != ISC_R_SUCCESS)
3913 dns_zone_log(zone, ISC_LOG_ERROR,
3914 "could not reset zone timer: %s",
3915 isc_result_totext(result));
3919 static void
3920 cancel_refresh(dns_zone_t *zone) {
3921 const char me[] = "cancel_refresh";
3922 isc_time_t now;
3925 * 'zone' locked by caller.
3928 REQUIRE(DNS_ZONE_VALID(zone));
3929 REQUIRE(LOCKED_ZONE(zone));
3931 ENTER;
3933 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3934 isc_time_now(&now);
3935 zone_settimer(zone, &now);
3938 static isc_result_t
3939 notify_createmessage(dns_zone_t *zone, unsigned int flags,
3940 dns_message_t **messagep)
3942 dns_dbnode_t *node = NULL;
3943 dns_dbversion_t *version = NULL;
3944 dns_message_t *message = NULL;
3945 dns_rdataset_t rdataset;
3946 dns_rdata_t rdata = DNS_RDATA_INIT;
3948 dns_name_t *tempname = NULL;
3949 dns_rdata_t *temprdata = NULL;
3950 dns_rdatalist_t *temprdatalist = NULL;
3951 dns_rdataset_t *temprdataset = NULL;
3953 isc_result_t result;
3954 isc_region_t r;
3955 isc_buffer_t *b = NULL;
3957 REQUIRE(DNS_ZONE_VALID(zone));
3958 REQUIRE(messagep != NULL && *messagep == NULL);
3960 message = NULL;
3961 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
3962 &message);
3963 if (result != ISC_R_SUCCESS)
3964 return (result);
3966 message->opcode = dns_opcode_notify;
3967 message->flags |= DNS_MESSAGEFLAG_AA;
3968 message->rdclass = zone->rdclass;
3970 result = dns_message_gettempname(message, &tempname);
3971 if (result != ISC_R_SUCCESS)
3972 goto cleanup;
3974 result = dns_message_gettemprdataset(message, &temprdataset);
3975 if (result != ISC_R_SUCCESS)
3976 goto cleanup;
3979 * Make question.
3981 dns_name_init(tempname, NULL);
3982 dns_name_clone(&zone->origin, tempname);
3983 dns_rdataset_init(temprdataset);
3984 dns_rdataset_makequestion(temprdataset, zone->rdclass,
3985 dns_rdatatype_soa);
3986 ISC_LIST_APPEND(tempname->list, temprdataset, link);
3987 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
3988 tempname = NULL;
3989 temprdataset = NULL;
3991 if ((flags & DNS_NOTIFY_NOSOA) != 0)
3992 goto done;
3994 result = dns_message_gettempname(message, &tempname);
3995 if (result != ISC_R_SUCCESS)
3996 goto soa_cleanup;
3997 result = dns_message_gettemprdata(message, &temprdata);
3998 if (result != ISC_R_SUCCESS)
3999 goto soa_cleanup;
4000 result = dns_message_gettemprdataset(message, &temprdataset);
4001 if (result != ISC_R_SUCCESS)
4002 goto soa_cleanup;
4003 result = dns_message_gettemprdatalist(message, &temprdatalist);
4004 if (result != ISC_R_SUCCESS)
4005 goto soa_cleanup;
4007 dns_name_init(tempname, NULL);
4008 dns_name_clone(&zone->origin, tempname);
4009 dns_db_currentversion(zone->db, &version);
4010 result = dns_db_findnode(zone->db, tempname, ISC_FALSE, &node);
4011 if (result != ISC_R_SUCCESS)
4012 goto soa_cleanup;
4014 dns_rdataset_init(&rdataset);
4015 result = dns_db_findrdataset(zone->db, node, version,
4016 dns_rdatatype_soa,
4017 dns_rdatatype_none, 0, &rdataset,
4018 NULL);
4019 if (result != ISC_R_SUCCESS)
4020 goto soa_cleanup;
4021 result = dns_rdataset_first(&rdataset);
4022 if (result != ISC_R_SUCCESS)
4023 goto soa_cleanup;
4024 dns_rdataset_current(&rdataset, &rdata);
4025 dns_rdata_toregion(&rdata, &r);
4026 result = isc_buffer_allocate(zone->mctx, &b, r.length);
4027 if (result != ISC_R_SUCCESS)
4028 goto soa_cleanup;
4029 isc_buffer_putmem(b, r.base, r.length);
4030 isc_buffer_usedregion(b, &r);
4031 dns_rdata_init(temprdata);
4032 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
4033 dns_message_takebuffer(message, &b);
4034 result = dns_rdataset_next(&rdataset);
4035 dns_rdataset_disassociate(&rdataset);
4036 if (result != ISC_R_NOMORE)
4037 goto soa_cleanup;
4038 temprdatalist->rdclass = rdata.rdclass;
4039 temprdatalist->type = rdata.type;
4040 temprdatalist->covers = 0;
4041 temprdatalist->ttl = rdataset.ttl;
4042 ISC_LIST_INIT(temprdatalist->rdata);
4043 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
4045 dns_rdataset_init(temprdataset);
4046 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
4047 if (result != ISC_R_SUCCESS)
4048 goto soa_cleanup;
4050 ISC_LIST_APPEND(tempname->list, temprdataset, link);
4051 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
4052 temprdatalist = NULL;
4053 temprdataset = NULL;
4054 temprdata = NULL;
4055 tempname = NULL;
4057 soa_cleanup:
4058 if (node != NULL)
4059 dns_db_detachnode(zone->db, &node);
4060 if (version != NULL)
4061 dns_db_closeversion(zone->db, &version, ISC_FALSE);
4062 if (tempname != NULL)
4063 dns_message_puttempname(message, &tempname);
4064 if (temprdata != NULL)
4065 dns_message_puttemprdata(message, &temprdata);
4066 if (temprdataset != NULL)
4067 dns_message_puttemprdataset(message, &temprdataset);
4068 if (temprdatalist != NULL)
4069 dns_message_puttemprdatalist(message, &temprdatalist);
4071 done:
4072 *messagep = message;
4073 return (ISC_R_SUCCESS);
4075 cleanup:
4076 if (tempname != NULL)
4077 dns_message_puttempname(message, &tempname);
4078 if (temprdataset != NULL)
4079 dns_message_puttemprdataset(message, &temprdataset);
4080 if (message != NULL)
4081 dns_message_destroy(&message);
4082 return (result);
4085 isc_result_t
4086 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
4087 dns_message_t *msg)
4089 unsigned int i;
4090 dns_rdata_soa_t soa;
4091 dns_rdataset_t *rdataset = NULL;
4092 dns_rdata_t rdata = DNS_RDATA_INIT;
4093 isc_result_t result;
4094 char fromtext[ISC_SOCKADDR_FORMATSIZE];
4095 int match = 0;
4096 isc_netaddr_t netaddr;
4098 REQUIRE(DNS_ZONE_VALID(zone));
4101 * If type != T_SOA return DNS_R_REFUSED. We don't yet support
4102 * ROLLOVER.
4104 * SOA: RFC 1996
4105 * Check that 'from' is a valid notify source, (zone->masters).
4106 * Return DNS_R_REFUSED if not.
4108 * If the notify message contains a serial number check it
4109 * against the zones serial and return if <= current serial
4111 * If a refresh check is progress, if so just record the
4112 * fact we received a NOTIFY and from where and return.
4113 * We will perform a new refresh check when the current one
4114 * completes. Return ISC_R_SUCCESS.
4116 * Otherwise initiate a refresh check using 'from' as the
4117 * first address to check. Return ISC_R_SUCCESS.
4120 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
4123 * We only handle NOTIFY (SOA) at the present.
4125 LOCK_ZONE(zone);
4126 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
4127 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
4128 dns_rdatatype_soa, dns_rdatatype_none,
4129 NULL, NULL) != ISC_R_SUCCESS) {
4130 UNLOCK_ZONE(zone);
4131 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
4132 dns_zone_log(zone, ISC_LOG_NOTICE,
4133 "NOTIFY with no "
4134 "question section from: %s", fromtext);
4135 return (DNS_R_FORMERR);
4137 dns_zone_log(zone, ISC_LOG_NOTICE,
4138 "NOTIFY zone does not match");
4139 return (DNS_R_NOTIMP);
4143 * If we are a master zone just succeed.
4145 if (zone->type == dns_zone_master) {
4146 UNLOCK_ZONE(zone);
4147 return (ISC_R_SUCCESS);
4150 isc_netaddr_fromsockaddr(&netaddr, from);
4151 for (i = 0; i < zone->masterscnt; i++) {
4152 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
4153 break;
4154 if (zone->view->aclenv.match_mapped &&
4155 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
4156 isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
4157 isc_netaddr_t na1, na2;
4158 isc_netaddr_fromv4mapped(&na1, &netaddr);
4159 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
4160 if (isc_netaddr_equal(&na1, &na2))
4161 break;
4166 * Accept notify requests from non masters if they are on
4167 * 'zone->notify_acl'.
4169 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
4170 dns_acl_match(&netaddr, NULL, zone->notify_acl,
4171 &zone->view->aclenv,
4172 &match, NULL) == ISC_R_SUCCESS &&
4173 match > 0)
4175 /* Accept notify. */
4176 } else if (i >= zone->masterscnt) {
4177 UNLOCK_ZONE(zone);
4178 dns_zone_log(zone, ISC_LOG_DEBUG(3),
4179 "refused notify from non-master: %s", fromtext);
4180 return (DNS_R_REFUSED);
4184 * If the zone is loaded and there are answers check the serial
4185 * to see if we need to do a refresh. Do not worry about this
4186 * check if we are a dialup zone as we use the notify request
4187 * to trigger a refresh check.
4189 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
4190 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
4191 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
4192 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
4193 &zone->origin,
4194 dns_rdatatype_soa,
4195 dns_rdatatype_none, NULL,
4196 &rdataset);
4197 if (result == ISC_R_SUCCESS)
4198 result = dns_rdataset_first(rdataset);
4199 if (result == ISC_R_SUCCESS) {
4200 isc_uint32_t serial = 0;
4202 dns_rdataset_current(rdataset, &rdata);
4203 result = dns_rdata_tostruct(&rdata, &soa, NULL);
4204 if (result == ISC_R_SUCCESS) {
4205 serial = soa.serial;
4206 if (isc_serial_le(serial, zone->serial)) {
4207 dns_zone_log(zone, ISC_LOG_DEBUG(3),
4208 "notify from %s: "
4209 "zone is up to date",
4210 fromtext);
4211 UNLOCK_ZONE(zone);
4212 return (ISC_R_SUCCESS);
4219 * If we got this far and there was a refresh in progress just
4220 * let it complete. Record where we got the notify from so we
4221 * can perform a refresh check when the current one completes
4223 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
4224 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
4225 zone->notifyfrom = *from;
4226 UNLOCK_ZONE(zone);
4227 dns_zone_log(zone, ISC_LOG_DEBUG(3),
4228 "notify from %s: refresh in progress, "
4229 "refresh check queued",
4230 fromtext);
4231 return (ISC_R_SUCCESS);
4233 zone->notifyfrom = *from;
4234 UNLOCK_ZONE(zone);
4235 dns_zone_refresh(zone);
4236 return (ISC_R_SUCCESS);
4239 void
4240 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
4242 REQUIRE(DNS_ZONE_VALID(zone));
4244 LOCK_ZONE(zone);
4245 if (zone->notify_acl != NULL)
4246 dns_acl_detach(&zone->notify_acl);
4247 dns_acl_attach(acl, &zone->notify_acl);
4248 UNLOCK_ZONE(zone);
4251 void
4252 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
4254 REQUIRE(DNS_ZONE_VALID(zone));
4256 LOCK_ZONE(zone);
4257 if (zone->query_acl != NULL)
4258 dns_acl_detach(&zone->query_acl);
4259 dns_acl_attach(acl, &zone->query_acl);
4260 UNLOCK_ZONE(zone);
4263 void
4264 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
4266 REQUIRE(DNS_ZONE_VALID(zone));
4268 LOCK_ZONE(zone);
4269 if (zone->update_acl != NULL)
4270 dns_acl_detach(&zone->update_acl);
4271 dns_acl_attach(acl, &zone->update_acl);
4272 UNLOCK_ZONE(zone);
4275 void
4276 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
4278 REQUIRE(DNS_ZONE_VALID(zone));
4280 LOCK_ZONE(zone);
4281 if (zone->forward_acl != NULL)
4282 dns_acl_detach(&zone->forward_acl);
4283 dns_acl_attach(acl, &zone->forward_acl);
4284 UNLOCK_ZONE(zone);
4287 void
4288 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
4290 REQUIRE(DNS_ZONE_VALID(zone));
4292 LOCK_ZONE(zone);
4293 if (zone->xfr_acl != NULL)
4294 dns_acl_detach(&zone->xfr_acl);
4295 dns_acl_attach(acl, &zone->xfr_acl);
4296 UNLOCK_ZONE(zone);
4299 dns_acl_t *
4300 dns_zone_getnotifyacl(dns_zone_t *zone) {
4302 REQUIRE(DNS_ZONE_VALID(zone));
4304 return (zone->notify_acl);
4307 dns_acl_t *
4308 dns_zone_getqueryacl(dns_zone_t *zone) {
4310 REQUIRE(DNS_ZONE_VALID(zone));
4312 return (zone->query_acl);
4315 dns_acl_t *
4316 dns_zone_getupdateacl(dns_zone_t *zone) {
4318 REQUIRE(DNS_ZONE_VALID(zone));
4320 return (zone->update_acl);
4323 dns_acl_t *
4324 dns_zone_getforwardacl(dns_zone_t *zone) {
4326 REQUIRE(DNS_ZONE_VALID(zone));
4328 return (zone->forward_acl);
4331 dns_acl_t *
4332 dns_zone_getxfracl(dns_zone_t *zone) {
4334 REQUIRE(DNS_ZONE_VALID(zone));
4336 return (zone->xfr_acl);
4339 void
4340 dns_zone_clearupdateacl(dns_zone_t *zone) {
4342 REQUIRE(DNS_ZONE_VALID(zone));
4344 LOCK_ZONE(zone);
4345 if (zone->update_acl != NULL)
4346 dns_acl_detach(&zone->update_acl);
4347 UNLOCK_ZONE(zone);
4350 void
4351 dns_zone_clearforwardacl(dns_zone_t *zone) {
4353 REQUIRE(DNS_ZONE_VALID(zone));
4355 LOCK_ZONE(zone);
4356 if (zone->forward_acl != NULL)
4357 dns_acl_detach(&zone->forward_acl);
4358 UNLOCK_ZONE(zone);
4361 void
4362 dns_zone_clearnotifyacl(dns_zone_t *zone) {
4364 REQUIRE(DNS_ZONE_VALID(zone));
4366 LOCK_ZONE(zone);
4367 if (zone->notify_acl != NULL)
4368 dns_acl_detach(&zone->notify_acl);
4369 UNLOCK_ZONE(zone);
4372 void
4373 dns_zone_clearqueryacl(dns_zone_t *zone) {
4375 REQUIRE(DNS_ZONE_VALID(zone));
4377 LOCK_ZONE(zone);
4378 if (zone->query_acl != NULL)
4379 dns_acl_detach(&zone->query_acl);
4380 UNLOCK_ZONE(zone);
4383 void
4384 dns_zone_clearxfracl(dns_zone_t *zone) {
4386 REQUIRE(DNS_ZONE_VALID(zone));
4388 LOCK_ZONE(zone);
4389 if (zone->xfr_acl != NULL)
4390 dns_acl_detach(&zone->xfr_acl);
4391 UNLOCK_ZONE(zone);
4394 void
4395 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
4397 REQUIRE(DNS_ZONE_VALID(zone));
4399 zone->check_names = severity;
4402 dns_severity_t
4403 dns_zone_getchecknames(dns_zone_t *zone) {
4405 REQUIRE(DNS_ZONE_VALID(zone));
4407 return (zone->check_names);
4410 void
4411 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
4413 REQUIRE(DNS_ZONE_VALID(zone));
4415 zone->journalsize = size;
4418 isc_int32_t
4419 dns_zone_getjournalsize(dns_zone_t *zone) {
4421 REQUIRE(DNS_ZONE_VALID(zone));
4423 return (zone->journalsize);
4426 static void
4427 zone_tostr(dns_zone_t *zone, char *buf, size_t length) {
4428 isc_result_t result = ISC_R_FAILURE;
4429 isc_buffer_t buffer;
4431 REQUIRE(buf != NULL);
4432 REQUIRE(length > 1U);
4435 * Leave space for terminating '\0'.
4437 isc_buffer_init(&buffer, buf, length - 1);
4438 if (dns_name_dynamic(&zone->origin))
4439 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
4440 if (result != ISC_R_SUCCESS)
4441 isc_buffer_putstr(&buffer, "<UNKNOWN>");
4443 isc_buffer_putstr(&buffer, "/");
4444 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
4445 buf[isc_buffer_usedlength(&buffer)] = '\0';
4448 static void
4449 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
4450 va_list ap;
4451 char message[4096];
4452 char namebuf[1024+32];
4454 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
4455 return;
4457 zone_tostr(zone, namebuf, sizeof(namebuf));
4459 va_start(ap, fmt);
4460 vsnprintf(message, sizeof message, fmt, ap);
4461 va_end(ap);
4462 isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
4463 level, "zone %s: %s", namebuf, message);
4466 void
4467 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
4468 va_list ap;
4469 char message[4096];
4470 char namebuf[1024+32];
4472 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
4473 return;
4475 zone_tostr(zone, namebuf, sizeof(namebuf));
4477 va_start(ap, fmt);
4478 vsnprintf(message, sizeof message, fmt, ap);
4479 va_end(ap);
4480 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
4481 level, "zone %s: %s", namebuf, message);
4484 static void
4485 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
4486 const char *fmt, ...)
4488 va_list ap;
4489 char message[4096];
4490 char namebuf[1024+32];
4491 int level = ISC_LOG_DEBUG(debuglevel);
4493 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
4494 return;
4496 zone_tostr(zone, namebuf, sizeof(namebuf));
4498 va_start(ap, fmt);
4499 vsnprintf(message, sizeof message, fmt, ap);
4500 va_end(ap);
4501 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
4502 level, "%s: zone %s: %s", me, namebuf, message);
4505 static int
4506 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
4508 isc_result_t result;
4509 dns_name_t *name;
4510 dns_rdataset_t *curr;
4511 int count = 0;
4513 result = dns_message_firstname(msg, section);
4514 while (result == ISC_R_SUCCESS) {
4515 name = NULL;
4516 dns_message_currentname(msg, section, &name);
4518 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
4519 curr = ISC_LIST_PREV(curr, link)) {
4520 if (curr->type == type)
4521 count++;
4523 result = dns_message_nextname(msg, section);
4526 return (count);
4529 void
4530 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
4531 REQUIRE(DNS_ZONE_VALID(zone));
4533 zone->maxxfrin = maxxfrin;
4536 isc_uint32_t
4537 dns_zone_getmaxxfrin(dns_zone_t *zone) {
4538 REQUIRE(DNS_ZONE_VALID(zone));
4540 return (zone->maxxfrin);
4543 void
4544 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
4545 REQUIRE(DNS_ZONE_VALID(zone));
4546 zone->maxxfrout = maxxfrout;
4549 isc_uint32_t
4550 dns_zone_getmaxxfrout(dns_zone_t *zone) {
4551 REQUIRE(DNS_ZONE_VALID(zone));
4553 return (zone->maxxfrout);
4556 dns_zonetype_t dns_zone_gettype(dns_zone_t *zone) {
4557 REQUIRE(DNS_ZONE_VALID(zone));
4559 return (zone->type);
4562 dns_name_t *
4563 dns_zone_getorigin(dns_zone_t *zone) {
4564 REQUIRE(DNS_ZONE_VALID(zone));
4566 return (&zone->origin);
4569 void
4570 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
4571 REQUIRE(DNS_ZONE_VALID(zone));
4573 LOCK_ZONE(zone);
4574 if (zone->task != NULL)
4575 isc_task_detach(&zone->task);
4576 isc_task_attach(task, &zone->task);
4577 if (zone->db != NULL)
4578 dns_db_settask(zone->db, zone->task);
4579 UNLOCK_ZONE(zone);
4582 void
4583 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
4584 REQUIRE(DNS_ZONE_VALID(zone));
4585 isc_task_attach(zone->task, target);
4588 void
4589 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
4590 REQUIRE(DNS_ZONE_VALID(zone));
4592 if (idlein == 0)
4593 idlein = DNS_DEFAULT_IDLEIN;
4594 zone->idlein = idlein;
4597 isc_uint32_t
4598 dns_zone_getidlein(dns_zone_t *zone) {
4599 REQUIRE(DNS_ZONE_VALID(zone));
4601 return (zone->idlein);
4604 void
4605 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
4606 REQUIRE(DNS_ZONE_VALID(zone));
4608 zone->idleout = idleout;
4611 isc_uint32_t
4612 dns_zone_getidleout(dns_zone_t *zone) {
4613 REQUIRE(DNS_ZONE_VALID(zone));
4615 return (zone->idleout);
4618 static void
4619 notify_done(isc_task_t *task, isc_event_t *event) {
4620 dns_requestevent_t *revent = (dns_requestevent_t *)event;
4621 dns_notify_t *notify;
4622 isc_result_t result;
4623 dns_message_t *message = NULL;
4624 isc_buffer_t buf;
4625 char rcode[128];
4626 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
4628 UNUSED(task);
4630 notify = event->ev_arg;
4631 REQUIRE(DNS_NOTIFY_VALID(notify));
4632 INSIST(task == notify->zone->task);
4634 isc_buffer_init(&buf, rcode, sizeof(rcode));
4635 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
4637 result = revent->result;
4638 if (result == ISC_R_SUCCESS)
4639 result = dns_message_create(notify->zone->mctx,
4640 DNS_MESSAGE_INTENTPARSE, &message);
4641 if (result == ISC_R_SUCCESS)
4642 result = dns_request_getresponse(revent->request, message,
4643 DNS_MESSAGEPARSE_PRESERVEORDER);
4644 if (result == ISC_R_SUCCESS)
4645 result = dns_rcode_totext(message->rcode, &buf);
4646 if (result == ISC_R_SUCCESS)
4647 notify_log(notify->zone, ISC_LOG_DEBUG(3),
4648 "notify response from %s: %.*s",
4649 addrbuf, (int)buf.used, rcode);
4650 else
4651 notify_log(notify->zone, ISC_LOG_DEBUG(1),
4652 "notify to %s failed: %s", addrbuf,
4653 dns_result_totext(result));
4656 * Old bind's return formerr if they see a soa record. Retry w/o
4657 * the soa if we see a formerr and had sent a SOA.
4659 isc_event_free(&event);
4660 if ((result == ISC_R_TIMEDOUT ||
4661 (message != NULL && message->rcode == dns_rcode_formerr &&
4662 (notify->flags & DNS_NOTIFY_NOSOA) == 0)) &&
4663 notify->attempt < 3) {
4664 notify->flags |= DNS_NOTIFY_NOSOA;
4665 notify->attempt++;
4666 dns_request_destroy(&notify->request);
4667 result = notify_send_queue(notify);
4668 if (result != ISC_R_SUCCESS)
4669 notify_destroy(notify, ISC_FALSE);
4670 } else {
4671 if (result == ISC_R_TIMEDOUT)
4672 notify_log(notify->zone, ISC_LOG_DEBUG(1),
4673 "notify to %s: retries exceeded", addrbuf);
4674 notify_destroy(notify, ISC_FALSE);
4676 if (message != NULL)
4677 dns_message_destroy(&message);
4680 isc_result_t
4681 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
4682 isc_result_t result;
4684 REQUIRE(DNS_ZONE_VALID(zone));
4685 LOCK_ZONE(zone);
4686 result = zone_replacedb(zone, db, dump);
4687 UNLOCK_ZONE(zone);
4688 return (result);
4691 static isc_result_t
4692 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
4693 dns_dbversion_t *ver;
4694 isc_result_t result;
4697 * 'zone' locked by caller.
4699 REQUIRE(DNS_ZONE_VALID(zone));
4700 REQUIRE(LOCKED_ZONE(zone));
4702 ver = NULL;
4703 dns_db_currentversion(db, &ver);
4706 * The initial version of a slave zone is always dumped;
4707 * subsequent versions may be journalled instead if this
4708 * is enabled in the configuration.
4710 if (zone->db != NULL && zone->journal != NULL &&
4711 zone->diff_on_reload) {
4712 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4713 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
4714 "generating diffs");
4715 result = dns_db_diff(zone->mctx, db, ver,
4716 zone->db, NULL /* XXX */,
4717 zone->journal);
4718 if (result != ISC_R_SUCCESS)
4719 goto fail;
4720 } else {
4721 if (dump && zone->masterfile != NULL) {
4722 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4723 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
4724 "dumping new zone version");
4725 result = dns_db_dump(db, ver, zone->masterfile);
4726 if (result != ISC_R_SUCCESS)
4727 goto fail;
4730 * Update the time the zone was updated, so
4731 * dns_zone_load can avoid loading it when
4732 * the server is reloaded. If isc_time_now
4733 * fails for some reason, all that happens is
4734 * the timestamp is not updated.
4736 (void)isc_time_now(&zone->loadtime);
4739 if (dump && zone->journal != NULL) {
4741 * The in-memory database just changed, and
4742 * because 'dump' is set, it didn't change by
4743 * being loaded from disk. Also, we have not
4744 * journalled diffs for this change.
4745 * Therefore, the on-disk journal is missing
4746 * the deltas for this change. Since it can
4747 * no longer be used to bring the zone
4748 * up-to-date, it is useless and should be
4749 * removed.
4751 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4752 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
4753 "removing journal file");
4754 (void)remove(zone->journal);
4758 dns_db_closeversion(db, &ver, ISC_FALSE);
4760 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4761 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
4762 "replacing zone database");
4764 if (zone->db != NULL)
4765 dns_db_detach(&zone->db);
4766 dns_db_attach(db, &zone->db);
4767 dns_db_settask(zone->db, zone->task);
4768 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
4769 return (ISC_R_SUCCESS);
4771 fail:
4772 dns_db_closeversion(db, &ver, ISC_FALSE);
4773 return (result);
4776 static void
4777 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
4778 isc_time_t now;
4779 isc_interval_t i;
4780 isc_boolean_t again = ISC_FALSE;
4781 unsigned int soacount;
4782 unsigned int nscount;
4783 isc_uint32_t serial, refresh, retry, expire, minimum;
4784 isc_result_t xfrresult = result;
4785 isc_boolean_t free_needed;
4787 REQUIRE(DNS_ZONE_VALID(zone));
4789 dns_zone_log(zone, ISC_LOG_DEBUG(1),
4790 "zone transfer finished: %s", dns_result_totext(result));
4792 LOCK_ZONE(zone);
4793 INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
4794 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4796 isc_time_now(&now);
4797 switch (result) {
4798 case ISC_R_SUCCESS:
4799 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
4800 /*FALLTHROUGH*/
4801 case DNS_R_UPTODATE:
4802 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
4804 * Has the zone expired underneath us?
4806 if (zone->db == NULL)
4807 goto same_master;
4810 * Update the zone structure's data from the actual
4811 * SOA received.
4813 nscount = 0;
4814 soacount = 0;
4815 INSIST(zone->db != NULL);
4816 result = zone_get_from_db(zone->db, &zone->origin, &nscount,
4817 &soacount, &serial, &refresh,
4818 &retry, &expire, &minimum);
4819 if (result == ISC_R_SUCCESS) {
4820 if (soacount != 1)
4821 dns_zone_log(zone, ISC_LOG_ERROR,
4822 "transferred zone "
4823 "has %d SOA record%s", soacount,
4824 (soacount != 0) ? "s" : "");
4825 if (nscount == 0)
4826 dns_zone_log(zone, ISC_LOG_ERROR,
4827 "transferred zone "
4828 "has no NS records");
4829 zone->serial = serial;
4830 zone->refresh = RANGE(refresh, zone->minrefresh,
4831 zone->maxrefresh);
4832 zone->retry = RANGE(retry, zone->minretry,
4833 zone->maxretry);
4834 zone->expire = RANGE(expire,
4835 zone->refresh + zone->retry,
4836 DNS_MAX_EXPIRE);
4837 zone->minimum = minimum;
4838 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4842 * Set our next update/expire times.
4844 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
4845 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
4846 zone->refreshtime = now;
4847 isc_interval_set(&i, zone->expire, 0);
4848 isc_time_add(&now, &i, &zone->expiretime);
4849 } else {
4850 isc_interval_set(&i, isc_random_jitter(zone->refresh,
4851 zone->refresh / 4), 0);
4852 isc_time_add(&now, &i, &zone->refreshtime);
4853 isc_interval_set(&i, zone->expire, 0);
4854 isc_time_add(&now, &i, &zone->expiretime);
4856 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS)
4857 dns_zone_log(zone, ISC_LOG_INFO,
4858 "transferred serial %u", zone->serial);
4861 * This is not neccessary if we just performed a AXFR
4862 * however it is necessary for an IXFR / UPTODATE and
4863 * won't hurt with an AXFR.
4865 if (zone->masterfile != NULL || zone->journal != NULL) {
4866 result = ISC_R_FAILURE;
4867 if (zone->journal != NULL)
4868 result = isc_file_settime(zone->journal, &now);
4869 if (result != ISC_R_SUCCESS &&
4870 zone->masterfile != NULL)
4871 result = isc_file_settime(zone->masterfile,
4872 &now);
4873 /* Someone removed the file from underneath us! */
4874 if (result == ISC_R_FILENOTFOUND &&
4875 zone->masterfile != NULL)
4876 zone_needdump(zone, DNS_DUMP_DELAY);
4877 else if (result != ISC_R_SUCCESS)
4878 dns_zone_log(zone, ISC_LOG_ERROR,
4879 "transfer: could not set file "
4880 "modification time of '%s': %s",
4881 zone->masterfile,
4882 dns_result_totext(result));
4885 break;
4887 case DNS_R_BADIXFR:
4888 /* Force retry with AXFR. */
4889 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
4890 goto same_master;
4892 default:
4893 zone->curmaster++;
4894 same_master:
4895 if (zone->curmaster >= zone->masterscnt)
4896 zone->curmaster = 0;
4897 else {
4898 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
4899 again = ISC_TRUE;
4901 break;
4903 zone_settimer(zone, &now);
4906 * If creating the transfer object failed, zone->xfr is NULL.
4907 * Otherwise, we are called as the done callback of a zone
4908 * transfer object that just entered its shutting-down
4909 * state. Since we are no longer responsible for shutting
4910 * it down, we can detach our reference.
4912 if (zone->xfr != NULL)
4913 dns_xfrin_detach(&zone->xfr);
4916 * This transfer finishing freed up a transfer quota slot.
4917 * Let any other zones waiting for quota have it.
4919 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
4920 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
4921 zone->statelist = NULL;
4922 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
4923 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
4926 * Retry with a different server if necessary.
4928 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
4929 queue_soa_query(zone);
4931 INSIST(zone->irefs > 0);
4932 zone->irefs--;
4933 free_needed = exit_check(zone);
4934 UNLOCK_ZONE(zone);
4935 if (free_needed)
4936 zone_free(zone);
4939 static void
4940 zone_loaddone(void *arg, isc_result_t result) {
4941 static char me[] = "zone_loaddone";
4942 dns_load_t *load = arg;
4943 dns_zone_t *zone;
4944 isc_result_t tresult;
4946 REQUIRE(DNS_LOAD_VALID(load));
4947 zone = load->zone;
4949 ENTER;
4951 tresult = dns_db_endload(load->db, &load->callbacks.add_private);
4952 if (tresult != ISC_R_SUCCESS &&
4953 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
4954 result = tresult;
4956 LOCK_ZONE(load->zone);
4957 (void)zone_postload(load->zone, load->db, load->loadtime, result);
4958 zonemgr_putio(&load->zone->readio);
4959 DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
4960 UNLOCK_ZONE(load->zone);
4962 load->magic = 0;
4963 dns_db_detach(&load->db);
4964 if (load->zone->lctx != NULL)
4965 dns_loadctx_detach(&load->zone->lctx);
4966 dns_zone_idetach(&load->zone);
4967 isc_mem_putanddetach(&load->mctx, load, sizeof (*load));
4970 void
4971 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
4972 REQUIRE(DNS_ZONE_VALID(zone));
4973 REQUIRE(table != NULL);
4974 REQUIRE(*table == NULL);
4976 LOCK_ZONE(zone);
4977 if (zone->ssutable != NULL)
4978 dns_ssutable_attach(zone->ssutable, table);
4979 UNLOCK_ZONE(zone);
4982 void
4983 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
4984 REQUIRE(DNS_ZONE_VALID(zone));
4986 LOCK_ZONE(zone);
4987 if (zone->ssutable != NULL)
4988 dns_ssutable_detach(&zone->ssutable);
4989 if (table != NULL)
4990 dns_ssutable_attach(table, &zone->ssutable);
4991 UNLOCK_ZONE(zone);
4994 void
4995 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
4996 REQUIRE(DNS_ZONE_VALID(zone));
4998 zone->sigvalidityinterval = interval;
5001 isc_uint32_t
5002 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
5003 REQUIRE(DNS_ZONE_VALID(zone));
5005 return (zone->sigvalidityinterval);
5008 static void
5009 queue_xfrin(dns_zone_t *zone) {
5010 const char me[] = "queue_xfrin";
5011 isc_result_t result;
5012 dns_zonemgr_t *zmgr = zone->zmgr;
5014 ENTER;
5016 INSIST(zone->statelist == NULL);
5018 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5019 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
5020 LOCK_ZONE(zone);
5021 zone->irefs++;
5022 UNLOCK_ZONE(zone);
5023 zone->statelist = &zmgr->waiting_for_xfrin;
5024 result = zmgr_start_xfrin_ifquota(zmgr, zone);
5025 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5027 if (result == ISC_R_QUOTA) {
5028 dns_zone_log(zone, ISC_LOG_DEBUG(1),
5029 "zone transfer deferred due to quota");
5030 } else if (result != ISC_R_SUCCESS) {
5031 dns_zone_log(zone, ISC_LOG_ERROR,
5032 "starting zone transfer: %s",
5033 isc_result_totext(result));
5038 * This event callback is called when a zone has received
5039 * any necessary zone transfer quota. This is the time
5040 * to go ahead and start the transfer.
5042 static void
5043 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
5044 isc_result_t result;
5045 dns_peer_t *peer = NULL;
5046 dns_tsigkey_t *tsigkey = NULL;
5047 char mastertext[256];
5048 dns_rdatatype_t xfrtype;
5049 dns_zone_t *zone = event->ev_arg;
5050 isc_netaddr_t masterip;
5052 UNUSED(task);
5054 INSIST(task == zone->task);
5056 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
5057 result = ISC_R_CANCELED;
5058 goto cleanup;
5061 isc_sockaddr_format(&zone->masteraddr, mastertext, sizeof(mastertext));
5063 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
5064 (void)dns_peerlist_peerbyaddr(zone->view->peers,
5065 &masterip, &peer);
5068 * Decide whether we should request IXFR or AXFR.
5070 if (zone->db == NULL) {
5071 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5072 "no database exists yet, "
5073 "requesting AXFR of "
5074 "initial version from %s", mastertext);
5075 xfrtype = dns_rdatatype_axfr;
5076 } else if (dns_zone_isforced(zone)) {
5077 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5078 "forced reload, requesting AXFR of "
5079 "initial version from %s", mastertext);
5080 xfrtype = dns_rdatatype_axfr;
5081 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
5082 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5083 "retrying with AXFR from %s due to "
5084 "previous IXFR failure", mastertext);
5085 xfrtype = dns_rdatatype_axfr;
5086 LOCK_ZONE(zone);
5087 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
5088 UNLOCK_ZONE(zone);
5089 } else {
5090 isc_boolean_t use_ixfr = ISC_TRUE;
5091 if (peer != NULL &&
5092 dns_peer_getrequestixfr(peer, &use_ixfr) ==
5093 ISC_R_SUCCESS) {
5094 ; /* Using peer setting */
5095 } else {
5096 use_ixfr = zone->view->requestixfr;
5098 if (use_ixfr == ISC_FALSE) {
5099 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5100 "IXFR disabled, "
5101 "requesting AXFR from %s",
5102 mastertext);
5103 xfrtype = dns_rdatatype_axfr;
5104 } else {
5105 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5106 "requesting IXFR from %s",
5107 mastertext);
5108 xfrtype = dns_rdatatype_ixfr;
5113 * Determine if we should attempt to sign the request with TSIG.
5115 result = ISC_R_NOTFOUND;
5117 * First, look for a tsig key in the master statement, then
5118 * try for a server key.
5120 if ((zone->masterkeynames != NULL) &&
5121 (zone->masterkeynames[zone->curmaster] != NULL)) {
5122 dns_view_t *view = dns_zone_getview(zone);
5123 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
5124 result = dns_view_gettsig(view, keyname, &tsigkey);
5126 if (tsigkey == NULL)
5127 result = dns_view_getpeertsig(zone->view, &masterip, &tsigkey);
5129 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
5130 dns_zone_log(zone, ISC_LOG_ERROR,
5131 "could not get TSIG key "
5132 "for zone transfer: %s",
5133 isc_result_totext(result));
5136 result = dns_xfrin_create(zone, xfrtype, &zone->masteraddr,
5137 tsigkey, zone->mctx,
5138 zone->zmgr->timermgr, zone->zmgr->socketmgr,
5139 zone->task, zone_xfrdone, &zone->xfr);
5140 cleanup:
5142 * Any failure in this function is handled like a failed
5143 * zone transfer. This ensures that we get removed from
5144 * zmgr->xfrin_in_progress.
5146 if (result != ISC_R_SUCCESS)
5147 zone_xfrdone(zone, result);
5149 if (tsigkey != NULL)
5150 dns_tsigkey_detach(&tsigkey);
5152 isc_event_free(&event);
5156 * Update forwarding support.
5159 static void
5160 forward_destroy(dns_forward_t *forward) {
5162 forward->magic = 0;
5163 if (forward->request != NULL)
5164 dns_request_destroy(&forward->request);
5165 if (forward->msgbuf != NULL)
5166 isc_buffer_free(&forward->msgbuf);
5167 if (forward->zone != NULL)
5168 dns_zone_idetach(&forward->zone);
5169 isc_mem_putanddetach(&forward->mctx, forward, sizeof (*forward));
5172 static isc_result_t
5173 sendtomaster(dns_forward_t *forward) {
5174 isc_result_t result;
5175 isc_sockaddr_t src;
5177 LOCK_ZONE(forward->zone);
5178 if (forward->which >= forward->zone->masterscnt) {
5179 UNLOCK_ZONE(forward->zone);
5180 return (ISC_R_NOMORE);
5183 forward->addr = forward->zone->masters[forward->which];
5185 * Always use TCP regardless of whether the original update
5186 * used TCP.
5187 * XXX The timeout may but a bit small if we are far down a
5188 * transfer graph and the master has to try several masters.
5190 switch (isc_sockaddr_pf(&forward->addr)) {
5191 case PF_INET:
5192 src = forward->zone->xfrsource4;
5193 break;
5194 case PF_INET6:
5195 src = forward->zone->xfrsource6;
5196 break;
5197 default:
5198 result = ISC_R_NOTIMPLEMENTED;
5199 goto unlock;
5201 result = dns_request_createraw(forward->zone->view->requestmgr,
5202 forward->msgbuf,
5203 &src, &forward->addr,
5204 DNS_REQUESTOPT_TCP, 15 /* XXX */,
5205 forward->zone->task,
5206 forward_callback, forward,
5207 &forward->request);
5208 unlock:
5209 UNLOCK_ZONE(forward->zone);
5210 return (result);
5213 static void
5214 forward_callback(isc_task_t *task, isc_event_t *event) {
5215 const char me[] = "forward_callback";
5216 dns_requestevent_t *revent = (dns_requestevent_t *)event;
5217 dns_message_t *msg = NULL;
5218 char master[ISC_SOCKADDR_FORMATSIZE];
5219 isc_result_t result;
5220 dns_forward_t *forward;
5221 dns_zone_t *zone;
5223 UNUSED(task);
5225 forward = revent->ev_arg;
5226 INSIST(DNS_FORWARD_VALID(forward));
5227 zone = forward->zone;
5228 INSIST(DNS_ZONE_VALID(zone));
5230 ENTER;
5232 isc_sockaddr_format(&forward->addr, master, sizeof(master));
5234 if (revent->result != ISC_R_SUCCESS) {
5235 dns_zone_log(zone, ISC_LOG_INFO,
5236 "could not forward dynamic update to %s: %s",
5237 master, dns_result_totext(revent->result));
5238 goto next_master;
5241 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
5242 if (result != ISC_R_SUCCESS)
5243 goto next_master;
5245 result = dns_request_getresponse(revent->request, msg,
5246 DNS_MESSAGEPARSE_PRESERVEORDER |
5247 DNS_MESSAGEPARSE_CLONEBUFFER);
5248 if (result != ISC_R_SUCCESS)
5249 goto next_master;
5251 switch (msg->rcode) {
5253 * Pass these rcodes back to client.
5255 case dns_rcode_noerror:
5256 case dns_rcode_yxdomain:
5257 case dns_rcode_yxrrset:
5258 case dns_rcode_nxrrset:
5259 case dns_rcode_refused:
5260 case dns_rcode_nxdomain:
5261 break;
5263 /* These should not occur if the masters/zone are valid. */
5264 case dns_rcode_notzone:
5265 case dns_rcode_notauth: {
5266 char rcode[128];
5267 isc_buffer_t rb;
5269 isc_buffer_init(&rb, rcode, sizeof(rcode));
5270 dns_rcode_totext(msg->rcode, &rb);
5271 dns_zone_log(zone, ISC_LOG_WARNING,
5272 "forwarding dynamic update: "
5273 "unexpected response: master %s returned: %.*s",
5274 master, (int)rb.used, rcode);
5275 goto next_master;
5278 /* Try another server for these rcodes. */
5279 case dns_rcode_formerr:
5280 case dns_rcode_servfail:
5281 case dns_rcode_notimp:
5282 case dns_rcode_badvers:
5283 default:
5284 goto next_master;
5287 /* call callback */
5288 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
5289 msg = NULL;
5290 dns_request_destroy(&forward->request);
5291 forward_destroy(forward);
5292 isc_event_free(&event);
5293 return;
5295 next_master:
5296 if (msg != NULL)
5297 dns_message_destroy(&msg);
5298 isc_event_free(&event);
5299 forward->which++;
5300 dns_request_destroy(&forward->request);
5301 result = sendtomaster(forward);
5302 if (result != ISC_R_SUCCESS) {
5303 /* call callback */
5304 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5305 "exhausted dynamic update forwarder list");
5306 (forward->callback)(forward->callback_arg, result, NULL);
5307 forward_destroy(forward);
5311 isc_result_t
5312 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
5313 dns_updatecallback_t callback, void *callback_arg)
5315 dns_forward_t *forward;
5316 isc_result_t result;
5317 isc_region_t *mr;
5319 REQUIRE(DNS_ZONE_VALID(zone));
5320 REQUIRE(msg != NULL);
5321 REQUIRE(callback != NULL);
5323 forward = isc_mem_get(zone->mctx, sizeof(*forward));
5324 if (forward == NULL)
5325 return (ISC_R_NOMEMORY);
5327 forward->request = NULL;
5328 forward->zone = NULL;
5329 forward->msgbuf = NULL;
5330 forward->which = 0;
5331 forward->mctx = 0;
5332 forward->callback = callback;
5333 forward->callback_arg = callback_arg;
5334 forward->magic = FORWARD_MAGIC;
5336 mr = dns_message_getrawmessage(msg);
5337 if (mr == NULL) {
5338 result = ISC_R_UNEXPECTEDEND;
5339 goto cleanup;
5342 result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
5343 if (result != ISC_R_SUCCESS)
5344 goto cleanup;
5345 result = isc_buffer_copyregion(forward->msgbuf, mr);
5346 if (result != ISC_R_SUCCESS)
5347 goto cleanup;
5349 isc_mem_attach(zone->mctx, &forward->mctx);
5350 dns_zone_iattach(zone, &forward->zone);
5351 result = sendtomaster(forward);
5353 cleanup:
5354 if (result != ISC_R_SUCCESS) {
5355 forward_destroy(forward);
5357 return (result);
5360 isc_result_t
5361 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
5362 REQUIRE(DNS_ZONE_VALID(zone));
5363 REQUIRE(next != NULL && *next == NULL);
5365 *next = ISC_LIST_NEXT(zone, link);
5366 if (*next == NULL)
5367 return (ISC_R_NOMORE);
5368 else
5369 return (ISC_R_SUCCESS);
5372 isc_result_t
5373 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
5374 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5375 REQUIRE(first != NULL && *first == NULL);
5377 *first = ISC_LIST_HEAD(zmgr->zones);
5378 if (*first == NULL)
5379 return (ISC_R_NOMORE);
5380 else
5381 return (ISC_R_SUCCESS);
5384 /***
5385 *** Zone manager.
5386 ***/
5388 isc_result_t
5389 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
5390 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
5391 dns_zonemgr_t **zmgrp)
5393 dns_zonemgr_t *zmgr;
5394 isc_result_t result;
5395 isc_interval_t interval;
5397 zmgr = isc_mem_get(mctx, sizeof *zmgr);
5398 if (zmgr == NULL)
5399 return (ISC_R_NOMEMORY);
5400 zmgr->mctx = NULL;
5401 zmgr->refs = 1;
5402 isc_mem_attach(mctx, &zmgr->mctx);
5403 zmgr->taskmgr = taskmgr;
5404 zmgr->timermgr = timermgr;
5405 zmgr->socketmgr = socketmgr;
5406 zmgr->zonetasks = NULL;
5407 zmgr->task = NULL;
5408 zmgr->rl = NULL;
5409 ISC_LIST_INIT(zmgr->zones);
5410 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
5411 ISC_LIST_INIT(zmgr->xfrin_in_progress);
5412 result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
5413 if (result != ISC_R_SUCCESS) {
5414 UNEXPECTED_ERROR(__FILE__, __LINE__,
5415 "isc_rwlock_init() failed: %s",
5416 isc_result_totext(result));
5417 result = ISC_R_UNEXPECTED;
5418 goto free_mem;
5420 zmgr->transfersin = 10;
5421 zmgr->transfersperns = 2;
5423 /* Create the zone task pool. */
5424 result = isc_taskpool_create(taskmgr, mctx,
5425 8 /* XXX */, 2, &zmgr->zonetasks);
5426 if (result != ISC_R_SUCCESS)
5427 goto free_rwlock;
5429 /* Create a single task for queueing of SOA queries. */
5430 result = isc_task_create(taskmgr, 1, &zmgr->task);
5431 if (result != ISC_R_SUCCESS)
5432 goto free_taskpool;
5433 isc_task_setname(zmgr->task, "zmgr", zmgr);
5434 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
5435 &zmgr->rl);
5436 if (result != ISC_R_SUCCESS)
5437 goto free_task;
5438 /* default to 20 refresh queries / notifies per second. */
5439 isc_interval_set(&interval, 0, 1000000000/2);
5440 result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
5441 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5442 isc_ratelimiter_setpertic(zmgr->rl, 10);
5444 zmgr->iolimit = 1;
5445 zmgr->ioactive = 0;
5446 ISC_LIST_INIT(zmgr->high);
5447 ISC_LIST_INIT(zmgr->low);
5449 result = isc_mutex_init(&zmgr->iolock);
5450 if (result != ISC_R_SUCCESS) {
5451 UNEXPECTED_ERROR(__FILE__, __LINE__,
5452 "isc_mutex_init() failed: %s",
5453 isc_result_totext(result));
5454 goto free_rl;
5456 zmgr->magic = ZONEMGR_MAGIC;
5458 *zmgrp = zmgr;
5459 return (ISC_R_SUCCESS);
5461 #if 0
5462 free_iolock:
5463 DESTROYLOCK(&zmgr->iolock);
5464 #endif
5465 free_rl:
5466 isc_ratelimiter_detach(&zmgr->rl);
5467 free_task:
5468 isc_task_detach(&zmgr->task);
5469 free_taskpool:
5470 isc_taskpool_destroy(&zmgr->zonetasks);
5471 free_rwlock:
5472 isc_rwlock_destroy(&zmgr->rwlock);
5473 free_mem:
5474 isc_mem_put(zmgr->mctx, zmgr, sizeof *zmgr);
5475 isc_mem_detach(&mctx);
5476 return (result);
5479 isc_result_t
5480 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
5481 isc_result_t result;
5483 REQUIRE(DNS_ZONE_VALID(zone));
5484 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5486 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5487 LOCK_ZONE(zone);
5488 REQUIRE(zone->task == NULL);
5489 REQUIRE(zone->timer == NULL);
5490 REQUIRE(zone->zmgr == NULL);
5492 isc_taskpool_gettask(zmgr->zonetasks,
5493 dns_name_hash(dns_zone_getorigin(zone),
5494 ISC_FALSE),
5495 &zone->task);
5498 * Set the task name. The tag will arbitrarily point to one
5499 * of the zones sharing the task (in practice, the one
5500 * to be managed last).
5502 isc_task_setname(zone->task, "zone", zone);
5504 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
5505 NULL, NULL,
5506 zone->task, zone_timer, zone,
5507 &zone->timer);
5508 if (result != ISC_R_SUCCESS)
5509 goto cleanup_task;
5511 * The timer "holds" a iref.
5513 zone->irefs++;
5514 INSIST(zone->irefs != 0);
5516 ISC_LIST_APPEND(zmgr->zones, zone, link);
5517 zone->zmgr = zmgr;
5518 zmgr->refs++;
5520 goto unlock;
5522 cleanup_task:
5523 isc_task_detach(&zone->task);
5525 unlock:
5526 UNLOCK_ZONE(zone);
5527 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5528 return (result);
5531 void
5532 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
5533 isc_boolean_t free_now = ISC_FALSE;
5535 REQUIRE(DNS_ZONE_VALID(zone));
5536 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5537 REQUIRE(zone->zmgr == zmgr);
5539 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5540 LOCK_ZONE(zone);
5542 ISC_LIST_UNLINK(zmgr->zones, zone, link);
5543 zone->zmgr = NULL;
5544 zmgr->refs--;
5545 if (zmgr->refs == 0)
5546 free_now = ISC_TRUE;
5548 UNLOCK_ZONE(zone);
5549 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5551 if (free_now)
5552 zonemgr_free(zmgr);
5553 ENSURE(zone->zmgr == NULL);
5556 void
5557 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
5558 REQUIRE(DNS_ZONEMGR_VALID(source));
5559 REQUIRE(target != NULL && *target == NULL);
5561 RWLOCK(&source->rwlock, isc_rwlocktype_write);
5562 REQUIRE(source->refs > 0);
5563 source->refs++;
5564 INSIST(source->refs > 0);
5565 RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
5566 *target = source;
5569 void
5570 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
5571 dns_zonemgr_t *zmgr;
5572 isc_boolean_t free_now = ISC_FALSE;
5574 REQUIRE(zmgrp != NULL);
5575 zmgr = *zmgrp;
5576 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5578 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5579 zmgr->refs--;
5580 if (zmgr->refs == 0)
5581 free_now = ISC_TRUE;
5582 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5584 if (free_now)
5585 zonemgr_free(zmgr);
5588 isc_result_t
5589 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
5590 dns_zone_t *p;
5592 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5594 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
5595 for (p = ISC_LIST_HEAD(zmgr->zones);
5596 p != NULL;
5597 p = ISC_LIST_NEXT(p, link))
5599 dns_zone_maintenance(p);
5601 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
5604 * Recent configuration changes may have increased the
5605 * amount of available transfers quota. Make sure any
5606 * transfers currently blocked on quota get started if
5607 * possible.
5609 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5610 zmgr_resume_xfrs(zmgr, ISC_TRUE);
5611 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5612 return (ISC_R_SUCCESS);
5615 void
5616 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
5617 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5619 isc_ratelimiter_shutdown(zmgr->rl);
5621 if (zmgr->task != NULL)
5622 isc_task_destroy(&zmgr->task);
5623 if (zmgr->zonetasks != NULL)
5624 isc_taskpool_destroy(&zmgr->zonetasks);
5627 static void
5628 zonemgr_free(dns_zonemgr_t *zmgr) {
5629 isc_mem_t *mctx;
5631 INSIST(zmgr->refs == 0);
5632 INSIST(ISC_LIST_EMPTY(zmgr->zones));
5634 zmgr->magic = 0;
5636 DESTROYLOCK(&zmgr->iolock);
5637 isc_ratelimiter_detach(&zmgr->rl);
5639 isc_rwlock_destroy(&zmgr->rwlock);
5640 mctx = zmgr->mctx;
5641 isc_mem_put(zmgr->mctx, zmgr, sizeof *zmgr);
5642 isc_mem_detach(&mctx);
5645 void
5646 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
5647 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5649 zmgr->transfersin = value;
5652 isc_uint32_t
5653 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
5654 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5656 return (zmgr->transfersin);
5659 void
5660 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
5661 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5663 zmgr->transfersperns = value;
5666 isc_uint32_t
5667 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
5668 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5670 return (zmgr->transfersperns);
5674 * Try to start a new incoming zone transfer to fill a quota
5675 * slot that was just vacated.
5677 * Requires:
5678 * The zone manager is locked by the caller.
5680 static void
5681 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
5682 dns_zone_t *zone;
5683 dns_zone_t *next;
5685 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
5686 zone != NULL;
5687 zone = next)
5689 isc_result_t result;
5690 next = ISC_LIST_NEXT(zone, statelink);
5691 result = zmgr_start_xfrin_ifquota(zmgr, zone);
5692 if (result == ISC_R_SUCCESS) {
5693 if (multi)
5694 continue;
5696 * We successfully filled the slot. We're done.
5698 break;
5699 } else if (result == ISC_R_QUOTA) {
5701 * Not enough quota. This is probably the per-server
5702 * quota, because we usually get called when a unit of
5703 * global quota has just been freed. Try the next
5704 * zone, it may succeed if it uses another master.
5706 continue;
5707 } else {
5708 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5709 "starting zone transfer: %s",
5710 isc_result_totext(result));
5711 break;
5717 * Try to start an incoming zone transfer for 'zone', quota permitting.
5719 * Requires:
5720 * The zone manager is locked by the caller.
5722 * Returns:
5723 * ISC_R_SUCCESS There was enough quota and we attempted to
5724 * start a transfer. zone_xfrdone() has been or will
5725 * be called.
5726 * ISC_R_QUOTA Not enough quota.
5727 * Others Failure.
5729 static isc_result_t
5730 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
5731 dns_peer_t *peer = NULL;
5732 isc_netaddr_t masterip;
5733 isc_uint32_t nxfrsin, nxfrsperns;
5734 dns_zone_t *x;
5735 isc_uint32_t maxtransfersin, maxtransfersperns;
5736 isc_event_t *e;
5739 * Find any configured information about the server we'd
5740 * like to transfer this zone from.
5742 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
5743 (void)dns_peerlist_peerbyaddr(zone->view->peers,
5744 &masterip, &peer);
5747 * Determine the total maximum number of simultaneous
5748 * transfers allowed, and the maximum for this specific
5749 * master.
5751 maxtransfersin = zmgr->transfersin;
5752 maxtransfersperns = zmgr->transfersperns;
5753 if (peer != NULL)
5754 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
5757 * Count the total number of transfers that are in progress,
5758 * and the number of transfers in progress from this master.
5759 * We linearly scan a list of all transfers; if this turns
5760 * out to be too slow, we could hash on the master address.
5762 nxfrsin = nxfrsperns = 0;
5763 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
5764 x != NULL;
5765 x = ISC_LIST_NEXT(x, statelink))
5767 isc_netaddr_t xip;
5768 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
5769 nxfrsin++;
5770 if (isc_netaddr_equal(&xip, &masterip))
5771 nxfrsperns++;
5774 /* Enforce quota. */
5775 if (nxfrsin >= maxtransfersin)
5776 return (ISC_R_QUOTA);
5778 if (nxfrsperns >= maxtransfersperns)
5779 return (ISC_R_QUOTA);
5782 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
5783 * list and send it an event to let it start the actual transfer in the
5784 * context of its own task.
5786 e = isc_event_allocate(zmgr->mctx, zmgr,
5787 DNS_EVENT_ZONESTARTXFRIN,
5788 got_transfer_quota, zone,
5789 sizeof(isc_event_t));
5790 if (e == NULL)
5791 return (ISC_R_NOMEMORY);
5793 LOCK_ZONE(zone);
5794 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
5795 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
5796 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
5797 zone->statelist = &zmgr->xfrin_in_progress;
5798 isc_task_send(zone->task, &e);
5799 UNLOCK_ZONE(zone);
5801 return (ISC_R_SUCCESS);
5804 void
5805 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
5807 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5808 REQUIRE(iolimit > 0);
5810 zmgr->iolimit = iolimit;
5813 isc_uint32_t
5814 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
5816 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5818 return (zmgr->iolimit);
5822 * Get permission to request a file handle from the OS.
5823 * An event will be sent to action when one is available.
5824 * There are two queues available (high and low), the high
5825 * queue will be serviced before the low one.
5827 * zonemgr_putio() must be called after the event is delivered to
5828 * 'action'.
5831 static isc_result_t
5832 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
5833 isc_task_t *task, isc_taskaction_t action, void *arg,
5834 dns_io_t **iop)
5836 dns_io_t *io;
5837 isc_boolean_t queue;
5839 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5840 REQUIRE(iop != NULL && *iop == NULL);
5842 io = isc_mem_get(zmgr->mctx, sizeof(*io));
5843 if (io == NULL)
5844 return (ISC_R_NOMEMORY);
5845 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
5846 action, arg, sizeof(*io->event));
5847 if (io->event == NULL) {
5848 isc_mem_put(zmgr->mctx, io, sizeof(*io));
5849 return (ISC_R_NOMEMORY);
5851 io->zmgr = zmgr;
5852 io->high = high;
5853 io->task = NULL;
5854 isc_task_attach(task, &io->task);
5855 ISC_LINK_INIT(io, link);
5856 io->magic = IO_MAGIC;
5858 LOCK(&zmgr->iolock);
5859 zmgr->ioactive++;
5860 queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
5861 if (queue) {
5862 if (io->high)
5863 ISC_LIST_APPEND(zmgr->high, io, link);
5864 else
5865 ISC_LIST_APPEND(zmgr->low, io, link);
5867 UNLOCK(&zmgr->iolock);
5868 *iop = io;
5870 if (!queue) {
5871 isc_task_send(io->task, &io->event);
5873 return (ISC_R_SUCCESS);
5876 static void
5877 zonemgr_putio(dns_io_t **iop) {
5878 dns_io_t *io;
5879 dns_io_t *next;
5880 dns_zonemgr_t *zmgr;
5882 REQUIRE(iop != NULL);
5883 io = *iop;
5884 REQUIRE(DNS_IO_VALID(io));
5886 *iop = NULL;
5888 INSIST(!ISC_LINK_LINKED(io, link));
5889 INSIST(io->event == NULL);
5891 zmgr = io->zmgr;
5892 isc_task_detach(&io->task);
5893 io->magic = 0;
5894 isc_mem_put(zmgr->mctx, io, sizeof(*io));
5896 LOCK(&zmgr->iolock);
5897 INSIST(zmgr->ioactive > 0);
5898 zmgr->ioactive--;
5899 next = HEAD(zmgr->high);
5900 if (next == NULL)
5901 next = HEAD(zmgr->low);
5902 if (next != NULL) {
5903 if (next->high)
5904 ISC_LIST_UNLINK(zmgr->high, next, link);
5905 else
5906 ISC_LIST_UNLINK(zmgr->low, next, link);
5907 INSIST(next->event != NULL);
5909 UNLOCK(&zmgr->iolock);
5910 if (next != NULL)
5911 isc_task_send(next->task, &next->event);
5914 static void
5915 zonemgr_cancelio(dns_io_t *io) {
5916 isc_boolean_t send_event = ISC_FALSE;
5918 REQUIRE(DNS_IO_VALID(io));
5921 * If we are queued to be run then dequeue.
5923 LOCK(&io->zmgr->iolock);
5924 if (ISC_LINK_LINKED(io, link)) {
5925 if (io->high)
5926 ISC_LIST_UNLINK(io->zmgr->high, io, link);
5927 else
5928 ISC_LIST_UNLINK(io->zmgr->low, io, link);
5930 send_event = ISC_TRUE;
5931 INSIST(io->event != NULL);
5933 UNLOCK(&io->zmgr->iolock);
5934 if (send_event) {
5935 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
5936 isc_task_send(io->task, &io->event);
5940 static void
5941 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
5942 char *buf;
5943 int buflen;
5944 isc_result_t result;
5946 buflen = strlen(path) + strlen(templat) + 2;
5948 buf = isc_mem_get(zone->mctx, buflen);
5949 if (buf == NULL)
5950 return;
5952 result = isc_file_template(path, templat, buf, buflen);
5953 if (result != ISC_R_SUCCESS)
5954 goto cleanup;
5956 result = isc_file_renameunique(path, buf);
5957 if (result != ISC_R_SUCCESS)
5958 goto cleanup;
5960 dns_zone_log(zone, ISC_LOG_INFO, "saved '%s' as '%s'",
5961 path, buf);
5963 cleanup:
5964 isc_mem_put(zone->mctx, buf, buflen);
5967 #if 0
5968 /* Hook for ondestroy notifcation from a database. */
5970 static void
5971 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
5972 dns_db_t *db = event->sender;
5973 UNUSED(task);
5975 isc_event_free(&event);
5977 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5978 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
5979 "database (%p) destroyed", (void*) db);
5981 #endif
5983 void
5984 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
5985 isc_interval_t interval;
5986 isc_uint32_t s, ns;
5987 isc_uint32_t pertic;
5988 isc_result_t result;
5990 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5992 if (value == 0)
5993 value = 1;
5995 if (value == 1) {
5996 s = 1;
5997 ns = 0;
5998 pertic = 1;
5999 } else if (value <= 10) {
6000 s = 0;
6001 ns = 1000000000 / value;
6002 pertic = 1;
6003 } else {
6004 s = 0;
6005 ns = (1000000000 / value) * 10;
6006 pertic = 10;
6009 isc_interval_set(&interval, s, ns);
6010 result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
6011 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6012 isc_ratelimiter_setpertic(zmgr->rl, pertic);
6014 zmgr->serialqueryrate = value;
6017 unsigned int
6018 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
6019 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6021 return (zmgr->serialqueryrate);
6024 void
6025 dns_zone_forcereload(dns_zone_t *zone) {
6026 REQUIRE(DNS_ZONE_VALID(zone));
6028 LOCK_ZONE(zone);
6029 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
6030 UNLOCK_ZONE(zone);
6031 dns_zone_refresh(zone);
6034 isc_boolean_t
6035 dns_zone_isforced(dns_zone_t *zone) {
6036 REQUIRE(DNS_ZONE_VALID(zone));
6038 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
6041 isc_result_t
6042 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
6043 isc_result_t result = ISC_R_SUCCESS;
6045 LOCK_ZONE(zone);
6046 if (on) {
6047 if (zone->counters != NULL)
6048 goto done;
6049 result = dns_stats_alloccounters(zone->mctx, &zone->counters);
6050 } else {
6051 if (zone->counters == NULL)
6052 goto done;
6053 dns_stats_freecounters(zone->mctx, &zone->counters);
6055 done:
6056 UNLOCK_ZONE(zone);
6057 return (result);
6060 isc_uint64_t *
6061 dns_zone_getstatscounters(dns_zone_t *zone) {
6062 return (zone->counters);
6065 void
6066 dns_zone_dialup(dns_zone_t *zone) {
6068 REQUIRE(DNS_ZONE_VALID(zone));
6070 zone_debuglog(zone, "dns_zone_dialup", 3,
6071 "notify = %d, refresh = %d",
6072 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
6073 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
6075 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
6076 dns_zone_notify(zone);
6077 if (zone->type != dns_zone_master &&
6078 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
6079 dns_zone_refresh(zone);
6082 void
6083 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
6084 REQUIRE(DNS_ZONE_VALID(zone));
6086 LOCK_ZONE(zone);
6087 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
6088 DNS_ZONEFLG_DIALREFRESH |
6089 DNS_ZONEFLG_NOREFRESH);
6090 switch (dialup) {
6091 case dns_dialuptype_no:
6092 break;
6093 case dns_dialuptype_yes:
6094 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
6095 DNS_ZONEFLG_DIALREFRESH |
6096 DNS_ZONEFLG_NOREFRESH));
6097 break;
6098 case dns_dialuptype_notify:
6099 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
6100 break;
6101 case dns_dialuptype_notifypassive:
6102 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
6103 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
6104 break;
6105 case dns_dialuptype_refresh:
6106 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
6107 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
6108 break;
6109 case dns_dialuptype_passive:
6110 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
6111 break;
6112 default:
6113 INSIST(0);
6115 UNLOCK_ZONE(zone);
6118 unsigned int
6119 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
6120 dns_zone_t *zone;
6121 unsigned int count = 0;
6123 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6125 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
6126 switch (state) {
6127 case DNS_ZONESTATE_XFERRUNNING:
6128 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
6129 zone != NULL;
6130 zone = ISC_LIST_NEXT(zone, statelink))
6131 count++;
6132 break;
6133 case DNS_ZONESTATE_XFERDEFERRED:
6134 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
6135 zone != NULL;
6136 zone = ISC_LIST_NEXT(zone, statelink))
6137 count++;
6138 break;
6139 case DNS_ZONESTATE_SOAQUERY:
6140 for (zone = ISC_LIST_HEAD(zmgr->zones);
6141 zone != NULL;
6142 zone = ISC_LIST_NEXT(zone, link))
6143 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
6144 count++;
6145 break;
6146 case DNS_ZONESTATE_ANY:
6147 for (zone = ISC_LIST_HEAD(zmgr->zones);
6148 zone != NULL;
6149 zone = ISC_LIST_NEXT(zone, link))
6150 count++;
6151 break;
6152 default:
6153 INSIST(0);
6156 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
6158 return (count);