Import bind-9.3.4
[dragonfly.git] / contrib / bind-9.3 / lib / dns / zone.c
blobd2a47b072b2fd672882ab78aadab461480251010
1 /*
2 * Copyright (C) 2004-2006 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.23.2.65 2006/07/19 01:04:24 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/rdatatype.h>
52 #include <dns/request.h>
53 #include <dns/resolver.h>
54 #include <dns/result.h>
55 #include <dns/stats.h>
56 #include <dns/ssu.h>
57 #include <dns/tsig.h>
58 #include <dns/xfrin.h>
59 #include <dns/zone.h>
61 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
62 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
64 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
65 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
67 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
68 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
70 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
71 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
73 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
74 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
76 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
77 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
79 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
80 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
83 * Ensure 'a' is at least 'min' but not more than 'max'.
85 #define RANGE(a, min, max) \
86 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
89 * Default values.
91 #define DNS_DEFAULT_IDLEIN 3600 /* 1 hour */
92 #define DNS_DEFAULT_IDLEOUT 3600 /* 1 hour */
93 #define MAX_XFER_TIME (2*3600) /* Documented default is 2 hours */
95 #ifndef DNS_MAX_EXPIRE
96 #define DNS_MAX_EXPIRE 14515200 /* 24 weeks */
97 #endif
99 #ifndef DNS_DUMP_DELAY
100 #define DNS_DUMP_DELAY 900 /* 15 minutes */
101 #endif
103 typedef struct dns_notify dns_notify_t;
104 typedef struct dns_stub dns_stub_t;
105 typedef struct dns_load dns_load_t;
106 typedef struct dns_forward dns_forward_t;
107 typedef struct dns_io dns_io_t;
108 typedef ISC_LIST(dns_io_t) dns_iolist_t;
110 #define DNS_ZONE_CHECKLOCK
111 #ifdef DNS_ZONE_CHECKLOCK
112 #define LOCK_ZONE(z) \
113 do { LOCK(&(z)->lock); \
114 INSIST((z)->locked == ISC_FALSE); \
115 (z)->locked = ISC_TRUE; \
116 } while (0)
117 #define UNLOCK_ZONE(z) \
118 do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
119 #define LOCKED_ZONE(z) ((z)->locked)
120 #else
121 #define LOCK_ZONE(z) LOCK(&(z)->lock)
122 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
123 #define LOCKED_ZONE(z) ISC_TRUE
124 #endif
126 struct dns_zone {
127 /* Unlocked */
128 unsigned int magic;
129 isc_mutex_t lock;
130 #ifdef DNS_ZONE_CHECKLOCK
131 isc_boolean_t locked;
132 #endif
133 isc_mem_t *mctx;
134 isc_refcount_t erefs;
136 /* Locked */
137 dns_db_t *db;
138 dns_zonemgr_t *zmgr;
139 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
140 isc_timer_t *timer;
141 unsigned int irefs;
142 dns_name_t origin;
143 char *masterfile;
144 char *journal;
145 isc_int32_t journalsize;
146 dns_rdataclass_t rdclass;
147 dns_zonetype_t type;
148 unsigned int flags;
149 unsigned int options;
150 unsigned int db_argc;
151 char **db_argv;
152 isc_time_t expiretime;
153 isc_time_t refreshtime;
154 isc_time_t dumptime;
155 isc_time_t loadtime;
156 isc_uint32_t serial;
157 isc_uint32_t refresh;
158 isc_uint32_t retry;
159 isc_uint32_t expire;
160 isc_uint32_t minimum;
161 char *keydirectory;
163 isc_uint32_t maxrefresh;
164 isc_uint32_t minrefresh;
165 isc_uint32_t maxretry;
166 isc_uint32_t minretry;
168 isc_sockaddr_t *masters;
169 dns_name_t **masterkeynames;
170 isc_boolean_t *mastersok;
171 unsigned int masterscnt;
172 unsigned int curmaster;
173 isc_sockaddr_t masteraddr;
174 dns_notifytype_t notifytype;
175 isc_sockaddr_t *notify;
176 unsigned int notifycnt;
177 isc_sockaddr_t notifyfrom;
178 isc_task_t *task;
179 isc_sockaddr_t notifysrc4;
180 isc_sockaddr_t notifysrc6;
181 isc_sockaddr_t xfrsource4;
182 isc_sockaddr_t xfrsource6;
183 isc_sockaddr_t altxfrsource4;
184 isc_sockaddr_t altxfrsource6;
185 isc_sockaddr_t sourceaddr;
186 dns_xfrin_ctx_t *xfr; /* task locked */
187 dns_tsigkey_t *tsigkey; /* key used for xfr */
188 /* Access Control Lists */
189 dns_acl_t *update_acl;
190 dns_acl_t *forward_acl;
191 dns_acl_t *notify_acl;
192 dns_acl_t *query_acl;
193 dns_acl_t *xfr_acl;
194 isc_boolean_t update_disabled;
195 dns_severity_t check_names;
196 ISC_LIST(dns_notify_t) notifies;
197 dns_request_t *request;
198 dns_loadctx_t *lctx;
199 dns_io_t *readio;
200 dns_dumpctx_t *dctx;
201 dns_io_t *writeio;
202 isc_uint32_t maxxfrin;
203 isc_uint32_t maxxfrout;
204 isc_uint32_t idlein;
205 isc_uint32_t idleout;
206 isc_event_t ctlevent;
207 dns_ssutable_t *ssutable;
208 isc_uint32_t sigvalidityinterval;
209 dns_view_t *view;
211 * Zones in certain states such as "waiting for zone transfer"
212 * or "zone transfer in progress" are kept on per-state linked lists
213 * in the zone manager using the 'statelink' field. The 'statelist'
214 * field points at the list the zone is currently on. It the zone
215 * is not on any such list, statelist is NULL.
217 ISC_LINK(dns_zone_t) statelink;
218 dns_zonelist_t *statelist;
220 * Optional per-zone statistics counters (NULL if not present).
222 isc_uint64_t *counters;
225 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
226 #define DNS_ZONE_SETFLAG(z,f) do { \
227 INSIST(LOCKED_ZONE(z)); \
228 (z)->flags |= (f); \
229 } while (0)
230 #define DNS_ZONE_CLRFLAG(z,f) do { \
231 INSIST(LOCKED_ZONE(z)); \
232 (z)->flags &= ~(f); \
233 } while (0)
234 /* XXX MPA these may need to go back into zone.h */
235 #define DNS_ZONEFLG_REFRESH 0x00000001U /* refresh check in progress */
236 #define DNS_ZONEFLG_NEEDDUMP 0x00000002U /* zone need consolidation */
237 #define DNS_ZONEFLG_USEVC 0x00000004U /* use tcp for refresh query */
238 #define DNS_ZONEFLG_DUMPING 0x00000008U /* a dump is in progress */
239 #define DNS_ZONEFLG_HASINCLUDE 0x00000010U /* $INCLUDE in zone file */
240 #define DNS_ZONEFLG_LOADED 0x00000020U /* database has loaded */
241 #define DNS_ZONEFLG_EXITING 0x00000040U /* zone is being destroyed */
242 #define DNS_ZONEFLG_EXPIRED 0x00000080U /* zone has expired */
243 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U /* refresh check needed */
244 #define DNS_ZONEFLG_UPTODATE 0x00000200U /* zone contents are
245 * uptodate */
246 #define DNS_ZONEFLG_NEEDNOTIFY 0x00000400U /* need to send out notify
247 * messages */
248 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U /* generate a journal diff on
249 * reload */
250 #define DNS_ZONEFLG_NOMASTERS 0x00001000U /* an attempt to refresh a
251 * zone with no masters
252 * occured */
253 #define DNS_ZONEFLG_LOADING 0x00002000U /* load from disk in progress*/
254 #define DNS_ZONEFLG_HAVETIMERS 0x00004000U /* timer values have been set
255 * from SOA (if not set, we
256 * are still using
257 * default timer values) */
258 #define DNS_ZONEFLG_FORCEXFER 0x00008000U /* Force a zone xfer */
259 #define DNS_ZONEFLG_NOREFRESH 0x00010000U
260 #define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
261 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
262 #define DNS_ZONEFLG_SHUTDOWN 0x00080000U
263 #define DNS_ZONEFLAG_NOIXFR 0x00100000U /* IXFR failed, force AXFR */
264 #define DNS_ZONEFLG_FLUSH 0x00200000U
265 #define DNS_ZONEFLG_NOEDNS 0x00400000U
266 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
267 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
269 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
271 /* Flags for zone_load() */
272 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
274 struct dns_zonemgr {
275 unsigned int magic;
276 isc_mem_t * mctx;
277 int refs; /* Locked by rwlock */
278 isc_taskmgr_t * taskmgr;
279 isc_timermgr_t * timermgr;
280 isc_socketmgr_t * socketmgr;
281 isc_taskpool_t * zonetasks;
282 isc_task_t * task;
283 isc_ratelimiter_t * rl;
284 isc_rwlock_t rwlock;
285 isc_mutex_t iolock;
287 /* Locked by rwlock. */
288 dns_zonelist_t zones;
289 dns_zonelist_t waiting_for_xfrin;
290 dns_zonelist_t xfrin_in_progress;
292 /* Configuration data. */
293 isc_uint32_t transfersin;
294 isc_uint32_t transfersperns;
295 unsigned int serialqueryrate;
297 /* Locked by iolock */
298 isc_uint32_t iolimit;
299 isc_uint32_t ioactive;
300 dns_iolist_t high;
301 dns_iolist_t low;
305 * Hold notify state.
307 struct dns_notify {
308 unsigned int magic;
309 unsigned int flags;
310 isc_mem_t *mctx;
311 dns_zone_t *zone;
312 dns_adbfind_t *find;
313 dns_request_t *request;
314 dns_name_t ns;
315 isc_sockaddr_t dst;
316 ISC_LINK(dns_notify_t) link;
319 #define DNS_NOTIFY_NOSOA 0x0001U
322 * dns_stub holds state while performing a 'stub' transfer.
323 * 'db' is the zone's 'db' or a new one if this is the initial
324 * transfer.
327 struct dns_stub {
328 unsigned int magic;
329 isc_mem_t *mctx;
330 dns_zone_t *zone;
331 dns_db_t *db;
332 dns_dbversion_t *version;
336 * Hold load state.
338 struct dns_load {
339 unsigned int magic;
340 isc_mem_t *mctx;
341 dns_zone_t *zone;
342 dns_db_t *db;
343 isc_time_t loadtime;
344 dns_rdatacallbacks_t callbacks;
348 * Hold forward state.
350 struct dns_forward {
351 unsigned int magic;
352 isc_mem_t *mctx;
353 dns_zone_t *zone;
354 isc_buffer_t *msgbuf;
355 dns_request_t *request;
356 isc_uint32_t which;
357 isc_sockaddr_t addr;
358 dns_updatecallback_t callback;
359 void *callback_arg;
363 * Hold IO request state.
365 struct dns_io {
366 unsigned int magic;
367 dns_zonemgr_t *zmgr;
368 isc_boolean_t high;
369 isc_task_t *task;
370 ISC_LINK(dns_io_t) link;
371 isc_event_t *event;
374 #define SEND_BUFFER_SIZE 2048
376 static void zone_settimer(dns_zone_t *, isc_time_t *);
377 static void cancel_refresh(dns_zone_t *);
378 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
379 const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
380 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
381 ISC_FORMAT_PRINTF(3, 4);
382 static void queue_xfrin(dns_zone_t *zone);
383 static void zone_unload(dns_zone_t *zone);
384 static void zone_expire(dns_zone_t *zone);
385 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
386 static void zone_idetach(dns_zone_t **zonep);
387 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
388 isc_boolean_t dump);
389 static isc_result_t default_journal(dns_zone_t *zone);
390 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
391 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
392 isc_time_t loadtime, isc_result_t result);
393 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
394 static void zone_shutdown(isc_task_t *, isc_event_t *);
395 static void zone_loaddone(void *arg, isc_result_t result);
396 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
397 isc_time_t loadtime);
399 #if 0
400 /* ondestroy example */
401 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
402 #endif
404 static void refresh_callback(isc_task_t *, isc_event_t *);
405 static void stub_callback(isc_task_t *, isc_event_t *);
406 static void queue_soa_query(dns_zone_t *zone);
407 static void soa_query(isc_task_t *, isc_event_t *);
408 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
409 dns_stub_t *stub);
410 static int message_count(dns_message_t *msg, dns_section_t section,
411 dns_rdatatype_t type);
412 static void notify_cancel(dns_zone_t *zone);
413 static void notify_find_address(dns_notify_t *notify);
414 static void notify_send(dns_notify_t *notify);
415 static isc_result_t notify_createmessage(dns_zone_t *zone,
416 unsigned int flags,
417 dns_message_t **messagep);
418 static void notify_done(isc_task_t *task, isc_event_t *event);
419 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
420 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
421 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
422 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
423 dns_zone_t *zone);
424 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
425 static void zonemgr_free(dns_zonemgr_t *zmgr);
426 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
427 isc_task_t *task, isc_taskaction_t action,
428 void *arg, dns_io_t **iop);
429 static void zonemgr_putio(dns_io_t **iop);
430 static void zonemgr_cancelio(dns_io_t *io);
432 static isc_result_t
433 zone_get_from_db(dns_db_t *db, dns_name_t *origin, unsigned int *nscount,
434 unsigned int *soacount, isc_uint32_t *serial,
435 isc_uint32_t *refresh, isc_uint32_t *retry,
436 isc_uint32_t *expire, isc_uint32_t *minimum);
438 static void zone_freedbargs(dns_zone_t *zone);
439 static void forward_callback(isc_task_t *task, isc_event_t *event);
440 static void zone_saveunique(dns_zone_t *zone, const char *path,
441 const char *templat);
442 static void zone_maintenance(dns_zone_t *zone);
443 static void zone_notify(dns_zone_t *zone);
444 static void dump_done(void *arg, isc_result_t result);
446 #define ENTER zone_debuglog(zone, me, 1, "enter")
448 static const unsigned int dbargc_default = 1;
449 static const char *dbargv_default[] = { "rbt" };
451 #define DNS_ZONE_JITTER_ADD(a, b, c) \
452 do { \
453 isc_interval_t _i; \
454 isc_uint32_t _j; \
455 _j = isc_random_jitter((b), (b)/4); \
456 isc_interval_set(&_i, _j, 0); \
457 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
458 dns_zone_log(zone, ISC_LOG_WARNING, \
459 "epoch approaching: upgrade required: " \
460 "now + %s failed", #b); \
461 isc_interval_set(&_i, _j/2, 0); \
462 (void)isc_time_add((a), &_i, (c)); \
464 } while (0)
466 #define DNS_ZONE_TIME_ADD(a, b, c) \
467 do { \
468 isc_interval_t _i; \
469 isc_interval_set(&_i, (b), 0); \
470 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
471 dns_zone_log(zone, ISC_LOG_WARNING, \
472 "epoch approaching: upgrade required: " \
473 "now + %s failed", #b); \
474 isc_interval_set(&_i, (b)/2, 0); \
475 (void)isc_time_add((a), &_i, (c)); \
477 } while (0)
479 /***
480 *** Public functions.
481 ***/
483 isc_result_t
484 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
485 isc_result_t result;
486 dns_zone_t *zone;
488 REQUIRE(zonep != NULL && *zonep == NULL);
489 REQUIRE(mctx != NULL);
491 zone = isc_mem_get(mctx, sizeof(*zone));
492 if (zone == NULL)
493 return (ISC_R_NOMEMORY);
495 result = isc_mutex_init(&zone->lock);
496 if (result != ISC_R_SUCCESS) {
497 isc_mem_put(mctx, zone, sizeof(*zone));
498 UNEXPECTED_ERROR(__FILE__, __LINE__,
499 "isc_mutex_init() failed: %s",
500 isc_result_totext(result));
501 return (ISC_R_UNEXPECTED);
504 /* XXX MPA check that all elements are initialised */
505 zone->mctx = NULL;
506 #ifdef DNS_ZONE_CHECKLOCK
507 zone->locked = ISC_FALSE;
508 #endif
509 isc_mem_attach(mctx, &zone->mctx);
510 zone->db = NULL;
511 zone->zmgr = NULL;
512 ISC_LINK_INIT(zone, link);
513 isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
514 zone->irefs = 0;
515 dns_name_init(&zone->origin, NULL);
516 zone->masterfile = NULL;
517 zone->keydirectory = NULL;
518 zone->journalsize = -1;
519 zone->journal = NULL;
520 zone->rdclass = dns_rdataclass_none;
521 zone->type = dns_zone_none;
522 zone->flags = 0;
523 zone->options = 0;
524 zone->db_argc = 0;
525 zone->db_argv = NULL;
526 isc_time_settoepoch(&zone->expiretime);
527 isc_time_settoepoch(&zone->refreshtime);
528 isc_time_settoepoch(&zone->dumptime);
529 isc_time_settoepoch(&zone->loadtime);
530 zone->serial = 0;
531 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
532 zone->retry = DNS_ZONE_DEFAULTRETRY;
533 zone->expire = 0;
534 zone->minimum = 0;
535 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
536 zone->minrefresh = DNS_ZONE_MINREFRESH;
537 zone->maxretry = DNS_ZONE_MAXRETRY;
538 zone->minretry = DNS_ZONE_MINRETRY;
539 zone->masters = NULL;
540 zone->masterkeynames = NULL;
541 zone->mastersok = NULL;
542 zone->masterscnt = 0;
543 zone->curmaster = 0;
544 zone->notify = NULL;
545 zone->notifytype = dns_notifytype_yes;
546 zone->notifycnt = 0;
547 zone->task = NULL;
548 zone->update_acl = NULL;
549 zone->forward_acl = NULL;
550 zone->notify_acl = NULL;
551 zone->query_acl = NULL;
552 zone->xfr_acl = NULL;
553 zone->update_disabled = ISC_FALSE;
554 zone->check_names = dns_severity_ignore;
555 zone->request = NULL;
556 zone->lctx = NULL;
557 zone->readio = NULL;
558 zone->dctx = NULL;
559 zone->writeio = NULL;
560 zone->timer = NULL;
561 zone->idlein = DNS_DEFAULT_IDLEIN;
562 zone->idleout = DNS_DEFAULT_IDLEOUT;
563 ISC_LIST_INIT(zone->notifies);
564 isc_sockaddr_any(&zone->notifysrc4);
565 isc_sockaddr_any6(&zone->notifysrc6);
566 isc_sockaddr_any(&zone->xfrsource4);
567 isc_sockaddr_any6(&zone->xfrsource6);
568 isc_sockaddr_any(&zone->altxfrsource4);
569 isc_sockaddr_any6(&zone->altxfrsource6);
570 zone->xfr = NULL;
571 zone->tsigkey = NULL;
572 zone->maxxfrin = MAX_XFER_TIME;
573 zone->maxxfrout = MAX_XFER_TIME;
574 zone->ssutable = NULL;
575 zone->sigvalidityinterval = 30 * 24 * 3600;
576 zone->view = NULL;
577 ISC_LINK_INIT(zone, statelink);
578 zone->statelist = NULL;
579 zone->counters = NULL;
581 zone->magic = ZONE_MAGIC;
583 /* Must be after magic is set. */
584 result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
585 if (result != ISC_R_SUCCESS)
586 goto free_mutex;
588 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
589 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
590 NULL, NULL);
591 *zonep = zone;
592 return (ISC_R_SUCCESS);
594 free_mutex:
595 DESTROYLOCK(&zone->lock);
596 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
597 return (result);
601 * Free a zone. Because we require that there be no more
602 * outstanding events or references, no locking is necessary.
604 static void
605 zone_free(dns_zone_t *zone) {
606 isc_mem_t *mctx = NULL;
608 REQUIRE(DNS_ZONE_VALID(zone));
609 REQUIRE(isc_refcount_current(&zone->erefs) == 0);
610 REQUIRE(zone->irefs == 0);
611 REQUIRE(!LOCKED_ZONE(zone));
612 REQUIRE(zone->timer == NULL);
615 * Managed objects. Order is important.
617 if (zone->request != NULL)
618 dns_request_destroy(&zone->request); /* XXXMPA */
619 INSIST(zone->readio == NULL);
620 INSIST(zone->statelist == NULL);
621 INSIST(zone->writeio == NULL);
623 if (zone->task != NULL)
624 isc_task_detach(&zone->task);
625 if (zone->zmgr)
626 dns_zonemgr_releasezone(zone->zmgr, zone);
628 /* Unmanaged objects */
629 if (zone->masterfile != NULL)
630 isc_mem_free(zone->mctx, zone->masterfile);
631 zone->masterfile = NULL;
632 if (zone->keydirectory != NULL)
633 isc_mem_free(zone->mctx, zone->keydirectory);
634 zone->keydirectory = NULL;
635 zone->journalsize = -1;
636 if (zone->journal != NULL)
637 isc_mem_free(zone->mctx, zone->journal);
638 zone->journal = NULL;
639 if (zone->counters != NULL)
640 dns_stats_freecounters(zone->mctx, &zone->counters);
641 if (zone->db != NULL)
642 dns_db_detach(&zone->db);
643 zone_freedbargs(zone);
644 RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
645 == ISC_R_SUCCESS);
646 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
647 == ISC_R_SUCCESS);
648 zone->check_names = dns_severity_ignore;
649 if (zone->update_acl != NULL)
650 dns_acl_detach(&zone->update_acl);
651 if (zone->forward_acl != NULL)
652 dns_acl_detach(&zone->forward_acl);
653 if (zone->notify_acl != NULL)
654 dns_acl_detach(&zone->notify_acl);
655 if (zone->query_acl != NULL)
656 dns_acl_detach(&zone->query_acl);
657 if (zone->xfr_acl != NULL)
658 dns_acl_detach(&zone->xfr_acl);
659 if (dns_name_dynamic(&zone->origin))
660 dns_name_free(&zone->origin, zone->mctx);
661 if (zone->ssutable != NULL)
662 dns_ssutable_detach(&zone->ssutable);
664 /* last stuff */
665 DESTROYLOCK(&zone->lock);
666 isc_refcount_destroy(&zone->erefs);
667 zone->magic = 0;
668 mctx = zone->mctx;
669 isc_mem_put(mctx, zone, sizeof(*zone));
670 isc_mem_detach(&mctx);
674 * Single shot.
676 void
677 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
679 REQUIRE(DNS_ZONE_VALID(zone));
680 REQUIRE(rdclass != dns_rdataclass_none);
683 * Test and set.
685 LOCK_ZONE(zone);
686 REQUIRE(zone->rdclass == dns_rdataclass_none ||
687 zone->rdclass == rdclass);
688 zone->rdclass = rdclass;
689 UNLOCK_ZONE(zone);
692 dns_rdataclass_t
693 dns_zone_getclass(dns_zone_t *zone){
694 REQUIRE(DNS_ZONE_VALID(zone));
696 return (zone->rdclass);
699 void
700 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
701 REQUIRE(DNS_ZONE_VALID(zone));
703 LOCK_ZONE(zone);
704 zone->notifytype = notifytype;
705 UNLOCK_ZONE(zone);
709 * Single shot.
711 void
712 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
714 REQUIRE(DNS_ZONE_VALID(zone));
715 REQUIRE(type != dns_zone_none);
718 * Test and set.
720 LOCK_ZONE(zone);
721 REQUIRE(zone->type == dns_zone_none || zone->type == type);
722 zone->type = type;
723 UNLOCK_ZONE(zone);
726 static void
727 zone_freedbargs(dns_zone_t *zone) {
728 unsigned int i;
730 /* Free the old database argument list. */
731 if (zone->db_argv != NULL) {
732 for (i = 0; i < zone->db_argc; i++)
733 isc_mem_free(zone->mctx, zone->db_argv[i]);
734 isc_mem_put(zone->mctx, zone->db_argv,
735 zone->db_argc * sizeof(*zone->db_argv));
737 zone->db_argc = 0;
738 zone->db_argv = NULL;
741 isc_result_t
742 dns_zone_setdbtype(dns_zone_t *zone,
743 unsigned int dbargc, const char * const *dbargv) {
744 isc_result_t result = ISC_R_SUCCESS;
745 char **new = NULL;
746 unsigned int i;
748 REQUIRE(DNS_ZONE_VALID(zone));
749 REQUIRE(dbargc >= 1);
750 REQUIRE(dbargv != NULL);
752 LOCK_ZONE(zone);
754 /* Set up a new database argument list. */
755 new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
756 if (new == NULL)
757 goto nomem;
758 for (i = 0; i < dbargc; i++)
759 new[i] = NULL;
760 for (i = 0; i < dbargc; i++) {
761 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
762 if (new[i] == NULL)
763 goto nomem;
766 /* Free the old list. */
767 zone_freedbargs(zone);
769 zone->db_argc = dbargc;
770 zone->db_argv = new;
771 result = ISC_R_SUCCESS;
772 goto unlock;
774 nomem:
775 if (new != NULL) {
776 for (i = 0; i < dbargc; i++)
777 if (new[i] != NULL)
778 isc_mem_free(zone->mctx, new[i]);
779 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
781 result = ISC_R_NOMEMORY;
783 unlock:
784 UNLOCK_ZONE(zone);
785 return (result);
788 void
789 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
790 REQUIRE(DNS_ZONE_VALID(zone));
792 LOCK_ZONE(zone);
793 if (zone->view != NULL)
794 dns_view_weakdetach(&zone->view);
795 dns_view_weakattach(view, &zone->view);
796 UNLOCK_ZONE(zone);
800 dns_view_t *
801 dns_zone_getview(dns_zone_t *zone) {
802 REQUIRE(DNS_ZONE_VALID(zone));
804 return (zone->view);
808 isc_result_t
809 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
810 isc_result_t result;
812 REQUIRE(DNS_ZONE_VALID(zone));
813 REQUIRE(origin != NULL);
815 LOCK_ZONE(zone);
816 if (dns_name_dynamic(&zone->origin)) {
817 dns_name_free(&zone->origin, zone->mctx);
818 dns_name_init(&zone->origin, NULL);
820 result = dns_name_dup(origin, zone->mctx, &zone->origin);
821 UNLOCK_ZONE(zone);
822 return (result);
826 static isc_result_t
827 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
828 char *copy;
830 if (value != NULL) {
831 copy = isc_mem_strdup(zone->mctx, value);
832 if (copy == NULL)
833 return (ISC_R_NOMEMORY);
834 } else {
835 copy = NULL;
838 if (*field != NULL)
839 isc_mem_free(zone->mctx, *field);
841 *field = copy;
842 return (ISC_R_SUCCESS);
845 isc_result_t
846 dns_zone_setfile(dns_zone_t *zone, const char *file) {
847 isc_result_t result = ISC_R_SUCCESS;
849 REQUIRE(DNS_ZONE_VALID(zone));
851 LOCK_ZONE(zone);
852 result = dns_zone_setstring(zone, &zone->masterfile, file);
853 if (result == ISC_R_SUCCESS)
854 result = default_journal(zone);
855 UNLOCK_ZONE(zone);
857 return (result);
860 const char *
861 dns_zone_getfile(dns_zone_t *zone) {
862 REQUIRE(DNS_ZONE_VALID(zone));
864 return (zone->masterfile);
867 static isc_result_t
868 default_journal(dns_zone_t *zone) {
869 isc_result_t result;
870 char *journal;
872 REQUIRE(DNS_ZONE_VALID(zone));
873 REQUIRE(LOCKED_ZONE(zone));
875 if (zone->masterfile != NULL) {
876 /* Calculate string length including '\0'. */
877 int len = strlen(zone->masterfile) + sizeof(".jnl");
878 journal = isc_mem_allocate(zone->mctx, len);
879 if (journal == NULL)
880 return (ISC_R_NOMEMORY);
881 strcpy(journal, zone->masterfile);
882 strcat(journal, ".jnl");
883 } else {
884 journal = NULL;
886 result = dns_zone_setstring(zone, &zone->journal, journal);
887 if (journal != NULL)
888 isc_mem_free(zone->mctx, journal);
889 return (result);
892 isc_result_t
893 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
894 isc_result_t result = ISC_R_SUCCESS;
896 REQUIRE(DNS_ZONE_VALID(zone));
898 LOCK_ZONE(zone);
899 result = dns_zone_setstring(zone, &zone->journal, journal);
900 UNLOCK_ZONE(zone);
902 return (result);
905 char *
906 dns_zone_getjournal(dns_zone_t *zone) {
907 REQUIRE(DNS_ZONE_VALID(zone));
909 return (zone->journal);
913 * Return true iff the zone is "dynamic", in the sense that the zone's
914 * master file (if any) is written by the server, rather than being
915 * updated manually and read by the server.
917 * This is true for slave zones, stub zones, and zones that allow
918 * dynamic updates either by having an update policy ("ssutable")
919 * or an "allow-update" ACL with a value other than exactly "{ none; }".
921 static isc_boolean_t
922 zone_isdynamic(dns_zone_t *zone) {
923 REQUIRE(DNS_ZONE_VALID(zone));
925 return (ISC_TF(zone->type == dns_zone_slave ||
926 zone->type == dns_zone_stub ||
927 (!zone->update_disabled && zone->ssutable != NULL) ||
928 (!zone->update_disabled && zone->update_acl != NULL &&
929 ! (zone->update_acl->length == 1 &&
930 zone->update_acl->elements[0].negative == ISC_TRUE
932 zone->update_acl->elements[0].type ==
933 dns_aclelementtype_any))));
937 static isc_result_t
938 zone_load(dns_zone_t *zone, unsigned int flags) {
939 isc_result_t result;
940 isc_time_t now;
941 isc_time_t loadtime, filetime;
942 dns_db_t *db = NULL;
944 REQUIRE(DNS_ZONE_VALID(zone));
946 LOCK_ZONE(zone);
947 TIME_NOW(&now);
949 INSIST(zone->type != dns_zone_none);
951 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
952 result = ISC_R_SUCCESS;
953 goto cleanup;
956 if (zone->db != NULL && zone->masterfile == NULL) {
958 * The zone has no master file configured, but it already
959 * has a database. It could be the built-in
960 * version.bind. CH zone, a zone with a persistent
961 * database being reloaded, or maybe a zone that
962 * used to have a master file but whose configuration
963 * was changed so that it no longer has one. Do nothing.
965 result = ISC_R_SUCCESS;
966 goto cleanup;
969 if (zone->db != NULL && zone_isdynamic(zone)) {
971 * This is a slave, stub, or dynamically updated
972 * zone being reloaded. Do nothing - the database
973 * we already have is guaranteed to be up-to-date.
975 if (zone->type == dns_zone_master)
976 result = DNS_R_DYNAMIC;
977 else
978 result = ISC_R_SUCCESS;
979 goto cleanup;
983 * Don't do the load if the file that stores the zone is older
984 * than the last time the zone was loaded. If the zone has not
985 * been loaded yet, zone->loadtime will be the epoch.
987 if (zone->masterfile != NULL && ! isc_time_isepoch(&zone->loadtime)) {
989 * The file is already loaded. If we are just doing a
990 * "rndc reconfig", we are done.
992 if ((flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
993 result = ISC_R_SUCCESS;
994 goto cleanup;
996 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE)) {
997 result = isc_file_getmodtime(zone->masterfile,
998 &filetime);
999 if (result == ISC_R_SUCCESS &&
1000 isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1001 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1002 "skipping load: master file older "
1003 "than last load");
1004 result = DNS_R_UPTODATE;
1005 goto cleanup;
1010 INSIST(zone->db_argc >= 1);
1013 * Built in zones don't need to be reloaded.
1015 if (zone->type == dns_zone_master &&
1016 strcmp(zone->db_argv[0], "_builtin") == 0 &&
1017 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1018 result = ISC_R_SUCCESS;
1019 goto cleanup;
1022 if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
1023 (strcmp(zone->db_argv[0], "rbt") == 0 ||
1024 strcmp(zone->db_argv[0], "rbt64") == 0)) {
1025 if (zone->masterfile == NULL ||
1026 !isc_file_exists(zone->masterfile)) {
1027 if (zone->masterfile != NULL)
1028 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1029 "no master file");
1030 zone->refreshtime = now;
1031 if (zone->task != NULL)
1032 zone_settimer(zone, &now);
1033 result = ISC_R_SUCCESS;
1034 goto cleanup;
1038 dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1041 * Store the current time before the zone is loaded, so that if the
1042 * file changes between the time of the load and the time that
1043 * zone->loadtime is set, then the file will still be reloaded
1044 * the next time dns_zone_load is called.
1046 TIME_NOW(&loadtime);
1048 result = dns_db_create(zone->mctx, zone->db_argv[0],
1049 &zone->origin, (zone->type == dns_zone_stub) ?
1050 dns_dbtype_stub : dns_dbtype_zone,
1051 zone->rdclass,
1052 zone->db_argc - 1, zone->db_argv + 1,
1053 &db);
1055 if (result != ISC_R_SUCCESS) {
1056 dns_zone_log(zone, ISC_LOG_ERROR,
1057 "loading zone: creating database: %s",
1058 isc_result_totext(result));
1059 goto cleanup;
1061 dns_db_settask(db, zone->task);
1063 if (! dns_db_ispersistent(db)) {
1064 if (zone->masterfile != NULL) {
1065 result = zone_startload(db, zone, loadtime);
1066 } else {
1067 result = DNS_R_NOMASTERFILE;
1068 if (zone->type == dns_zone_master) {
1069 dns_zone_log(zone, ISC_LOG_ERROR,
1070 "loading zone: "
1071 "no master file configured");
1072 goto cleanup;
1074 dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1075 "no master file configured: continuing");
1079 if (result == DNS_R_CONTINUE) {
1080 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1081 goto cleanup;
1084 result = zone_postload(zone, db, loadtime, result);
1086 cleanup:
1087 UNLOCK_ZONE(zone);
1088 if (db != NULL)
1089 dns_db_detach(&db);
1090 return (result);
1093 isc_result_t
1094 dns_zone_load(dns_zone_t *zone) {
1095 return (zone_load(zone, 0));
1098 isc_result_t
1099 dns_zone_loadnew(dns_zone_t *zone) {
1100 return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1103 static void
1104 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1105 dns_load_t *load = event->ev_arg;
1106 isc_result_t result = ISC_R_SUCCESS;
1107 unsigned int options;
1109 REQUIRE(DNS_LOAD_VALID(load));
1111 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1112 result = ISC_R_CANCELED;
1113 isc_event_free(&event);
1114 if (result == ISC_R_CANCELED)
1115 goto fail;
1117 options = DNS_MASTER_ZONE;
1118 if (load->zone->type == dns_zone_slave)
1119 options |= DNS_MASTER_SLAVE;
1120 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNS))
1121 options |= DNS_MASTER_CHECKNS;
1122 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_FATALNS))
1123 options |= DNS_MASTER_FATALNS;
1124 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNAMES))
1125 options |= DNS_MASTER_CHECKNAMES;
1126 if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1127 options |= DNS_MASTER_CHECKNAMESFAIL;
1128 result = dns_master_loadfileinc(load->zone->masterfile,
1129 dns_db_origin(load->db),
1130 dns_db_origin(load->db),
1131 load->zone->rdclass,
1132 options,
1133 &load->callbacks, task,
1134 zone_loaddone, load,
1135 &load->zone->lctx, load->zone->mctx);
1136 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1137 result != DNS_R_SEENINCLUDE)
1138 goto fail;
1139 return;
1141 fail:
1142 zone_loaddone(load, result);
1145 static void
1146 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1147 const char me[] = "zone_gotwritehandle";
1148 dns_zone_t *zone = event->ev_arg;
1149 isc_result_t result = ISC_R_SUCCESS;
1150 dns_dbversion_t *version = NULL;
1152 REQUIRE(DNS_ZONE_VALID(zone));
1153 INSIST(task == zone->task);
1154 ENTER;
1156 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1157 result = ISC_R_CANCELED;
1158 isc_event_free(&event);
1159 if (result == ISC_R_CANCELED)
1160 goto fail;
1162 LOCK_ZONE(zone);
1163 dns_db_currentversion(zone->db, &version);
1164 result = dns_master_dumpinc(zone->mctx, zone->db, version,
1165 &dns_master_style_default,
1166 zone->masterfile, zone->task,
1167 dump_done, zone, &zone->dctx);
1168 dns_db_closeversion(zone->db, &version, ISC_FALSE);
1169 UNLOCK_ZONE(zone);
1170 if (result != DNS_R_CONTINUE)
1171 goto fail;
1172 return;
1174 fail:
1175 dump_done(zone, result);
1178 static isc_result_t
1179 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1180 dns_load_t *load;
1181 isc_result_t result;
1182 isc_result_t tresult;
1183 unsigned int options;
1185 options = DNS_MASTER_ZONE;
1186 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1187 options |= DNS_MASTER_MANYERRORS;
1188 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1189 options |= DNS_MASTER_CHECKNS;
1190 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1191 options |= DNS_MASTER_FATALNS;
1192 if (zone->type == dns_zone_slave)
1193 options |= DNS_MASTER_SLAVE;
1194 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1195 options |= DNS_MASTER_CHECKNAMES;
1196 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1197 options |= DNS_MASTER_CHECKNAMESFAIL;
1199 if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1200 load = isc_mem_get(zone->mctx, sizeof(*load));
1201 if (load == NULL)
1202 return (ISC_R_NOMEMORY);
1204 load->mctx = NULL;
1205 load->zone = NULL;
1206 load->db = NULL;
1207 load->loadtime = loadtime;
1208 load->magic = LOAD_MAGIC;
1210 isc_mem_attach(zone->mctx, &load->mctx);
1211 zone_iattach(zone, &load->zone);
1212 dns_db_attach(db, &load->db);
1213 dns_rdatacallbacks_init(&load->callbacks);
1214 result = dns_db_beginload(db, &load->callbacks.add,
1215 &load->callbacks.add_private);
1216 if (result != ISC_R_SUCCESS)
1217 goto cleanup;
1218 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1219 zone_gotreadhandle, load,
1220 &zone->readio);
1221 if (result != ISC_R_SUCCESS) {
1223 * We can't report multiple errors so ignore
1224 * the result of dns_db_endload().
1226 (void)dns_db_endload(load->db,
1227 &load->callbacks.add_private);
1228 goto cleanup;
1229 } else
1230 result = DNS_R_CONTINUE;
1231 } else {
1232 dns_rdatacallbacks_t callbacks;
1234 dns_rdatacallbacks_init(&callbacks);
1235 result = dns_db_beginload(db, &callbacks.add,
1236 &callbacks.add_private);
1237 if (result != ISC_R_SUCCESS)
1238 return (result);
1239 result = dns_master_loadfile(zone->masterfile, &zone->origin,
1240 &zone->origin, zone->rdclass,
1241 options, &callbacks, zone->mctx);
1242 tresult = dns_db_endload(db, &callbacks.add_private);
1243 if (result == ISC_R_SUCCESS)
1244 result = tresult;
1247 return (result);
1249 cleanup:
1250 load->magic = 0;
1251 dns_db_detach(&load->db);
1252 zone_idetach(&load->zone);
1253 isc_mem_detach(&load->mctx);
1254 isc_mem_put(zone->mctx, load, sizeof(*load));
1255 return (result);
1258 static isc_result_t
1259 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
1260 isc_result_t result)
1262 unsigned int soacount = 0;
1263 unsigned int nscount = 0;
1264 isc_uint32_t serial, refresh, retry, expire, minimum;
1265 isc_time_t now;
1266 isc_boolean_t needdump = ISC_FALSE;
1267 isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1269 TIME_NOW(&now);
1272 * Initiate zone transfer? We may need a error code that
1273 * indicates that the "permanent" form does not exist.
1274 * XXX better error feedback to log.
1276 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
1277 if (zone->type == dns_zone_slave ||
1278 zone->type == dns_zone_stub) {
1279 if (result == ISC_R_FILENOTFOUND)
1280 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1281 "no master file");
1282 else if (result != DNS_R_NOMASTERFILE)
1283 dns_zone_log(zone, ISC_LOG_ERROR,
1284 "loading master file %s: %s",
1285 zone->masterfile,
1286 dns_result_totext(result));
1287 } else
1288 dns_zone_log(zone, ISC_LOG_ERROR,
1289 "loading master file %s: %s",
1290 zone->masterfile,
1291 dns_result_totext(result));
1292 goto cleanup;
1295 dns_zone_log(zone, ISC_LOG_DEBUG(2),
1296 "number of nodes in database: %u",
1297 dns_db_nodecount(db));
1299 if (result == DNS_R_SEENINCLUDE)
1300 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1301 else
1302 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1305 * Apply update log, if any, on initial load.
1307 if (zone->journal != NULL &&
1308 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
1309 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
1311 result = dns_journal_rollforward(zone->mctx, db,
1312 zone->journal);
1313 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
1314 result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
1315 result != ISC_R_RANGE) {
1316 dns_zone_log(zone, ISC_LOG_ERROR,
1317 "journal rollforward failed: %s",
1318 dns_result_totext(result));
1319 goto cleanup;
1321 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
1322 dns_zone_log(zone, ISC_LOG_ERROR,
1323 "journal rollforward failed: "
1324 "journal out of sync with zone");
1325 goto cleanup;
1327 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1328 "journal rollforward completed "
1329 "successfully: %s",
1330 dns_result_totext(result));
1331 if (result == ISC_R_SUCCESS)
1332 needdump = ISC_TRUE;
1335 zone->loadtime = loadtime;
1337 dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
1340 * Obtain ns and soa counts for top of zone.
1342 nscount = 0;
1343 soacount = 0;
1344 INSIST(db != NULL);
1345 result = zone_get_from_db(db, &zone->origin, &nscount,
1346 &soacount, &serial, &refresh, &retry,
1347 &expire, &minimum);
1348 if (result != ISC_R_SUCCESS) {
1349 dns_zone_log(zone, ISC_LOG_ERROR,
1350 "could not find NS and/or SOA records");
1354 * Master / Slave / Stub zones require both NS and SOA records at
1355 * the top of the zone.
1358 switch (zone->type) {
1359 case dns_zone_master:
1360 case dns_zone_slave:
1361 case dns_zone_stub:
1362 if (soacount != 1) {
1363 dns_zone_log(zone, ISC_LOG_ERROR,
1364 "has %d SOA records", soacount);
1365 result = DNS_R_BADZONE;
1367 if (nscount == 0) {
1368 dns_zone_log(zone, ISC_LOG_ERROR,
1369 "has no NS records");
1370 result = DNS_R_BADZONE;
1372 if (result != ISC_R_SUCCESS)
1373 goto cleanup;
1374 if (zone->db != NULL) {
1376 * This is checked in zone_replacedb() for slave zones
1377 * as they don't reload from disk.
1379 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
1380 !isc_serial_gt(serial, zone->serial)) {
1381 isc_uint32_t serialmin, serialmax;
1383 INSIST(zone->type == dns_zone_master);
1385 serialmin = (zone->serial + 1) & 0xffffffffU;
1386 serialmax = (zone->serial + 0x7fffffffU) &
1387 0xffffffffU;
1388 dns_zone_log(zone, ISC_LOG_ERROR,
1389 "ixfr-from-differences: "
1390 "new serial (%u) out of range "
1391 "[%u - %u]", serial, serialmin,
1392 serialmax);
1393 result = DNS_R_BADZONE;
1394 goto cleanup;
1395 } else if (!isc_serial_ge(serial, zone->serial))
1396 dns_zone_log(zone, ISC_LOG_ERROR,
1397 "zone serial has gone backwards");
1398 else if (serial == zone->serial && !hasinclude)
1399 dns_zone_log(zone, ISC_LOG_ERROR,
1400 "zone serial unchanged");
1402 zone->serial = serial;
1403 zone->refresh = RANGE(refresh,
1404 zone->minrefresh, zone->maxrefresh);
1405 zone->retry = RANGE(retry,
1406 zone->minretry, zone->maxretry);
1407 zone->expire = RANGE(expire, zone->refresh + zone->retry,
1408 DNS_MAX_EXPIRE);
1409 zone->minimum = minimum;
1410 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
1412 if (zone->type == dns_zone_slave ||
1413 zone->type == dns_zone_stub) {
1414 isc_time_t t;
1415 isc_uint32_t delay;
1417 result = isc_file_getmodtime(zone->journal, &t);
1418 if (result != ISC_R_SUCCESS)
1419 result = isc_file_getmodtime(zone->masterfile,
1420 &t);
1421 if (result == ISC_R_SUCCESS)
1422 DNS_ZONE_TIME_ADD(&t, zone->expire,
1423 &zone->expiretime);
1424 else
1425 DNS_ZONE_TIME_ADD(&now, zone->retry,
1426 &zone->expiretime);
1428 delay = isc_random_jitter(zone->retry,
1429 (zone->retry * 3) / 4);
1430 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
1431 if (isc_time_compare(&zone->refreshtime,
1432 &zone->expiretime) >= 0)
1433 zone->refreshtime = now;
1435 break;
1436 default:
1437 UNEXPECTED_ERROR(__FILE__, __LINE__,
1438 "unexpected zone type %d", zone->type);
1439 result = ISC_R_UNEXPECTED;
1440 goto cleanup;
1444 #if 0
1445 /* destroy notification example. */
1447 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
1448 DNS_EVENT_DBDESTROYED,
1449 dns_zonemgr_dbdestroyed,
1450 zone,
1451 sizeof(isc_event_t));
1452 dns_db_ondestroy(db, zone->task, &e);
1454 #endif
1456 if (zone->db != NULL) {
1457 result = zone_replacedb(zone, db, ISC_FALSE);
1458 if (result != ISC_R_SUCCESS)
1459 goto cleanup;
1460 } else {
1461 dns_db_attach(db, &zone->db);
1462 DNS_ZONE_SETFLAG(zone,
1463 DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
1465 result = ISC_R_SUCCESS;
1466 if (needdump)
1467 zone_needdump(zone, DNS_DUMP_DELAY);
1468 if (zone->task != NULL)
1469 zone_settimer(zone, &now);
1471 if (! dns_db_ispersistent(db))
1472 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s",
1473 zone->serial,
1474 dns_db_issecure(db) ? " (signed)" : "");
1476 return (result);
1478 cleanup:
1479 if (zone->type == dns_zone_slave ||
1480 zone->type == dns_zone_stub) {
1481 if (zone->journal != NULL)
1482 zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
1483 if (zone->masterfile != NULL)
1484 zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
1486 /* Mark the zone for immediate refresh. */
1487 zone->refreshtime = now;
1488 if (zone->task != NULL)
1489 zone_settimer(zone, &now);
1490 result = ISC_R_SUCCESS;
1492 return (result);
1495 static isc_boolean_t
1496 exit_check(dns_zone_t *zone) {
1498 REQUIRE(LOCKED_ZONE(zone));
1500 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
1501 zone->irefs == 0)
1504 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
1506 INSIST(isc_refcount_current(&zone->erefs) == 0);
1507 return (ISC_TRUE);
1509 return (ISC_FALSE);
1512 static isc_result_t
1513 zone_count_ns_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1514 unsigned int *nscount)
1516 isc_result_t result;
1517 unsigned int count;
1518 dns_rdataset_t rdataset;
1520 REQUIRE(nscount != NULL);
1522 dns_rdataset_init(&rdataset);
1523 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
1524 dns_rdatatype_none, 0, &rdataset, NULL);
1525 if (result == ISC_R_NOTFOUND) {
1526 *nscount = 0;
1527 result = ISC_R_SUCCESS;
1528 goto invalidate_rdataset;
1530 if (result != ISC_R_SUCCESS)
1531 goto invalidate_rdataset;
1533 count = 0;
1534 result = dns_rdataset_first(&rdataset);
1535 while (result == ISC_R_SUCCESS) {
1536 count++;
1537 result = dns_rdataset_next(&rdataset);
1539 dns_rdataset_disassociate(&rdataset);
1541 *nscount = count;
1542 result = ISC_R_SUCCESS;
1544 invalidate_rdataset:
1545 dns_rdataset_invalidate(&rdataset);
1547 return (result);
1550 static isc_result_t
1551 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1552 unsigned int *soacount,
1553 isc_uint32_t *serial, isc_uint32_t *refresh,
1554 isc_uint32_t *retry, isc_uint32_t *expire,
1555 isc_uint32_t *minimum)
1557 isc_result_t result;
1558 unsigned int count;
1559 dns_rdataset_t rdataset;
1560 dns_rdata_t rdata = DNS_RDATA_INIT;
1561 dns_rdata_soa_t soa;
1563 dns_rdataset_init(&rdataset);
1564 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
1565 dns_rdatatype_none, 0, &rdataset, NULL);
1566 if (result == ISC_R_NOTFOUND) {
1567 if (soacount != NULL)
1568 *soacount = 0;
1569 if (serial != NULL)
1570 *serial = 0;
1571 if (refresh != NULL)
1572 *refresh = 0;
1573 if (retry != NULL)
1574 *retry = 0;
1575 if (expire != NULL)
1576 *expire = 0;
1577 if (minimum != NULL)
1578 *minimum = 0;
1579 result = ISC_R_SUCCESS;
1580 goto invalidate_rdataset;
1582 if (result != ISC_R_SUCCESS)
1583 goto invalidate_rdataset;
1585 count = 0;
1586 result = dns_rdataset_first(&rdataset);
1587 while (result == ISC_R_SUCCESS) {
1588 dns_rdata_init(&rdata);
1589 dns_rdataset_current(&rdataset, &rdata);
1590 count++;
1591 if (count == 1) {
1592 result = dns_rdata_tostruct(&rdata, &soa, NULL);
1593 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1596 result = dns_rdataset_next(&rdataset);
1597 dns_rdata_reset(&rdata);
1599 dns_rdataset_disassociate(&rdataset);
1601 if (soacount != NULL)
1602 *soacount = count;
1604 if (count > 0) {
1605 if (serial != NULL)
1606 *serial = soa.serial;
1607 if (refresh != NULL)
1608 *refresh = soa.refresh;
1609 if (retry != NULL)
1610 *retry = soa.retry;
1611 if (expire != NULL)
1612 *expire = soa.expire;
1613 if (minimum != NULL)
1614 *minimum = soa.minimum;
1617 result = ISC_R_SUCCESS;
1619 invalidate_rdataset:
1620 dns_rdataset_invalidate(&rdataset);
1622 return (result);
1626 * zone must be locked.
1628 static isc_result_t
1629 zone_get_from_db(dns_db_t *db, dns_name_t *origin, unsigned int *nscount,
1630 unsigned int *soacount, isc_uint32_t *serial,
1631 isc_uint32_t *refresh, isc_uint32_t *retry,
1632 isc_uint32_t *expire, isc_uint32_t *minimum)
1634 dns_dbversion_t *version;
1635 isc_result_t result;
1636 isc_result_t answer = ISC_R_SUCCESS;
1637 dns_dbnode_t *node;
1639 REQUIRE(db != NULL);
1640 REQUIRE(origin != NULL);
1642 version = NULL;
1643 dns_db_currentversion(db, &version);
1645 node = NULL;
1646 result = dns_db_findnode(db, origin, ISC_FALSE, &node);
1647 if (result != ISC_R_SUCCESS) {
1648 answer = result;
1649 goto closeversion;
1652 if (nscount != NULL) {
1653 result = zone_count_ns_rr(db, node, version, nscount);
1654 if (result != ISC_R_SUCCESS)
1655 answer = result;
1658 if (soacount != NULL || serial != NULL || refresh != NULL
1659 || retry != NULL || expire != NULL || minimum != NULL) {
1660 result = zone_load_soa_rr(db, node, version, soacount,
1661 serial, refresh, retry, expire,
1662 minimum);
1663 if (result != ISC_R_SUCCESS)
1664 answer = result;
1667 dns_db_detachnode(db, &node);
1668 closeversion:
1669 dns_db_closeversion(db, &version, ISC_FALSE);
1671 return (answer);
1674 void
1675 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
1676 REQUIRE(DNS_ZONE_VALID(source));
1677 REQUIRE(target != NULL && *target == NULL);
1678 isc_refcount_increment(&source->erefs, NULL);
1679 *target = source;
1682 void
1683 dns_zone_detach(dns_zone_t **zonep) {
1684 dns_zone_t *zone;
1685 unsigned int refs;
1686 isc_boolean_t free_now = ISC_FALSE;
1688 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1690 zone = *zonep;
1692 isc_refcount_decrement(&zone->erefs, &refs);
1694 if (refs == 0) {
1695 LOCK_ZONE(zone);
1697 * We just detached the last external reference.
1699 if (zone->task != NULL) {
1701 * This zone is being managed. Post
1702 * its control event and let it clean
1703 * up synchronously in the context of
1704 * its task.
1706 isc_event_t *ev = &zone->ctlevent;
1707 isc_task_send(zone->task, &ev);
1708 } else {
1710 * This zone is not being managed; it has
1711 * no task and can have no outstanding
1712 * events. Free it immediately.
1715 * Unmanaged zones should not have non-null views;
1716 * we have no way of detaching from the view here
1717 * without causing deadlock because this code is called
1718 * with the view already locked.
1720 INSIST(zone->view == NULL);
1721 free_now = ISC_TRUE;
1723 UNLOCK_ZONE(zone);
1725 *zonep = NULL;
1726 if (free_now)
1727 zone_free(zone);
1730 void
1731 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
1732 REQUIRE(DNS_ZONE_VALID(source));
1733 REQUIRE(target != NULL && *target == NULL);
1734 LOCK_ZONE(source);
1735 zone_iattach(source, target);
1736 UNLOCK_ZONE(source);
1739 static void
1740 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
1743 * 'source' locked by caller.
1745 REQUIRE(LOCKED_ZONE(source));
1746 REQUIRE(DNS_ZONE_VALID(source));
1747 REQUIRE(target != NULL && *target == NULL);
1748 INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
1749 source->irefs++;
1750 INSIST(source->irefs != 0);
1751 *target = source;
1754 static void
1755 zone_idetach(dns_zone_t **zonep) {
1756 dns_zone_t *zone;
1759 * 'zone' locked by caller.
1761 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1762 zone = *zonep;
1763 REQUIRE(LOCKED_ZONE(*zonep));
1764 *zonep = NULL;
1766 INSIST(zone->irefs > 0);
1767 zone->irefs--;
1768 INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
1771 void
1772 dns_zone_idetach(dns_zone_t **zonep) {
1773 dns_zone_t *zone;
1774 isc_boolean_t free_needed;
1776 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1777 zone = *zonep;
1778 *zonep = NULL;
1780 LOCK_ZONE(zone);
1781 INSIST(zone->irefs > 0);
1782 zone->irefs--;
1783 free_needed = exit_check(zone);
1784 UNLOCK_ZONE(zone);
1785 if (free_needed)
1786 zone_free(zone);
1789 isc_mem_t *
1790 dns_zone_getmctx(dns_zone_t *zone) {
1791 REQUIRE(DNS_ZONE_VALID(zone));
1793 return (zone->mctx);
1796 dns_zonemgr_t *
1797 dns_zone_getmgr(dns_zone_t *zone) {
1798 REQUIRE(DNS_ZONE_VALID(zone));
1800 return (zone->zmgr);
1803 void
1804 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
1805 REQUIRE(DNS_ZONE_VALID(zone));
1807 LOCK_ZONE(zone);
1808 if (value)
1809 DNS_ZONE_SETFLAG(zone, flags);
1810 else
1811 DNS_ZONE_CLRFLAG(zone, flags);
1812 UNLOCK_ZONE(zone);
1815 void
1816 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
1818 REQUIRE(DNS_ZONE_VALID(zone));
1820 LOCK_ZONE(zone);
1821 if (value)
1822 zone->options |= option;
1823 else
1824 zone->options &= ~option;
1825 UNLOCK_ZONE(zone);
1828 unsigned int
1829 dns_zone_getoptions(dns_zone_t *zone) {
1831 REQUIRE(DNS_ZONE_VALID(zone));
1833 return (zone->options);
1836 isc_result_t
1837 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
1838 REQUIRE(DNS_ZONE_VALID(zone));
1840 LOCK_ZONE(zone);
1841 zone->xfrsource4 = *xfrsource;
1842 UNLOCK_ZONE(zone);
1844 return (ISC_R_SUCCESS);
1847 isc_sockaddr_t *
1848 dns_zone_getxfrsource4(dns_zone_t *zone) {
1849 REQUIRE(DNS_ZONE_VALID(zone));
1850 return (&zone->xfrsource4);
1853 isc_result_t
1854 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
1855 REQUIRE(DNS_ZONE_VALID(zone));
1857 LOCK_ZONE(zone);
1858 zone->xfrsource6 = *xfrsource;
1859 UNLOCK_ZONE(zone);
1861 return (ISC_R_SUCCESS);
1864 isc_sockaddr_t *
1865 dns_zone_getxfrsource6(dns_zone_t *zone) {
1866 REQUIRE(DNS_ZONE_VALID(zone));
1867 return (&zone->xfrsource6);
1870 isc_result_t
1871 dns_zone_setaltxfrsource4(dns_zone_t *zone,
1872 const isc_sockaddr_t *altxfrsource)
1874 REQUIRE(DNS_ZONE_VALID(zone));
1876 LOCK_ZONE(zone);
1877 zone->altxfrsource4 = *altxfrsource;
1878 UNLOCK_ZONE(zone);
1880 return (ISC_R_SUCCESS);
1883 isc_sockaddr_t *
1884 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
1885 REQUIRE(DNS_ZONE_VALID(zone));
1886 return (&zone->altxfrsource4);
1889 isc_result_t
1890 dns_zone_setaltxfrsource6(dns_zone_t *zone,
1891 const isc_sockaddr_t *altxfrsource)
1893 REQUIRE(DNS_ZONE_VALID(zone));
1895 LOCK_ZONE(zone);
1896 zone->altxfrsource6 = *altxfrsource;
1897 UNLOCK_ZONE(zone);
1899 return (ISC_R_SUCCESS);
1902 isc_sockaddr_t *
1903 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
1904 REQUIRE(DNS_ZONE_VALID(zone));
1905 return (&zone->altxfrsource6);
1908 isc_result_t
1909 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
1910 REQUIRE(DNS_ZONE_VALID(zone));
1912 LOCK_ZONE(zone);
1913 zone->notifysrc4 = *notifysrc;
1914 UNLOCK_ZONE(zone);
1916 return (ISC_R_SUCCESS);
1919 isc_sockaddr_t *
1920 dns_zone_getnotifysrc4(dns_zone_t *zone) {
1921 REQUIRE(DNS_ZONE_VALID(zone));
1922 return (&zone->notifysrc4);
1925 isc_result_t
1926 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
1927 REQUIRE(DNS_ZONE_VALID(zone));
1929 LOCK_ZONE(zone);
1930 zone->notifysrc6 = *notifysrc;
1931 UNLOCK_ZONE(zone);
1933 return (ISC_R_SUCCESS);
1936 isc_sockaddr_t *
1937 dns_zone_getnotifysrc6(dns_zone_t *zone) {
1938 REQUIRE(DNS_ZONE_VALID(zone));
1939 return (&zone->notifysrc6);
1942 isc_result_t
1943 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
1944 isc_uint32_t count)
1946 isc_sockaddr_t *new;
1948 REQUIRE(DNS_ZONE_VALID(zone));
1949 REQUIRE(count == 0 || notify != NULL);
1951 LOCK_ZONE(zone);
1952 if (zone->notify != NULL) {
1953 isc_mem_put(zone->mctx, zone->notify,
1954 zone->notifycnt * sizeof(*new));
1955 zone->notify = NULL;
1956 zone->notifycnt = 0;
1958 if (count != 0) {
1959 new = isc_mem_get(zone->mctx, count * sizeof(*new));
1960 if (new == NULL) {
1961 UNLOCK_ZONE(zone);
1962 return (ISC_R_NOMEMORY);
1964 memcpy(new, notify, count * sizeof(*new));
1965 zone->notify = new;
1966 zone->notifycnt = count;
1968 UNLOCK_ZONE(zone);
1969 return (ISC_R_SUCCESS);
1972 isc_result_t
1973 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
1974 isc_uint32_t count)
1976 isc_result_t result;
1978 result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
1979 return (result);
1982 isc_result_t
1983 dns_zone_setmasterswithkeys(dns_zone_t *zone,
1984 const isc_sockaddr_t *masters,
1985 dns_name_t **keynames,
1986 isc_uint32_t count)
1988 isc_sockaddr_t *new;
1989 isc_result_t result = ISC_R_SUCCESS;
1990 dns_name_t **newname;
1991 isc_boolean_t *newok;
1992 unsigned int i;
1994 REQUIRE(DNS_ZONE_VALID(zone));
1995 REQUIRE(count == 0 || masters != NULL);
1996 if (keynames != NULL) {
1997 REQUIRE(count != 0);
2000 LOCK_ZONE(zone);
2001 if (zone->masters != NULL) {
2002 isc_mem_put(zone->mctx, zone->masters,
2003 zone->masterscnt * sizeof(*new));
2004 zone->masters = NULL;
2006 if (zone->masterkeynames != NULL) {
2007 for (i = 0; i < zone->masterscnt; i++) {
2008 if (zone->masterkeynames[i] != NULL) {
2009 dns_name_free(zone->masterkeynames[i],
2010 zone->mctx);
2011 isc_mem_put(zone->mctx,
2012 zone->masterkeynames[i],
2013 sizeof(dns_name_t));
2014 zone->masterkeynames[i] = NULL;
2017 isc_mem_put(zone->mctx, zone->masterkeynames,
2018 zone->masterscnt * sizeof(dns_name_t *));
2019 zone->masterkeynames = NULL;
2021 if (zone->mastersok != NULL) {
2022 isc_mem_put(zone->mctx, zone->mastersok,
2023 zone->masterscnt * sizeof(isc_boolean_t));
2024 zone->mastersok = NULL;
2026 zone->masterscnt = 0;
2028 * If count == 0, don't allocate any space for masters, mastersok or
2029 * keynames so internally, those pointers are NULL if count == 0
2031 if (count == 0)
2032 goto unlock;
2035 * masters must countain count elements!
2037 new = isc_mem_get(zone->mctx, count * sizeof(*new));
2038 if (new == NULL) {
2039 result = ISC_R_NOMEMORY;
2040 goto unlock;
2042 memcpy(new, masters, count * sizeof(*new));
2045 * Similarly for mastersok.
2047 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
2048 if (newok == NULL) {
2049 result = ISC_R_NOMEMORY;
2050 isc_mem_put(zone->mctx, new, count * sizeof(*new));
2051 goto unlock;
2053 for (i = 0; i < count; i++)
2054 newok[i] = ISC_FALSE;
2057 * if keynames is non-NULL, it must contain count elements!
2059 newname = NULL;
2060 if (keynames != NULL) {
2061 newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
2062 if (newname == NULL) {
2063 result = ISC_R_NOMEMORY;
2064 isc_mem_put(zone->mctx, new, count * sizeof(*new));
2065 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
2066 goto unlock;
2068 for (i = 0; i < count; i++)
2069 newname[i] = NULL;
2070 for (i = 0; i < count; i++) {
2071 if (keynames[i] != NULL) {
2072 newname[i] = isc_mem_get(zone->mctx,
2073 sizeof(dns_name_t));
2074 if (newname[i] == NULL)
2075 goto allocfail;
2076 dns_name_init(newname[i], NULL);
2077 result = dns_name_dup(keynames[i], zone->mctx,
2078 newname[i]);
2079 if (result != ISC_R_SUCCESS) {
2080 allocfail:
2081 for (i = 0; i < count; i++)
2082 if (newname[i] != NULL)
2083 dns_name_free(
2084 newname[i],
2085 zone->mctx);
2086 isc_mem_put(zone->mctx, new,
2087 count * sizeof(*new));
2088 isc_mem_put(zone->mctx, newok,
2089 count * sizeof(*newok));
2090 isc_mem_put(zone->mctx, newname,
2091 count * sizeof(*newname));
2092 goto unlock;
2099 * Everything is ok so attach to the zone.
2101 zone->masters = new;
2102 zone->mastersok = newok;
2103 zone->masterkeynames = newname;
2104 zone->masterscnt = count;
2105 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
2107 unlock:
2108 UNLOCK_ZONE(zone);
2109 return (result);
2112 isc_result_t
2113 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
2114 isc_result_t result = ISC_R_SUCCESS;
2116 REQUIRE(DNS_ZONE_VALID(zone));
2118 LOCK_ZONE(zone);
2119 if (zone->db == NULL)
2120 result = DNS_R_NOTLOADED;
2121 else
2122 dns_db_attach(zone->db, dpb);
2123 UNLOCK_ZONE(zone);
2125 return (result);
2129 * Co-ordinates the starting of routine jobs.
2132 void
2133 dns_zone_maintenance(dns_zone_t *zone) {
2134 const char me[] = "dns_zone_maintenance";
2135 isc_time_t now;
2137 REQUIRE(DNS_ZONE_VALID(zone));
2138 ENTER;
2140 LOCK_ZONE(zone);
2141 TIME_NOW(&now);
2142 zone_settimer(zone, &now);
2143 UNLOCK_ZONE(zone);
2146 static inline isc_boolean_t
2147 was_dumping(dns_zone_t *zone) {
2148 isc_boolean_t dumping;
2150 REQUIRE(LOCKED_ZONE(zone));
2152 dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
2153 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
2154 if (!dumping) {
2155 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2156 isc_time_settoepoch(&zone->dumptime);
2158 return (dumping);
2161 static void
2162 zone_maintenance(dns_zone_t *zone) {
2163 const char me[] = "zone_maintenance";
2164 isc_time_t now;
2165 isc_result_t result;
2166 isc_boolean_t dumping;
2168 REQUIRE(DNS_ZONE_VALID(zone));
2169 ENTER;
2172 * Configuring the view of this zone may have
2173 * failed, for example because the config file
2174 * had a syntax error. In that case, the view
2175 * adb or resolver, and we had better not try
2176 * to do maintenance on it.
2178 if (zone->view == NULL || zone->view->adb == NULL)
2179 return;
2181 TIME_NOW(&now);
2184 * Expire check.
2186 switch (zone->type) {
2187 case dns_zone_slave:
2188 case dns_zone_stub:
2189 LOCK_ZONE(zone);
2190 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
2191 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
2192 zone_expire(zone);
2193 zone->refreshtime = now;
2195 UNLOCK_ZONE(zone);
2196 break;
2197 default:
2198 break;
2202 * Up to date check.
2204 switch (zone->type) {
2205 case dns_zone_slave:
2206 case dns_zone_stub:
2207 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
2208 isc_time_compare(&now, &zone->refreshtime) >= 0)
2209 dns_zone_refresh(zone);
2210 break;
2211 default:
2212 break;
2216 * Do we need to consolidate the backing store?
2218 switch (zone->type) {
2219 case dns_zone_master:
2220 case dns_zone_slave:
2221 LOCK_ZONE(zone);
2222 if (zone->masterfile != NULL &&
2223 isc_time_compare(&now, &zone->dumptime) >= 0 &&
2224 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2225 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
2226 dumping = was_dumping(zone);
2227 } else
2228 dumping = ISC_TRUE;
2229 UNLOCK_ZONE(zone);
2230 if (!dumping) {
2231 result = zone_dump(zone, ISC_TRUE); /* task locked */
2232 if (result != ISC_R_SUCCESS)
2233 dns_zone_log(zone, ISC_LOG_WARNING,
2234 "dump failed: %s",
2235 dns_result_totext(result));
2237 break;
2238 default:
2239 break;
2243 * Do we need to send out notify messages?
2245 switch (zone->type) {
2246 case dns_zone_master:
2247 case dns_zone_slave:
2248 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
2249 zone_notify(zone);
2250 break;
2251 default:
2252 break;
2254 zone_settimer(zone, &now);
2257 void
2258 dns_zone_markdirty(dns_zone_t *zone) {
2260 LOCK_ZONE(zone);
2261 zone_needdump(zone, DNS_DUMP_DELAY);
2262 UNLOCK_ZONE(zone);
2265 void
2266 dns_zone_expire(dns_zone_t *zone) {
2267 REQUIRE(DNS_ZONE_VALID(zone));
2269 LOCK_ZONE(zone);
2270 zone_expire(zone);
2271 UNLOCK_ZONE(zone);
2274 static void
2275 zone_expire(dns_zone_t *zone) {
2277 * 'zone' locked by caller.
2280 REQUIRE(LOCKED_ZONE(zone));
2282 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
2284 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
2285 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
2286 zone->retry = DNS_ZONE_DEFAULTRETRY;
2287 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
2288 zone_unload(zone);
2291 void
2292 dns_zone_refresh(dns_zone_t *zone) {
2293 isc_interval_t i;
2294 isc_uint32_t oldflags;
2295 unsigned int j;
2296 isc_result_t result;
2298 REQUIRE(DNS_ZONE_VALID(zone));
2300 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
2301 return;
2304 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
2305 * in progress at a time.
2308 LOCK_ZONE(zone);
2309 oldflags = zone->flags;
2310 if (zone->masterscnt == 0) {
2311 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
2312 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
2313 dns_zone_log(zone, ISC_LOG_ERROR,
2314 "cannot refresh: no masters");
2315 goto unlock;
2317 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
2318 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
2319 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
2320 if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
2321 goto unlock;
2324 * Set the next refresh time as if refresh check has failed.
2325 * Setting this to the retry time will do that. XXXMLG
2326 * If we are successful it will be reset using zone->refresh.
2328 isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
2330 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
2331 if (result |= ISC_R_SUCCESS)
2332 dns_zone_log(zone, ISC_LOG_WARNING,
2333 "isc_time_nowplusinterval() failed: %s",
2334 dns_result_totext(result));
2337 * When lacking user-specified timer values from the SOA,
2338 * do exponential backoff of the retry time up to a
2339 * maximum of six hours.
2341 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
2342 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
2344 zone->curmaster = 0;
2345 for (j = 0; j < zone->masterscnt; j++)
2346 zone->mastersok[j] = ISC_FALSE;
2347 /* initiate soa query */
2348 queue_soa_query(zone);
2349 unlock:
2350 UNLOCK_ZONE(zone);
2353 isc_result_t
2354 dns_zone_flush(dns_zone_t *zone) {
2355 isc_result_t result = ISC_R_SUCCESS;
2356 isc_boolean_t dumping;
2358 REQUIRE(DNS_ZONE_VALID(zone));
2360 LOCK_ZONE(zone);
2361 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
2362 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
2363 zone->masterfile != NULL) {
2364 result = ISC_R_ALREADYRUNNING;
2365 dumping = was_dumping(zone);
2366 } else
2367 dumping = ISC_TRUE;
2368 UNLOCK_ZONE(zone);
2369 if (!dumping)
2370 result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
2371 return (result);
2374 isc_result_t
2375 dns_zone_dump(dns_zone_t *zone) {
2376 isc_result_t result = ISC_R_ALREADYRUNNING;
2377 isc_boolean_t dumping;
2379 REQUIRE(DNS_ZONE_VALID(zone));
2381 LOCK_ZONE(zone);
2382 dumping = was_dumping(zone);
2383 UNLOCK_ZONE(zone);
2384 if (!dumping)
2385 result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
2386 return (result);
2389 static void
2390 zone_needdump(dns_zone_t *zone, unsigned int delay) {
2391 isc_time_t dumptime;
2392 isc_time_t now;
2395 * 'zone' locked by caller
2398 REQUIRE(DNS_ZONE_VALID(zone));
2399 REQUIRE(LOCKED_ZONE(zone));
2402 * Do we have a place to dump to and are we loaded?
2404 if (zone->masterfile == NULL ||
2405 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
2406 return;
2408 TIME_NOW(&now);
2409 /* add some noise */
2410 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
2412 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2413 if (isc_time_isepoch(&zone->dumptime) ||
2414 isc_time_compare(&zone->dumptime, &dumptime) > 0)
2415 zone->dumptime = dumptime;
2416 if (zone->task != NULL)
2417 zone_settimer(zone, &now);
2420 static void
2421 dump_done(void *arg, isc_result_t result) {
2422 const char me[] = "dump_done";
2423 dns_zone_t *zone = arg;
2424 dns_db_t *db;
2425 dns_dbversion_t *version;
2426 isc_boolean_t again = ISC_FALSE;
2428 REQUIRE(DNS_ZONE_VALID(zone));
2430 ENTER;
2432 if (result == ISC_R_SUCCESS && zone->journal != NULL &&
2433 zone->journalsize != -1) {
2434 isc_uint32_t serial;
2435 isc_result_t tresult;
2438 * We don't own these, zone->dctx must stay valid.
2440 db = dns_dumpctx_db(zone->dctx);
2441 version = dns_dumpctx_version(zone->dctx);
2443 tresult = dns_db_getsoaserial(db, version, &serial);
2444 if (tresult == ISC_R_SUCCESS) {
2445 tresult = dns_journal_compact(zone->mctx,
2446 zone->journal,
2447 serial,
2448 zone->journalsize);
2449 switch (tresult) {
2450 case ISC_R_SUCCESS:
2451 case ISC_R_NOSPACE:
2452 case ISC_R_NOTFOUND:
2453 dns_zone_log(zone, ISC_LOG_DEBUG(3),
2454 "dns_journal_compact: %s",
2455 dns_result_totext(tresult));
2456 break;
2457 default:
2458 dns_zone_log(zone, ISC_LOG_ERROR,
2459 "dns_journal_compact failed: %s",
2460 dns_result_totext(tresult));
2461 break;
2466 LOCK_ZONE(zone);
2467 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
2468 if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
2470 * Try again in a short while.
2472 zone_needdump(zone, DNS_DUMP_DELAY);
2473 } else if (result == ISC_R_SUCCESS &&
2474 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
2475 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
2476 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
2477 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2478 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
2479 isc_time_settoepoch(&zone->dumptime);
2480 again = ISC_TRUE;
2481 } else if (result == ISC_R_SUCCESS)
2482 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
2484 if (zone->dctx != NULL)
2485 dns_dumpctx_detach(&zone->dctx);
2486 zonemgr_putio(&zone->writeio);
2487 UNLOCK_ZONE(zone);
2488 if (again)
2489 (void)zone_dump(zone, ISC_FALSE);
2490 dns_zone_idetach(&zone);
2493 static isc_result_t
2494 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
2495 const char me[] = "zone_dump";
2496 isc_result_t result;
2497 dns_dbversion_t *version = NULL;
2498 isc_boolean_t again;
2499 dns_db_t *db = NULL;
2500 char *masterfile = NULL;
2503 * 'compact' MUST only be set if we are task locked.
2506 REQUIRE(DNS_ZONE_VALID(zone));
2507 ENTER;
2509 redo:
2510 LOCK_ZONE(zone);
2511 if (zone->db != NULL)
2512 dns_db_attach(zone->db, &db);
2513 if (zone->masterfile != NULL)
2514 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
2515 UNLOCK_ZONE(zone);
2516 if (db == NULL) {
2517 result = DNS_R_NOTLOADED;
2518 goto fail;
2520 if (masterfile == NULL) {
2521 result = DNS_R_NOMASTERFILE;
2522 goto fail;
2525 if (compact) {
2526 dns_zone_t *dummy = NULL;
2527 LOCK_ZONE(zone);
2528 zone_iattach(zone, &dummy);
2529 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
2530 zone_gotwritehandle, zone,
2531 &zone->writeio);
2532 if (result != ISC_R_SUCCESS)
2533 zone_idetach(&dummy);
2534 else
2535 result = DNS_R_CONTINUE;
2536 UNLOCK_ZONE(zone);
2537 } else {
2538 dns_db_currentversion(db, &version);
2539 result = dns_master_dump(zone->mctx, db, version,
2540 &dns_master_style_default,
2541 masterfile);
2542 dns_db_closeversion(db, &version, ISC_FALSE);
2544 fail:
2545 if (db != NULL)
2546 dns_db_detach(&db);
2547 if (masterfile != NULL)
2548 isc_mem_free(zone->mctx, masterfile);
2549 masterfile = NULL;
2551 if (result == DNS_R_CONTINUE)
2552 return (ISC_R_SUCCESS); /* XXXMPA */
2554 again = ISC_FALSE;
2555 LOCK_ZONE(zone);
2556 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
2557 if (result != ISC_R_SUCCESS) {
2559 * Try again in a short while.
2561 zone_needdump(zone, DNS_DUMP_DELAY);
2562 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
2563 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
2564 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
2565 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2566 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
2567 isc_time_settoepoch(&zone->dumptime);
2568 again = ISC_TRUE;
2569 } else
2570 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
2571 UNLOCK_ZONE(zone);
2572 if (again)
2573 goto redo;
2575 return (result);
2578 static isc_result_t
2579 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style) {
2580 isc_result_t result;
2581 dns_dbversion_t *version = NULL;
2582 dns_db_t *db = NULL;
2584 REQUIRE(DNS_ZONE_VALID(zone));
2586 LOCK_ZONE(zone);
2587 if (zone->db != NULL)
2588 dns_db_attach(zone->db, &db);
2589 UNLOCK_ZONE(zone);
2590 if (db == NULL)
2591 return (DNS_R_NOTLOADED);
2593 dns_db_currentversion(db, &version);
2594 result = dns_master_dumptostream(zone->mctx, db, version, style, fd);
2595 dns_db_closeversion(db, &version, ISC_FALSE);
2596 dns_db_detach(&db);
2597 return (result);
2600 isc_result_t
2601 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
2602 return dumptostream(zone, fd, &dns_master_style_default);
2605 isc_result_t
2606 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
2607 return dumptostream(zone, fd, &dns_master_style_full);
2610 void
2611 dns_zone_unload(dns_zone_t *zone) {
2612 REQUIRE(DNS_ZONE_VALID(zone));
2614 LOCK_ZONE(zone);
2615 zone_unload(zone);
2616 UNLOCK_ZONE(zone);
2619 static void
2620 notify_cancel(dns_zone_t *zone) {
2621 dns_notify_t *notify;
2624 * 'zone' locked by caller.
2627 REQUIRE(LOCKED_ZONE(zone));
2629 for (notify = ISC_LIST_HEAD(zone->notifies);
2630 notify != NULL;
2631 notify = ISC_LIST_NEXT(notify, link)) {
2632 if (notify->find != NULL)
2633 dns_adb_cancelfind(notify->find);
2634 if (notify->request != NULL)
2635 dns_request_cancel(notify->request);
2639 static void
2640 zone_unload(dns_zone_t *zone) {
2643 * 'zone' locked by caller.
2646 REQUIRE(LOCKED_ZONE(zone));
2648 dns_db_detach(&zone->db);
2649 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
2650 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2653 void
2654 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
2655 REQUIRE(DNS_ZONE_VALID(zone));
2656 REQUIRE(val > 0);
2658 zone->minrefresh = val;
2661 void
2662 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
2663 REQUIRE(DNS_ZONE_VALID(zone));
2664 REQUIRE(val > 0);
2666 zone->maxrefresh = val;
2669 void
2670 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
2671 REQUIRE(DNS_ZONE_VALID(zone));
2672 REQUIRE(val > 0);
2674 zone->minretry = val;
2677 void
2678 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
2679 REQUIRE(DNS_ZONE_VALID(zone));
2680 REQUIRE(val > 0);
2682 zone->maxretry = val;
2685 static isc_boolean_t
2686 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
2687 dns_notify_t *notify;
2689 for (notify = ISC_LIST_HEAD(zone->notifies);
2690 notify != NULL;
2691 notify = ISC_LIST_NEXT(notify, link)) {
2692 if (notify->request != NULL)
2693 continue;
2694 if (name != NULL && dns_name_dynamic(&notify->ns) &&
2695 dns_name_equal(name, &notify->ns))
2696 return (ISC_TRUE);
2697 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
2698 return (ISC_TRUE);
2700 return (ISC_FALSE);
2703 static void
2704 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
2705 isc_mem_t *mctx;
2708 * Caller holds zone lock.
2710 REQUIRE(DNS_NOTIFY_VALID(notify));
2712 if (notify->zone != NULL) {
2713 if (!locked)
2714 LOCK_ZONE(notify->zone);
2715 REQUIRE(LOCKED_ZONE(notify->zone));
2716 if (ISC_LINK_LINKED(notify, link))
2717 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
2718 if (!locked)
2719 UNLOCK_ZONE(notify->zone);
2720 if (locked)
2721 zone_idetach(&notify->zone);
2722 else
2723 dns_zone_idetach(&notify->zone);
2725 if (notify->find != NULL)
2726 dns_adb_destroyfind(&notify->find);
2727 if (notify->request != NULL)
2728 dns_request_destroy(&notify->request);
2729 if (dns_name_dynamic(&notify->ns))
2730 dns_name_free(&notify->ns, notify->mctx);
2731 mctx = notify->mctx;
2732 isc_mem_put(notify->mctx, notify, sizeof(*notify));
2733 isc_mem_detach(&mctx);
2736 static isc_result_t
2737 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
2738 dns_notify_t *notify;
2740 REQUIRE(notifyp != NULL && *notifyp == NULL);
2742 notify = isc_mem_get(mctx, sizeof(*notify));
2743 if (notify == NULL)
2744 return (ISC_R_NOMEMORY);
2746 notify->mctx = NULL;
2747 isc_mem_attach(mctx, &notify->mctx);
2748 notify->flags = flags;
2749 notify->zone = NULL;
2750 notify->find = NULL;
2751 notify->request = NULL;
2752 isc_sockaddr_any(&notify->dst);
2753 dns_name_init(&notify->ns, NULL);
2754 ISC_LINK_INIT(notify, link);
2755 notify->magic = NOTIFY_MAGIC;
2756 *notifyp = notify;
2757 return (ISC_R_SUCCESS);
2761 * XXXAG should check for DNS_ZONEFLG_EXITING
2763 static void
2764 process_adb_event(isc_task_t *task, isc_event_t *ev) {
2765 dns_notify_t *notify;
2766 isc_eventtype_t result;
2768 UNUSED(task);
2770 notify = ev->ev_arg;
2771 REQUIRE(DNS_NOTIFY_VALID(notify));
2772 INSIST(task == notify->zone->task);
2773 result = ev->ev_type;
2774 isc_event_free(&ev);
2775 if (result == DNS_EVENT_ADBMOREADDRESSES) {
2776 dns_adb_destroyfind(&notify->find);
2777 notify_find_address(notify);
2778 return;
2780 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
2781 LOCK_ZONE(notify->zone);
2782 notify_send(notify);
2783 UNLOCK_ZONE(notify->zone);
2785 notify_destroy(notify, ISC_FALSE);
2788 static void
2789 notify_find_address(dns_notify_t *notify) {
2790 isc_result_t result;
2791 unsigned int options;
2793 REQUIRE(DNS_NOTIFY_VALID(notify));
2794 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
2795 DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
2797 if (notify->zone->view->adb == NULL)
2798 goto destroy;
2800 result = dns_adb_createfind(notify->zone->view->adb,
2801 notify->zone->task,
2802 process_adb_event, notify,
2803 &notify->ns, dns_rootname,
2804 options, 0, NULL,
2805 notify->zone->view->dstport,
2806 &notify->find);
2808 /* Something failed? */
2809 if (result != ISC_R_SUCCESS)
2810 goto destroy;
2812 /* More addresses pending? */
2813 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
2814 return;
2816 /* We have as many addresses as we can get. */
2817 LOCK_ZONE(notify->zone);
2818 notify_send(notify);
2819 UNLOCK_ZONE(notify->zone);
2821 destroy:
2822 notify_destroy(notify, ISC_FALSE);
2826 static isc_result_t
2827 notify_send_queue(dns_notify_t *notify) {
2828 isc_event_t *e;
2829 isc_result_t result;
2831 e = isc_event_allocate(notify->mctx, NULL,
2832 DNS_EVENT_NOTIFYSENDTOADDR,
2833 notify_send_toaddr,
2834 notify, sizeof(isc_event_t));
2835 if (e == NULL)
2836 return (ISC_R_NOMEMORY);
2837 e->ev_arg = notify;
2838 e->ev_sender = NULL;
2839 result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
2840 notify->zone->task, &e);
2841 if (result != ISC_R_SUCCESS)
2842 isc_event_free(&e);
2843 return (result);
2846 static void
2847 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
2848 dns_notify_t *notify;
2849 isc_result_t result;
2850 dns_message_t *message = NULL;
2851 isc_netaddr_t dstip;
2852 dns_tsigkey_t *key = NULL;
2853 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2854 isc_sockaddr_t src;
2855 int timeout;
2857 notify = event->ev_arg;
2858 REQUIRE(DNS_NOTIFY_VALID(notify));
2860 UNUSED(task);
2862 LOCK_ZONE(notify->zone);
2864 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
2865 result = ISC_R_CANCELED;
2866 goto cleanup;
2869 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
2870 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
2871 notify->zone->view->requestmgr == NULL ||
2872 notify->zone->db == NULL) {
2873 result = ISC_R_CANCELED;
2874 goto cleanup;
2878 * The raw IPv4 address should also exist. Don't send to the
2879 * mapped form.
2881 if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
2882 IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
2883 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
2884 notify_log(notify->zone, ISC_LOG_DEBUG(3),
2885 "notify: ignoring IPv6 mapped IPV4 address: %s",
2886 addrbuf);
2887 result = ISC_R_CANCELED;
2888 goto cleanup;
2891 result = notify_createmessage(notify->zone, notify->flags, &message);
2892 if (result != ISC_R_SUCCESS)
2893 goto cleanup;
2895 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
2896 (void)dns_view_getpeertsig(notify->zone->view, &dstip, &key);
2898 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
2899 notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
2900 addrbuf);
2901 switch (isc_sockaddr_pf(&notify->dst)) {
2902 case PF_INET:
2903 src = notify->zone->notifysrc4;
2904 break;
2905 case PF_INET6:
2906 src = notify->zone->notifysrc6;
2907 break;
2908 default:
2909 result = ISC_R_NOTIMPLEMENTED;
2910 goto cleanup_key;
2912 timeout = 15;
2913 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
2914 timeout = 30;
2915 result = dns_request_createvia2(notify->zone->view->requestmgr,
2916 message, &src, &notify->dst, 0, key,
2917 timeout * 3, timeout,
2918 notify->zone->task, notify_done,
2919 notify, &notify->request);
2920 cleanup_key:
2921 if (key != NULL)
2922 dns_tsigkey_detach(&key);
2923 dns_message_destroy(&message);
2924 cleanup:
2925 UNLOCK_ZONE(notify->zone);
2926 if (result != ISC_R_SUCCESS)
2927 notify_destroy(notify, ISC_FALSE);
2928 isc_event_free(&event);
2931 static void
2932 notify_send(dns_notify_t *notify) {
2933 dns_adbaddrinfo_t *ai;
2934 isc_sockaddr_t dst;
2935 isc_result_t result;
2936 dns_notify_t *new = NULL;
2939 * Zone lock held by caller.
2941 REQUIRE(DNS_NOTIFY_VALID(notify));
2942 REQUIRE(LOCKED_ZONE(notify->zone));
2944 for (ai = ISC_LIST_HEAD(notify->find->list);
2945 ai != NULL;
2946 ai = ISC_LIST_NEXT(ai, publink)) {
2947 dst = ai->sockaddr;
2948 if (notify_isqueued(notify->zone, NULL, &dst))
2949 continue;
2950 new = NULL;
2951 result = notify_create(notify->mctx,
2952 (notify->flags & DNS_NOTIFY_NOSOA),
2953 &new);
2954 if (result != ISC_R_SUCCESS)
2955 goto cleanup;
2956 zone_iattach(notify->zone, &new->zone);
2957 ISC_LIST_APPEND(new->zone->notifies, new, link);
2958 new->dst = dst;
2959 result = notify_send_queue(new);
2960 if (result != ISC_R_SUCCESS)
2961 goto cleanup;
2962 new = NULL;
2965 cleanup:
2966 if (new != NULL)
2967 notify_destroy(new, ISC_TRUE);
2970 void
2971 dns_zone_notify(dns_zone_t *zone) {
2972 isc_time_t now;
2974 REQUIRE(DNS_ZONE_VALID(zone));
2976 LOCK_ZONE(zone);
2977 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
2979 TIME_NOW(&now);
2980 zone_settimer(zone, &now);
2981 UNLOCK_ZONE(zone);
2984 static void
2985 zone_notify(dns_zone_t *zone) {
2986 dns_dbnode_t *node = NULL;
2987 dns_dbversion_t *version = NULL;
2988 dns_name_t *origin = NULL;
2989 dns_name_t master;
2990 dns_rdata_ns_t ns;
2991 dns_rdata_soa_t soa;
2992 isc_uint32_t serial;
2993 dns_rdata_t rdata = DNS_RDATA_INIT;
2994 dns_rdataset_t nsrdset;
2995 dns_rdataset_t soardset;
2996 isc_result_t result;
2997 dns_notify_t *notify = NULL;
2998 unsigned int i;
2999 isc_sockaddr_t dst;
3000 isc_boolean_t isqueued;
3001 dns_notifytype_t notifytype;
3002 unsigned int flags = 0;
3003 isc_boolean_t loggednotify = ISC_FALSE;
3004 dns_db_t *db = NULL;
3006 REQUIRE(DNS_ZONE_VALID(zone));
3008 LOCK_ZONE(zone);
3009 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
3010 notifytype = zone->notifytype;
3011 UNLOCK_ZONE(zone);
3013 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3014 return;
3016 if (notifytype == dns_notifytype_no)
3017 return;
3019 LOCK_ZONE(zone);
3020 if (zone->db != NULL)
3021 dns_db_attach(zone->db, &db);
3022 UNLOCK_ZONE(zone);
3023 if (db == NULL)
3024 return;
3026 origin = &zone->origin;
3029 * If the zone is dialup we are done as we don't want to send
3030 * the current soa so as to force a refresh query.
3032 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
3033 flags |= DNS_NOTIFY_NOSOA;
3036 * Get SOA RRset.
3038 dns_db_currentversion(db, &version);
3039 result = dns_db_findnode(db, origin, ISC_FALSE, &node);
3040 if (result != ISC_R_SUCCESS)
3041 goto cleanup1;
3043 dns_rdataset_init(&soardset);
3044 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
3045 dns_rdatatype_none, 0, &soardset, NULL);
3046 if (result != ISC_R_SUCCESS)
3047 goto cleanup2;
3050 * Find serial and master server's name.
3052 dns_name_init(&master, NULL);
3053 result = dns_rdataset_first(&soardset);
3054 if (result != ISC_R_SUCCESS)
3055 goto cleanup3;
3056 dns_rdataset_current(&soardset, &rdata);
3057 result = dns_rdata_tostruct(&rdata, &soa, NULL);
3058 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3059 dns_rdata_reset(&rdata);
3060 result = dns_name_dup(&soa.origin, zone->mctx, &master);
3061 serial = soa.serial;
3062 dns_rdataset_disassociate(&soardset);
3063 if (result != ISC_R_SUCCESS)
3064 goto cleanup3;
3067 * Enqueue notify requests for 'also-notify' servers.
3069 LOCK_ZONE(zone);
3070 for (i = 0; i < zone->notifycnt; i++) {
3071 dst = zone->notify[i];
3072 if (notify_isqueued(zone, NULL, &dst))
3073 continue;
3074 result = notify_create(zone->mctx, flags, &notify);
3075 if (result != ISC_R_SUCCESS)
3076 continue;
3077 zone_iattach(zone, &notify->zone);
3078 notify->dst = dst;
3079 ISC_LIST_APPEND(zone->notifies, notify, link);
3080 result = notify_send_queue(notify);
3081 if (result != ISC_R_SUCCESS)
3082 notify_destroy(notify, ISC_TRUE);
3083 if (!loggednotify) {
3084 notify_log(zone, ISC_LOG_INFO,
3085 "sending notifies (serial %u)",
3086 serial);
3087 loggednotify = ISC_TRUE;
3089 notify = NULL;
3091 UNLOCK_ZONE(zone);
3093 if (notifytype == dns_notifytype_explicit)
3094 goto cleanup3;
3097 * Process NS RRset to generate notifies.
3100 dns_rdataset_init(&nsrdset);
3101 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
3102 dns_rdatatype_none, 0, &nsrdset, NULL);
3103 if (result != ISC_R_SUCCESS)
3104 goto cleanup3;
3106 result = dns_rdataset_first(&nsrdset);
3107 while (result == ISC_R_SUCCESS) {
3108 dns_rdataset_current(&nsrdset, &rdata);
3109 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3110 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3111 dns_rdata_reset(&rdata);
3113 * don't notify the master server.
3115 if (dns_name_compare(&master, &ns.name) == 0) {
3116 result = dns_rdataset_next(&nsrdset);
3117 continue;
3120 if (!loggednotify) {
3121 notify_log(zone, ISC_LOG_INFO,
3122 "sending notifies (serial %u)",
3123 serial);
3124 loggednotify = ISC_TRUE;
3127 LOCK_ZONE(zone);
3128 isqueued = notify_isqueued(zone, &ns.name, NULL);
3129 UNLOCK_ZONE(zone);
3130 if (isqueued) {
3131 result = dns_rdataset_next(&nsrdset);
3132 continue;
3134 result = notify_create(zone->mctx, flags, &notify);
3135 if (result != ISC_R_SUCCESS)
3136 continue;
3137 dns_zone_iattach(zone, &notify->zone);
3138 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
3139 if (result != ISC_R_SUCCESS) {
3140 LOCK_ZONE(zone);
3141 notify_destroy(notify, ISC_TRUE);
3142 UNLOCK_ZONE(zone);
3143 continue;
3145 LOCK_ZONE(zone);
3146 ISC_LIST_APPEND(zone->notifies, notify, link);
3147 UNLOCK_ZONE(zone);
3148 notify_find_address(notify);
3149 notify = NULL;
3150 result = dns_rdataset_next(&nsrdset);
3152 dns_rdataset_disassociate(&nsrdset);
3154 cleanup3:
3155 if (dns_name_dynamic(&master))
3156 dns_name_free(&master, zone->mctx);
3157 cleanup2:
3158 dns_db_detachnode(db, &node);
3159 cleanup1:
3160 dns_db_closeversion(db, &version, ISC_FALSE);
3161 dns_db_detach(&db);
3164 /***
3165 *** Private
3166 ***/
3168 static inline isc_result_t
3169 save_nsrrset(dns_message_t *message, dns_name_t *name,
3170 dns_db_t *db, dns_dbversion_t *version)
3172 dns_rdataset_t *nsrdataset = NULL;
3173 dns_rdataset_t *rdataset = NULL;
3174 dns_dbnode_t *node = NULL;
3175 dns_rdata_ns_t ns;
3176 isc_result_t result;
3177 dns_rdata_t rdata = DNS_RDATA_INIT;
3180 * Extract NS RRset from message.
3182 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
3183 dns_rdatatype_ns, dns_rdatatype_none,
3184 NULL, &nsrdataset);
3185 if (result != ISC_R_SUCCESS)
3186 goto fail;
3189 * Add NS rdataset.
3191 result = dns_db_findnode(db, name, ISC_TRUE, &node);
3192 if (result != ISC_R_SUCCESS)
3193 goto fail;
3194 result = dns_db_addrdataset(db, node, version, 0,
3195 nsrdataset, 0, NULL);
3196 dns_db_detachnode(db, &node);
3197 if (result != ISC_R_SUCCESS)
3198 goto fail;
3200 * Add glue rdatasets.
3202 for (result = dns_rdataset_first(nsrdataset);
3203 result == ISC_R_SUCCESS;
3204 result = dns_rdataset_next(nsrdataset)) {
3205 dns_rdataset_current(nsrdataset, &rdata);
3206 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3207 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3208 dns_rdata_reset(&rdata);
3209 if (!dns_name_issubdomain(&ns.name, name))
3210 continue;
3211 rdataset = NULL;
3212 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
3213 &ns.name, dns_rdatatype_aaaa,
3214 dns_rdatatype_none, NULL,
3215 &rdataset);
3216 if (result == ISC_R_SUCCESS) {
3217 result = dns_db_findnode(db, &ns.name,
3218 ISC_TRUE, &node);
3219 if (result != ISC_R_SUCCESS)
3220 goto fail;
3221 result = dns_db_addrdataset(db, node, version, 0,
3222 rdataset, 0, NULL);
3223 dns_db_detachnode(db, &node);
3224 if (result != ISC_R_SUCCESS)
3225 goto fail;
3227 rdataset = NULL;
3228 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
3229 &ns.name, dns_rdatatype_a,
3230 dns_rdatatype_none, NULL,
3231 &rdataset);
3232 if (result == ISC_R_SUCCESS) {
3233 result = dns_db_findnode(db, &ns.name,
3234 ISC_TRUE, &node);
3235 if (result != ISC_R_SUCCESS)
3236 goto fail;
3237 result = dns_db_addrdataset(db, node, version, 0,
3238 rdataset, 0, NULL);
3239 dns_db_detachnode(db, &node);
3240 if (result != ISC_R_SUCCESS)
3241 goto fail;
3244 if (result != ISC_R_NOMORE)
3245 goto fail;
3247 return (ISC_R_SUCCESS);
3249 fail:
3250 return (result);
3253 static void
3254 stub_callback(isc_task_t *task, isc_event_t *event) {
3255 const char me[] = "stub_callback";
3256 dns_requestevent_t *revent = (dns_requestevent_t *)event;
3257 dns_stub_t *stub = NULL;
3258 dns_message_t *msg = NULL;
3259 dns_zone_t *zone = NULL;
3260 char master[ISC_SOCKADDR_FORMATSIZE];
3261 char source[ISC_SOCKADDR_FORMATSIZE];
3262 isc_uint32_t nscnt, cnamecnt;
3263 isc_result_t result;
3264 isc_time_t now;
3265 isc_boolean_t exiting = ISC_FALSE;
3266 isc_interval_t i;
3267 unsigned int j;
3269 stub = revent->ev_arg;
3270 INSIST(DNS_STUB_VALID(stub));
3272 UNUSED(task);
3274 zone = stub->zone;
3276 ENTER;
3278 TIME_NOW(&now);
3280 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
3281 zone_debuglog(zone, me, 1, "exiting");
3282 exiting = ISC_TRUE;
3283 goto next_master;
3286 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
3287 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
3289 if (revent->result != ISC_R_SUCCESS) {
3290 if (revent->result == ISC_R_TIMEDOUT &&
3291 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
3292 LOCK_ZONE(zone);
3293 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
3294 UNLOCK_ZONE(zone);
3295 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3296 "refreshing stub: timeout retrying "
3297 " without EDNS master %s (source %s)",
3298 master, source);
3299 goto same_master;
3301 dns_zone_log(zone, ISC_LOG_INFO,
3302 "could not refresh stub from master %s"
3303 " (source %s): %s", master, source,
3304 dns_result_totext(revent->result));
3305 goto next_master;
3308 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3309 if (result != ISC_R_SUCCESS)
3310 goto next_master;
3312 result = dns_request_getresponse(revent->request, msg, 0);
3313 if (result != ISC_R_SUCCESS)
3314 goto next_master;
3317 * Unexpected rcode.
3319 if (msg->rcode != dns_rcode_noerror) {
3320 char rcode[128];
3321 isc_buffer_t rb;
3323 isc_buffer_init(&rb, rcode, sizeof(rcode));
3324 (void)dns_rcode_totext(msg->rcode, &rb);
3326 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
3327 (msg->rcode == dns_rcode_servfail ||
3328 msg->rcode == dns_rcode_notimp ||
3329 msg->rcode == dns_rcode_formerr)) {
3330 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3331 "refreshing stub: rcode (%.*s) retrying "
3332 "without EDNS master %s (source %s)",
3333 (int)rb.used, rcode, master, source);
3334 LOCK_ZONE(zone);
3335 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
3336 UNLOCK_ZONE(zone);
3337 goto same_master;
3340 dns_zone_log(zone, ISC_LOG_INFO,
3341 "refreshing stub: "
3342 "unexpected rcode (%.*s) from %s (source %s)",
3343 (int)rb.used, rcode, master, source);
3344 goto next_master;
3348 * We need complete messages.
3350 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
3351 if (dns_request_usedtcp(revent->request)) {
3352 dns_zone_log(zone, ISC_LOG_INFO,
3353 "refreshing stub: truncated TCP "
3354 "response from master %s (source %s)",
3355 master, source);
3356 goto next_master;
3358 LOCK_ZONE(zone);
3359 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
3360 UNLOCK_ZONE(zone);
3361 goto same_master;
3365 * If non-auth log and next master.
3367 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
3368 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
3369 "non-authoritative answer from "
3370 "master %s (source %s)", master, source);
3371 goto next_master;
3375 * Sanity checks.
3377 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
3378 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
3380 if (cnamecnt != 0) {
3381 dns_zone_log(zone, ISC_LOG_INFO,
3382 "refreshing stub: unexpected CNAME response "
3383 "from master %s (source %s)", master, source);
3384 goto next_master;
3387 if (nscnt == 0) {
3388 dns_zone_log(zone, ISC_LOG_INFO,
3389 "refreshing stub: no NS records in response "
3390 "from master %s (source %s)", master, source);
3391 goto next_master;
3395 * Save answer.
3397 result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
3398 if (result != ISC_R_SUCCESS) {
3399 dns_zone_log(zone, ISC_LOG_INFO,
3400 "refreshing stub: unable to save NS records "
3401 "from master %s (source %s)", master, source);
3402 goto next_master;
3406 * Tidy up.
3408 dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
3409 LOCK_ZONE(zone);
3410 if (zone->db == NULL)
3411 dns_db_attach(stub->db, &zone->db);
3412 UNLOCK_ZONE(zone);
3413 dns_db_detach(&stub->db);
3415 if (zone->masterfile != NULL) {
3416 dns_zone_dump(zone);
3417 TIME_NOW(&zone->loadtime);
3420 dns_message_destroy(&msg);
3421 isc_event_free(&event);
3422 LOCK_ZONE(zone);
3423 dns_request_destroy(&zone->request);
3424 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3425 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
3426 isc_interval_set(&i, zone->expire, 0);
3427 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
3428 zone_settimer(zone, &now);
3429 UNLOCK_ZONE(zone);
3430 goto free_stub;
3432 next_master:
3433 if (stub->version != NULL)
3434 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
3435 if (stub->db != NULL)
3436 dns_db_detach(&stub->db);
3437 if (msg != NULL)
3438 dns_message_destroy(&msg);
3439 isc_event_free(&event);
3440 LOCK_ZONE(zone);
3441 dns_request_destroy(&zone->request);
3443 * Skip to next failed / untried master.
3445 do {
3446 zone->curmaster++;
3447 } while (zone->curmaster < zone->masterscnt &&
3448 zone->mastersok[zone->curmaster]);
3449 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
3450 if (exiting || zone->curmaster >= zone->masterscnt) {
3451 isc_boolean_t done = ISC_TRUE;
3452 if (!exiting &&
3453 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
3454 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
3456 * Did we get a good answer from all the masters?
3458 for (j = 0; j < zone->masterscnt; j++)
3459 if (zone->mastersok[j] == ISC_FALSE) {
3460 done = ISC_FALSE;
3461 break;
3463 } else
3464 done = ISC_TRUE;
3465 if (!done) {
3466 zone->curmaster = 0;
3468 * Find the next failed master.
3470 while (zone->curmaster < zone->masterscnt &&
3471 zone->mastersok[zone->curmaster])
3472 zone->curmaster++;
3473 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
3474 } else {
3475 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3477 zone_settimer(zone, &now);
3478 UNLOCK_ZONE(zone);
3479 goto free_stub;
3482 queue_soa_query(zone);
3483 UNLOCK_ZONE(zone);
3484 goto free_stub;
3486 same_master:
3487 if (msg != NULL)
3488 dns_message_destroy(&msg);
3489 isc_event_free(&event);
3490 LOCK_ZONE(zone);
3491 dns_request_destroy(&zone->request);
3492 UNLOCK_ZONE(zone);
3493 ns_query(zone, NULL, stub);
3494 goto done;
3496 free_stub:
3497 stub->magic = 0;
3498 dns_zone_idetach(&stub->zone);
3499 INSIST(stub->db == NULL);
3500 INSIST(stub->version == NULL);
3501 isc_mem_put(stub->mctx, stub, sizeof(*stub));
3503 done:
3504 INSIST(event == NULL);
3505 return;
3509 * An SOA query has finished (successfully or not).
3511 static void
3512 refresh_callback(isc_task_t *task, isc_event_t *event) {
3513 const char me[] = "refresh_callback";
3514 dns_requestevent_t *revent = (dns_requestevent_t *)event;
3515 dns_zone_t *zone;
3516 dns_message_t *msg = NULL;
3517 isc_uint32_t soacnt, cnamecnt, soacount, nscount;
3518 isc_time_t now;
3519 char master[ISC_SOCKADDR_FORMATSIZE];
3520 char source[ISC_SOCKADDR_FORMATSIZE];
3521 dns_rdataset_t *rdataset = NULL;
3522 dns_rdata_t rdata = DNS_RDATA_INIT;
3523 dns_rdata_soa_t soa;
3524 isc_result_t result;
3525 isc_uint32_t serial;
3526 unsigned int j;
3528 zone = revent->ev_arg;
3529 INSIST(DNS_ZONE_VALID(zone));
3531 UNUSED(task);
3533 ENTER;
3536 * if timeout log and next master;
3539 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
3540 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
3542 TIME_NOW(&now);
3544 if (revent->result != ISC_R_SUCCESS) {
3545 if (revent->result == ISC_R_TIMEDOUT &&
3546 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
3547 LOCK_ZONE(zone);
3548 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
3549 UNLOCK_ZONE(zone);
3550 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3551 "refresh: timeout retrying without EDNS "
3552 "master %s (source %s)", master, source);
3553 goto same_master;
3555 if (revent->result == ISC_R_TIMEDOUT &&
3556 !dns_request_usedtcp(revent->request)) {
3557 dns_zone_log(zone, ISC_LOG_INFO,
3558 "refresh: retry limit for "
3559 "master %s exceeded (source %s)",
3560 master, source);
3561 /* Try with slave with TCP. */
3562 if (zone->type == dns_zone_slave) {
3563 LOCK_ZONE(zone);
3564 DNS_ZONE_SETFLAG(zone,
3565 DNS_ZONEFLG_SOABEFOREAXFR);
3566 UNLOCK_ZONE(zone);
3567 goto tcp_transfer;
3569 } else
3570 dns_zone_log(zone, ISC_LOG_INFO,
3571 "refresh: failure trying master "
3572 "%s (source %s): %s", master, source,
3573 dns_result_totext(revent->result));
3574 goto next_master;
3577 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3578 if (result != ISC_R_SUCCESS)
3579 goto next_master;
3580 result = dns_request_getresponse(revent->request, msg, 0);
3581 if (result != ISC_R_SUCCESS) {
3582 dns_zone_log(zone, ISC_LOG_INFO,
3583 "refresh: failure trying master "
3584 "%s (source %s): %s", master, source,
3585 dns_result_totext(result));
3586 goto next_master;
3590 * Unexpected rcode.
3592 if (msg->rcode != dns_rcode_noerror) {
3593 char rcode[128];
3594 isc_buffer_t rb;
3596 isc_buffer_init(&rb, rcode, sizeof(rcode));
3597 (void)dns_rcode_totext(msg->rcode, &rb);
3599 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
3600 (msg->rcode == dns_rcode_servfail ||
3601 msg->rcode == dns_rcode_notimp ||
3602 msg->rcode == dns_rcode_formerr)) {
3603 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3604 "refresh: rcode (%.*s) retrying without "
3605 "EDNS master %s (source %s)",
3606 (int)rb.used, rcode, master, source);
3607 LOCK_ZONE(zone);
3608 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
3609 UNLOCK_ZONE(zone);
3610 goto same_master;
3612 dns_zone_log(zone, ISC_LOG_INFO,
3613 "refresh: unexpected rcode (%.*s) from "
3614 "master %s (source %s)", (int)rb.used, rcode,
3615 master, source);
3617 * Perhaps AXFR/IXFR is allowed even if SOA queries arn't.
3619 if (msg->rcode == dns_rcode_refused &&
3620 zone->type == dns_zone_slave)
3621 goto tcp_transfer;
3622 goto next_master;
3626 * If truncated punt to zone transfer which will query again.
3628 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
3629 if (zone->type == dns_zone_slave) {
3630 dns_zone_log(zone, ISC_LOG_INFO,
3631 "refresh: truncated UDP answer, "
3632 "initiating TCP zone xfer "
3633 "for master %s (source %s)",
3634 master, source);
3635 LOCK_ZONE(zone);
3636 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
3637 UNLOCK_ZONE(zone);
3638 goto tcp_transfer;
3639 } else {
3640 INSIST(zone->type == dns_zone_stub);
3641 if (dns_request_usedtcp(revent->request)) {
3642 dns_zone_log(zone, ISC_LOG_INFO,
3643 "refresh: truncated TCP response "
3644 "from master %s (source %s)",
3645 master, source);
3646 goto next_master;
3648 LOCK_ZONE(zone);
3649 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
3650 UNLOCK_ZONE(zone);
3651 goto same_master;
3656 * if non-auth log and next master;
3658 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
3659 dns_zone_log(zone, ISC_LOG_INFO,
3660 "refresh: non-authoritative answer from "
3661 "master %s (source %s)", master, source);
3662 goto next_master;
3665 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
3666 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
3667 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
3668 soacount = message_count(msg, DNS_SECTION_AUTHORITY,
3669 dns_rdatatype_soa);
3672 * There should not be a CNAME record at top of zone.
3674 if (cnamecnt != 0) {
3675 dns_zone_log(zone, ISC_LOG_INFO,
3676 "refresh: CNAME at top of zone "
3677 "in master %s (source %s)", master, source);
3678 goto next_master;
3682 * if referral log and next master;
3684 if (soacnt == 0 && soacount == 0 && nscount != 0) {
3685 dns_zone_log(zone, ISC_LOG_INFO,
3686 "refresh: referral response "
3687 "from master %s (source %s)", master, source);
3688 goto next_master;
3692 * if nodata log and next master;
3694 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
3695 dns_zone_log(zone, ISC_LOG_INFO,
3696 "refresh: NODATA response "
3697 "from master %s (source %s)", master, source);
3698 goto next_master;
3702 * Only one soa at top of zone.
3704 if (soacnt != 1) {
3705 dns_zone_log(zone, ISC_LOG_INFO,
3706 "refresh: answer SOA count (%d) != 1 "
3707 "from master %s (source %s)",
3708 soacnt, master, source);
3709 goto next_master;
3712 * Extract serial
3714 rdataset = NULL;
3715 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
3716 dns_rdatatype_soa, dns_rdatatype_none,
3717 NULL, &rdataset);
3718 if (result != ISC_R_SUCCESS) {
3719 dns_zone_log(zone, ISC_LOG_INFO,
3720 "refresh: unable to get SOA record "
3721 "from master %s (source %s)", master, source);
3722 goto next_master;
3725 result = dns_rdataset_first(rdataset);
3726 if (result != ISC_R_SUCCESS) {
3727 dns_zone_log(zone, ISC_LOG_INFO,
3728 "refresh: dns_rdataset_first() failed");
3729 goto next_master;
3732 dns_rdataset_current(rdataset, &rdata);
3733 result = dns_rdata_tostruct(&rdata, &soa, NULL);
3734 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3736 serial = soa.serial;
3738 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
3739 serial, zone->serial);
3740 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
3741 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
3742 isc_serial_gt(serial, zone->serial)) {
3743 tcp_transfer:
3744 isc_event_free(&event);
3745 LOCK_ZONE(zone);
3746 dns_request_destroy(&zone->request);
3747 UNLOCK_ZONE(zone);
3748 if (zone->type == dns_zone_slave) {
3749 queue_xfrin(zone);
3750 } else {
3751 INSIST(zone->type == dns_zone_stub);
3752 ns_query(zone, rdataset, NULL);
3754 if (msg != NULL)
3755 dns_message_destroy(&msg);
3756 } else if (isc_serial_eq(soa.serial, zone->serial)) {
3757 if (zone->masterfile != NULL) {
3758 result = ISC_R_FAILURE;
3759 if (zone->journal != NULL)
3760 result = isc_file_settime(zone->journal, &now);
3761 if (result == ISC_R_SUCCESS &&
3762 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
3763 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
3764 result = isc_file_settime(zone->masterfile,
3765 &now);
3766 } else if (result != ISC_R_SUCCESS)
3767 result = isc_file_settime(zone->masterfile,
3768 &now);
3769 /* Someone removed the file from underneath us! */
3770 if (result == ISC_R_FILENOTFOUND) {
3771 LOCK_ZONE(zone);
3772 zone_needdump(zone, DNS_DUMP_DELAY);
3773 UNLOCK_ZONE(zone);
3774 } else if (result != ISC_R_SUCCESS)
3775 dns_zone_log(zone, ISC_LOG_ERROR,
3776 "refresh: could not set file "
3777 "modification time of '%s': %s",
3778 zone->masterfile,
3779 dns_result_totext(result));
3781 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
3782 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
3783 zone->mastersok[zone->curmaster] = ISC_TRUE;
3784 goto next_master;
3785 } else {
3786 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
3787 dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
3788 "received from master %s < ours (%u)",
3789 soa.serial, master, zone->serial);
3790 else
3791 zone_debuglog(zone, me, 1, "ahead");
3792 zone->mastersok[zone->curmaster] = ISC_TRUE;
3793 goto next_master;
3795 if (msg != NULL)
3796 dns_message_destroy(&msg);
3797 goto detach;
3799 next_master:
3800 if (msg != NULL)
3801 dns_message_destroy(&msg);
3802 isc_event_free(&event);
3803 LOCK_ZONE(zone);
3804 dns_request_destroy(&zone->request);
3806 * Skip to next failed / untried master.
3808 do {
3809 zone->curmaster++;
3810 } while (zone->curmaster < zone->masterscnt &&
3811 zone->mastersok[zone->curmaster]);
3812 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
3813 if (zone->curmaster >= zone->masterscnt) {
3814 isc_boolean_t done = ISC_TRUE;
3815 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
3816 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
3818 * Did we get a good answer from all the masters?
3820 for (j = 0; j < zone->masterscnt; j++)
3821 if (zone->mastersok[j] == ISC_FALSE) {
3822 done = ISC_FALSE;
3823 break;
3825 } else
3826 done = ISC_TRUE;
3827 if (!done) {
3828 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
3829 zone->curmaster = 0;
3831 * Find the next failed master.
3833 while (zone->curmaster < zone->masterscnt &&
3834 zone->mastersok[zone->curmaster])
3835 zone->curmaster++;
3836 goto requeue;
3838 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3839 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
3840 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
3841 zone->refreshtime = now;
3843 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
3844 zone_settimer(zone, &now);
3845 UNLOCK_ZONE(zone);
3846 goto detach;
3849 requeue:
3850 queue_soa_query(zone);
3851 UNLOCK_ZONE(zone);
3852 goto detach;
3854 same_master:
3855 if (msg != NULL)
3856 dns_message_destroy(&msg);
3857 isc_event_free(&event);
3858 LOCK_ZONE(zone);
3859 dns_request_destroy(&zone->request);
3860 queue_soa_query(zone);
3861 UNLOCK_ZONE(zone);
3863 detach:
3864 dns_zone_idetach(&zone);
3865 return;
3868 static void
3869 queue_soa_query(dns_zone_t *zone) {
3870 const char me[] = "queue_soa_query";
3871 isc_event_t *e;
3872 dns_zone_t *dummy = NULL;
3873 isc_result_t result;
3875 ENTER;
3877 * Locked by caller
3879 REQUIRE(LOCKED_ZONE(zone));
3881 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
3882 cancel_refresh(zone);
3883 return;
3886 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
3887 soa_query, zone, sizeof(isc_event_t));
3888 if (e == NULL) {
3889 cancel_refresh(zone);
3890 return;
3894 * Attach so that we won't clean up
3895 * until the event is delivered.
3897 zone_iattach(zone, &dummy);
3899 e->ev_arg = zone;
3900 e->ev_sender = NULL;
3901 result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
3902 if (result != ISC_R_SUCCESS) {
3903 zone_idetach(&dummy);
3904 isc_event_free(&e);
3905 cancel_refresh(zone);
3909 static inline isc_result_t
3910 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
3911 dns_message_t **messagep)
3913 dns_message_t *message = NULL;
3914 dns_name_t *qname = NULL;
3915 dns_rdataset_t *qrdataset = NULL;
3916 isc_result_t result;
3918 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
3919 &message);
3920 if (result != ISC_R_SUCCESS)
3921 goto cleanup;
3923 message->opcode = dns_opcode_query;
3924 message->rdclass = zone->rdclass;
3926 result = dns_message_gettempname(message, &qname);
3927 if (result != ISC_R_SUCCESS)
3928 goto cleanup;
3930 result = dns_message_gettemprdataset(message, &qrdataset);
3931 if (result != ISC_R_SUCCESS)
3932 goto cleanup;
3935 * Make question.
3937 dns_name_init(qname, NULL);
3938 dns_name_clone(&zone->origin, qname);
3939 dns_rdataset_init(qrdataset);
3940 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
3941 ISC_LIST_APPEND(qname->list, qrdataset, link);
3942 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
3944 *messagep = message;
3945 return (ISC_R_SUCCESS);
3947 cleanup:
3948 if (qname != NULL)
3949 dns_message_puttempname(message, &qname);
3950 if (qrdataset != NULL)
3951 dns_message_puttemprdataset(message, &qrdataset);
3952 if (message != NULL)
3953 dns_message_destroy(&message);
3954 return (result);
3957 static isc_result_t
3958 add_opt(dns_message_t *message) {
3959 dns_rdataset_t *rdataset = NULL;
3960 dns_rdatalist_t *rdatalist = NULL;
3961 dns_rdata_t *rdata = NULL;
3962 isc_result_t result;
3964 result = dns_message_gettemprdatalist(message, &rdatalist);
3965 if (result != ISC_R_SUCCESS)
3966 goto cleanup;
3967 result = dns_message_gettemprdata(message, &rdata);
3968 if (result != ISC_R_SUCCESS)
3969 goto cleanup;
3970 result = dns_message_gettemprdataset(message, &rdataset);
3971 if (result != ISC_R_SUCCESS)
3972 goto cleanup;
3973 dns_rdataset_init(rdataset);
3975 rdatalist->type = dns_rdatatype_opt;
3976 rdatalist->covers = 0;
3979 * Set Maximum UDP buffer size.
3981 rdatalist->rdclass = SEND_BUFFER_SIZE;
3984 * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
3986 rdatalist->ttl = 0;
3989 * No EDNS options.
3991 rdata->data = NULL;
3992 rdata->length = 0;
3993 rdata->rdclass = rdatalist->rdclass;
3994 rdata->type = rdatalist->type;
3995 rdata->flags = 0;
3997 ISC_LIST_INIT(rdatalist->rdata);
3998 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
3999 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
4000 == ISC_R_SUCCESS);
4002 return (dns_message_setopt(message, rdataset));
4004 cleanup:
4005 if (rdatalist != NULL)
4006 dns_message_puttemprdatalist(message, &rdatalist);
4007 if (rdataset != NULL)
4008 dns_message_puttemprdataset(message, &rdataset);
4009 if (rdata != NULL)
4010 dns_message_puttemprdata(message, &rdata);
4012 return (result);
4015 static void
4016 soa_query(isc_task_t *task, isc_event_t *event) {
4017 const char me[] = "soa_query";
4018 isc_result_t result = ISC_R_FAILURE;
4019 dns_message_t *message = NULL;
4020 dns_zone_t *zone = event->ev_arg;
4021 dns_zone_t *dummy = NULL;
4022 isc_netaddr_t masterip;
4023 dns_tsigkey_t *key = NULL;
4024 isc_uint32_t options;
4025 isc_boolean_t cancel = ISC_TRUE;
4026 int timeout;
4027 isc_boolean_t have_xfrsource;
4029 REQUIRE(DNS_ZONE_VALID(zone));
4031 UNUSED(task);
4033 ENTER;
4035 LOCK_ZONE(zone);
4036 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
4037 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
4038 zone->view->requestmgr == NULL) {
4039 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
4040 cancel = ISC_FALSE;
4041 goto cleanup;
4045 * XXX Optimisation: Create message when zone is setup and reuse.
4047 result = create_query(zone, dns_rdatatype_soa, &message);
4048 if (result != ISC_R_SUCCESS)
4049 goto cleanup;
4051 again:
4052 INSIST(zone->masterscnt > 0);
4053 INSIST(zone->curmaster < zone->masterscnt);
4055 zone->masteraddr = zone->masters[zone->curmaster];
4057 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
4059 * First, look for a tsig key in the master statement, then
4060 * try for a server key.
4062 if ((zone->masterkeynames != NULL) &&
4063 (zone->masterkeynames[zone->curmaster] != NULL)) {
4064 dns_view_t *view = dns_zone_getview(zone);
4065 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
4066 result = dns_view_gettsig(view, keyname, &key);
4067 if (result != ISC_R_SUCCESS) {
4068 char namebuf[DNS_NAME_FORMATSIZE];
4069 dns_name_format(keyname, namebuf, sizeof(namebuf));
4070 dns_zone_log(zone, ISC_LOG_ERROR,
4071 "unable to find key: %s", namebuf);
4074 if (key == NULL)
4075 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
4077 have_xfrsource = ISC_FALSE;
4078 if (zone->view->peers != NULL) {
4079 dns_peer_t *peer = NULL;
4080 isc_boolean_t edns;
4081 result = dns_peerlist_peerbyaddr(zone->view->peers,
4082 &masterip, &peer);
4083 if (result == ISC_R_SUCCESS) {
4084 result = dns_peer_getsupportedns(peer, &edns);
4085 if (result == ISC_R_SUCCESS && !edns)
4086 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4087 result = dns_peer_gettransfersource(peer,
4088 &zone->sourceaddr);
4089 if (result == ISC_R_SUCCESS)
4090 have_xfrsource = ISC_TRUE;
4094 switch (isc_sockaddr_pf(&zone->masteraddr)) {
4095 case PF_INET:
4096 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
4097 if (isc_sockaddr_equal(&zone->altxfrsource4,
4098 &zone->xfrsource4))
4099 goto skip_master;
4100 zone->sourceaddr = zone->altxfrsource4;
4101 } else if (!have_xfrsource)
4102 zone->sourceaddr = zone->xfrsource4;
4103 break;
4104 case PF_INET6:
4105 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
4106 if (isc_sockaddr_equal(&zone->altxfrsource6,
4107 &zone->xfrsource6))
4108 goto skip_master;
4109 zone->sourceaddr = zone->altxfrsource6;
4110 } else if (!have_xfrsource)
4111 zone->sourceaddr = zone->xfrsource6;
4112 break;
4113 default:
4114 result = ISC_R_NOTIMPLEMENTED;
4115 goto cleanup;
4118 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
4119 DNS_REQUESTOPT_TCP : 0;
4121 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
4122 result = add_opt(message);
4123 if (result != ISC_R_SUCCESS)
4124 zone_debuglog(zone, me, 1,
4125 "unable to add opt record: %s",
4126 dns_result_totext(result));
4129 zone_iattach(zone, &dummy);
4130 timeout = 15;
4131 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
4132 timeout = 30;
4133 result = dns_request_createvia2(zone->view->requestmgr, message,
4134 &zone->sourceaddr, &zone->masteraddr,
4135 options, key, timeout * 3, timeout,
4136 zone->task, refresh_callback, zone,
4137 &zone->request);
4138 if (result != ISC_R_SUCCESS) {
4139 zone_idetach(&dummy);
4140 zone_debuglog(zone, me, 1,
4141 "dns_request_createvia2() failed: %s",
4142 dns_result_totext(result));
4143 goto cleanup;
4145 cancel = ISC_FALSE;
4147 cleanup:
4148 if (key != NULL)
4149 dns_tsigkey_detach(&key);
4150 if (result != ISC_R_SUCCESS)
4151 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4152 if (message != NULL)
4153 dns_message_destroy(&message);
4154 if (cancel)
4155 cancel_refresh(zone);
4156 isc_event_free(&event);
4157 UNLOCK_ZONE(zone);
4158 dns_zone_idetach(&zone);
4159 return;
4161 skip_master:
4162 if (key != NULL)
4163 dns_tsigkey_detach(&key);
4165 * Skip to next failed / untried master.
4167 do {
4168 zone->curmaster++;
4169 } while (zone->curmaster < zone->masterscnt &&
4170 zone->mastersok[zone->curmaster]);
4171 if (zone->curmaster < zone->masterscnt)
4172 goto again;
4173 zone->curmaster = 0;
4174 goto cleanup;
4177 static void
4178 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
4179 const char me[] = "ns_query";
4180 isc_result_t result;
4181 dns_message_t *message = NULL;
4182 isc_netaddr_t masterip;
4183 dns_tsigkey_t *key = NULL;
4184 dns_dbnode_t *node = NULL;
4185 int timeout;
4186 isc_boolean_t have_xfrsource = ISC_FALSE;
4188 REQUIRE(DNS_ZONE_VALID(zone));
4189 REQUIRE((soardataset != NULL && stub == NULL) ||
4190 (soardataset == NULL && stub != NULL));
4191 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
4193 ENTER;
4195 LOCK_ZONE(zone);
4196 if (stub == NULL) {
4197 stub = isc_mem_get(zone->mctx, sizeof(*stub));
4198 if (stub == NULL)
4199 goto cleanup;
4200 stub->magic = STUB_MAGIC;
4201 stub->mctx = zone->mctx;
4202 stub->zone = NULL;
4203 stub->db = NULL;
4204 stub->version = NULL;
4207 * Attach so that the zone won't disappear from under us.
4209 zone_iattach(zone, &stub->zone);
4212 * If a db exists we will update it, otherwise we create a
4213 * new one and attach it to the zone once we have the NS
4214 * RRset and glue.
4216 if (zone->db != NULL)
4217 dns_db_attach(zone->db, &stub->db);
4218 else {
4219 INSIST(zone->db_argc >= 1);
4220 result = dns_db_create(zone->mctx, zone->db_argv[0],
4221 &zone->origin, dns_dbtype_stub,
4222 zone->rdclass,
4223 zone->db_argc - 1,
4224 zone->db_argv + 1,
4225 &stub->db);
4226 if (result != ISC_R_SUCCESS) {
4227 dns_zone_log(zone, ISC_LOG_ERROR,
4228 "refreshing stub: "
4229 "could not create "
4230 "database: %s",
4231 dns_result_totext(result));
4232 goto cleanup;
4234 dns_db_settask(stub->db, zone->task);
4237 dns_db_newversion(stub->db, &stub->version);
4240 * Update SOA record.
4242 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
4243 &node);
4244 if (result != ISC_R_SUCCESS) {
4245 dns_zone_log(zone, ISC_LOG_INFO,
4246 "refreshing stub: "
4247 "dns_db_findnode() failed: %s",
4248 dns_result_totext(result));
4249 goto cleanup;
4252 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
4253 soardataset, 0, NULL);
4254 dns_db_detachnode(stub->db, &node);
4255 if (result != ISC_R_SUCCESS) {
4256 dns_zone_log(zone, ISC_LOG_INFO,
4257 "refreshing stub: "
4258 "dns_db_addrdataset() failed: %s",
4259 dns_result_totext(result));
4260 goto cleanup;
4265 * XXX Optimisation: Create message when zone is setup and reuse.
4267 result = create_query(zone, dns_rdatatype_ns, &message);
4269 INSIST(zone->masterscnt > 0);
4270 INSIST(zone->curmaster < zone->masterscnt);
4271 zone->masteraddr = zone->masters[zone->curmaster];
4273 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
4275 * First, look for a tsig key in the master statement, then
4276 * try for a server key.
4278 if ((zone->masterkeynames != NULL) &&
4279 (zone->masterkeynames[zone->curmaster] != NULL)) {
4280 dns_view_t *view = dns_zone_getview(zone);
4281 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
4282 result = dns_view_gettsig(view, keyname, &key);
4283 if (result != ISC_R_SUCCESS) {
4284 char namebuf[DNS_NAME_FORMATSIZE];
4285 dns_name_format(keyname, namebuf, sizeof(namebuf));
4286 dns_zone_log(zone, ISC_LOG_ERROR,
4287 "unable to find key: %s", namebuf);
4290 if (key == NULL)
4291 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
4293 if (zone->view->peers != NULL) {
4294 dns_peer_t *peer = NULL;
4295 isc_boolean_t edns;
4296 result = dns_peerlist_peerbyaddr(zone->view->peers,
4297 &masterip, &peer);
4298 if (result == ISC_R_SUCCESS) {
4299 result = dns_peer_getsupportedns(peer, &edns);
4300 if (result == ISC_R_SUCCESS && !edns)
4301 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4302 result = dns_peer_gettransfersource(peer,
4303 &zone->sourceaddr);
4304 if (result == ISC_R_SUCCESS)
4305 have_xfrsource = ISC_TRUE;
4309 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
4310 result = add_opt(message);
4311 if (result != ISC_R_SUCCESS)
4312 zone_debuglog(zone, me, 1,
4313 "unable to add opt record: %s",
4314 dns_result_totext(result));
4318 * Always use TCP so that we shouldn't truncate in additional section.
4320 switch (isc_sockaddr_pf(&zone->masteraddr)) {
4321 case PF_INET:
4322 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
4323 zone->sourceaddr = zone->altxfrsource4;
4324 else if (!have_xfrsource)
4325 zone->sourceaddr = zone->xfrsource4;
4326 break;
4327 case PF_INET6:
4328 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
4329 zone->sourceaddr = zone->altxfrsource6;
4330 else if (!have_xfrsource)
4331 zone->sourceaddr = zone->xfrsource6;
4332 break;
4333 default:
4334 result = ISC_R_NOTIMPLEMENTED;
4335 goto cleanup;
4337 timeout = 15;
4338 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
4339 timeout = 30;
4340 result = dns_request_createvia2(zone->view->requestmgr, message,
4341 &zone->sourceaddr, &zone->masteraddr,
4342 DNS_REQUESTOPT_TCP, key, timeout * 3,
4343 timeout, zone->task, stub_callback,
4344 stub, &zone->request);
4345 if (result != ISC_R_SUCCESS) {
4346 zone_debuglog(zone, me, 1,
4347 "dns_request_createvia() failed: %s",
4348 dns_result_totext(result));
4349 goto cleanup;
4351 dns_message_destroy(&message);
4352 goto unlock;
4354 cleanup:
4355 cancel_refresh(zone);
4356 if (stub != NULL) {
4357 stub->magic = 0;
4358 if (stub->version != NULL)
4359 dns_db_closeversion(stub->db, &stub->version,
4360 ISC_FALSE);
4361 if (stub->db != NULL)
4362 dns_db_detach(&stub->db);
4363 if (stub->zone != NULL)
4364 zone_idetach(&stub->zone);
4365 isc_mem_put(stub->mctx, stub, sizeof(*stub));
4367 if (message != NULL)
4368 dns_message_destroy(&message);
4369 unlock:
4370 if (key != NULL)
4371 dns_tsigkey_detach(&key);
4372 UNLOCK_ZONE(zone);
4373 return;
4377 * Handle the control event. Note that although this event causes the zone
4378 * to shut down, it is not a shutdown event in the sense of the task library.
4380 static void
4381 zone_shutdown(isc_task_t *task, isc_event_t *event) {
4382 dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
4383 isc_boolean_t free_needed, linked = ISC_FALSE;
4385 UNUSED(task);
4386 REQUIRE(DNS_ZONE_VALID(zone));
4387 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
4388 INSIST(isc_refcount_current(&zone->erefs) == 0);
4389 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
4392 * Stop things being restarted after we cancel them below.
4394 LOCK_ZONE(zone);
4395 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
4396 UNLOCK_ZONE(zone);
4399 * If we were waiting for xfrin quota, step out of
4400 * the queue.
4401 * If there's no zone manager, we can't be waiting for the
4402 * xfrin quota
4404 if (zone->zmgr != NULL) {
4405 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
4406 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
4407 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
4408 statelink);
4409 linked = ISC_TRUE;
4410 zone->statelist = NULL;
4412 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
4416 * In task context, no locking required. See zone_xfrdone().
4418 if (zone->xfr != NULL)
4419 dns_xfrin_shutdown(zone->xfr);
4421 LOCK_ZONE(zone);
4422 if (linked) {
4423 INSIST(zone->irefs > 0);
4424 zone->irefs--;
4426 if (zone->request != NULL) {
4427 dns_request_cancel(zone->request);
4430 if (zone->readio != NULL)
4431 zonemgr_cancelio(zone->readio);
4433 if (zone->lctx != NULL)
4434 dns_loadctx_cancel(zone->lctx);
4436 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
4437 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
4438 if (zone->writeio != NULL)
4439 zonemgr_cancelio(zone->writeio);
4441 if (zone->dctx != NULL)
4442 dns_dumpctx_cancel(zone->dctx);
4445 notify_cancel(zone);
4447 if (zone->timer != NULL) {
4448 isc_timer_detach(&zone->timer);
4449 INSIST(zone->irefs > 0);
4450 zone->irefs--;
4453 if (zone->view != NULL)
4454 dns_view_weakdetach(&zone->view);
4457 * We have now canceled everything set the flag to allow exit_check()
4458 * to succeed. We must not unlock between setting this flag and
4459 * calling exit_check().
4461 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
4462 free_needed = exit_check(zone);
4463 UNLOCK_ZONE(zone);
4464 if (free_needed)
4465 zone_free(zone);
4468 static void
4469 zone_timer(isc_task_t *task, isc_event_t *event) {
4470 const char me[] = "zone_timer";
4471 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
4473 UNUSED(task);
4474 REQUIRE(DNS_ZONE_VALID(zone));
4476 ENTER;
4478 zone_maintenance(zone);
4480 isc_event_free(&event);
4483 static void
4484 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
4485 const char me[] = "zone_settimer";
4486 isc_time_t next;
4487 isc_result_t result;
4489 REQUIRE(DNS_ZONE_VALID(zone));
4490 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
4491 return;
4493 isc_time_settoepoch(&next);
4495 switch (zone->type) {
4496 case dns_zone_master:
4497 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
4498 next = *now;
4499 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
4500 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
4501 INSIST(!isc_time_isepoch(&zone->dumptime));
4502 if (isc_time_isepoch(&next) ||
4503 isc_time_compare(&zone->dumptime, &next) < 0)
4504 next = zone->dumptime;
4506 break;
4508 case dns_zone_slave:
4509 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
4510 next = *now;
4511 /*FALLTHROUGH*/
4513 case dns_zone_stub:
4514 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
4515 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
4516 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
4517 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
4518 INSIST(!isc_time_isepoch(&zone->refreshtime));
4519 if (isc_time_isepoch(&next) ||
4520 isc_time_compare(&zone->refreshtime, &next) < 0)
4521 next = zone->refreshtime;
4523 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
4524 INSIST(!isc_time_isepoch(&zone->expiretime));
4525 if (isc_time_isepoch(&next) ||
4526 isc_time_compare(&zone->expiretime, &next) < 0)
4527 next = zone->expiretime;
4529 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
4530 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
4531 INSIST(!isc_time_isepoch(&zone->dumptime));
4532 if (isc_time_isepoch(&next) ||
4533 isc_time_compare(&zone->dumptime, &next) < 0)
4534 next = zone->dumptime;
4536 break;
4538 default:
4539 break;
4542 if (isc_time_isepoch(&next)) {
4543 zone_debuglog(zone, me, 10, "settimer inactive");
4544 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
4545 NULL, NULL, ISC_TRUE);
4546 if (result != ISC_R_SUCCESS)
4547 dns_zone_log(zone, ISC_LOG_ERROR,
4548 "could not deactivate zone timer: %s",
4549 isc_result_totext(result));
4550 } else {
4551 if (isc_time_compare(&next, now) <= 0)
4552 next = *now;
4553 result = isc_timer_reset(zone->timer, isc_timertype_once,
4554 &next, NULL, ISC_TRUE);
4555 if (result != ISC_R_SUCCESS)
4556 dns_zone_log(zone, ISC_LOG_ERROR,
4557 "could not reset zone timer: %s",
4558 isc_result_totext(result));
4562 static void
4563 cancel_refresh(dns_zone_t *zone) {
4564 const char me[] = "cancel_refresh";
4565 isc_time_t now;
4568 * 'zone' locked by caller.
4571 REQUIRE(DNS_ZONE_VALID(zone));
4572 REQUIRE(LOCKED_ZONE(zone));
4574 ENTER;
4576 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4577 TIME_NOW(&now);
4578 zone_settimer(zone, &now);
4581 static isc_result_t
4582 notify_createmessage(dns_zone_t *zone, unsigned int flags,
4583 dns_message_t **messagep)
4585 dns_dbnode_t *node = NULL;
4586 dns_dbversion_t *version = NULL;
4587 dns_message_t *message = NULL;
4588 dns_rdataset_t rdataset;
4589 dns_rdata_t rdata = DNS_RDATA_INIT;
4591 dns_name_t *tempname = NULL;
4592 dns_rdata_t *temprdata = NULL;
4593 dns_rdatalist_t *temprdatalist = NULL;
4594 dns_rdataset_t *temprdataset = NULL;
4596 isc_result_t result;
4597 isc_region_t r;
4598 isc_buffer_t *b = NULL;
4600 REQUIRE(DNS_ZONE_VALID(zone));
4601 REQUIRE(messagep != NULL && *messagep == NULL);
4603 message = NULL;
4604 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
4605 &message);
4606 if (result != ISC_R_SUCCESS)
4607 return (result);
4609 message->opcode = dns_opcode_notify;
4610 message->flags |= DNS_MESSAGEFLAG_AA;
4611 message->rdclass = zone->rdclass;
4613 result = dns_message_gettempname(message, &tempname);
4614 if (result != ISC_R_SUCCESS)
4615 goto cleanup;
4617 result = dns_message_gettemprdataset(message, &temprdataset);
4618 if (result != ISC_R_SUCCESS)
4619 goto cleanup;
4622 * Make question.
4624 dns_name_init(tempname, NULL);
4625 dns_name_clone(&zone->origin, tempname);
4626 dns_rdataset_init(temprdataset);
4627 dns_rdataset_makequestion(temprdataset, zone->rdclass,
4628 dns_rdatatype_soa);
4629 ISC_LIST_APPEND(tempname->list, temprdataset, link);
4630 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
4631 tempname = NULL;
4632 temprdataset = NULL;
4634 if ((flags & DNS_NOTIFY_NOSOA) != 0)
4635 goto done;
4637 result = dns_message_gettempname(message, &tempname);
4638 if (result != ISC_R_SUCCESS)
4639 goto soa_cleanup;
4640 result = dns_message_gettemprdata(message, &temprdata);
4641 if (result != ISC_R_SUCCESS)
4642 goto soa_cleanup;
4643 result = dns_message_gettemprdataset(message, &temprdataset);
4644 if (result != ISC_R_SUCCESS)
4645 goto soa_cleanup;
4646 result = dns_message_gettemprdatalist(message, &temprdatalist);
4647 if (result != ISC_R_SUCCESS)
4648 goto soa_cleanup;
4650 dns_name_init(tempname, NULL);
4651 dns_name_clone(&zone->origin, tempname);
4652 dns_db_currentversion(zone->db, &version);
4653 result = dns_db_findnode(zone->db, tempname, ISC_FALSE, &node);
4654 if (result != ISC_R_SUCCESS)
4655 goto soa_cleanup;
4657 dns_rdataset_init(&rdataset);
4658 result = dns_db_findrdataset(zone->db, node, version,
4659 dns_rdatatype_soa,
4660 dns_rdatatype_none, 0, &rdataset,
4661 NULL);
4662 if (result != ISC_R_SUCCESS)
4663 goto soa_cleanup;
4664 result = dns_rdataset_first(&rdataset);
4665 if (result != ISC_R_SUCCESS)
4666 goto soa_cleanup;
4667 dns_rdataset_current(&rdataset, &rdata);
4668 dns_rdata_toregion(&rdata, &r);
4669 result = isc_buffer_allocate(zone->mctx, &b, r.length);
4670 if (result != ISC_R_SUCCESS)
4671 goto soa_cleanup;
4672 isc_buffer_putmem(b, r.base, r.length);
4673 isc_buffer_usedregion(b, &r);
4674 dns_rdata_init(temprdata);
4675 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
4676 dns_message_takebuffer(message, &b);
4677 result = dns_rdataset_next(&rdataset);
4678 dns_rdataset_disassociate(&rdataset);
4679 if (result != ISC_R_NOMORE)
4680 goto soa_cleanup;
4681 temprdatalist->rdclass = rdata.rdclass;
4682 temprdatalist->type = rdata.type;
4683 temprdatalist->covers = 0;
4684 temprdatalist->ttl = rdataset.ttl;
4685 ISC_LIST_INIT(temprdatalist->rdata);
4686 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
4688 dns_rdataset_init(temprdataset);
4689 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
4690 if (result != ISC_R_SUCCESS)
4691 goto soa_cleanup;
4693 ISC_LIST_APPEND(tempname->list, temprdataset, link);
4694 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
4695 temprdatalist = NULL;
4696 temprdataset = NULL;
4697 temprdata = NULL;
4698 tempname = NULL;
4700 soa_cleanup:
4701 if (node != NULL)
4702 dns_db_detachnode(zone->db, &node);
4703 if (version != NULL)
4704 dns_db_closeversion(zone->db, &version, ISC_FALSE);
4705 if (tempname != NULL)
4706 dns_message_puttempname(message, &tempname);
4707 if (temprdata != NULL)
4708 dns_message_puttemprdata(message, &temprdata);
4709 if (temprdataset != NULL)
4710 dns_message_puttemprdataset(message, &temprdataset);
4711 if (temprdatalist != NULL)
4712 dns_message_puttemprdatalist(message, &temprdatalist);
4714 done:
4715 *messagep = message;
4716 return (ISC_R_SUCCESS);
4718 cleanup:
4719 if (tempname != NULL)
4720 dns_message_puttempname(message, &tempname);
4721 if (temprdataset != NULL)
4722 dns_message_puttemprdataset(message, &temprdataset);
4723 if (message != NULL)
4724 dns_message_destroy(&message);
4725 return (result);
4728 isc_result_t
4729 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
4730 dns_message_t *msg)
4732 unsigned int i;
4733 dns_rdata_soa_t soa;
4734 dns_rdataset_t *rdataset = NULL;
4735 dns_rdata_t rdata = DNS_RDATA_INIT;
4736 isc_result_t result;
4737 char fromtext[ISC_SOCKADDR_FORMATSIZE];
4738 int match = 0;
4739 isc_netaddr_t netaddr;
4741 REQUIRE(DNS_ZONE_VALID(zone));
4744 * If type != T_SOA return DNS_R_REFUSED. We don't yet support
4745 * ROLLOVER.
4747 * SOA: RFC 1996
4748 * Check that 'from' is a valid notify source, (zone->masters).
4749 * Return DNS_R_REFUSED if not.
4751 * If the notify message contains a serial number check it
4752 * against the zones serial and return if <= current serial
4754 * If a refresh check is progress, if so just record the
4755 * fact we received a NOTIFY and from where and return.
4756 * We will perform a new refresh check when the current one
4757 * completes. Return ISC_R_SUCCESS.
4759 * Otherwise initiate a refresh check using 'from' as the
4760 * first address to check. Return ISC_R_SUCCESS.
4763 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
4766 * We only handle NOTIFY (SOA) at the present.
4768 LOCK_ZONE(zone);
4769 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
4770 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
4771 dns_rdatatype_soa, dns_rdatatype_none,
4772 NULL, NULL) != ISC_R_SUCCESS) {
4773 UNLOCK_ZONE(zone);
4774 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
4775 dns_zone_log(zone, ISC_LOG_NOTICE,
4776 "NOTIFY with no "
4777 "question section from: %s", fromtext);
4778 return (DNS_R_FORMERR);
4780 dns_zone_log(zone, ISC_LOG_NOTICE,
4781 "NOTIFY zone does not match");
4782 return (DNS_R_NOTIMP);
4786 * If we are a master zone just succeed.
4788 if (zone->type == dns_zone_master) {
4789 UNLOCK_ZONE(zone);
4790 return (ISC_R_SUCCESS);
4793 isc_netaddr_fromsockaddr(&netaddr, from);
4794 for (i = 0; i < zone->masterscnt; i++) {
4795 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
4796 break;
4797 if (zone->view->aclenv.match_mapped &&
4798 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
4799 isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
4800 isc_netaddr_t na1, na2;
4801 isc_netaddr_fromv4mapped(&na1, &netaddr);
4802 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
4803 if (isc_netaddr_equal(&na1, &na2))
4804 break;
4809 * Accept notify requests from non masters if they are on
4810 * 'zone->notify_acl'.
4812 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
4813 dns_acl_match(&netaddr, NULL, zone->notify_acl,
4814 &zone->view->aclenv,
4815 &match, NULL) == ISC_R_SUCCESS &&
4816 match > 0)
4818 /* Accept notify. */
4819 } else if (i >= zone->masterscnt) {
4820 UNLOCK_ZONE(zone);
4821 dns_zone_log(zone, ISC_LOG_INFO,
4822 "refused notify from non-master: %s", fromtext);
4823 return (DNS_R_REFUSED);
4827 * If the zone is loaded and there are answers check the serial
4828 * to see if we need to do a refresh. Do not worry about this
4829 * check if we are a dialup zone as we use the notify request
4830 * to trigger a refresh check.
4832 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
4833 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
4834 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
4835 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
4836 &zone->origin,
4837 dns_rdatatype_soa,
4838 dns_rdatatype_none, NULL,
4839 &rdataset);
4840 if (result == ISC_R_SUCCESS)
4841 result = dns_rdataset_first(rdataset);
4842 if (result == ISC_R_SUCCESS) {
4843 isc_uint32_t serial = 0;
4845 dns_rdataset_current(rdataset, &rdata);
4846 result = dns_rdata_tostruct(&rdata, &soa, NULL);
4847 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4848 serial = soa.serial;
4849 if (isc_serial_le(serial, zone->serial)) {
4850 dns_zone_log(zone, ISC_LOG_INFO,
4851 "notify from %s: "
4852 "zone is up to date",
4853 fromtext);
4854 UNLOCK_ZONE(zone);
4855 return (ISC_R_SUCCESS);
4861 * If we got this far and there was a refresh in progress just
4862 * let it complete. Record where we got the notify from so we
4863 * can perform a refresh check when the current one completes
4865 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
4866 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
4867 zone->notifyfrom = *from;
4868 UNLOCK_ZONE(zone);
4869 dns_zone_log(zone, ISC_LOG_INFO,
4870 "notify from %s: refresh in progress, "
4871 "refresh check queued",
4872 fromtext);
4873 return (ISC_R_SUCCESS);
4875 zone->notifyfrom = *from;
4876 UNLOCK_ZONE(zone);
4877 dns_zone_refresh(zone);
4878 return (ISC_R_SUCCESS);
4881 void
4882 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
4884 REQUIRE(DNS_ZONE_VALID(zone));
4886 LOCK_ZONE(zone);
4887 if (zone->notify_acl != NULL)
4888 dns_acl_detach(&zone->notify_acl);
4889 dns_acl_attach(acl, &zone->notify_acl);
4890 UNLOCK_ZONE(zone);
4893 void
4894 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
4896 REQUIRE(DNS_ZONE_VALID(zone));
4898 LOCK_ZONE(zone);
4899 if (zone->query_acl != NULL)
4900 dns_acl_detach(&zone->query_acl);
4901 dns_acl_attach(acl, &zone->query_acl);
4902 UNLOCK_ZONE(zone);
4905 void
4906 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
4908 REQUIRE(DNS_ZONE_VALID(zone));
4910 LOCK_ZONE(zone);
4911 if (zone->update_acl != NULL)
4912 dns_acl_detach(&zone->update_acl);
4913 dns_acl_attach(acl, &zone->update_acl);
4914 UNLOCK_ZONE(zone);
4917 void
4918 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
4920 REQUIRE(DNS_ZONE_VALID(zone));
4922 LOCK_ZONE(zone);
4923 if (zone->forward_acl != NULL)
4924 dns_acl_detach(&zone->forward_acl);
4925 dns_acl_attach(acl, &zone->forward_acl);
4926 UNLOCK_ZONE(zone);
4929 void
4930 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
4932 REQUIRE(DNS_ZONE_VALID(zone));
4934 LOCK_ZONE(zone);
4935 if (zone->xfr_acl != NULL)
4936 dns_acl_detach(&zone->xfr_acl);
4937 dns_acl_attach(acl, &zone->xfr_acl);
4938 UNLOCK_ZONE(zone);
4941 dns_acl_t *
4942 dns_zone_getnotifyacl(dns_zone_t *zone) {
4944 REQUIRE(DNS_ZONE_VALID(zone));
4946 return (zone->notify_acl);
4949 dns_acl_t *
4950 dns_zone_getqueryacl(dns_zone_t *zone) {
4952 REQUIRE(DNS_ZONE_VALID(zone));
4954 return (zone->query_acl);
4957 dns_acl_t *
4958 dns_zone_getupdateacl(dns_zone_t *zone) {
4960 REQUIRE(DNS_ZONE_VALID(zone));
4962 return (zone->update_acl);
4965 dns_acl_t *
4966 dns_zone_getforwardacl(dns_zone_t *zone) {
4968 REQUIRE(DNS_ZONE_VALID(zone));
4970 return (zone->forward_acl);
4973 dns_acl_t *
4974 dns_zone_getxfracl(dns_zone_t *zone) {
4976 REQUIRE(DNS_ZONE_VALID(zone));
4978 return (zone->xfr_acl);
4981 void
4982 dns_zone_clearupdateacl(dns_zone_t *zone) {
4984 REQUIRE(DNS_ZONE_VALID(zone));
4986 LOCK_ZONE(zone);
4987 if (zone->update_acl != NULL)
4988 dns_acl_detach(&zone->update_acl);
4989 UNLOCK_ZONE(zone);
4992 void
4993 dns_zone_clearforwardacl(dns_zone_t *zone) {
4995 REQUIRE(DNS_ZONE_VALID(zone));
4997 LOCK_ZONE(zone);
4998 if (zone->forward_acl != NULL)
4999 dns_acl_detach(&zone->forward_acl);
5000 UNLOCK_ZONE(zone);
5003 void
5004 dns_zone_clearnotifyacl(dns_zone_t *zone) {
5006 REQUIRE(DNS_ZONE_VALID(zone));
5008 LOCK_ZONE(zone);
5009 if (zone->notify_acl != NULL)
5010 dns_acl_detach(&zone->notify_acl);
5011 UNLOCK_ZONE(zone);
5014 void
5015 dns_zone_clearqueryacl(dns_zone_t *zone) {
5017 REQUIRE(DNS_ZONE_VALID(zone));
5019 LOCK_ZONE(zone);
5020 if (zone->query_acl != NULL)
5021 dns_acl_detach(&zone->query_acl);
5022 UNLOCK_ZONE(zone);
5025 void
5026 dns_zone_clearxfracl(dns_zone_t *zone) {
5028 REQUIRE(DNS_ZONE_VALID(zone));
5030 LOCK_ZONE(zone);
5031 if (zone->xfr_acl != NULL)
5032 dns_acl_detach(&zone->xfr_acl);
5033 UNLOCK_ZONE(zone);
5036 isc_boolean_t
5037 dns_zone_getupdatedisabled(dns_zone_t *zone) {
5038 REQUIRE(DNS_ZONE_VALID(zone));
5039 return (zone->update_disabled);
5043 void
5044 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
5045 REQUIRE(DNS_ZONE_VALID(zone));
5046 zone->update_disabled = state;
5049 void
5050 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
5052 REQUIRE(DNS_ZONE_VALID(zone));
5054 zone->check_names = severity;
5057 dns_severity_t
5058 dns_zone_getchecknames(dns_zone_t *zone) {
5060 REQUIRE(DNS_ZONE_VALID(zone));
5062 return (zone->check_names);
5065 void
5066 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
5068 REQUIRE(DNS_ZONE_VALID(zone));
5070 zone->journalsize = size;
5073 isc_int32_t
5074 dns_zone_getjournalsize(dns_zone_t *zone) {
5076 REQUIRE(DNS_ZONE_VALID(zone));
5078 return (zone->journalsize);
5081 static void
5082 zone_tostr(dns_zone_t *zone, char *buf, size_t length) {
5083 isc_result_t result = ISC_R_FAILURE;
5084 isc_buffer_t buffer;
5086 REQUIRE(buf != NULL);
5087 REQUIRE(length > 1U);
5090 * Leave space for terminating '\0'.
5092 isc_buffer_init(&buffer, buf, length - 1);
5093 if (dns_name_dynamic(&zone->origin))
5094 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
5095 if (result != ISC_R_SUCCESS &&
5096 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
5097 isc_buffer_putstr(&buffer, "<UNKNOWN>");
5099 if (isc_buffer_availablelength(&buffer) > 0)
5100 isc_buffer_putstr(&buffer, "/");
5101 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
5103 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
5104 strcmp(zone->view->name, "_default") != 0 &&
5105 strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
5106 isc_buffer_putstr(&buffer, "/");
5107 isc_buffer_putstr(&buffer, zone->view->name);
5110 buf[isc_buffer_usedlength(&buffer)] = '\0';
5113 void
5114 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
5115 REQUIRE(DNS_ZONE_VALID(zone));
5116 REQUIRE(buf != NULL);
5117 zone_tostr(zone, buf, length);
5120 static void
5121 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
5122 va_list ap;
5123 char message[4096];
5124 char namebuf[1024+32];
5126 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
5127 return;
5129 zone_tostr(zone, namebuf, sizeof(namebuf));
5131 va_start(ap, fmt);
5132 vsnprintf(message, sizeof(message), fmt, ap);
5133 va_end(ap);
5134 isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
5135 level, "zone %s: %s", namebuf, message);
5138 void
5139 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
5140 int level, const char *fmt, ...) {
5141 va_list ap;
5142 char message[4096];
5143 char namebuf[1024+32];
5145 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
5146 return;
5148 zone_tostr(zone, namebuf, sizeof(namebuf));
5150 va_start(ap, fmt);
5151 vsnprintf(message, sizeof(message), fmt, ap);
5152 va_end(ap);
5153 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
5154 level, "zone %s: %s", namebuf, message);
5157 void
5158 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
5159 va_list ap;
5160 char message[4096];
5161 char namebuf[1024+32];
5163 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
5164 return;
5166 zone_tostr(zone, namebuf, sizeof(namebuf));
5168 va_start(ap, fmt);
5169 vsnprintf(message, sizeof(message), fmt, ap);
5170 va_end(ap);
5171 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
5172 level, "zone %s: %s", namebuf, message);
5175 static void
5176 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
5177 const char *fmt, ...)
5179 va_list ap;
5180 char message[4096];
5181 char namebuf[1024+32];
5182 int level = ISC_LOG_DEBUG(debuglevel);
5184 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
5185 return;
5187 zone_tostr(zone, namebuf, sizeof(namebuf));
5189 va_start(ap, fmt);
5190 vsnprintf(message, sizeof(message), fmt, ap);
5191 va_end(ap);
5192 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
5193 level, "%s: zone %s: %s", me, namebuf, message);
5196 static int
5197 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
5199 isc_result_t result;
5200 dns_name_t *name;
5201 dns_rdataset_t *curr;
5202 int count = 0;
5204 result = dns_message_firstname(msg, section);
5205 while (result == ISC_R_SUCCESS) {
5206 name = NULL;
5207 dns_message_currentname(msg, section, &name);
5209 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
5210 curr = ISC_LIST_PREV(curr, link)) {
5211 if (curr->type == type)
5212 count++;
5214 result = dns_message_nextname(msg, section);
5217 return (count);
5220 void
5221 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
5222 REQUIRE(DNS_ZONE_VALID(zone));
5224 zone->maxxfrin = maxxfrin;
5227 isc_uint32_t
5228 dns_zone_getmaxxfrin(dns_zone_t *zone) {
5229 REQUIRE(DNS_ZONE_VALID(zone));
5231 return (zone->maxxfrin);
5234 void
5235 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
5236 REQUIRE(DNS_ZONE_VALID(zone));
5237 zone->maxxfrout = maxxfrout;
5240 isc_uint32_t
5241 dns_zone_getmaxxfrout(dns_zone_t *zone) {
5242 REQUIRE(DNS_ZONE_VALID(zone));
5244 return (zone->maxxfrout);
5247 dns_zonetype_t dns_zone_gettype(dns_zone_t *zone) {
5248 REQUIRE(DNS_ZONE_VALID(zone));
5250 return (zone->type);
5253 dns_name_t *
5254 dns_zone_getorigin(dns_zone_t *zone) {
5255 REQUIRE(DNS_ZONE_VALID(zone));
5257 return (&zone->origin);
5260 void
5261 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
5262 REQUIRE(DNS_ZONE_VALID(zone));
5264 LOCK_ZONE(zone);
5265 if (zone->task != NULL)
5266 isc_task_detach(&zone->task);
5267 isc_task_attach(task, &zone->task);
5268 if (zone->db != NULL)
5269 dns_db_settask(zone->db, zone->task);
5270 UNLOCK_ZONE(zone);
5273 void
5274 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
5275 REQUIRE(DNS_ZONE_VALID(zone));
5276 isc_task_attach(zone->task, target);
5279 void
5280 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
5281 REQUIRE(DNS_ZONE_VALID(zone));
5283 if (idlein == 0)
5284 idlein = DNS_DEFAULT_IDLEIN;
5285 zone->idlein = idlein;
5288 isc_uint32_t
5289 dns_zone_getidlein(dns_zone_t *zone) {
5290 REQUIRE(DNS_ZONE_VALID(zone));
5292 return (zone->idlein);
5295 void
5296 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
5297 REQUIRE(DNS_ZONE_VALID(zone));
5299 zone->idleout = idleout;
5302 isc_uint32_t
5303 dns_zone_getidleout(dns_zone_t *zone) {
5304 REQUIRE(DNS_ZONE_VALID(zone));
5306 return (zone->idleout);
5309 static void
5310 notify_done(isc_task_t *task, isc_event_t *event) {
5311 dns_requestevent_t *revent = (dns_requestevent_t *)event;
5312 dns_notify_t *notify;
5313 isc_result_t result;
5314 dns_message_t *message = NULL;
5315 isc_buffer_t buf;
5316 char rcode[128];
5317 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
5319 UNUSED(task);
5321 notify = event->ev_arg;
5322 REQUIRE(DNS_NOTIFY_VALID(notify));
5323 INSIST(task == notify->zone->task);
5325 isc_buffer_init(&buf, rcode, sizeof(rcode));
5326 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
5328 result = revent->result;
5329 if (result == ISC_R_SUCCESS)
5330 result = dns_message_create(notify->zone->mctx,
5331 DNS_MESSAGE_INTENTPARSE, &message);
5332 if (result == ISC_R_SUCCESS)
5333 result = dns_request_getresponse(revent->request, message,
5334 DNS_MESSAGEPARSE_PRESERVEORDER);
5335 if (result == ISC_R_SUCCESS)
5336 result = dns_rcode_totext(message->rcode, &buf);
5337 if (result == ISC_R_SUCCESS)
5338 notify_log(notify->zone, ISC_LOG_DEBUG(3),
5339 "notify response from %s: %.*s",
5340 addrbuf, (int)buf.used, rcode);
5341 else
5342 notify_log(notify->zone, ISC_LOG_DEBUG(2),
5343 "notify to %s failed: %s", addrbuf,
5344 dns_result_totext(result));
5347 * Old bind's return formerr if they see a soa record. Retry w/o
5348 * the soa if we see a formerr and had sent a SOA.
5350 isc_event_free(&event);
5351 if (message != NULL && message->rcode == dns_rcode_formerr &&
5352 (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
5353 notify->flags |= DNS_NOTIFY_NOSOA;
5354 dns_request_destroy(&notify->request);
5355 result = notify_send_queue(notify);
5356 if (result != ISC_R_SUCCESS)
5357 notify_destroy(notify, ISC_FALSE);
5358 } else {
5359 if (result == ISC_R_TIMEDOUT)
5360 notify_log(notify->zone, ISC_LOG_DEBUG(1),
5361 "notify to %s: retries exceeded", addrbuf);
5362 notify_destroy(notify, ISC_FALSE);
5364 if (message != NULL)
5365 dns_message_destroy(&message);
5368 isc_result_t
5369 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
5370 isc_result_t result;
5372 REQUIRE(DNS_ZONE_VALID(zone));
5373 LOCK_ZONE(zone);
5374 result = zone_replacedb(zone, db, dump);
5375 UNLOCK_ZONE(zone);
5376 return (result);
5379 static isc_result_t
5380 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
5381 dns_dbversion_t *ver;
5382 isc_result_t result;
5383 unsigned int soacount = 0;
5384 unsigned int nscount = 0;
5387 * 'zone' locked by caller.
5389 REQUIRE(DNS_ZONE_VALID(zone));
5390 REQUIRE(LOCKED_ZONE(zone));
5392 result = zone_get_from_db(db, &zone->origin, &nscount, &soacount,
5393 NULL, NULL, NULL, NULL, NULL);
5394 if (result == ISC_R_SUCCESS) {
5395 if (soacount != 1) {
5396 dns_zone_log(zone, ISC_LOG_ERROR,
5397 "has %d SOA records", soacount);
5398 result = DNS_R_BADZONE;
5400 if (nscount == 0) {
5401 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
5402 result = DNS_R_BADZONE;
5404 if (result != ISC_R_SUCCESS)
5405 return (result);
5406 } else {
5407 dns_zone_log(zone, ISC_LOG_ERROR,
5408 "retrieving SOA and NS records failed: %s",
5409 dns_result_totext(result));
5410 return (result);
5413 ver = NULL;
5414 dns_db_currentversion(db, &ver);
5417 * The initial version of a slave zone is always dumped;
5418 * subsequent versions may be journalled instead if this
5419 * is enabled in the configuration.
5421 if (zone->db != NULL && zone->journal != NULL &&
5422 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
5423 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
5424 isc_uint32_t serial;
5426 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
5428 result = dns_db_getsoaserial(db, ver, &serial);
5429 if (result != ISC_R_SUCCESS) {
5430 dns_zone_log(zone, ISC_LOG_ERROR,
5431 "ixfr-from-differences: unable to get "
5432 "new serial");
5433 goto fail;
5437 * This is checked in zone_postload() for master zones.
5439 if (zone->type == dns_zone_slave &&
5440 !isc_serial_gt(serial, zone->serial)) {
5441 isc_uint32_t serialmin, serialmax;
5442 serialmin = (zone->serial + 1) & 0xffffffffU;
5443 serialmax = (zone->serial + 0x7fffffffU) & 0xffffffffU;
5444 dns_zone_log(zone, ISC_LOG_ERROR,
5445 "ixfr-from-differences: failed: "
5446 "new serial (%u) out of range [%u - %u]",
5447 serial, serialmin, serialmax);
5448 result = ISC_R_RANGE;
5449 goto fail;
5452 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
5453 zone->journal);
5454 if (result != ISC_R_SUCCESS)
5455 goto fail;
5456 if (dump)
5457 zone_needdump(zone, DNS_DUMP_DELAY);
5458 else if (zone->journalsize != -1) {
5459 result = dns_journal_compact(zone->mctx, zone->journal,
5460 serial, zone->journalsize);
5461 switch (result) {
5462 case ISC_R_SUCCESS:
5463 case ISC_R_NOSPACE:
5464 case ISC_R_NOTFOUND:
5465 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5466 "dns_journal_compact: %s",
5467 dns_result_totext(result));
5468 break;
5469 default:
5470 dns_zone_log(zone, ISC_LOG_ERROR,
5471 "dns_journal_compact failed: %s",
5472 dns_result_totext(result));
5473 break;
5476 } else {
5477 if (dump && zone->masterfile != NULL) {
5478 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5479 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
5480 "dumping new zone version");
5481 result = dns_db_dump(db, ver, zone->masterfile);
5482 if (result != ISC_R_SUCCESS)
5483 goto fail;
5486 * Update the time the zone was updated, so
5487 * dns_zone_load can avoid loading it when
5488 * the server is reloaded. If isc_time_now
5489 * fails for some reason, all that happens is
5490 * the timestamp is not updated.
5492 TIME_NOW(&zone->loadtime);
5495 if (dump && zone->journal != NULL) {
5497 * The in-memory database just changed, and
5498 * because 'dump' is set, it didn't change by
5499 * being loaded from disk. Also, we have not
5500 * journalled diffs for this change.
5501 * Therefore, the on-disk journal is missing
5502 * the deltas for this change. Since it can
5503 * no longer be used to bring the zone
5504 * up-to-date, it is useless and should be
5505 * removed.
5507 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5508 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
5509 "removing journal file");
5510 (void)remove(zone->journal);
5514 dns_db_closeversion(db, &ver, ISC_FALSE);
5516 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5517 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
5518 "replacing zone database");
5520 if (zone->db != NULL)
5521 dns_db_detach(&zone->db);
5522 dns_db_attach(db, &zone->db);
5523 dns_db_settask(zone->db, zone->task);
5524 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
5525 return (ISC_R_SUCCESS);
5527 fail:
5528 dns_db_closeversion(db, &ver, ISC_FALSE);
5529 return (result);
5532 static void
5533 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
5534 isc_time_t now;
5535 isc_boolean_t again = ISC_FALSE;
5536 unsigned int soacount;
5537 unsigned int nscount;
5538 isc_uint32_t serial, refresh, retry, expire, minimum;
5539 isc_result_t xfrresult = result;
5540 isc_boolean_t free_needed;
5542 REQUIRE(DNS_ZONE_VALID(zone));
5544 dns_zone_log(zone, ISC_LOG_DEBUG(1),
5545 "zone transfer finished: %s", dns_result_totext(result));
5547 LOCK_ZONE(zone);
5548 INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
5549 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
5550 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
5552 TIME_NOW(&now);
5553 switch (result) {
5554 case ISC_R_SUCCESS:
5555 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5556 /*FALLTHROUGH*/
5557 case DNS_R_UPTODATE:
5558 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
5560 * Has the zone expired underneath us?
5562 if (zone->db == NULL)
5563 goto same_master;
5566 * Update the zone structure's data from the actual
5567 * SOA received.
5569 nscount = 0;
5570 soacount = 0;
5571 INSIST(zone->db != NULL);
5572 result = zone_get_from_db(zone->db, &zone->origin, &nscount,
5573 &soacount, &serial, &refresh,
5574 &retry, &expire, &minimum);
5575 if (result == ISC_R_SUCCESS) {
5576 if (soacount != 1)
5577 dns_zone_log(zone, ISC_LOG_ERROR,
5578 "transferred zone "
5579 "has %d SOA record%s", soacount,
5580 (soacount != 0) ? "s" : "");
5581 if (nscount == 0) {
5582 dns_zone_log(zone, ISC_LOG_ERROR,
5583 "transferred zone "
5584 "has no NS records");
5585 if (DNS_ZONE_FLAG(zone,
5586 DNS_ZONEFLG_HAVETIMERS)) {
5587 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
5588 zone->retry = DNS_ZONE_DEFAULTRETRY;
5590 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5591 zone_unload(zone);
5592 goto next_master;
5594 zone->serial = serial;
5595 zone->refresh = RANGE(refresh, zone->minrefresh,
5596 zone->maxrefresh);
5597 zone->retry = RANGE(retry, zone->minretry,
5598 zone->maxretry);
5599 zone->expire = RANGE(expire,
5600 zone->refresh + zone->retry,
5601 DNS_MAX_EXPIRE);
5602 zone->minimum = minimum;
5603 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5607 * Set our next update/expire times.
5609 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
5610 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
5611 zone->refreshtime = now;
5612 DNS_ZONE_TIME_ADD(&now, zone->expire,
5613 &zone->expiretime);
5614 } else {
5615 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
5616 &zone->refreshtime);
5617 DNS_ZONE_TIME_ADD(&now, zone->expire,
5618 &zone->expiretime);
5620 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
5621 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
5622 if (zone->tsigkey != NULL) {
5623 char namebuf[DNS_NAME_FORMATSIZE];
5624 dns_name_format(&zone->tsigkey->name, namebuf,
5625 sizeof(namebuf));
5626 snprintf(buf, sizeof(buf), ": TSIG '%s'",
5627 namebuf);
5628 } else
5629 buf[0] = '\0';
5630 dns_zone_log(zone, ISC_LOG_INFO,
5631 "transferred serial %u%s",
5632 zone->serial, buf);
5636 * This is not neccessary if we just performed a AXFR
5637 * however it is necessary for an IXFR / UPTODATE and
5638 * won't hurt with an AXFR.
5640 if (zone->masterfile != NULL || zone->journal != NULL) {
5641 result = ISC_R_FAILURE;
5642 if (zone->journal != NULL)
5643 result = isc_file_settime(zone->journal, &now);
5644 if (result != ISC_R_SUCCESS &&
5645 zone->masterfile != NULL)
5646 result = isc_file_settime(zone->masterfile,
5647 &now);
5648 /* Someone removed the file from underneath us! */
5649 if (result == ISC_R_FILENOTFOUND &&
5650 zone->masterfile != NULL)
5651 zone_needdump(zone, DNS_DUMP_DELAY);
5652 else if (result != ISC_R_SUCCESS)
5653 dns_zone_log(zone, ISC_LOG_ERROR,
5654 "transfer: could not set file "
5655 "modification time of '%s': %s",
5656 zone->masterfile,
5657 dns_result_totext(result));
5660 break;
5662 case DNS_R_BADIXFR:
5663 /* Force retry with AXFR. */
5664 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
5665 goto same_master;
5667 default:
5668 next_master:
5670 * Skip to next failed / untried master.
5672 do {
5673 zone->curmaster++;
5674 } while (zone->curmaster < zone->masterscnt &&
5675 zone->mastersok[zone->curmaster]);
5676 /* FALLTHROUGH */
5677 same_master:
5678 if (zone->curmaster >= zone->masterscnt) {
5679 zone->curmaster = 0;
5680 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
5681 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
5682 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
5683 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
5684 while (zone->curmaster < zone->masterscnt &&
5685 zone->mastersok[zone->curmaster])
5686 zone->curmaster++;
5687 again = ISC_TRUE;
5688 } else
5689 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
5690 } else {
5691 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
5692 again = ISC_TRUE;
5694 break;
5696 zone_settimer(zone, &now);
5699 * If creating the transfer object failed, zone->xfr is NULL.
5700 * Otherwise, we are called as the done callback of a zone
5701 * transfer object that just entered its shutting-down
5702 * state. Since we are no longer responsible for shutting
5703 * it down, we can detach our reference.
5705 if (zone->xfr != NULL)
5706 dns_xfrin_detach(&zone->xfr);
5708 if (zone->tsigkey != NULL)
5709 dns_tsigkey_detach(&zone->tsigkey);
5712 * This transfer finishing freed up a transfer quota slot.
5713 * Let any other zones waiting for quota have it.
5715 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
5716 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
5717 zone->statelist = NULL;
5718 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
5719 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
5722 * Retry with a different server if necessary.
5724 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
5725 queue_soa_query(zone);
5727 INSIST(zone->irefs > 0);
5728 zone->irefs--;
5729 free_needed = exit_check(zone);
5730 UNLOCK_ZONE(zone);
5731 if (free_needed)
5732 zone_free(zone);
5735 static void
5736 zone_loaddone(void *arg, isc_result_t result) {
5737 static char me[] = "zone_loaddone";
5738 dns_load_t *load = arg;
5739 dns_zone_t *zone;
5740 isc_result_t tresult;
5742 REQUIRE(DNS_LOAD_VALID(load));
5743 zone = load->zone;
5745 ENTER;
5747 tresult = dns_db_endload(load->db, &load->callbacks.add_private);
5748 if (tresult != ISC_R_SUCCESS &&
5749 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
5750 result = tresult;
5752 LOCK_ZONE(load->zone);
5753 (void)zone_postload(load->zone, load->db, load->loadtime, result);
5754 zonemgr_putio(&load->zone->readio);
5755 DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
5756 UNLOCK_ZONE(load->zone);
5758 load->magic = 0;
5759 dns_db_detach(&load->db);
5760 if (load->zone->lctx != NULL)
5761 dns_loadctx_detach(&load->zone->lctx);
5762 dns_zone_idetach(&load->zone);
5763 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
5766 void
5767 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
5768 REQUIRE(DNS_ZONE_VALID(zone));
5769 REQUIRE(table != NULL);
5770 REQUIRE(*table == NULL);
5772 LOCK_ZONE(zone);
5773 if (zone->ssutable != NULL)
5774 dns_ssutable_attach(zone->ssutable, table);
5775 UNLOCK_ZONE(zone);
5778 void
5779 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
5780 REQUIRE(DNS_ZONE_VALID(zone));
5782 LOCK_ZONE(zone);
5783 if (zone->ssutable != NULL)
5784 dns_ssutable_detach(&zone->ssutable);
5785 if (table != NULL)
5786 dns_ssutable_attach(table, &zone->ssutable);
5787 UNLOCK_ZONE(zone);
5790 void
5791 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
5792 REQUIRE(DNS_ZONE_VALID(zone));
5794 zone->sigvalidityinterval = interval;
5797 isc_uint32_t
5798 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
5799 REQUIRE(DNS_ZONE_VALID(zone));
5801 return (zone->sigvalidityinterval);
5804 static void
5805 queue_xfrin(dns_zone_t *zone) {
5806 const char me[] = "queue_xfrin";
5807 isc_result_t result;
5808 dns_zonemgr_t *zmgr = zone->zmgr;
5810 ENTER;
5812 INSIST(zone->statelist == NULL);
5814 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5815 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
5816 LOCK_ZONE(zone);
5817 zone->irefs++;
5818 UNLOCK_ZONE(zone);
5819 zone->statelist = &zmgr->waiting_for_xfrin;
5820 result = zmgr_start_xfrin_ifquota(zmgr, zone);
5821 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5823 if (result == ISC_R_QUOTA) {
5824 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
5825 "zone transfer deferred due to quota");
5826 } else if (result != ISC_R_SUCCESS) {
5827 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
5828 "starting zone transfer: %s",
5829 isc_result_totext(result));
5834 * This event callback is called when a zone has received
5835 * any necessary zone transfer quota. This is the time
5836 * to go ahead and start the transfer.
5838 static void
5839 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
5840 isc_result_t result;
5841 dns_peer_t *peer = NULL;
5842 char mastertext[256];
5843 dns_rdatatype_t xfrtype;
5844 dns_zone_t *zone = event->ev_arg;
5845 isc_netaddr_t masterip;
5846 isc_sockaddr_t sourceaddr;
5847 isc_sockaddr_t masteraddr;
5849 UNUSED(task);
5851 INSIST(task == zone->task);
5853 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
5854 result = ISC_R_CANCELED;
5855 goto cleanup;
5858 isc_sockaddr_format(&zone->masteraddr, mastertext, sizeof(mastertext));
5860 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
5861 (void)dns_peerlist_peerbyaddr(zone->view->peers,
5862 &masterip, &peer);
5865 * Decide whether we should request IXFR or AXFR.
5867 if (zone->db == NULL) {
5868 dns_zone_log(zone, ISC_LOG_DEBUG(1),
5869 "no database exists yet, "
5870 "requesting AXFR of "
5871 "initial version from %s", mastertext);
5872 xfrtype = dns_rdatatype_axfr;
5873 } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
5874 dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
5875 "set, requesting AXFR from %s", mastertext);
5876 xfrtype = dns_rdatatype_axfr;
5877 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
5878 dns_zone_log(zone, ISC_LOG_DEBUG(1),
5879 "forced reload, requesting AXFR of "
5880 "initial version from %s", mastertext);
5881 xfrtype = dns_rdatatype_axfr;
5882 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
5883 dns_zone_log(zone, ISC_LOG_DEBUG(1),
5884 "retrying with AXFR from %s due to "
5885 "previous IXFR failure", mastertext);
5886 xfrtype = dns_rdatatype_axfr;
5887 LOCK_ZONE(zone);
5888 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
5889 UNLOCK_ZONE(zone);
5890 } else {
5891 isc_boolean_t use_ixfr = ISC_TRUE;
5892 if (peer != NULL &&
5893 dns_peer_getrequestixfr(peer, &use_ixfr) ==
5894 ISC_R_SUCCESS) {
5895 ; /* Using peer setting */
5896 } else {
5897 use_ixfr = zone->view->requestixfr;
5899 if (use_ixfr == ISC_FALSE) {
5900 dns_zone_log(zone, ISC_LOG_DEBUG(1),
5901 "IXFR disabled, "
5902 "requesting AXFR from %s",
5903 mastertext);
5904 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
5905 xfrtype = dns_rdatatype_soa;
5906 else
5907 xfrtype = dns_rdatatype_axfr;
5908 } else {
5909 dns_zone_log(zone, ISC_LOG_DEBUG(1),
5910 "requesting IXFR from %s",
5911 mastertext);
5912 xfrtype = dns_rdatatype_ixfr;
5917 * Determine if we should attempt to sign the request with TSIG.
5919 result = ISC_R_NOTFOUND;
5921 * First, look for a tsig key in the master statement, then
5922 * try for a server key.
5924 if ((zone->masterkeynames != NULL) &&
5925 (zone->masterkeynames[zone->curmaster] != NULL)) {
5926 dns_view_t *view = dns_zone_getview(zone);
5927 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
5928 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
5930 if (zone->tsigkey == NULL)
5931 result = dns_view_getpeertsig(zone->view, &masterip,
5932 &zone->tsigkey);
5934 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
5935 dns_zone_log(zone, ISC_LOG_ERROR,
5936 "could not get TSIG key "
5937 "for zone transfer: %s",
5938 isc_result_totext(result));
5941 LOCK_ZONE(zone);
5942 masteraddr = zone->masteraddr;
5943 sourceaddr = zone->sourceaddr;
5944 UNLOCK_ZONE(zone);
5945 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
5946 result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
5947 zone->tsigkey, zone->mctx,
5948 zone->zmgr->timermgr, zone->zmgr->socketmgr,
5949 zone->task, zone_xfrdone, &zone->xfr);
5950 cleanup:
5952 * Any failure in this function is handled like a failed
5953 * zone transfer. This ensures that we get removed from
5954 * zmgr->xfrin_in_progress.
5956 if (result != ISC_R_SUCCESS)
5957 zone_xfrdone(zone, result);
5959 isc_event_free(&event);
5963 * Update forwarding support.
5966 static void
5967 forward_destroy(dns_forward_t *forward) {
5969 forward->magic = 0;
5970 if (forward->request != NULL)
5971 dns_request_destroy(&forward->request);
5972 if (forward->msgbuf != NULL)
5973 isc_buffer_free(&forward->msgbuf);
5974 if (forward->zone != NULL)
5975 dns_zone_idetach(&forward->zone);
5976 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
5979 static isc_result_t
5980 sendtomaster(dns_forward_t *forward) {
5981 isc_result_t result;
5982 isc_sockaddr_t src;
5984 LOCK_ZONE(forward->zone);
5985 if (forward->which >= forward->zone->masterscnt) {
5986 UNLOCK_ZONE(forward->zone);
5987 return (ISC_R_NOMORE);
5990 forward->addr = forward->zone->masters[forward->which];
5992 * Always use TCP regardless of whether the original update
5993 * used TCP.
5994 * XXX The timeout may but a bit small if we are far down a
5995 * transfer graph and the master has to try several masters.
5997 switch (isc_sockaddr_pf(&forward->addr)) {
5998 case PF_INET:
5999 src = forward->zone->xfrsource4;
6000 break;
6001 case PF_INET6:
6002 src = forward->zone->xfrsource6;
6003 break;
6004 default:
6005 result = ISC_R_NOTIMPLEMENTED;
6006 goto unlock;
6008 result = dns_request_createraw(forward->zone->view->requestmgr,
6009 forward->msgbuf,
6010 &src, &forward->addr,
6011 DNS_REQUESTOPT_TCP, 15 /* XXX */,
6012 forward->zone->task,
6013 forward_callback, forward,
6014 &forward->request);
6015 unlock:
6016 UNLOCK_ZONE(forward->zone);
6017 return (result);
6020 static void
6021 forward_callback(isc_task_t *task, isc_event_t *event) {
6022 const char me[] = "forward_callback";
6023 dns_requestevent_t *revent = (dns_requestevent_t *)event;
6024 dns_message_t *msg = NULL;
6025 char master[ISC_SOCKADDR_FORMATSIZE];
6026 isc_result_t result;
6027 dns_forward_t *forward;
6028 dns_zone_t *zone;
6030 UNUSED(task);
6032 forward = revent->ev_arg;
6033 INSIST(DNS_FORWARD_VALID(forward));
6034 zone = forward->zone;
6035 INSIST(DNS_ZONE_VALID(zone));
6037 ENTER;
6039 isc_sockaddr_format(&forward->addr, master, sizeof(master));
6041 if (revent->result != ISC_R_SUCCESS) {
6042 dns_zone_log(zone, ISC_LOG_INFO,
6043 "could not forward dynamic update to %s: %s",
6044 master, dns_result_totext(revent->result));
6045 goto next_master;
6048 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
6049 if (result != ISC_R_SUCCESS)
6050 goto next_master;
6052 result = dns_request_getresponse(revent->request, msg,
6053 DNS_MESSAGEPARSE_PRESERVEORDER |
6054 DNS_MESSAGEPARSE_CLONEBUFFER);
6055 if (result != ISC_R_SUCCESS)
6056 goto next_master;
6058 switch (msg->rcode) {
6060 * Pass these rcodes back to client.
6062 case dns_rcode_noerror:
6063 case dns_rcode_yxdomain:
6064 case dns_rcode_yxrrset:
6065 case dns_rcode_nxrrset:
6066 case dns_rcode_refused:
6067 case dns_rcode_nxdomain:
6068 break;
6070 /* These should not occur if the masters/zone are valid. */
6071 case dns_rcode_notzone:
6072 case dns_rcode_notauth: {
6073 char rcode[128];
6074 isc_buffer_t rb;
6076 isc_buffer_init(&rb, rcode, sizeof(rcode));
6077 (void)dns_rcode_totext(msg->rcode, &rb);
6078 dns_zone_log(zone, ISC_LOG_WARNING,
6079 "forwarding dynamic update: "
6080 "unexpected response: master %s returned: %.*s",
6081 master, (int)rb.used, rcode);
6082 goto next_master;
6085 /* Try another server for these rcodes. */
6086 case dns_rcode_formerr:
6087 case dns_rcode_servfail:
6088 case dns_rcode_notimp:
6089 case dns_rcode_badvers:
6090 default:
6091 goto next_master;
6094 /* call callback */
6095 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
6096 msg = NULL;
6097 dns_request_destroy(&forward->request);
6098 forward_destroy(forward);
6099 isc_event_free(&event);
6100 return;
6102 next_master:
6103 if (msg != NULL)
6104 dns_message_destroy(&msg);
6105 isc_event_free(&event);
6106 forward->which++;
6107 dns_request_destroy(&forward->request);
6108 result = sendtomaster(forward);
6109 if (result != ISC_R_SUCCESS) {
6110 /* call callback */
6111 dns_zone_log(zone, ISC_LOG_DEBUG(3),
6112 "exhausted dynamic update forwarder list");
6113 (forward->callback)(forward->callback_arg, result, NULL);
6114 forward_destroy(forward);
6118 isc_result_t
6119 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
6120 dns_updatecallback_t callback, void *callback_arg)
6122 dns_forward_t *forward;
6123 isc_result_t result;
6124 isc_region_t *mr;
6126 REQUIRE(DNS_ZONE_VALID(zone));
6127 REQUIRE(msg != NULL);
6128 REQUIRE(callback != NULL);
6130 forward = isc_mem_get(zone->mctx, sizeof(*forward));
6131 if (forward == NULL)
6132 return (ISC_R_NOMEMORY);
6134 forward->request = NULL;
6135 forward->zone = NULL;
6136 forward->msgbuf = NULL;
6137 forward->which = 0;
6138 forward->mctx = 0;
6139 forward->callback = callback;
6140 forward->callback_arg = callback_arg;
6141 forward->magic = FORWARD_MAGIC;
6143 mr = dns_message_getrawmessage(msg);
6144 if (mr == NULL) {
6145 result = ISC_R_UNEXPECTEDEND;
6146 goto cleanup;
6149 result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
6150 if (result != ISC_R_SUCCESS)
6151 goto cleanup;
6152 result = isc_buffer_copyregion(forward->msgbuf, mr);
6153 if (result != ISC_R_SUCCESS)
6154 goto cleanup;
6156 isc_mem_attach(zone->mctx, &forward->mctx);
6157 dns_zone_iattach(zone, &forward->zone);
6158 result = sendtomaster(forward);
6160 cleanup:
6161 if (result != ISC_R_SUCCESS) {
6162 forward_destroy(forward);
6164 return (result);
6167 isc_result_t
6168 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
6169 REQUIRE(DNS_ZONE_VALID(zone));
6170 REQUIRE(next != NULL && *next == NULL);
6172 *next = ISC_LIST_NEXT(zone, link);
6173 if (*next == NULL)
6174 return (ISC_R_NOMORE);
6175 else
6176 return (ISC_R_SUCCESS);
6179 isc_result_t
6180 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
6181 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6182 REQUIRE(first != NULL && *first == NULL);
6184 *first = ISC_LIST_HEAD(zmgr->zones);
6185 if (*first == NULL)
6186 return (ISC_R_NOMORE);
6187 else
6188 return (ISC_R_SUCCESS);
6191 /***
6192 *** Zone manager.
6193 ***/
6195 isc_result_t
6196 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
6197 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
6198 dns_zonemgr_t **zmgrp)
6200 dns_zonemgr_t *zmgr;
6201 isc_result_t result;
6202 isc_interval_t interval;
6204 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
6205 if (zmgr == NULL)
6206 return (ISC_R_NOMEMORY);
6207 zmgr->mctx = NULL;
6208 zmgr->refs = 1;
6209 isc_mem_attach(mctx, &zmgr->mctx);
6210 zmgr->taskmgr = taskmgr;
6211 zmgr->timermgr = timermgr;
6212 zmgr->socketmgr = socketmgr;
6213 zmgr->zonetasks = NULL;
6214 zmgr->task = NULL;
6215 zmgr->rl = NULL;
6216 ISC_LIST_INIT(zmgr->zones);
6217 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
6218 ISC_LIST_INIT(zmgr->xfrin_in_progress);
6219 result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
6220 if (result != ISC_R_SUCCESS) {
6221 UNEXPECTED_ERROR(__FILE__, __LINE__,
6222 "isc_rwlock_init() failed: %s",
6223 isc_result_totext(result));
6224 result = ISC_R_UNEXPECTED;
6225 goto free_mem;
6227 zmgr->transfersin = 10;
6228 zmgr->transfersperns = 2;
6230 /* Create the zone task pool. */
6231 result = isc_taskpool_create(taskmgr, mctx,
6232 8 /* XXX */, 2, &zmgr->zonetasks);
6233 if (result != ISC_R_SUCCESS)
6234 goto free_rwlock;
6236 /* Create a single task for queueing of SOA queries. */
6237 result = isc_task_create(taskmgr, 1, &zmgr->task);
6238 if (result != ISC_R_SUCCESS)
6239 goto free_taskpool;
6240 isc_task_setname(zmgr->task, "zmgr", zmgr);
6241 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
6242 &zmgr->rl);
6243 if (result != ISC_R_SUCCESS)
6244 goto free_task;
6245 /* default to 20 refresh queries / notifies per second. */
6246 isc_interval_set(&interval, 0, 1000000000/2);
6247 result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
6248 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6249 isc_ratelimiter_setpertic(zmgr->rl, 10);
6251 zmgr->iolimit = 1;
6252 zmgr->ioactive = 0;
6253 ISC_LIST_INIT(zmgr->high);
6254 ISC_LIST_INIT(zmgr->low);
6256 result = isc_mutex_init(&zmgr->iolock);
6257 if (result != ISC_R_SUCCESS) {
6258 UNEXPECTED_ERROR(__FILE__, __LINE__,
6259 "isc_mutex_init() failed: %s",
6260 isc_result_totext(result));
6261 goto free_rl;
6263 zmgr->magic = ZONEMGR_MAGIC;
6265 *zmgrp = zmgr;
6266 return (ISC_R_SUCCESS);
6268 #if 0
6269 free_iolock:
6270 DESTROYLOCK(&zmgr->iolock);
6271 #endif
6272 free_rl:
6273 isc_ratelimiter_detach(&zmgr->rl);
6274 free_task:
6275 isc_task_detach(&zmgr->task);
6276 free_taskpool:
6277 isc_taskpool_destroy(&zmgr->zonetasks);
6278 free_rwlock:
6279 isc_rwlock_destroy(&zmgr->rwlock);
6280 free_mem:
6281 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
6282 isc_mem_detach(&mctx);
6283 return (result);
6286 isc_result_t
6287 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
6288 isc_result_t result;
6290 REQUIRE(DNS_ZONE_VALID(zone));
6291 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6293 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6294 LOCK_ZONE(zone);
6295 REQUIRE(zone->task == NULL);
6296 REQUIRE(zone->timer == NULL);
6297 REQUIRE(zone->zmgr == NULL);
6299 isc_taskpool_gettask(zmgr->zonetasks,
6300 dns_name_hash(dns_zone_getorigin(zone),
6301 ISC_FALSE),
6302 &zone->task);
6305 * Set the task name. The tag will arbitrarily point to one
6306 * of the zones sharing the task (in practice, the one
6307 * to be managed last).
6309 isc_task_setname(zone->task, "zone", zone);
6311 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
6312 NULL, NULL,
6313 zone->task, zone_timer, zone,
6314 &zone->timer);
6315 if (result != ISC_R_SUCCESS)
6316 goto cleanup_task;
6318 * The timer "holds" a iref.
6320 zone->irefs++;
6321 INSIST(zone->irefs != 0);
6323 ISC_LIST_APPEND(zmgr->zones, zone, link);
6324 zone->zmgr = zmgr;
6325 zmgr->refs++;
6327 goto unlock;
6329 cleanup_task:
6330 isc_task_detach(&zone->task);
6332 unlock:
6333 UNLOCK_ZONE(zone);
6334 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6335 return (result);
6338 void
6339 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
6340 isc_boolean_t free_now = ISC_FALSE;
6342 REQUIRE(DNS_ZONE_VALID(zone));
6343 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6344 REQUIRE(zone->zmgr == zmgr);
6346 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6347 LOCK_ZONE(zone);
6349 ISC_LIST_UNLINK(zmgr->zones, zone, link);
6350 zone->zmgr = NULL;
6351 zmgr->refs--;
6352 if (zmgr->refs == 0)
6353 free_now = ISC_TRUE;
6355 UNLOCK_ZONE(zone);
6356 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6358 if (free_now)
6359 zonemgr_free(zmgr);
6360 ENSURE(zone->zmgr == NULL);
6363 void
6364 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
6365 REQUIRE(DNS_ZONEMGR_VALID(source));
6366 REQUIRE(target != NULL && *target == NULL);
6368 RWLOCK(&source->rwlock, isc_rwlocktype_write);
6369 REQUIRE(source->refs > 0);
6370 source->refs++;
6371 INSIST(source->refs > 0);
6372 RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
6373 *target = source;
6376 void
6377 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
6378 dns_zonemgr_t *zmgr;
6379 isc_boolean_t free_now = ISC_FALSE;
6381 REQUIRE(zmgrp != NULL);
6382 zmgr = *zmgrp;
6383 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6385 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6386 zmgr->refs--;
6387 if (zmgr->refs == 0)
6388 free_now = ISC_TRUE;
6389 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6391 if (free_now)
6392 zonemgr_free(zmgr);
6395 isc_result_t
6396 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
6397 dns_zone_t *p;
6399 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6401 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
6402 for (p = ISC_LIST_HEAD(zmgr->zones);
6403 p != NULL;
6404 p = ISC_LIST_NEXT(p, link))
6406 dns_zone_maintenance(p);
6408 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
6411 * Recent configuration changes may have increased the
6412 * amount of available transfers quota. Make sure any
6413 * transfers currently blocked on quota get started if
6414 * possible.
6416 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6417 zmgr_resume_xfrs(zmgr, ISC_TRUE);
6418 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6419 return (ISC_R_SUCCESS);
6422 void
6423 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
6425 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6427 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6428 zmgr_resume_xfrs(zmgr, ISC_TRUE);
6429 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6432 void
6433 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
6434 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6436 isc_ratelimiter_shutdown(zmgr->rl);
6438 if (zmgr->task != NULL)
6439 isc_task_destroy(&zmgr->task);
6440 if (zmgr->zonetasks != NULL)
6441 isc_taskpool_destroy(&zmgr->zonetasks);
6444 static void
6445 zonemgr_free(dns_zonemgr_t *zmgr) {
6446 isc_mem_t *mctx;
6448 INSIST(zmgr->refs == 0);
6449 INSIST(ISC_LIST_EMPTY(zmgr->zones));
6451 zmgr->magic = 0;
6453 DESTROYLOCK(&zmgr->iolock);
6454 isc_ratelimiter_detach(&zmgr->rl);
6456 isc_rwlock_destroy(&zmgr->rwlock);
6457 mctx = zmgr->mctx;
6458 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
6459 isc_mem_detach(&mctx);
6462 void
6463 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
6464 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6466 zmgr->transfersin = value;
6469 isc_uint32_t
6470 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
6471 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6473 return (zmgr->transfersin);
6476 void
6477 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
6478 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6480 zmgr->transfersperns = value;
6483 isc_uint32_t
6484 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
6485 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6487 return (zmgr->transfersperns);
6491 * Try to start a new incoming zone transfer to fill a quota
6492 * slot that was just vacated.
6494 * Requires:
6495 * The zone manager is locked by the caller.
6497 static void
6498 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
6499 dns_zone_t *zone;
6500 dns_zone_t *next;
6502 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
6503 zone != NULL;
6504 zone = next)
6506 isc_result_t result;
6507 next = ISC_LIST_NEXT(zone, statelink);
6508 result = zmgr_start_xfrin_ifquota(zmgr, zone);
6509 if (result == ISC_R_SUCCESS) {
6510 if (multi)
6511 continue;
6513 * We successfully filled the slot. We're done.
6515 break;
6516 } else if (result == ISC_R_QUOTA) {
6518 * Not enough quota. This is probably the per-server
6519 * quota, because we usually get called when a unit of
6520 * global quota has just been freed. Try the next
6521 * zone, it may succeed if it uses another master.
6523 continue;
6524 } else {
6525 dns_zone_log(zone, ISC_LOG_DEBUG(1),
6526 "starting zone transfer: %s",
6527 isc_result_totext(result));
6528 break;
6534 * Try to start an incoming zone transfer for 'zone', quota permitting.
6536 * Requires:
6537 * The zone manager is locked by the caller.
6539 * Returns:
6540 * ISC_R_SUCCESS There was enough quota and we attempted to
6541 * start a transfer. zone_xfrdone() has been or will
6542 * be called.
6543 * ISC_R_QUOTA Not enough quota.
6544 * Others Failure.
6546 static isc_result_t
6547 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
6548 dns_peer_t *peer = NULL;
6549 isc_netaddr_t masterip;
6550 isc_uint32_t nxfrsin, nxfrsperns;
6551 dns_zone_t *x;
6552 isc_uint32_t maxtransfersin, maxtransfersperns;
6553 isc_event_t *e;
6556 * Find any configured information about the server we'd
6557 * like to transfer this zone from.
6559 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
6560 (void)dns_peerlist_peerbyaddr(zone->view->peers,
6561 &masterip, &peer);
6564 * Determine the total maximum number of simultaneous
6565 * transfers allowed, and the maximum for this specific
6566 * master.
6568 maxtransfersin = zmgr->transfersin;
6569 maxtransfersperns = zmgr->transfersperns;
6570 if (peer != NULL)
6571 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
6574 * Count the total number of transfers that are in progress,
6575 * and the number of transfers in progress from this master.
6576 * We linearly scan a list of all transfers; if this turns
6577 * out to be too slow, we could hash on the master address.
6579 nxfrsin = nxfrsperns = 0;
6580 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
6581 x != NULL;
6582 x = ISC_LIST_NEXT(x, statelink))
6584 isc_netaddr_t xip;
6585 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
6586 nxfrsin++;
6587 if (isc_netaddr_equal(&xip, &masterip))
6588 nxfrsperns++;
6591 /* Enforce quota. */
6592 if (nxfrsin >= maxtransfersin)
6593 return (ISC_R_QUOTA);
6595 if (nxfrsperns >= maxtransfersperns)
6596 return (ISC_R_QUOTA);
6599 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
6600 * list and send it an event to let it start the actual transfer in the
6601 * context of its own task.
6603 e = isc_event_allocate(zmgr->mctx, zmgr,
6604 DNS_EVENT_ZONESTARTXFRIN,
6605 got_transfer_quota, zone,
6606 sizeof(isc_event_t));
6607 if (e == NULL)
6608 return (ISC_R_NOMEMORY);
6610 LOCK_ZONE(zone);
6611 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
6612 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
6613 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
6614 zone->statelist = &zmgr->xfrin_in_progress;
6615 isc_task_send(zone->task, &e);
6616 dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
6617 UNLOCK_ZONE(zone);
6619 return (ISC_R_SUCCESS);
6622 void
6623 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
6625 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6626 REQUIRE(iolimit > 0);
6628 zmgr->iolimit = iolimit;
6631 isc_uint32_t
6632 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
6634 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6636 return (zmgr->iolimit);
6640 * Get permission to request a file handle from the OS.
6641 * An event will be sent to action when one is available.
6642 * There are two queues available (high and low), the high
6643 * queue will be serviced before the low one.
6645 * zonemgr_putio() must be called after the event is delivered to
6646 * 'action'.
6649 static isc_result_t
6650 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
6651 isc_task_t *task, isc_taskaction_t action, void *arg,
6652 dns_io_t **iop)
6654 dns_io_t *io;
6655 isc_boolean_t queue;
6657 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6658 REQUIRE(iop != NULL && *iop == NULL);
6660 io = isc_mem_get(zmgr->mctx, sizeof(*io));
6661 if (io == NULL)
6662 return (ISC_R_NOMEMORY);
6663 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
6664 action, arg, sizeof(*io->event));
6665 if (io->event == NULL) {
6666 isc_mem_put(zmgr->mctx, io, sizeof(*io));
6667 return (ISC_R_NOMEMORY);
6669 io->zmgr = zmgr;
6670 io->high = high;
6671 io->task = NULL;
6672 isc_task_attach(task, &io->task);
6673 ISC_LINK_INIT(io, link);
6674 io->magic = IO_MAGIC;
6676 LOCK(&zmgr->iolock);
6677 zmgr->ioactive++;
6678 queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
6679 if (queue) {
6680 if (io->high)
6681 ISC_LIST_APPEND(zmgr->high, io, link);
6682 else
6683 ISC_LIST_APPEND(zmgr->low, io, link);
6685 UNLOCK(&zmgr->iolock);
6686 *iop = io;
6688 if (!queue) {
6689 isc_task_send(io->task, &io->event);
6691 return (ISC_R_SUCCESS);
6694 static void
6695 zonemgr_putio(dns_io_t **iop) {
6696 dns_io_t *io;
6697 dns_io_t *next;
6698 dns_zonemgr_t *zmgr;
6700 REQUIRE(iop != NULL);
6701 io = *iop;
6702 REQUIRE(DNS_IO_VALID(io));
6704 *iop = NULL;
6706 INSIST(!ISC_LINK_LINKED(io, link));
6707 INSIST(io->event == NULL);
6709 zmgr = io->zmgr;
6710 isc_task_detach(&io->task);
6711 io->magic = 0;
6712 isc_mem_put(zmgr->mctx, io, sizeof(*io));
6714 LOCK(&zmgr->iolock);
6715 INSIST(zmgr->ioactive > 0);
6716 zmgr->ioactive--;
6717 next = HEAD(zmgr->high);
6718 if (next == NULL)
6719 next = HEAD(zmgr->low);
6720 if (next != NULL) {
6721 if (next->high)
6722 ISC_LIST_UNLINK(zmgr->high, next, link);
6723 else
6724 ISC_LIST_UNLINK(zmgr->low, next, link);
6725 INSIST(next->event != NULL);
6727 UNLOCK(&zmgr->iolock);
6728 if (next != NULL)
6729 isc_task_send(next->task, &next->event);
6732 static void
6733 zonemgr_cancelio(dns_io_t *io) {
6734 isc_boolean_t send_event = ISC_FALSE;
6736 REQUIRE(DNS_IO_VALID(io));
6739 * If we are queued to be run then dequeue.
6741 LOCK(&io->zmgr->iolock);
6742 if (ISC_LINK_LINKED(io, link)) {
6743 if (io->high)
6744 ISC_LIST_UNLINK(io->zmgr->high, io, link);
6745 else
6746 ISC_LIST_UNLINK(io->zmgr->low, io, link);
6748 send_event = ISC_TRUE;
6749 INSIST(io->event != NULL);
6751 UNLOCK(&io->zmgr->iolock);
6752 if (send_event) {
6753 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
6754 isc_task_send(io->task, &io->event);
6758 static void
6759 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
6760 char *buf;
6761 int buflen;
6762 isc_result_t result;
6764 buflen = strlen(path) + strlen(templat) + 2;
6766 buf = isc_mem_get(zone->mctx, buflen);
6767 if (buf == NULL)
6768 return;
6770 result = isc_file_template(path, templat, buf, buflen);
6771 if (result != ISC_R_SUCCESS)
6772 goto cleanup;
6774 result = isc_file_renameunique(path, buf);
6775 if (result != ISC_R_SUCCESS)
6776 goto cleanup;
6778 dns_zone_log(zone, ISC_LOG_INFO, "saved '%s' as '%s'",
6779 path, buf);
6781 cleanup:
6782 isc_mem_put(zone->mctx, buf, buflen);
6785 #if 0
6786 /* Hook for ondestroy notifcation from a database. */
6788 static void
6789 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
6790 dns_db_t *db = event->sender;
6791 UNUSED(task);
6793 isc_event_free(&event);
6795 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
6796 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
6797 "database (%p) destroyed", (void*) db);
6799 #endif
6801 void
6802 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
6803 isc_interval_t interval;
6804 isc_uint32_t s, ns;
6805 isc_uint32_t pertic;
6806 isc_result_t result;
6808 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6810 if (value == 0)
6811 value = 1;
6813 if (value == 1) {
6814 s = 1;
6815 ns = 0;
6816 pertic = 1;
6817 } else if (value <= 10) {
6818 s = 0;
6819 ns = 1000000000 / value;
6820 pertic = 1;
6821 } else {
6822 s = 0;
6823 ns = (1000000000 / value) * 10;
6824 pertic = 10;
6827 isc_interval_set(&interval, s, ns);
6828 result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
6829 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6830 isc_ratelimiter_setpertic(zmgr->rl, pertic);
6832 zmgr->serialqueryrate = value;
6835 unsigned int
6836 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
6837 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6839 return (zmgr->serialqueryrate);
6842 void
6843 dns_zone_forcereload(dns_zone_t *zone) {
6844 REQUIRE(DNS_ZONE_VALID(zone));
6846 if (zone->type == dns_zone_master)
6847 return;
6849 LOCK_ZONE(zone);
6850 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
6851 UNLOCK_ZONE(zone);
6852 dns_zone_refresh(zone);
6855 isc_boolean_t
6856 dns_zone_isforced(dns_zone_t *zone) {
6857 REQUIRE(DNS_ZONE_VALID(zone));
6859 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
6862 isc_result_t
6863 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
6864 isc_result_t result = ISC_R_SUCCESS;
6866 LOCK_ZONE(zone);
6867 if (on) {
6868 if (zone->counters != NULL)
6869 goto done;
6870 result = dns_stats_alloccounters(zone->mctx, &zone->counters);
6871 } else {
6872 if (zone->counters == NULL)
6873 goto done;
6874 dns_stats_freecounters(zone->mctx, &zone->counters);
6876 done:
6877 UNLOCK_ZONE(zone);
6878 return (result);
6881 isc_uint64_t *
6882 dns_zone_getstatscounters(dns_zone_t *zone) {
6883 return (zone->counters);
6886 void
6887 dns_zone_dialup(dns_zone_t *zone) {
6889 REQUIRE(DNS_ZONE_VALID(zone));
6891 zone_debuglog(zone, "dns_zone_dialup", 3,
6892 "notify = %d, refresh = %d",
6893 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
6894 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
6896 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
6897 dns_zone_notify(zone);
6898 if (zone->type != dns_zone_master &&
6899 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
6900 dns_zone_refresh(zone);
6903 void
6904 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
6905 REQUIRE(DNS_ZONE_VALID(zone));
6907 LOCK_ZONE(zone);
6908 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
6909 DNS_ZONEFLG_DIALREFRESH |
6910 DNS_ZONEFLG_NOREFRESH);
6911 switch (dialup) {
6912 case dns_dialuptype_no:
6913 break;
6914 case dns_dialuptype_yes:
6915 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
6916 DNS_ZONEFLG_DIALREFRESH |
6917 DNS_ZONEFLG_NOREFRESH));
6918 break;
6919 case dns_dialuptype_notify:
6920 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
6921 break;
6922 case dns_dialuptype_notifypassive:
6923 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
6924 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
6925 break;
6926 case dns_dialuptype_refresh:
6927 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
6928 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
6929 break;
6930 case dns_dialuptype_passive:
6931 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
6932 break;
6933 default:
6934 INSIST(0);
6936 UNLOCK_ZONE(zone);
6939 isc_result_t
6940 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
6941 isc_result_t result = ISC_R_SUCCESS;
6943 REQUIRE(DNS_ZONE_VALID(zone));
6945 LOCK_ZONE(zone);
6946 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
6947 UNLOCK_ZONE(zone);
6949 return (result);
6952 const char *
6953 dns_zone_getkeydirectory(dns_zone_t *zone) {
6954 REQUIRE(DNS_ZONE_VALID(zone));
6956 return (zone->keydirectory);
6958 unsigned int
6959 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
6960 dns_zone_t *zone;
6961 unsigned int count = 0;
6963 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6965 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
6966 switch (state) {
6967 case DNS_ZONESTATE_XFERRUNNING:
6968 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
6969 zone != NULL;
6970 zone = ISC_LIST_NEXT(zone, statelink))
6971 count++;
6972 break;
6973 case DNS_ZONESTATE_XFERDEFERRED:
6974 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
6975 zone != NULL;
6976 zone = ISC_LIST_NEXT(zone, statelink))
6977 count++;
6978 break;
6979 case DNS_ZONESTATE_SOAQUERY:
6980 for (zone = ISC_LIST_HEAD(zmgr->zones);
6981 zone != NULL;
6982 zone = ISC_LIST_NEXT(zone, link))
6983 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
6984 count++;
6985 break;
6986 case DNS_ZONESTATE_ANY:
6987 for (zone = ISC_LIST_HEAD(zmgr->zones);
6988 zone != NULL;
6989 zone = ISC_LIST_NEXT(zone, link)) {
6990 dns_view_t *view = zone->view;
6991 if (view != NULL && strcmp(view->name, "_bind") == 0)
6992 continue;
6993 count++;
6995 break;
6996 default:
6997 INSIST(0);
7000 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
7002 return (count);
7005 isc_result_t
7006 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
7007 isc_boolean_t ok = ISC_TRUE;
7008 isc_boolean_t fail = ISC_FALSE;
7009 char namebuf[DNS_NAME_FORMATSIZE];
7010 char namebuf2[DNS_NAME_FORMATSIZE];
7011 char typebuf[DNS_RDATATYPE_FORMATSIZE];
7012 int level = ISC_LOG_WARNING;
7013 dns_name_t bad;
7015 REQUIRE(DNS_ZONE_VALID(zone));
7017 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
7018 return (ISC_R_SUCCESS);
7020 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
7021 level = ISC_LOG_ERROR;
7022 fail = ISC_TRUE;
7025 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
7026 if (!ok) {
7027 dns_name_format(name, namebuf, sizeof(namebuf));
7028 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
7029 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
7030 dns_result_totext(DNS_R_BADOWNERNAME));
7031 if (fail)
7032 return (DNS_R_BADOWNERNAME);
7035 dns_name_init(&bad, NULL);
7036 ok = dns_rdata_checknames(rdata, name, &bad);
7037 if (!ok) {
7038 dns_name_format(name, namebuf, sizeof(namebuf));
7039 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
7040 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
7041 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
7042 namebuf2, dns_result_totext(DNS_R_BADNAME));
7043 if (fail)
7044 return (DNS_R_BADNAME);
7047 return (ISC_R_SUCCESS);