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