Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / contrib / bind-9.3 / lib / dns / zone.c
1 /*
2  * Copyright (C) 2004-2006  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
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.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: zone.c,v 1.333.2.23.2.65 2006/07/19 01:04:24 marka Exp $ */
19
20 #include <config.h>
21
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>
33
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>
60
61 #define ZONE_MAGIC                      ISC_MAGIC('Z', 'O', 'N', 'E')
62 #define DNS_ZONE_VALID(zone)            ISC_MAGIC_VALID(zone, ZONE_MAGIC)
63
64 #define NOTIFY_MAGIC                    ISC_MAGIC('N', 't', 'f', 'y')
65 #define DNS_NOTIFY_VALID(notify)        ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
66
67 #define STUB_MAGIC                      ISC_MAGIC('S', 't', 'u', 'b')
68 #define DNS_STUB_VALID(stub)            ISC_MAGIC_VALID(stub, STUB_MAGIC)
69
70 #define ZONEMGR_MAGIC                   ISC_MAGIC('Z', 'm', 'g', 'r')
71 #define DNS_ZONEMGR_VALID(stub)         ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
72
73 #define LOAD_MAGIC                      ISC_MAGIC('L', 'o', 'a', 'd')
74 #define DNS_LOAD_VALID(load)            ISC_MAGIC_VALID(load, LOAD_MAGIC)
75
76 #define FORWARD_MAGIC                   ISC_MAGIC('F', 'o', 'r', 'w')
77 #define DNS_FORWARD_VALID(load)         ISC_MAGIC_VALID(load, FORWARD_MAGIC)
78
79 #define IO_MAGIC                        ISC_MAGIC('Z', 'm', 'I', 'O')
80 #define DNS_IO_VALID(load)              ISC_MAGIC_VALID(load, IO_MAGIC)
81
82 /*
83  * Ensure 'a' is at least 'min' but not more than 'max'.
84  */
85 #define RANGE(a, min, max) \
86                 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
87
88 /*
89  * Default values.
90  */
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 */
94
95 #ifndef DNS_MAX_EXPIRE
96 #define DNS_MAX_EXPIRE  14515200        /* 24 weeks */
97 #endif
98
99 #ifndef DNS_DUMP_DELAY
100 #define DNS_DUMP_DELAY 900              /* 15 minutes */
101 #endif
102
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;
109
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
125
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;
135
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;
162
163         isc_uint32_t            maxrefresh;
164         isc_uint32_t            minrefresh;
165         isc_uint32_t            maxretry;
166         isc_uint32_t            minretry;
167
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;
210         /*
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.
216          */
217         ISC_LINK(dns_zone_t)    statelink;
218         dns_zonelist_t          *statelist;
219         /*
220          * Optional per-zone statistics counters (NULL if not present).
221          */
222         isc_uint64_t        *counters;
223 };
224
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
268
269 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
270
271 /* Flags for zone_load() */
272 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
273
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;
286
287         /* Locked by rwlock. */
288         dns_zonelist_t          zones;
289         dns_zonelist_t          waiting_for_xfrin;
290         dns_zonelist_t          xfrin_in_progress;
291
292         /* Configuration data. */
293         isc_uint32_t            transfersin;
294         isc_uint32_t            transfersperns;
295         unsigned int            serialqueryrate;
296
297         /* Locked by iolock */
298         isc_uint32_t            iolimit;
299         isc_uint32_t            ioactive;
300         dns_iolist_t            high;
301         dns_iolist_t            low;
302 };
303
304 /*
305  * Hold notify state.
306  */
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;
317 };
318
319 #define DNS_NOTIFY_NOSOA        0x0001U
320
321 /*
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.
325  */
326
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;
333 };
334
335 /*
336  *      Hold load state.
337  */
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;
345 };
346
347 /*
348  *      Hold forward state.
349  */
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;
360 };
361
362 /*
363  *      Hold IO request state.
364  */
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;
372 };
373
374 #define SEND_BUFFER_SIZE 2048
375
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);
398
399 #if 0
400 /* ondestroy example */
401 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
402 #endif
403
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);
431
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);
437
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);
445
446 #define ENTER zone_debuglog(zone, me, 1, "enter")
447
448 static const unsigned int dbargc_default = 1;
449 static const char *dbargv_default[] = { "rbt" };
450
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)); \
463                 } \
464         } while (0)
465
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)); \
476                 } \
477         } while (0)
478
479 /***
480  ***    Public functions.
481  ***/
482
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;
487
488         REQUIRE(zonep != NULL && *zonep == NULL);
489         REQUIRE(mctx != NULL);
490
491         zone = isc_mem_get(mctx, sizeof(*zone));
492         if (zone == NULL)
493                 return (ISC_R_NOMEMORY);
494
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);
502         }
503
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;
580
581         zone->magic = ZONE_MAGIC;
582
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;
587
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);
593
594  free_mutex:
595         DESTROYLOCK(&zone->lock);
596         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
597         return (result);
598 }
599
600 /*
601  * Free a zone.  Because we require that there be no more
602  * outstanding events or references, no locking is necessary.
603  */
604 static void
605 zone_free(dns_zone_t *zone) {
606         isc_mem_t *mctx = NULL;
607
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);
613
614         /*
615          * Managed objects.  Order is important.
616          */
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);
622
623         if (zone->task != NULL)
624                 isc_task_detach(&zone->task);
625         if (zone->zmgr)
626                 dns_zonemgr_releasezone(zone->zmgr, zone);
627
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);
663
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);
671 }
672
673 /*
674  *      Single shot.
675  */
676 void
677 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
678
679         REQUIRE(DNS_ZONE_VALID(zone));
680         REQUIRE(rdclass != dns_rdataclass_none);
681
682         /*
683          * Test and set.
684          */
685         LOCK_ZONE(zone);
686         REQUIRE(zone->rdclass == dns_rdataclass_none ||
687                 zone->rdclass == rdclass);
688         zone->rdclass = rdclass;
689         UNLOCK_ZONE(zone);
690 }
691
692 dns_rdataclass_t
693 dns_zone_getclass(dns_zone_t *zone){
694         REQUIRE(DNS_ZONE_VALID(zone));
695
696         return (zone->rdclass);
697 }
698
699 void
700 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
701         REQUIRE(DNS_ZONE_VALID(zone));
702
703         LOCK_ZONE(zone);
704         zone->notifytype = notifytype;
705         UNLOCK_ZONE(zone);
706 }
707
708 /*
709  *      Single shot.
710  */
711 void
712 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
713
714         REQUIRE(DNS_ZONE_VALID(zone));
715         REQUIRE(type != dns_zone_none);
716
717         /*
718          * Test and set.
719          */
720         LOCK_ZONE(zone);
721         REQUIRE(zone->type == dns_zone_none || zone->type == type);
722         zone->type = type;
723         UNLOCK_ZONE(zone);
724 }
725
726 static void
727 zone_freedbargs(dns_zone_t *zone) {
728         unsigned int i;
729
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));
736         }
737         zone->db_argc = 0;
738         zone->db_argv = NULL;
739 }
740
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;
747
748         REQUIRE(DNS_ZONE_VALID(zone));
749         REQUIRE(dbargc >= 1);
750         REQUIRE(dbargv != NULL);
751
752         LOCK_ZONE(zone);
753
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;
764         }
765
766         /* Free the old list. */
767         zone_freedbargs(zone);
768
769         zone->db_argc = dbargc;
770         zone->db_argv = new;
771         result = ISC_R_SUCCESS;
772         goto unlock;
773
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));
780         }
781         result = ISC_R_NOMEMORY;
782
783  unlock:
784         UNLOCK_ZONE(zone);
785         return (result);
786 }
787
788 void
789 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
790         REQUIRE(DNS_ZONE_VALID(zone));
791
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);
797 }
798
799
800 dns_view_t *
801 dns_zone_getview(dns_zone_t *zone) {
802         REQUIRE(DNS_ZONE_VALID(zone));
803
804         return (zone->view);
805 }
806
807
808 isc_result_t
809 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
810         isc_result_t result;
811
812         REQUIRE(DNS_ZONE_VALID(zone));
813         REQUIRE(origin != NULL);
814
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);
819         }
820         result = dns_name_dup(origin, zone->mctx, &zone->origin);
821         UNLOCK_ZONE(zone);
822         return (result);
823 }
824
825
826 static isc_result_t
827 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
828         char *copy;
829
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;
836         }
837
838         if (*field != NULL)
839                 isc_mem_free(zone->mctx, *field);
840
841         *field = copy;
842         return (ISC_R_SUCCESS);
843 }
844
845 isc_result_t
846 dns_zone_setfile(dns_zone_t *zone, const char *file) {
847         isc_result_t result = ISC_R_SUCCESS;
848
849         REQUIRE(DNS_ZONE_VALID(zone));
850
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);
856
857         return (result);
858 }
859
860 const char *
861 dns_zone_getfile(dns_zone_t *zone) {
862         REQUIRE(DNS_ZONE_VALID(zone));
863
864         return (zone->masterfile);
865 }
866
867 static isc_result_t
868 default_journal(dns_zone_t *zone) {
869         isc_result_t result;
870         char *journal;
871
872         REQUIRE(DNS_ZONE_VALID(zone));
873         REQUIRE(LOCKED_ZONE(zone));
874
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;
885         }
886         result = dns_zone_setstring(zone, &zone->journal, journal);
887         if (journal != NULL)
888                 isc_mem_free(zone->mctx, journal);
889         return (result);
890 }
891
892 isc_result_t
893 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
894         isc_result_t result = ISC_R_SUCCESS;
895
896         REQUIRE(DNS_ZONE_VALID(zone));
897
898         LOCK_ZONE(zone);
899         result = dns_zone_setstring(zone, &zone->journal, journal);
900         UNLOCK_ZONE(zone);
901
902         return (result);
903 }
904
905 char *
906 dns_zone_getjournal(dns_zone_t *zone) {
907         REQUIRE(DNS_ZONE_VALID(zone));
908
909         return (zone->journal);
910 }
911
912 /*
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.
916  *
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; }".
920  */
921 static isc_boolean_t
922 zone_isdynamic(dns_zone_t *zone) {
923         REQUIRE(DNS_ZONE_VALID(zone));
924
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
931                            &&
932                            zone->update_acl->elements[0].type ==
933                            dns_aclelementtype_any))));
934 }
935
936
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;
943
944         REQUIRE(DNS_ZONE_VALID(zone));
945
946         LOCK_ZONE(zone);
947         TIME_NOW(&now);
948
949         INSIST(zone->type != dns_zone_none);
950
951         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
952                 result = ISC_R_SUCCESS;
953                 goto cleanup;
954         }
955
956         if (zone->db != NULL && zone->masterfile == NULL) {
957                 /*
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.
964                  */
965                 result = ISC_R_SUCCESS;
966                 goto cleanup;
967         }
968
969         if (zone->db != NULL && zone_isdynamic(zone)) {
970                 /*
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.
974                  */
975                 if (zone->type == dns_zone_master)
976                         result = DNS_R_DYNAMIC;
977                 else
978                         result = ISC_R_SUCCESS;
979                 goto cleanup;
980         }
981
982         /*
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.
986          */
987         if (zone->masterfile != NULL && ! isc_time_isepoch(&zone->loadtime)) {
988                 /*
989                  * The file is already loaded.  If we are just doing a
990                  * "rndc reconfig", we are done.
991                  */
992                 if ((flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
993                         result = ISC_R_SUCCESS;
994                         goto cleanup;
995                 }
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;
1006                         }
1007                 }
1008         }
1009
1010         INSIST(zone->db_argc >= 1);
1011
1012         /*
1013          * Built in zones don't need to be reloaded.
1014          */
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;
1020         }
1021
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;
1035                 }
1036         }
1037
1038         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1039
1040         /*
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.
1045          */
1046         TIME_NOW(&loadtime);
1047
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);
1054
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;
1060         }
1061         dns_db_settask(db, zone->task);
1062
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;
1073                         }
1074                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1075                                      "no master file configured: continuing");
1076                 }
1077         }
1078
1079         if (result == DNS_R_CONTINUE) {
1080                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1081                 goto cleanup;
1082         }
1083
1084         result = zone_postload(zone, db, loadtime, result);
1085
1086  cleanup:
1087         UNLOCK_ZONE(zone);
1088         if (db != NULL)
1089                 dns_db_detach(&db);
1090         return (result);
1091 }
1092
1093 isc_result_t
1094 dns_zone_load(dns_zone_t *zone) {
1095         return (zone_load(zone, 0));
1096 }
1097
1098 isc_result_t
1099 dns_zone_loadnew(dns_zone_t *zone) {
1100         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1101 }
1102
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;
1108
1109         REQUIRE(DNS_LOAD_VALID(load));
1110
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;
1116
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;
1140
1141  fail:
1142         zone_loaddone(load, result);
1143 }
1144
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;
1151
1152         REQUIRE(DNS_ZONE_VALID(zone));
1153         INSIST(task == zone->task);
1154         ENTER;
1155
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;
1161
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;
1173
1174  fail:
1175         dump_done(zone, result);
1176 }
1177
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;
1184
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;
1198
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);
1203
1204                 load->mctx = NULL;
1205                 load->zone = NULL;
1206                 load->db = NULL;
1207                 load->loadtime = loadtime;
1208                 load->magic = LOAD_MAGIC;
1209
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) {
1222                         /*
1223                          * We can't report multiple errors so ignore
1224                          * the result of dns_db_endload().
1225                          */
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;
1233
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;
1245         }
1246
1247         return (result);
1248
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);
1256 }
1257
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)
1261 {
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);
1268
1269         TIME_NOW(&now);
1270
1271         /*
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.
1275          */
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;
1293         }
1294
1295         dns_zone_log(zone, ISC_LOG_DEBUG(2),
1296                      "number of nodes in database: %u",
1297                      dns_db_nodecount(db));
1298
1299         if (result == DNS_R_SEENINCLUDE)
1300                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1301         else
1302                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1303
1304         /*
1305          * Apply update log, if any, on initial load.
1306          */
1307         if (zone->journal != NULL &&
1308             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
1309             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
1310         {
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;
1320                 }
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;
1326                 }
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;
1333         }
1334
1335         zone->loadtime = loadtime;
1336
1337         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
1338
1339         /*
1340          * Obtain ns and soa counts for top of zone.
1341          */
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");
1351         }
1352
1353         /*
1354          * Master / Slave / Stub zones require both NS and SOA records at
1355          * the top of the zone.
1356          */
1357
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;
1366                 }
1367                 if (nscount == 0) {
1368                         dns_zone_log(zone, ISC_LOG_ERROR,
1369                                      "has no NS records");
1370                         result = DNS_R_BADZONE;
1371                 }
1372                 if (result != ISC_R_SUCCESS)
1373                         goto cleanup;
1374                 if (zone->db != NULL) {
1375                         /*
1376                          * This is checked in zone_replacedb() for slave zones
1377                          * as they don't reload from disk.
1378                          */
1379                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
1380                             !isc_serial_gt(serial, zone->serial)) {
1381                                 isc_uint32_t serialmin, serialmax;
1382
1383                                 INSIST(zone->type == dns_zone_master);
1384
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");
1401                 }
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);
1411
1412                 if (zone->type == dns_zone_slave ||
1413                     zone->type == dns_zone_stub) {
1414                         isc_time_t t;
1415                         isc_uint32_t delay;
1416
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);
1427
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;
1434                 }
1435                 break;
1436         default:
1437                 UNEXPECTED_ERROR(__FILE__, __LINE__,
1438                                  "unexpected zone type %d", zone->type);
1439                 result = ISC_R_UNEXPECTED;
1440                 goto cleanup;
1441         }
1442
1443
1444 #if 0
1445         /* destroy notification example. */
1446         {
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);
1453         }
1454 #endif
1455
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);
1464         }
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);
1470
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)" : "");
1475
1476         return (result);
1477
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");
1485
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;
1491         }
1492         return (result);
1493 }
1494
1495 static isc_boolean_t
1496 exit_check(dns_zone_t *zone) {
1497
1498         REQUIRE(LOCKED_ZONE(zone));
1499
1500         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
1501             zone->irefs == 0)
1502         {
1503                 /*
1504                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
1505                  */
1506                 INSIST(isc_refcount_current(&zone->erefs) == 0);
1507                 return (ISC_TRUE);
1508         }
1509         return (ISC_FALSE);
1510 }
1511
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)
1515 {
1516         isc_result_t result;
1517         unsigned int count;
1518         dns_rdataset_t rdataset;
1519
1520         REQUIRE(nscount != NULL);
1521
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;
1529         }
1530         if (result != ISC_R_SUCCESS)
1531                 goto invalidate_rdataset;
1532
1533         count = 0;
1534         result = dns_rdataset_first(&rdataset);
1535         while (result == ISC_R_SUCCESS) {
1536                 count++;
1537                 result = dns_rdataset_next(&rdataset);
1538         }
1539         dns_rdataset_disassociate(&rdataset);
1540
1541         *nscount = count;
1542         result = ISC_R_SUCCESS;
1543
1544  invalidate_rdataset:
1545         dns_rdataset_invalidate(&rdataset);
1546
1547         return (result);
1548 }
1549
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)
1556 {
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;
1562
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;
1581         }
1582         if (result != ISC_R_SUCCESS)
1583                 goto invalidate_rdataset;
1584
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);
1594                 }
1595
1596                 result = dns_rdataset_next(&rdataset);
1597                 dns_rdata_reset(&rdata);
1598         }
1599         dns_rdataset_disassociate(&rdataset);
1600
1601         if (soacount != NULL)
1602                 *soacount = count;
1603
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;
1615         }
1616
1617         result = ISC_R_SUCCESS;
1618
1619  invalidate_rdataset:
1620         dns_rdataset_invalidate(&rdataset);
1621
1622         return (result);
1623 }
1624
1625 /*
1626  * zone must be locked.
1627  */
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)
1633 {
1634         dns_dbversion_t *version;
1635         isc_result_t result;
1636         isc_result_t answer = ISC_R_SUCCESS;
1637         dns_dbnode_t *node;
1638
1639         REQUIRE(db != NULL);
1640         REQUIRE(origin != NULL);
1641
1642         version = NULL;
1643         dns_db_currentversion(db, &version);
1644
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;
1650         }
1651
1652         if (nscount != NULL) {
1653                 result = zone_count_ns_rr(db, node, version, nscount);
1654                 if (result != ISC_R_SUCCESS)
1655                         answer = result;
1656         }
1657
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;
1665         }
1666
1667         dns_db_detachnode(db, &node);
1668  closeversion:
1669         dns_db_closeversion(db, &version, ISC_FALSE);
1670
1671         return (answer);
1672 }
1673
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;
1680 }
1681
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;
1687
1688         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1689
1690         zone = *zonep;
1691
1692         isc_refcount_decrement(&zone->erefs, &refs);
1693
1694         if (refs == 0) {
1695                 LOCK_ZONE(zone);
1696                 /*
1697                  * We just detached the last external reference.
1698                  */
1699                 if (zone->task != NULL) {
1700                         /*
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.
1705                          */
1706                         isc_event_t *ev = &zone->ctlevent;
1707                         isc_task_send(zone->task, &ev);
1708                 } else {
1709                         /*
1710                          * This zone is not being managed; it has
1711                          * no task and can have no outstanding
1712                          * events.  Free it immediately.
1713                          */
1714                         /*
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.
1719                          */
1720                         INSIST(zone->view == NULL);
1721                         free_now = ISC_TRUE;
1722                 }
1723                 UNLOCK_ZONE(zone);
1724         }
1725         *zonep = NULL;
1726         if (free_now)
1727                 zone_free(zone);
1728 }
1729
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);
1737 }
1738
1739 static void
1740 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
1741
1742         /*
1743          * 'source' locked by caller.
1744          */
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;
1752 }
1753
1754 static void
1755 zone_idetach(dns_zone_t **zonep) {
1756         dns_zone_t *zone;
1757
1758         /*
1759          * 'zone' locked by caller.
1760          */
1761         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1762         zone = *zonep;
1763         REQUIRE(LOCKED_ZONE(*zonep));
1764         *zonep = NULL;
1765
1766         INSIST(zone->irefs > 0);
1767         zone->irefs--;
1768         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
1769 }
1770
1771 void
1772 dns_zone_idetach(dns_zone_t **zonep) {
1773         dns_zone_t *zone;
1774         isc_boolean_t free_needed;
1775
1776         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1777         zone = *zonep;
1778         *zonep = NULL;
1779
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);
1787 }
1788
1789 isc_mem_t *
1790 dns_zone_getmctx(dns_zone_t *zone) {
1791         REQUIRE(DNS_ZONE_VALID(zone));
1792
1793         return (zone->mctx);
1794 }
1795
1796 dns_zonemgr_t *
1797 dns_zone_getmgr(dns_zone_t *zone) {
1798         REQUIRE(DNS_ZONE_VALID(zone));
1799
1800         return (zone->zmgr);
1801 }
1802
1803 void
1804 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
1805         REQUIRE(DNS_ZONE_VALID(zone));
1806
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);
1813 }
1814
1815 void
1816 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
1817 {
1818         REQUIRE(DNS_ZONE_VALID(zone));
1819
1820         LOCK_ZONE(zone);
1821         if (value)
1822                 zone->options |= option;
1823         else
1824                 zone->options &= ~option;
1825         UNLOCK_ZONE(zone);
1826 }
1827
1828 unsigned int
1829 dns_zone_getoptions(dns_zone_t *zone) {
1830
1831         REQUIRE(DNS_ZONE_VALID(zone));
1832
1833         return (zone->options);
1834 }
1835
1836 isc_result_t
1837 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
1838         REQUIRE(DNS_ZONE_VALID(zone));
1839
1840         LOCK_ZONE(zone);
1841         zone->xfrsource4 = *xfrsource;
1842         UNLOCK_ZONE(zone);
1843
1844         return (ISC_R_SUCCESS);
1845 }
1846
1847 isc_sockaddr_t *
1848 dns_zone_getxfrsource4(dns_zone_t *zone) {
1849         REQUIRE(DNS_ZONE_VALID(zone));
1850         return (&zone->xfrsource4);
1851 }
1852
1853 isc_result_t
1854 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
1855         REQUIRE(DNS_ZONE_VALID(zone));
1856
1857         LOCK_ZONE(zone);
1858         zone->xfrsource6 = *xfrsource;
1859         UNLOCK_ZONE(zone);
1860
1861         return (ISC_R_SUCCESS);
1862 }
1863
1864 isc_sockaddr_t *
1865 dns_zone_getxfrsource6(dns_zone_t *zone) {
1866         REQUIRE(DNS_ZONE_VALID(zone));
1867         return (&zone->xfrsource6);
1868 }
1869
1870 isc_result_t
1871 dns_zone_setaltxfrsource4(dns_zone_t *zone,
1872                           const isc_sockaddr_t *altxfrsource)
1873 {
1874         REQUIRE(DNS_ZONE_VALID(zone));
1875
1876         LOCK_ZONE(zone);
1877         zone->altxfrsource4 = *altxfrsource;
1878         UNLOCK_ZONE(zone);
1879
1880         return (ISC_R_SUCCESS);
1881 }
1882
1883 isc_sockaddr_t *
1884 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
1885         REQUIRE(DNS_ZONE_VALID(zone));
1886         return (&zone->altxfrsource4);
1887 }
1888
1889 isc_result_t
1890 dns_zone_setaltxfrsource6(dns_zone_t *zone,
1891                           const isc_sockaddr_t *altxfrsource)
1892 {
1893         REQUIRE(DNS_ZONE_VALID(zone));
1894
1895         LOCK_ZONE(zone);
1896         zone->altxfrsource6 = *altxfrsource;
1897         UNLOCK_ZONE(zone);
1898
1899         return (ISC_R_SUCCESS);
1900 }
1901
1902 isc_sockaddr_t *
1903 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
1904         REQUIRE(DNS_ZONE_VALID(zone));
1905         return (&zone->altxfrsource6);
1906 }
1907
1908 isc_result_t
1909 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
1910         REQUIRE(DNS_ZONE_VALID(zone));
1911
1912         LOCK_ZONE(zone);
1913         zone->notifysrc4 = *notifysrc;
1914         UNLOCK_ZONE(zone);
1915
1916         return (ISC_R_SUCCESS);
1917 }
1918
1919 isc_sockaddr_t *
1920 dns_zone_getnotifysrc4(dns_zone_t *zone) {
1921         REQUIRE(DNS_ZONE_VALID(zone));
1922         return (&zone->notifysrc4);
1923 }
1924
1925 isc_result_t
1926 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
1927         REQUIRE(DNS_ZONE_VALID(zone));
1928
1929         LOCK_ZONE(zone);
1930         zone->notifysrc6 = *notifysrc;
1931         UNLOCK_ZONE(zone);
1932
1933         return (ISC_R_SUCCESS);
1934 }
1935
1936 isc_sockaddr_t *
1937 dns_zone_getnotifysrc6(dns_zone_t *zone) {
1938         REQUIRE(DNS_ZONE_VALID(zone));
1939         return (&zone->notifysrc6);
1940 }
1941
1942 isc_result_t
1943 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
1944                        isc_uint32_t count)
1945 {
1946         isc_sockaddr_t *new;
1947
1948         REQUIRE(DNS_ZONE_VALID(zone));
1949         REQUIRE(count == 0 || notify != NULL);
1950
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;
1957         }
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);
1963                 }
1964                 memcpy(new, notify, count * sizeof(*new));
1965                 zone->notify = new;
1966                 zone->notifycnt = count;
1967         }
1968         UNLOCK_ZONE(zone);
1969         return (ISC_R_SUCCESS);
1970 }
1971
1972 isc_result_t
1973 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
1974                     isc_uint32_t count)
1975 {
1976         isc_result_t result;
1977
1978         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
1979         return (result);
1980 }
1981
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)
1987 {
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;
1993
1994         REQUIRE(DNS_ZONE_VALID(zone));
1995         REQUIRE(count == 0 || masters != NULL);
1996         if (keynames != NULL) {
1997                 REQUIRE(count != 0);
1998         }
1999
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;
2005         }
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;
2015                         }
2016                 }
2017                 isc_mem_put(zone->mctx, zone->masterkeynames,
2018                             zone->masterscnt * sizeof(dns_name_t *));
2019                 zone->masterkeynames = NULL;
2020         }
2021         if (zone->mastersok != NULL) {
2022                 isc_mem_put(zone->mctx, zone->mastersok,
2023                             zone->masterscnt * sizeof(isc_boolean_t));
2024                 zone->mastersok = NULL;
2025         }
2026         zone->masterscnt = 0;
2027         /*
2028          * If count == 0, don't allocate any space for masters, mastersok or
2029          * keynames so internally, those pointers are NULL if count == 0
2030          */
2031         if (count == 0)
2032                 goto unlock;
2033
2034         /*
2035          * masters must countain count elements!
2036          */
2037         new = isc_mem_get(zone->mctx, count * sizeof(*new));
2038         if (new == NULL) {
2039                 result = ISC_R_NOMEMORY;
2040                 goto unlock;
2041         }
2042         memcpy(new, masters, count * sizeof(*new));
2043         
2044         /*
2045          * Similarly for mastersok.
2046          */
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;
2052         };
2053         for (i = 0; i < count; i++)
2054                 newok[i] = ISC_FALSE;
2055
2056         /*
2057          * if keynames is non-NULL, it must contain count elements!
2058          */
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;
2067                 }
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;
2093                                 }
2094                         }
2095                 }
2096         }
2097
2098         /*
2099          * Everything is ok so attach to the zone.
2100          */
2101         zone->masters = new;
2102         zone->mastersok = newok;
2103         zone->masterkeynames = newname;
2104         zone->masterscnt = count;
2105         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
2106
2107  unlock:
2108         UNLOCK_ZONE(zone);
2109         return (result);
2110 }
2111
2112 isc_result_t
2113 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
2114         isc_result_t result = ISC_R_SUCCESS;
2115
2116         REQUIRE(DNS_ZONE_VALID(zone));
2117
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);
2124
2125         return (result);
2126 }
2127
2128 /*
2129  * Co-ordinates the starting of routine jobs.
2130  */
2131
2132 void
2133 dns_zone_maintenance(dns_zone_t *zone) {
2134         const char me[] = "dns_zone_maintenance";
2135         isc_time_t now;
2136
2137         REQUIRE(DNS_ZONE_VALID(zone));
2138         ENTER;
2139
2140         LOCK_ZONE(zone);
2141         TIME_NOW(&now);
2142         zone_settimer(zone, &now);
2143         UNLOCK_ZONE(zone);
2144 }
2145
2146 static inline isc_boolean_t
2147 was_dumping(dns_zone_t *zone) {
2148         isc_boolean_t dumping;
2149
2150         REQUIRE(LOCKED_ZONE(zone));
2151
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);
2157         }
2158         return (dumping);
2159 }
2160
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;
2167
2168         REQUIRE(DNS_ZONE_VALID(zone));
2169         ENTER;
2170
2171         /*
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.
2177          */
2178         if (zone->view == NULL || zone->view->adb == NULL)
2179                 return;
2180
2181         TIME_NOW(&now);
2182
2183         /*
2184          * Expire check.
2185          */
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;
2194                 }
2195                 UNLOCK_ZONE(zone);
2196                 break;
2197         default:
2198                 break;
2199         }
2200
2201         /*
2202          * Up to date check.
2203          */
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;
2213         }
2214
2215         /*
2216          * Do we need to consolidate the backing store?
2217          */
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));
2236                 }
2237                 break;
2238         default:
2239                 break;
2240         }
2241
2242         /*
2243          * Do we need to send out notify messages?
2244          */
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;
2253         }
2254         zone_settimer(zone, &now);
2255 }
2256
2257 void
2258 dns_zone_markdirty(dns_zone_t *zone) {
2259
2260         LOCK_ZONE(zone);
2261         zone_needdump(zone, DNS_DUMP_DELAY);
2262         UNLOCK_ZONE(zone);
2263 }
2264
2265 void
2266 dns_zone_expire(dns_zone_t *zone) {
2267         REQUIRE(DNS_ZONE_VALID(zone));
2268
2269         LOCK_ZONE(zone);
2270         zone_expire(zone);
2271         UNLOCK_ZONE(zone);
2272 }
2273
2274 static void
2275 zone_expire(dns_zone_t *zone) {
2276         /*
2277          * 'zone' locked by caller.
2278          */
2279
2280         REQUIRE(LOCKED_ZONE(zone));
2281
2282         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
2283
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);
2289 }
2290
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;
2297
2298         REQUIRE(DNS_ZONE_VALID(zone));
2299
2300         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
2301                 return;
2302
2303         /*
2304          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
2305          * in progress at a time.
2306          */
2307
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;
2316         }
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;
2322
2323         /*
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.
2327          */
2328         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
2329                          0);
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));
2335
2336         /*
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.
2340          */
2341         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
2342                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
2343
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);
2351 }
2352
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;
2357
2358         REQUIRE(DNS_ZONE_VALID(zone));
2359
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);
2372 }
2373
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;
2378
2379         REQUIRE(DNS_ZONE_VALID(zone));
2380
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);
2387 }
2388
2389 static void
2390 zone_needdump(dns_zone_t *zone, unsigned int delay) {
2391         isc_time_t dumptime;
2392         isc_time_t now;
2393
2394         /*
2395          * 'zone' locked by caller
2396          */
2397
2398         REQUIRE(DNS_ZONE_VALID(zone));
2399         REQUIRE(LOCKED_ZONE(zone));
2400
2401         /*
2402          * Do we have a place to dump to and are we loaded?
2403          */
2404         if (zone->masterfile == NULL ||
2405             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
2406                 return;
2407
2408         TIME_NOW(&now);
2409         /* add some noise */
2410         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
2411
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);
2418 }
2419
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;
2427
2428         REQUIRE(DNS_ZONE_VALID(zone));
2429
2430         ENTER;
2431
2432         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
2433             zone->journalsize != -1) {
2434                 isc_uint32_t serial;
2435                 isc_result_t tresult;
2436
2437                 /*
2438                  * We don't own these, zone->dctx must stay valid.
2439                  */
2440                 db = dns_dumpctx_db(zone->dctx);
2441                 version = dns_dumpctx_version(zone->dctx);
2442
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;
2462                         }
2463                 }
2464         }
2465
2466         LOCK_ZONE(zone);
2467         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
2468         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
2469                 /*
2470                  * Try again in a short while.
2471                  */
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);
2483
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);
2491 }
2492
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;
2501
2502 /*
2503  * 'compact' MUST only be set if we are task locked.
2504  */
2505
2506         REQUIRE(DNS_ZONE_VALID(zone));
2507         ENTER;
2508
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;
2519         }
2520         if (masterfile == NULL) {
2521                 result = DNS_R_NOMASTERFILE;
2522                 goto fail;
2523         }
2524
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);
2543         }
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;
2550
2551         if (result == DNS_R_CONTINUE)
2552                 return (ISC_R_SUCCESS); /* XXXMPA */
2553
2554         again = ISC_FALSE;
2555         LOCK_ZONE(zone);
2556         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
2557         if (result != ISC_R_SUCCESS) {
2558                 /*
2559                  * Try again in a short while.
2560                  */
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;
2574
2575         return (result);
2576 }
2577
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;
2583
2584         REQUIRE(DNS_ZONE_VALID(zone));
2585
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);
2592
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);
2598 }
2599
2600 isc_result_t
2601 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
2602         return dumptostream(zone, fd, &dns_master_style_default);
2603 }
2604
2605 isc_result_t
2606 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
2607         return dumptostream(zone, fd, &dns_master_style_full);
2608 }
2609
2610 void
2611 dns_zone_unload(dns_zone_t *zone) {
2612         REQUIRE(DNS_ZONE_VALID(zone));
2613
2614         LOCK_ZONE(zone);
2615         zone_unload(zone);
2616         UNLOCK_ZONE(zone);
2617 }
2618
2619 static void
2620 notify_cancel(dns_zone_t *zone) {
2621         dns_notify_t *notify;
2622
2623         /*
2624          * 'zone' locked by caller.
2625          */
2626
2627         REQUIRE(LOCKED_ZONE(zone));
2628
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);
2636         }
2637 }
2638
2639 static void
2640 zone_unload(dns_zone_t *zone) {
2641
2642         /*
2643          * 'zone' locked by caller.
2644          */
2645
2646         REQUIRE(LOCKED_ZONE(zone));
2647
2648         dns_db_detach(&zone->db);
2649         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
2650         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2651 }
2652
2653 void
2654 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
2655         REQUIRE(DNS_ZONE_VALID(zone));
2656         REQUIRE(val > 0);
2657
2658         zone->minrefresh = val;
2659 }
2660
2661 void
2662 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
2663         REQUIRE(DNS_ZONE_VALID(zone));
2664         REQUIRE(val > 0);
2665
2666         zone->maxrefresh = val;
2667 }
2668
2669 void
2670 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
2671         REQUIRE(DNS_ZONE_VALID(zone));
2672         REQUIRE(val > 0);
2673
2674         zone->minretry = val;
2675 }
2676
2677 void
2678 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
2679         REQUIRE(DNS_ZONE_VALID(zone));
2680         REQUIRE(val > 0);
2681
2682         zone->maxretry = val;
2683 }
2684
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;
2688
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);
2699         }
2700         return (ISC_FALSE);
2701 }
2702
2703 static void
2704 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
2705         isc_mem_t *mctx;
2706
2707         /*
2708          * Caller holds zone lock.
2709          */
2710         REQUIRE(DNS_NOTIFY_VALID(notify));
2711
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);
2724         }
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);
2734 }
2735
2736 static isc_result_t
2737 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
2738         dns_notify_t *notify;
2739
2740         REQUIRE(notifyp != NULL && *notifyp == NULL);
2741
2742         notify = isc_mem_get(mctx, sizeof(*notify));
2743         if (notify == NULL)
2744                 return (ISC_R_NOMEMORY);
2745
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);
2758 }
2759
2760 /*
2761  * XXXAG should check for DNS_ZONEFLG_EXITING
2762  */
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;
2767
2768         UNUSED(task);
2769
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;
2779         }
2780         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
2781                 LOCK_ZONE(notify->zone);
2782                 notify_send(notify);
2783                 UNLOCK_ZONE(notify->zone);
2784         }
2785         notify_destroy(notify, ISC_FALSE);
2786 }
2787
2788 static void
2789 notify_find_address(dns_notify_t *notify) {
2790         isc_result_t result;
2791         unsigned int options;
2792
2793         REQUIRE(DNS_NOTIFY_VALID(notify));
2794         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
2795                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
2796
2797         if (notify->zone->view->adb == NULL)
2798                 goto destroy;
2799
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);
2807
2808         /* Something failed? */
2809         if (result != ISC_R_SUCCESS)
2810                 goto destroy;
2811
2812         /* More addresses pending? */
2813         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
2814                 return;
2815
2816         /* We have as many addresses as we can get. */
2817         LOCK_ZONE(notify->zone);
2818         notify_send(notify);
2819         UNLOCK_ZONE(notify->zone);
2820
2821  destroy:
2822         notify_destroy(notify, ISC_FALSE);
2823 }
2824
2825
2826 static isc_result_t
2827 notify_send_queue(dns_notify_t *notify) {
2828         isc_event_t *e;
2829         isc_result_t result;
2830
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);
2844 }
2845
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;
2856
2857         notify = event->ev_arg;
2858         REQUIRE(DNS_NOTIFY_VALID(notify));
2859
2860         UNUSED(task);
2861
2862         LOCK_ZONE(notify->zone);
2863
2864         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
2865                 result = ISC_R_CANCELED;
2866                 goto cleanup;
2867         }
2868
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;
2875         }
2876
2877         /*
2878          * The raw IPv4 address should also exist.  Don't send to the
2879          * mapped form.
2880          */
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;
2889         }
2890
2891         result = notify_createmessage(notify->zone, notify->flags, &message);
2892         if (result != ISC_R_SUCCESS)
2893                 goto cleanup;
2894
2895         isc_netaddr_fromsockaddr(&dstip, &notify->dst);
2896         (void)dns_view_getpeertsig(notify->zone->view, &dstip, &key);
2897
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;
2911         }
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);
2929 }
2930
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;
2937
2938         /*
2939          * Zone lock held by caller.
2940          */
2941         REQUIRE(DNS_NOTIFY_VALID(notify));
2942         REQUIRE(LOCKED_ZONE(notify->zone));
2943
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;
2963         }
2964
2965  cleanup:
2966         if (new != NULL)
2967                 notify_destroy(new, ISC_TRUE);
2968 }
2969
2970 void
2971 dns_zone_notify(dns_zone_t *zone) {
2972         isc_time_t now;
2973
2974         REQUIRE(DNS_ZONE_VALID(zone));
2975
2976         LOCK_ZONE(zone);
2977         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
2978
2979         TIME_NOW(&now);
2980         zone_settimer(zone, &now);
2981         UNLOCK_ZONE(zone);
2982 }
2983
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;
3005
3006         REQUIRE(DNS_ZONE_VALID(zone));
3007
3008         LOCK_ZONE(zone);
3009         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
3010         notifytype = zone->notifytype;
3011         UNLOCK_ZONE(zone);
3012
3013         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3014                 return;
3015
3016         if (notifytype == dns_notifytype_no)
3017                 return;
3018
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;
3025
3026         origin = &zone->origin;
3027
3028         /*
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.
3031          */
3032         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
3033                 flags |= DNS_NOTIFY_NOSOA;
3034
3035         /*
3036          * Get SOA RRset.
3037          */
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;
3042
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;
3048
3049         /*
3050          * Find serial and master server's name.
3051          */
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;
3065
3066         /*
3067          * Enqueue notify requests for 'also-notify' servers.
3068          */
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;
3088                 }
3089                 notify = NULL;
3090         }
3091         UNLOCK_ZONE(zone);
3092
3093         if (notifytype == dns_notifytype_explicit)
3094                 goto cleanup3;
3095
3096         /*
3097          * Process NS RRset to generate notifies.
3098          */
3099
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;
3105
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);
3112                 /*
3113                  * don't notify the master server.
3114                  */
3115                 if (dns_name_compare(&master, &ns.name) == 0) {
3116                         result = dns_rdataset_next(&nsrdset);
3117                         continue;
3118                 }
3119
3120                 if (!loggednotify) {
3121                         notify_log(zone, ISC_LOG_INFO,
3122                                    "sending notifies (serial %u)",
3123                                    serial);
3124                         loggednotify = ISC_TRUE;
3125                 }
3126
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;
3133                 }
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;
3144                 }
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);
3151         }
3152         dns_rdataset_disassociate(&nsrdset);
3153
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);
3162 }
3163
3164 /***
3165  *** Private
3166  ***/
3167
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)
3171 {
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;
3178
3179         /*
3180          * Extract NS RRset from message.
3181          */
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;
3187
3188         /*
3189          * Add NS rdataset.
3190          */
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;
3199         /*
3200          * Add glue rdatasets.
3201          */
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;
3226                 }
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;
3242                 }
3243         }
3244         if (result != ISC_R_NOMORE)
3245                 goto fail;
3246
3247         return (ISC_R_SUCCESS);
3248
3249 fail:
3250         return (result);
3251 }
3252
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;
3268
3269         stub = revent->ev_arg;
3270         INSIST(DNS_STUB_VALID(stub));
3271
3272         UNUSED(task);
3273
3274         zone = stub->zone;
3275
3276         ENTER;
3277
3278         TIME_NOW(&now);
3279
3280         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
3281                 zone_debuglog(zone, me, 1, "exiting");
3282                 exiting = ISC_TRUE;
3283                 goto next_master;
3284         }
3285
3286         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
3287         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
3288
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;
3300                 }
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;
3306         }
3307
3308         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3309         if (result != ISC_R_SUCCESS)
3310                 goto next_master;
3311
3312         result = dns_request_getresponse(revent->request, msg, 0);
3313         if (result != ISC_R_SUCCESS)
3314                 goto next_master;
3315
3316         /*
3317          * Unexpected rcode.
3318          */
3319         if (msg->rcode != dns_rcode_noerror) {
3320                 char rcode[128];
3321                 isc_buffer_t rb;
3322
3323                 isc_buffer_init(&rb, rcode, sizeof(rcode));
3324                 (void)dns_rcode_totext(msg->rcode, &rb);
3325
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;
3338                 }
3339
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;
3345         }
3346
3347         /*
3348          * We need complete messages.
3349          */
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;
3357                 }
3358                 LOCK_ZONE(zone);
3359                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
3360                 UNLOCK_ZONE(zone);
3361                 goto same_master;
3362         }
3363
3364         /*
3365          * If non-auth log and next master.
3366          */
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;
3372         }
3373
3374         /*
3375          * Sanity checks.
3376          */
3377         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
3378         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
3379
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;
3385         }
3386
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;
3392         }
3393
3394         /*
3395          * Save answer.
3396          */
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;
3403         }
3404
3405         /*
3406          * Tidy up.
3407          */
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);
3414
3415         if (zone->masterfile != NULL) {
3416                 dns_zone_dump(zone);
3417                 TIME_NOW(&zone->loadtime);
3418         }
3419
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;
3431
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);
3442         /*
3443          * Skip to next failed / untried master.
3444          */
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)) {
3455                         /*
3456                          * Did we get a good answer from all the masters?
3457                          */
3458                         for (j = 0; j < zone->masterscnt; j++)
3459                                 if (zone->mastersok[j] == ISC_FALSE) {
3460                                         done = ISC_FALSE;
3461                                         break;
3462                                 }
3463                 } else
3464                         done = ISC_TRUE;
3465                 if (!done) {
3466                         zone->curmaster = 0;
3467                         /*
3468                          * Find the next failed master.
3469                          */
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);
3476
3477                         zone_settimer(zone, &now);
3478                         UNLOCK_ZONE(zone);
3479                         goto free_stub;
3480                 }
3481         }
3482         queue_soa_query(zone);
3483         UNLOCK_ZONE(zone);
3484         goto free_stub;
3485
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;
3495
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));
3502
3503  done:
3504         INSIST(event == NULL);
3505         return;
3506 }
3507
3508 /*
3509  * An SOA query has finished (successfully or not).
3510  */
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;
3527
3528         zone = revent->ev_arg;
3529         INSIST(DNS_ZONE_VALID(zone));
3530
3531         UNUSED(task);
3532
3533         ENTER;
3534
3535         /*
3536          * if timeout log and next master;
3537          */
3538
3539         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
3540         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
3541
3542         TIME_NOW(&now);
3543
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;
3554                 }
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;
3568                         }
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;
3575         }
3576
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;
3587         }
3588
3589         /*
3590          * Unexpected rcode.
3591          */
3592         if (msg->rcode != dns_rcode_noerror) {
3593                 char rcode[128];
3594                 isc_buffer_t rb;
3595
3596                 isc_buffer_init(&rb, rcode, sizeof(rcode));
3597                 (void)dns_rcode_totext(msg->rcode, &rb);
3598
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;
3611                 }
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);
3616                 /*
3617                  * Perhaps AXFR/IXFR is allowed even if SOA queries arn't.
3618                  */
3619                 if (msg->rcode == dns_rcode_refused &&
3620                     zone->type == dns_zone_slave)
3621                         goto tcp_transfer;
3622                 goto next_master;
3623         }
3624
3625         /*
3626          * If truncated punt to zone transfer which will query again.
3627          */
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;
3647                         }
3648                         LOCK_ZONE(zone);
3649                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
3650                         UNLOCK_ZONE(zone);
3651                         goto same_master;
3652                 }
3653         }
3654
3655         /*
3656          * if non-auth log and next master;
3657          */
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;
3663         }
3664
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);
3670
3671         /*
3672          * There should not be a CNAME record at top of zone.
3673          */
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;
3679         }
3680
3681         /*
3682          * if referral log and next master;
3683          */
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;
3689         }
3690
3691         /*
3692          * if nodata log and next master;
3693          */
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;
3699         }
3700
3701         /*
3702          * Only one soa at top of zone.
3703          */
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;
3710         }
3711         /*
3712          * Extract serial
3713          */
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;
3723         }
3724
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;
3730         }
3731
3732         dns_rdataset_current(rdataset, &rdata);
3733         result = dns_rdata_tostruct(&rdata, &soa, NULL);
3734         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3735
3736         serial = soa.serial;
3737
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);
3753                 }
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));
3780                 }
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;
3794         }
3795         if (msg != NULL)
3796                 dns_message_destroy(&msg);
3797         goto detach;
3798
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);
3805         /*
3806          * Skip to next failed / untried master.
3807          */
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)) {
3817                         /*
3818                          * Did we get a good answer from all the masters?
3819                          */
3820                         for (j = 0; j < zone->masterscnt; j++)
3821                                 if (zone->mastersok[j] == ISC_FALSE) {
3822                                         done = ISC_FALSE;
3823                                         break;
3824                                 }
3825                 } else
3826                         done = ISC_TRUE;
3827                 if (!done) {
3828                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
3829                         zone->curmaster = 0;
3830                         /*
3831                          * Find the next failed master.
3832                          */
3833                         while (zone->curmaster < zone->masterscnt &&
3834                                zone->mastersok[zone->curmaster])
3835                                 zone->curmaster++;
3836                         goto requeue;
3837                 }
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;
3842                 }
3843                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
3844                 zone_settimer(zone, &now);
3845                 UNLOCK_ZONE(zone);
3846                 goto detach;
3847         }
3848
3849  requeue:
3850         queue_soa_query(zone);
3851         UNLOCK_ZONE(zone);
3852         goto detach;
3853
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);
3862
3863  detach:
3864         dns_zone_idetach(&zone);
3865         return;
3866 }
3867
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;
3874
3875         ENTER;
3876         /*
3877          * Locked by caller
3878          */
3879         REQUIRE(LOCKED_ZONE(zone));
3880
3881         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
3882                 cancel_refresh(zone);
3883                 return;
3884         }
3885
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;
3891         }
3892
3893         /*
3894          * Attach so that we won't clean up
3895          * until the event is delivered.
3896          */
3897         zone_iattach(zone, &dummy);
3898
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);
3906         }
3907 }
3908
3909 static inline isc_result_t
3910 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
3911              dns_message_t **messagep)
3912 {
3913         dns_message_t *message = NULL;
3914         dns_name_t *qname = NULL;
3915         dns_rdataset_t *qrdataset = NULL;
3916         isc_result_t result;
3917
3918         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
3919                                     &message);
3920         if (result != ISC_R_SUCCESS)
3921                 goto cleanup;
3922
3923         message->opcode = dns_opcode_query;
3924         message->rdclass = zone->rdclass;
3925
3926         result = dns_message_gettempname(message, &qname);
3927         if (result != ISC_R_SUCCESS)
3928                 goto cleanup;
3929
3930         result = dns_message_gettemprdataset(message, &qrdataset);
3931         if (result != ISC_R_SUCCESS)
3932                 goto cleanup;
3933
3934         /*
3935          * Make question.
3936          */
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);
3943
3944         *messagep = message;
3945         return (ISC_R_SUCCESS);
3946
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);
3955 }
3956
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;
3963
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);
3974         
3975         rdatalist->type = dns_rdatatype_opt;
3976         rdatalist->covers = 0;
3977
3978         /*
3979          * Set Maximum UDP buffer size.
3980          */
3981         rdatalist->rdclass = SEND_BUFFER_SIZE;
3982
3983         /*
3984          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
3985          */
3986         rdatalist->ttl = 0;
3987
3988         /*
3989          * No EDNS options.
3990          */
3991         rdata->data = NULL;
3992         rdata->length = 0;
3993         rdata->rdclass = rdatalist->rdclass;
3994         rdata->type = rdatalist->type;
3995         rdata->flags = 0;
3996
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);
4001
4002         return (dns_message_setopt(message, rdataset));
4003
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);
4011         
4012         return (result);
4013 }
4014
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;
4028
4029         REQUIRE(DNS_ZONE_VALID(zone));
4030
4031         UNUSED(task);
4032
4033         ENTER;
4034
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;
4042         }
4043
4044         /*
4045          * XXX Optimisation: Create message when zone is setup and reuse.
4046          */
4047         result = create_query(zone, dns_rdatatype_soa, &message);
4048         if (result != ISC_R_SUCCESS)
4049                 goto cleanup;
4050
4051  again:
4052         INSIST(zone->masterscnt > 0);
4053         INSIST(zone->curmaster < zone->masterscnt);
4054
4055         zone->masteraddr = zone->masters[zone->curmaster];
4056
4057         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
4058         /*
4059          * First, look for a tsig key in the master statement, then
4060          * try for a server key.
4061          */
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);
4072                 }
4073         }
4074         if (key == NULL)
4075                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
4076
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;
4091                 }
4092         }
4093
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;
4116         }
4117
4118         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
4119                   DNS_REQUESTOPT_TCP : 0;
4120
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));
4127         }
4128
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;
4144         }
4145         cancel = ISC_FALSE;
4146
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;
4160
4161  skip_master:
4162         if (key != NULL)
4163                 dns_tsigkey_detach(&key);
4164         /*
4165          * Skip to next failed / untried master.
4166          */
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;
4175 }
4176
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;
4187
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));
4192
4193         ENTER;
4194
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;
4205
4206                 /*
4207                  * Attach so that the zone won't disappear from under us.
4208                  */
4209                 zone_iattach(zone, &stub->zone);
4210
4211                 /*
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.
4215                  */
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;
4233                         }
4234                         dns_db_settask(stub->db, zone->task);
4235                 }
4236
4237                 dns_db_newversion(stub->db, &stub->version);
4238
4239                 /*
4240                  * Update SOA record.
4241                  */
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;
4250                 }
4251
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;
4261                 }
4262         }
4263
4264         /*
4265          * XXX Optimisation: Create message when zone is setup and reuse.
4266          */
4267         result = create_query(zone, dns_rdatatype_ns, &message);
4268
4269         INSIST(zone->masterscnt > 0);
4270         INSIST(zone->curmaster < zone->masterscnt);
4271         zone->masteraddr = zone->masters[zone->curmaster];
4272
4273         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
4274         /*
4275          * First, look for a tsig key in the master statement, then
4276          * try for a server key.
4277          */
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);
4288                 }
4289         }
4290         if (key == NULL)
4291                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);        
4292
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;
4306                 }
4307                 
4308         }
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));
4315         }
4316
4317         /*
4318          * Always use TCP so that we shouldn't truncate in additional section.
4319          */
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;
4336         }
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;
4350         }
4351         dns_message_destroy(&message);
4352         goto unlock;
4353
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));
4366         }
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;
4374 }
4375
4376 /*
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.
4379  */
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;
4384
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");
4390
4391         /*
4392          * Stop things being restarted after we cancel them below.
4393          */
4394         LOCK_ZONE(zone);
4395         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
4396         UNLOCK_ZONE(zone);
4397
4398         /*
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
4403          */
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;
4411                 }
4412                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
4413         }
4414
4415         /*
4416          * In task context, no locking required.  See zone_xfrdone().
4417          */
4418         if (zone->xfr != NULL)
4419                 dns_xfrin_shutdown(zone->xfr);
4420
4421         LOCK_ZONE(zone);
4422         if (linked) {
4423                 INSIST(zone->irefs > 0);
4424                 zone->irefs--;
4425         }
4426         if (zone->request != NULL) {
4427                 dns_request_cancel(zone->request);
4428         }
4429
4430         if (zone->readio != NULL)
4431                 zonemgr_cancelio(zone->readio);
4432
4433         if (zone->lctx != NULL)
4434                 dns_loadctx_cancel(zone->lctx);
4435
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);
4440
4441                 if (zone->dctx != NULL) 
4442                         dns_dumpctx_cancel(zone->dctx);
4443         }
4444
4445         notify_cancel(zone);
4446
4447         if (zone->timer != NULL) {
4448                 isc_timer_detach(&zone->timer);
4449                 INSIST(zone->irefs > 0);
4450                 zone->irefs--;
4451         }
4452
4453         if (zone->view != NULL)
4454                 dns_view_weakdetach(&zone->view);
4455
4456         /*
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().
4460          */
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);
4466 }
4467
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;
4472
4473         UNUSED(task);
4474         REQUIRE(DNS_ZONE_VALID(zone));
4475
4476         ENTER;
4477
4478         zone_maintenance(zone);
4479
4480         isc_event_free(&event);
4481 }
4482
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;
4488
4489         REQUIRE(DNS_ZONE_VALID(zone));
4490         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
4491                 return;
4492
4493         isc_time_settoepoch(&next);
4494
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;
4505                 }
4506                 break;
4507
4508         case dns_zone_slave:
4509                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
4510                         next = *now;
4511                 /*FALLTHROUGH*/
4512
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;
4522                 }
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;
4528                 }
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;
4535                 }
4536                 break;
4537
4538         default:
4539                 break;
4540         }
4541
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));
4559         }
4560 }
4561
4562 static void
4563 cancel_refresh(dns_zone_t *zone) {
4564         const char me[] = "cancel_refresh";
4565         isc_time_t now;
4566
4567         /*
4568          * 'zone' locked by caller.
4569          */
4570
4571         REQUIRE(DNS_ZONE_VALID(zone));
4572         REQUIRE(LOCKED_ZONE(zone));
4573
4574         ENTER;
4575
4576         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4577         TIME_NOW(&now);
4578         zone_settimer(zone, &now);
4579 }
4580
4581 static isc_result_t
4582 notify_createmessage(dns_zone_t *zone, unsigned int flags,
4583                      dns_message_t **messagep)
4584 {
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;
4590
4591         dns_name_t *tempname = NULL;
4592         dns_rdata_t *temprdata = NULL;
4593         dns_rdatalist_t *temprdatalist = NULL;
4594         dns_rdataset_t *temprdataset = NULL;
4595
4596         isc_result_t result;
4597         isc_region_t r;
4598         isc_buffer_t *b = NULL;
4599
4600         REQUIRE(DNS_ZONE_VALID(zone));
4601         REQUIRE(messagep != NULL && *messagep == NULL);
4602
4603         message = NULL;
4604         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
4605                                     &message);
4606         if (result != ISC_R_SUCCESS)
4607                 return (result);
4608
4609         message->opcode = dns_opcode_notify;
4610         message->flags |= DNS_MESSAGEFLAG_AA;
4611         message->rdclass = zone->rdclass;
4612
4613         result = dns_message_gettempname(message, &tempname);
4614         if (result != ISC_R_SUCCESS)
4615                 goto cleanup;
4616
4617         result = dns_message_gettemprdataset(message, &temprdataset);
4618         if (result != ISC_R_SUCCESS)
4619                 goto cleanup;
4620
4621         /*
4622          * Make question.
4623          */
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;
4633
4634         if ((flags & DNS_NOTIFY_NOSOA) != 0)
4635                 goto done;
4636
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;
4649
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;
4656
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);
4687
4688         dns_rdataset_init(temprdataset);
4689         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
4690         if (result != ISC_R_SUCCESS)
4691                 goto soa_cleanup;
4692
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;
4699
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);
4713
4714  done:
4715         *messagep = message;
4716         return (ISC_R_SUCCESS);
4717
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);
4726 }
4727
4728 isc_result_t
4729 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
4730                        dns_message_t *msg)
4731 {
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;
4740
4741         REQUIRE(DNS_ZONE_VALID(zone));
4742
4743         /*
4744          * If type != T_SOA return DNS_R_REFUSED.  We don't yet support
4745          * ROLLOVER.
4746          *
4747          * SOA: RFC 1996
4748          * Check that 'from' is a valid notify source, (zone->masters).
4749          *      Return DNS_R_REFUSED if not.
4750          *
4751          * If the notify message contains a serial number check it
4752          * against the zones serial and return if <= current serial
4753          *
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.
4758          *
4759          * Otherwise initiate a refresh check using 'from' as the
4760          * first address to check.  Return ISC_R_SUCCESS.
4761          */
4762
4763         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
4764
4765         /*
4766          *  We only handle NOTIFY (SOA) at the present.
4767          */
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);
4779                 }
4780                 dns_zone_log(zone, ISC_LOG_NOTICE,
4781                              "NOTIFY zone does not match");
4782                 return (DNS_R_NOTIMP);
4783         }
4784
4785         /*
4786          * If we are a master zone just succeed.
4787          */
4788         if (zone->type == dns_zone_master) {
4789                 UNLOCK_ZONE(zone);
4790                 return (ISC_R_SUCCESS);
4791         }
4792
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;
4805                 }
4806         }
4807
4808         /*
4809          * Accept notify requests from non masters if they are on
4810          * 'zone->notify_acl'.
4811          */
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)
4817         {
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);
4824         }
4825
4826         /*
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.
4831          */
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;
4844
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);
4856                         }
4857                 }
4858         }
4859
4860         /*
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
4864          */
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);
4874         }
4875         zone->notifyfrom = *from;
4876         UNLOCK_ZONE(zone);
4877         dns_zone_refresh(zone);
4878         return (ISC_R_SUCCESS);
4879 }
4880
4881 void
4882 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
4883
4884         REQUIRE(DNS_ZONE_VALID(zone));
4885
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);
4891 }
4892
4893 void
4894 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
4895
4896         REQUIRE(DNS_ZONE_VALID(zone));
4897
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);
4903 }
4904
4905 void
4906 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
4907
4908         REQUIRE(DNS_ZONE_VALID(zone));
4909
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);
4915 }
4916
4917 void
4918 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
4919
4920         REQUIRE(DNS_ZONE_VALID(zone));
4921
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);
4927 }
4928
4929 void
4930 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
4931
4932         REQUIRE(DNS_ZONE_VALID(zone));
4933
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);
4939 }
4940
4941 dns_acl_t *
4942 dns_zone_getnotifyacl(dns_zone_t *zone) {
4943
4944         REQUIRE(DNS_ZONE_VALID(zone));
4945
4946         return (zone->notify_acl);
4947 }
4948
4949 dns_acl_t *
4950 dns_zone_getqueryacl(dns_zone_t *zone) {
4951
4952         REQUIRE(DNS_ZONE_VALID(zone));
4953
4954         return (zone->query_acl);
4955 }
4956
4957 dns_acl_t *
4958 dns_zone_getupdateacl(dns_zone_t *zone) {
4959
4960         REQUIRE(DNS_ZONE_VALID(zone));
4961
4962         return (zone->update_acl);
4963 }
4964
4965 dns_acl_t *
4966 dns_zone_getforwardacl(dns_zone_t *zone) {
4967
4968         REQUIRE(DNS_ZONE_VALID(zone));
4969
4970         return (zone->forward_acl);
4971 }
4972
4973 dns_acl_t *
4974 dns_zone_getxfracl(dns_zone_t *zone) {
4975
4976         REQUIRE(DNS_ZONE_VALID(zone));
4977
4978         return (zone->xfr_acl);
4979 }
4980
4981 void
4982 dns_zone_clearupdateacl(dns_zone_t *zone) {
4983
4984         REQUIRE(DNS_ZONE_VALID(zone));
4985
4986         LOCK_ZONE(zone);
4987         if (zone->update_acl != NULL)
4988                 dns_acl_detach(&zone->update_acl);
4989         UNLOCK_ZONE(zone);
4990 }
4991
4992 void
4993 dns_zone_clearforwardacl(dns_zone_t *zone) {
4994
4995         REQUIRE(DNS_ZONE_VALID(zone));
4996
4997         LOCK_ZONE(zone);
4998         if (zone->forward_acl != NULL)
4999                 dns_acl_detach(&zone->forward_acl);
5000         UNLOCK_ZONE(zone);
5001 }
5002
5003 void
5004 dns_zone_clearnotifyacl(dns_zone_t *zone) {
5005
5006         REQUIRE(DNS_ZONE_VALID(zone));
5007
5008         LOCK_ZONE(zone);
5009         if (zone->notify_acl != NULL)
5010                 dns_acl_detach(&zone->notify_acl);
5011         UNLOCK_ZONE(zone);
5012 }
5013
5014 void
5015 dns_zone_clearqueryacl(dns_zone_t *zone) {
5016
5017         REQUIRE(DNS_ZONE_VALID(zone));
5018
5019         LOCK_ZONE(zone);
5020         if (zone->query_acl != NULL)
5021                 dns_acl_detach(&zone->query_acl);
5022         UNLOCK_ZONE(zone);
5023 }
5024
5025 void
5026 dns_zone_clearxfracl(dns_zone_t *zone) {
5027
5028         REQUIRE(DNS_ZONE_VALID(zone));
5029
5030         LOCK_ZONE(zone);
5031         if (zone->xfr_acl != NULL)
5032                 dns_acl_detach(&zone->xfr_acl);
5033         UNLOCK_ZONE(zone);
5034 }
5035
5036 isc_boolean_t
5037 dns_zone_getupdatedisabled(dns_zone_t *zone) {
5038         REQUIRE(DNS_ZONE_VALID(zone));
5039         return (zone->update_disabled);
5040
5041 }
5042
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;
5047 }
5048
5049 void
5050 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
5051
5052         REQUIRE(DNS_ZONE_VALID(zone));
5053
5054         zone->check_names = severity;
5055 }
5056
5057 dns_severity_t
5058 dns_zone_getchecknames(dns_zone_t *zone) {
5059
5060         REQUIRE(DNS_ZONE_VALID(zone));
5061
5062         return (zone->check_names);
5063 }
5064
5065 void
5066 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
5067
5068         REQUIRE(DNS_ZONE_VALID(zone));
5069
5070         zone->journalsize = size;
5071 }
5072
5073 isc_int32_t
5074 dns_zone_getjournalsize(dns_zone_t *zone) {
5075
5076         REQUIRE(DNS_ZONE_VALID(zone));
5077
5078         return (zone->journalsize);
5079 }
5080
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;
5085
5086         REQUIRE(buf != NULL);
5087         REQUIRE(length > 1U);
5088
5089         /*
5090          * Leave space for terminating '\0'.
5091          */
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>");
5098
5099         if (isc_buffer_availablelength(&buffer) > 0)
5100                 isc_buffer_putstr(&buffer, "/");
5101         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
5102
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);
5108         }
5109
5110         buf[isc_buffer_usedlength(&buffer)] = '\0';
5111 }
5112
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);
5118 }
5119
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];
5125
5126         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
5127                 return;
5128
5129         zone_tostr(zone, namebuf, sizeof(namebuf));
5130
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);
5136 }
5137
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];
5144
5145         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
5146                 return;
5147
5148         zone_tostr(zone, namebuf, sizeof(namebuf));
5149
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);
5155 }
5156
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];
5162
5163         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
5164                 return;
5165
5166         zone_tostr(zone, namebuf, sizeof(namebuf));
5167
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);
5173 }
5174
5175 static void
5176 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
5177               const char *fmt, ...)
5178 {
5179         va_list ap;
5180         char message[4096];
5181         char namebuf[1024+32];
5182         int level = ISC_LOG_DEBUG(debuglevel);
5183
5184         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
5185                 return;
5186
5187         zone_tostr(zone, namebuf, sizeof(namebuf));
5188
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);
5194 }
5195
5196 static int
5197 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
5198 {
5199         isc_result_t result;
5200         dns_name_t *name;
5201         dns_rdataset_t *curr;
5202         int count = 0;
5203
5204         result = dns_message_firstname(msg, section);
5205         while (result == ISC_R_SUCCESS) {
5206                 name = NULL;
5207                 dns_message_currentname(msg, section, &name);
5208
5209                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
5210                      curr = ISC_LIST_PREV(curr, link)) {
5211                         if (curr->type == type)
5212                                 count++;
5213                 }
5214                 result = dns_message_nextname(msg, section);
5215         }
5216
5217         return (count);
5218 }
5219
5220 void
5221 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
5222         REQUIRE(DNS_ZONE_VALID(zone));
5223
5224         zone->maxxfrin = maxxfrin;
5225 }
5226
5227 isc_uint32_t
5228 dns_zone_getmaxxfrin(dns_zone_t *zone) {
5229         REQUIRE(DNS_ZONE_VALID(zone));
5230
5231         return (zone->maxxfrin);
5232 }
5233
5234 void
5235 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
5236         REQUIRE(DNS_ZONE_VALID(zone));
5237         zone->maxxfrout = maxxfrout;
5238 }
5239
5240 isc_uint32_t
5241 dns_zone_getmaxxfrout(dns_zone_t *zone) {
5242         REQUIRE(DNS_ZONE_VALID(zone));
5243
5244         return (zone->maxxfrout);
5245 }
5246
5247 dns_zonetype_t dns_zone_gettype(dns_zone_t *zone) {
5248         REQUIRE(DNS_ZONE_VALID(zone));
5249
5250         return (zone->type);
5251 }
5252
5253 dns_name_t *
5254 dns_zone_getorigin(dns_zone_t *zone) {
5255         REQUIRE(DNS_ZONE_VALID(zone));
5256
5257         return (&zone->origin);
5258 }
5259
5260 void
5261 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
5262         REQUIRE(DNS_ZONE_VALID(zone));
5263
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);
5271 }
5272
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);
5277 }
5278
5279 void
5280 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
5281         REQUIRE(DNS_ZONE_VALID(zone));
5282
5283         if (idlein == 0)
5284                 idlein = DNS_DEFAULT_IDLEIN;
5285         zone->idlein = idlein;
5286 }
5287
5288 isc_uint32_t
5289 dns_zone_getidlein(dns_zone_t *zone) {
5290         REQUIRE(DNS_ZONE_VALID(zone));
5291
5292         return (zone->idlein);
5293 }
5294
5295 void
5296 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
5297         REQUIRE(DNS_ZONE_VALID(zone));
5298
5299         zone->idleout = idleout;
5300 }
5301
5302 isc_uint32_t
5303 dns_zone_getidleout(dns_zone_t *zone) {
5304         REQUIRE(DNS_ZONE_VALID(zone));
5305
5306         return (zone->idleout);
5307 }
5308
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];
5318
5319         UNUSED(task);
5320
5321         notify = event->ev_arg;
5322         REQUIRE(DNS_NOTIFY_VALID(notify));
5323         INSIST(task == notify->zone->task);
5324
5325         isc_buffer_init(&buf, rcode, sizeof(rcode));
5326         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
5327
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));
5345
5346         /*
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.
5349          */
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);
5363         }
5364         if (message != NULL)
5365                 dns_message_destroy(&message);
5366 }
5367
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;
5371
5372         REQUIRE(DNS_ZONE_VALID(zone));
5373         LOCK_ZONE(zone);
5374         result = zone_replacedb(zone, db, dump);
5375         UNLOCK_ZONE(zone);
5376         return (result);
5377 }
5378
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;
5385
5386         /*
5387          * 'zone' locked by caller.
5388          */
5389         REQUIRE(DNS_ZONE_VALID(zone));
5390         REQUIRE(LOCKED_ZONE(zone));
5391
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;
5399                 }
5400                 if (nscount == 0) {
5401                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
5402                         result = DNS_R_BADZONE;
5403                 }
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);
5411         }
5412
5413         ver = NULL;
5414         dns_db_currentversion(db, &ver);
5415
5416         /*
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.
5420          */
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;
5425
5426                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
5427
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;
5434                 }
5435
5436                 /*
5437                  * This is checked in zone_postload() for master zones.
5438                  */
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;
5450                 }
5451
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;
5474                         }
5475                 }
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;
5484
5485                         /*
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.
5491                          */
5492                         TIME_NOW(&zone->loadtime);
5493                 }
5494
5495                 if (dump && zone->journal != NULL) {
5496                         /*
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.
5506                          */
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);
5511                 }
5512         }
5513
5514         dns_db_closeversion(db, &ver, ISC_FALSE);
5515
5516         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5517                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
5518                       "replacing zone database");
5519
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);
5526
5527  fail:
5528         dns_db_closeversion(db, &ver, ISC_FALSE);
5529         return (result);
5530 }
5531
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;
5541
5542         REQUIRE(DNS_ZONE_VALID(zone));
5543
5544         dns_zone_log(zone, ISC_LOG_DEBUG(1),
5545                      "zone transfer finished: %s", dns_result_totext(result));
5546
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);
5551
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);
5559                 /*
5560                  * Has the zone expired underneath us?
5561                  */
5562                 if (zone->db == NULL)
5563                         goto same_master;
5564
5565                 /*
5566                  * Update the zone structure's data from the actual
5567                  * SOA received.
5568                  */
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;
5589                                 }
5590                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5591                                 zone_unload(zone);
5592                                 goto next_master;
5593                         }
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);
5604                 }
5605
5606                 /*
5607                  * Set our next update/expire times.
5608                  */
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);
5619                 }
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);
5633                 }
5634
5635                 /*
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.
5639                  */
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));
5658                 }
5659
5660                 break;
5661
5662         case DNS_R_BADIXFR:
5663                 /* Force retry with AXFR. */
5664                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
5665                 goto same_master;
5666
5667         default:
5668         next_master:
5669                 /*
5670                  * Skip to next failed / untried master.
5671                  */
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;
5693                 }
5694                 break;
5695         }
5696         zone_settimer(zone, &now);
5697
5698         /*
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.
5704          */
5705         if (zone->xfr != NULL)
5706                 dns_xfrin_detach(&zone->xfr);
5707
5708         if (zone->tsigkey != NULL)
5709                 dns_tsigkey_detach(&zone->tsigkey);
5710
5711         /*
5712          * This transfer finishing freed up a transfer quota slot.
5713          * Let any other zones waiting for quota have it.
5714          */
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);
5720
5721         /*
5722          * Retry with a different server if necessary.
5723          */
5724         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
5725                 queue_soa_query(zone);
5726
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);
5733 }
5734
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;
5741
5742         REQUIRE(DNS_LOAD_VALID(load));
5743         zone = load->zone;
5744
5745         ENTER;
5746
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;
5751
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);
5757
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));
5764 }
5765
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);
5771
5772         LOCK_ZONE(zone);
5773         if (zone->ssutable != NULL)
5774                 dns_ssutable_attach(zone->ssutable, table);
5775         UNLOCK_ZONE(zone);
5776 }
5777
5778 void
5779 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
5780         REQUIRE(DNS_ZONE_VALID(zone));
5781
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);
5788 }
5789
5790 void
5791 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
5792         REQUIRE(DNS_ZONE_VALID(zone));
5793
5794         zone->sigvalidityinterval = interval;
5795 }
5796
5797 isc_uint32_t
5798 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
5799         REQUIRE(DNS_ZONE_VALID(zone));
5800
5801         return (zone->sigvalidityinterval);
5802 }
5803
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;
5809
5810         ENTER;
5811
5812         INSIST(zone->statelist == NULL);
5813
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);
5822
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));
5830         }
5831 }
5832
5833 /*
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.
5837  */
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;
5848
5849         UNUSED(task);
5850
5851         INSIST(task == zone->task);
5852
5853         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
5854                 result = ISC_R_CANCELED;
5855                 goto cleanup;
5856         }
5857
5858         isc_sockaddr_format(&zone->masteraddr, mastertext, sizeof(mastertext));
5859
5860         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
5861         (void)dns_peerlist_peerbyaddr(zone->view->peers,
5862                                       &masterip, &peer);
5863
5864         /*
5865          * Decide whether we should request IXFR or AXFR.
5866          */
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;
5898                 }
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;
5913                 }
5914         }
5915
5916         /*
5917          * Determine if we should attempt to sign the request with TSIG.
5918          */
5919         result = ISC_R_NOTFOUND;
5920         /*
5921          * First, look for a tsig key in the master statement, then
5922          * try for a server key.
5923          */
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);
5929         }
5930         if (zone->tsigkey == NULL)
5931                 result = dns_view_getpeertsig(zone->view, &masterip,
5932                                               &zone->tsigkey);
5933
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));
5939         }
5940
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:
5951         /*
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.
5955          */
5956         if (result != ISC_R_SUCCESS)
5957                 zone_xfrdone(zone, result);
5958
5959         isc_event_free(&event);
5960 }
5961
5962 /*
5963  * Update forwarding support.
5964  */
5965
5966 static void
5967 forward_destroy(dns_forward_t *forward) {
5968
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));
5977 }
5978
5979 static isc_result_t
5980 sendtomaster(dns_forward_t *forward) {
5981         isc_result_t result;
5982         isc_sockaddr_t src;
5983
5984         LOCK_ZONE(forward->zone);
5985         if (forward->which >= forward->zone->masterscnt) {
5986                 UNLOCK_ZONE(forward->zone);
5987                 return (ISC_R_NOMORE);
5988         }
5989
5990         forward->addr = forward->zone->masters[forward->which];
5991         /*
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.
5996          */
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;
6007         }
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);
6018 }
6019
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;
6029
6030         UNUSED(task);
6031
6032         forward = revent->ev_arg;
6033         INSIST(DNS_FORWARD_VALID(forward));
6034         zone = forward->zone;
6035         INSIST(DNS_ZONE_VALID(zone));
6036
6037         ENTER;
6038
6039         isc_sockaddr_format(&forward->addr, master, sizeof(master));
6040
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;
6046         }
6047
6048         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
6049         if (result != ISC_R_SUCCESS)
6050                 goto next_master;
6051
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;
6057
6058         switch (msg->rcode) {
6059         /*
6060          * Pass these rcodes back to client.
6061          */
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;
6069
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;
6075
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;
6083         }
6084
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;
6092         }
6093
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;
6101
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);
6115         }
6116 }
6117
6118 isc_result_t
6119 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
6120                        dns_updatecallback_t callback, void *callback_arg)
6121 {
6122         dns_forward_t *forward;
6123         isc_result_t result;
6124         isc_region_t *mr;
6125
6126         REQUIRE(DNS_ZONE_VALID(zone));
6127         REQUIRE(msg != NULL);
6128         REQUIRE(callback != NULL);
6129
6130         forward = isc_mem_get(zone->mctx, sizeof(*forward));
6131         if (forward == NULL)
6132                 return (ISC_R_NOMEMORY);
6133
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;
6142
6143         mr = dns_message_getrawmessage(msg);
6144         if (mr == NULL) {
6145                 result = ISC_R_UNEXPECTEDEND;
6146                 goto cleanup;
6147         }
6148
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;
6155
6156         isc_mem_attach(zone->mctx, &forward->mctx);
6157         dns_zone_iattach(zone, &forward->zone);
6158         result = sendtomaster(forward);
6159
6160  cleanup:
6161         if (result != ISC_R_SUCCESS) {
6162                 forward_destroy(forward);
6163         }
6164         return (result);
6165 }
6166
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);
6171
6172         *next = ISC_LIST_NEXT(zone, link);
6173         if (*next == NULL)
6174                 return (ISC_R_NOMORE);
6175         else
6176                 return (ISC_R_SUCCESS);
6177 }
6178
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);
6183
6184         *first = ISC_LIST_HEAD(zmgr->zones);
6185         if (*first == NULL)
6186                 return (ISC_R_NOMORE);
6187         else
6188                 return (ISC_R_SUCCESS);
6189 }
6190
6191 /***
6192  ***    Zone manager.
6193  ***/
6194
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)
6199 {
6200         dns_zonemgr_t *zmgr;
6201         isc_result_t result;
6202         isc_interval_t interval;
6203
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;
6226         }
6227         zmgr->transfersin = 10;
6228         zmgr->transfersperns = 2;
6229
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;
6235
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);
6250
6251         zmgr->iolimit = 1;
6252         zmgr->ioactive = 0;
6253         ISC_LIST_INIT(zmgr->high);
6254         ISC_LIST_INIT(zmgr->low);
6255
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;
6262         }
6263         zmgr->magic = ZONEMGR_MAGIC;
6264
6265         *zmgrp = zmgr;
6266         return (ISC_R_SUCCESS);
6267
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);
6284 }
6285
6286 isc_result_t
6287 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
6288         isc_result_t result;
6289
6290         REQUIRE(DNS_ZONE_VALID(zone));
6291         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6292
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);
6298
6299         isc_taskpool_gettask(zmgr->zonetasks,
6300                              dns_name_hash(dns_zone_getorigin(zone),
6301                                            ISC_FALSE),
6302                              &zone->task);
6303
6304         /*
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).
6308          */
6309         isc_task_setname(zone->task, "zone", zone);
6310
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;
6317         /*
6318          * The timer "holds" a iref.
6319          */
6320         zone->irefs++;
6321         INSIST(zone->irefs != 0);
6322
6323         ISC_LIST_APPEND(zmgr->zones, zone, link);
6324         zone->zmgr = zmgr;
6325         zmgr->refs++;
6326
6327         goto unlock;
6328
6329  cleanup_task:
6330         isc_task_detach(&zone->task);
6331
6332  unlock:
6333         UNLOCK_ZONE(zone);
6334         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6335         return (result);
6336 }
6337
6338 void
6339 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
6340         isc_boolean_t free_now = ISC_FALSE;
6341
6342         REQUIRE(DNS_ZONE_VALID(zone));
6343         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6344         REQUIRE(zone->zmgr == zmgr);
6345
6346         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6347         LOCK_ZONE(zone);
6348
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;
6354
6355         UNLOCK_ZONE(zone);
6356         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6357
6358         if (free_now)
6359                 zonemgr_free(zmgr);
6360         ENSURE(zone->zmgr == NULL);
6361 }
6362
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);
6367
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;
6374 }
6375
6376 void
6377 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
6378         dns_zonemgr_t *zmgr;
6379         isc_boolean_t free_now = ISC_FALSE;
6380
6381         REQUIRE(zmgrp != NULL);
6382         zmgr = *zmgrp;
6383         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6384
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);
6390
6391         if (free_now)
6392                 zonemgr_free(zmgr);
6393 }
6394
6395 isc_result_t
6396 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
6397         dns_zone_t *p;
6398
6399         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6400
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))
6405         {
6406                 dns_zone_maintenance(p);
6407         }
6408         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
6409
6410         /*
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.
6415          */
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);
6420 }
6421
6422 void
6423 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
6424
6425         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6426
6427         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6428         zmgr_resume_xfrs(zmgr, ISC_TRUE);
6429         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6430 }
6431
6432 void
6433 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
6434         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6435
6436         isc_ratelimiter_shutdown(zmgr->rl);
6437
6438         if (zmgr->task != NULL)
6439                 isc_task_destroy(&zmgr->task);
6440         if (zmgr->zonetasks != NULL)
6441                 isc_taskpool_destroy(&zmgr->zonetasks);
6442 }
6443
6444 static void
6445 zonemgr_free(dns_zonemgr_t *zmgr) {
6446         isc_mem_t *mctx;
6447
6448         INSIST(zmgr->refs == 0);
6449         INSIST(ISC_LIST_EMPTY(zmgr->zones));
6450
6451         zmgr->magic = 0;
6452
6453         DESTROYLOCK(&zmgr->iolock);
6454         isc_ratelimiter_detach(&zmgr->rl);
6455
6456         isc_rwlock_destroy(&zmgr->rwlock);
6457         mctx = zmgr->mctx;
6458         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
6459         isc_mem_detach(&mctx);
6460 }
6461
6462 void
6463 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
6464         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6465
6466         zmgr->transfersin = value;
6467 }
6468
6469 isc_uint32_t
6470 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
6471         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6472
6473         return (zmgr->transfersin);
6474 }
6475
6476 void
6477 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
6478         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6479
6480         zmgr->transfersperns = value;
6481 }
6482
6483 isc_uint32_t
6484 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
6485         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6486
6487         return (zmgr->transfersperns);
6488 }
6489
6490 /*
6491  * Try to start a new incoming zone transfer to fill a quota
6492  * slot that was just vacated.
6493  *
6494  * Requires:
6495  *      The zone manager is locked by the caller.
6496  */
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;
6501
6502         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
6503              zone != NULL;
6504              zone = next)
6505         {
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;
6512                         /*
6513                          * We successfully filled the slot.  We're done.
6514                          */
6515                         break;
6516                 } else if (result == ISC_R_QUOTA) {
6517                         /*
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.
6522                          */
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;
6529                 }
6530         }
6531 }
6532
6533 /*
6534  * Try to start an incoming zone transfer for 'zone', quota permitting.
6535  *
6536  * Requires:
6537  *      The zone manager is locked by the caller.
6538  *
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.
6545  */
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;
6554
6555         /*
6556          * Find any configured information about the server we'd
6557          * like to transfer this zone from.
6558          */
6559         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
6560         (void)dns_peerlist_peerbyaddr(zone->view->peers,
6561                                       &masterip, &peer);
6562
6563         /*
6564          * Determine the total maximum number of simultaneous
6565          * transfers allowed, and the maximum for this specific
6566          * master.
6567          */
6568         maxtransfersin = zmgr->transfersin;
6569         maxtransfersperns = zmgr->transfersperns;
6570         if (peer != NULL)
6571                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
6572
6573         /*
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.
6578          */
6579         nxfrsin = nxfrsperns = 0;
6580         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
6581              x != NULL;
6582              x = ISC_LIST_NEXT(x, statelink))
6583         {
6584                 isc_netaddr_t xip;
6585                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
6586                 nxfrsin++;
6587                 if (isc_netaddr_equal(&xip, &masterip))
6588                         nxfrsperns++;
6589         }
6590
6591         /* Enforce quota. */
6592         if (nxfrsin >= maxtransfersin)
6593                 return (ISC_R_QUOTA);
6594
6595         if (nxfrsperns >= maxtransfersperns)
6596                 return (ISC_R_QUOTA);
6597
6598         /*
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.
6602          */
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);
6609
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);
6618
6619         return (ISC_R_SUCCESS);
6620 }
6621
6622 void
6623 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
6624
6625         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6626         REQUIRE(iolimit > 0);
6627
6628         zmgr->iolimit = iolimit;
6629 }
6630
6631 isc_uint32_t
6632 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
6633
6634         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6635
6636         return (zmgr->iolimit);
6637 }
6638
6639 /*
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.
6644  *
6645  * zonemgr_putio() must be called after the event is delivered to
6646  * 'action'.
6647  */
6648
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)
6653 {
6654         dns_io_t *io;
6655         isc_boolean_t queue;
6656
6657         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6658         REQUIRE(iop != NULL && *iop == NULL);
6659
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);
6668         }
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;
6675
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);
6684         }
6685         UNLOCK(&zmgr->iolock);
6686         *iop = io;
6687
6688         if (!queue) {
6689                 isc_task_send(io->task, &io->event);
6690         }
6691         return (ISC_R_SUCCESS);
6692 }
6693
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;
6699
6700         REQUIRE(iop != NULL);
6701         io = *iop;
6702         REQUIRE(DNS_IO_VALID(io));
6703
6704         *iop = NULL;
6705
6706         INSIST(!ISC_LINK_LINKED(io, link));
6707         INSIST(io->event == NULL);
6708
6709         zmgr = io->zmgr;
6710         isc_task_detach(&io->task);
6711         io->magic = 0;
6712         isc_mem_put(zmgr->mctx, io, sizeof(*io));
6713
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);
6726         }
6727         UNLOCK(&zmgr->iolock);
6728         if (next != NULL)
6729                 isc_task_send(next->task, &next->event);
6730 }
6731
6732 static void
6733 zonemgr_cancelio(dns_io_t *io) {
6734         isc_boolean_t send_event = ISC_FALSE;
6735
6736         REQUIRE(DNS_IO_VALID(io));
6737
6738         /*
6739          * If we are queued to be run then dequeue.
6740          */
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);
6747
6748                 send_event = ISC_TRUE;
6749                 INSIST(io->event != NULL);
6750         }
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);
6755         }
6756 }
6757
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;
6763
6764         buflen = strlen(path) + strlen(templat) + 2;
6765
6766         buf = isc_mem_get(zone->mctx, buflen);
6767         if (buf == NULL)
6768                 return;
6769
6770         result = isc_file_template(path, templat, buf, buflen);
6771         if (result != ISC_R_SUCCESS)
6772                 goto cleanup;
6773
6774         result = isc_file_renameunique(path, buf);
6775         if (result != ISC_R_SUCCESS)
6776                 goto cleanup;
6777
6778         dns_zone_log(zone, ISC_LOG_INFO, "saved '%s' as '%s'",
6779                      path, buf);
6780
6781  cleanup:
6782         isc_mem_put(zone->mctx, buf, buflen);
6783 }
6784
6785 #if 0
6786 /* Hook for ondestroy notifcation from a database. */
6787
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);
6792
6793         isc_event_free(&event);
6794
6795         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
6796                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
6797                       "database (%p) destroyed", (void*) db);
6798 }
6799 #endif
6800
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;
6807
6808         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6809
6810         if (value == 0)
6811                 value = 1;
6812
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;
6825         }
6826
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);
6831
6832         zmgr->serialqueryrate = value;
6833 }
6834
6835 unsigned int
6836 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
6837         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6838
6839         return (zmgr->serialqueryrate);
6840 }
6841
6842 void
6843 dns_zone_forcereload(dns_zone_t *zone) {
6844         REQUIRE(DNS_ZONE_VALID(zone));
6845
6846         if (zone->type == dns_zone_master)
6847                 return;
6848
6849         LOCK_ZONE(zone);
6850         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
6851         UNLOCK_ZONE(zone);
6852         dns_zone_refresh(zone);
6853 }
6854
6855 isc_boolean_t
6856 dns_zone_isforced(dns_zone_t *zone) {
6857         REQUIRE(DNS_ZONE_VALID(zone));
6858
6859         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
6860 }
6861
6862 isc_result_t
6863 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
6864         isc_result_t result = ISC_R_SUCCESS;
6865
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);
6875         }
6876  done:
6877         UNLOCK_ZONE(zone);
6878         return (result);
6879 }
6880
6881 isc_uint64_t *
6882 dns_zone_getstatscounters(dns_zone_t *zone) {
6883         return (zone->counters);
6884 }
6885
6886 void
6887 dns_zone_dialup(dns_zone_t *zone) {
6888
6889         REQUIRE(DNS_ZONE_VALID(zone));
6890
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));
6895
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);
6901 }
6902
6903 void
6904 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
6905         REQUIRE(DNS_ZONE_VALID(zone));
6906
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);
6935         }
6936         UNLOCK_ZONE(zone);
6937 }
6938
6939 isc_result_t
6940 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
6941         isc_result_t result = ISC_R_SUCCESS;
6942
6943         REQUIRE(DNS_ZONE_VALID(zone));
6944
6945         LOCK_ZONE(zone);
6946         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
6947         UNLOCK_ZONE(zone);
6948
6949         return (result);
6950 }
6951
6952 const char *
6953 dns_zone_getkeydirectory(dns_zone_t *zone) {
6954         REQUIRE(DNS_ZONE_VALID(zone));
6955
6956         return (zone->keydirectory);
6957 }
6958 unsigned int
6959 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
6960         dns_zone_t *zone;
6961         unsigned int count = 0;
6962
6963         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6964
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++;
6994                 }
6995                 break;
6996         default:
6997                 INSIST(0);
6998         }
6999
7000         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
7001
7002         return (count);
7003 }
7004
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;
7014
7015         REQUIRE(DNS_ZONE_VALID(zone));
7016
7017         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
7018                 return (ISC_R_SUCCESS);
7019
7020         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
7021                 level = ISC_LOG_ERROR;
7022                 fail = ISC_TRUE;
7023         }
7024
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);
7033         }
7034
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);
7045         }
7046
7047         return (ISC_R_SUCCESS);
7048 }