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