]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/bind9/lib/dns/zone.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / bind9 / lib / dns / zone.c
1 /*
2  * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
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.410.18.55 2008/10/24 01:43:17 tbox Exp $ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <isc/file.h>
25 #include <isc/mutex.h>
26 #include <isc/print.h>
27 #include <isc/random.h>
28 #include <isc/ratelimiter.h>
29 #include <isc/refcount.h>
30 #include <isc/rwlock.h>
31 #include <isc/serial.h>
32 #include <isc/string.h>
33 #include <isc/taskpool.h>
34 #include <isc/timer.h>
35 #include <isc/util.h>
36
37 #include <dns/acache.h>
38 #include <dns/acl.h>
39 #include <dns/adb.h>
40 #include <dns/callbacks.h>
41 #include <dns/db.h>
42 #include <dns/dbiterator.h>
43 #include <dns/events.h>
44 #include <dns/journal.h>
45 #include <dns/log.h>
46 #include <dns/master.h>
47 #include <dns/masterdump.h>
48 #include <dns/message.h>
49 #include <dns/name.h>
50 #include <dns/peer.h>
51 #include <dns/rcode.h>
52 #include <dns/rdataclass.h>
53 #include <dns/rdatalist.h>
54 #include <dns/rdataset.h>
55 #include <dns/rdatastruct.h>
56 #include <dns/rdatatype.h>
57 #include <dns/request.h>
58 #include <dns/resolver.h>
59 #include <dns/result.h>
60 #include <dns/stats.h>
61 #include <dns/ssu.h>
62 #include <dns/tsig.h>
63 #include <dns/xfrin.h>
64 #include <dns/zone.h>
65
66 #define ZONE_MAGIC                      ISC_MAGIC('Z', 'O', 'N', 'E')
67 #define DNS_ZONE_VALID(zone)            ISC_MAGIC_VALID(zone, ZONE_MAGIC)
68
69 #define NOTIFY_MAGIC                    ISC_MAGIC('N', 't', 'f', 'y')
70 #define DNS_NOTIFY_VALID(notify)        ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
71
72 #define STUB_MAGIC                      ISC_MAGIC('S', 't', 'u', 'b')
73 #define DNS_STUB_VALID(stub)            ISC_MAGIC_VALID(stub, STUB_MAGIC)
74
75 #define ZONEMGR_MAGIC                   ISC_MAGIC('Z', 'm', 'g', 'r')
76 #define DNS_ZONEMGR_VALID(stub)         ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
77
78 #define LOAD_MAGIC                      ISC_MAGIC('L', 'o', 'a', 'd')
79 #define DNS_LOAD_VALID(load)            ISC_MAGIC_VALID(load, LOAD_MAGIC)
80
81 #define FORWARD_MAGIC                   ISC_MAGIC('F', 'o', 'r', 'w')
82 #define DNS_FORWARD_VALID(load)         ISC_MAGIC_VALID(load, FORWARD_MAGIC)
83
84 #define IO_MAGIC                        ISC_MAGIC('Z', 'm', 'I', 'O')
85 #define DNS_IO_VALID(load)              ISC_MAGIC_VALID(load, IO_MAGIC)
86
87 /*%
88  * Ensure 'a' is at least 'min' but not more than 'max'.
89  */
90 #define RANGE(a, min, max) \
91                 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
92
93 /*
94  * Default values.
95  */
96 #define DNS_DEFAULT_IDLEIN 3600         /*%< 1 hour */
97 #define DNS_DEFAULT_IDLEOUT 3600        /*%< 1 hour */
98 #define MAX_XFER_TIME (2*3600)          /*%< Documented default is 2 hours */
99
100 #ifndef DNS_MAX_EXPIRE
101 #define DNS_MAX_EXPIRE  14515200        /*%< 24 weeks */
102 #endif
103
104 #ifndef DNS_DUMP_DELAY
105 #define DNS_DUMP_DELAY 900              /*%< 15 minutes */
106 #endif
107
108 typedef struct dns_notify dns_notify_t;
109 typedef struct dns_stub dns_stub_t;
110 typedef struct dns_load dns_load_t;
111 typedef struct dns_forward dns_forward_t;
112 typedef struct dns_io dns_io_t;
113 typedef ISC_LIST(dns_io_t) dns_iolist_t;
114
115 #define DNS_ZONE_CHECKLOCK
116 #ifdef DNS_ZONE_CHECKLOCK
117 #define LOCK_ZONE(z) \
118          do { LOCK(&(z)->lock); \
119               INSIST((z)->locked == ISC_FALSE); \
120              (z)->locked = ISC_TRUE; \
121                 } while (0)
122 #define UNLOCK_ZONE(z) \
123         do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
124 #define LOCKED_ZONE(z) ((z)->locked)
125 #else
126 #define LOCK_ZONE(z) LOCK(&(z)->lock)
127 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
128 #define LOCKED_ZONE(z) ISC_TRUE
129 #endif
130
131 #ifdef ISC_RWLOCK_USEATOMIC
132 #define ZONEDB_INITLOCK(l)      isc_rwlock_init((l), 0, 0)
133 #define ZONEDB_DESTROYLOCK(l)   isc_rwlock_destroy(l)
134 #define ZONEDB_LOCK(l, t)       RWLOCK((l), (t))
135 #define ZONEDB_UNLOCK(l, t)     RWUNLOCK((l), (t))
136 #else
137 #define ZONEDB_INITLOCK(l)      isc_mutex_init(l)
138 #define ZONEDB_DESTROYLOCK(l)   DESTROYLOCK(l)
139 #define ZONEDB_LOCK(l, t)       LOCK(l)
140 #define ZONEDB_UNLOCK(l, t)     UNLOCK(l)
141 #endif
142
143 struct dns_zone {
144         /* Unlocked */
145         unsigned int            magic;
146         isc_mutex_t             lock;
147 #ifdef DNS_ZONE_CHECKLOCK
148         isc_boolean_t           locked;
149 #endif
150         isc_mem_t               *mctx;
151         isc_refcount_t          erefs;
152
153 #ifdef ISC_RWLOCK_USEATOMIC
154         isc_rwlock_t            dblock;
155 #else
156         isc_mutex_t             dblock;
157 #endif
158         dns_db_t                *db;            /* Locked by dblock */
159
160         /* Locked */
161         dns_zonemgr_t           *zmgr;
162         ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
163         isc_timer_t             *timer;
164         unsigned int            irefs;
165         dns_name_t              origin;
166         char                    *masterfile;
167         dns_masterformat_t      masterformat;
168         char                    *journal;
169         isc_int32_t             journalsize;
170         dns_rdataclass_t        rdclass;
171         dns_zonetype_t          type;
172         unsigned int            flags;
173         unsigned int            options;
174         unsigned int            db_argc;
175         char                    **db_argv;
176         isc_time_t              expiretime;
177         isc_time_t              refreshtime;
178         isc_time_t              dumptime;
179         isc_time_t              loadtime;
180         isc_time_t              notifytime;
181         isc_uint32_t            serial;
182         isc_uint32_t            refresh;
183         isc_uint32_t            retry;
184         isc_uint32_t            expire;
185         isc_uint32_t            minimum;
186         char                    *keydirectory;
187
188         isc_uint32_t            maxrefresh;
189         isc_uint32_t            minrefresh;
190         isc_uint32_t            maxretry;
191         isc_uint32_t            minretry;
192
193         isc_sockaddr_t          *masters;
194         dns_name_t              **masterkeynames;
195         isc_boolean_t           *mastersok;
196         unsigned int            masterscnt;
197         unsigned int            curmaster;
198         isc_sockaddr_t          masteraddr;
199         dns_notifytype_t        notifytype;
200         isc_sockaddr_t          *notify;
201         unsigned int            notifycnt;
202         isc_sockaddr_t          notifyfrom;
203         isc_task_t              *task;
204         isc_sockaddr_t          notifysrc4;
205         isc_sockaddr_t          notifysrc6;
206         isc_sockaddr_t          xfrsource4;
207         isc_sockaddr_t          xfrsource6;
208         isc_sockaddr_t          altxfrsource4;
209         isc_sockaddr_t          altxfrsource6;
210         isc_sockaddr_t          sourceaddr;
211         dns_xfrin_ctx_t         *xfr;           /* task locked */
212         dns_tsigkey_t           *tsigkey;       /* key used for xfr */
213         /* Access Control Lists */
214         dns_acl_t               *update_acl;
215         dns_acl_t               *forward_acl;
216         dns_acl_t               *notify_acl;
217         dns_acl_t               *query_acl;
218         dns_acl_t               *xfr_acl;
219         isc_boolean_t           update_disabled;
220         isc_boolean_t           zero_no_soa_ttl;
221         dns_severity_t          check_names;
222         ISC_LIST(dns_notify_t)  notifies;
223         dns_request_t           *request;
224         dns_loadctx_t           *lctx;
225         dns_io_t                *readio;
226         dns_dumpctx_t           *dctx;
227         dns_io_t                *writeio;
228         isc_uint32_t            maxxfrin;
229         isc_uint32_t            maxxfrout;
230         isc_uint32_t            idlein;
231         isc_uint32_t            idleout;
232         isc_event_t             ctlevent;
233         dns_ssutable_t          *ssutable;
234         isc_uint32_t            sigvalidityinterval;
235         dns_view_t              *view;
236         dns_acache_t            *acache;
237         dns_checkmxfunc_t       checkmx;
238         dns_checksrvfunc_t      checksrv;
239         dns_checknsfunc_t       checkns;
240         /*%
241          * Zones in certain states such as "waiting for zone transfer"
242          * or "zone transfer in progress" are kept on per-state linked lists
243          * in the zone manager using the 'statelink' field.  The 'statelist'
244          * field points at the list the zone is currently on.  It the zone
245          * is not on any such list, statelist is NULL.
246          */
247         ISC_LINK(dns_zone_t)    statelink;
248         dns_zonelist_t          *statelist;
249         /*%
250          * Optional per-zone statistics counters (NULL if not present).
251          */
252         isc_uint64_t            *counters;
253         isc_uint32_t            notifydelay;
254         dns_isselffunc_t        isself;
255         void                    *isselfarg;
256
257         /*%
258          * Serial number for deferred journal compaction.
259          */
260         isc_uint32_t            compact_serial;
261 };
262
263 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
264 #define DNS_ZONE_SETFLAG(z,f) do { \
265                 INSIST(LOCKED_ZONE(z)); \
266                 (z)->flags |= (f); \
267                 } while (0)
268 #define DNS_ZONE_CLRFLAG(z,f) do { \
269                 INSIST(LOCKED_ZONE(z)); \
270                 (z)->flags &= ~(f); \
271                 } while (0)
272         /* XXX MPA these may need to go back into zone.h */
273 #define DNS_ZONEFLG_REFRESH     0x00000001U     /*%< refresh check in progress */
274 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /*%< zone need consolidation */
275 #define DNS_ZONEFLG_USEVC       0x00000004U     /*%< use tcp for refresh query */
276 #define DNS_ZONEFLG_DUMPING     0x00000008U     /*%< a dump is in progress */
277 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /*%< $INCLUDE in zone file */
278 #define DNS_ZONEFLG_LOADED      0x00000020U     /*%< database has loaded */
279 #define DNS_ZONEFLG_EXITING     0x00000040U     /*%< zone is being destroyed */
280 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /*%< zone has expired */
281 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /*%< refresh check needed */
282 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /*%< zone contents are
283                                                  * uptodate */
284 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /*%< need to send out notify
285                                                  * messages */
286 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /*%< generate a journal diff on
287                                                  * reload */
288 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /*%< an attempt to refresh a
289                                                  * zone with no masters
290                                                  * occured */
291 #define DNS_ZONEFLG_LOADING     0x00002000U     /*%< load from disk in progress*/
292 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /*%< timer values have been set
293                                                  * from SOA (if not set, we
294                                                  * are still using
295                                                  * default timer values) */
296 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
297 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
298 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
299 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
300 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
301 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /*%< IXFR failed, force AXFR */
302 #define DNS_ZONEFLG_FLUSH       0x00200000U
303 #define DNS_ZONEFLG_NOEDNS      0x00400000U
304 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
305 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
306 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
307
308 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
309
310 /* Flags for zone_load() */
311 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
312
313 struct dns_zonemgr {
314         unsigned int            magic;
315         isc_mem_t *             mctx;
316         int                     refs;           /* Locked by rwlock */
317         isc_taskmgr_t *         taskmgr;
318         isc_timermgr_t *        timermgr;
319         isc_socketmgr_t *       socketmgr;
320         isc_taskpool_t *        zonetasks;
321         isc_task_t *            task;
322         isc_ratelimiter_t *     rl;
323         isc_rwlock_t            rwlock;
324         isc_mutex_t             iolock;
325
326         /* Locked by rwlock. */
327         dns_zonelist_t          zones;
328         dns_zonelist_t          waiting_for_xfrin;
329         dns_zonelist_t          xfrin_in_progress;
330
331         /* Configuration data. */
332         isc_uint32_t            transfersin;
333         isc_uint32_t            transfersperns;
334         unsigned int            serialqueryrate;
335
336         /* Locked by iolock */
337         isc_uint32_t            iolimit;
338         isc_uint32_t            ioactive;
339         dns_iolist_t            high;
340         dns_iolist_t            low;
341 };
342
343 /*%
344  * Hold notify state.
345  */
346 struct dns_notify {
347         unsigned int            magic;
348         unsigned int            flags;
349         isc_mem_t               *mctx;
350         dns_zone_t              *zone;
351         dns_adbfind_t           *find;
352         dns_request_t           *request;
353         dns_name_t              ns;
354         isc_sockaddr_t          dst;
355         ISC_LINK(dns_notify_t)  link;
356 };
357
358 #define DNS_NOTIFY_NOSOA        0x0001U
359
360 /*%
361  *      dns_stub holds state while performing a 'stub' transfer.
362  *      'db' is the zone's 'db' or a new one if this is the initial
363  *      transfer.
364  */
365
366 struct dns_stub {
367         unsigned int            magic;
368         isc_mem_t               *mctx;
369         dns_zone_t              *zone;
370         dns_db_t                *db;
371         dns_dbversion_t         *version;
372 };
373
374 /*%
375  *      Hold load state.
376  */
377 struct dns_load {
378         unsigned int            magic;
379         isc_mem_t               *mctx;
380         dns_zone_t              *zone;
381         dns_db_t                *db;
382         isc_time_t              loadtime;
383         dns_rdatacallbacks_t    callbacks;
384 };
385
386 /*%
387  *      Hold forward state.
388  */
389 struct dns_forward {
390         unsigned int            magic;
391         isc_mem_t               *mctx;
392         dns_zone_t              *zone;
393         isc_buffer_t            *msgbuf;
394         dns_request_t           *request;
395         isc_uint32_t            which;
396         isc_sockaddr_t          addr;
397         dns_updatecallback_t    callback;
398         void                    *callback_arg;
399 };
400
401 /*%
402  *      Hold IO request state.
403  */
404 struct dns_io {
405         unsigned int    magic;
406         dns_zonemgr_t   *zmgr;
407         isc_boolean_t   high;
408         isc_task_t      *task;
409         ISC_LINK(dns_io_t) link;
410         isc_event_t     *event;
411 };
412
413 #define SEND_BUFFER_SIZE 2048
414
415 static void zone_settimer(dns_zone_t *, isc_time_t *);
416 static void cancel_refresh(dns_zone_t *);
417 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
418                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
419 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
420      ISC_FORMAT_PRINTF(3, 4);
421 static void queue_xfrin(dns_zone_t *zone);
422 static void zone_unload(dns_zone_t *zone);
423 static void zone_expire(dns_zone_t *zone);
424 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
425 static void zone_idetach(dns_zone_t **zonep);
426 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
427                                    isc_boolean_t dump);
428 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
429 static inline void zone_detachdb(dns_zone_t *zone);
430 static isc_result_t default_journal(dns_zone_t *zone);
431 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
432 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
433                                   isc_time_t loadtime, isc_result_t result);
434 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
435 static void zone_shutdown(isc_task_t *, isc_event_t *);
436 static void zone_loaddone(void *arg, isc_result_t result);
437 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
438                                    isc_time_t loadtime);
439
440 #if 0
441 /* ondestroy example */
442 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
443 #endif
444
445 static void refresh_callback(isc_task_t *, isc_event_t *);
446 static void stub_callback(isc_task_t *, isc_event_t *);
447 static void queue_soa_query(dns_zone_t *zone);
448 static void soa_query(isc_task_t *, isc_event_t *);
449 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
450                      dns_stub_t *stub);
451 static int message_count(dns_message_t *msg, dns_section_t section,
452                          dns_rdatatype_t type);
453 static void notify_cancel(dns_zone_t *zone);
454 static void notify_find_address(dns_notify_t *notify);
455 static void notify_send(dns_notify_t *notify);
456 static isc_result_t notify_createmessage(dns_zone_t *zone,
457                                          unsigned int flags,
458                                          dns_message_t **messagep);
459 static void notify_done(isc_task_t *task, isc_event_t *event);
460 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
461 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
462 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
463 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
464                                              dns_zone_t *zone);
465 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
466 static void zonemgr_free(dns_zonemgr_t *zmgr);
467 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
468                                   isc_task_t *task, isc_taskaction_t action,
469                                   void *arg, dns_io_t **iop);
470 static void zonemgr_putio(dns_io_t **iop);
471 static void zonemgr_cancelio(dns_io_t *io);
472
473 static isc_result_t
474 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
475                  unsigned int *soacount, isc_uint32_t *serial,
476                  isc_uint32_t *refresh, isc_uint32_t *retry,
477                  isc_uint32_t *expire, isc_uint32_t *minimum,
478                  unsigned int *errors);
479
480 static void zone_freedbargs(dns_zone_t *zone);
481 static void forward_callback(isc_task_t *task, isc_event_t *event);
482 static void zone_saveunique(dns_zone_t *zone, const char *path,
483                             const char *templat);
484 static void zone_maintenance(dns_zone_t *zone);
485 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
486 static void dump_done(void *arg, isc_result_t result);
487
488 #define ENTER zone_debuglog(zone, me, 1, "enter")
489
490 static const unsigned int dbargc_default = 1;
491 static const char *dbargv_default[] = { "rbt" };
492
493 #define DNS_ZONE_JITTER_ADD(a, b, c) \
494         do { \
495                 isc_interval_t _i; \
496                 isc_uint32_t _j; \
497                 _j = isc_random_jitter((b), (b)/4); \
498                 isc_interval_set(&_i, _j, 0); \
499                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
500                         dns_zone_log(zone, ISC_LOG_WARNING, \
501                                      "epoch approaching: upgrade required: " \
502                                      "now + %s failed", #b); \
503                         isc_interval_set(&_i, _j/2, 0); \
504                         (void)isc_time_add((a), &_i, (c)); \
505                 } \
506         } while (0)
507
508 #define DNS_ZONE_TIME_ADD(a, b, c) \
509         do { \
510                 isc_interval_t _i; \
511                 isc_interval_set(&_i, (b), 0); \
512                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
513                         dns_zone_log(zone, ISC_LOG_WARNING, \
514                                      "epoch approaching: upgrade required: " \
515                                      "now + %s failed", #b); \
516                         isc_interval_set(&_i, (b)/2, 0); \
517                         (void)isc_time_add((a), &_i, (c)); \
518                 } \
519         } while (0)
520
521 /***
522  ***    Public functions.
523  ***/
524
525 isc_result_t
526 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
527         isc_result_t result;
528         dns_zone_t *zone;
529         isc_time_t now;
530
531         REQUIRE(zonep != NULL && *zonep == NULL);
532         REQUIRE(mctx != NULL);
533
534         TIME_NOW(&now);
535         zone = isc_mem_get(mctx, sizeof(*zone));
536         if (zone == NULL)
537                 return (ISC_R_NOMEMORY);
538
539         zone->mctx = NULL;
540         isc_mem_attach(mctx, &zone->mctx);
541
542         result = isc_mutex_init(&zone->lock);
543         if (result != ISC_R_SUCCESS)
544                 goto free_zone;
545
546         result = ZONEDB_INITLOCK(&zone->dblock);
547         if (result != ISC_R_SUCCESS)
548                 goto free_mutex;
549
550         /* XXX MPA check that all elements are initialised */
551 #ifdef DNS_ZONE_CHECKLOCK
552         zone->locked = ISC_FALSE;
553 #endif
554         zone->db = NULL;
555         zone->zmgr = NULL;
556         ISC_LINK_INIT(zone, link);
557         result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
558         if (result != ISC_R_SUCCESS)
559                 goto free_dblock;
560         zone->irefs = 0;
561         dns_name_init(&zone->origin, NULL);
562         zone->masterfile = NULL;
563         zone->masterformat =  dns_masterformat_none;
564         zone->keydirectory = NULL;
565         zone->journalsize = -1;
566         zone->journal = NULL;
567         zone->rdclass = dns_rdataclass_none;
568         zone->type = dns_zone_none;
569         zone->flags = 0;
570         zone->options = 0;
571         zone->db_argc = 0;
572         zone->db_argv = NULL;
573         isc_time_settoepoch(&zone->expiretime);
574         isc_time_settoepoch(&zone->refreshtime);
575         isc_time_settoepoch(&zone->dumptime);
576         isc_time_settoepoch(&zone->loadtime);
577         zone->notifytime = now;
578         zone->serial = 0;
579         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
580         zone->retry = DNS_ZONE_DEFAULTRETRY;
581         zone->expire = 0;
582         zone->minimum = 0;
583         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
584         zone->minrefresh = DNS_ZONE_MINREFRESH;
585         zone->maxretry = DNS_ZONE_MAXRETRY;
586         zone->minretry = DNS_ZONE_MINRETRY;
587         zone->masters = NULL;
588         zone->masterkeynames = NULL;
589         zone->mastersok = NULL;
590         zone->masterscnt = 0;
591         zone->curmaster = 0;
592         zone->notify = NULL;
593         zone->notifytype = dns_notifytype_yes;
594         zone->notifycnt = 0;
595         zone->task = NULL;
596         zone->update_acl = NULL;
597         zone->forward_acl = NULL;
598         zone->notify_acl = NULL;
599         zone->query_acl = NULL;
600         zone->xfr_acl = NULL;
601         zone->update_disabled = ISC_FALSE;
602         zone->zero_no_soa_ttl = ISC_TRUE;
603         zone->check_names = dns_severity_ignore;
604         zone->request = NULL;
605         zone->lctx = NULL;
606         zone->readio = NULL;
607         zone->dctx = NULL;
608         zone->writeio = NULL;
609         zone->timer = NULL;
610         zone->idlein = DNS_DEFAULT_IDLEIN;
611         zone->idleout = DNS_DEFAULT_IDLEOUT;
612         ISC_LIST_INIT(zone->notifies);
613         isc_sockaddr_any(&zone->notifysrc4);
614         isc_sockaddr_any6(&zone->notifysrc6);
615         isc_sockaddr_any(&zone->xfrsource4);
616         isc_sockaddr_any6(&zone->xfrsource6);
617         isc_sockaddr_any(&zone->altxfrsource4);
618         isc_sockaddr_any6(&zone->altxfrsource6);
619         zone->xfr = NULL;
620         zone->tsigkey = NULL;
621         zone->maxxfrin = MAX_XFER_TIME;
622         zone->maxxfrout = MAX_XFER_TIME;
623         zone->ssutable = NULL;
624         zone->sigvalidityinterval = 30 * 24 * 3600;
625         zone->view = NULL;
626         zone->acache = NULL;
627         zone->checkmx = NULL;
628         zone->checksrv = NULL;
629         zone->checkns = NULL;
630         ISC_LINK_INIT(zone, statelink);
631         zone->statelist = NULL;
632         zone->counters = NULL;
633         zone->notifydelay = 5;
634         zone->isself = NULL;
635         zone->isselfarg = NULL;
636
637         zone->magic = ZONE_MAGIC;
638
639         /* Must be after magic is set. */
640         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
641         if (result != ISC_R_SUCCESS)
642                 goto free_erefs;
643
644         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
645                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
646                        NULL, NULL);
647         *zonep = zone;
648         return (ISC_R_SUCCESS);
649
650  free_erefs:
651         isc_refcount_decrement(&zone->erefs, NULL);
652         isc_refcount_destroy(&zone->erefs);
653
654  free_dblock:
655         ZONEDB_DESTROYLOCK(&zone->dblock);
656
657  free_mutex:
658         DESTROYLOCK(&zone->lock);
659
660  free_zone:
661         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
662         return (result);
663 }
664
665 /*
666  * Free a zone.  Because we require that there be no more
667  * outstanding events or references, no locking is necessary.
668  */
669 static void
670 zone_free(dns_zone_t *zone) {
671         isc_mem_t *mctx = NULL;
672
673         REQUIRE(DNS_ZONE_VALID(zone));
674         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
675         REQUIRE(zone->irefs == 0);
676         REQUIRE(!LOCKED_ZONE(zone));
677         REQUIRE(zone->timer == NULL);
678
679         /*
680          * Managed objects.  Order is important.
681          */
682         if (zone->request != NULL)
683                 dns_request_destroy(&zone->request); /* XXXMPA */
684         INSIST(zone->readio == NULL);
685         INSIST(zone->statelist == NULL);
686         INSIST(zone->writeio == NULL);
687
688         if (zone->task != NULL)
689                 isc_task_detach(&zone->task);
690         if (zone->zmgr)
691                 dns_zonemgr_releasezone(zone->zmgr, zone);
692
693         /* Unmanaged objects */
694         if (zone->masterfile != NULL)
695                 isc_mem_free(zone->mctx, zone->masterfile);
696         zone->masterfile = NULL;
697         if (zone->keydirectory != NULL)
698                 isc_mem_free(zone->mctx, zone->keydirectory);
699         zone->keydirectory = NULL;
700         zone->journalsize = -1;
701         if (zone->journal != NULL)
702                 isc_mem_free(zone->mctx, zone->journal);
703         zone->journal = NULL;
704         if (zone->counters != NULL)
705                 dns_stats_freecounters(zone->mctx, &zone->counters);
706         if (zone->db != NULL)
707                 zone_detachdb(zone);
708         if (zone->acache != NULL)
709                 dns_acache_detach(&zone->acache);
710         zone_freedbargs(zone);
711         RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
712                       == ISC_R_SUCCESS);
713         RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
714                       == ISC_R_SUCCESS);
715         zone->check_names = dns_severity_ignore;
716         if (zone->update_acl != NULL)
717                 dns_acl_detach(&zone->update_acl);
718         if (zone->forward_acl != NULL)
719                 dns_acl_detach(&zone->forward_acl);
720         if (zone->notify_acl != NULL)
721                 dns_acl_detach(&zone->notify_acl);
722         if (zone->query_acl != NULL)
723                 dns_acl_detach(&zone->query_acl);
724         if (zone->xfr_acl != NULL)
725                 dns_acl_detach(&zone->xfr_acl);
726         if (dns_name_dynamic(&zone->origin))
727                 dns_name_free(&zone->origin, zone->mctx);
728         if (zone->ssutable != NULL)
729                 dns_ssutable_detach(&zone->ssutable);
730
731         /* last stuff */
732         ZONEDB_DESTROYLOCK(&zone->dblock);
733         DESTROYLOCK(&zone->lock);
734         isc_refcount_destroy(&zone->erefs);
735         zone->magic = 0;
736         mctx = zone->mctx;
737         isc_mem_put(mctx, zone, sizeof(*zone));
738         isc_mem_detach(&mctx);
739 }
740
741 /*
742  *      Single shot.
743  */
744 void
745 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
746
747         REQUIRE(DNS_ZONE_VALID(zone));
748         REQUIRE(rdclass != dns_rdataclass_none);
749
750         /*
751          * Test and set.
752          */
753         LOCK_ZONE(zone);
754         REQUIRE(zone->rdclass == dns_rdataclass_none ||
755                 zone->rdclass == rdclass);
756         zone->rdclass = rdclass;
757         UNLOCK_ZONE(zone);
758 }
759
760 dns_rdataclass_t
761 dns_zone_getclass(dns_zone_t *zone){
762         REQUIRE(DNS_ZONE_VALID(zone));
763
764         return (zone->rdclass);
765 }
766
767 void
768 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
769         REQUIRE(DNS_ZONE_VALID(zone));
770
771         LOCK_ZONE(zone);
772         zone->notifytype = notifytype;
773         UNLOCK_ZONE(zone);
774 }
775
776 /*
777  *      Single shot.
778  */
779 void
780 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
781
782         REQUIRE(DNS_ZONE_VALID(zone));
783         REQUIRE(type != dns_zone_none);
784
785         /*
786          * Test and set.
787          */
788         LOCK_ZONE(zone);
789         REQUIRE(zone->type == dns_zone_none || zone->type == type);
790         zone->type = type;
791         UNLOCK_ZONE(zone);
792 }
793
794 static void
795 zone_freedbargs(dns_zone_t *zone) {
796         unsigned int i;
797
798         /* Free the old database argument list. */
799         if (zone->db_argv != NULL) {
800                 for (i = 0; i < zone->db_argc; i++)
801                         isc_mem_free(zone->mctx, zone->db_argv[i]);
802                 isc_mem_put(zone->mctx, zone->db_argv,
803                             zone->db_argc * sizeof(*zone->db_argv));
804         }
805         zone->db_argc = 0;
806         zone->db_argv = NULL;
807 }
808
809 isc_result_t
810 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
811         size_t size = 0;
812         unsigned int i;
813         isc_result_t result = ISC_R_SUCCESS;
814         void *mem;
815         char **tmp, *tmp2;
816
817         REQUIRE(DNS_ZONE_VALID(zone));
818         REQUIRE(argv != NULL && *argv == NULL);
819
820         LOCK_ZONE(zone);
821         size = (zone->db_argc + 1) * sizeof(char *);
822         for (i = 0; i < zone->db_argc; i++)
823                 size += strlen(zone->db_argv[i]) + 1;
824         mem = isc_mem_allocate(mctx, size);
825         if (mem != NULL) {
826                 tmp = mem;
827                 tmp2 = mem;
828                 tmp2 += (zone->db_argc + 1) * sizeof(char *);
829                 for (i = 0; i < zone->db_argc; i++) {
830                         *tmp++ = tmp2;
831                         strcpy(tmp2, zone->db_argv[i]);
832                         tmp2 += strlen(tmp2) + 1;
833                 }
834                 *tmp = NULL;
835         } else
836                 result = ISC_R_NOMEMORY;
837         UNLOCK_ZONE(zone);
838         *argv = mem;
839         return (result);
840 }
841
842 isc_result_t
843 dns_zone_setdbtype(dns_zone_t *zone,
844                    unsigned int dbargc, const char * const *dbargv) {
845         isc_result_t result = ISC_R_SUCCESS;
846         char **new = NULL;
847         unsigned int i;
848
849         REQUIRE(DNS_ZONE_VALID(zone));
850         REQUIRE(dbargc >= 1);
851         REQUIRE(dbargv != NULL);
852
853         LOCK_ZONE(zone);
854
855         /* Set up a new database argument list. */
856         new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
857         if (new == NULL)
858                 goto nomem;
859         for (i = 0; i < dbargc; i++)
860                 new[i] = NULL;
861         for (i = 0; i < dbargc; i++) {
862                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
863                 if (new[i] == NULL)
864                         goto nomem;
865         }
866
867         /* Free the old list. */
868         zone_freedbargs(zone);
869
870         zone->db_argc = dbargc;
871         zone->db_argv = new;
872         result = ISC_R_SUCCESS;
873         goto unlock;
874
875  nomem:
876         if (new != NULL) {
877                 for (i = 0; i < dbargc; i++)
878                         if (new[i] != NULL)
879                                 isc_mem_free(zone->mctx, new[i]);
880                 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
881         }
882         result = ISC_R_NOMEMORY;
883
884  unlock:
885         UNLOCK_ZONE(zone);
886         return (result);
887 }
888
889 void
890 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
891         REQUIRE(DNS_ZONE_VALID(zone));
892
893         LOCK_ZONE(zone);
894         if (zone->view != NULL)
895                 dns_view_weakdetach(&zone->view);
896         dns_view_weakattach(view, &zone->view);
897         UNLOCK_ZONE(zone);
898 }
899
900
901 dns_view_t *
902 dns_zone_getview(dns_zone_t *zone) {
903         REQUIRE(DNS_ZONE_VALID(zone));
904
905         return (zone->view);
906 }
907
908
909 isc_result_t
910 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
911         isc_result_t result;
912
913         REQUIRE(DNS_ZONE_VALID(zone));
914         REQUIRE(origin != NULL);
915
916         LOCK_ZONE(zone);
917         if (dns_name_dynamic(&zone->origin)) {
918                 dns_name_free(&zone->origin, zone->mctx);
919                 dns_name_init(&zone->origin, NULL);
920         }
921         result = dns_name_dup(origin, zone->mctx, &zone->origin);
922         UNLOCK_ZONE(zone);
923         return (result);
924 }
925
926 void
927 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
928         REQUIRE(DNS_ZONE_VALID(zone));
929         REQUIRE(acache != NULL);
930
931         LOCK_ZONE(zone);
932         if (zone->acache != NULL)
933                 dns_acache_detach(&zone->acache);
934         dns_acache_attach(acache, &zone->acache);
935         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
936         if (zone->db != NULL) {
937                 isc_result_t result;
938
939                 /*
940                  * If the zone reuses an existing DB, the DB needs to be
941                  * set in the acache explicitly.  We can safely ignore the
942                  * case where the DB is already set.  If other error happens,
943                  * the acache will not work effectively.
944                  */
945                 result = dns_acache_setdb(acache, zone->db);
946                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
947                         UNEXPECTED_ERROR(__FILE__, __LINE__,
948                                          "dns_acache_setdb() failed: %s",
949                                          isc_result_totext(result));
950                 }
951         }
952         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
953         UNLOCK_ZONE(zone);
954 }
955
956 static isc_result_t
957 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
958         char *copy;
959
960         if (value != NULL) {
961                 copy = isc_mem_strdup(zone->mctx, value);
962                 if (copy == NULL)
963                         return (ISC_R_NOMEMORY);
964         } else {
965                 copy = NULL;
966         }
967
968         if (*field != NULL)
969                 isc_mem_free(zone->mctx, *field);
970
971         *field = copy;
972         return (ISC_R_SUCCESS);
973 }
974
975 isc_result_t
976 dns_zone_setfile(dns_zone_t *zone, const char *file) {
977         return (dns_zone_setfile2(zone, file, dns_masterformat_text));
978 }
979
980 isc_result_t
981 dns_zone_setfile2(dns_zone_t *zone, const char *file,
982                   dns_masterformat_t format) {
983         isc_result_t result = ISC_R_SUCCESS;
984
985         REQUIRE(DNS_ZONE_VALID(zone));
986
987         LOCK_ZONE(zone);
988         result = dns_zone_setstring(zone, &zone->masterfile, file);
989         if (result == ISC_R_SUCCESS) {
990                 zone->masterformat = format;
991                 result = default_journal(zone);
992         }
993         UNLOCK_ZONE(zone);
994
995         return (result);
996 }
997
998 const char *
999 dns_zone_getfile(dns_zone_t *zone) {
1000         REQUIRE(DNS_ZONE_VALID(zone));
1001
1002         return (zone->masterfile);
1003 }
1004
1005 static isc_result_t
1006 default_journal(dns_zone_t *zone) {
1007         isc_result_t result;
1008         char *journal;
1009
1010         REQUIRE(DNS_ZONE_VALID(zone));
1011         REQUIRE(LOCKED_ZONE(zone));
1012
1013         if (zone->masterfile != NULL) {
1014                 /* Calculate string length including '\0'. */
1015                 int len = strlen(zone->masterfile) + sizeof(".jnl");
1016                 journal = isc_mem_allocate(zone->mctx, len);
1017                 if (journal == NULL)
1018                         return (ISC_R_NOMEMORY);
1019                 strcpy(journal, zone->masterfile);
1020                 strcat(journal, ".jnl");
1021         } else {
1022                 journal = NULL;
1023         }
1024         result = dns_zone_setstring(zone, &zone->journal, journal);
1025         if (journal != NULL)
1026                 isc_mem_free(zone->mctx, journal);
1027         return (result);
1028 }
1029
1030 isc_result_t
1031 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1032         isc_result_t result = ISC_R_SUCCESS;
1033
1034         REQUIRE(DNS_ZONE_VALID(zone));
1035
1036         LOCK_ZONE(zone);
1037         result = dns_zone_setstring(zone, &zone->journal, journal);
1038         UNLOCK_ZONE(zone);
1039
1040         return (result);
1041 }
1042
1043 char *
1044 dns_zone_getjournal(dns_zone_t *zone) {
1045         REQUIRE(DNS_ZONE_VALID(zone));
1046
1047         return (zone->journal);
1048 }
1049
1050 /*
1051  * Return true iff the zone is "dynamic", in the sense that the zone's
1052  * master file (if any) is written by the server, rather than being
1053  * updated manually and read by the server.
1054  *
1055  * This is true for slave zones, stub zones, and zones that allow
1056  * dynamic updates either by having an update policy ("ssutable")
1057  * or an "allow-update" ACL with a value other than exactly "{ none; }".
1058  */
1059 static isc_boolean_t
1060 zone_isdynamic(dns_zone_t *zone) {
1061         REQUIRE(DNS_ZONE_VALID(zone));
1062
1063         return (ISC_TF(zone->type == dns_zone_slave ||
1064                        zone->type == dns_zone_stub ||
1065                        (!zone->update_disabled && zone->ssutable != NULL) ||
1066                        (!zone->update_disabled && zone->update_acl != NULL &&
1067                         ! (zone->update_acl->length == 1 &&
1068                            zone->update_acl->elements[0].negative == ISC_TRUE
1069                            &&
1070                            zone->update_acl->elements[0].type ==
1071                            dns_aclelementtype_any))));
1072 }
1073
1074
1075 static isc_result_t
1076 zone_load(dns_zone_t *zone, unsigned int flags) {
1077         isc_result_t result;
1078         isc_time_t now;
1079         isc_time_t loadtime, filetime;
1080         dns_db_t *db = NULL;
1081
1082         REQUIRE(DNS_ZONE_VALID(zone));
1083
1084         LOCK_ZONE(zone);
1085         TIME_NOW(&now);
1086
1087         INSIST(zone->type != dns_zone_none);
1088
1089         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1090                 result = ISC_R_SUCCESS;
1091                 goto cleanup;
1092         }
1093
1094         if (zone->db != NULL && zone->masterfile == NULL) {
1095                 /*
1096                  * The zone has no master file configured, but it already
1097                  * has a database.  It could be the built-in
1098                  * version.bind. CH zone, a zone with a persistent
1099                  * database being reloaded, or maybe a zone that
1100                  * used to have a master file but whose configuration
1101                  * was changed so that it no longer has one.  Do nothing.
1102                  */
1103                 result = ISC_R_SUCCESS;
1104                 goto cleanup;
1105         }
1106
1107         if (zone->db != NULL && zone_isdynamic(zone)) {
1108                 /*
1109                  * This is a slave, stub, or dynamically updated
1110                  * zone being reloaded.  Do nothing - the database
1111                  * we already have is guaranteed to be up-to-date.
1112                  */
1113                 if (zone->type == dns_zone_master)
1114                         result = DNS_R_DYNAMIC;
1115                 else
1116                         result = ISC_R_SUCCESS;
1117                 goto cleanup;
1118         }
1119
1120
1121         /*
1122          * Store the current time before the zone is loaded, so that if the
1123          * file changes between the time of the load and the time that
1124          * zone->loadtime is set, then the file will still be reloaded
1125          * the next time dns_zone_load is called.
1126          */
1127         TIME_NOW(&loadtime);
1128
1129         /*
1130          * Don't do the load if the file that stores the zone is older
1131          * than the last time the zone was loaded.  If the zone has not
1132          * been loaded yet, zone->loadtime will be the epoch.
1133          */
1134         if (zone->masterfile != NULL) {
1135                 /*
1136                  * The file is already loaded.  If we are just doing a
1137                  * "rndc reconfig", we are done.
1138                  */
1139                 if (!isc_time_isepoch(&zone->loadtime) &&
1140                     (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1141                         result = ISC_R_SUCCESS;
1142                         goto cleanup;
1143                 }
1144
1145                 result = isc_file_getmodtime(zone->masterfile, &filetime);
1146                 if (result == ISC_R_SUCCESS) {
1147                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1148                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1149                             isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1150                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1151                                              "skipping load: master file "
1152                                              "older than last load");
1153                                 result = DNS_R_UPTODATE;
1154                                 goto cleanup;
1155                         }
1156                         loadtime = filetime;
1157                 }
1158         }
1159
1160         INSIST(zone->db_argc >= 1);
1161
1162         /*
1163          * Built in zones don't need to be reloaded.
1164          */
1165         if (zone->type == dns_zone_master &&
1166             strcmp(zone->db_argv[0], "_builtin") == 0 &&
1167             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1168                 result = ISC_R_SUCCESS;
1169                 goto cleanup;
1170         }
1171
1172         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
1173             (strcmp(zone->db_argv[0], "rbt") == 0 ||
1174              strcmp(zone->db_argv[0], "rbt64") == 0)) {
1175                 if (zone->masterfile == NULL ||
1176                     !isc_file_exists(zone->masterfile)) {
1177                         if (zone->masterfile != NULL) {
1178                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1179                                              "no master file");
1180                         }
1181                         zone->refreshtime = now;
1182                         if (zone->task != NULL)
1183                                 zone_settimer(zone, &now);
1184                         result = ISC_R_SUCCESS;
1185                         goto cleanup;
1186                 }
1187         }
1188
1189         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1190
1191         result = dns_db_create(zone->mctx, zone->db_argv[0],
1192                                &zone->origin, (zone->type == dns_zone_stub) ?
1193                                dns_dbtype_stub : dns_dbtype_zone,
1194                                zone->rdclass,
1195                                zone->db_argc - 1, zone->db_argv + 1,
1196                                &db);
1197
1198         if (result != ISC_R_SUCCESS) {
1199                 dns_zone_log(zone, ISC_LOG_ERROR,
1200                              "loading zone: creating database: %s",
1201                              isc_result_totext(result));
1202                 goto cleanup;
1203         }
1204         dns_db_settask(db, zone->task);
1205
1206         if (! dns_db_ispersistent(db)) {
1207                 if (zone->masterfile != NULL) {
1208                         result = zone_startload(db, zone, loadtime);
1209                 } else {
1210                         result = DNS_R_NOMASTERFILE;
1211                         if (zone->type == dns_zone_master) {
1212                                 dns_zone_log(zone, ISC_LOG_ERROR,
1213                                              "loading zone: "
1214                                              "no master file configured");
1215                                 goto cleanup;
1216                         }
1217                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1218                                      "no master file configured: continuing");
1219                 }
1220         }
1221
1222         if (result == DNS_R_CONTINUE) {
1223                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1224                 goto cleanup;
1225         }
1226
1227         result = zone_postload(zone, db, loadtime, result);
1228
1229  cleanup:
1230         UNLOCK_ZONE(zone);
1231         if (db != NULL)
1232                 dns_db_detach(&db);
1233         return (result);
1234 }
1235
1236 isc_result_t
1237 dns_zone_load(dns_zone_t *zone) {
1238         return (zone_load(zone, 0));
1239 }
1240
1241 isc_result_t
1242 dns_zone_loadnew(dns_zone_t *zone) {
1243         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1244 }
1245
1246 static void
1247 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1248         dns_load_t *load = event->ev_arg;
1249         isc_result_t result = ISC_R_SUCCESS;
1250         unsigned int options;
1251
1252         REQUIRE(DNS_LOAD_VALID(load));
1253
1254         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1255                 result = ISC_R_CANCELED;
1256         isc_event_free(&event);
1257         if (result == ISC_R_CANCELED)
1258                 goto fail;
1259
1260         options = DNS_MASTER_ZONE;
1261         if (load->zone->type == dns_zone_slave)
1262                 options |= DNS_MASTER_SLAVE;
1263         if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNS))
1264                 options |= DNS_MASTER_CHECKNS;
1265         if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_FATALNS))
1266                 options |= DNS_MASTER_FATALNS;
1267         if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNAMES))
1268                 options |= DNS_MASTER_CHECKNAMES;
1269         if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1270                 options |= DNS_MASTER_CHECKNAMESFAIL;
1271         if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKMX))
1272                 options |= DNS_MASTER_CHECKMX;
1273         if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKMXFAIL))
1274                 options |= DNS_MASTER_CHECKMXFAIL;
1275         if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKWILDCARD))
1276                 options |= DNS_MASTER_CHECKWILDCARD;
1277         result = dns_master_loadfileinc2(load->zone->masterfile,
1278                                          dns_db_origin(load->db),
1279                                          dns_db_origin(load->db),
1280                                          load->zone->rdclass,
1281                                          options,
1282                                          &load->callbacks, task,
1283                                          zone_loaddone, load,
1284                                          &load->zone->lctx, load->zone->mctx,
1285                                          load->zone->masterformat);
1286         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1287             result != DNS_R_SEENINCLUDE)
1288                 goto fail;
1289         return;
1290
1291  fail:
1292         zone_loaddone(load, result);
1293 }
1294
1295 static void
1296 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1297         const char me[] = "zone_gotwritehandle";
1298         dns_zone_t *zone = event->ev_arg;
1299         isc_result_t result = ISC_R_SUCCESS;
1300         dns_dbversion_t *version = NULL;
1301
1302         REQUIRE(DNS_ZONE_VALID(zone));
1303         INSIST(task == zone->task);
1304         ENTER;
1305
1306         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1307                 result = ISC_R_CANCELED;
1308         isc_event_free(&event);
1309         if (result == ISC_R_CANCELED)
1310                 goto fail;
1311
1312         LOCK_ZONE(zone);
1313         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1314         dns_db_currentversion(zone->db, &version);
1315         result = dns_master_dumpinc2(zone->mctx, zone->db, version,
1316                                      &dns_master_style_default,
1317                                      zone->masterfile, zone->task, dump_done,
1318                                      zone, &zone->dctx, zone->masterformat);
1319         dns_db_closeversion(zone->db, &version, ISC_FALSE);
1320         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1321         UNLOCK_ZONE(zone);
1322         if (result != DNS_R_CONTINUE)
1323                 goto fail;
1324         return;
1325
1326  fail:
1327         dump_done(zone, result);
1328 }
1329
1330 static isc_result_t
1331 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1332         dns_load_t *load;
1333         isc_result_t result;
1334         isc_result_t tresult;
1335         unsigned int options;
1336
1337         options = DNS_MASTER_ZONE;
1338         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1339                 options |= DNS_MASTER_MANYERRORS;
1340         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1341                 options |= DNS_MASTER_CHECKNS;
1342         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1343                 options |= DNS_MASTER_FATALNS;
1344         if (zone->type == dns_zone_slave)
1345                 options |= DNS_MASTER_SLAVE;
1346         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1347                 options |= DNS_MASTER_CHECKNAMES;
1348         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1349                 options |= DNS_MASTER_CHECKNAMESFAIL;
1350         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1351                 options |= DNS_MASTER_CHECKMX;
1352         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1353                 options |= DNS_MASTER_CHECKMXFAIL;
1354         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1355                 options |= DNS_MASTER_CHECKWILDCARD;
1356
1357         if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1358                 load = isc_mem_get(zone->mctx, sizeof(*load));
1359                 if (load == NULL)
1360                         return (ISC_R_NOMEMORY);
1361
1362                 load->mctx = NULL;
1363                 load->zone = NULL;
1364                 load->db = NULL;
1365                 load->loadtime = loadtime;
1366                 load->magic = LOAD_MAGIC;
1367
1368                 isc_mem_attach(zone->mctx, &load->mctx);
1369                 zone_iattach(zone, &load->zone);
1370                 dns_db_attach(db, &load->db);
1371                 dns_rdatacallbacks_init(&load->callbacks);
1372                 result = dns_db_beginload(db, &load->callbacks.add,
1373                                           &load->callbacks.add_private);
1374                 if (result != ISC_R_SUCCESS)
1375                         goto cleanup;
1376                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1377                                        zone_gotreadhandle, load,
1378                                        &zone->readio);
1379                 if (result != ISC_R_SUCCESS) {
1380                         /*
1381                          * We can't report multiple errors so ignore
1382                          * the result of dns_db_endload().
1383                          */
1384                         (void)dns_db_endload(load->db,
1385                                              &load->callbacks.add_private);
1386                         goto cleanup;
1387                 } else
1388                         result = DNS_R_CONTINUE;
1389         } else {
1390                 dns_rdatacallbacks_t callbacks;
1391
1392                 dns_rdatacallbacks_init(&callbacks);
1393                 result = dns_db_beginload(db, &callbacks.add,
1394                                           &callbacks.add_private);
1395                 if (result != ISC_R_SUCCESS)
1396                         return (result);
1397                 result = dns_master_loadfile2(zone->masterfile, &zone->origin,
1398                                               &zone->origin, zone->rdclass,
1399                                               options, &callbacks, zone->mctx,
1400                                               zone->masterformat);
1401                 tresult = dns_db_endload(db, &callbacks.add_private);
1402                 if (result == ISC_R_SUCCESS)
1403                         result = tresult;
1404         }
1405
1406         return (result);
1407
1408  cleanup:
1409         load->magic = 0;
1410         dns_db_detach(&load->db);
1411         zone_idetach(&load->zone);
1412         isc_mem_detach(&load->mctx);
1413         isc_mem_put(zone->mctx, load, sizeof(*load));
1414         return (result);
1415 }
1416
1417 static isc_boolean_t
1418 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1419               dns_name_t *owner)
1420 {
1421         isc_result_t result;
1422         char ownerbuf[DNS_NAME_FORMATSIZE];
1423         char namebuf[DNS_NAME_FORMATSIZE];
1424         char altbuf[DNS_NAME_FORMATSIZE];
1425         dns_fixedname_t fixed;
1426         dns_name_t *foundname;
1427         int level;
1428
1429         /*
1430          * Outside of zone.
1431          */
1432         if (!dns_name_issubdomain(name, &zone->origin)) {
1433                 if (zone->checkmx != NULL)
1434                         return ((zone->checkmx)(zone, name, owner));
1435                 return (ISC_TRUE);
1436         }
1437
1438         if (zone->type == dns_zone_master)
1439                 level = ISC_LOG_ERROR;
1440         else
1441                 level = ISC_LOG_WARNING;
1442
1443         dns_fixedname_init(&fixed);
1444         foundname = dns_fixedname_name(&fixed);
1445
1446         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1447                              0, 0, NULL, foundname, NULL, NULL);
1448         if (result == ISC_R_SUCCESS)
1449                 return (ISC_TRUE);
1450
1451         if (result == DNS_R_NXRRSET) {
1452                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1453                                      0, 0, NULL, foundname, NULL, NULL);
1454                 if (result == ISC_R_SUCCESS)
1455                         return (ISC_TRUE);
1456         }
1457
1458         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1459         dns_name_format(name, namebuf, sizeof namebuf);
1460         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1461             result == DNS_R_EMPTYNAME) {
1462                 dns_zone_log(zone, level,
1463                              "%s/MX '%s' has no address records (A or AAAA)",
1464                              ownerbuf, namebuf);
1465                 /* XXX950 make fatal for 9.5.0. */
1466                 return (ISC_TRUE);
1467         }
1468
1469         if (result == DNS_R_CNAME) {
1470                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1471                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1472                         level = ISC_LOG_WARNING;
1473                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1474                         dns_zone_log(zone, level,
1475                                      "%s/MX '%s' is a CNAME (illegal)",
1476                                      ownerbuf, namebuf);
1477                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1478         }
1479
1480         if (result == DNS_R_DNAME) {
1481                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1482                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1483                         level = ISC_LOG_WARNING;
1484                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
1485                         dns_name_format(foundname, altbuf, sizeof altbuf);
1486                         dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
1487                                      " '%s' (illegal)", ownerbuf, namebuf,
1488                                      altbuf);
1489                 }
1490                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1491         }
1492
1493         if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
1494                 return ((zone->checkmx)(zone, name, owner));
1495
1496         return (ISC_TRUE);
1497 }
1498
1499 static isc_boolean_t
1500 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1501                dns_name_t *owner)
1502 {
1503         isc_result_t result;
1504         char ownerbuf[DNS_NAME_FORMATSIZE];
1505         char namebuf[DNS_NAME_FORMATSIZE];
1506         char altbuf[DNS_NAME_FORMATSIZE];
1507         dns_fixedname_t fixed;
1508         dns_name_t *foundname;
1509         int level;
1510
1511         /*
1512          * "." means the services does not exist.
1513          */
1514         if (dns_name_equal(name, dns_rootname))
1515                 return (ISC_TRUE);
1516
1517         /*
1518          * Outside of zone.
1519          */
1520         if (!dns_name_issubdomain(name, &zone->origin)) {
1521                 if (zone->checksrv != NULL)
1522                         return ((zone->checksrv)(zone, name, owner));
1523                 return (ISC_TRUE);
1524         }
1525
1526         if (zone->type == dns_zone_master)
1527                 level = ISC_LOG_ERROR;
1528         else
1529                 level = ISC_LOG_WARNING;
1530
1531         dns_fixedname_init(&fixed);
1532         foundname = dns_fixedname_name(&fixed);
1533
1534         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1535                              0, 0, NULL, foundname, NULL, NULL);
1536         if (result == ISC_R_SUCCESS)
1537                 return (ISC_TRUE);
1538
1539         if (result == DNS_R_NXRRSET) {
1540                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1541                                      0, 0, NULL, foundname, NULL, NULL);
1542                 if (result == ISC_R_SUCCESS)
1543                         return (ISC_TRUE);
1544         }
1545
1546         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1547         dns_name_format(name, namebuf, sizeof namebuf);
1548         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1549             result == DNS_R_EMPTYNAME) {
1550                 dns_zone_log(zone, level,
1551                              "%s/SRV '%s' has no address records (A or AAAA)",
1552                              ownerbuf, namebuf);
1553                 /* XXX950 make fatal for 9.5.0. */
1554                 return (ISC_TRUE);
1555         }
1556
1557         if (result == DNS_R_CNAME) {
1558                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1559                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1560                         level = ISC_LOG_WARNING;
1561                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1562                         dns_zone_log(zone, level,
1563                                      "%s/SRV '%s' is a CNAME (illegal)",
1564                                      ownerbuf, namebuf);
1565                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1566         }
1567
1568         if (result == DNS_R_DNAME) {
1569                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1570                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1571                         level = ISC_LOG_WARNING;
1572                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
1573                         dns_name_format(foundname, altbuf, sizeof altbuf);
1574                         dns_zone_log(zone, level, "%s/SRV '%s' is below a "
1575                                      "DNAME '%s' (illegal)", ownerbuf, namebuf,
1576                                      altbuf);
1577                 }
1578                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1579         }
1580
1581         if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
1582                 return ((zone->checksrv)(zone, name, owner));
1583
1584         return (ISC_TRUE);
1585 }
1586
1587 static isc_boolean_t
1588 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1589                 dns_name_t *owner)
1590 {
1591         isc_boolean_t answer = ISC_TRUE;
1592         isc_result_t result, tresult;
1593         char ownerbuf[DNS_NAME_FORMATSIZE];
1594         char namebuf[DNS_NAME_FORMATSIZE];
1595         char altbuf[DNS_NAME_FORMATSIZE];
1596         dns_fixedname_t fixed;
1597         dns_name_t *foundname;
1598         dns_rdataset_t a;
1599         dns_rdataset_t aaaa;
1600         int level;
1601
1602         /*
1603          * Outside of zone.
1604          */
1605         if (!dns_name_issubdomain(name, &zone->origin)) {
1606                 if (zone->checkns != NULL)
1607                         return ((zone->checkns)(zone, name, owner, NULL, NULL));
1608                 return (ISC_TRUE);
1609         }
1610
1611         if (zone->type == dns_zone_master)
1612                 level = ISC_LOG_ERROR;
1613         else
1614                 level = ISC_LOG_WARNING;
1615
1616         dns_fixedname_init(&fixed);
1617         foundname = dns_fixedname_name(&fixed);
1618         dns_rdataset_init(&a);
1619         dns_rdataset_init(&aaaa);
1620
1621         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1622                              DNS_DBFIND_GLUEOK, 0, NULL,
1623                              foundname, &a, NULL);
1624
1625         if (result == ISC_R_SUCCESS) {
1626                 dns_rdataset_disassociate(&a);
1627                 return (ISC_TRUE);
1628         } else if (result == DNS_R_DELEGATION)
1629                 dns_rdataset_disassociate(&a);
1630
1631         if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
1632             result == DNS_R_GLUE) {
1633                 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1634                                      DNS_DBFIND_GLUEOK, 0, NULL,
1635                                      foundname, &aaaa, NULL);
1636                 if (tresult == ISC_R_SUCCESS) {
1637                         dns_rdataset_disassociate(&aaaa);
1638                         return (ISC_TRUE);
1639                 }
1640                 if (tresult == DNS_R_DELEGATION)
1641                         dns_rdataset_disassociate(&aaaa);
1642                 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
1643                         /*
1644                          * Check glue against child zone.
1645                          */
1646                         if (zone->checkns != NULL)
1647                                 answer = (zone->checkns)(zone, name, owner,
1648                                                          &a, &aaaa);
1649                         if (dns_rdataset_isassociated(&a))
1650                                 dns_rdataset_disassociate(&a);
1651                         if (dns_rdataset_isassociated(&aaaa))
1652                                 dns_rdataset_disassociate(&aaaa);
1653                         return (answer);
1654                 }
1655         } else
1656                 tresult = result;
1657
1658         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1659         dns_name_format(name, namebuf, sizeof namebuf);
1660         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1661             result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
1662                 const char *what;
1663                 isc_boolean_t required = ISC_FALSE;
1664                 if (dns_name_issubdomain(name, owner)) {
1665                         what = "REQUIRED GLUE ";
1666                         required = ISC_TRUE;
1667                  } else if (result == DNS_R_DELEGATION)
1668                         what = "SIBLING GLUE ";
1669                 else
1670                         what = "";
1671
1672                 if (result != DNS_R_DELEGATION || required ||
1673                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
1674                         dns_zone_log(zone, level, "%s/NS '%s' has no %s"
1675                                      "address records (A or AAAA)",
1676                                      ownerbuf, namebuf, what);
1677                         /*
1678                          * Log missing address record.
1679                          */
1680                         if (result == DNS_R_DELEGATION && zone->checkns != NULL)
1681                                 (void)(zone->checkns)(zone, name, owner,
1682                                                       &a, &aaaa);
1683                         /* XXX950 make fatal for 9.5.0. */
1684                         /* answer = ISC_FALSE; */
1685                 }
1686         } else if (result == DNS_R_CNAME) {
1687                 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
1688                              ownerbuf, namebuf);
1689                 /* XXX950 make fatal for 9.5.0. */
1690                 /* answer = ISC_FALSE; */
1691         } else if (result == DNS_R_DNAME) {
1692                 dns_name_format(foundname, altbuf, sizeof altbuf);
1693                 dns_zone_log(zone, level,
1694                              "%s/NS '%s' is below a DNAME '%s' (illegal)",
1695                              ownerbuf, namebuf, altbuf);
1696                 /* XXX950 make fatal for 9.5.0. */
1697                 /* answer = ISC_FALSE; */
1698         }
1699
1700         if (dns_rdataset_isassociated(&a))
1701                 dns_rdataset_disassociate(&a);
1702         if (dns_rdataset_isassociated(&aaaa))
1703                 dns_rdataset_disassociate(&aaaa);
1704         return (answer);
1705 }
1706
1707 static isc_boolean_t
1708 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
1709         dns_dbiterator_t *dbiterator = NULL;
1710         dns_dbnode_t *node = NULL;
1711         dns_rdataset_t rdataset;
1712         dns_fixedname_t fixed;
1713         dns_fixedname_t fixedbottom;
1714         dns_rdata_mx_t mx;
1715         dns_rdata_ns_t ns;
1716         dns_rdata_in_srv_t srv;
1717         dns_rdata_t rdata;
1718         dns_name_t *name;
1719         dns_name_t *bottom;
1720         isc_result_t result;
1721         isc_boolean_t ok = ISC_TRUE;
1722
1723         dns_fixedname_init(&fixed);
1724         name = dns_fixedname_name(&fixed);
1725         dns_fixedname_init(&fixedbottom);
1726         bottom = dns_fixedname_name(&fixedbottom);
1727         dns_rdataset_init(&rdataset);
1728         dns_rdata_init(&rdata);
1729
1730         result = dns_db_createiterator(db, ISC_FALSE, &dbiterator);
1731         if (result != ISC_R_SUCCESS)
1732                 return (ISC_TRUE);
1733
1734         result = dns_dbiterator_first(dbiterator);
1735         while (result == ISC_R_SUCCESS) {
1736                 result = dns_dbiterator_current(dbiterator, &node, name);
1737                 if (result != ISC_R_SUCCESS)
1738                         goto cleanup;
1739
1740                 /*
1741                  * Is this name visible in the zone?
1742                  */
1743                 if (!dns_name_issubdomain(name, &zone->origin) ||
1744                     (dns_name_countlabels(bottom) > 0 &&
1745                      dns_name_issubdomain(name, bottom)))
1746                         goto next;
1747
1748                 /*
1749                  * Don't check the NS records at the origin.
1750                  */
1751                 if (dns_name_equal(name, &zone->origin))
1752                         goto checkmx;
1753
1754                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
1755                                              0, 0, &rdataset, NULL);
1756                 if (result != ISC_R_SUCCESS)
1757                         goto checkmx;
1758                 /*
1759                  * Remember bottom of zone.
1760                  */
1761                 dns_name_copy(name, bottom, NULL);
1762
1763                 result = dns_rdataset_first(&rdataset);
1764                 while (result == ISC_R_SUCCESS) {
1765                         dns_rdataset_current(&rdataset, &rdata);
1766                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
1767                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
1768                         if (!zone_check_glue(zone, db, &ns.name, name))
1769                                 ok = ISC_FALSE;
1770                         dns_rdata_reset(&rdata);
1771                         result = dns_rdataset_next(&rdataset);
1772                 }
1773                 dns_rdataset_disassociate(&rdataset);
1774
1775  checkmx:
1776                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
1777                                              0, 0, &rdataset, NULL);
1778                 if (result != ISC_R_SUCCESS)
1779                         goto checksrv;
1780                 result = dns_rdataset_first(&rdataset);
1781                 while (result == ISC_R_SUCCESS) {
1782                         dns_rdataset_current(&rdataset, &rdata);
1783                         result = dns_rdata_tostruct(&rdata, &mx, NULL);
1784                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
1785                         if (!zone_check_mx(zone, db, &mx.mx, name))
1786                                 ok = ISC_FALSE;
1787                         dns_rdata_reset(&rdata);
1788                         result = dns_rdataset_next(&rdataset);
1789                 }
1790                 dns_rdataset_disassociate(&rdataset);
1791
1792  checksrv:
1793                 if (zone->rdclass != dns_rdataclass_in)
1794                         goto next;
1795                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
1796                                              0, 0, &rdataset, NULL);
1797                 if (result != ISC_R_SUCCESS)
1798                         goto next;
1799                 result = dns_rdataset_first(&rdataset);
1800                 while (result == ISC_R_SUCCESS) {
1801                         dns_rdataset_current(&rdataset, &rdata);
1802                         result = dns_rdata_tostruct(&rdata, &srv, NULL);
1803                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
1804                         if (!zone_check_srv(zone, db, &srv.target, name))
1805                                 ok = ISC_FALSE;
1806                         dns_rdata_reset(&rdata);
1807                         result = dns_rdataset_next(&rdataset);
1808                 }
1809                 dns_rdataset_disassociate(&rdataset);
1810
1811  next:
1812                 dns_db_detachnode(db, &node);
1813                 result = dns_dbiterator_next(dbiterator);
1814         }
1815
1816  cleanup:
1817         if (node != NULL)
1818                 dns_db_detachnode(db, &node);
1819         dns_dbiterator_destroy(&dbiterator);
1820
1821         return (ok);
1822 }
1823
1824 /*
1825  * OpenSSL verification of RSA keys with exponent 3 is known to be
1826  * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
1827  * if they are in use.
1828  */
1829 static void
1830 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
1831         dns_dbnode_t *node = NULL;
1832         dns_dbversion_t *version = NULL;
1833         dns_rdata_dnskey_t dnskey;
1834         dns_rdata_t rdata = DNS_RDATA_INIT;
1835         dns_rdataset_t rdataset;
1836         isc_result_t result;
1837         isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
1838         const char *algorithm;
1839
1840         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
1841         if (result != ISC_R_SUCCESS)
1842                 goto cleanup;
1843
1844         dns_db_currentversion(db, &version);
1845         dns_rdataset_init(&rdataset);
1846         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
1847                                      dns_rdatatype_none, 0, &rdataset, NULL);
1848         if (result != ISC_R_SUCCESS)
1849                 goto cleanup;
1850
1851         for (result = dns_rdataset_first(&rdataset);
1852              result == ISC_R_SUCCESS;
1853              result = dns_rdataset_next(&rdataset))
1854         {
1855                 dns_rdataset_current(&rdataset, &rdata);
1856                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1857                 INSIST(result == ISC_R_SUCCESS);
1858
1859                 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
1860                      dnskey.algorithm == DST_ALG_RSAMD5) &&
1861                      dnskey.datalen > 1 && dnskey.data[0] == 1 &&
1862                      dnskey.data[1] == 3)
1863                 {
1864                         if (dnskey.algorithm == DST_ALG_RSASHA1) {
1865                                 logit = !foundrsa;
1866                                 foundrsa = ISC_TRUE;
1867                                 algorithm = "RSASHA1";
1868                         } else {
1869                                 logit = !foundmd5;
1870                                 foundmd5 = ISC_TRUE;
1871                                 algorithm = "RSAMD5";
1872                         }
1873                         if (logit)
1874                                 dns_zone_log(zone, ISC_LOG_WARNING,
1875                                              "weak %s (%u) key found "
1876                                              "(exponent=3)", algorithm,
1877                                              dnskey.algorithm);
1878                         if (foundrsa && foundmd5)
1879                                 break;
1880                 }
1881                 dns_rdata_reset(&rdata);
1882         }
1883         dns_rdataset_disassociate(&rdataset);
1884
1885  cleanup:
1886         if (node != NULL)
1887                 dns_db_detachnode(db, &node);
1888         if (version != NULL)
1889                 dns_db_closeversion(db, &version, ISC_FALSE);
1890
1891 }
1892
1893 static isc_result_t
1894 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
1895               isc_result_t result)
1896 {
1897         unsigned int soacount = 0;
1898         unsigned int nscount = 0;
1899         unsigned int errors = 0;
1900         isc_uint32_t serial, refresh, retry, expire, minimum;
1901         isc_time_t now;
1902         isc_boolean_t needdump = ISC_FALSE;
1903         isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1904
1905         TIME_NOW(&now);
1906
1907         /*
1908          * Initiate zone transfer?  We may need a error code that
1909          * indicates that the "permanent" form does not exist.
1910          * XXX better error feedback to log.
1911          */
1912         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
1913                 if (zone->type == dns_zone_slave ||
1914                     zone->type == dns_zone_stub) {
1915                         if (result == ISC_R_FILENOTFOUND)
1916                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1917                                              "no master file");
1918                         else if (result != DNS_R_NOMASTERFILE)
1919                                 dns_zone_log(zone, ISC_LOG_ERROR,
1920                                              "loading from master file %s "
1921                                              "failed: %s",
1922                                              zone->masterfile,
1923                                              dns_result_totext(result));
1924                 } else
1925                         dns_zone_log(zone, ISC_LOG_ERROR,
1926                                      "loading from master file %s failed: %s",
1927                                      zone->masterfile,
1928                                      dns_result_totext(result));
1929                 goto cleanup;
1930         }
1931
1932         dns_zone_log(zone, ISC_LOG_DEBUG(2),
1933                      "number of nodes in database: %u",
1934                      dns_db_nodecount(db));
1935
1936         if (result == DNS_R_SEENINCLUDE)
1937                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1938         else
1939                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1940
1941         /*
1942          * Apply update log, if any, on initial load.
1943          */
1944         if (zone->journal != NULL &&
1945             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
1946             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
1947         {
1948                 result = dns_journal_rollforward(zone->mctx, db,
1949                                                  zone->journal);
1950                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
1951                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
1952                     result != ISC_R_RANGE) {
1953                         dns_zone_log(zone, ISC_LOG_ERROR,
1954                                      "journal rollforward failed: %s",
1955                                      dns_result_totext(result));
1956                         goto cleanup;
1957                 }
1958                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
1959                         dns_zone_log(zone, ISC_LOG_ERROR,
1960                                      "journal rollforward failed: "
1961                                      "journal out of sync with zone");
1962                         goto cleanup;
1963                 }
1964                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1965                              "journal rollforward completed "
1966                              "successfully: %s",
1967                              dns_result_totext(result));
1968                 if (result == ISC_R_SUCCESS)
1969                         needdump = ISC_TRUE;
1970         }
1971
1972         zone->loadtime = loadtime;
1973
1974         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
1975
1976         /*
1977          * Obtain ns, soa and cname counts for top of zone.
1978          */
1979         INSIST(db != NULL);
1980         result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
1981                                   &refresh, &retry, &expire, &minimum,
1982                                   &errors);
1983         if (result != ISC_R_SUCCESS) {
1984                 dns_zone_log(zone, ISC_LOG_ERROR,
1985                              "could not find NS and/or SOA records");
1986         }
1987
1988         /*
1989          * Master / Slave / Stub zones require both NS and SOA records at
1990          * the top of the zone.
1991          */
1992
1993         switch (zone->type) {
1994         case dns_zone_master:
1995         case dns_zone_slave:
1996         case dns_zone_stub:
1997                 if (soacount != 1) {
1998                         dns_zone_log(zone, ISC_LOG_ERROR,
1999                                      "has %d SOA records", soacount);
2000                         result = DNS_R_BADZONE;
2001                 }
2002                 if (nscount == 0) {
2003                         dns_zone_log(zone, ISC_LOG_ERROR,
2004                                      "has no NS records");
2005                         result = DNS_R_BADZONE;
2006                 }
2007                 if (result != ISC_R_SUCCESS)
2008                         goto cleanup;
2009                 if (zone->type == dns_zone_master && errors != 0) {
2010                         result = DNS_R_BADZONE;
2011                         goto cleanup;
2012                 }
2013                 if (zone->type == dns_zone_master &&
2014                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
2015                     !integrity_checks(zone, db)) {
2016                         result = DNS_R_BADZONE;
2017                         goto cleanup;
2018                 }
2019
2020                 if (zone->db != NULL) {
2021                         /*
2022                          * This is checked in zone_replacedb() for slave zones
2023                          * as they don't reload from disk.
2024                          */
2025                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
2026                             !isc_serial_gt(serial, zone->serial)) {
2027                                 isc_uint32_t serialmin, serialmax;
2028
2029                                 INSIST(zone->type == dns_zone_master);
2030
2031                                 serialmin = (zone->serial + 1) & 0xffffffffU;
2032                                 serialmax = (zone->serial + 0x7fffffffU) &
2033                                              0xffffffffU;
2034                                 dns_zone_log(zone, ISC_LOG_ERROR,
2035                                              "ixfr-from-differences: "
2036                                              "new serial (%u) out of range "
2037                                              "[%u - %u]", serial, serialmin,
2038                                              serialmax);
2039                                 result = DNS_R_BADZONE;
2040                                 goto cleanup;
2041                         } else if (!isc_serial_ge(serial, zone->serial))
2042                                 dns_zone_log(zone, ISC_LOG_ERROR,
2043                                              "zone serial has gone backwards");
2044                         else if (serial == zone->serial && !hasinclude)
2045                                 dns_zone_log(zone, ISC_LOG_ERROR,
2046                                              "zone serial unchanged. "
2047                                              "zone may fail to transfer "
2048                                              "to slaves.");
2049                 }
2050                 zone->serial = serial;
2051                 zone->refresh = RANGE(refresh,
2052                                       zone->minrefresh, zone->maxrefresh);
2053                 zone->retry = RANGE(retry,
2054                                     zone->minretry, zone->maxretry);
2055                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
2056                                      DNS_MAX_EXPIRE);
2057                 zone->minimum = minimum;
2058                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
2059
2060                 if (zone->type == dns_zone_slave ||
2061                     zone->type == dns_zone_stub) {
2062                         isc_time_t t;
2063                         isc_uint32_t delay;
2064
2065                         result = isc_file_getmodtime(zone->journal, &t);
2066                         if (result != ISC_R_SUCCESS)
2067                                 result = isc_file_getmodtime(zone->masterfile,
2068                                                              &t);
2069                         if (result == ISC_R_SUCCESS)
2070                                 DNS_ZONE_TIME_ADD(&t, zone->expire,
2071                                                   &zone->expiretime);
2072                         else
2073                                 DNS_ZONE_TIME_ADD(&now, zone->retry,
2074                                                   &zone->expiretime);
2075
2076                         delay = isc_random_jitter(zone->retry,
2077                                                   (zone->retry * 3) / 4);
2078                         DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
2079                         if (isc_time_compare(&zone->refreshtime,
2080                                              &zone->expiretime) >= 0)
2081                                 zone->refreshtime = now;
2082                 }
2083                 break;
2084         default:
2085                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2086                                  "unexpected zone type %d", zone->type);
2087                 result = ISC_R_UNEXPECTED;
2088                 goto cleanup;
2089         }
2090
2091         /*
2092          * Check for weak DNSKEY's.
2093          */
2094         if (zone->type == dns_zone_master)
2095                 zone_check_dnskeys(zone, db);
2096
2097 #if 0
2098         /* destroy notification example. */
2099         {
2100                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
2101                                                     DNS_EVENT_DBDESTROYED,
2102                                                     dns_zonemgr_dbdestroyed,
2103                                                     zone,
2104                                                     sizeof(isc_event_t));
2105                 dns_db_ondestroy(db, zone->task, &e);
2106         }
2107 #endif
2108
2109         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2110         if (zone->db != NULL) {
2111                 result = zone_replacedb(zone, db, ISC_FALSE);
2112                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2113                 if (result != ISC_R_SUCCESS)
2114                         goto cleanup;
2115         } else {
2116                 zone_attachdb(zone, db);
2117                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2118                 DNS_ZONE_SETFLAG(zone,
2119                                  DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
2120         }
2121         result = ISC_R_SUCCESS;
2122         if (needdump)
2123                 zone_needdump(zone, DNS_DUMP_DELAY);
2124         if (zone->task != NULL)
2125                 zone_settimer(zone, &now);
2126
2127         if (! dns_db_ispersistent(db))
2128                 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s",
2129                              zone->serial,
2130                              dns_db_issecure(db) ? " (signed)" : "");
2131
2132         return (result);
2133
2134  cleanup:
2135         if (zone->type == dns_zone_slave ||
2136             zone->type == dns_zone_stub) {
2137                 if (zone->journal != NULL)
2138                         zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
2139                 if (zone->masterfile != NULL)
2140                         zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
2141
2142                 /* Mark the zone for immediate refresh. */
2143                 zone->refreshtime = now;
2144                 if (zone->task != NULL)
2145                         zone_settimer(zone, &now);
2146                 result = ISC_R_SUCCESS;
2147         }
2148         return (result);
2149 }
2150
2151 static isc_boolean_t
2152 exit_check(dns_zone_t *zone) {
2153
2154         REQUIRE(LOCKED_ZONE(zone));
2155
2156         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
2157             zone->irefs == 0)
2158         {
2159                 /*
2160                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
2161                  */
2162                 INSIST(isc_refcount_current(&zone->erefs) == 0);
2163                 return (ISC_TRUE);
2164         }
2165         return (ISC_FALSE);
2166 }
2167
2168 static isc_boolean_t
2169 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
2170         isc_result_t result;
2171         char namebuf[DNS_NAME_FORMATSIZE];
2172         char altbuf[DNS_NAME_FORMATSIZE];
2173         dns_fixedname_t fixed;
2174         dns_name_t *foundname;
2175         int level;
2176
2177         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
2178                 return (ISC_TRUE);
2179
2180         if (zone->type == dns_zone_master)
2181                 level = ISC_LOG_ERROR;
2182         else
2183                 level = ISC_LOG_WARNING;
2184
2185         dns_fixedname_init(&fixed);
2186         foundname = dns_fixedname_name(&fixed);
2187
2188         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2189                              0, 0, NULL, foundname, NULL, NULL);
2190         if (result == ISC_R_SUCCESS)
2191                 return (ISC_TRUE);
2192
2193         if (result == DNS_R_NXRRSET) {
2194                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2195                                      0, 0, NULL, foundname, NULL, NULL);
2196                 if (result == ISC_R_SUCCESS)
2197                         return (ISC_TRUE);
2198         }
2199
2200         dns_name_format(name, namebuf, sizeof namebuf);
2201         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2202             result == DNS_R_EMPTYNAME) {
2203                 dns_zone_log(zone, level,
2204                              "NS '%s' has no address records (A or AAAA)",
2205                              namebuf);
2206                 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2207                 return (ISC_TRUE);
2208         }
2209
2210         if (result == DNS_R_CNAME) {
2211                 dns_zone_log(zone, level, "NS '%s' is a CNAME (illegal)",
2212                              namebuf);
2213                 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2214                 return (ISC_TRUE);
2215         }
2216
2217         if (result == DNS_R_DNAME) {
2218                 dns_name_format(foundname, altbuf, sizeof altbuf);
2219                 dns_zone_log(zone, level,
2220                              "NS '%s' is below a DNAME '%s' (illegal)",
2221                              namebuf, altbuf);
2222                 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2223                 return (ISC_TRUE);
2224         }
2225
2226         return (ISC_TRUE);
2227 }
2228
2229 static isc_result_t
2230 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
2231                  dns_dbversion_t *version, unsigned int *nscount,
2232                  unsigned int *errors)
2233 {
2234         isc_result_t result;
2235         unsigned int count = 0;
2236         unsigned int ecount = 0;
2237         dns_rdataset_t rdataset;
2238         dns_rdata_t rdata;
2239         dns_rdata_ns_t ns;
2240
2241         dns_rdataset_init(&rdataset);
2242         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
2243                                      dns_rdatatype_none, 0, &rdataset, NULL);
2244         if (result == ISC_R_NOTFOUND)
2245                 goto success;
2246         if (result != ISC_R_SUCCESS)
2247                 goto invalidate_rdataset;
2248
2249         result = dns_rdataset_first(&rdataset);
2250         while (result == ISC_R_SUCCESS) {
2251                 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
2252                     (zone->type == dns_zone_master ||
2253                      zone->type == dns_zone_slave)) {
2254                         dns_rdata_init(&rdata);
2255                         dns_rdataset_current(&rdataset, &rdata);
2256                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
2257                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2258                         if (dns_name_issubdomain(&ns.name, &zone->origin) &&
2259                             !zone_check_ns(zone, db, &ns.name))
2260                                 ecount++;
2261                 }
2262                 count++;
2263                 result = dns_rdataset_next(&rdataset);
2264         }
2265         dns_rdataset_disassociate(&rdataset);
2266
2267  success:
2268         if (nscount != NULL)
2269                 *nscount = count;
2270         if (errors != NULL)
2271                 *errors = ecount;
2272
2273         result = ISC_R_SUCCESS;
2274
2275  invalidate_rdataset:
2276         dns_rdataset_invalidate(&rdataset);
2277
2278         return (result);
2279 }
2280
2281 static isc_result_t
2282 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
2283                  unsigned int *soacount,
2284                  isc_uint32_t *serial, isc_uint32_t *refresh,
2285                  isc_uint32_t *retry, isc_uint32_t *expire,
2286                  isc_uint32_t *minimum)
2287 {
2288         isc_result_t result;
2289         unsigned int count;
2290         dns_rdataset_t rdataset;
2291         dns_rdata_t rdata = DNS_RDATA_INIT;
2292         dns_rdata_soa_t soa;
2293
2294         dns_rdataset_init(&rdataset);
2295         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
2296                                      dns_rdatatype_none, 0, &rdataset, NULL);
2297         if (result == ISC_R_NOTFOUND) {
2298                 if (soacount != NULL)
2299                         *soacount = 0;
2300                 if (serial != NULL)
2301                         *serial = 0;
2302                 if (refresh != NULL)
2303                         *refresh = 0;
2304                 if (retry != NULL)
2305                         *retry = 0;
2306                 if (expire != NULL)
2307                         *expire = 0;
2308                 if (minimum != NULL)
2309                         *minimum = 0;
2310                 result = ISC_R_SUCCESS;
2311                 goto invalidate_rdataset;
2312         }
2313         if (result != ISC_R_SUCCESS)
2314                 goto invalidate_rdataset;
2315
2316         count = 0;
2317         result = dns_rdataset_first(&rdataset);
2318         while (result == ISC_R_SUCCESS) {
2319                 dns_rdata_init(&rdata);
2320                 dns_rdataset_current(&rdataset, &rdata);
2321                 count++;
2322                 if (count == 1) {
2323                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
2324                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2325                 }
2326
2327                 result = dns_rdataset_next(&rdataset);
2328                 dns_rdata_reset(&rdata);
2329         }
2330         dns_rdataset_disassociate(&rdataset);
2331
2332         if (soacount != NULL)
2333                 *soacount = count;
2334
2335         if (count > 0) {
2336                 if (serial != NULL)
2337                         *serial = soa.serial;
2338                 if (refresh != NULL)
2339                         *refresh = soa.refresh;
2340                 if (retry != NULL)
2341                         *retry = soa.retry;
2342                 if (expire != NULL)
2343                         *expire = soa.expire;
2344                 if (minimum != NULL)
2345                         *minimum = soa.minimum;
2346         }
2347
2348         result = ISC_R_SUCCESS;
2349
2350  invalidate_rdataset:
2351         dns_rdataset_invalidate(&rdataset);
2352
2353         return (result);
2354 }
2355
2356 /*
2357  * zone must be locked.
2358  */
2359 static isc_result_t
2360 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
2361                  unsigned int *soacount, isc_uint32_t *serial,
2362                  isc_uint32_t *refresh, isc_uint32_t *retry,
2363                  isc_uint32_t *expire, isc_uint32_t *minimum,
2364                  unsigned int *errors)
2365 {
2366         dns_dbversion_t *version;
2367         isc_result_t result;
2368         isc_result_t answer = ISC_R_SUCCESS;
2369         dns_dbnode_t *node;
2370
2371         REQUIRE(db != NULL);
2372         REQUIRE(zone != NULL);
2373
2374         version = NULL;
2375         dns_db_currentversion(db, &version);
2376
2377         node = NULL;
2378         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2379         if (result != ISC_R_SUCCESS) {
2380                 answer = result;
2381                 goto closeversion;
2382         }
2383
2384         if (nscount != NULL || errors != NULL) {
2385                 result = zone_count_ns_rr(zone, db, node, version,
2386                                           nscount, errors);
2387                 if (result != ISC_R_SUCCESS)
2388                         answer = result;
2389         }
2390
2391         if (soacount != NULL || serial != NULL || refresh != NULL
2392             || retry != NULL || expire != NULL || minimum != NULL) {
2393                 result = zone_load_soa_rr(db, node, version, soacount,
2394                                           serial, refresh, retry, expire,
2395                                           minimum);
2396                 if (result != ISC_R_SUCCESS)
2397                         answer = result;
2398         }
2399
2400         dns_db_detachnode(db, &node);
2401  closeversion:
2402         dns_db_closeversion(db, &version, ISC_FALSE);
2403
2404         return (answer);
2405 }
2406
2407 void
2408 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
2409         REQUIRE(DNS_ZONE_VALID(source));
2410         REQUIRE(target != NULL && *target == NULL);
2411         isc_refcount_increment(&source->erefs, NULL);
2412         *target = source;
2413 }
2414
2415 void
2416 dns_zone_detach(dns_zone_t **zonep) {
2417         dns_zone_t *zone;
2418         unsigned int refs;
2419         isc_boolean_t free_now = ISC_FALSE;
2420
2421         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
2422
2423         zone = *zonep;
2424
2425         isc_refcount_decrement(&zone->erefs, &refs);
2426
2427         if (refs == 0) {
2428                 LOCK_ZONE(zone);
2429                 /*
2430                  * We just detached the last external reference.
2431                  */
2432                 if (zone->task != NULL) {
2433                         /*
2434                          * This zone is being managed.  Post
2435                          * its control event and let it clean
2436                          * up synchronously in the context of
2437                          * its task.
2438                          */
2439                         isc_event_t *ev = &zone->ctlevent;
2440                         isc_task_send(zone->task, &ev);
2441                 } else {
2442                         /*
2443                          * This zone is not being managed; it has
2444                          * no task and can have no outstanding
2445                          * events.  Free it immediately.
2446                          */
2447                         /*
2448                          * Unmanaged zones should not have non-null views;
2449                          * we have no way of detaching from the view here
2450                          * without causing deadlock because this code is called
2451                          * with the view already locked.
2452                          */
2453                         INSIST(zone->view == NULL);
2454                         free_now = ISC_TRUE;
2455                 }
2456                 UNLOCK_ZONE(zone);
2457         }
2458         *zonep = NULL;
2459         if (free_now)
2460                 zone_free(zone);
2461 }
2462
2463 void
2464 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
2465         REQUIRE(DNS_ZONE_VALID(source));
2466         REQUIRE(target != NULL && *target == NULL);
2467         LOCK_ZONE(source);
2468         zone_iattach(source, target);
2469         UNLOCK_ZONE(source);
2470 }
2471
2472 static void
2473 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
2474
2475         /*
2476          * 'source' locked by caller.
2477          */
2478         REQUIRE(LOCKED_ZONE(source));
2479         REQUIRE(DNS_ZONE_VALID(source));
2480         REQUIRE(target != NULL && *target == NULL);
2481         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
2482         source->irefs++;
2483         INSIST(source->irefs != 0);
2484         *target = source;
2485 }
2486
2487 static void
2488 zone_idetach(dns_zone_t **zonep) {
2489         dns_zone_t *zone;
2490
2491         /*
2492          * 'zone' locked by caller.
2493          */
2494         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
2495         zone = *zonep;
2496         REQUIRE(LOCKED_ZONE(*zonep));
2497         *zonep = NULL;
2498
2499         INSIST(zone->irefs > 0);
2500         zone->irefs--;
2501         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
2502 }
2503
2504 void
2505 dns_zone_idetach(dns_zone_t **zonep) {
2506         dns_zone_t *zone;
2507         isc_boolean_t free_needed;
2508
2509         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
2510         zone = *zonep;
2511         *zonep = NULL;
2512
2513         LOCK_ZONE(zone);
2514         INSIST(zone->irefs > 0);
2515         zone->irefs--;
2516         free_needed = exit_check(zone);
2517         UNLOCK_ZONE(zone);
2518         if (free_needed)
2519                 zone_free(zone);
2520 }
2521
2522 isc_mem_t *
2523 dns_zone_getmctx(dns_zone_t *zone) {
2524         REQUIRE(DNS_ZONE_VALID(zone));
2525
2526         return (zone->mctx);
2527 }
2528
2529 dns_zonemgr_t *
2530 dns_zone_getmgr(dns_zone_t *zone) {
2531         REQUIRE(DNS_ZONE_VALID(zone));
2532
2533         return (zone->zmgr);
2534 }
2535
2536 void
2537 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
2538         REQUIRE(DNS_ZONE_VALID(zone));
2539
2540         LOCK_ZONE(zone);
2541         if (value)
2542                 DNS_ZONE_SETFLAG(zone, flags);
2543         else
2544                 DNS_ZONE_CLRFLAG(zone, flags);
2545         UNLOCK_ZONE(zone);
2546 }
2547
2548 void
2549 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
2550 {
2551         REQUIRE(DNS_ZONE_VALID(zone));
2552
2553         LOCK_ZONE(zone);
2554         if (value)
2555                 zone->options |= option;
2556         else
2557                 zone->options &= ~option;
2558         UNLOCK_ZONE(zone);
2559 }
2560
2561 unsigned int
2562 dns_zone_getoptions(dns_zone_t *zone) {
2563
2564         REQUIRE(DNS_ZONE_VALID(zone));
2565
2566         return (zone->options);
2567 }
2568
2569 isc_result_t
2570 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
2571         REQUIRE(DNS_ZONE_VALID(zone));
2572
2573         LOCK_ZONE(zone);
2574         zone->xfrsource4 = *xfrsource;
2575         UNLOCK_ZONE(zone);
2576
2577         return (ISC_R_SUCCESS);
2578 }
2579
2580 isc_sockaddr_t *
2581 dns_zone_getxfrsource4(dns_zone_t *zone) {
2582         REQUIRE(DNS_ZONE_VALID(zone));
2583         return (&zone->xfrsource4);
2584 }
2585
2586 isc_result_t
2587 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
2588         REQUIRE(DNS_ZONE_VALID(zone));
2589
2590         LOCK_ZONE(zone);
2591         zone->xfrsource6 = *xfrsource;
2592         UNLOCK_ZONE(zone);
2593
2594         return (ISC_R_SUCCESS);
2595 }
2596
2597 isc_sockaddr_t *
2598 dns_zone_getxfrsource6(dns_zone_t *zone) {
2599         REQUIRE(DNS_ZONE_VALID(zone));
2600         return (&zone->xfrsource6);
2601 }
2602
2603 isc_result_t
2604 dns_zone_setaltxfrsource4(dns_zone_t *zone,
2605                           const isc_sockaddr_t *altxfrsource)
2606 {
2607         REQUIRE(DNS_ZONE_VALID(zone));
2608
2609         LOCK_ZONE(zone);
2610         zone->altxfrsource4 = *altxfrsource;
2611         UNLOCK_ZONE(zone);
2612
2613         return (ISC_R_SUCCESS);
2614 }
2615
2616 isc_sockaddr_t *
2617 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
2618         REQUIRE(DNS_ZONE_VALID(zone));
2619         return (&zone->altxfrsource4);
2620 }
2621
2622 isc_result_t
2623 dns_zone_setaltxfrsource6(dns_zone_t *zone,
2624                           const isc_sockaddr_t *altxfrsource)
2625 {
2626         REQUIRE(DNS_ZONE_VALID(zone));
2627
2628         LOCK_ZONE(zone);
2629         zone->altxfrsource6 = *altxfrsource;
2630         UNLOCK_ZONE(zone);
2631
2632         return (ISC_R_SUCCESS);
2633 }
2634
2635 isc_sockaddr_t *
2636 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
2637         REQUIRE(DNS_ZONE_VALID(zone));
2638         return (&zone->altxfrsource6);
2639 }
2640
2641 isc_result_t
2642 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
2643         REQUIRE(DNS_ZONE_VALID(zone));
2644
2645         LOCK_ZONE(zone);
2646         zone->notifysrc4 = *notifysrc;
2647         UNLOCK_ZONE(zone);
2648
2649         return (ISC_R_SUCCESS);
2650 }
2651
2652 isc_sockaddr_t *
2653 dns_zone_getnotifysrc4(dns_zone_t *zone) {
2654         REQUIRE(DNS_ZONE_VALID(zone));
2655         return (&zone->notifysrc4);
2656 }
2657
2658 isc_result_t
2659 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
2660         REQUIRE(DNS_ZONE_VALID(zone));
2661
2662         LOCK_ZONE(zone);
2663         zone->notifysrc6 = *notifysrc;
2664         UNLOCK_ZONE(zone);
2665
2666         return (ISC_R_SUCCESS);
2667 }
2668
2669 isc_sockaddr_t *
2670 dns_zone_getnotifysrc6(dns_zone_t *zone) {
2671         REQUIRE(DNS_ZONE_VALID(zone));
2672         return (&zone->notifysrc6);
2673 }
2674
2675 isc_result_t
2676 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
2677                        isc_uint32_t count)
2678 {
2679         isc_sockaddr_t *new;
2680
2681         REQUIRE(DNS_ZONE_VALID(zone));
2682         REQUIRE(count == 0 || notify != NULL);
2683
2684         LOCK_ZONE(zone);
2685         if (zone->notify != NULL) {
2686                 isc_mem_put(zone->mctx, zone->notify,
2687                             zone->notifycnt * sizeof(*new));
2688                 zone->notify = NULL;
2689                 zone->notifycnt = 0;
2690         }
2691         if (count != 0) {
2692                 new = isc_mem_get(zone->mctx, count * sizeof(*new));
2693                 if (new == NULL) {
2694                         UNLOCK_ZONE(zone);
2695                         return (ISC_R_NOMEMORY);
2696                 }
2697                 memcpy(new, notify, count * sizeof(*new));
2698                 zone->notify = new;
2699                 zone->notifycnt = count;
2700         }
2701         UNLOCK_ZONE(zone);
2702         return (ISC_R_SUCCESS);
2703 }
2704
2705 isc_result_t
2706 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
2707                     isc_uint32_t count)
2708 {
2709         isc_result_t result;
2710
2711         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
2712         return (result);
2713 }
2714
2715 static isc_boolean_t
2716 same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
2717              isc_uint32_t count)
2718 {
2719         unsigned int i;
2720
2721         for (i = 0; i < count; i++)
2722                 if (!isc_sockaddr_equal(&old[i], &new[i]))
2723                         return (ISC_FALSE);
2724         return (ISC_TRUE);
2725 }
2726
2727 static isc_boolean_t
2728 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
2729         unsigned int i;
2730
2731         if (old == NULL && new == NULL)
2732                 return (ISC_TRUE);
2733         if (old == NULL || new == NULL)
2734                 return (ISC_FALSE);
2735
2736         for (i = 0; i < count; i++) {
2737                 if (old[i] == NULL && new[i] == NULL)
2738                         continue;
2739                 if (old[i] == NULL || new[i] == NULL ||
2740                      !dns_name_equal(old[i], new[i]))
2741                         return (ISC_FALSE);
2742         }
2743         return (ISC_TRUE);
2744 }
2745
2746 isc_result_t
2747 dns_zone_setmasterswithkeys(dns_zone_t *zone,
2748                             const isc_sockaddr_t *masters,
2749                             dns_name_t **keynames,
2750                             isc_uint32_t count)
2751 {
2752         isc_sockaddr_t *new;
2753         isc_result_t result = ISC_R_SUCCESS;
2754         dns_name_t **newname;
2755         isc_boolean_t *newok;
2756         unsigned int i;
2757
2758         REQUIRE(DNS_ZONE_VALID(zone));
2759         REQUIRE(count == 0 || masters != NULL);
2760         if (keynames != NULL) {
2761                 REQUIRE(count != 0);
2762         }
2763
2764         LOCK_ZONE(zone);
2765         /*
2766          * The refresh code assumes that 'masters' wouldn't change under it.
2767          * If it will change then kill off any current refresh in progress
2768          * and update the masters info.  If it won't change then we can just
2769          * unlock and exit.
2770          */
2771         if (count != zone->masterscnt ||
2772             !same_masters(zone->masters, masters, count) ||
2773             !same_keynames(zone->masterkeynames, keynames, count)) {
2774                 if (zone->request != NULL)
2775                         dns_request_cancel(zone->request);
2776         } else
2777                 goto unlock;
2778         if (zone->masters != NULL) {
2779                 isc_mem_put(zone->mctx, zone->masters,
2780                             zone->masterscnt * sizeof(*new));
2781                 zone->masters = NULL;
2782         }
2783         if (zone->masterkeynames != NULL) {
2784                 for (i = 0; i < zone->masterscnt; i++) {
2785                         if (zone->masterkeynames[i] != NULL) {
2786                                 dns_name_free(zone->masterkeynames[i],
2787                                               zone->mctx);
2788                                 isc_mem_put(zone->mctx,
2789                                             zone->masterkeynames[i],
2790                                             sizeof(dns_name_t));
2791                                 zone->masterkeynames[i] = NULL;
2792                         }
2793                 }
2794                 isc_mem_put(zone->mctx, zone->masterkeynames,
2795                             zone->masterscnt * sizeof(dns_name_t *));
2796                 zone->masterkeynames = NULL;
2797         }
2798         if (zone->mastersok != NULL) {
2799                 isc_mem_put(zone->mctx, zone->mastersok,
2800                             zone->masterscnt * sizeof(isc_boolean_t));
2801                 zone->mastersok = NULL;
2802         }
2803         zone->masterscnt = 0;
2804         /*
2805          * If count == 0, don't allocate any space for masters, mastersok or
2806          * keynames so internally, those pointers are NULL if count == 0
2807          */
2808         if (count == 0)
2809                 goto unlock;
2810
2811         /*
2812          * masters must countain count elements!
2813          */
2814         new = isc_mem_get(zone->mctx, count * sizeof(*new));
2815         if (new == NULL) {
2816                 result = ISC_R_NOMEMORY;
2817                 goto unlock;
2818         }
2819         memcpy(new, masters, count * sizeof(*new));
2820
2821         /*
2822          * Similarly for mastersok.
2823          */
2824         newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
2825         if (newok == NULL) {
2826                 result = ISC_R_NOMEMORY;
2827                 isc_mem_put(zone->mctx, new, count * sizeof(*new));
2828                 goto unlock;
2829         };
2830         for (i = 0; i < count; i++)
2831                 newok[i] = ISC_FALSE;
2832
2833         /*
2834          * if keynames is non-NULL, it must contain count elements!
2835          */
2836         newname = NULL;
2837         if (keynames != NULL) {
2838                 newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
2839                 if (newname == NULL) {
2840                         result = ISC_R_NOMEMORY;
2841                         isc_mem_put(zone->mctx, new, count * sizeof(*new));
2842                         isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
2843                         goto unlock;
2844                 }
2845                 for (i = 0; i < count; i++)
2846                         newname[i] = NULL;
2847                 for (i = 0; i < count; i++) {
2848                         if (keynames[i] != NULL) {
2849                                 newname[i] = isc_mem_get(zone->mctx,
2850                                                          sizeof(dns_name_t));
2851                                 if (newname[i] == NULL)
2852                                         goto allocfail;
2853                                 dns_name_init(newname[i], NULL);
2854                                 result = dns_name_dup(keynames[i], zone->mctx,
2855                                                       newname[i]);
2856                                 if (result != ISC_R_SUCCESS) {
2857                                 allocfail:
2858                                         for (i = 0; i < count; i++)
2859                                                 if (newname[i] != NULL)
2860                                                         dns_name_free(
2861                                                                newname[i],
2862                                                                zone->mctx);
2863                                         isc_mem_put(zone->mctx, new,
2864                                                     count * sizeof(*new));
2865                                         isc_mem_put(zone->mctx, newok,
2866                                                     count * sizeof(*newok));
2867                                         isc_mem_put(zone->mctx, newname,
2868                                                     count * sizeof(*newname));
2869                                         goto unlock;
2870                                 }
2871                         }
2872                 }
2873         }
2874
2875         /*
2876          * Everything is ok so attach to the zone.
2877          */
2878         zone->masters = new;
2879         zone->mastersok = newok;
2880         zone->masterkeynames = newname;
2881         zone->masterscnt = count;
2882         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
2883
2884  unlock:
2885         UNLOCK_ZONE(zone);
2886         return (result);
2887 }
2888
2889 isc_result_t
2890 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
2891         isc_result_t result = ISC_R_SUCCESS;
2892
2893         REQUIRE(DNS_ZONE_VALID(zone));
2894
2895         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2896         if (zone->db == NULL)
2897                 result = DNS_R_NOTLOADED;
2898         else
2899                 dns_db_attach(zone->db, dpb);
2900         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2901
2902         return (result);
2903 }
2904
2905 /*
2906  * Co-ordinates the starting of routine jobs.
2907  */
2908
2909 void
2910 dns_zone_maintenance(dns_zone_t *zone) {
2911         const char me[] = "dns_zone_maintenance";
2912         isc_time_t now;
2913
2914         REQUIRE(DNS_ZONE_VALID(zone));
2915         ENTER;
2916
2917         LOCK_ZONE(zone);
2918         TIME_NOW(&now);
2919         zone_settimer(zone, &now);
2920         UNLOCK_ZONE(zone);
2921 }
2922
2923 static inline isc_boolean_t
2924 was_dumping(dns_zone_t *zone) {
2925         isc_boolean_t dumping;
2926
2927         REQUIRE(LOCKED_ZONE(zone));
2928
2929         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
2930         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
2931         if (!dumping) {
2932                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2933                 isc_time_settoepoch(&zone->dumptime);
2934         }
2935         return (dumping);
2936 }
2937
2938 static void
2939 zone_maintenance(dns_zone_t *zone) {
2940         const char me[] = "zone_maintenance";
2941         isc_time_t now;
2942         isc_result_t result;
2943         isc_boolean_t dumping;
2944
2945         REQUIRE(DNS_ZONE_VALID(zone));
2946         ENTER;
2947
2948         /*
2949          * Configuring the view of this zone may have
2950          * failed, for example because the config file
2951          * had a syntax error.  In that case, the view
2952          * adb or resolver, and we had better not try
2953          * to do maintenance on it.
2954          */
2955         if (zone->view == NULL || zone->view->adb == NULL)
2956                 return;
2957
2958         TIME_NOW(&now);
2959
2960         /*
2961          * Expire check.
2962          */
2963         switch (zone->type) {
2964         case dns_zone_slave:
2965         case dns_zone_stub:
2966                 LOCK_ZONE(zone);
2967                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
2968                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
2969                         zone_expire(zone);
2970                         zone->refreshtime = now;
2971                 }
2972                 UNLOCK_ZONE(zone);
2973                 break;
2974         default:
2975                 break;
2976         }
2977
2978         /*
2979          * Up to date check.
2980          */
2981         switch (zone->type) {
2982         case dns_zone_slave:
2983         case dns_zone_stub:
2984                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
2985                     isc_time_compare(&now, &zone->refreshtime) >= 0)
2986                         dns_zone_refresh(zone);
2987                 break;
2988         default:
2989                 break;
2990         }
2991
2992         /*
2993          * Do we need to consolidate the backing store?
2994          */
2995         switch (zone->type) {
2996         case dns_zone_master:
2997         case dns_zone_slave:
2998                 LOCK_ZONE(zone);
2999                 if (zone->masterfile != NULL &&
3000                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
3001                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
3002                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
3003                         dumping = was_dumping(zone);
3004                 } else
3005                         dumping = ISC_TRUE;
3006                 UNLOCK_ZONE(zone);
3007                 if (!dumping) {
3008                         result = zone_dump(zone, ISC_TRUE); /* task locked */
3009                         if (result != ISC_R_SUCCESS)
3010                                 dns_zone_log(zone, ISC_LOG_WARNING,
3011                                              "dump failed: %s",
3012                                              dns_result_totext(result));
3013                 }
3014                 break;
3015         default:
3016                 break;
3017         }
3018
3019         /*
3020          * Do we need to send out notify messages?
3021          */
3022         switch (zone->type) {
3023         case dns_zone_master:
3024         case dns_zone_slave:
3025                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
3026                     isc_time_compare(&now, &zone->notifytime) >= 0)
3027                         zone_notify(zone, &now);
3028                 break;
3029         default:
3030                 break;
3031         }
3032         zone_settimer(zone, &now);
3033 }
3034
3035 void
3036 dns_zone_markdirty(dns_zone_t *zone) {
3037
3038         LOCK_ZONE(zone);
3039         zone_needdump(zone, DNS_DUMP_DELAY);
3040         UNLOCK_ZONE(zone);
3041 }
3042
3043 void
3044 dns_zone_expire(dns_zone_t *zone) {
3045         REQUIRE(DNS_ZONE_VALID(zone));
3046
3047         LOCK_ZONE(zone);
3048         zone_expire(zone);
3049         UNLOCK_ZONE(zone);
3050 }
3051
3052 static void
3053 zone_expire(dns_zone_t *zone) {
3054         /*
3055          * 'zone' locked by caller.
3056          */
3057
3058         REQUIRE(LOCKED_ZONE(zone));
3059
3060         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
3061
3062         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
3063         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
3064         zone->retry = DNS_ZONE_DEFAULTRETRY;
3065         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
3066         zone_unload(zone);
3067 }
3068
3069 void
3070 dns_zone_refresh(dns_zone_t *zone) {
3071         isc_interval_t i;
3072         isc_uint32_t oldflags;
3073         unsigned int j;
3074         isc_result_t result;
3075
3076         REQUIRE(DNS_ZONE_VALID(zone));
3077
3078         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
3079                 return;
3080
3081         /*
3082          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
3083          * in progress at a time.
3084          */
3085
3086         LOCK_ZONE(zone);
3087         oldflags = zone->flags;
3088         if (zone->masterscnt == 0) {
3089                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
3090                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
3091                         dns_zone_log(zone, ISC_LOG_ERROR,
3092                                      "cannot refresh: no masters");
3093                 goto unlock;
3094         }
3095         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
3096         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
3097         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
3098         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
3099                 goto unlock;
3100
3101         /*
3102          * Set the next refresh time as if refresh check has failed.
3103          * Setting this to the retry time will do that.  XXXMLG
3104          * If we are successful it will be reset using zone->refresh.
3105          */
3106         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
3107                          0);
3108         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
3109         if (result |= ISC_R_SUCCESS)
3110                 dns_zone_log(zone, ISC_LOG_WARNING,
3111                              "isc_time_nowplusinterval() failed: %s",
3112                              dns_result_totext(result));
3113
3114         /*
3115          * When lacking user-specified timer values from the SOA,
3116          * do exponential backoff of the retry time up to a
3117          * maximum of six hours.
3118          */
3119         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
3120                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
3121
3122         zone->curmaster = 0;
3123         for (j = 0; j < zone->masterscnt; j++)
3124                 zone->mastersok[j] = ISC_FALSE;
3125         /* initiate soa query */
3126         queue_soa_query(zone);
3127  unlock:
3128         UNLOCK_ZONE(zone);
3129 }
3130
3131 isc_result_t
3132 dns_zone_flush(dns_zone_t *zone) {
3133         isc_result_t result = ISC_R_SUCCESS;
3134         isc_boolean_t dumping;
3135
3136         REQUIRE(DNS_ZONE_VALID(zone));
3137
3138         LOCK_ZONE(zone);
3139         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
3140         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
3141             zone->masterfile != NULL) {
3142                 result = ISC_R_ALREADYRUNNING;
3143                 dumping = was_dumping(zone);
3144         } else
3145                 dumping = ISC_TRUE;
3146         UNLOCK_ZONE(zone);
3147         if (!dumping)
3148                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
3149         return (result);
3150 }
3151
3152 isc_result_t
3153 dns_zone_dump(dns_zone_t *zone) {
3154         isc_result_t result = ISC_R_ALREADYRUNNING;
3155         isc_boolean_t dumping;
3156
3157         REQUIRE(DNS_ZONE_VALID(zone));
3158
3159         LOCK_ZONE(zone);
3160         dumping = was_dumping(zone);
3161         UNLOCK_ZONE(zone);
3162         if (!dumping)
3163                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
3164         return (result);
3165 }
3166
3167 static void
3168 zone_needdump(dns_zone_t *zone, unsigned int delay) {
3169         isc_time_t dumptime;
3170         isc_time_t now;
3171
3172         /*
3173          * 'zone' locked by caller
3174          */
3175
3176         REQUIRE(DNS_ZONE_VALID(zone));
3177         REQUIRE(LOCKED_ZONE(zone));
3178
3179         /*
3180          * Do we have a place to dump to and are we loaded?
3181          */
3182         if (zone->masterfile == NULL ||
3183             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
3184                 return;
3185
3186         TIME_NOW(&now);
3187         /* add some noise */
3188         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
3189
3190         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3191         if (isc_time_isepoch(&zone->dumptime) ||
3192             isc_time_compare(&zone->dumptime, &dumptime) > 0)
3193                 zone->dumptime = dumptime;
3194         if (zone->task != NULL)
3195                 zone_settimer(zone, &now);
3196 }
3197
3198 static void
3199 dump_done(void *arg, isc_result_t result) {
3200         const char me[] = "dump_done";
3201         dns_zone_t *zone = arg;
3202         dns_db_t *db;
3203         dns_dbversion_t *version;
3204         isc_boolean_t again = ISC_FALSE;
3205         isc_boolean_t compact = ISC_FALSE;
3206         isc_uint32_t serial;
3207         isc_result_t tresult;
3208
3209         REQUIRE(DNS_ZONE_VALID(zone));
3210
3211         ENTER;
3212
3213         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
3214             zone->journalsize != -1) {
3215
3216                 /*
3217                  * We don't own these, zone->dctx must stay valid.
3218                  */
3219                 db = dns_dumpctx_db(zone->dctx);
3220                 version = dns_dumpctx_version(zone->dctx);
3221
3222                 tresult = dns_db_getsoaserial(db, version, &serial);
3223                 /*
3224                  * Note: we are task locked here so we can test
3225                  * zone->xfr safely.
3226                  */
3227                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
3228                         tresult = dns_journal_compact(zone->mctx,
3229                                                       zone->journal,
3230                                                       serial,
3231                                                       zone->journalsize);
3232                         switch (tresult) {
3233                         case ISC_R_SUCCESS:
3234                         case ISC_R_NOSPACE:
3235                         case ISC_R_NOTFOUND:
3236                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
3237                                              "dns_journal_compact: %s",
3238                                              dns_result_totext(tresult));
3239                                 break;
3240                         default:
3241                                 dns_zone_log(zone, ISC_LOG_ERROR,
3242                                              "dns_journal_compact failed: %s",
3243                                              dns_result_totext(tresult));
3244                                 break;
3245                         }
3246                 } else if (tresult == ISC_R_SUCCESS) {
3247                         compact = ISC_TRUE;
3248                         zone->compact_serial = serial;
3249                 }
3250         }
3251
3252         LOCK_ZONE(zone);
3253         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
3254         if (compact)
3255                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
3256         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
3257                 /*
3258                  * Try again in a short while.
3259                  */
3260                 zone_needdump(zone, DNS_DUMP_DELAY);
3261         } else if (result == ISC_R_SUCCESS &&
3262                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
3263                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
3264                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3265                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3266                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
3267                 isc_time_settoepoch(&zone->dumptime);
3268                 again = ISC_TRUE;
3269         } else if (result == ISC_R_SUCCESS)
3270                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
3271
3272         if (zone->dctx != NULL)
3273                 dns_dumpctx_detach(&zone->dctx);
3274         zonemgr_putio(&zone->writeio);
3275         UNLOCK_ZONE(zone);
3276         if (again)
3277                 (void)zone_dump(zone, ISC_FALSE);
3278         dns_zone_idetach(&zone);
3279 }
3280
3281 static isc_result_t
3282 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
3283         const char me[] = "zone_dump";
3284         isc_result_t result;
3285         dns_dbversion_t *version = NULL;
3286         isc_boolean_t again;
3287         dns_db_t *db = NULL;
3288         char *masterfile = NULL;
3289         dns_masterformat_t masterformat = dns_masterformat_none;
3290
3291 /*
3292  * 'compact' MUST only be set if we are task locked.
3293  */
3294
3295         REQUIRE(DNS_ZONE_VALID(zone));
3296         ENTER;
3297
3298  redo:
3299         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3300         if (zone->db != NULL)
3301                 dns_db_attach(zone->db, &db);
3302         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3303         LOCK_ZONE(zone);
3304         if (zone->masterfile != NULL) {
3305                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
3306                 masterformat = zone->masterformat;
3307         }
3308         UNLOCK_ZONE(zone);
3309         if (db == NULL) {
3310                 result = DNS_R_NOTLOADED;
3311                 goto fail;
3312         }
3313         if (masterfile == NULL) {
3314                 result = DNS_R_NOMASTERFILE;
3315                 goto fail;
3316         }
3317
3318         if (compact) {
3319                 dns_zone_t *dummy = NULL;
3320                 LOCK_ZONE(zone);
3321                 zone_iattach(zone, &dummy);
3322                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
3323                                        zone_gotwritehandle, zone,
3324                                        &zone->writeio);
3325                 if (result != ISC_R_SUCCESS)
3326                         zone_idetach(&dummy);
3327                 else
3328                         result = DNS_R_CONTINUE;
3329                 UNLOCK_ZONE(zone);
3330         } else {
3331                 dns_db_currentversion(db, &version);
3332                 result = dns_master_dump2(zone->mctx, db, version,
3333                                           &dns_master_style_default,
3334                                           masterfile, masterformat);
3335                 dns_db_closeversion(db, &version, ISC_FALSE);
3336         }
3337  fail:
3338         if (db != NULL)
3339                 dns_db_detach(&db);
3340         if (masterfile != NULL)
3341                 isc_mem_free(zone->mctx, masterfile);
3342         masterfile = NULL;
3343
3344         if (result == DNS_R_CONTINUE)
3345                 return (ISC_R_SUCCESS); /* XXXMPA */
3346
3347         again = ISC_FALSE;
3348         LOCK_ZONE(zone);
3349         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
3350         if (result != ISC_R_SUCCESS) {
3351                 /*
3352                  * Try again in a short while.
3353                  */
3354                 zone_needdump(zone, DNS_DUMP_DELAY);
3355         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
3356                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
3357                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3358                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3359                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
3360                 isc_time_settoepoch(&zone->dumptime);
3361                 again = ISC_TRUE;
3362         } else
3363                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
3364         UNLOCK_ZONE(zone);
3365         if (again)
3366                 goto redo;
3367
3368         return (result);
3369 }
3370
3371 static isc_result_t
3372 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
3373              dns_masterformat_t format)
3374 {
3375         isc_result_t result;
3376         dns_dbversion_t *version = NULL;
3377         dns_db_t *db = NULL;
3378
3379         REQUIRE(DNS_ZONE_VALID(zone));
3380
3381         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3382         if (zone->db != NULL)
3383                 dns_db_attach(zone->db, &db);
3384         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3385         if (db == NULL)
3386                 return (DNS_R_NOTLOADED);
3387
3388         dns_db_currentversion(db, &version);
3389         result = dns_master_dumptostream2(zone->mctx, db, version, style,
3390                                           format, fd);
3391         dns_db_closeversion(db, &version, ISC_FALSE);
3392         dns_db_detach(&db);
3393         return (result);
3394 }
3395
3396 isc_result_t
3397 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
3398                        const dns_master_style_t *style) {
3399         return dumptostream(zone, fd, style, format);
3400 }
3401
3402 isc_result_t
3403 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
3404         return dumptostream(zone, fd, &dns_master_style_default,
3405                             dns_masterformat_text);
3406 }
3407
3408 isc_result_t
3409 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
3410         return dumptostream(zone, fd, &dns_master_style_full,
3411                             dns_masterformat_text);
3412 }
3413
3414 void
3415 dns_zone_unload(dns_zone_t *zone) {
3416         REQUIRE(DNS_ZONE_VALID(zone));
3417
3418         LOCK_ZONE(zone);
3419         zone_unload(zone);
3420         UNLOCK_ZONE(zone);
3421 }
3422
3423 static void
3424 notify_cancel(dns_zone_t *zone) {
3425         dns_notify_t *notify;
3426
3427         /*
3428          * 'zone' locked by caller.
3429          */
3430
3431         REQUIRE(LOCKED_ZONE(zone));
3432
3433         for (notify = ISC_LIST_HEAD(zone->notifies);
3434              notify != NULL;
3435              notify = ISC_LIST_NEXT(notify, link)) {
3436                 if (notify->find != NULL)
3437                         dns_adb_cancelfind(notify->find);
3438                 if (notify->request != NULL)
3439                         dns_request_cancel(notify->request);
3440         }
3441 }
3442
3443 static void
3444 zone_unload(dns_zone_t *zone) {
3445
3446         /*
3447          * 'zone' locked by caller.
3448          */
3449
3450         REQUIRE(LOCKED_ZONE(zone));
3451
3452         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
3453         zone_detachdb(zone);
3454         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3455         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
3456         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3457 }
3458
3459 void
3460 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
3461         REQUIRE(DNS_ZONE_VALID(zone));
3462         REQUIRE(val > 0);
3463
3464         zone->minrefresh = val;
3465 }
3466
3467 void
3468 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
3469         REQUIRE(DNS_ZONE_VALID(zone));
3470         REQUIRE(val > 0);
3471
3472         zone->maxrefresh = val;
3473 }
3474
3475 void
3476 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
3477         REQUIRE(DNS_ZONE_VALID(zone));
3478         REQUIRE(val > 0);
3479
3480         zone->minretry = val;
3481 }
3482
3483 void
3484 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
3485         REQUIRE(DNS_ZONE_VALID(zone));
3486         REQUIRE(val > 0);
3487
3488         zone->maxretry = val;
3489 }
3490
3491 static isc_boolean_t
3492 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
3493         dns_notify_t *notify;
3494
3495         for (notify = ISC_LIST_HEAD(zone->notifies);
3496              notify != NULL;
3497              notify = ISC_LIST_NEXT(notify, link)) {
3498                 if (notify->request != NULL)
3499                         continue;
3500                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
3501                     dns_name_equal(name, &notify->ns))
3502                         return (ISC_TRUE);
3503                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
3504                         return (ISC_TRUE);
3505         }
3506         return (ISC_FALSE);
3507 }
3508
3509 static isc_boolean_t
3510 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
3511         dns_tsigkey_t *key = NULL;
3512         isc_sockaddr_t src;
3513         isc_sockaddr_t any;
3514         isc_boolean_t isself;
3515         isc_netaddr_t dstaddr;
3516
3517         if (zone->view == NULL || zone->isself == NULL)
3518                 return (ISC_FALSE);
3519
3520         switch (isc_sockaddr_pf(dst)) {
3521         case PF_INET:
3522                 src = zone->notifysrc4;
3523                 isc_sockaddr_any(&any);
3524                 break;
3525         case PF_INET6:
3526                 src = zone->notifysrc6;
3527                 isc_sockaddr_any6(&any);
3528                 break;
3529         default:
3530                 return (ISC_FALSE);
3531         }
3532
3533         /*
3534          * When sending from any the kernel will assign a source address
3535          * that matches the destination address.
3536          */
3537         if (isc_sockaddr_eqaddr(&any, &src))
3538                 src = *dst;
3539
3540         isc_netaddr_fromsockaddr(&dstaddr, dst);
3541         (void)dns_view_getpeertsig(zone->view, &dstaddr, &key);
3542         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
3543                                 zone->isselfarg);
3544         if (key != NULL)
3545                 dns_tsigkey_detach(&key);
3546         return (isself);
3547 }
3548
3549 static void
3550 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
3551         isc_mem_t *mctx;
3552
3553         /*
3554          * Caller holds zone lock.
3555          */
3556         REQUIRE(DNS_NOTIFY_VALID(notify));
3557
3558         if (notify->zone != NULL) {
3559                 if (!locked)
3560                         LOCK_ZONE(notify->zone);
3561                 REQUIRE(LOCKED_ZONE(notify->zone));
3562                 if (ISC_LINK_LINKED(notify, link))
3563                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
3564                 if (!locked)
3565                         UNLOCK_ZONE(notify->zone);
3566                 if (locked)
3567                         zone_idetach(&notify->zone);
3568                 else
3569                         dns_zone_idetach(&notify->zone);
3570         }
3571         if (notify->find != NULL)
3572                 dns_adb_destroyfind(&notify->find);
3573         if (notify->request != NULL)
3574                 dns_request_destroy(&notify->request);
3575         if (dns_name_dynamic(&notify->ns))
3576                 dns_name_free(&notify->ns, notify->mctx);
3577         mctx = notify->mctx;
3578         isc_mem_put(notify->mctx, notify, sizeof(*notify));
3579         isc_mem_detach(&mctx);
3580 }
3581
3582 static isc_result_t
3583 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
3584         dns_notify_t *notify;
3585
3586         REQUIRE(notifyp != NULL && *notifyp == NULL);
3587
3588         notify = isc_mem_get(mctx, sizeof(*notify));
3589         if (notify == NULL)
3590                 return (ISC_R_NOMEMORY);
3591
3592         notify->mctx = NULL;
3593         isc_mem_attach(mctx, &notify->mctx);
3594         notify->flags = flags;
3595         notify->zone = NULL;
3596         notify->find = NULL;
3597         notify->request = NULL;
3598         isc_sockaddr_any(&notify->dst);
3599         dns_name_init(&notify->ns, NULL);
3600         ISC_LINK_INIT(notify, link);
3601         notify->magic = NOTIFY_MAGIC;
3602         *notifyp = notify;
3603         return (ISC_R_SUCCESS);
3604 }
3605
3606 /*
3607  * XXXAG should check for DNS_ZONEFLG_EXITING
3608  */
3609 static void
3610 process_adb_event(isc_task_t *task, isc_event_t *ev) {
3611         dns_notify_t *notify;
3612         isc_eventtype_t result;
3613
3614         UNUSED(task);
3615
3616         notify = ev->ev_arg;
3617         REQUIRE(DNS_NOTIFY_VALID(notify));
3618         INSIST(task == notify->zone->task);
3619         result = ev->ev_type;
3620         isc_event_free(&ev);
3621         if (result == DNS_EVENT_ADBMOREADDRESSES) {
3622                 dns_adb_destroyfind(&notify->find);
3623                 notify_find_address(notify);
3624                 return;
3625         }
3626         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
3627                 LOCK_ZONE(notify->zone);
3628                 notify_send(notify);
3629                 UNLOCK_ZONE(notify->zone);
3630         }
3631         notify_destroy(notify, ISC_FALSE);
3632 }
3633
3634 static void
3635 notify_find_address(dns_notify_t *notify) {
3636         isc_result_t result;
3637         unsigned int options;
3638
3639         REQUIRE(DNS_NOTIFY_VALID(notify));
3640         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
3641                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
3642
3643         if (notify->zone->view->adb == NULL)
3644                 goto destroy;
3645
3646         result = dns_adb_createfind(notify->zone->view->adb,
3647                                     notify->zone->task,
3648                                     process_adb_event, notify,
3649                                     &notify->ns, dns_rootname, 0,
3650                                     options, 0, NULL,
3651                                     notify->zone->view->dstport,
3652                                     &notify->find);
3653
3654         /* Something failed? */
3655         if (result != ISC_R_SUCCESS)
3656                 goto destroy;
3657
3658         /* More addresses pending? */
3659         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
3660                 return;
3661
3662         /* We have as many addresses as we can get. */
3663         LOCK_ZONE(notify->zone);
3664         notify_send(notify);
3665         UNLOCK_ZONE(notify->zone);
3666
3667  destroy:
3668         notify_destroy(notify, ISC_FALSE);
3669 }
3670
3671
3672 static isc_result_t
3673 notify_send_queue(dns_notify_t *notify) {
3674         isc_event_t *e;
3675         isc_result_t result;
3676
3677         e = isc_event_allocate(notify->mctx, NULL,
3678                                DNS_EVENT_NOTIFYSENDTOADDR,
3679                                notify_send_toaddr,
3680                                notify, sizeof(isc_event_t));
3681         if (e == NULL)
3682                 return (ISC_R_NOMEMORY);
3683         e->ev_arg = notify;
3684         e->ev_sender = NULL;
3685         result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
3686                                          notify->zone->task, &e);
3687         if (result != ISC_R_SUCCESS)
3688                 isc_event_free(&e);
3689         return (result);
3690 }
3691
3692 static void
3693 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
3694         dns_notify_t *notify;
3695         isc_result_t result;
3696         dns_message_t *message = NULL;
3697         isc_netaddr_t dstip;
3698         dns_tsigkey_t *key = NULL;
3699         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
3700         isc_sockaddr_t src;
3701         int timeout;
3702         isc_boolean_t have_notifysource = ISC_FALSE;
3703
3704         notify = event->ev_arg;
3705         REQUIRE(DNS_NOTIFY_VALID(notify));
3706
3707         UNUSED(task);
3708
3709         LOCK_ZONE(notify->zone);
3710
3711         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
3712                 result = ISC_R_CANCELED;
3713                 goto cleanup;
3714         }
3715
3716         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
3717             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
3718             notify->zone->view->requestmgr == NULL ||
3719             notify->zone->db == NULL) {
3720                 result = ISC_R_CANCELED;
3721                 goto cleanup;
3722         }
3723
3724         /*
3725          * The raw IPv4 address should also exist.  Don't send to the
3726          * mapped form.
3727          */
3728         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
3729             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
3730                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
3731                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
3732                            "notify: ignoring IPv6 mapped IPV4 address: %s",
3733                            addrbuf);
3734                 result = ISC_R_CANCELED;
3735                 goto cleanup;
3736         }
3737
3738         result = notify_createmessage(notify->zone, notify->flags, &message);
3739         if (result != ISC_R_SUCCESS)
3740                 goto cleanup;
3741
3742         isc_netaddr_fromsockaddr(&dstip, &notify->dst);
3743         (void)dns_view_getpeertsig(notify->zone->view, &dstip, &key);
3744
3745         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
3746         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
3747                    addrbuf);
3748         if (notify->zone->view->peers != NULL) {
3749                 dns_peer_t *peer = NULL;
3750                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
3751                                                  &dstip, &peer);
3752                 if (result == ISC_R_SUCCESS) {
3753                         result = dns_peer_getnotifysource(peer, &src);
3754                         if (result == ISC_R_SUCCESS)
3755                                 have_notifysource = ISC_TRUE;
3756                 }
3757         }
3758         switch (isc_sockaddr_pf(&notify->dst)) {
3759         case PF_INET:
3760                 if (!have_notifysource)
3761                         src = notify->zone->notifysrc4;
3762                 break;
3763         case PF_INET6:
3764                 if (!have_notifysource)
3765                         src = notify->zone->notifysrc6;
3766                 break;
3767         default:
3768                 result = ISC_R_NOTIMPLEMENTED;
3769                 goto cleanup_key;
3770         }
3771         timeout = 15;
3772         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
3773                 timeout = 30;
3774         result = dns_request_createvia2(notify->zone->view->requestmgr,
3775                                         message, &src, &notify->dst, 0, key,
3776                                         timeout * 3, timeout,
3777                                         notify->zone->task, notify_done,
3778                                         notify, &notify->request);
3779  cleanup_key:
3780         if (key != NULL)
3781                 dns_tsigkey_detach(&key);
3782         dns_message_destroy(&message);
3783  cleanup:
3784         UNLOCK_ZONE(notify->zone);
3785         if (result != ISC_R_SUCCESS)
3786                 notify_destroy(notify, ISC_FALSE);
3787         isc_event_free(&event);
3788 }
3789
3790 static void
3791 notify_send(dns_notify_t *notify) {
3792         dns_adbaddrinfo_t *ai;
3793         isc_sockaddr_t dst;
3794         isc_result_t result;
3795         dns_notify_t *new = NULL;
3796
3797         /*
3798          * Zone lock held by caller.
3799          */
3800         REQUIRE(DNS_NOTIFY_VALID(notify));
3801         REQUIRE(LOCKED_ZONE(notify->zone));
3802
3803         for (ai = ISC_LIST_HEAD(notify->find->list);
3804              ai != NULL;
3805              ai = ISC_LIST_NEXT(ai, publink)) {
3806                 dst = ai->sockaddr;
3807                 if (notify_isqueued(notify->zone, NULL, &dst))
3808                         continue;
3809                 if (notify_isself(notify->zone, &dst))
3810                         continue;
3811                 new = NULL;
3812                 result = notify_create(notify->mctx,
3813                                        (notify->flags & DNS_NOTIFY_NOSOA),
3814                                        &new);
3815                 if (result != ISC_R_SUCCESS)
3816                         goto cleanup;
3817                 zone_iattach(notify->zone, &new->zone);
3818                 ISC_LIST_APPEND(new->zone->notifies, new, link);
3819                 new->dst = dst;
3820                 result = notify_send_queue(new);
3821                 if (result != ISC_R_SUCCESS)
3822                         goto cleanup;
3823                 new = NULL;
3824         }
3825
3826  cleanup:
3827         if (new != NULL)
3828                 notify_destroy(new, ISC_TRUE);
3829 }
3830
3831 void
3832 dns_zone_notify(dns_zone_t *zone) {
3833         isc_time_t now;
3834
3835         REQUIRE(DNS_ZONE_VALID(zone));
3836
3837         LOCK_ZONE(zone);
3838         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
3839
3840         TIME_NOW(&now);
3841         zone_settimer(zone, &now);
3842         UNLOCK_ZONE(zone);
3843 }
3844
3845 static void
3846 zone_notify(dns_zone_t *zone, isc_time_t *now) {
3847         dns_dbnode_t *node = NULL;
3848         dns_db_t *zonedb = NULL;
3849         dns_dbversion_t *version = NULL;
3850         dns_name_t *origin = NULL;
3851         dns_name_t master;
3852         dns_rdata_ns_t ns;
3853         dns_rdata_soa_t soa;
3854         isc_uint32_t serial;
3855         dns_rdata_t rdata = DNS_RDATA_INIT;
3856         dns_rdataset_t nsrdset;
3857         dns_rdataset_t soardset;
3858         isc_result_t result;
3859         dns_notify_t *notify = NULL;
3860         unsigned int i;
3861         isc_sockaddr_t dst;
3862         isc_boolean_t isqueued;
3863         dns_notifytype_t notifytype;
3864         unsigned int flags = 0;
3865         isc_boolean_t loggednotify = ISC_FALSE;
3866
3867         REQUIRE(DNS_ZONE_VALID(zone));
3868
3869         LOCK_ZONE(zone);
3870         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
3871         notifytype = zone->notifytype;
3872         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
3873         UNLOCK_ZONE(zone);
3874
3875         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3876                 return;
3877
3878         if (notifytype == dns_notifytype_no)
3879                 return;
3880
3881         if (notifytype == dns_notifytype_masteronly &&
3882             zone->type != dns_zone_master)
3883                 return;
3884
3885         origin = &zone->origin;
3886
3887         /*
3888          * If the zone is dialup we are done as we don't want to send
3889          * the current soa so as to force a refresh query.
3890          */
3891         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
3892                 flags |= DNS_NOTIFY_NOSOA;
3893
3894         /*
3895          * Get SOA RRset.
3896          */
3897         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3898         if (zone->db != NULL)
3899                 dns_db_attach(zone->db, &zonedb);
3900         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3901         if (zonedb == NULL)
3902                 return;
3903         dns_db_currentversion(zonedb, &version);
3904         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
3905         if (result != ISC_R_SUCCESS)
3906                 goto cleanup1;
3907
3908         dns_rdataset_init(&soardset);
3909         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
3910                                      dns_rdatatype_none, 0, &soardset, NULL);
3911         if (result != ISC_R_SUCCESS)
3912                 goto cleanup2;
3913
3914         /*
3915          * Find serial and master server's name.
3916          */
3917         dns_name_init(&master, NULL);
3918         result = dns_rdataset_first(&soardset);
3919         if (result != ISC_R_SUCCESS)
3920                 goto cleanup3;
3921         dns_rdataset_current(&soardset, &rdata);
3922         result = dns_rdata_tostruct(&rdata, &soa, NULL);
3923         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3924         dns_rdata_reset(&rdata);
3925         result = dns_name_dup(&soa.origin, zone->mctx, &master);
3926         serial = soa.serial;
3927         dns_rdataset_disassociate(&soardset);
3928         if (result != ISC_R_SUCCESS)
3929                 goto cleanup3;
3930
3931         /*
3932          * Enqueue notify requests for 'also-notify' servers.
3933          */
3934         LOCK_ZONE(zone);
3935         for (i = 0; i < zone->notifycnt; i++) {
3936                 dst = zone->notify[i];
3937                 if (notify_isqueued(zone, NULL, &dst))
3938                         continue;
3939                 result = notify_create(zone->mctx, flags, &notify);
3940                 if (result != ISC_R_SUCCESS)
3941                         continue;
3942                 zone_iattach(zone, &notify->zone);
3943                 notify->dst = dst;
3944                 ISC_LIST_APPEND(zone->notifies, notify, link);
3945                 result = notify_send_queue(notify);
3946                 if (result != ISC_R_SUCCESS)
3947                         notify_destroy(notify, ISC_TRUE);
3948                 if (!loggednotify) {
3949                         notify_log(zone, ISC_LOG_INFO,
3950                                    "sending notifies (serial %u)",
3951                                    serial);
3952                         loggednotify = ISC_TRUE;
3953                 }
3954                 notify = NULL;
3955         }
3956         UNLOCK_ZONE(zone);
3957
3958         if (notifytype == dns_notifytype_explicit)
3959                 goto cleanup3;
3960
3961         /*
3962          * Process NS RRset to generate notifies.
3963          */
3964
3965         dns_rdataset_init(&nsrdset);
3966         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
3967                                      dns_rdatatype_none, 0, &nsrdset, NULL);
3968         if (result != ISC_R_SUCCESS)
3969                 goto cleanup3;
3970
3971         result = dns_rdataset_first(&nsrdset);
3972         while (result == ISC_R_SUCCESS) {
3973                 dns_rdataset_current(&nsrdset, &rdata);
3974                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3975                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3976                 dns_rdata_reset(&rdata);
3977                 /*
3978                  * don't notify the master server.
3979                  */
3980                 if (dns_name_compare(&master, &ns.name) == 0) {
3981                         result = dns_rdataset_next(&nsrdset);
3982                         continue;
3983                 }
3984
3985                 if (!loggednotify) {
3986                         notify_log(zone, ISC_LOG_INFO,
3987                                    "sending notifies (serial %u)",
3988                                    serial);
3989                         loggednotify = ISC_TRUE;
3990                 }
3991
3992                 LOCK_ZONE(zone);
3993                 isqueued = notify_isqueued(zone, &ns.name, NULL);
3994                 UNLOCK_ZONE(zone);
3995                 if (isqueued) {
3996                         result = dns_rdataset_next(&nsrdset);
3997                         continue;
3998                 }
3999                 result = notify_create(zone->mctx, flags, &notify);
4000                 if (result != ISC_R_SUCCESS)
4001                         continue;
4002                 dns_zone_iattach(zone, &notify->zone);
4003                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
4004                 if (result != ISC_R_SUCCESS) {
4005                         LOCK_ZONE(zone);
4006                         notify_destroy(notify, ISC_TRUE);
4007                         UNLOCK_ZONE(zone);
4008                         continue;
4009                 }
4010                 LOCK_ZONE(zone);
4011                 ISC_LIST_APPEND(zone->notifies, notify, link);
4012                 UNLOCK_ZONE(zone);
4013                 notify_find_address(notify);
4014                 notify = NULL;
4015                 result = dns_rdataset_next(&nsrdset);
4016         }
4017         dns_rdataset_disassociate(&nsrdset);
4018
4019  cleanup3:
4020         if (dns_name_dynamic(&master))
4021                 dns_name_free(&master, zone->mctx);
4022  cleanup2:
4023         dns_db_detachnode(zonedb, &node);
4024  cleanup1:
4025         dns_db_closeversion(zonedb, &version, ISC_FALSE);
4026         dns_db_detach(&zonedb);
4027 }
4028
4029 /***
4030  *** Private
4031  ***/
4032
4033 static inline isc_result_t
4034 save_nsrrset(dns_message_t *message, dns_name_t *name,
4035              dns_db_t *db, dns_dbversion_t *version)
4036 {
4037         dns_rdataset_t *nsrdataset = NULL;
4038         dns_rdataset_t *rdataset = NULL;
4039         dns_dbnode_t *node = NULL;
4040         dns_rdata_ns_t ns;
4041         isc_result_t result;
4042         dns_rdata_t rdata = DNS_RDATA_INIT;
4043
4044         /*
4045          * Extract NS RRset from message.
4046          */
4047         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
4048                                       dns_rdatatype_ns, dns_rdatatype_none,
4049                                       NULL, &nsrdataset);
4050         if (result != ISC_R_SUCCESS)
4051                 goto fail;
4052
4053         /*
4054          * Add NS rdataset.
4055          */
4056         result = dns_db_findnode(db, name, ISC_TRUE, &node);
4057         if (result != ISC_R_SUCCESS)
4058                 goto fail;
4059         result = dns_db_addrdataset(db, node, version, 0,
4060                                     nsrdataset, 0, NULL);
4061         dns_db_detachnode(db, &node);
4062         if (result != ISC_R_SUCCESS)
4063                 goto fail;
4064         /*
4065          * Add glue rdatasets.
4066          */
4067         for (result = dns_rdataset_first(nsrdataset);
4068              result == ISC_R_SUCCESS;
4069              result = dns_rdataset_next(nsrdataset)) {
4070                 dns_rdataset_current(nsrdataset, &rdata);
4071                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
4072                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4073                 dns_rdata_reset(&rdata);
4074                 if (!dns_name_issubdomain(&ns.name, name))
4075                         continue;
4076                 rdataset = NULL;
4077                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
4078                                               &ns.name, dns_rdatatype_aaaa,
4079                                               dns_rdatatype_none, NULL,
4080                                               &rdataset);
4081                 if (result == ISC_R_SUCCESS) {
4082                         result = dns_db_findnode(db, &ns.name,
4083                                                  ISC_TRUE, &node);
4084                         if (result != ISC_R_SUCCESS)
4085                                 goto fail;
4086                         result = dns_db_addrdataset(db, node, version, 0,
4087                                                     rdataset, 0, NULL);
4088                         dns_db_detachnode(db, &node);
4089                         if (result != ISC_R_SUCCESS)
4090                                 goto fail;
4091                 }
4092                 rdataset = NULL;
4093                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
4094                                               &ns.name, dns_rdatatype_a,
4095                                               dns_rdatatype_none, NULL,
4096                                               &rdataset);
4097                 if (result == ISC_R_SUCCESS) {
4098                         result = dns_db_findnode(db, &ns.name,
4099                                                  ISC_TRUE, &node);
4100                         if (result != ISC_R_SUCCESS)
4101                                 goto fail;
4102                         result = dns_db_addrdataset(db, node, version, 0,
4103                                                     rdataset, 0, NULL);
4104                         dns_db_detachnode(db, &node);
4105                         if (result != ISC_R_SUCCESS)
4106                                 goto fail;
4107                 }
4108         }
4109         if (result != ISC_R_NOMORE)
4110                 goto fail;
4111
4112         return (ISC_R_SUCCESS);
4113
4114 fail:
4115         return (result);
4116 }
4117
4118 static void
4119 stub_callback(isc_task_t *task, isc_event_t *event) {
4120         const char me[] = "stub_callback";
4121         dns_requestevent_t *revent = (dns_requestevent_t *)event;
4122         dns_stub_t *stub = NULL;
4123         dns_message_t *msg = NULL;
4124         dns_zone_t *zone = NULL;
4125         char master[ISC_SOCKADDR_FORMATSIZE];
4126         char source[ISC_SOCKADDR_FORMATSIZE];
4127         isc_uint32_t nscnt, cnamecnt;
4128         isc_result_t result;
4129         isc_time_t now;
4130         isc_boolean_t exiting = ISC_FALSE;
4131         isc_interval_t i;
4132         unsigned int j;
4133
4134         stub = revent->ev_arg;
4135         INSIST(DNS_STUB_VALID(stub));
4136
4137         UNUSED(task);
4138
4139         zone = stub->zone;
4140
4141         ENTER;
4142
4143         TIME_NOW(&now);
4144
4145         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
4146                 zone_debuglog(zone, me, 1, "exiting");
4147                 exiting = ISC_TRUE;
4148                 goto next_master;
4149         }
4150
4151         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
4152         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
4153
4154         if (revent->result != ISC_R_SUCCESS) {
4155                 if (revent->result == ISC_R_TIMEDOUT &&
4156                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
4157                         LOCK_ZONE(zone);
4158                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4159                         UNLOCK_ZONE(zone);
4160                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
4161                                      "refreshing stub: timeout retrying "
4162                                      " without EDNS master %s (source %s)",
4163                                      master, source);
4164                         goto same_master;
4165                 }
4166                 dns_zone_log(zone, ISC_LOG_INFO,
4167                              "could not refresh stub from master %s"
4168                              " (source %s): %s", master, source,
4169                              dns_result_totext(revent->result));
4170                 goto next_master;
4171         }
4172
4173         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
4174         if (result != ISC_R_SUCCESS)
4175                 goto next_master;
4176
4177         result = dns_request_getresponse(revent->request, msg, 0);
4178         if (result != ISC_R_SUCCESS)
4179                 goto next_master;
4180
4181         /*
4182          * Unexpected rcode.
4183          */
4184         if (msg->rcode != dns_rcode_noerror) {
4185                 char rcode[128];
4186                 isc_buffer_t rb;
4187
4188                 isc_buffer_init(&rb, rcode, sizeof(rcode));
4189                 (void)dns_rcode_totext(msg->rcode, &rb);
4190
4191                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
4192                     (msg->rcode == dns_rcode_servfail ||
4193                      msg->rcode == dns_rcode_notimp ||
4194                      msg->rcode == dns_rcode_formerr)) {
4195                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
4196                                      "refreshing stub: rcode (%.*s) retrying "
4197                                      "without EDNS master %s (source %s)",
4198                                      (int)rb.used, rcode, master, source);
4199                         LOCK_ZONE(zone);
4200                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4201                         UNLOCK_ZONE(zone);
4202                         goto same_master;
4203                 }
4204
4205                 dns_zone_log(zone, ISC_LOG_INFO,
4206                              "refreshing stub: "
4207                              "unexpected rcode (%.*s) from %s (source %s)",
4208                              (int)rb.used, rcode, master, source);
4209                 goto next_master;
4210         }
4211
4212         /*
4213          * We need complete messages.
4214          */
4215         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
4216                 if (dns_request_usedtcp(revent->request)) {
4217                         dns_zone_log(zone, ISC_LOG_INFO,
4218                                      "refreshing stub: truncated TCP "
4219                                      "response from master %s (source %s)",
4220                                      master, source);
4221                         goto next_master;
4222                 }
4223                 LOCK_ZONE(zone);
4224                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
4225                 UNLOCK_ZONE(zone);
4226                 goto same_master;
4227         }
4228
4229         /*
4230          * If non-auth log and next master.
4231          */
4232         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
4233                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
4234                              "non-authoritative answer from "
4235                              "master %s (source %s)", master, source);
4236                 goto next_master;
4237         }
4238
4239         /*
4240          * Sanity checks.
4241          */
4242         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
4243         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
4244
4245         if (cnamecnt != 0) {
4246                 dns_zone_log(zone, ISC_LOG_INFO,
4247                              "refreshing stub: unexpected CNAME response "
4248                              "from master %s (source %s)", master, source);
4249                 goto next_master;
4250         }
4251
4252         if (nscnt == 0) {
4253                 dns_zone_log(zone, ISC_LOG_INFO,
4254                              "refreshing stub: no NS records in response "
4255                              "from master %s (source %s)", master, source);
4256                 goto next_master;
4257         }
4258
4259         /*
4260          * Save answer.
4261          */
4262         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
4263         if (result != ISC_R_SUCCESS) {
4264                 dns_zone_log(zone, ISC_LOG_INFO,
4265                              "refreshing stub: unable to save NS records "
4266                              "from master %s (source %s)", master, source);
4267                 goto next_master;
4268         }
4269
4270         /*
4271          * Tidy up.
4272          */
4273         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
4274         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4275         if (zone->db == NULL)
4276                 zone_attachdb(zone, stub->db);
4277         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4278         dns_db_detach(&stub->db);
4279
4280         if (zone->masterfile != NULL) {
4281                 dns_zone_dump(zone);
4282                 TIME_NOW(&zone->loadtime);
4283         }
4284
4285         dns_message_destroy(&msg);
4286         isc_event_free(&event);
4287         LOCK_ZONE(zone);
4288         dns_request_destroy(&zone->request);
4289         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4290         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
4291         isc_interval_set(&i, zone->expire, 0);
4292         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
4293         zone_settimer(zone, &now);
4294         UNLOCK_ZONE(zone);
4295         goto free_stub;
4296
4297  next_master:
4298         if (stub->version != NULL)
4299                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
4300         if (stub->db != NULL)
4301                 dns_db_detach(&stub->db);
4302         if (msg != NULL)
4303                 dns_message_destroy(&msg);
4304         isc_event_free(&event);
4305         LOCK_ZONE(zone);
4306         dns_request_destroy(&zone->request);
4307         /*
4308          * Skip to next failed / untried master.
4309          */
4310         do {
4311                 zone->curmaster++;
4312         } while (zone->curmaster < zone->masterscnt &&
4313                  zone->mastersok[zone->curmaster]);
4314         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
4315         if (exiting || zone->curmaster >= zone->masterscnt) {
4316                 isc_boolean_t done = ISC_TRUE;
4317                 if (!exiting &&
4318                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
4319                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
4320                         /*
4321                          * Did we get a good answer from all the masters?
4322                          */
4323                         for (j = 0; j < zone->masterscnt; j++)
4324                                 if (zone->mastersok[j] == ISC_FALSE) {
4325                                         done = ISC_FALSE;
4326                                         break;
4327                                 }
4328                 } else
4329                         done = ISC_TRUE;
4330                 if (!done) {
4331                         zone->curmaster = 0;
4332                         /*
4333                          * Find the next failed master.
4334                          */
4335                         while (zone->curmaster < zone->masterscnt &&
4336                                zone->mastersok[zone->curmaster])
4337                                 zone->curmaster++;
4338                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
4339                 } else {
4340                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4341
4342                         zone_settimer(zone, &now);
4343                         UNLOCK_ZONE(zone);
4344                         goto free_stub;
4345                 }
4346         }
4347         queue_soa_query(zone);
4348         UNLOCK_ZONE(zone);
4349         goto free_stub;
4350
4351  same_master:
4352         if (msg != NULL)
4353                 dns_message_destroy(&msg);
4354         isc_event_free(&event);
4355         LOCK_ZONE(zone);
4356         dns_request_destroy(&zone->request);
4357         UNLOCK_ZONE(zone);
4358         ns_query(zone, NULL, stub);
4359         goto done;
4360
4361  free_stub:
4362         stub->magic = 0;
4363         dns_zone_idetach(&stub->zone);
4364         INSIST(stub->db == NULL);
4365         INSIST(stub->version == NULL);
4366         isc_mem_put(stub->mctx, stub, sizeof(*stub));
4367
4368  done:
4369         INSIST(event == NULL);
4370         return;
4371 }
4372
4373 /*
4374  * An SOA query has finished (successfully or not).
4375  */
4376 static void
4377 refresh_callback(isc_task_t *task, isc_event_t *event) {
4378         const char me[] = "refresh_callback";
4379         dns_requestevent_t *revent = (dns_requestevent_t *)event;
4380         dns_zone_t *zone;
4381         dns_message_t *msg = NULL;
4382         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
4383         isc_time_t now;
4384         char master[ISC_SOCKADDR_FORMATSIZE];
4385         char source[ISC_SOCKADDR_FORMATSIZE];
4386         dns_rdataset_t *rdataset = NULL;
4387         dns_rdata_t rdata = DNS_RDATA_INIT;
4388         dns_rdata_soa_t soa;
4389         isc_result_t result;
4390         isc_uint32_t serial;
4391         unsigned int j;
4392
4393         zone = revent->ev_arg;
4394         INSIST(DNS_ZONE_VALID(zone));
4395
4396         UNUSED(task);
4397
4398         ENTER;
4399
4400         /*
4401          * if timeout log and next master;
4402          */
4403
4404         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
4405         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
4406
4407         TIME_NOW(&now);
4408
4409         if (revent->result != ISC_R_SUCCESS) {
4410                 if (revent->result == ISC_R_TIMEDOUT &&
4411                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
4412                         LOCK_ZONE(zone);
4413                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4414                         UNLOCK_ZONE(zone);
4415                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
4416                                      "refresh: timeout retrying without EDNS "
4417                                      "master %s (source %s)", master, source);
4418                         goto same_master;
4419                 }
4420                 if (revent->result == ISC_R_TIMEDOUT &&
4421                     !dns_request_usedtcp(revent->request)) {
4422                         dns_zone_log(zone, ISC_LOG_INFO,
4423                                      "refresh: retry limit for "
4424                                      "master %s exceeded (source %s)",
4425                                      master, source);
4426                         /* Try with slave with TCP. */
4427                         if (zone->type == dns_zone_slave) {
4428                                 LOCK_ZONE(zone);
4429                                 DNS_ZONE_SETFLAG(zone,
4430                                                  DNS_ZONEFLG_SOABEFOREAXFR);
4431                                 UNLOCK_ZONE(zone);
4432                                 goto tcp_transfer;
4433                         }
4434                 } else
4435                         dns_zone_log(zone, ISC_LOG_INFO,
4436                                      "refresh: failure trying master "
4437                                      "%s (source %s): %s", master, source,
4438                                      dns_result_totext(revent->result));
4439                 goto next_master;
4440         }
4441
4442         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
4443         if (result != ISC_R_SUCCESS)
4444                 goto next_master;
4445         result = dns_request_getresponse(revent->request, msg, 0);
4446         if (result != ISC_R_SUCCESS) {
4447                 dns_zone_log(zone, ISC_LOG_INFO,
4448                              "refresh: failure trying master "
4449                              "%s (source %s): %s", master, source,
4450                              dns_result_totext(result));
4451                 goto next_master;
4452         }
4453
4454         /*
4455          * Unexpected rcode.
4456          */
4457         if (msg->rcode != dns_rcode_noerror) {
4458                 char rcode[128];
4459                 isc_buffer_t rb;
4460
4461                 isc_buffer_init(&rb, rcode, sizeof(rcode));
4462                 (void)dns_rcode_totext(msg->rcode, &rb);
4463
4464                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
4465                     (msg->rcode == dns_rcode_servfail ||
4466                      msg->rcode == dns_rcode_notimp ||
4467                      msg->rcode == dns_rcode_formerr)) {
4468                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
4469                                      "refresh: rcode (%.*s) retrying without "
4470                                      "EDNS master %s (source %s)",
4471                                      (int)rb.used, rcode, master, source);
4472                         LOCK_ZONE(zone);
4473                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4474                         UNLOCK_ZONE(zone);
4475                         goto same_master;
4476                 }
4477                 dns_zone_log(zone, ISC_LOG_INFO,
4478                              "refresh: unexpected rcode (%.*s) from "
4479                              "master %s (source %s)", (int)rb.used, rcode,
4480                              master, source);
4481                 /*
4482                  * Perhaps AXFR/IXFR is allowed even if SOA queries arn't.
4483                  */
4484                 if (msg->rcode == dns_rcode_refused &&
4485                     zone->type == dns_zone_slave)
4486                         goto tcp_transfer;
4487                 goto next_master;
4488         }
4489
4490         /*
4491          * If truncated punt to zone transfer which will query again.
4492          */
4493         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
4494                 if (zone->type == dns_zone_slave) {
4495                         dns_zone_log(zone, ISC_LOG_INFO,
4496                                      "refresh: truncated UDP answer, "
4497                                      "initiating TCP zone xfer "
4498                                      "for master %s (source %s)",
4499                                      master, source);
4500                         LOCK_ZONE(zone);
4501                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
4502                         UNLOCK_ZONE(zone);
4503                         goto tcp_transfer;
4504                 } else {
4505                         INSIST(zone->type == dns_zone_stub);
4506                         if (dns_request_usedtcp(revent->request)) {
4507                                 dns_zone_log(zone, ISC_LOG_INFO,
4508                                              "refresh: truncated TCP response "
4509                                              "from master %s (source %s)",
4510                                              master, source);
4511                                 goto next_master;
4512                         }
4513                         LOCK_ZONE(zone);
4514                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
4515                         UNLOCK_ZONE(zone);
4516                         goto same_master;
4517                 }
4518         }
4519
4520         /*
4521          * if non-auth log and next master;
4522          */
4523         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
4524                 dns_zone_log(zone, ISC_LOG_INFO,
4525                              "refresh: non-authoritative answer from "
4526                              "master %s (source %s)", master, source);
4527                 goto next_master;
4528         }
4529
4530         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
4531         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
4532         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
4533         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
4534                                  dns_rdatatype_soa);
4535
4536         /*
4537          * There should not be a CNAME record at top of zone.
4538          */
4539         if (cnamecnt != 0) {
4540                 dns_zone_log(zone, ISC_LOG_INFO,
4541                              "refresh: CNAME at top of zone "
4542                              "in master %s (source %s)", master, source);
4543                 goto next_master;
4544         }
4545
4546         /*
4547          * if referral log and next master;
4548          */
4549         if (soacnt == 0 && soacount == 0 && nscount != 0) {
4550                 dns_zone_log(zone, ISC_LOG_INFO,
4551                              "refresh: referral response "
4552                              "from master %s (source %s)", master, source);
4553                 goto next_master;
4554         }
4555
4556         /*
4557          * if nodata log and next master;
4558          */
4559         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
4560                 dns_zone_log(zone, ISC_LOG_INFO,
4561                              "refresh: NODATA response "
4562                              "from master %s (source %s)", master, source);
4563                 goto next_master;
4564         }
4565
4566         /*
4567          * Only one soa at top of zone.
4568          */
4569         if (soacnt != 1) {
4570                 dns_zone_log(zone, ISC_LOG_INFO,
4571                              "refresh: answer SOA count (%d) != 1 "
4572                              "from master %s (source %s)",
4573                              soacnt, master, source);
4574                 goto next_master;
4575         }
4576         /*
4577          * Extract serial
4578          */
4579         rdataset = NULL;
4580         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
4581                                       dns_rdatatype_soa, dns_rdatatype_none,
4582                                       NULL, &rdataset);
4583         if (result != ISC_R_SUCCESS) {
4584                 dns_zone_log(zone, ISC_LOG_INFO,
4585                              "refresh: unable to get SOA record "
4586                              "from master %s (source %s)", master, source);
4587                 goto next_master;
4588         }
4589
4590         result = dns_rdataset_first(rdataset);
4591         if (result != ISC_R_SUCCESS) {
4592                 dns_zone_log(zone, ISC_LOG_INFO,
4593                              "refresh: dns_rdataset_first() failed");
4594                 goto next_master;
4595         }
4596
4597         dns_rdataset_current(rdataset, &rdata);
4598         result = dns_rdata_tostruct(&rdata, &soa, NULL);
4599         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4600
4601         serial = soa.serial;
4602
4603         zone_debuglog(zone, me, 1, "serial: new %u, old %u",
4604                       serial, zone->serial);
4605         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
4606             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
4607             isc_serial_gt(serial, zone->serial)) {
4608  tcp_transfer:
4609                 isc_event_free(&event);
4610                 LOCK_ZONE(zone);
4611                 dns_request_destroy(&zone->request);
4612                 UNLOCK_ZONE(zone);
4613                 if (zone->type == dns_zone_slave) {
4614                         queue_xfrin(zone);
4615                 } else {
4616                         INSIST(zone->type == dns_zone_stub);
4617                         ns_query(zone, rdataset, NULL);
4618                 }
4619                 if (msg != NULL)
4620                         dns_message_destroy(&msg);
4621         } else if (isc_serial_eq(soa.serial, zone->serial)) {
4622                 if (zone->masterfile != NULL) {
4623                         result = ISC_R_FAILURE;
4624                         if (zone->journal != NULL)
4625                                 result = isc_file_settime(zone->journal, &now);
4626                         if (result == ISC_R_SUCCESS &&
4627                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
4628                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
4629                                 result = isc_file_settime(zone->masterfile,
4630                                                           &now);
4631                         } else if (result != ISC_R_SUCCESS)
4632                                 result = isc_file_settime(zone->masterfile,
4633                                                           &now);
4634                         /* Someone removed the file from underneath us! */
4635                         if (result == ISC_R_FILENOTFOUND) {
4636                                 LOCK_ZONE(zone);
4637                                 zone_needdump(zone, DNS_DUMP_DELAY);
4638                                 UNLOCK_ZONE(zone);
4639                         } else if (result != ISC_R_SUCCESS)
4640                                 dns_zone_log(zone, ISC_LOG_ERROR,
4641                                              "refresh: could not set file "
4642                                              "modification time of '%s': %s",
4643                                              zone->masterfile,
4644                                              dns_result_totext(result));
4645                 }
4646                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
4647                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
4648                 zone->mastersok[zone->curmaster] = ISC_TRUE;
4649                 goto next_master;
4650         } else {
4651                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
4652                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
4653                                      "received from master %s < ours (%u)",
4654                                      soa.serial, master, zone->serial);
4655                 else
4656                         zone_debuglog(zone, me, 1, "ahead");
4657                 zone->mastersok[zone->curmaster] = ISC_TRUE;
4658                 goto next_master;
4659         }
4660         if (msg != NULL)
4661                 dns_message_destroy(&msg);
4662         goto detach;
4663
4664  next_master:
4665         if (msg != NULL)
4666                 dns_message_destroy(&msg);
4667         isc_event_free(&event);
4668         LOCK_ZONE(zone);
4669         dns_request_destroy(&zone->request);
4670         /*
4671          * Skip to next failed / untried master.
4672          */
4673         do {
4674                 zone->curmaster++;
4675         } while (zone->curmaster < zone->masterscnt &&
4676                  zone->mastersok[zone->curmaster]);
4677         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
4678         if (zone->curmaster >= zone->masterscnt) {
4679                 isc_boolean_t done = ISC_TRUE;
4680                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
4681                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
4682                         /*
4683                          * Did we get a good answer from all the masters?
4684                          */
4685                         for (j = 0; j < zone->masterscnt; j++)
4686                                 if (zone->mastersok[j] == ISC_FALSE) {
4687                                         done = ISC_FALSE;
4688                                         break;
4689                                 }
4690                 } else
4691                         done = ISC_TRUE;
4692                 if (!done) {
4693                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
4694                         zone->curmaster = 0;
4695                         /*
4696                          * Find the next failed master.
4697                          */
4698                         while (zone->curmaster < zone->masterscnt &&
4699                                zone->mastersok[zone->curmaster])
4700                                 zone->curmaster++;
4701                         goto requeue;
4702                 }
4703                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4704                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
4705                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
4706                         zone->refreshtime = now;
4707                 }
4708                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
4709                 zone_settimer(zone, &now);
4710                 UNLOCK_ZONE(zone);
4711                 goto detach;
4712         }
4713
4714  requeue:
4715         queue_soa_query(zone);
4716         UNLOCK_ZONE(zone);
4717         goto detach;
4718
4719  same_master:
4720         if (msg != NULL)
4721                 dns_message_destroy(&msg);
4722         isc_event_free(&event);
4723         LOCK_ZONE(zone);
4724         dns_request_destroy(&zone->request);
4725         queue_soa_query(zone);
4726         UNLOCK_ZONE(zone);
4727
4728  detach:
4729         dns_zone_idetach(&zone);
4730         return;
4731 }
4732
4733 static void
4734 queue_soa_query(dns_zone_t *zone) {
4735         const char me[] = "queue_soa_query";
4736         isc_event_t *e;
4737         dns_zone_t *dummy = NULL;
4738         isc_result_t result;
4739
4740         ENTER;
4741         /*
4742          * Locked by caller
4743          */
4744         REQUIRE(LOCKED_ZONE(zone));
4745
4746         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
4747                 cancel_refresh(zone);
4748                 return;
4749         }
4750
4751         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
4752                                soa_query, zone, sizeof(isc_event_t));
4753         if (e == NULL) {
4754                 cancel_refresh(zone);
4755                 return;
4756         }
4757
4758         /*
4759          * Attach so that we won't clean up
4760          * until the event is delivered.
4761          */
4762         zone_iattach(zone, &dummy);
4763
4764         e->ev_arg = zone;
4765         e->ev_sender = NULL;
4766         result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
4767         if (result != ISC_R_SUCCESS) {
4768                 zone_idetach(&dummy);
4769                 isc_event_free(&e);
4770                 cancel_refresh(zone);
4771         }
4772 }
4773
4774 static inline isc_result_t
4775 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
4776              dns_message_t **messagep)
4777 {
4778         dns_message_t *message = NULL;
4779         dns_name_t *qname = NULL;
4780         dns_rdataset_t *qrdataset = NULL;
4781         isc_result_t result;
4782
4783         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
4784                                     &message);
4785         if (result != ISC_R_SUCCESS)
4786                 goto cleanup;
4787
4788         message->opcode = dns_opcode_query;
4789         message->rdclass = zone->rdclass;
4790
4791         result = dns_message_gettempname(message, &qname);
4792         if (result != ISC_R_SUCCESS)
4793                 goto cleanup;
4794
4795         result = dns_message_gettemprdataset(message, &qrdataset);
4796         if (result != ISC_R_SUCCESS)
4797                 goto cleanup;
4798
4799         /*
4800          * Make question.
4801          */
4802         dns_name_init(qname, NULL);
4803         dns_name_clone(&zone->origin, qname);
4804         dns_rdataset_init(qrdataset);
4805         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
4806         ISC_LIST_APPEND(qname->list, qrdataset, link);
4807         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
4808
4809         *messagep = message;
4810         return (ISC_R_SUCCESS);
4811
4812  cleanup:
4813         if (qname != NULL)
4814                 dns_message_puttempname(message, &qname);
4815         if (qrdataset != NULL)
4816                 dns_message_puttemprdataset(message, &qrdataset);
4817         if (message != NULL)
4818                 dns_message_destroy(&message);
4819         return (result);
4820 }
4821
4822 static isc_result_t
4823 add_opt(dns_message_t *message, isc_uint16_t udpsize) {
4824         dns_rdataset_t *rdataset = NULL;
4825         dns_rdatalist_t *rdatalist = NULL;
4826         dns_rdata_t *rdata = NULL;
4827         isc_result_t result;
4828
4829         result = dns_message_gettemprdatalist(message, &rdatalist);
4830         if (result != ISC_R_SUCCESS)
4831                 goto cleanup;
4832         result = dns_message_gettemprdata(message, &rdata);
4833         if (result != ISC_R_SUCCESS)
4834                 goto cleanup;
4835         result = dns_message_gettemprdataset(message, &rdataset);
4836         if (result != ISC_R_SUCCESS)
4837                 goto cleanup;
4838         dns_rdataset_init(rdataset);
4839
4840         rdatalist->type = dns_rdatatype_opt;
4841         rdatalist->covers = 0;
4842
4843         /*
4844          * Set Maximum UDP buffer size.
4845          */
4846         rdatalist->rdclass = udpsize;
4847
4848         /*
4849          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
4850          */
4851         rdatalist->ttl = 0;
4852
4853         /*
4854          * No EDNS options.
4855          */
4856         rdata->data = NULL;
4857         rdata->length = 0;
4858         rdata->rdclass = rdatalist->rdclass;
4859         rdata->type = rdatalist->type;
4860         rdata->flags = 0;
4861
4862         ISC_LIST_INIT(rdatalist->rdata);
4863         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
4864         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
4865                       == ISC_R_SUCCESS);
4866
4867         return (dns_message_setopt(message, rdataset));
4868
4869  cleanup:
4870         if (rdatalist != NULL)
4871                 dns_message_puttemprdatalist(message, &rdatalist);
4872         if (rdataset != NULL)
4873                 dns_message_puttemprdataset(message, &rdataset);
4874         if (rdata != NULL)
4875                 dns_message_puttemprdata(message, &rdata);
4876
4877         return (result);
4878 }
4879
4880 static void
4881 soa_query(isc_task_t *task, isc_event_t *event) {
4882         const char me[] = "soa_query";
4883         isc_result_t result = ISC_R_FAILURE;
4884         dns_message_t *message = NULL;
4885         dns_zone_t *zone = event->ev_arg;
4886         dns_zone_t *dummy = NULL;
4887         isc_netaddr_t masterip;
4888         dns_tsigkey_t *key = NULL;
4889         isc_uint32_t options;
4890         isc_boolean_t cancel = ISC_TRUE;
4891         int timeout;
4892         isc_boolean_t have_xfrsource;
4893         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
4894
4895         REQUIRE(DNS_ZONE_VALID(zone));
4896
4897         UNUSED(task);
4898
4899         ENTER;
4900
4901         LOCK_ZONE(zone);
4902         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
4903             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
4904             zone->view->requestmgr == NULL) {
4905                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
4906                         cancel = ISC_FALSE;
4907                 goto cleanup;
4908         }
4909
4910         /*
4911          * XXX Optimisation: Create message when zone is setup and reuse.
4912          */
4913         result = create_query(zone, dns_rdatatype_soa, &message);
4914         if (result != ISC_R_SUCCESS)
4915                 goto cleanup;
4916
4917  again:
4918         INSIST(zone->masterscnt > 0);
4919         INSIST(zone->curmaster < zone->masterscnt);
4920
4921         zone->masteraddr = zone->masters[zone->curmaster];
4922
4923         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
4924         /*
4925          * First, look for a tsig key in the master statement, then
4926          * try for a server key.
4927          */
4928         if ((zone->masterkeynames != NULL) &&
4929             (zone->masterkeynames[zone->curmaster] != NULL)) {
4930                 dns_view_t *view = dns_zone_getview(zone);
4931                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
4932                 result = dns_view_gettsig(view, keyname, &key);
4933                 if (result != ISC_R_SUCCESS) {
4934                         char namebuf[DNS_NAME_FORMATSIZE];
4935                         dns_name_format(keyname, namebuf, sizeof(namebuf));
4936                         dns_zone_log(zone, ISC_LOG_ERROR,
4937                                      "unable to find key: %s", namebuf);
4938                 }
4939         }
4940         if (key == NULL)
4941                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
4942
4943         have_xfrsource = ISC_FALSE;
4944         if (zone->view->peers != NULL) {
4945                 dns_peer_t *peer = NULL;
4946                 isc_boolean_t edns;
4947                 result = dns_peerlist_peerbyaddr(zone->view->peers,
4948                                                  &masterip, &peer);
4949                 if (result == ISC_R_SUCCESS) {
4950                         result = dns_peer_getsupportedns(peer, &edns);
4951                         if (result == ISC_R_SUCCESS && !edns)
4952                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
4953                         result = dns_peer_gettransfersource(peer,
4954                                                             &zone->sourceaddr);
4955                         if (result == ISC_R_SUCCESS)
4956                                 have_xfrsource = ISC_TRUE;
4957                         if (zone->view->resolver != NULL)
4958                                 udpsize =
4959                                   dns_resolver_getudpsize(zone->view->resolver);
4960                         (void)dns_peer_getudpsize(peer, &udpsize);
4961                 }
4962         }
4963
4964         switch (isc_sockaddr_pf(&zone->masteraddr)) {
4965         case PF_INET:
4966                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
4967                         if (isc_sockaddr_equal(&zone->altxfrsource4,
4968                                                &zone->xfrsource4))
4969                                 goto skip_master;
4970                         zone->sourceaddr = zone->altxfrsource4;
4971                 } else if (!have_xfrsource)
4972                         zone->sourceaddr = zone->xfrsource4;
4973                 break;
4974         case PF_INET6:
4975                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
4976                         if (isc_sockaddr_equal(&zone->altxfrsource6,
4977                                                &zone->xfrsource6))
4978                                 goto skip_master;
4979                         zone->sourceaddr = zone->altxfrsource6;
4980                 } else if (!have_xfrsource)
4981                         zone->sourceaddr = zone->xfrsource6;
4982                 break;
4983         default:
4984                 result = ISC_R_NOTIMPLEMENTED;
4985                 goto cleanup;
4986         }
4987
4988         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
4989                   DNS_REQUESTOPT_TCP : 0;
4990
4991         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
4992                 result = add_opt(message, udpsize);
4993                 if (result != ISC_R_SUCCESS)
4994                         zone_debuglog(zone, me, 1,
4995                                       "unable to add opt record: %s",
4996                                       dns_result_totext(result));
4997         }
4998
4999         zone_iattach(zone, &dummy);
5000         timeout = 15;
5001         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
5002                 timeout = 30;
5003         result = dns_request_createvia2(zone->view->requestmgr, message,
5004                                         &zone->sourceaddr, &zone->masteraddr,
5005                                         options, key, timeout * 3, timeout,
5006                                         zone->task, refresh_callback, zone,
5007                                         &zone->request);
5008         if (result != ISC_R_SUCCESS) {
5009                 zone_idetach(&dummy);
5010                 zone_debuglog(zone, me, 1,
5011                               "dns_request_createvia2() failed: %s",
5012                               dns_result_totext(result));
5013                 goto cleanup;
5014         }
5015         cancel = ISC_FALSE;
5016
5017  cleanup:
5018         if (key != NULL)
5019                 dns_tsigkey_detach(&key);
5020         if (result != ISC_R_SUCCESS)
5021                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
5022         if (message != NULL)
5023                 dns_message_destroy(&message);
5024         if (cancel)
5025                 cancel_refresh(zone);
5026         isc_event_free(&event);
5027         UNLOCK_ZONE(zone);
5028         dns_zone_idetach(&zone);
5029         return;
5030
5031  skip_master:
5032         if (key != NULL)
5033                 dns_tsigkey_detach(&key);
5034         /*
5035          * Skip to next failed / untried master.
5036          */
5037         do {
5038                 zone->curmaster++;
5039         } while (zone->curmaster < zone->masterscnt &&
5040                  zone->mastersok[zone->curmaster]);
5041         if (zone->curmaster < zone->masterscnt)
5042                 goto again;
5043         zone->curmaster = 0;
5044         goto cleanup;
5045 }
5046
5047 static void
5048 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
5049         const char me[] = "ns_query";
5050         isc_result_t result;
5051         dns_message_t *message = NULL;
5052         isc_netaddr_t masterip;
5053         dns_tsigkey_t *key = NULL;
5054         dns_dbnode_t *node = NULL;
5055         int timeout;
5056         isc_boolean_t have_xfrsource = ISC_FALSE;
5057         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
5058
5059         REQUIRE(DNS_ZONE_VALID(zone));
5060         REQUIRE((soardataset != NULL && stub == NULL) ||
5061                 (soardataset == NULL && stub != NULL));
5062         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
5063
5064         ENTER;
5065
5066         LOCK_ZONE(zone);
5067         if (stub == NULL) {
5068                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
5069                 if (stub == NULL)
5070                         goto cleanup;
5071                 stub->magic = STUB_MAGIC;
5072                 stub->mctx = zone->mctx;
5073                 stub->zone = NULL;
5074                 stub->db = NULL;
5075                 stub->version = NULL;
5076
5077                 /*
5078                  * Attach so that the zone won't disappear from under us.
5079                  */
5080                 zone_iattach(zone, &stub->zone);
5081
5082                 /*
5083                  * If a db exists we will update it, otherwise we create a
5084                  * new one and attach it to the zone once we have the NS
5085                  * RRset and glue.
5086                  */
5087                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5088                 if (zone->db != NULL) {
5089                         dns_db_attach(zone->db, &stub->db);
5090                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5091                 } else {
5092                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5093
5094                         INSIST(zone->db_argc >= 1);
5095                         result = dns_db_create(zone->mctx, zone->db_argv[0],
5096                                                &zone->origin, dns_dbtype_stub,
5097                                                zone->rdclass,
5098                                                zone->db_argc - 1,
5099                                                zone->db_argv + 1,
5100                                                &stub->db);
5101                         if (result != ISC_R_SUCCESS) {
5102                                 dns_zone_log(zone, ISC_LOG_ERROR,
5103                                              "refreshing stub: "
5104                                              "could not create "
5105                                              "database: %s",
5106                                              dns_result_totext(result));
5107                                 goto cleanup;
5108                         }
5109                         dns_db_settask(stub->db, zone->task);
5110                 }
5111
5112                 dns_db_newversion(stub->db, &stub->version);
5113
5114                 /*
5115                  * Update SOA record.
5116                  */
5117                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
5118                                          &node);
5119                 if (result != ISC_R_SUCCESS) {
5120                         dns_zone_log(zone, ISC_LOG_INFO,
5121                                      "refreshing stub: "
5122                                      "dns_db_findnode() failed: %s",
5123                                      dns_result_totext(result));
5124                         goto cleanup;
5125                 }
5126
5127                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
5128                                             soardataset, 0, NULL);
5129                 dns_db_detachnode(stub->db, &node);
5130                 if (result != ISC_R_SUCCESS) {
5131                         dns_zone_log(zone, ISC_LOG_INFO,
5132                                      "refreshing stub: "
5133                                      "dns_db_addrdataset() failed: %s",
5134                                      dns_result_totext(result));
5135                         goto cleanup;
5136                 }
5137         }
5138
5139         /*
5140          * XXX Optimisation: Create message when zone is setup and reuse.
5141          */
5142         result = create_query(zone, dns_rdatatype_ns, &message);
5143
5144         INSIST(zone->masterscnt > 0);
5145         INSIST(zone->curmaster < zone->masterscnt);
5146         zone->masteraddr = zone->masters[zone->curmaster];
5147
5148         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
5149         /*
5150          * First, look for a tsig key in the master statement, then
5151          * try for a server key.
5152          */
5153         if ((zone->masterkeynames != NULL) &&
5154             (zone->masterkeynames[zone->curmaster] != NULL)) {
5155                 dns_view_t *view = dns_zone_getview(zone);
5156                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
5157                 result = dns_view_gettsig(view, keyname, &key);
5158                 if (result != ISC_R_SUCCESS) {
5159                         char namebuf[DNS_NAME_FORMATSIZE];
5160                         dns_name_format(keyname, namebuf, sizeof(namebuf));
5161                         dns_zone_log(zone, ISC_LOG_ERROR,
5162                                      "unable to find key: %s", namebuf);
5163                 }
5164         }
5165         if (key == NULL)
5166                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
5167
5168         if (zone->view->peers != NULL) {
5169                 dns_peer_t *peer = NULL;
5170                 isc_boolean_t edns;
5171                 result = dns_peerlist_peerbyaddr(zone->view->peers,
5172                                                  &masterip, &peer);
5173                 if (result == ISC_R_SUCCESS) {
5174                         result = dns_peer_getsupportedns(peer, &edns);
5175                         if (result == ISC_R_SUCCESS && !edns)
5176                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
5177                         result = dns_peer_gettransfersource(peer,
5178                                                             &zone->sourceaddr);
5179                         if (result == ISC_R_SUCCESS)
5180                                 have_xfrsource = ISC_TRUE;
5181                         if (zone->view->resolver != NULL)
5182                                 udpsize =
5183                                   dns_resolver_getudpsize(zone->view->resolver);
5184                         (void)dns_peer_getudpsize(peer, &udpsize);
5185                 }
5186
5187         }
5188         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
5189                 result = add_opt(message, udpsize);
5190                 if (result != ISC_R_SUCCESS)
5191                         zone_debuglog(zone, me, 1,
5192                                       "unable to add opt record: %s",
5193                                       dns_result_totext(result));
5194         }
5195
5196         /*
5197          * Always use TCP so that we shouldn't truncate in additional section.
5198          */
5199         switch (isc_sockaddr_pf(&zone->masteraddr)) {
5200         case PF_INET:
5201                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
5202                         zone->sourceaddr = zone->altxfrsource4;
5203                 else if (!have_xfrsource)
5204                         zone->sourceaddr = zone->xfrsource4;
5205                 break;
5206         case PF_INET6:
5207                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
5208                         zone->sourceaddr = zone->altxfrsource6;
5209                 else if (!have_xfrsource)
5210                         zone->sourceaddr = zone->xfrsource6;
5211                 break;
5212         default:
5213                 result = ISC_R_NOTIMPLEMENTED;
5214                 goto cleanup;
5215         }
5216         timeout = 15;
5217         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
5218                 timeout = 30;
5219         result = dns_request_createvia2(zone->view->requestmgr, message,
5220                                         &zone->sourceaddr, &zone->masteraddr,
5221                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
5222                                         timeout, zone->task, stub_callback,
5223                                         stub, &zone->request);
5224         if (result != ISC_R_SUCCESS) {
5225                 zone_debuglog(zone, me, 1,
5226                               "dns_request_createvia() failed: %s",
5227                               dns_result_totext(result));
5228                 goto cleanup;
5229         }
5230         dns_message_destroy(&message);
5231         goto unlock;
5232
5233  cleanup:
5234         cancel_refresh(zone);
5235         if (stub != NULL) {
5236                 stub->magic = 0;
5237                 if (stub->version != NULL)
5238                         dns_db_closeversion(stub->db, &stub->version,
5239                                             ISC_FALSE);
5240                 if (stub->db != NULL)
5241                         dns_db_detach(&stub->db);
5242                 if (stub->zone != NULL)
5243                         zone_idetach(&stub->zone);
5244                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
5245         }
5246         if (message != NULL)
5247                 dns_message_destroy(&message);
5248   unlock:
5249         if (key != NULL)
5250                 dns_tsigkey_detach(&key);
5251         UNLOCK_ZONE(zone);
5252         return;
5253 }
5254
5255 /*
5256  * Handle the control event.  Note that although this event causes the zone
5257  * to shut down, it is not a shutdown event in the sense of the task library.
5258  */
5259 static void
5260 zone_shutdown(isc_task_t *task, isc_event_t *event) {
5261         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
5262         isc_boolean_t free_needed, linked = ISC_FALSE;
5263
5264         UNUSED(task);
5265         REQUIRE(DNS_ZONE_VALID(zone));
5266         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
5267         INSIST(isc_refcount_current(&zone->erefs) == 0);
5268         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
5269
5270         /*
5271          * Stop things being restarted after we cancel them below.
5272          */
5273         LOCK_ZONE(zone);
5274         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
5275         UNLOCK_ZONE(zone);
5276
5277         /*
5278          * If we were waiting for xfrin quota, step out of
5279          * the queue.
5280          * If there's no zone manager, we can't be waiting for the
5281          * xfrin quota
5282          */
5283         if (zone->zmgr != NULL) {
5284                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
5285                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
5286                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
5287                                         statelink);
5288                         linked = ISC_TRUE;
5289                         zone->statelist = NULL;
5290                 }
5291                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
5292         }
5293
5294         /*
5295          * In task context, no locking required.  See zone_xfrdone().
5296          */
5297         if (zone->xfr != NULL)
5298                 dns_xfrin_shutdown(zone->xfr);
5299
5300         LOCK_ZONE(zone);
5301         if (linked) {
5302                 INSIST(zone->irefs > 0);
5303                 zone->irefs--;
5304         }
5305         if (zone->request != NULL) {
5306                 dns_request_cancel(zone->request);
5307         }
5308
5309         if (zone->readio != NULL)
5310                 zonemgr_cancelio(zone->readio);
5311
5312         if (zone->lctx != NULL)
5313                 dns_loadctx_cancel(zone->lctx);
5314
5315         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
5316             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
5317                 if (zone->writeio != NULL)
5318                         zonemgr_cancelio(zone->writeio);
5319
5320                 if (zone->dctx != NULL)
5321                         dns_dumpctx_cancel(zone->dctx);
5322         }
5323
5324         notify_cancel(zone);
5325
5326         if (zone->timer != NULL) {
5327                 isc_timer_detach(&zone->timer);
5328                 INSIST(zone->irefs > 0);
5329                 zone->irefs--;
5330         }
5331
5332         if (zone->view != NULL)
5333                 dns_view_weakdetach(&zone->view);
5334
5335         /*
5336          * We have now canceled everything set the flag to allow exit_check()
5337          * to succeed.  We must not unlock between setting this flag and
5338          * calling exit_check().
5339          */
5340         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
5341         free_needed = exit_check(zone);
5342         UNLOCK_ZONE(zone);
5343         if (free_needed)
5344                 zone_free(zone);
5345 }
5346
5347 static void
5348 zone_timer(isc_task_t *task, isc_event_t *event) {
5349         const char me[] = "zone_timer";
5350         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
5351
5352         UNUSED(task);
5353         REQUIRE(DNS_ZONE_VALID(zone));
5354
5355         ENTER;
5356
5357         zone_maintenance(zone);
5358
5359         isc_event_free(&event);
5360 }
5361
5362 static void
5363 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
5364         const char me[] = "zone_settimer";
5365         isc_time_t next;
5366         isc_result_t result;
5367
5368         REQUIRE(DNS_ZONE_VALID(zone));
5369         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
5370                 return;
5371
5372         isc_time_settoepoch(&next);
5373
5374         switch (zone->type) {
5375         case dns_zone_master:
5376                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
5377                         next = zone->notifytime;
5378                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
5379                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
5380                         INSIST(!isc_time_isepoch(&zone->dumptime));
5381                         if (isc_time_isepoch(&next) ||
5382                             isc_time_compare(&zone->dumptime, &next) < 0)
5383                                 next = zone->dumptime;
5384                 }
5385                 break;
5386
5387         case dns_zone_slave:
5388                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
5389                         next = zone->notifytime;
5390                 /*FALLTHROUGH*/
5391
5392         case dns_zone_stub:
5393                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
5394                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
5395                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
5396                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
5397                         INSIST(!isc_time_isepoch(&zone->refreshtime));
5398                         if (isc_time_isepoch(&next) ||
5399                             isc_time_compare(&zone->refreshtime, &next) < 0)
5400                                 next = zone->refreshtime;
5401                 }
5402                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
5403                         INSIST(!isc_time_isepoch(&zone->expiretime));
5404                         if (isc_time_isepoch(&next) ||
5405                             isc_time_compare(&zone->expiretime, &next) < 0)
5406                                 next = zone->expiretime;
5407                 }
5408                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
5409                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
5410                         INSIST(!isc_time_isepoch(&zone->dumptime));
5411                         if (isc_time_isepoch(&next) ||
5412                             isc_time_compare(&zone->dumptime, &next) < 0)
5413                                 next = zone->dumptime;
5414                 }
5415                 break;
5416
5417         default:
5418                 break;
5419         }
5420
5421         if (isc_time_isepoch(&next)) {
5422                 zone_debuglog(zone, me, 10, "settimer inactive");
5423                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
5424                                           NULL, NULL, ISC_TRUE);
5425                 if (result != ISC_R_SUCCESS)
5426                         dns_zone_log(zone, ISC_LOG_ERROR,
5427                                      "could not deactivate zone timer: %s",
5428                                      isc_result_totext(result));
5429         } else {
5430                 if (isc_time_compare(&next, now) <= 0)
5431                         next = *now;
5432                 result = isc_timer_reset(zone->timer, isc_timertype_once,
5433                                          &next, NULL, ISC_TRUE);
5434                 if (result != ISC_R_SUCCESS)
5435                         dns_zone_log(zone, ISC_LOG_ERROR,
5436                                      "could not reset zone timer: %s",
5437                                      isc_result_totext(result));
5438         }
5439 }
5440
5441 static void
5442 cancel_refresh(dns_zone_t *zone) {
5443         const char me[] = "cancel_refresh";
5444         isc_time_t now;
5445
5446         /*
5447          * 'zone' locked by caller.
5448          */
5449
5450         REQUIRE(DNS_ZONE_VALID(zone));
5451         REQUIRE(LOCKED_ZONE(zone));
5452
5453         ENTER;
5454
5455         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
5456         TIME_NOW(&now);
5457         zone_settimer(zone, &now);
5458 }
5459
5460 static isc_result_t
5461 notify_createmessage(dns_zone_t *zone, unsigned int flags,
5462                      dns_message_t **messagep)
5463 {
5464         dns_db_t *zonedb = NULL;
5465         dns_dbnode_t *node = NULL;
5466         dns_dbversion_t *version = NULL;
5467         dns_message_t *message = NULL;
5468         dns_rdataset_t rdataset;
5469         dns_rdata_t rdata = DNS_RDATA_INIT;
5470
5471         dns_name_t *tempname = NULL;
5472         dns_rdata_t *temprdata = NULL;
5473         dns_rdatalist_t *temprdatalist = NULL;
5474         dns_rdataset_t *temprdataset = NULL;
5475
5476         isc_result_t result;
5477         isc_region_t r;
5478         isc_buffer_t *b = NULL;
5479
5480         REQUIRE(DNS_ZONE_VALID(zone));
5481         REQUIRE(messagep != NULL && *messagep == NULL);
5482
5483         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
5484                                     &message);
5485         if (result != ISC_R_SUCCESS)
5486                 return (result);
5487
5488         message->opcode = dns_opcode_notify;
5489         message->flags |= DNS_MESSAGEFLAG_AA;
5490         message->rdclass = zone->rdclass;
5491
5492         result = dns_message_gettempname(message, &tempname);
5493         if (result != ISC_R_SUCCESS)
5494                 goto cleanup;
5495
5496         result = dns_message_gettemprdataset(message, &temprdataset);
5497         if (result != ISC_R_SUCCESS)
5498                 goto cleanup;
5499
5500         /*
5501          * Make question.
5502          */
5503         dns_name_init(tempname, NULL);
5504         dns_name_clone(&zone->origin, tempname);
5505         dns_rdataset_init(temprdataset);
5506         dns_rdataset_makequestion(temprdataset, zone->rdclass,
5507                                   dns_rdatatype_soa);
5508         ISC_LIST_APPEND(tempname->list, temprdataset, link);
5509         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
5510         tempname = NULL;
5511         temprdataset = NULL;
5512
5513         if ((flags & DNS_NOTIFY_NOSOA) != 0)
5514                 goto done;
5515
5516         result = dns_message_gettempname(message, &tempname);
5517         if (result != ISC_R_SUCCESS)
5518                 goto soa_cleanup;
5519         result = dns_message_gettemprdata(message, &temprdata);
5520         if (result != ISC_R_SUCCESS)
5521                 goto soa_cleanup;
5522         result = dns_message_gettemprdataset(message, &temprdataset);
5523         if (result != ISC_R_SUCCESS)
5524                 goto soa_cleanup;
5525         result = dns_message_gettemprdatalist(message, &temprdatalist);
5526         if (result != ISC_R_SUCCESS)
5527                 goto soa_cleanup;
5528
5529         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5530         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
5531         dns_db_attach(zone->db, &zonedb);
5532         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5533
5534         dns_name_init(tempname, NULL);
5535         dns_name_clone(&zone->origin, tempname);
5536         dns_db_currentversion(zonedb, &version);
5537         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
5538         if (result != ISC_R_SUCCESS)
5539                 goto soa_cleanup;
5540
5541         dns_rdataset_init(&rdataset);
5542         result = dns_db_findrdataset(zonedb, node, version,
5543                                      dns_rdatatype_soa,
5544                                      dns_rdatatype_none, 0, &rdataset,
5545                                      NULL);
5546         if (result != ISC_R_SUCCESS)
5547                 goto soa_cleanup;
5548         result = dns_rdataset_first(&rdataset);
5549         if (result != ISC_R_SUCCESS)
5550                 goto soa_cleanup;
5551         dns_rdataset_current(&rdataset, &rdata);
5552         dns_rdata_toregion(&rdata, &r);
5553         result = isc_buffer_allocate(zone->mctx, &b, r.length);
5554         if (result != ISC_R_SUCCESS)
5555                 goto soa_cleanup;
5556         isc_buffer_putmem(b, r.base, r.length);
5557         isc_buffer_usedregion(b, &r);
5558         dns_rdata_init(temprdata);
5559         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
5560         dns_message_takebuffer(message, &b);
5561         result = dns_rdataset_next(&rdataset);
5562         dns_rdataset_disassociate(&rdataset);
5563         if (result != ISC_R_NOMORE)
5564                 goto soa_cleanup;
5565         temprdatalist->rdclass = rdata.rdclass;
5566         temprdatalist->type = rdata.type;
5567         temprdatalist->covers = 0;
5568         temprdatalist->ttl = rdataset.ttl;
5569         ISC_LIST_INIT(temprdatalist->rdata);
5570         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
5571
5572         dns_rdataset_init(temprdataset);
5573         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
5574         if (result != ISC_R_SUCCESS)
5575                 goto soa_cleanup;
5576
5577         ISC_LIST_APPEND(tempname->list, temprdataset, link);
5578         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
5579         temprdatalist = NULL;
5580         temprdataset = NULL;
5581         temprdata = NULL;
5582         tempname = NULL;
5583
5584  soa_cleanup:
5585         if (node != NULL)
5586                 dns_db_detachnode(zonedb, &node);
5587         if (version != NULL)
5588                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
5589         if (zonedb != NULL)
5590                 dns_db_detach(&zonedb);
5591         if (tempname != NULL)
5592                 dns_message_puttempname(message, &tempname);
5593         if (temprdata != NULL)
5594                 dns_message_puttemprdata(message, &temprdata);
5595         if (temprdataset != NULL)
5596                 dns_message_puttemprdataset(message, &temprdataset);
5597         if (temprdatalist != NULL)
5598                 dns_message_puttemprdatalist(message, &temprdatalist);
5599
5600  done:
5601         *messagep = message;
5602         return (ISC_R_SUCCESS);
5603
5604  cleanup:
5605         if (tempname != NULL)
5606                 dns_message_puttempname(message, &tempname);
5607         if (temprdataset != NULL)
5608                 dns_message_puttemprdataset(message, &temprdataset);
5609         dns_message_destroy(&message);
5610         return (result);
5611 }
5612
5613 isc_result_t
5614 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
5615                        dns_message_t *msg)
5616 {
5617         unsigned int i;
5618         dns_rdata_soa_t soa;
5619         dns_rdataset_t *rdataset = NULL;
5620         dns_rdata_t rdata = DNS_RDATA_INIT;
5621         isc_result_t result;
5622         char fromtext[ISC_SOCKADDR_FORMATSIZE];
5623         int match = 0;
5624         isc_netaddr_t netaddr;
5625
5626         REQUIRE(DNS_ZONE_VALID(zone));
5627
5628         /*
5629          * If type != T_SOA return DNS_R_REFUSED.  We don't yet support
5630          * ROLLOVER.
5631          *
5632          * SOA: RFC1996
5633          * Check that 'from' is a valid notify source, (zone->masters).
5634          *      Return DNS_R_REFUSED if not.
5635          *
5636          * If the notify message contains a serial number check it
5637          * against the zones serial and return if <= current serial
5638          *
5639          * If a refresh check is progress, if so just record the
5640          * fact we received a NOTIFY and from where and return.
5641          * We will perform a new refresh check when the current one
5642          * completes. Return ISC_R_SUCCESS.
5643          *
5644          * Otherwise initiate a refresh check using 'from' as the
5645          * first address to check.  Return ISC_R_SUCCESS.
5646          */
5647
5648         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
5649
5650         /*
5651          *  We only handle NOTIFY (SOA) at the present.
5652          */
5653         LOCK_ZONE(zone);
5654         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
5655             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
5656                                  dns_rdatatype_soa, dns_rdatatype_none,
5657                                  NULL, NULL) != ISC_R_SUCCESS) {
5658                 UNLOCK_ZONE(zone);
5659                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
5660                         dns_zone_log(zone, ISC_LOG_NOTICE,
5661                                      "NOTIFY with no "
5662                                      "question section from: %s", fromtext);
5663                         return (DNS_R_FORMERR);
5664                 }
5665                 dns_zone_log(zone, ISC_LOG_NOTICE,
5666                              "NOTIFY zone does not match");
5667                 return (DNS_R_NOTIMP);
5668         }
5669
5670         /*
5671          * If we are a master zone just succeed.
5672          */
5673         if (zone->type == dns_zone_master) {
5674                 UNLOCK_ZONE(zone);
5675                 return (ISC_R_SUCCESS);
5676         }
5677
5678         isc_netaddr_fromsockaddr(&netaddr, from);
5679         for (i = 0; i < zone->masterscnt; i++) {
5680                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
5681                         break;
5682                 if (zone->view->aclenv.match_mapped &&
5683                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
5684                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
5685                         isc_netaddr_t na1, na2;
5686                         isc_netaddr_fromv4mapped(&na1, &netaddr);
5687                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
5688                         if (isc_netaddr_equal(&na1, &na2))
5689                                 break;
5690                 }
5691         }
5692
5693         /*
5694          * Accept notify requests from non masters if they are on
5695          * 'zone->notify_acl'.
5696          */
5697         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
5698             dns_acl_match(&netaddr, NULL, zone->notify_acl,
5699                           &zone->view->aclenv,
5700                           &match, NULL) == ISC_R_SUCCESS &&
5701             match > 0)
5702         {
5703                 /* Accept notify. */
5704         } else if (i >= zone->masterscnt) {
5705                 UNLOCK_ZONE(zone);
5706                 dns_zone_log(zone, ISC_LOG_INFO,
5707                              "refused notify from non-master: %s", fromtext);
5708                 return (DNS_R_REFUSED);
5709         }
5710
5711         /*
5712          * If the zone is loaded and there are answers check the serial
5713          * to see if we need to do a refresh.  Do not worry about this
5714          * check if we are a dialup zone as we use the notify request
5715          * to trigger a refresh check.
5716          */
5717         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
5718             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
5719             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
5720                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
5721                                               &zone->origin,
5722                                               dns_rdatatype_soa,
5723                                               dns_rdatatype_none, NULL,
5724                                               &rdataset);
5725                 if (result == ISC_R_SUCCESS)
5726                         result = dns_rdataset_first(rdataset);
5727                 if (result == ISC_R_SUCCESS) {
5728                         isc_uint32_t serial = 0;
5729
5730                         dns_rdataset_current(rdataset, &rdata);
5731                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
5732                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5733                         serial = soa.serial;
5734                         if (isc_serial_le(serial, zone->serial)) {
5735                           dns_zone_log(zone, ISC_LOG_INFO,
5736                                              "notify from %s: "
5737                                              "zone is up to date",
5738                                              fromtext);
5739                                 UNLOCK_ZONE(zone);
5740                                 return (ISC_R_SUCCESS);
5741                         }
5742                 }
5743         }
5744
5745         /*
5746          * If we got this far and there was a refresh in progress just
5747          * let it complete.  Record where we got the notify from so we
5748          * can perform a refresh check when the current one completes
5749          */
5750         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
5751                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
5752                 zone->notifyfrom = *from;
5753                 UNLOCK_ZONE(zone);
5754                 dns_zone_log(zone, ISC_LOG_INFO,
5755                              "notify from %s: refresh in progress, "
5756                              "refresh check queued",
5757                              fromtext);
5758                 return (ISC_R_SUCCESS);
5759         }
5760         zone->notifyfrom = *from;
5761         UNLOCK_ZONE(zone);
5762         dns_zone_refresh(zone);
5763         return (ISC_R_SUCCESS);
5764 }
5765
5766 void
5767 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
5768
5769         REQUIRE(DNS_ZONE_VALID(zone));
5770
5771         LOCK_ZONE(zone);
5772         if (zone->notify_acl != NULL)
5773                 dns_acl_detach(&zone->notify_acl);
5774         dns_acl_attach(acl, &zone->notify_acl);
5775         UNLOCK_ZONE(zone);
5776 }
5777
5778 void
5779 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
5780
5781         REQUIRE(DNS_ZONE_VALID(zone));
5782
5783         LOCK_ZONE(zone);
5784         if (zone->query_acl != NULL)
5785                 dns_acl_detach(&zone->query_acl);
5786         dns_acl_attach(acl, &zone->query_acl);
5787         UNLOCK_ZONE(zone);
5788 }
5789
5790 void
5791 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
5792
5793         REQUIRE(DNS_ZONE_VALID(zone));
5794
5795         LOCK_ZONE(zone);
5796         if (zone->update_acl != NULL)
5797                 dns_acl_detach(&zone->update_acl);
5798         dns_acl_attach(acl, &zone->update_acl);
5799         UNLOCK_ZONE(zone);
5800 }
5801
5802 void
5803 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
5804
5805         REQUIRE(DNS_ZONE_VALID(zone));
5806
5807         LOCK_ZONE(zone);
5808         if (zone->forward_acl != NULL)
5809                 dns_acl_detach(&zone->forward_acl);
5810         dns_acl_attach(acl, &zone->forward_acl);
5811         UNLOCK_ZONE(zone);
5812 }
5813
5814 void
5815 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
5816
5817         REQUIRE(DNS_ZONE_VALID(zone));
5818
5819         LOCK_ZONE(zone);
5820         if (zone->xfr_acl != NULL)
5821                 dns_acl_detach(&zone->xfr_acl);
5822         dns_acl_attach(acl, &zone->xfr_acl);
5823         UNLOCK_ZONE(zone);
5824 }
5825
5826 dns_acl_t *
5827 dns_zone_getnotifyacl(dns_zone_t *zone) {
5828
5829         REQUIRE(DNS_ZONE_VALID(zone));
5830
5831         return (zone->notify_acl);
5832 }
5833
5834 dns_acl_t *
5835 dns_zone_getqueryacl(dns_zone_t *zone) {
5836
5837         REQUIRE(DNS_ZONE_VALID(zone));
5838
5839         return (zone->query_acl);
5840 }
5841
5842 dns_acl_t *
5843 dns_zone_getupdateacl(dns_zone_t *zone) {
5844
5845         REQUIRE(DNS_ZONE_VALID(zone));
5846
5847         return (zone->update_acl);
5848 }
5849
5850 dns_acl_t *
5851 dns_zone_getforwardacl(dns_zone_t *zone) {
5852
5853         REQUIRE(DNS_ZONE_VALID(zone));
5854
5855         return (zone->forward_acl);
5856 }
5857
5858 dns_acl_t *
5859 dns_zone_getxfracl(dns_zone_t *zone) {
5860
5861         REQUIRE(DNS_ZONE_VALID(zone));
5862
5863         return (zone->xfr_acl);
5864 }
5865
5866 void
5867 dns_zone_clearupdateacl(dns_zone_t *zone) {
5868
5869         REQUIRE(DNS_ZONE_VALID(zone));
5870
5871         LOCK_ZONE(zone);
5872         if (zone->update_acl != NULL)
5873                 dns_acl_detach(&zone->update_acl);
5874         UNLOCK_ZONE(zone);
5875 }
5876
5877 void
5878 dns_zone_clearforwardacl(dns_zone_t *zone) {
5879
5880         REQUIRE(DNS_ZONE_VALID(zone));
5881
5882         LOCK_ZONE(zone);
5883         if (zone->forward_acl != NULL)
5884                 dns_acl_detach(&zone->forward_acl);
5885         UNLOCK_ZONE(zone);
5886 }
5887
5888 void
5889 dns_zone_clearnotifyacl(dns_zone_t *zone) {
5890
5891         REQUIRE(DNS_ZONE_VALID(zone));
5892
5893         LOCK_ZONE(zone);
5894         if (zone->notify_acl != NULL)
5895                 dns_acl_detach(&zone->notify_acl);
5896         UNLOCK_ZONE(zone);
5897 }
5898
5899 void
5900 dns_zone_clearqueryacl(dns_zone_t *zone) {
5901
5902         REQUIRE(DNS_ZONE_VALID(zone));
5903
5904         LOCK_ZONE(zone);
5905         if (zone->query_acl != NULL)
5906                 dns_acl_detach(&zone->query_acl);
5907         UNLOCK_ZONE(zone);
5908 }
5909
5910 void
5911 dns_zone_clearxfracl(dns_zone_t *zone) {
5912
5913         REQUIRE(DNS_ZONE_VALID(zone));
5914
5915         LOCK_ZONE(zone);
5916         if (zone->xfr_acl != NULL)
5917                 dns_acl_detach(&zone->xfr_acl);
5918         UNLOCK_ZONE(zone);
5919 }
5920
5921 isc_boolean_t
5922 dns_zone_getupdatedisabled(dns_zone_t *zone) {
5923         REQUIRE(DNS_ZONE_VALID(zone));
5924         return (zone->update_disabled);
5925
5926 }
5927
5928 void
5929 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
5930         REQUIRE(DNS_ZONE_VALID(zone));
5931         zone->update_disabled = state;
5932 }
5933
5934 isc_boolean_t
5935 dns_zone_getzeronosoattl(dns_zone_t *zone) {
5936         REQUIRE(DNS_ZONE_VALID(zone));
5937         return (zone->zero_no_soa_ttl);
5938
5939 }
5940
5941 void
5942 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
5943         REQUIRE(DNS_ZONE_VALID(zone));
5944         zone->zero_no_soa_ttl = state;
5945 }
5946
5947 void
5948 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
5949
5950         REQUIRE(DNS_ZONE_VALID(zone));
5951
5952         zone->check_names = severity;
5953 }
5954
5955 dns_severity_t
5956 dns_zone_getchecknames(dns_zone_t *zone) {
5957
5958         REQUIRE(DNS_ZONE_VALID(zone));
5959
5960         return (zone->check_names);
5961 }
5962
5963 void
5964 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
5965
5966         REQUIRE(DNS_ZONE_VALID(zone));
5967
5968         zone->journalsize = size;
5969 }
5970
5971 isc_int32_t
5972 dns_zone_getjournalsize(dns_zone_t *zone) {
5973
5974         REQUIRE(DNS_ZONE_VALID(zone));
5975
5976         return (zone->journalsize);
5977 }
5978
5979 static void
5980 zone_tostr(dns_zone_t *zone, char *buf, size_t length) {
5981         isc_result_t result = ISC_R_FAILURE;
5982         isc_buffer_t buffer;
5983
5984         REQUIRE(buf != NULL);
5985         REQUIRE(length > 1U);
5986
5987         /*
5988          * Leave space for terminating '\0'.
5989          */
5990         isc_buffer_init(&buffer, buf, length - 1);
5991         if (dns_name_dynamic(&zone->origin))
5992                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
5993         if (result != ISC_R_SUCCESS &&
5994             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
5995                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
5996
5997         if (isc_buffer_availablelength(&buffer) > 0)
5998                 isc_buffer_putstr(&buffer, "/");
5999         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
6000
6001         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
6002             strcmp(zone->view->name, "_default") != 0 &&
6003             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
6004                 isc_buffer_putstr(&buffer, "/");
6005                 isc_buffer_putstr(&buffer, zone->view->name);
6006         }
6007
6008         buf[isc_buffer_usedlength(&buffer)] = '\0';
6009 }
6010
6011 void
6012 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
6013         REQUIRE(DNS_ZONE_VALID(zone));
6014         REQUIRE(buf != NULL);
6015         zone_tostr(zone, buf, length);
6016 }
6017
6018 static void
6019 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
6020         va_list ap;
6021         char message[4096];
6022         char namebuf[1024+32];
6023
6024         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
6025                 return;
6026
6027         zone_tostr(zone, namebuf, sizeof(namebuf));
6028
6029         va_start(ap, fmt);
6030         vsnprintf(message, sizeof(message), fmt, ap);
6031         va_end(ap);
6032         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
6033                       level, "zone %s: %s", namebuf, message);
6034 }
6035
6036 void
6037 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
6038               int level, const char *fmt, ...) {
6039         va_list ap;
6040         char message[4096];
6041         char namebuf[1024+32];
6042
6043         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
6044                 return;
6045
6046         zone_tostr(zone, namebuf, sizeof(namebuf));
6047
6048         va_start(ap, fmt);
6049         vsnprintf(message, sizeof(message), fmt, ap);
6050         va_end(ap);
6051         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
6052                       level, "zone %s: %s", namebuf, message);
6053 }
6054
6055 void
6056 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
6057         va_list ap;
6058         char message[4096];
6059         char namebuf[1024+32];
6060
6061         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
6062                 return;
6063
6064         zone_tostr(zone, namebuf, sizeof(namebuf));
6065
6066         va_start(ap, fmt);
6067         vsnprintf(message, sizeof(message), fmt, ap);
6068         va_end(ap);
6069         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
6070                       level, "zone %s: %s", namebuf, message);
6071 }
6072
6073 static void
6074 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
6075               const char *fmt, ...)
6076 {
6077         va_list ap;
6078         char message[4096];
6079         char namebuf[1024+32];
6080         int level = ISC_LOG_DEBUG(debuglevel);
6081
6082         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
6083                 return;
6084
6085         zone_tostr(zone, namebuf, sizeof(namebuf));
6086
6087         va_start(ap, fmt);
6088         vsnprintf(message, sizeof(message), fmt, ap);
6089         va_end(ap);
6090         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
6091                       level, "%s: zone %s: %s", me, namebuf, message);
6092 }
6093
6094 static int
6095 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
6096 {
6097         isc_result_t result;
6098         dns_name_t *name;
6099         dns_rdataset_t *curr;
6100         int count = 0;
6101
6102         result = dns_message_firstname(msg, section);
6103         while (result == ISC_R_SUCCESS) {
6104                 name = NULL;
6105                 dns_message_currentname(msg, section, &name);
6106
6107                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
6108                      curr = ISC_LIST_PREV(curr, link)) {
6109                         if (curr->type == type)
6110                                 count++;
6111                 }
6112                 result = dns_message_nextname(msg, section);
6113         }
6114
6115         return (count);
6116 }
6117
6118 void
6119 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
6120         REQUIRE(DNS_ZONE_VALID(zone));
6121
6122         zone->maxxfrin = maxxfrin;
6123 }
6124
6125 isc_uint32_t
6126 dns_zone_getmaxxfrin(dns_zone_t *zone) {
6127         REQUIRE(DNS_ZONE_VALID(zone));
6128
6129         return (zone->maxxfrin);
6130 }
6131
6132 void
6133 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
6134         REQUIRE(DNS_ZONE_VALID(zone));
6135         zone->maxxfrout = maxxfrout;
6136 }
6137
6138 isc_uint32_t
6139 dns_zone_getmaxxfrout(dns_zone_t *zone) {
6140         REQUIRE(DNS_ZONE_VALID(zone));
6141
6142         return (zone->maxxfrout);
6143 }
6144
6145 dns_zonetype_t
6146 dns_zone_gettype(dns_zone_t *zone) {
6147         REQUIRE(DNS_ZONE_VALID(zone));
6148
6149         return (zone->type);
6150 }
6151
6152 dns_name_t *
6153 dns_zone_getorigin(dns_zone_t *zone) {
6154         REQUIRE(DNS_ZONE_VALID(zone));
6155
6156         return (&zone->origin);
6157 }
6158
6159 void
6160 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
6161         REQUIRE(DNS_ZONE_VALID(zone));
6162
6163         LOCK_ZONE(zone);
6164         if (zone->task != NULL)
6165                 isc_task_detach(&zone->task);
6166         isc_task_attach(task, &zone->task);
6167         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6168         if (zone->db != NULL)
6169                 dns_db_settask(zone->db, zone->task);
6170         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6171         UNLOCK_ZONE(zone);
6172 }
6173
6174 void
6175 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
6176         REQUIRE(DNS_ZONE_VALID(zone));
6177         isc_task_attach(zone->task, target);
6178 }
6179
6180 void
6181 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
6182         REQUIRE(DNS_ZONE_VALID(zone));
6183
6184         if (idlein == 0)
6185                 idlein = DNS_DEFAULT_IDLEIN;
6186         zone->idlein = idlein;
6187 }
6188
6189 isc_uint32_t
6190 dns_zone_getidlein(dns_zone_t *zone) {
6191         REQUIRE(DNS_ZONE_VALID(zone));
6192
6193         return (zone->idlein);
6194 }
6195
6196 void
6197 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
6198         REQUIRE(DNS_ZONE_VALID(zone));
6199
6200         zone->idleout = idleout;
6201 }
6202
6203 isc_uint32_t
6204 dns_zone_getidleout(dns_zone_t *zone) {
6205         REQUIRE(DNS_ZONE_VALID(zone));
6206
6207         return (zone->idleout);
6208 }
6209
6210 static void
6211 notify_done(isc_task_t *task, isc_event_t *event) {
6212         dns_requestevent_t *revent = (dns_requestevent_t *)event;
6213         dns_notify_t *notify;
6214         isc_result_t result;
6215         dns_message_t *message = NULL;
6216         isc_buffer_t buf;
6217         char rcode[128];
6218         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6219
6220         UNUSED(task);
6221
6222         notify = event->ev_arg;
6223         REQUIRE(DNS_NOTIFY_VALID(notify));
6224         INSIST(task == notify->zone->task);
6225
6226         isc_buffer_init(&buf, rcode, sizeof(rcode));
6227         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
6228
6229         result = revent->result;
6230         if (result == ISC_R_SUCCESS)
6231                 result = dns_message_create(notify->zone->mctx,
6232                                             DNS_MESSAGE_INTENTPARSE, &message);
6233         if (result == ISC_R_SUCCESS)
6234                 result = dns_request_getresponse(revent->request, message,
6235                                         DNS_MESSAGEPARSE_PRESERVEORDER);
6236         if (result == ISC_R_SUCCESS)
6237                 result = dns_rcode_totext(message->rcode, &buf);
6238         if (result == ISC_R_SUCCESS)
6239                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
6240                            "notify response from %s: %.*s",
6241                            addrbuf, (int)buf.used, rcode);
6242         else
6243                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
6244                            "notify to %s failed: %s", addrbuf,
6245                            dns_result_totext(result));
6246
6247         /*
6248          * Old bind's return formerr if they see a soa record.  Retry w/o
6249          * the soa if we see a formerr and had sent a SOA.
6250          */
6251         isc_event_free(&event);
6252         if (message != NULL && message->rcode == dns_rcode_formerr &&
6253             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
6254                 notify->flags |= DNS_NOTIFY_NOSOA;
6255                 dns_request_destroy(&notify->request);
6256                 result = notify_send_queue(notify);
6257                 if (result != ISC_R_SUCCESS)
6258                         notify_destroy(notify, ISC_FALSE);
6259         } else {
6260                 if (result == ISC_R_TIMEDOUT)
6261                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
6262                                    "notify to %s: retries exceeded", addrbuf);
6263                 notify_destroy(notify, ISC_FALSE);
6264         }
6265         if (message != NULL)
6266                 dns_message_destroy(&message);
6267 }
6268
6269 isc_result_t
6270 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
6271         isc_result_t result;
6272
6273         REQUIRE(DNS_ZONE_VALID(zone));
6274         LOCK_ZONE(zone);
6275         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6276         result = zone_replacedb(zone, db, dump);
6277         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6278         UNLOCK_ZONE(zone);
6279         return (result);
6280 }
6281
6282 static isc_result_t
6283 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
6284         dns_dbversion_t *ver;
6285         isc_result_t result;
6286         unsigned int soacount = 0;
6287         unsigned int nscount = 0;
6288
6289         /*
6290          * 'zone' and 'zonedb' locked by caller.
6291          */
6292         REQUIRE(DNS_ZONE_VALID(zone));
6293         REQUIRE(LOCKED_ZONE(zone));
6294
6295         result = zone_get_from_db(zone, db, &nscount, &soacount,
6296                                   NULL, NULL, NULL, NULL, NULL, NULL);
6297         if (result == ISC_R_SUCCESS) {
6298                 if (soacount != 1) {
6299                         dns_zone_log(zone, ISC_LOG_ERROR,
6300                                      "has %d SOA records", soacount);
6301                         result = DNS_R_BADZONE;
6302                 }
6303                 if (nscount == 0) {
6304                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
6305                         result = DNS_R_BADZONE;
6306                 }
6307                 if (result != ISC_R_SUCCESS)
6308                         return (result);
6309         } else {
6310                 dns_zone_log(zone, ISC_LOG_ERROR,
6311                             "retrieving SOA and NS records failed: %s",
6312                             dns_result_totext(result));
6313                 return (result);
6314         }
6315
6316         ver = NULL;
6317         dns_db_currentversion(db, &ver);
6318
6319         /*
6320          * The initial version of a slave zone is always dumped;
6321          * subsequent versions may be journalled instead if this
6322          * is enabled in the configuration.
6323          */
6324         if (zone->db != NULL && zone->journal != NULL &&
6325             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
6326             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
6327                 isc_uint32_t serial;
6328
6329                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
6330
6331                 result = dns_db_getsoaserial(db, ver, &serial);
6332                 if (result != ISC_R_SUCCESS) {
6333                         dns_zone_log(zone, ISC_LOG_ERROR,
6334                                      "ixfr-from-differences: unable to get "
6335                                      "new serial");
6336                         goto fail;
6337                 }
6338
6339                 /*
6340                  * This is checked in zone_postload() for master zones.
6341                  */
6342                 if (zone->type == dns_zone_slave &&
6343                     !isc_serial_gt(serial, zone->serial)) {
6344                         isc_uint32_t serialmin, serialmax;
6345                         serialmin = (zone->serial + 1) & 0xffffffffU;
6346                         serialmax = (zone->serial + 0x7fffffffU) & 0xffffffffU;
6347                         dns_zone_log(zone, ISC_LOG_ERROR,
6348                                      "ixfr-from-differences: failed: "
6349                                      "new serial (%u) out of range [%u - %u]",
6350                                      serial, serialmin, serialmax);
6351                         result = ISC_R_RANGE;
6352                         goto fail;
6353                 }
6354
6355                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
6356                                      zone->journal);
6357                 if (result != ISC_R_SUCCESS)
6358                         goto fail;
6359                 if (dump)
6360                         zone_needdump(zone, DNS_DUMP_DELAY);
6361                 else if (zone->journalsize != -1) {
6362                         result = dns_journal_compact(zone->mctx, zone->journal,
6363                                                      serial, zone->journalsize);
6364                         switch (result) {
6365                         case ISC_R_SUCCESS:
6366                         case ISC_R_NOSPACE:
6367                         case ISC_R_NOTFOUND:
6368                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
6369                                              "dns_journal_compact: %s",
6370                                              dns_result_totext(result));
6371                                 break;
6372                         default:
6373                                 dns_zone_log(zone, ISC_LOG_ERROR,
6374                                              "dns_journal_compact failed: %s",
6375                                              dns_result_totext(result));
6376                                 break;
6377                         }
6378                 }
6379         } else {
6380                 if (dump && zone->masterfile != NULL) {
6381                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
6382                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
6383                                       "dumping new zone version");
6384                         result = dns_db_dump2(db, ver, zone->masterfile,
6385                                               zone->masterformat);
6386                         if (result != ISC_R_SUCCESS)
6387                                 goto fail;
6388
6389                         /*
6390                          * Update the time the zone was updated, so
6391                          * dns_zone_load can avoid loading it when
6392                          * the server is reloaded.  If isc_time_now
6393                          * fails for some reason, all that happens is
6394                          * the timestamp is not updated.
6395                          */
6396                         TIME_NOW(&zone->loadtime);
6397                 }
6398
6399                 if (dump && zone->journal != NULL) {
6400                         /*
6401                          * The in-memory database just changed, and
6402                          * because 'dump' is set, it didn't change by
6403                          * being loaded from disk.  Also, we have not
6404                          * journalled diffs for this change.
6405                          * Therefore, the on-disk journal is missing
6406                          * the deltas for this change.  Since it can
6407                          * no longer be used to bring the zone
6408                          * up-to-date, it is useless and should be
6409                          * removed.
6410                          */
6411                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
6412                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
6413                                       "removing journal file");
6414                         (void)remove(zone->journal);
6415                 }
6416         }
6417
6418         dns_db_closeversion(db, &ver, ISC_FALSE);
6419
6420         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
6421                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
6422                       "replacing zone database");
6423
6424         if (zone->db != NULL)
6425                 zone_detachdb(zone);
6426         zone_attachdb(zone, db);
6427         dns_db_settask(zone->db, zone->task);
6428         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
6429         return (ISC_R_SUCCESS);
6430
6431  fail:
6432         dns_db_closeversion(db, &ver, ISC_FALSE);
6433         return (result);
6434 }
6435
6436 /* The caller must hold the dblock as a writer. */
6437 static inline void
6438 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
6439         REQUIRE(zone->db == NULL && db != NULL);
6440
6441         dns_db_attach(db, &zone->db);
6442         if (zone->acache != NULL) {
6443                 isc_result_t result;
6444                 result = dns_acache_setdb(zone->acache, db);
6445                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
6446                         UNEXPECTED_ERROR(__FILE__, __LINE__,
6447                                          "dns_acache_setdb() failed: %s",
6448                                          isc_result_totext(result));
6449                 }
6450         }
6451 }
6452
6453 /* The caller must hold the dblock as a writer. */
6454 static inline void
6455 zone_detachdb(dns_zone_t *zone) {
6456         REQUIRE(zone->db != NULL);
6457
6458         if (zone->acache != NULL)
6459                 (void)dns_acache_putdb(zone->acache, zone->db);
6460         dns_db_detach(&zone->db);
6461 }
6462
6463 static void
6464 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
6465         isc_time_t now;
6466         isc_boolean_t again = ISC_FALSE;
6467         unsigned int soacount;
6468         unsigned int nscount;
6469         isc_uint32_t serial, refresh, retry, expire, minimum;
6470         isc_result_t xfrresult = result;
6471         isc_boolean_t free_needed;
6472
6473         REQUIRE(DNS_ZONE_VALID(zone));
6474
6475         dns_zone_log(zone, ISC_LOG_DEBUG(1),
6476                      "zone transfer finished: %s", dns_result_totext(result));
6477
6478         LOCK_ZONE(zone);
6479         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
6480         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
6481         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
6482
6483         TIME_NOW(&now);
6484         switch (result) {
6485         case ISC_R_SUCCESS:
6486                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6487                 /*FALLTHROUGH*/
6488         case DNS_R_UPTODATE:
6489                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
6490                 /*
6491                  * Has the zone expired underneath us?
6492                  */
6493                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6494                 if (zone->db == NULL) {
6495                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6496                         goto same_master;
6497                 }
6498
6499                 /*
6500                  * Update the zone structure's data from the actual
6501                  * SOA received.
6502                  */
6503                 nscount = 0;
6504                 soacount = 0;
6505                 INSIST(zone->db != NULL);
6506                 result = zone_get_from_db(zone, zone->db, &nscount,
6507                                           &soacount, &serial, &refresh,
6508                                           &retry, &expire, &minimum, NULL);
6509                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6510                 if (result == ISC_R_SUCCESS) {
6511                         if (soacount != 1)
6512                                 dns_zone_log(zone, ISC_LOG_ERROR,
6513                                              "transferred zone "
6514                                              "has %d SOA record%s", soacount,
6515                                              (soacount != 0) ? "s" : "");
6516                         if (nscount == 0) {
6517                                 dns_zone_log(zone, ISC_LOG_ERROR,
6518                                              "transferred zone "
6519                                              "has no NS records");
6520                                 if (DNS_ZONE_FLAG(zone,
6521                                                   DNS_ZONEFLG_HAVETIMERS)) {
6522                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
6523                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
6524                                 }
6525                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
6526                                 zone_unload(zone);
6527                                 goto next_master;
6528                         }
6529                         zone->serial = serial;
6530                         zone->refresh = RANGE(refresh, zone->minrefresh,
6531                                               zone->maxrefresh);
6532                         zone->retry = RANGE(retry, zone->minretry,
6533                                             zone->maxretry);
6534                         zone->expire = RANGE(expire,
6535                                              zone->refresh + zone->retry,
6536                                              DNS_MAX_EXPIRE);
6537                         zone->minimum = minimum;
6538                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
6539                 }
6540
6541                 /*
6542                  * Set our next update/expire times.
6543                  */
6544                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
6545                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
6546                         zone->refreshtime = now;
6547                         DNS_ZONE_TIME_ADD(&now, zone->expire,
6548                                           &zone->expiretime);
6549                 } else {
6550                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
6551                                             &zone->refreshtime);
6552                         DNS_ZONE_TIME_ADD(&now, zone->expire,
6553                                           &zone->expiretime);
6554                 }
6555                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
6556                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
6557                         if (zone->tsigkey != NULL) {
6558                                 char namebuf[DNS_NAME_FORMATSIZE];
6559                                 dns_name_format(&zone->tsigkey->name, namebuf,
6560                                                 sizeof(namebuf));
6561                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
6562                                          namebuf);
6563                         } else
6564                                 buf[0] = '\0';
6565                         dns_zone_log(zone, ISC_LOG_INFO,
6566                                      "transferred serial %u%s",
6567                                      zone->serial, buf);
6568                 }
6569
6570                 /*
6571                  * This is not neccessary if we just performed a AXFR
6572                  * however it is necessary for an IXFR / UPTODATE and
6573                  * won't hurt with an AXFR.
6574                  */
6575                 if (zone->masterfile != NULL || zone->journal != NULL) {
6576                         result = ISC_R_FAILURE;
6577                         if (zone->journal != NULL)
6578                                 result = isc_file_settime(zone->journal, &now);
6579                         if (result != ISC_R_SUCCESS &&
6580                             zone->masterfile != NULL)
6581                                 result = isc_file_settime(zone->masterfile,
6582                                                           &now);
6583                         /* Someone removed the file from underneath us! */
6584                         if (result == ISC_R_FILENOTFOUND &&
6585                             zone->masterfile != NULL)
6586                                 zone_needdump(zone, DNS_DUMP_DELAY);
6587                         else if (result != ISC_R_SUCCESS)
6588                                 dns_zone_log(zone, ISC_LOG_ERROR,
6589                                              "transfer: could not set file "
6590                                              "modification time of '%s': %s",
6591                                              zone->masterfile,
6592                                              dns_result_totext(result));
6593                 }
6594
6595                 break;
6596
6597         case DNS_R_BADIXFR:
6598                 /* Force retry with AXFR. */
6599                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
6600                 goto same_master;
6601
6602         default:
6603         next_master:
6604                 /*
6605                  * Skip to next failed / untried master.
6606                  */
6607                 do {
6608                         zone->curmaster++;
6609                 } while (zone->curmaster < zone->masterscnt &&
6610                          zone->mastersok[zone->curmaster]);
6611                 /* FALLTHROUGH */
6612         same_master:
6613                 if (zone->curmaster >= zone->masterscnt) {
6614                         zone->curmaster = 0;
6615                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
6616                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
6617                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
6618                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
6619                                 while (zone->curmaster < zone->masterscnt &&
6620                                        zone->mastersok[zone->curmaster])
6621                                         zone->curmaster++;
6622                                 again = ISC_TRUE;
6623                         } else
6624                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
6625                 } else {
6626                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
6627                         again = ISC_TRUE;
6628                 }
6629                 break;
6630         }
6631         zone_settimer(zone, &now);
6632
6633         /*
6634          * If creating the transfer object failed, zone->xfr is NULL.
6635          * Otherwise, we are called as the done callback of a zone
6636          * transfer object that just entered its shutting-down
6637          * state.  Since we are no longer responsible for shutting
6638          * it down, we can detach our reference.
6639          */
6640         if (zone->xfr != NULL)
6641                 dns_xfrin_detach(&zone->xfr);
6642
6643         if (zone->tsigkey != NULL)
6644                 dns_tsigkey_detach(&zone->tsigkey);
6645
6646         /*
6647          * Handle any deferred journal compaction.
6648          */
6649         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
6650                 result = dns_journal_compact(zone->mctx, zone->journal,
6651                                              zone->compact_serial,
6652                                              zone->journalsize);
6653                 switch (result) {
6654                 case ISC_R_SUCCESS:
6655                 case ISC_R_NOSPACE:
6656                 case ISC_R_NOTFOUND:
6657                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
6658                                      "dns_journal_compact: %s",
6659                                      dns_result_totext(result));
6660                         break;
6661                 default:
6662                         dns_zone_log(zone, ISC_LOG_ERROR,
6663                                      "dns_journal_compact failed: %s",
6664                                      dns_result_totext(result));
6665                         break;
6666                 }
6667                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
6668         }
6669
6670         /*
6671          * This transfer finishing freed up a transfer quota slot.
6672          * Let any other zones waiting for quota have it.
6673          */
6674         RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
6675         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
6676         zone->statelist = NULL;
6677         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
6678         RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
6679
6680         /*
6681          * Retry with a different server if necessary.
6682          */
6683         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
6684                 queue_soa_query(zone);
6685
6686         INSIST(zone->irefs > 0);
6687         zone->irefs--;
6688         free_needed = exit_check(zone);
6689         UNLOCK_ZONE(zone);
6690         if (free_needed)
6691                 zone_free(zone);
6692 }
6693
6694 static void
6695 zone_loaddone(void *arg, isc_result_t result) {
6696         static char me[] = "zone_loaddone";
6697         dns_load_t *load = arg;
6698         dns_zone_t *zone;
6699         isc_result_t tresult;
6700
6701         REQUIRE(DNS_LOAD_VALID(load));
6702         zone = load->zone;
6703
6704         ENTER;
6705
6706         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
6707         if (tresult != ISC_R_SUCCESS &&
6708             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
6709                 result = tresult;
6710
6711         LOCK_ZONE(load->zone);
6712         (void)zone_postload(load->zone, load->db, load->loadtime, result);
6713         zonemgr_putio(&load->zone->readio);
6714         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
6715         UNLOCK_ZONE(load->zone);
6716
6717         load->magic = 0;
6718         dns_db_detach(&load->db);
6719         if (load->zone->lctx != NULL)
6720                 dns_loadctx_detach(&load->zone->lctx);
6721         dns_zone_idetach(&load->zone);
6722         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
6723 }
6724
6725 void
6726 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
6727         REQUIRE(DNS_ZONE_VALID(zone));
6728         REQUIRE(table != NULL);
6729         REQUIRE(*table == NULL);
6730
6731         LOCK_ZONE(zone);
6732         if (zone->ssutable != NULL)
6733                 dns_ssutable_attach(zone->ssutable, table);
6734         UNLOCK_ZONE(zone);
6735 }
6736
6737 void
6738 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
6739         REQUIRE(DNS_ZONE_VALID(zone));
6740
6741         LOCK_ZONE(zone);
6742         if (zone->ssutable != NULL)
6743                 dns_ssutable_detach(&zone->ssutable);
6744         if (table != NULL)
6745                 dns_ssutable_attach(table, &zone->ssutable);
6746         UNLOCK_ZONE(zone);
6747 }
6748
6749 void
6750 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
6751         REQUIRE(DNS_ZONE_VALID(zone));
6752
6753         zone->sigvalidityinterval = interval;
6754 }
6755
6756 isc_uint32_t
6757 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
6758         REQUIRE(DNS_ZONE_VALID(zone));
6759
6760         return (zone->sigvalidityinterval);
6761 }
6762
6763 static void
6764 queue_xfrin(dns_zone_t *zone) {
6765         const char me[] = "queue_xfrin";
6766         isc_result_t result;
6767         dns_zonemgr_t *zmgr = zone->zmgr;
6768
6769         ENTER;
6770
6771         INSIST(zone->statelist == NULL);
6772
6773         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6774         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
6775         LOCK_ZONE(zone);
6776         zone->irefs++;
6777         UNLOCK_ZONE(zone);
6778         zone->statelist = &zmgr->waiting_for_xfrin;
6779         result = zmgr_start_xfrin_ifquota(zmgr, zone);
6780         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
6781
6782         if (result == ISC_R_QUOTA) {
6783                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
6784                               "zone transfer deferred due to quota");
6785         } else if (result != ISC_R_SUCCESS) {
6786                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
6787                               "starting zone transfer: %s",
6788                               isc_result_totext(result));
6789         }
6790 }
6791
6792 /*
6793  * This event callback is called when a zone has received
6794  * any necessary zone transfer quota.  This is the time
6795  * to go ahead and start the transfer.
6796  */
6797 static void
6798 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
6799         isc_result_t result;
6800         dns_peer_t *peer = NULL;
6801         char mastertext[256];
6802         dns_rdatatype_t xfrtype;
6803         dns_zone_t *zone = event->ev_arg;
6804         isc_netaddr_t masterip;
6805         isc_sockaddr_t sourceaddr;
6806         isc_sockaddr_t masteraddr;
6807
6808         UNUSED(task);
6809
6810         INSIST(task == zone->task);
6811
6812         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
6813                 result = ISC_R_CANCELED;
6814                 goto cleanup;
6815         }
6816
6817         isc_sockaddr_format(&zone->masteraddr, mastertext, sizeof(mastertext));
6818
6819         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
6820         (void)dns_peerlist_peerbyaddr(zone->view->peers,
6821                                       &masterip, &peer);
6822
6823         /*
6824          * Decide whether we should request IXFR or AXFR.
6825          */
6826         if (zone->db == NULL) {
6827                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
6828                              "no database exists yet, "
6829                              "requesting AXFR of "
6830                              "initial version from %s", mastertext);
6831                 xfrtype = dns_rdatatype_axfr;
6832         } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
6833                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
6834                              "set, requesting AXFR from %s", mastertext);
6835                 xfrtype = dns_rdatatype_axfr;
6836         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
6837                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
6838                              "forced reload, requesting AXFR of "
6839                              "initial version from %s", mastertext);
6840                 xfrtype = dns_rdatatype_axfr;
6841         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
6842                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
6843                              "retrying with AXFR from %s due to "
6844                              "previous IXFR failure", mastertext);
6845                 xfrtype = dns_rdatatype_axfr;
6846                 LOCK_ZONE(zone);
6847                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
6848                 UNLOCK_ZONE(zone);
6849         } else {
6850                 isc_boolean_t use_ixfr = ISC_TRUE;
6851                 if (peer != NULL &&
6852                     dns_peer_getrequestixfr(peer, &use_ixfr) ==
6853                     ISC_R_SUCCESS) {
6854                         ; /* Using peer setting */
6855                 } else {
6856                         use_ixfr = zone->view->requestixfr;
6857                 }
6858                 if (use_ixfr == ISC_FALSE) {
6859                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
6860                                      "IXFR disabled, "
6861                                      "requesting AXFR from %s",
6862                                      mastertext);
6863                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
6864                                 xfrtype = dns_rdatatype_soa;
6865                         else
6866                                 xfrtype = dns_rdatatype_axfr;
6867                 } else {
6868                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
6869                                      "requesting IXFR from %s",
6870                                      mastertext);
6871                         xfrtype = dns_rdatatype_ixfr;
6872                 }
6873         }
6874
6875         /*
6876          * Determine if we should attempt to sign the request with TSIG.
6877          */
6878         result = ISC_R_NOTFOUND;
6879         /*
6880          * First, look for a tsig key in the master statement, then
6881          * try for a server key.
6882          */
6883         if ((zone->masterkeynames != NULL) &&
6884             (zone->masterkeynames[zone->curmaster] != NULL)) {
6885                 dns_view_t *view = dns_zone_getview(zone);
6886                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
6887                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
6888         }
6889         if (zone->tsigkey == NULL)
6890                 result = dns_view_getpeertsig(zone->view, &masterip,
6891                                               &zone->tsigkey);
6892
6893         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6894                 dns_zone_log(zone, ISC_LOG_ERROR,
6895                              "could not get TSIG key "
6896                              "for zone transfer: %s",
6897                              isc_result_totext(result));
6898         }
6899
6900         LOCK_ZONE(zone);
6901         masteraddr = zone->masteraddr;
6902         sourceaddr = zone->sourceaddr;
6903         UNLOCK_ZONE(zone);
6904         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
6905         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
6906                                    zone->tsigkey, zone->mctx,
6907                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
6908                                    zone->task, zone_xfrdone, &zone->xfr);
6909  cleanup:
6910         /*
6911          * Any failure in this function is handled like a failed
6912          * zone transfer.  This ensures that we get removed from
6913          * zmgr->xfrin_in_progress.
6914          */
6915         if (result != ISC_R_SUCCESS)
6916                 zone_xfrdone(zone, result);
6917
6918         isc_event_free(&event);
6919 }
6920
6921 /*
6922  * Update forwarding support.
6923  */
6924
6925 static void
6926 forward_destroy(dns_forward_t *forward) {
6927
6928         forward->magic = 0;
6929         if (forward->request != NULL)
6930                 dns_request_destroy(&forward->request);
6931         if (forward->msgbuf != NULL)
6932                 isc_buffer_free(&forward->msgbuf);
6933         if (forward->zone != NULL)
6934                 dns_zone_idetach(&forward->zone);
6935         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
6936 }
6937
6938 static isc_result_t
6939 sendtomaster(dns_forward_t *forward) {
6940         isc_result_t result;
6941         isc_sockaddr_t src;
6942
6943         LOCK_ZONE(forward->zone);
6944         if (forward->which >= forward->zone->masterscnt) {
6945                 UNLOCK_ZONE(forward->zone);
6946                 return (ISC_R_NOMORE);
6947         }
6948
6949         forward->addr = forward->zone->masters[forward->which];
6950         /*
6951          * Always use TCP regardless of whether the original update
6952          * used TCP.
6953          * XXX The timeout may but a bit small if we are far down a
6954          * transfer graph and the master has to try several masters.
6955          */
6956         switch (isc_sockaddr_pf(&forward->addr)) {
6957         case PF_INET:
6958                 src = forward->zone->xfrsource4;
6959                 break;
6960         case PF_INET6:
6961                 src = forward->zone->xfrsource6;
6962                 break;
6963         default:
6964                 result = ISC_R_NOTIMPLEMENTED;
6965                 goto unlock;
6966         }
6967         result = dns_request_createraw(forward->zone->view->requestmgr,
6968                                        forward->msgbuf,
6969                                        &src, &forward->addr,
6970                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
6971                                        forward->zone->task,
6972                                        forward_callback, forward,
6973                                        &forward->request);
6974  unlock:
6975         UNLOCK_ZONE(forward->zone);
6976         return (result);
6977 }
6978
6979 static void
6980 forward_callback(isc_task_t *task, isc_event_t *event) {
6981         const char me[] = "forward_callback";
6982         dns_requestevent_t *revent = (dns_requestevent_t *)event;
6983         dns_message_t *msg = NULL;
6984         char master[ISC_SOCKADDR_FORMATSIZE];
6985         isc_result_t result;
6986         dns_forward_t *forward;
6987         dns_zone_t *zone;
6988
6989         UNUSED(task);
6990
6991         forward = revent->ev_arg;
6992         INSIST(DNS_FORWARD_VALID(forward));
6993         zone = forward->zone;
6994         INSIST(DNS_ZONE_VALID(zone));
6995
6996         ENTER;
6997
6998         isc_sockaddr_format(&forward->addr, master, sizeof(master));
6999
7000         if (revent->result != ISC_R_SUCCESS) {
7001                 dns_zone_log(zone, ISC_LOG_INFO,
7002                              "could not forward dynamic update to %s: %s",
7003                              master, dns_result_totext(revent->result));
7004                 goto next_master;
7005         }
7006
7007         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
7008         if (result != ISC_R_SUCCESS)
7009                 goto next_master;
7010
7011         result = dns_request_getresponse(revent->request, msg,
7012                                          DNS_MESSAGEPARSE_PRESERVEORDER |
7013                                          DNS_MESSAGEPARSE_CLONEBUFFER);
7014         if (result != ISC_R_SUCCESS)
7015                 goto next_master;
7016
7017         switch (msg->rcode) {
7018         /*
7019          * Pass these rcodes back to client.
7020          */
7021         case dns_rcode_noerror:
7022         case dns_rcode_yxdomain:
7023         case dns_rcode_yxrrset:
7024         case dns_rcode_nxrrset:
7025         case dns_rcode_refused:
7026         case dns_rcode_nxdomain:
7027                 break;
7028
7029         /* These should not occur if the masters/zone are valid. */
7030         case dns_rcode_notzone:
7031         case dns_rcode_notauth: {
7032                 char rcode[128];
7033                 isc_buffer_t rb;
7034
7035                 isc_buffer_init(&rb, rcode, sizeof(rcode));
7036                 (void)dns_rcode_totext(msg->rcode, &rb);
7037                 dns_zone_log(zone, ISC_LOG_WARNING,
7038                              "forwarding dynamic update: "
7039                              "unexpected response: master %s returned: %.*s",
7040                              master, (int)rb.used, rcode);
7041                 goto next_master;
7042         }
7043
7044         /* Try another server for these rcodes. */
7045         case dns_rcode_formerr:
7046         case dns_rcode_servfail:
7047         case dns_rcode_notimp:
7048         case dns_rcode_badvers:
7049         default:
7050                 goto next_master;
7051         }
7052
7053         /* call callback */
7054         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
7055         msg = NULL;
7056         dns_request_destroy(&forward->request);
7057         forward_destroy(forward);
7058         isc_event_free(&event);
7059         return;
7060
7061  next_master:
7062         if (msg != NULL)
7063                 dns_message_destroy(&msg);
7064         isc_event_free(&event);
7065         forward->which++;
7066         dns_request_destroy(&forward->request);
7067         result = sendtomaster(forward);
7068         if (result != ISC_R_SUCCESS) {
7069                 /* call callback */
7070                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
7071                              "exhausted dynamic update forwarder list");
7072                 (forward->callback)(forward->callback_arg, result, NULL);
7073                 forward_destroy(forward);
7074         }
7075 }
7076
7077 isc_result_t
7078 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
7079                        dns_updatecallback_t callback, void *callback_arg)
7080 {
7081         dns_forward_t *forward;
7082         isc_result_t result;
7083         isc_region_t *mr;
7084
7085         REQUIRE(DNS_ZONE_VALID(zone));
7086         REQUIRE(msg != NULL);
7087         REQUIRE(callback != NULL);
7088
7089         forward = isc_mem_get(zone->mctx, sizeof(*forward));
7090         if (forward == NULL)
7091                 return (ISC_R_NOMEMORY);
7092
7093         forward->request = NULL;
7094         forward->zone = NULL;
7095         forward->msgbuf = NULL;
7096         forward->which = 0;
7097         forward->mctx = 0;
7098         forward->callback = callback;
7099         forward->callback_arg = callback_arg;
7100         forward->magic = FORWARD_MAGIC;
7101
7102         mr = dns_message_getrawmessage(msg);
7103         if (mr == NULL) {
7104                 result = ISC_R_UNEXPECTEDEND;
7105                 goto cleanup;
7106         }
7107
7108         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
7109         if (result != ISC_R_SUCCESS)
7110                 goto cleanup;
7111         result = isc_buffer_copyregion(forward->msgbuf, mr);
7112         if (result != ISC_R_SUCCESS)
7113                 goto cleanup;
7114
7115         isc_mem_attach(zone->mctx, &forward->mctx);
7116         dns_zone_iattach(zone, &forward->zone);
7117         result = sendtomaster(forward);
7118
7119  cleanup:
7120         if (result != ISC_R_SUCCESS) {
7121                 forward_destroy(forward);
7122         }
7123         return (result);
7124 }
7125
7126 isc_result_t
7127 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
7128         REQUIRE(DNS_ZONE_VALID(zone));
7129         REQUIRE(next != NULL && *next == NULL);
7130
7131         *next = ISC_LIST_NEXT(zone, link);
7132         if (*next == NULL)
7133                 return (ISC_R_NOMORE);
7134         else
7135                 return (ISC_R_SUCCESS);
7136 }
7137
7138 isc_result_t
7139 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
7140         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7141         REQUIRE(first != NULL && *first == NULL);
7142
7143         *first = ISC_LIST_HEAD(zmgr->zones);
7144         if (*first == NULL)
7145                 return (ISC_R_NOMORE);
7146         else
7147                 return (ISC_R_SUCCESS);
7148 }
7149
7150 /***
7151  ***    Zone manager.
7152  ***/
7153
7154 isc_result_t
7155 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
7156                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
7157                    dns_zonemgr_t **zmgrp)
7158 {
7159         dns_zonemgr_t *zmgr;
7160         isc_result_t result;
7161         isc_interval_t interval;
7162
7163         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
7164         if (zmgr == NULL)
7165                 return (ISC_R_NOMEMORY);
7166         zmgr->mctx = NULL;
7167         zmgr->refs = 1;
7168         isc_mem_attach(mctx, &zmgr->mctx);
7169         zmgr->taskmgr = taskmgr;
7170         zmgr->timermgr = timermgr;
7171         zmgr->socketmgr = socketmgr;
7172         zmgr->zonetasks = NULL;
7173         zmgr->task = NULL;
7174         zmgr->rl = NULL;
7175         ISC_LIST_INIT(zmgr->zones);
7176         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
7177         ISC_LIST_INIT(zmgr->xfrin_in_progress);
7178         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
7179         if (result != ISC_R_SUCCESS)
7180                 goto free_mem;
7181
7182         zmgr->transfersin = 10;
7183         zmgr->transfersperns = 2;
7184
7185         /* Create the zone task pool. */
7186         result = isc_taskpool_create(taskmgr, mctx,
7187                                      8 /* XXX */, 2, &zmgr->zonetasks);
7188         if (result != ISC_R_SUCCESS)
7189                 goto free_rwlock;
7190
7191         /* Create a single task for queueing of SOA queries. */
7192         result = isc_task_create(taskmgr, 1, &zmgr->task);
7193         if (result != ISC_R_SUCCESS)
7194                 goto free_taskpool;
7195         isc_task_setname(zmgr->task, "zmgr", zmgr);
7196         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
7197                                         &zmgr->rl);
7198         if (result != ISC_R_SUCCESS)
7199                 goto free_task;
7200         /* default to 20 refresh queries / notifies per second. */
7201         isc_interval_set(&interval, 0, 1000000000/2);
7202         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
7203         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7204         isc_ratelimiter_setpertic(zmgr->rl, 10);
7205
7206         zmgr->iolimit = 1;
7207         zmgr->ioactive = 0;
7208         ISC_LIST_INIT(zmgr->high);
7209         ISC_LIST_INIT(zmgr->low);
7210
7211         result = isc_mutex_init(&zmgr->iolock);
7212         if (result != ISC_R_SUCCESS)
7213                 goto free_rl;
7214
7215         zmgr->magic = ZONEMGR_MAGIC;
7216
7217         *zmgrp = zmgr;
7218         return (ISC_R_SUCCESS);
7219
7220 #if 0
7221  free_iolock:
7222         DESTROYLOCK(&zmgr->iolock);
7223 #endif
7224  free_rl:
7225         isc_ratelimiter_detach(&zmgr->rl);
7226  free_task:
7227         isc_task_detach(&zmgr->task);
7228  free_taskpool:
7229         isc_taskpool_destroy(&zmgr->zonetasks);
7230  free_rwlock:
7231         isc_rwlock_destroy(&zmgr->rwlock);
7232  free_mem:
7233         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
7234         isc_mem_detach(&mctx);
7235         return (result);
7236 }
7237
7238 isc_result_t
7239 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
7240         isc_result_t result;
7241
7242         REQUIRE(DNS_ZONE_VALID(zone));
7243         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7244
7245         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7246         LOCK_ZONE(zone);
7247         REQUIRE(zone->task == NULL);
7248         REQUIRE(zone->timer == NULL);
7249         REQUIRE(zone->zmgr == NULL);
7250
7251         isc_taskpool_gettask(zmgr->zonetasks,
7252                              dns_name_hash(dns_zone_getorigin(zone),
7253                                            ISC_FALSE),
7254                              &zone->task);
7255
7256         /*
7257          * Set the task name.  The tag will arbitrarily point to one
7258          * of the zones sharing the task (in practice, the one
7259          * to be managed last).
7260          */
7261         isc_task_setname(zone->task, "zone", zone);
7262
7263         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
7264                                   NULL, NULL,
7265                                   zone->task, zone_timer, zone,
7266                                   &zone->timer);
7267         if (result != ISC_R_SUCCESS)
7268                 goto cleanup_task;
7269         /*
7270          * The timer "holds" a iref.
7271          */
7272         zone->irefs++;
7273         INSIST(zone->irefs != 0);
7274
7275         ISC_LIST_APPEND(zmgr->zones, zone, link);
7276         zone->zmgr = zmgr;
7277         zmgr->refs++;
7278
7279         goto unlock;
7280
7281  cleanup_task:
7282         isc_task_detach(&zone->task);
7283
7284  unlock:
7285         UNLOCK_ZONE(zone);
7286         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7287         return (result);
7288 }
7289
7290 void
7291 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
7292         isc_boolean_t free_now = ISC_FALSE;
7293
7294         REQUIRE(DNS_ZONE_VALID(zone));
7295         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7296         REQUIRE(zone->zmgr == zmgr);
7297
7298         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7299         LOCK_ZONE(zone);
7300
7301         ISC_LIST_UNLINK(zmgr->zones, zone, link);
7302         zone->zmgr = NULL;
7303         zmgr->refs--;
7304         if (zmgr->refs == 0)
7305                 free_now = ISC_TRUE;
7306
7307         UNLOCK_ZONE(zone);
7308         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7309
7310         if (free_now)
7311                 zonemgr_free(zmgr);
7312         ENSURE(zone->zmgr == NULL);
7313 }
7314
7315 void
7316 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
7317         REQUIRE(DNS_ZONEMGR_VALID(source));
7318         REQUIRE(target != NULL && *target == NULL);
7319
7320         RWLOCK(&source->rwlock, isc_rwlocktype_write);
7321         REQUIRE(source->refs > 0);
7322         source->refs++;
7323         INSIST(source->refs > 0);
7324         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
7325         *target = source;
7326 }
7327
7328 void
7329 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
7330         dns_zonemgr_t *zmgr;
7331         isc_boolean_t free_now = ISC_FALSE;
7332
7333         REQUIRE(zmgrp != NULL);
7334         zmgr = *zmgrp;
7335         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7336
7337         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7338         zmgr->refs--;
7339         if (zmgr->refs == 0)
7340                 free_now = ISC_TRUE;
7341         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7342
7343         if (free_now)
7344                 zonemgr_free(zmgr);
7345 }
7346
7347 isc_result_t
7348 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
7349         dns_zone_t *p;
7350
7351         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7352
7353         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
7354         for (p = ISC_LIST_HEAD(zmgr->zones);
7355              p != NULL;
7356              p = ISC_LIST_NEXT(p, link))
7357         {
7358                 dns_zone_maintenance(p);
7359         }
7360         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
7361
7362         /*
7363          * Recent configuration changes may have increased the
7364          * amount of available transfers quota.  Make sure any
7365          * transfers currently blocked on quota get started if
7366          * possible.
7367          */
7368         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7369         zmgr_resume_xfrs(zmgr, ISC_TRUE);
7370         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7371         return (ISC_R_SUCCESS);
7372 }
7373
7374 void
7375 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
7376
7377         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7378
7379         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7380         zmgr_resume_xfrs(zmgr, ISC_TRUE);
7381         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
7382 }
7383
7384 void
7385 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
7386         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7387
7388         isc_ratelimiter_shutdown(zmgr->rl);
7389
7390         if (zmgr->task != NULL)
7391                 isc_task_destroy(&zmgr->task);
7392         if (zmgr->zonetasks != NULL)
7393                 isc_taskpool_destroy(&zmgr->zonetasks);
7394 }
7395
7396 static void
7397 zonemgr_free(dns_zonemgr_t *zmgr) {
7398         isc_mem_t *mctx;
7399
7400         INSIST(zmgr->refs == 0);
7401         INSIST(ISC_LIST_EMPTY(zmgr->zones));
7402
7403         zmgr->magic = 0;
7404
7405         DESTROYLOCK(&zmgr->iolock);
7406         isc_ratelimiter_detach(&zmgr->rl);
7407
7408         isc_rwlock_destroy(&zmgr->rwlock);
7409         mctx = zmgr->mctx;
7410         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
7411         isc_mem_detach(&mctx);
7412 }
7413
7414 void
7415 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
7416         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7417
7418         zmgr->transfersin = value;
7419 }
7420
7421 isc_uint32_t
7422 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
7423         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7424
7425         return (zmgr->transfersin);
7426 }
7427
7428 void
7429 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
7430         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7431
7432         zmgr->transfersperns = value;
7433 }
7434
7435 isc_uint32_t
7436 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
7437         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7438
7439         return (zmgr->transfersperns);
7440 }
7441
7442 /*
7443  * Try to start a new incoming zone transfer to fill a quota
7444  * slot that was just vacated.
7445  *
7446  * Requires:
7447  *      The zone manager is locked by the caller.
7448  */
7449 static void
7450 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
7451         dns_zone_t *zone;
7452         dns_zone_t *next;
7453
7454         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
7455              zone != NULL;
7456              zone = next)
7457         {
7458                 isc_result_t result;
7459                 next = ISC_LIST_NEXT(zone, statelink);
7460                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
7461                 if (result == ISC_R_SUCCESS) {
7462                         if (multi)
7463                                 continue;
7464                         /*
7465                          * We successfully filled the slot.  We're done.
7466                          */
7467                         break;
7468                 } else if (result == ISC_R_QUOTA) {
7469                         /*
7470                          * Not enough quota.  This is probably the per-server
7471                          * quota, because we usually get called when a unit of
7472                          * global quota has just been freed.  Try the next
7473                          * zone, it may succeed if it uses another master.
7474                          */
7475                         continue;
7476                 } else {
7477                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
7478                                      "starting zone transfer: %s",
7479                                      isc_result_totext(result));
7480                         break;
7481                 }
7482         }
7483 }
7484
7485 /*
7486  * Try to start an incoming zone transfer for 'zone', quota permitting.
7487  *
7488  * Requires:
7489  *      The zone manager is locked by the caller.
7490  *
7491  * Returns:
7492  *      ISC_R_SUCCESS   There was enough quota and we attempted to
7493  *                      start a transfer.  zone_xfrdone() has been or will
7494  *                      be called.
7495  *      ISC_R_QUOTA     Not enough quota.
7496  *      Others          Failure.
7497  */
7498 static isc_result_t
7499 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
7500         dns_peer_t *peer = NULL;
7501         isc_netaddr_t masterip;
7502         isc_uint32_t nxfrsin, nxfrsperns;
7503         dns_zone_t *x;
7504         isc_uint32_t maxtransfersin, maxtransfersperns;
7505         isc_event_t *e;
7506
7507         /*
7508          * Find any configured information about the server we'd
7509          * like to transfer this zone from.
7510          */
7511         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
7512         (void)dns_peerlist_peerbyaddr(zone->view->peers,
7513                                       &masterip, &peer);
7514
7515         /*
7516          * Determine the total maximum number of simultaneous
7517          * transfers allowed, and the maximum for this specific
7518          * master.
7519          */
7520         maxtransfersin = zmgr->transfersin;
7521         maxtransfersperns = zmgr->transfersperns;
7522         if (peer != NULL)
7523                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
7524
7525         /*
7526          * Count the total number of transfers that are in progress,
7527          * and the number of transfers in progress from this master.
7528          * We linearly scan a list of all transfers; if this turns
7529          * out to be too slow, we could hash on the master address.
7530          */
7531         nxfrsin = nxfrsperns = 0;
7532         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
7533              x != NULL;
7534              x = ISC_LIST_NEXT(x, statelink))
7535         {
7536                 isc_netaddr_t xip;
7537                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
7538                 nxfrsin++;
7539                 if (isc_netaddr_equal(&xip, &masterip))
7540                         nxfrsperns++;
7541         }
7542
7543         /* Enforce quota. */
7544         if (nxfrsin >= maxtransfersin)
7545                 return (ISC_R_QUOTA);
7546
7547         if (nxfrsperns >= maxtransfersperns)
7548                 return (ISC_R_QUOTA);
7549
7550         /*
7551          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
7552          * list and send it an event to let it start the actual transfer in the
7553          * context of its own task.
7554          */
7555         e = isc_event_allocate(zmgr->mctx, zmgr,
7556                                DNS_EVENT_ZONESTARTXFRIN,
7557                                got_transfer_quota, zone,
7558                                sizeof(isc_event_t));
7559         if (e == NULL)
7560                 return (ISC_R_NOMEMORY);
7561
7562         LOCK_ZONE(zone);
7563         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
7564         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
7565         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
7566         zone->statelist = &zmgr->xfrin_in_progress;
7567         isc_task_send(zone->task, &e);
7568         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
7569         UNLOCK_ZONE(zone);
7570
7571         return (ISC_R_SUCCESS);
7572 }
7573
7574 void
7575 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
7576
7577         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7578         REQUIRE(iolimit > 0);
7579
7580         zmgr->iolimit = iolimit;
7581 }
7582
7583 isc_uint32_t
7584 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
7585
7586         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7587
7588         return (zmgr->iolimit);
7589 }
7590
7591 /*
7592  * Get permission to request a file handle from the OS.
7593  * An event will be sent to action when one is available.
7594  * There are two queues available (high and low), the high
7595  * queue will be serviced before the low one.
7596  *
7597  * zonemgr_putio() must be called after the event is delivered to
7598  * 'action'.
7599  */
7600
7601 static isc_result_t
7602 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
7603               isc_task_t *task, isc_taskaction_t action, void *arg,
7604               dns_io_t **iop)
7605 {
7606         dns_io_t *io;
7607         isc_boolean_t queue;
7608
7609         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7610         REQUIRE(iop != NULL && *iop == NULL);
7611
7612         io = isc_mem_get(zmgr->mctx, sizeof(*io));
7613         if (io == NULL)
7614                 return (ISC_R_NOMEMORY);
7615         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
7616                                        action, arg, sizeof(*io->event));
7617         if (io->event == NULL) {
7618                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
7619                 return (ISC_R_NOMEMORY);
7620         }
7621         io->zmgr = zmgr;
7622         io->high = high;
7623         io->task = NULL;
7624         isc_task_attach(task, &io->task);
7625         ISC_LINK_INIT(io, link);
7626         io->magic = IO_MAGIC;
7627
7628         LOCK(&zmgr->iolock);
7629         zmgr->ioactive++;
7630         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
7631         if (queue) {
7632                 if (io->high)
7633                         ISC_LIST_APPEND(zmgr->high, io, link);
7634                 else
7635                         ISC_LIST_APPEND(zmgr->low, io, link);
7636         }
7637         UNLOCK(&zmgr->iolock);
7638         *iop = io;
7639
7640         if (!queue) {
7641                 isc_task_send(io->task, &io->event);
7642         }
7643         return (ISC_R_SUCCESS);
7644 }
7645
7646 static void
7647 zonemgr_putio(dns_io_t **iop) {
7648         dns_io_t *io;
7649         dns_io_t *next;
7650         dns_zonemgr_t *zmgr;
7651
7652         REQUIRE(iop != NULL);
7653         io = *iop;
7654         REQUIRE(DNS_IO_VALID(io));
7655
7656         *iop = NULL;
7657
7658         INSIST(!ISC_LINK_LINKED(io, link));
7659         INSIST(io->event == NULL);
7660
7661         zmgr = io->zmgr;
7662         isc_task_detach(&io->task);
7663         io->magic = 0;
7664         isc_mem_put(zmgr->mctx, io, sizeof(*io));
7665
7666         LOCK(&zmgr->iolock);
7667         INSIST(zmgr->ioactive > 0);
7668         zmgr->ioactive--;
7669         next = HEAD(zmgr->high);
7670         if (next == NULL)
7671                 next = HEAD(zmgr->low);
7672         if (next != NULL) {
7673                 if (next->high)
7674                         ISC_LIST_UNLINK(zmgr->high, next, link);
7675                 else
7676                         ISC_LIST_UNLINK(zmgr->low, next, link);
7677                 INSIST(next->event != NULL);
7678         }
7679         UNLOCK(&zmgr->iolock);
7680         if (next != NULL)
7681                 isc_task_send(next->task, &next->event);
7682 }
7683
7684 static void
7685 zonemgr_cancelio(dns_io_t *io) {
7686         isc_boolean_t send_event = ISC_FALSE;
7687
7688         REQUIRE(DNS_IO_VALID(io));
7689
7690         /*
7691          * If we are queued to be run then dequeue.
7692          */
7693         LOCK(&io->zmgr->iolock);
7694         if (ISC_LINK_LINKED(io, link)) {
7695                 if (io->high)
7696                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
7697                 else
7698                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
7699
7700                 send_event = ISC_TRUE;
7701                 INSIST(io->event != NULL);
7702         }
7703         UNLOCK(&io->zmgr->iolock);
7704         if (send_event) {
7705                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
7706                 isc_task_send(io->task, &io->event);
7707         }
7708 }
7709
7710 static void
7711 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
7712         char *buf;
7713         int buflen;
7714         isc_result_t result;
7715
7716         buflen = strlen(path) + strlen(templat) + 2;
7717
7718         buf = isc_mem_get(zone->mctx, buflen);
7719         if (buf == NULL)
7720                 return;
7721
7722         result = isc_file_template(path, templat, buf, buflen);
7723         if (result != ISC_R_SUCCESS)
7724                 goto cleanup;
7725
7726         result = isc_file_renameunique(path, buf);
7727         if (result != ISC_R_SUCCESS)
7728                 goto cleanup;
7729
7730         dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'",
7731                      path, buf);
7732
7733  cleanup:
7734         isc_mem_put(zone->mctx, buf, buflen);
7735 }
7736
7737 #if 0
7738 /* Hook for ondestroy notifcation from a database. */
7739
7740 static void
7741 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
7742         dns_db_t *db = event->sender;
7743         UNUSED(task);
7744
7745         isc_event_free(&event);
7746
7747         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
7748                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
7749                       "database (%p) destroyed", (void*) db);
7750 }
7751 #endif
7752
7753 void
7754 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
7755         isc_interval_t interval;
7756         isc_uint32_t s, ns;
7757         isc_uint32_t pertic;
7758         isc_result_t result;
7759
7760         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7761
7762         if (value == 0)
7763                 value = 1;
7764
7765         if (value == 1) {
7766                 s = 1;
7767                 ns = 0;
7768                 pertic = 1;
7769         } else if (value <= 10) {
7770                 s = 0;
7771                 ns = 1000000000 / value;
7772                 pertic = 1;
7773         } else {
7774                 s = 0;
7775                 ns = (1000000000 / value) * 10;
7776                 pertic = 10;
7777         }
7778
7779         isc_interval_set(&interval, s, ns);
7780         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
7781         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7782         isc_ratelimiter_setpertic(zmgr->rl, pertic);
7783
7784         zmgr->serialqueryrate = value;
7785 }
7786
7787 unsigned int
7788 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
7789         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7790
7791         return (zmgr->serialqueryrate);
7792 }
7793
7794 void
7795 dns_zone_forcereload(dns_zone_t *zone) {
7796         REQUIRE(DNS_ZONE_VALID(zone));
7797
7798         if (zone->type == dns_zone_master)
7799                 return;
7800
7801         LOCK_ZONE(zone);
7802         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
7803         UNLOCK_ZONE(zone);
7804         dns_zone_refresh(zone);
7805 }
7806
7807 isc_boolean_t
7808 dns_zone_isforced(dns_zone_t *zone) {
7809         REQUIRE(DNS_ZONE_VALID(zone));
7810
7811         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
7812 }
7813
7814 isc_result_t
7815 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
7816         isc_result_t result = ISC_R_SUCCESS;
7817
7818         LOCK_ZONE(zone);
7819         if (on) {
7820                 if (zone->counters != NULL)
7821                         goto done;
7822                 result = dns_stats_alloccounters(zone->mctx, &zone->counters);
7823         } else {
7824                 if (zone->counters == NULL)
7825                         goto done;
7826                 dns_stats_freecounters(zone->mctx, &zone->counters);
7827         }
7828  done:
7829         UNLOCK_ZONE(zone);
7830         return (result);
7831 }
7832
7833 isc_uint64_t *
7834 dns_zone_getstatscounters(dns_zone_t *zone) {
7835         return (zone->counters);
7836 }
7837
7838 void
7839 dns_zone_dialup(dns_zone_t *zone) {
7840
7841         REQUIRE(DNS_ZONE_VALID(zone));
7842
7843         zone_debuglog(zone, "dns_zone_dialup", 3,
7844                       "notify = %d, refresh = %d",
7845                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
7846                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
7847
7848         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
7849                 dns_zone_notify(zone);
7850         if (zone->type != dns_zone_master &&
7851             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
7852                 dns_zone_refresh(zone);
7853 }
7854
7855 void
7856 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
7857         REQUIRE(DNS_ZONE_VALID(zone));
7858
7859         LOCK_ZONE(zone);
7860         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
7861                          DNS_ZONEFLG_DIALREFRESH |
7862                          DNS_ZONEFLG_NOREFRESH);
7863         switch (dialup) {
7864         case dns_dialuptype_no:
7865                 break;
7866         case dns_dialuptype_yes:
7867                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
7868                                  DNS_ZONEFLG_DIALREFRESH |
7869                                  DNS_ZONEFLG_NOREFRESH));
7870                 break;
7871         case dns_dialuptype_notify:
7872                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
7873                 break;
7874         case dns_dialuptype_notifypassive:
7875                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
7876                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
7877                 break;
7878         case dns_dialuptype_refresh:
7879                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
7880                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
7881                 break;
7882         case dns_dialuptype_passive:
7883                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
7884                 break;
7885         default:
7886                 INSIST(0);
7887         }
7888         UNLOCK_ZONE(zone);
7889 }
7890
7891 isc_result_t
7892 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
7893         isc_result_t result = ISC_R_SUCCESS;
7894
7895         REQUIRE(DNS_ZONE_VALID(zone));
7896
7897         LOCK_ZONE(zone);
7898         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
7899         UNLOCK_ZONE(zone);
7900
7901         return (result);
7902 }
7903
7904 const char *
7905 dns_zone_getkeydirectory(dns_zone_t *zone) {
7906         REQUIRE(DNS_ZONE_VALID(zone));
7907
7908         return (zone->keydirectory);
7909 }
7910
7911 unsigned int
7912 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
7913         dns_zone_t *zone;
7914         unsigned int count = 0;
7915
7916         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
7917
7918         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
7919         switch (state) {
7920         case DNS_ZONESTATE_XFERRUNNING:
7921                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
7922                      zone != NULL;
7923                      zone = ISC_LIST_NEXT(zone, statelink))
7924                         count++;
7925                 break;
7926         case DNS_ZONESTATE_XFERDEFERRED:
7927                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
7928                      zone != NULL;
7929                      zone = ISC_LIST_NEXT(zone, statelink))
7930                         count++;
7931                 break;
7932         case DNS_ZONESTATE_SOAQUERY:
7933                 for (zone = ISC_LIST_HEAD(zmgr->zones);
7934                      zone != NULL;
7935                      zone = ISC_LIST_NEXT(zone, link))
7936                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
7937                                 count++;
7938                 break;
7939         case DNS_ZONESTATE_ANY:
7940                 for (zone = ISC_LIST_HEAD(zmgr->zones);
7941                      zone != NULL;
7942                      zone = ISC_LIST_NEXT(zone, link)) {
7943                         dns_view_t *view = zone->view;
7944                         if (view != NULL && strcmp(view->name, "_bind") == 0)
7945                                 continue;
7946                         count++;
7947                 }
7948                 break;
7949         default:
7950                 INSIST(0);
7951         }
7952
7953         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
7954
7955         return (count);
7956 }
7957
7958 isc_result_t
7959 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
7960         isc_boolean_t ok = ISC_TRUE;
7961         isc_boolean_t fail = ISC_FALSE;
7962         char namebuf[DNS_NAME_FORMATSIZE];
7963         char namebuf2[DNS_NAME_FORMATSIZE];
7964         char typebuf[DNS_RDATATYPE_FORMATSIZE];
7965         int level = ISC_LOG_WARNING;
7966         dns_name_t bad;
7967
7968         REQUIRE(DNS_ZONE_VALID(zone));
7969
7970         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
7971                 return (ISC_R_SUCCESS);
7972
7973         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
7974                 level = ISC_LOG_ERROR;
7975                 fail = ISC_TRUE;
7976         }
7977
7978         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
7979         if (!ok) {
7980                 dns_name_format(name, namebuf, sizeof(namebuf));
7981                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
7982                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
7983                              dns_result_totext(DNS_R_BADOWNERNAME));
7984                 if (fail)
7985                         return (DNS_R_BADOWNERNAME);
7986         }
7987
7988         dns_name_init(&bad, NULL);
7989         ok = dns_rdata_checknames(rdata, name, &bad);
7990         if (!ok) {
7991                 dns_name_format(name, namebuf, sizeof(namebuf));
7992                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
7993                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
7994                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
7995                              namebuf2, dns_result_totext(DNS_R_BADNAME));
7996                 if (fail)
7997                         return (DNS_R_BADNAME);
7998         }
7999
8000         return (ISC_R_SUCCESS);
8001 }
8002
8003 void
8004 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
8005         REQUIRE(DNS_ZONE_VALID(zone));
8006         zone->checkmx = checkmx;
8007 }
8008
8009 void
8010 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
8011         REQUIRE(DNS_ZONE_VALID(zone));
8012         zone->checksrv = checksrv;
8013 }
8014
8015 void
8016 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
8017         REQUIRE(DNS_ZONE_VALID(zone));
8018         zone->checkns = checkns;
8019 }
8020
8021 void
8022 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
8023         REQUIRE(DNS_ZONE_VALID(zone));
8024
8025         LOCK_ZONE(zone);
8026         zone->isself = isself;
8027         zone->isselfarg = arg;
8028         UNLOCK_ZONE(zone);
8029 }
8030
8031 void
8032 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
8033         REQUIRE(DNS_ZONE_VALID(zone));
8034
8035         LOCK_ZONE(zone);
8036         zone->notifydelay = delay;
8037         UNLOCK_ZONE(zone);
8038 }
8039
8040 isc_uint32_t
8041 dns_zone_getnotifydelay(dns_zone_t *zone) {
8042         REQUIRE(DNS_ZONE_VALID(zone));
8043
8044         return (zone->notifydelay);
8045 }