Merge from vendor branch OPENSSL:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / zone.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: zone.c,v 1.333.2.33 2004/06/04 02:41:39 marka Exp $ */
19
20 #include <config.h>
21
22 #include <isc/file.h>
23 #include <isc/mutex.h>
24 #include <isc/print.h>
25 #include <isc/random.h>
26 #include <isc/ratelimiter.h>
27 #include <isc/refcount.h>
28 #include <isc/serial.h>
29 #include <isc/string.h>
30 #include <isc/taskpool.h>
31 #include <isc/timer.h>
32 #include <isc/util.h>
33
34 #include <dns/acl.h>
35 #include <dns/adb.h>
36 #include <dns/callbacks.h>
37 #include <dns/db.h>
38 #include <dns/events.h>
39 #include <dns/journal.h>
40 #include <dns/log.h>
41 #include <dns/master.h>
42 #include <dns/masterdump.h>
43 #include <dns/message.h>
44 #include <dns/name.h>
45 #include <dns/peer.h>
46 #include <dns/rcode.h>
47 #include <dns/rdataclass.h>
48 #include <dns/rdatalist.h>
49 #include <dns/rdataset.h>
50 #include <dns/rdatastruct.h>
51 #include <dns/request.h>
52 #include <dns/resolver.h>
53 #include <dns/result.h>
54 #include <dns/stats.h>
55 #include <dns/ssu.h>
56 #include <dns/tsig.h>
57 #include <dns/xfrin.h>
58 #include <dns/zone.h>
59
60 #define ZONE_MAGIC                      ISC_MAGIC('Z', 'O', 'N', 'E')
61 #define DNS_ZONE_VALID(zone)            ISC_MAGIC_VALID(zone, ZONE_MAGIC)
62
63 #define NOTIFY_MAGIC                    ISC_MAGIC('N', 't', 'f', 'y')
64 #define DNS_NOTIFY_VALID(notify)        ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
65
66 #define STUB_MAGIC                      ISC_MAGIC('S', 't', 'u', 'b')
67 #define DNS_STUB_VALID(stub)            ISC_MAGIC_VALID(stub, STUB_MAGIC)
68
69 #define ZONEMGR_MAGIC                   ISC_MAGIC('Z', 'm', 'g', 'r')
70 #define DNS_ZONEMGR_VALID(stub)         ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
71
72 #define LOAD_MAGIC                      ISC_MAGIC('L', 'o', 'a', 'd')
73 #define DNS_LOAD_VALID(load)            ISC_MAGIC_VALID(load, LOAD_MAGIC)
74
75 #define FORWARD_MAGIC                   ISC_MAGIC('F', 'o', 'r', 'w')
76 #define DNS_FORWARD_VALID(load)         ISC_MAGIC_VALID(load, FORWARD_MAGIC)
77
78 #define IO_MAGIC                        ISC_MAGIC('Z', 'm', 'I', 'O')
79 #define DNS_IO_VALID(load)              ISC_MAGIC_VALID(load, IO_MAGIC)
80
81 /*
82  * Ensure 'a' is at least 'min' but not more than 'max'.
83  */
84 #define RANGE(a, min, max) \
85                 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
86
87 /*
88  * Default values.
89  */
90 #define DNS_DEFAULT_IDLEIN 3600         /* 1 hour */
91 #define DNS_DEFAULT_IDLEOUT 3600        /* 1 hour */
92 #define MAX_XFER_TIME (2*3600)          /* Documented default is 2 hours */
93
94 #ifndef DNS_MAX_EXPIRE
95 #define DNS_MAX_EXPIRE  14515200        /* 24 weeks */
96 #endif
97
98 #ifndef DNS_DUMP_DELAY
99 #define DNS_DUMP_DELAY 900              /* 15 minutes */
100 #endif
101
102 typedef struct dns_notify dns_notify_t;
103 typedef struct dns_stub dns_stub_t;
104 typedef struct dns_load dns_load_t;
105 typedef struct dns_forward dns_forward_t;
106 typedef struct dns_io dns_io_t;
107 typedef ISC_LIST(dns_io_t) dns_iolist_t;
108
109 #define DNS_ZONE_CHECKLOCK
110 #ifdef DNS_ZONE_CHECKLOCK
111 #define LOCK_ZONE(z) \
112          do { LOCK(&(z)->lock); \
113               INSIST((z)->locked == ISC_FALSE); \
114              (z)->locked = ISC_TRUE; \
115                 } while (0)
116 #define UNLOCK_ZONE(z) \
117         do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
118 #define LOCKED_ZONE(z) ((z)->locked)
119 #else
120 #define LOCK_ZONE(z) LOCK(&(z)->lock)
121 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
122 #define LOCKED_ZONE(z) ISC_TRUE
123 #endif
124
125 struct dns_zone {
126         /* Unlocked */
127         unsigned int            magic;
128         isc_mutex_t             lock;
129 #ifdef DNS_ZONE_CHECKLOCK
130         isc_boolean_t           locked;
131 #endif
132         isc_mem_t               *mctx;
133         isc_refcount_t          erefs;
134
135         /* Locked */
136         dns_db_t                *db;
137         dns_zonemgr_t           *zmgr;
138         ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
139         isc_timer_t             *timer;
140         unsigned int            irefs;
141         dns_name_t              origin;
142         char                    *masterfile;
143         char                    *journal;
144         isc_int32_t             journalsize;
145         dns_rdataclass_t        rdclass;
146         dns_zonetype_t          type;
147         unsigned int            flags;
148         unsigned int            options;
149         unsigned int            db_argc;
150         char                    **db_argv;
151         isc_time_t              expiretime;
152         isc_time_t              refreshtime;
153         isc_time_t              dumptime;
154         isc_time_t              loadtime;
155         isc_uint32_t            serial;
156         isc_uint32_t            refresh;
157         isc_uint32_t            retry;
158         isc_uint32_t            expire;
159         isc_uint32_t            minimum;
160
161         isc_uint32_t            maxrefresh;
162         isc_uint32_t            minrefresh;
163         isc_uint32_t            maxretry;
164         isc_uint32_t            minretry;
165
166         isc_sockaddr_t          *masters;
167         dns_name_t              **masterkeynames;
168         unsigned int            masterscnt;
169         unsigned int            curmaster;
170         unsigned int            refreshcnt;
171         isc_sockaddr_t          masteraddr;
172         dns_notifytype_t        notifytype;
173         isc_sockaddr_t          *notify;
174         unsigned int            notifycnt;
175         isc_sockaddr_t          notifyfrom;
176         isc_task_t              *task;
177         isc_sockaddr_t          notifysrc4;
178         isc_sockaddr_t          notifysrc6;
179         isc_sockaddr_t          xfrsource4;
180         isc_sockaddr_t          xfrsource6;
181         dns_xfrin_ctx_t         *xfr;           /* task locked */
182         /* Access Control Lists */
183         dns_acl_t               *update_acl;
184         dns_acl_t               *forward_acl;
185         dns_acl_t               *notify_acl;
186         dns_acl_t               *query_acl;
187         dns_acl_t               *xfr_acl;
188         dns_severity_t          check_names;
189         ISC_LIST(dns_notify_t)  notifies;
190         dns_request_t           *request;
191         dns_loadctx_t           *lctx;
192         dns_io_t                *readio;
193         isc_uint32_t            maxxfrin;
194         isc_uint32_t            maxxfrout;
195         isc_uint32_t            idlein;
196         isc_uint32_t            idleout;
197         isc_boolean_t           diff_on_reload;
198         isc_event_t             ctlevent;
199         dns_ssutable_t          *ssutable;
200         isc_uint32_t            sigvalidityinterval;
201         dns_view_t              *view;
202         /*
203          * Zones in certain states such as "waiting for zone transfer"
204          * or "zone transfer in progress" are kept on per-state linked lists
205          * in the zone manager using the 'statelink' field.  The 'statelist'
206          * field points at the list the zone is currently on.  It the zone
207          * is not on any such list, statelist is NULL.
208          */
209         ISC_LINK(dns_zone_t)    statelink;
210         dns_zonelist_t          *statelist;
211         /*
212          * Optional per-zone statistics counters (NULL if not present).
213          */
214         isc_uint64_t        *counters;
215 };
216
217 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
218 #define DNS_ZONE_SETFLAG(z,f) do { \
219                 INSIST(LOCKED_ZONE(z)); \
220                 (z)->flags |= (f); \
221                 } while (0)
222 #define DNS_ZONE_CLRFLAG(z,f) do { \
223                 INSIST(LOCKED_ZONE(z)); \
224                 (z)->flags &= ~(f); \
225                 } while (0)
226         /* XXX MPA these may need to go back into zone.h */
227 #define DNS_ZONEFLG_REFRESH     0x00000001U     /* refresh check in progress */
228 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /* zone need consolidation */
229 #define DNS_ZONEFLG_USEVC       0x00000004U     /* use tcp for refresh query */
230 #define DNS_ZONEFLG_DUMPING     0x00000008U     /* a dump is in progress */
231 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /* $INCLUDE in zone file */
232 #define DNS_ZONEFLG_LOADED      0x00000020U     /* database has loaded */
233 #define DNS_ZONEFLG_EXITING     0x00000040U     /* zone is being destroyed */
234 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /* zone has expired */
235 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /* refresh check needed */
236 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /* zone contents are
237                                                  * uptodate */
238 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /* need to send out notify
239                                                  * messages */
240 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /* generate a journal diff on
241                                                  * reload */
242 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /* an attempt to refresh a
243                                                  * zone with no masters
244                                                  * occured */
245 #define DNS_ZONEFLG_LOADING     0x00002000U     /* load from disk in progress*/
246 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /* timer values have been set
247                                                  * from SOA (if not set, we
248                                                  * are still using
249                                                  * default timer values) */
250 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /* Force a zone xfer */
251 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
252 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
253 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
254 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
255 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /* IXFR failed, force AXFR */
256 #define DNS_ZONEFLG_FLUSH       0x00200000U
257
258 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
259
260 /* Flags for zone_load() */
261 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
262
263 struct dns_zonemgr {
264         unsigned int            magic;
265         isc_mem_t *             mctx;
266         int                     refs;           /* Locked by rwlock */
267         isc_taskmgr_t *         taskmgr;
268         isc_timermgr_t *        timermgr;
269         isc_socketmgr_t *       socketmgr;
270         isc_taskpool_t *        zonetasks;
271         isc_task_t *            task;
272         isc_ratelimiter_t *     rl;
273         isc_rwlock_t            rwlock;
274         isc_mutex_t             iolock;
275
276         /* Locked by rwlock. */
277         dns_zonelist_t          zones;
278         dns_zonelist_t          waiting_for_xfrin;
279         dns_zonelist_t          xfrin_in_progress;
280
281         /* Configuration data. */
282         isc_uint32_t            transfersin;
283         isc_uint32_t            transfersperns;
284         unsigned int            serialqueryrate;
285
286         /* Locked by iolock */
287         isc_uint32_t            iolimit;
288         isc_uint32_t            ioactive;
289         dns_iolist_t            high;
290         dns_iolist_t            low;
291 };
292
293 /*
294  * Hold notify state.
295  */
296 struct dns_notify {
297         unsigned int            magic;
298         unsigned int            flags;
299         isc_mem_t               *mctx;
300         dns_zone_t              *zone;
301         dns_adbfind_t           *find;
302         dns_request_t           *request;
303         dns_name_t              ns;
304         isc_sockaddr_t          dst;
305         unsigned int            attempt;
306         ISC_LINK(dns_notify_t)  link;
307 };
308
309 #define DNS_NOTIFY_NOSOA        0x0001U
310
311 /*
312  *      dns_stub holds state while performing a 'stub' transfer.
313  *      'db' is the zone's 'db' or a new one if this is the initial
314  *      transfer.
315  */
316
317 struct dns_stub {
318         unsigned int            magic;
319         isc_mem_t               *mctx;
320         dns_zone_t              *zone;
321         dns_db_t                *db;
322         dns_dbversion_t         *version;
323 };
324
325 /*
326  *      Hold load state.
327  */
328 struct dns_load {
329         unsigned int            magic;
330         isc_mem_t               *mctx;
331         dns_zone_t              *zone;
332         dns_db_t                *db;
333         isc_time_t              loadtime;
334         dns_rdatacallbacks_t    callbacks;
335 };
336
337 /*
338  *      Hold forward state.
339  */
340 struct dns_forward {
341         unsigned int            magic;
342         isc_mem_t               *mctx;
343         dns_zone_t              *zone;
344         isc_buffer_t            *msgbuf;
345         dns_request_t           *request;
346         isc_uint32_t            which;
347         isc_sockaddr_t          addr;
348         dns_updatecallback_t    callback;
349         void                    *callback_arg;
350 };
351
352 /*
353  *      Hold IO request state.
354  */
355 struct dns_io {
356         unsigned int    magic;
357         dns_zonemgr_t   *zmgr;
358         isc_boolean_t   high;
359         isc_task_t      *task;
360         ISC_LINK(dns_io_t) link;
361         isc_event_t     *event;
362 };
363
364 static void zone_settimer(dns_zone_t *, isc_time_t *);
365 static void cancel_refresh(dns_zone_t *);
366 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
367                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
368 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
369      ISC_FORMAT_PRINTF(3, 4);
370 static void queue_xfrin(dns_zone_t *zone);
371 static void zone_unload(dns_zone_t *zone);
372 static void zone_expire(dns_zone_t *zone);
373 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
374 static void zone_idetach(dns_zone_t **zonep);
375 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
376                                    isc_boolean_t dump);
377 static isc_result_t default_journal(dns_zone_t *zone);
378 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
379 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
380                                   isc_time_t loadtime, isc_result_t result);
381 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
382 static void zone_shutdown(isc_task_t *, isc_event_t *);
383 static void zone_loaddone(void *arg, isc_result_t result);
384 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
385                                    isc_time_t loadtime);
386
387 #if 0
388 /* ondestroy example */
389 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
390 #endif
391
392 static void refresh_callback(isc_task_t *, isc_event_t *);
393 static void stub_callback(isc_task_t *, isc_event_t *);
394 static void queue_soa_query(dns_zone_t *zone);
395 static void soa_query(isc_task_t *, isc_event_t *);
396 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
397                      dns_stub_t *stub);
398 static int message_count(dns_message_t *msg, dns_section_t section,
399                          dns_rdatatype_t type);
400 static void notify_cancel(dns_zone_t *zone);
401 static void notify_find_address(dns_notify_t *notify);
402 static void notify_send(dns_notify_t *notify);
403 static isc_result_t notify_createmessage(dns_zone_t *zone,
404                                          unsigned int flags,
405                                          dns_message_t **messagep);
406 static void notify_done(isc_task_t *task, isc_event_t *event);
407 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
408 static isc_result_t zone_dump(dns_zone_t *);
409 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
410 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
411                                              dns_zone_t *zone);
412 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
413 static void zonemgr_free(dns_zonemgr_t *zmgr);
414 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
415                                   isc_task_t *task, isc_taskaction_t action,
416                                   void *arg, dns_io_t **iop);
417 static void zonemgr_putio(dns_io_t **iop);
418 static void zonemgr_cancelio(dns_io_t *io);
419
420 static isc_result_t
421 zone_get_from_db(dns_db_t *db, dns_name_t *origin, unsigned int *nscount,
422                  unsigned int *soacount, isc_uint32_t *serial,
423                  isc_uint32_t *refresh, isc_uint32_t *retry,
424                  isc_uint32_t *expire, isc_uint32_t *minimum);
425
426 static void zone_freedbargs(dns_zone_t *zone);
427 static void forward_callback(isc_task_t *task, isc_event_t *event);
428 static void zone_saveunique(dns_zone_t *zone, const char *path,
429                             const char *templat);
430 static void zone_maintenance(dns_zone_t *zone);
431 static void zone_notify(dns_zone_t *zone);
432
433 #define ENTER zone_debuglog(zone, me, 1, "enter")
434
435 static const unsigned int dbargc_default = 1;
436 static const char *dbargv_default[] = { "rbt" };
437
438 /***
439  ***    Public functions.
440  ***/
441
442 isc_result_t
443 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
444         isc_result_t result;
445         dns_zone_t *zone;
446
447         REQUIRE(zonep != NULL && *zonep == NULL);
448         REQUIRE(mctx != NULL);
449
450         zone = isc_mem_get(mctx, sizeof *zone);
451         if (zone == NULL)
452                 return (ISC_R_NOMEMORY);
453
454         result = isc_mutex_init(&zone->lock);
455         if (result != ISC_R_SUCCESS) {
456                 isc_mem_put(mctx, zone, sizeof *zone);
457                 UNEXPECTED_ERROR(__FILE__, __LINE__,
458                                  "isc_mutex_init() failed: %s",
459                                  isc_result_totext(result));
460                 return (ISC_R_UNEXPECTED);
461         }
462
463         /* XXX MPA check that all elements are initialised */
464         zone->mctx = NULL;
465 #ifdef DNS_ZONE_CHECKLOCK
466         zone->locked = ISC_FALSE;
467 #endif
468         isc_mem_attach(mctx, &zone->mctx);
469         zone->db = NULL;
470         zone->zmgr = NULL;
471         ISC_LINK_INIT(zone, link);
472         isc_refcount_init(&zone->erefs, 1);     /* Implicit attach. */
473         zone->irefs = 0;
474         dns_name_init(&zone->origin, NULL);
475         zone->masterfile = NULL;
476         zone->journalsize = -1;
477         zone->journal = NULL;
478         zone->rdclass = dns_rdataclass_none;
479         zone->type = dns_zone_none;
480         zone->flags = 0;
481         zone->options = 0;
482         zone->db_argc = 0;
483         zone->db_argv = NULL;
484         isc_time_settoepoch(&zone->expiretime);
485         isc_time_settoepoch(&zone->refreshtime);
486         isc_time_settoepoch(&zone->dumptime);
487         isc_time_settoepoch(&zone->loadtime);
488         zone->serial = 0;
489         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
490         zone->retry = DNS_ZONE_DEFAULTRETRY;
491         zone->expire = 0;
492         zone->minimum = 0;
493         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
494         zone->minrefresh = DNS_ZONE_MINREFRESH;
495         zone->maxretry = DNS_ZONE_MAXRETRY;
496         zone->minretry = DNS_ZONE_MINRETRY;
497         zone->masters = NULL;
498         zone->masterkeynames = NULL;
499         zone->masterscnt = 0;
500         zone->curmaster = 0;
501         zone->refreshcnt = 0;
502         zone->notify = NULL;
503         zone->notifytype = dns_notifytype_yes;
504         zone->notifycnt = 0;
505         zone->task = NULL;
506         zone->update_acl = NULL;
507         zone->forward_acl = NULL;
508         zone->notify_acl = NULL;
509         zone->query_acl = NULL;
510         zone->xfr_acl = NULL;
511         zone->check_names = dns_severity_ignore;
512         zone->request = NULL;
513         zone->lctx = NULL;
514         zone->readio = NULL;
515         zone->timer = NULL;
516         zone->idlein = DNS_DEFAULT_IDLEIN;
517         zone->idleout = DNS_DEFAULT_IDLEOUT;
518         ISC_LIST_INIT(zone->notifies);
519         isc_sockaddr_any(&zone->notifysrc4);
520         isc_sockaddr_any6(&zone->notifysrc6);
521         isc_sockaddr_any(&zone->xfrsource4);
522         isc_sockaddr_any6(&zone->xfrsource6);
523         zone->xfr = NULL;
524         zone->maxxfrin = MAX_XFER_TIME;
525         zone->maxxfrout = MAX_XFER_TIME;
526         zone->diff_on_reload = ISC_FALSE;
527         zone->ssutable = NULL;
528         zone->sigvalidityinterval = 30 * 24 * 3600;
529         zone->view = NULL;
530         ISC_LINK_INIT(zone, statelink);
531         zone->statelist = NULL;
532         zone->counters = NULL;
533
534         zone->magic = ZONE_MAGIC;
535
536         /* Must be after magic is set. */
537         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
538         if (result != ISC_R_SUCCESS)
539                 goto free_mutex;
540         
541         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
542                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
543                        NULL, NULL);
544         *zonep = zone;
545         return (ISC_R_SUCCESS);
546
547  free_mutex:
548         DESTROYLOCK(&zone->lock);
549         return (ISC_R_NOMEMORY);
550 }
551
552 /*
553  * Free a zone.  Because we require that there be no more
554  * outstanding events or references, no locking is necessary.
555  */
556 static void
557 zone_free(dns_zone_t *zone) {
558         isc_mem_t *mctx = NULL;
559
560         REQUIRE(DNS_ZONE_VALID(zone));
561         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
562         REQUIRE(zone->irefs == 0);
563         REQUIRE(!LOCKED_ZONE(zone));
564         REQUIRE(zone->timer == NULL);
565
566         /*
567          * Managed objects.  Order is important.
568          */
569         if (zone->request != NULL)
570                 dns_request_destroy(&zone->request); /* XXXMPA */
571         INSIST(zone->readio == NULL);
572         INSIST(zone->statelist == NULL);
573
574         if (zone->task != NULL)
575                 isc_task_detach(&zone->task);
576         if (zone->zmgr)
577                 dns_zonemgr_releasezone(zone->zmgr, zone);
578
579         /* Unmanaged objects */
580         if (zone->masterfile != NULL)
581                 isc_mem_free(zone->mctx, zone->masterfile);
582         zone->masterfile = NULL;
583         zone->journalsize = -1;
584         if (zone->journal != NULL)
585                 isc_mem_free(zone->mctx, zone->journal);
586         zone->journal = NULL;
587         if (zone->counters != NULL)
588                 dns_stats_freecounters(zone->mctx, &zone->counters);
589         if (zone->db != NULL)
590                 dns_db_detach(&zone->db);
591         zone_freedbargs(zone);
592         dns_zone_setmasterswithkeys(zone, NULL, NULL, 0);
593         dns_zone_setalsonotify(zone, NULL, 0);
594         zone->check_names = dns_severity_ignore;
595         if (zone->update_acl != NULL)
596                 dns_acl_detach(&zone->update_acl);
597         if (zone->forward_acl != NULL)
598                 dns_acl_detach(&zone->forward_acl);
599         if (zone->notify_acl != NULL)
600                 dns_acl_detach(&zone->notify_acl);
601         if (zone->query_acl != NULL)
602                 dns_acl_detach(&zone->query_acl);
603         if (zone->xfr_acl != NULL)
604                 dns_acl_detach(&zone->xfr_acl);
605         if (dns_name_dynamic(&zone->origin))
606                 dns_name_free(&zone->origin, zone->mctx);
607         if (zone->ssutable != NULL)
608                 dns_ssutable_detach(&zone->ssutable);
609
610         /* last stuff */
611         DESTROYLOCK(&zone->lock);
612         isc_refcount_destroy(&zone->erefs);
613         zone->magic = 0;
614         mctx = zone->mctx;
615         isc_mem_put(mctx, zone, sizeof *zone);
616         isc_mem_detach(&mctx);
617 }
618
619 /*
620  *      Single shot.
621  */
622 void
623 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
624
625         REQUIRE(DNS_ZONE_VALID(zone));
626         REQUIRE(rdclass != dns_rdataclass_none);
627
628         /*
629          * Test and set.
630          */
631         LOCK_ZONE(zone);
632         REQUIRE(zone->rdclass == dns_rdataclass_none ||
633                 zone->rdclass == rdclass);
634         zone->rdclass = rdclass;
635         UNLOCK_ZONE(zone);
636 }
637
638 dns_rdataclass_t
639 dns_zone_getclass(dns_zone_t *zone){
640         REQUIRE(DNS_ZONE_VALID(zone));
641
642         return (zone->rdclass);
643 }
644
645 void
646 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
647         REQUIRE(DNS_ZONE_VALID(zone));
648
649         LOCK_ZONE(zone);
650         zone->notifytype = notifytype;
651         UNLOCK_ZONE(zone);
652 }
653
654 /*
655  *      Single shot.
656  */
657 void
658 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
659
660         REQUIRE(DNS_ZONE_VALID(zone));
661         REQUIRE(type != dns_zone_none);
662
663         /*
664          * Test and set.
665          */
666         LOCK_ZONE(zone);
667         REQUIRE(zone->type == dns_zone_none || zone->type == type);
668         zone->type = type;
669         UNLOCK_ZONE(zone);
670 }
671
672 static void
673 zone_freedbargs(dns_zone_t *zone) {
674         unsigned int i;
675
676         /* Free the old database argument list. */
677         if (zone->db_argv != NULL) {
678                 for (i = 0; i < zone->db_argc; i++)
679                         isc_mem_free(zone->mctx, zone->db_argv[i]);
680                 isc_mem_put(zone->mctx, zone->db_argv,
681                             zone->db_argc * sizeof *zone->db_argv);
682         }
683         zone->db_argc = 0;
684         zone->db_argv = NULL;
685 }
686
687 isc_result_t
688 dns_zone_setdbtype(dns_zone_t *zone,
689                    unsigned int dbargc, const char * const *dbargv) {
690         isc_result_t result = ISC_R_SUCCESS;
691         char **new = NULL;
692         unsigned int i;
693
694         REQUIRE(DNS_ZONE_VALID(zone));
695         REQUIRE(dbargc >= 1);
696         REQUIRE(dbargv != NULL);
697
698         LOCK_ZONE(zone);
699
700         /* Set up a new database argument list. */
701         new = isc_mem_get(zone->mctx, dbargc * sizeof *new);
702         if (new == NULL)
703                 goto nomem;
704         for (i = 0; i < dbargc; i++)
705                 new[i] = NULL;
706         for (i = 0; i < dbargc; i++) {
707                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
708                 if (new[i] == NULL)
709                         goto nomem;
710         }
711
712         /* Free the old list. */
713         zone_freedbargs(zone);
714
715         zone->db_argc = dbargc;
716         zone->db_argv = new;
717         result = ISC_R_SUCCESS;
718         goto unlock;
719         
720  nomem:
721         if (new != NULL) {
722                 for (i = 0; i < dbargc; i++) {
723                         if (zone->db_argv[i] != NULL)
724                                 isc_mem_free(zone->mctx, new[i]);
725                         isc_mem_put(zone->mctx, new, 
726                                     dbargc * sizeof *new);
727                 }
728         }
729         result = ISC_R_NOMEMORY;
730         
731  unlock:
732         UNLOCK_ZONE(zone);
733         return (result);
734 }
735
736 void
737 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
738         REQUIRE(DNS_ZONE_VALID(zone));
739
740         LOCK_ZONE(zone);
741         if (zone->view != NULL)
742                 dns_view_weakdetach(&zone->view);
743         dns_view_weakattach(view, &zone->view);
744         UNLOCK_ZONE(zone);
745 }
746
747
748 dns_view_t *
749 dns_zone_getview(dns_zone_t *zone) {
750         REQUIRE(DNS_ZONE_VALID(zone));
751
752         return (zone->view);
753 }
754
755
756 isc_result_t
757 dns_zone_setorigin(dns_zone_t *zone, dns_name_t *origin) {
758         isc_result_t result;
759
760         REQUIRE(DNS_ZONE_VALID(zone));
761         REQUIRE(origin != NULL);
762
763         LOCK_ZONE(zone);
764         if (dns_name_dynamic(&zone->origin)) {
765                 dns_name_free(&zone->origin, zone->mctx);
766                 dns_name_init(&zone->origin, NULL);
767         }
768         result = dns_name_dup(origin, zone->mctx, &zone->origin);
769         UNLOCK_ZONE(zone);
770         return (result);
771 }
772
773         
774 static isc_result_t
775 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
776         char *copy;
777
778         if (value != NULL) {
779                 copy = isc_mem_strdup(zone->mctx, value);
780                 if (copy == NULL)
781                         return (ISC_R_NOMEMORY);
782         } else {
783                 copy = NULL;
784         }
785
786         if (*field != NULL)
787                 isc_mem_free(zone->mctx, *field);
788
789         *field = copy;
790         return (ISC_R_SUCCESS);
791 }       
792
793 isc_result_t
794 dns_zone_setfile(dns_zone_t *zone, const char *file) {
795         isc_result_t result = ISC_R_SUCCESS;
796
797         REQUIRE(DNS_ZONE_VALID(zone));
798
799         LOCK_ZONE(zone);
800         result = dns_zone_setstring(zone, &zone->masterfile, file);
801         if (result == ISC_R_SUCCESS)
802                 result = default_journal(zone);
803         UNLOCK_ZONE(zone);
804
805         return (result);
806 }
807
808 const char *
809 dns_zone_getfile(dns_zone_t *zone) {
810         REQUIRE(DNS_ZONE_VALID(zone));
811
812         return (zone->masterfile);
813 }
814
815 static isc_result_t
816 default_journal(dns_zone_t *zone) {
817         isc_result_t result;
818         char *journal;
819
820         REQUIRE(DNS_ZONE_VALID(zone));
821         REQUIRE(LOCKED_ZONE(zone));
822
823         if (zone->masterfile != NULL) {
824                 /* Calculate string length including '\0'. */
825                 int len = strlen(zone->masterfile) + sizeof ".jnl";
826                 journal = isc_mem_allocate(zone->mctx, len);
827                 if (journal == NULL)
828                         return (ISC_R_NOMEMORY);
829                 strcpy(journal, zone->masterfile);
830                 strcat(journal, ".jnl");
831         } else {
832                 journal = NULL;
833         }
834         result = dns_zone_setstring(zone, &zone->journal, journal);
835         if (journal != NULL)
836                 isc_mem_free(zone->mctx, journal);
837         return (result);
838 }
839
840 isc_result_t
841 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
842         isc_result_t result = ISC_R_SUCCESS;
843
844         REQUIRE(DNS_ZONE_VALID(zone));
845
846         LOCK_ZONE(zone);
847         result = dns_zone_setstring(zone, &zone->journal, journal);     
848         UNLOCK_ZONE(zone);
849
850         return (result);
851 }
852
853 char *
854 dns_zone_getjournal(dns_zone_t *zone) {
855         REQUIRE(DNS_ZONE_VALID(zone));
856
857         return (zone->journal);
858 }
859
860 /*
861  * Return true iff the zone is "dynamic", in the sense that the zone's
862  * master file (if any) is written by the server, rather than being
863  * updated manually and read by the server.
864  *
865  * This is true for slave zones, stub zones, and zones that allow
866  * dynamic updates either by having an update policy ("ssutable")
867  * or an "allow-update" ACL with a value other than exactly "{ none; }".
868  */
869 static isc_boolean_t
870 zone_isdynamic(dns_zone_t *zone) {
871         REQUIRE(DNS_ZONE_VALID(zone));
872
873         return (ISC_TF(zone->type == dns_zone_slave ||
874                        zone->type == dns_zone_stub ||
875                        zone->ssutable != NULL ||
876                        (zone->update_acl != NULL &&
877                         ! (zone->update_acl->length == 1 && 
878                            zone->update_acl->elements[0].negative == ISC_TRUE
879                            &&
880                            zone->update_acl->elements[0].type ==
881                            dns_aclelementtype_any))));
882 }
883
884
885 static isc_result_t
886 zone_load(dns_zone_t *zone, unsigned int flags) {
887         isc_result_t result;
888         isc_time_t now;
889         isc_time_t loadtime, filetime;
890         dns_db_t *db = NULL;
891
892         REQUIRE(DNS_ZONE_VALID(zone));
893
894         LOCK_ZONE(zone);
895         isc_time_now(&now);
896
897         INSIST(zone->type != dns_zone_none);
898
899         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
900                 result = ISC_R_SUCCESS;
901                 goto cleanup;
902         }
903
904         if (zone->db != NULL && zone->masterfile == NULL) {
905                 /*
906                  * The zone has no master file configured, but it already
907                  * has a database.  It could be the built-in
908                  * version.bind. CH zone, a zone with a persistent
909                  * database being reloaded, or maybe a zone that
910                  * used to have a master file but whose configuration
911                  * was changed so that it no longer has one.  Do nothing.
912                  */
913                 result = ISC_R_SUCCESS;
914                 goto cleanup;
915         }
916
917         if (zone->db != NULL && zone_isdynamic(zone)) {
918                 /*
919                  * This is a slave, stub, or dynamically updated
920                  * zone being reloaded.  Do nothing - the database
921                  * we already have is guaranteed to be up-to-date.
922                  */
923                 if (zone->type == dns_zone_master)
924                         result = DNS_R_DYNAMIC;
925                 else
926                         result = ISC_R_SUCCESS;
927                 goto cleanup;
928         }
929                 
930         /*
931          * Don't do the load if the file that stores the zone is older
932          * than the last time the zone was loaded.  If the zone has not
933          * been loaded yet, zone->loadtime will be the epoch.
934          */
935         if (zone->masterfile != NULL && ! isc_time_isepoch(&zone->loadtime)) {
936                 /*
937                  * The file is already loaded.  If we are just doing a
938                  * "rndc reconfig", we are done.
939                  */
940                 if ((flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
941                         result = ISC_R_SUCCESS;
942                         goto cleanup;
943                 }
944                 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE)) {
945                         result = isc_file_getmodtime(zone->masterfile,
946                                                      &filetime);
947                         if (result == ISC_R_SUCCESS &&
948                             isc_time_compare(&filetime, &zone->loadtime) < 0) {
949                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
950                                              "skipping load: master file older "
951                                              "than last load");
952                                 result = ISC_R_SUCCESS;
953                                 goto cleanup;
954                         }
955                 }
956         } 
957
958         INSIST(zone->db_argc >= 1);
959
960         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
961             (strcmp(zone->db_argv[0], "rbt") == 0 ||
962              strcmp(zone->db_argv[0], "rbt64") == 0)) {
963                 if (zone->masterfile == NULL ||
964                     !isc_file_exists(zone->masterfile)) {
965                         if (zone->masterfile != NULL)
966                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
967                                              "no master file");
968                         zone->refreshtime = now;
969                         if (zone->task != NULL)
970                                 zone_settimer(zone, &now);
971                         result = ISC_R_SUCCESS;
972                         goto cleanup;
973                 }
974         }
975
976         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
977
978         /*
979          * Store the current time before the zone is loaded, so that if the
980          * file changes between the time of the load and the time that
981          * zone->loadtime is set, then the file will still be reloaded
982          * the next time dns_zone_load is called.
983          */
984         result = isc_time_now(&loadtime);
985         if (result != ISC_R_SUCCESS)
986                 goto cleanup;
987
988         result = dns_db_create(zone->mctx, zone->db_argv[0],
989                                &zone->origin, (zone->type == dns_zone_stub) ?
990                                dns_dbtype_stub : dns_dbtype_zone,
991                                zone->rdclass,
992                                zone->db_argc - 1, zone->db_argv + 1,
993                                &db);
994
995         if (result != ISC_R_SUCCESS) {
996                 dns_zone_log(zone, ISC_LOG_ERROR,
997                              "loading zone: creating database: %s",
998                              isc_result_totext(result));
999                 goto cleanup;
1000         }
1001         dns_db_settask(db, zone->task);
1002
1003         if (! dns_db_ispersistent(db)) {
1004                 if (zone->masterfile != NULL) {
1005                         result = zone_startload(db, zone, loadtime);
1006                 } else {
1007                         result = DNS_R_NOMASTERFILE;
1008                         if (zone->type == dns_zone_master) {
1009                                 dns_zone_log(zone, ISC_LOG_ERROR,
1010                                              "loading zone: "
1011                                              "no master file configured");
1012                                 goto cleanup;
1013                         }
1014                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1015                                      "no master file configured: continuing");
1016                 }
1017         }
1018
1019         if (result == DNS_R_CONTINUE) {
1020                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1021                 result = ISC_R_SUCCESS;
1022                 goto cleanup;
1023         }
1024
1025         result = zone_postload(zone, db, loadtime, result);
1026
1027  cleanup:
1028         UNLOCK_ZONE(zone);
1029         if (db != NULL)
1030                 dns_db_detach(&db);
1031         return (result);
1032 }
1033
1034 isc_result_t
1035 dns_zone_load(dns_zone_t *zone) {
1036         return (zone_load(zone, 0));
1037 }
1038
1039 isc_result_t
1040 dns_zone_loadnew(dns_zone_t *zone) {
1041         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1042 }
1043
1044 static void
1045 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1046         dns_load_t *load = event->ev_arg;
1047         isc_result_t result = ISC_R_SUCCESS;
1048         unsigned int options;
1049
1050         REQUIRE(DNS_LOAD_VALID(load));
1051
1052         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1053                 result = ISC_R_CANCELED;
1054         isc_event_free(&event);
1055         if (result == ISC_R_CANCELED)
1056                 goto fail;
1057
1058         options = DNS_MASTER_ZONE;
1059         if (load->zone->type == dns_zone_slave)
1060                 options |= DNS_MASTER_SLAVE;
1061         result = dns_master_loadfileinc(load->zone->masterfile,
1062                                         dns_db_origin(load->db),
1063                                         dns_db_origin(load->db),
1064                                         load->zone->rdclass,
1065                                         options,
1066                                         &load->callbacks, task,
1067                                         zone_loaddone, load,
1068                                         &load->zone->lctx, load->zone->mctx);
1069         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1070             result != DNS_R_SEENINCLUDE)
1071                 goto fail;
1072         return;
1073
1074  fail:
1075         zone_loaddone(load, result);
1076 }
1077
1078 static isc_result_t
1079 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1080         dns_load_t *load;
1081         isc_result_t result;
1082         isc_result_t tresult;
1083         unsigned int options;
1084
1085         options = DNS_MASTER_ZONE;
1086         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1087                 options |= DNS_MASTER_MANYERRORS;
1088         if (zone->type == dns_zone_slave)
1089                 options |= DNS_MASTER_SLAVE;
1090         if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1091                 load = isc_mem_get(zone->mctx, sizeof(*load));
1092                 if (load == NULL)
1093                         return (ISC_R_NOMEMORY);
1094
1095                 load->mctx = NULL;
1096                 load->zone = NULL;
1097                 load->db = NULL;
1098                 load->loadtime = loadtime;
1099                 load->magic = LOAD_MAGIC;
1100
1101                 isc_mem_attach(zone->mctx, &load->mctx);
1102                 zone_iattach(zone, &load->zone);
1103                 dns_db_attach(db, &load->db);
1104                 dns_rdatacallbacks_init(&load->callbacks);
1105                 result = dns_db_beginload(db, &load->callbacks.add,
1106                                           &load->callbacks.add_private);
1107                 if (result != ISC_R_SUCCESS)
1108                         goto cleanup;
1109                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task, 
1110                                        zone_gotreadhandle, load,
1111                                        &zone->readio);
1112                 if (result != ISC_R_SUCCESS) {
1113                         tresult = dns_db_endload(load->db,
1114                                                  &load->callbacks.add_private);
1115                         if (result == ISC_R_SUCCESS)
1116                                 result = tresult;
1117                         goto cleanup;
1118                 } else
1119                         result = DNS_R_CONTINUE;
1120         } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
1121                 dns_rdatacallbacks_t    callbacks;
1122
1123                 dns_rdatacallbacks_init(&callbacks);
1124                 result = dns_db_beginload(db, &callbacks.add,
1125                                           &callbacks.add_private);
1126                 if (result != ISC_R_SUCCESS)
1127                         return (result);
1128                 result = dns_master_loadfile(zone->masterfile, &zone->origin,
1129                                              &zone->origin, zone->rdclass,
1130                                              options, &callbacks, zone->mctx);
1131                 tresult = dns_db_endload(db, &callbacks.add_private);
1132                 if (result == ISC_R_SUCCESS)
1133                         result = tresult;
1134         } else {
1135                 result = dns_db_load(db, zone->masterfile);
1136         }
1137
1138         return (result);
1139
1140  cleanup:
1141         load->magic = 0;
1142         dns_db_detach(&load->db);
1143         zone_idetach(&load->zone);
1144         isc_mem_detach(&load->mctx);
1145         isc_mem_put(zone->mctx, load, sizeof(*load));
1146         return (result);
1147 }
1148
1149 static isc_result_t
1150 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
1151               isc_result_t result)
1152 {
1153         unsigned int soacount = 0;
1154         unsigned int nscount = 0;
1155         isc_uint32_t serial, refresh, retry, expire, minimum;
1156         isc_time_t now;
1157         isc_boolean_t needdump = ISC_FALSE;
1158
1159         isc_time_now(&now);
1160
1161         /*
1162          * Initiate zone transfer?  We may need a error code that
1163          * indicates that the "permanent" form does not exist.
1164          * XXX better error feedback to log.
1165          */
1166         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
1167                 if (zone->type == dns_zone_slave ||
1168                     zone->type == dns_zone_stub) {
1169                         if (result == ISC_R_FILENOTFOUND)
1170                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1171                                              "no master file");
1172                         else if (result != DNS_R_NOMASTERFILE)
1173                                 dns_zone_log(zone, ISC_LOG_ERROR,
1174                                              "loading master file %s: %s",
1175                                              zone->masterfile,
1176                                              dns_result_totext(result));
1177                 } else
1178                         dns_zone_log(zone, ISC_LOG_ERROR,
1179                                      "loading master file %s: %s",
1180                                      zone->masterfile,
1181                                      dns_result_totext(result));
1182                 goto cleanup;
1183         }
1184
1185         dns_zone_log(zone, ISC_LOG_DEBUG(2),
1186                      "number of nodes in database: %u",
1187                      dns_db_nodecount(db));
1188         zone->loadtime = loadtime;
1189
1190         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
1191
1192         if (result == DNS_R_SEENINCLUDE)
1193                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1194         else
1195                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
1196         /*
1197          * Apply update log, if any.
1198          */
1199         if (zone->journal != NULL &&
1200             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE)) {
1201                 result = dns_journal_rollforward(zone->mctx, db,
1202                                                  zone->journal);
1203                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
1204                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
1205                     result != ISC_R_RANGE) {
1206                         dns_zone_log(zone, ISC_LOG_ERROR,
1207                                      "journal rollforward failed: %s",
1208                                      dns_result_totext(result));
1209                         goto cleanup;
1210                 }
1211                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
1212                         dns_zone_log(zone, ISC_LOG_ERROR,
1213                                      "journal rollforward failed: "
1214                                      "journal out of sync with zone");
1215                         goto cleanup;
1216                 }
1217                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1218                              "journal rollforward completed "
1219                              "successfully: %s",
1220                              dns_result_totext(result));
1221                 if (result == ISC_R_SUCCESS)
1222                         needdump = ISC_TRUE;
1223         }
1224
1225         /*
1226          * Obtain ns and soa counts for top of zone.
1227          */
1228         nscount = 0;
1229         soacount = 0;
1230         INSIST(db != NULL);
1231         result = zone_get_from_db(db, &zone->origin, &nscount,
1232                                   &soacount, &serial, &refresh, &retry,
1233                                   &expire, &minimum);
1234         if (result != ISC_R_SUCCESS) {
1235                 dns_zone_log(zone, ISC_LOG_ERROR,
1236                              "could not find NS and/or SOA records");
1237         }
1238
1239         /*
1240          * Master / Slave / Stub zones require both NS and SOA records at
1241          * the top of the zone.
1242          */
1243
1244         switch (zone->type) {
1245         case dns_zone_master:
1246         case dns_zone_slave:
1247         case dns_zone_stub:
1248                 if (soacount != 1) {
1249                         dns_zone_log(zone, ISC_LOG_ERROR,
1250                                      "has %d SOA records", soacount);
1251                         result = DNS_R_BADZONE;
1252                 }
1253                 if (nscount == 0) {
1254                         dns_zone_log(zone, ISC_LOG_ERROR,
1255                                      "has no NS records");
1256                         result = DNS_R_BADZONE;
1257                 }
1258                 if (result != ISC_R_SUCCESS)
1259                         goto cleanup;
1260                 if (zone->db != NULL) {
1261                         if (!isc_serial_ge(serial, zone->serial)) {
1262                                 dns_zone_log(zone, ISC_LOG_ERROR,
1263                                              "zone serial has gone backwards");
1264                         }
1265                 }
1266                 zone->serial = serial;
1267                 zone->refresh = RANGE(refresh,
1268                                       zone->minrefresh, zone->maxrefresh);
1269                 zone->retry = RANGE(retry,
1270                                     zone->minretry, zone->maxretry);
1271                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
1272                                      DNS_MAX_EXPIRE);
1273                 zone->minimum = minimum;
1274                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
1275
1276                 if (zone->type == dns_zone_slave ||
1277                     zone->type == dns_zone_stub) {
1278                         isc_time_t t;
1279                         isc_interval_t i;
1280                         unsigned int delay;
1281
1282                         result = isc_file_getmodtime(zone->journal, &t);
1283                         if (result != ISC_R_SUCCESS)
1284                                 result = isc_file_getmodtime(zone->masterfile,
1285                                                              &t);
1286
1287                         if (result == ISC_R_SUCCESS) {
1288                                 isc_interval_set(&i, zone->expire, 0);
1289                                 isc_time_add(&t, &i, &zone->expiretime);
1290                         } else {
1291                                 isc_interval_set(&i, zone->retry, 0);
1292                                 isc_time_add(&now, &i, &zone->expiretime);
1293                         }
1294                         delay = isc_random_jitter(zone->retry,
1295                                                   (zone->retry * 3) / 4);
1296                         isc_interval_set(&i, delay, 0);
1297                         isc_time_add(&now, &i, &zone->refreshtime);
1298                         if (isc_time_compare(&zone->refreshtime,   
1299                                              &zone->expiretime) >= 0)
1300                                 zone->refreshtime = now;
1301                 }
1302                 break;
1303         default:
1304                 UNEXPECTED_ERROR(__FILE__, __LINE__,
1305                                  "unexpected zone type %d", zone->type);
1306                 result = ISC_R_UNEXPECTED;
1307                 goto cleanup;
1308         }
1309
1310
1311 #if 0
1312         /* destroy notification example. */
1313         {
1314                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
1315                                                     DNS_EVENT_DBDESTROYED,
1316                                                     dns_zonemgr_dbdestroyed,
1317                                                     zone,
1318                                                     sizeof(isc_event_t));
1319                 dns_db_ondestroy(db, zone->task, &e);
1320         }
1321 #endif
1322
1323         if (zone->db != NULL) {
1324                 result = zone_replacedb(zone, db, ISC_FALSE);
1325                 if (result != ISC_R_SUCCESS)
1326                         goto cleanup;
1327         } else {
1328                 dns_db_attach(db, &zone->db);
1329                 DNS_ZONE_SETFLAG(zone,
1330                                  DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
1331         }
1332         result = ISC_R_SUCCESS;
1333         if (needdump)
1334                 zone_needdump(zone, DNS_DUMP_DELAY);
1335         if (zone->task != NULL)
1336                 zone_settimer(zone, &now);
1337         dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u", zone->serial);
1338         return (result);
1339
1340  cleanup:
1341         if (zone->type == dns_zone_slave ||
1342             zone->type == dns_zone_stub) {
1343                 if (zone->journal != NULL)
1344                         zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
1345                 if (zone->masterfile != NULL)
1346                         zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
1347
1348                 /* Mark the zone for immediate refresh. */
1349                 zone->refreshtime = now;
1350                 if (zone->task != NULL)
1351                         zone_settimer(zone, &now);
1352                 result = ISC_R_SUCCESS;
1353         }
1354         return (result);
1355 }
1356
1357 static isc_boolean_t
1358 exit_check(dns_zone_t *zone) {
1359
1360         REQUIRE(LOCKED_ZONE(zone));
1361
1362         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
1363             zone->irefs == 0)
1364         {
1365                 /*
1366                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
1367                  */
1368                 INSIST(isc_refcount_current(&zone->erefs) == 0);
1369                 return (ISC_TRUE);
1370         }
1371         return (ISC_FALSE);
1372 }
1373
1374 static isc_result_t
1375 zone_count_ns_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1376                  unsigned int *nscount)
1377 {
1378         isc_result_t result;
1379         unsigned int count;
1380         dns_rdataset_t rdataset;
1381
1382         REQUIRE(nscount != NULL);
1383
1384         dns_rdataset_init(&rdataset);
1385         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
1386                                      dns_rdatatype_none, 0, &rdataset, NULL);
1387         if (result == ISC_R_NOTFOUND) {
1388                 *nscount = 0;
1389                 result = ISC_R_SUCCESS;
1390                 goto invalidate_rdataset;
1391         }
1392         else if (result != ISC_R_SUCCESS)
1393                 goto invalidate_rdataset;
1394
1395         count = 0;
1396         result = dns_rdataset_first(&rdataset);
1397         while (result == ISC_R_SUCCESS) {
1398                 count++;
1399                 result = dns_rdataset_next(&rdataset);
1400         }
1401         dns_rdataset_disassociate(&rdataset);
1402
1403         *nscount = count;
1404         result = ISC_R_SUCCESS;
1405
1406  invalidate_rdataset:
1407         dns_rdataset_invalidate(&rdataset);
1408
1409         return (result);
1410 }
1411
1412 static isc_result_t
1413 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1414                  unsigned int *soacount,
1415                  isc_uint32_t *serial, isc_uint32_t *refresh,
1416                  isc_uint32_t *retry, isc_uint32_t *expire,
1417                  isc_uint32_t *minimum)
1418 {
1419         isc_result_t result;
1420         unsigned int count;
1421         dns_rdataset_t rdataset;
1422         dns_rdata_t rdata = DNS_RDATA_INIT;
1423         dns_rdata_soa_t soa;
1424
1425         dns_rdataset_init(&rdataset);
1426         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
1427                                      dns_rdatatype_none, 0, &rdataset, NULL);
1428         if (result != ISC_R_SUCCESS)
1429                 goto invalidate_rdataset;
1430
1431         count = 0;
1432         result = dns_rdataset_first(&rdataset);
1433         while (result == ISC_R_SUCCESS) {
1434                 dns_rdata_init(&rdata);
1435                 dns_rdataset_current(&rdataset, &rdata);
1436                 count++;
1437                 if (count == 1)
1438                         dns_rdata_tostruct(&rdata, &soa, NULL);
1439
1440                 result = dns_rdataset_next(&rdataset);
1441                 dns_rdata_reset(&rdata);
1442         }
1443         dns_rdataset_disassociate(&rdataset);
1444
1445         if (soacount != NULL)
1446                 *soacount = count;
1447
1448         if (count > 0) {
1449                 if (serial != NULL)
1450                         *serial = soa.serial;
1451                 if (refresh != NULL)
1452                         *refresh = soa.refresh;
1453                 if (retry != NULL)
1454                         *retry = soa.retry;
1455                 if (expire != NULL)
1456                         *expire = soa.expire;
1457                 if (minimum != NULL)
1458                         *minimum = soa.minimum;
1459         }
1460
1461         result = ISC_R_SUCCESS;
1462
1463  invalidate_rdataset:
1464         dns_rdataset_invalidate(&rdataset);
1465
1466         return (result);
1467 }
1468
1469 /*
1470  * zone must be locked.
1471  */
1472 static isc_result_t
1473 zone_get_from_db(dns_db_t *db, dns_name_t *origin, unsigned int *nscount,
1474                  unsigned int *soacount, isc_uint32_t *serial,
1475                  isc_uint32_t *refresh, isc_uint32_t *retry,
1476                  isc_uint32_t *expire, isc_uint32_t *minimum)
1477 {
1478         dns_dbversion_t *version;
1479         isc_result_t result;
1480         isc_result_t answer = ISC_R_SUCCESS;
1481         dns_dbnode_t *node;
1482
1483         REQUIRE(db != NULL);
1484         REQUIRE(origin != NULL);
1485
1486         version = NULL;
1487         dns_db_currentversion(db, &version);
1488
1489         node = NULL;
1490         result = dns_db_findnode(db, origin, ISC_FALSE, &node);
1491         if (result != ISC_R_SUCCESS) {
1492                 answer = result;
1493                 goto closeversion;
1494         }
1495
1496         if (nscount != NULL) {
1497                 result = zone_count_ns_rr(db, node, version, nscount);
1498                 if (result != ISC_R_SUCCESS)
1499                         answer = result;
1500         }
1501
1502         if (soacount != NULL || serial != NULL || refresh != NULL
1503             || retry != NULL || expire != NULL || minimum != NULL) {
1504                 result = zone_load_soa_rr(db, node, version, soacount,
1505                                           serial, refresh, retry, expire,
1506                                           minimum);
1507                 if (result != ISC_R_SUCCESS)
1508                         answer = result;
1509         }
1510
1511         dns_db_detachnode(db, &node);
1512  closeversion:
1513         dns_db_closeversion(db, &version, ISC_FALSE);
1514
1515         return (answer);
1516 }
1517
1518 void
1519 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
1520         REQUIRE(DNS_ZONE_VALID(source));
1521         REQUIRE(target != NULL && *target == NULL);
1522         isc_refcount_increment(&source->erefs, NULL);
1523         *target = source;
1524 }
1525
1526 void
1527 dns_zone_detach(dns_zone_t **zonep) {
1528         dns_zone_t *zone;
1529         unsigned int refs;
1530         isc_boolean_t free_now = ISC_FALSE;
1531
1532         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1533
1534         zone = *zonep;
1535
1536         isc_refcount_decrement(&zone->erefs, &refs);
1537
1538         if (refs == 0) {
1539                 LOCK_ZONE(zone);
1540                 /*
1541                  * We just detached the last external reference.
1542                  */
1543                 if (zone->task != NULL) {
1544                         /*
1545                          * This zone is being managed.  Post
1546                          * its control event and let it clean
1547                          * up synchronously in the context of
1548                          * its task.
1549                          */
1550                         isc_event_t *ev = &zone->ctlevent;
1551                         isc_task_send(zone->task, &ev);
1552                 } else {
1553                         /*
1554                          * This zone is not being managed; it has
1555                          * no task and can have no outstanding
1556                          * events.  Free it immediately.
1557                          */
1558                         /*
1559                          * Unmanaged zones should not have non-null views;
1560                          * we have no way of detaching from the view here
1561                          * without causing deadlock because this code is called
1562                          * with the view already locked.
1563                          */
1564                         INSIST(zone->view == NULL);
1565                         free_now = ISC_TRUE;
1566                 }
1567                 UNLOCK_ZONE(zone);
1568         }
1569         *zonep = NULL;
1570         if (free_now)
1571                 zone_free(zone);
1572 }
1573
1574 void
1575 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
1576         REQUIRE(DNS_ZONE_VALID(source));
1577         REQUIRE(target != NULL && *target == NULL);
1578         LOCK_ZONE(source);
1579         zone_iattach(source, target);
1580         UNLOCK_ZONE(source);
1581 }
1582
1583 static void
1584 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
1585
1586         /*
1587          * 'source' locked by caller.
1588          */
1589         REQUIRE(LOCKED_ZONE(source));
1590         REQUIRE(DNS_ZONE_VALID(source));
1591         REQUIRE(target != NULL && *target == NULL);
1592         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
1593         source->irefs++;
1594         INSIST(source->irefs != 0);
1595         *target = source;
1596 }
1597
1598 static void
1599 zone_idetach(dns_zone_t **zonep) {
1600         dns_zone_t *zone;
1601
1602         /*
1603          * 'zone' locked by caller.
1604          */
1605         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1606         zone = *zonep;
1607         REQUIRE(LOCKED_ZONE(*zonep));
1608         *zonep = NULL;
1609
1610         INSIST(zone->irefs > 0);
1611         zone->irefs--;
1612         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
1613 }
1614
1615 void
1616 dns_zone_idetach(dns_zone_t **zonep) {
1617         dns_zone_t *zone;
1618         isc_boolean_t free_needed;
1619
1620         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
1621         zone = *zonep;
1622         *zonep = NULL;
1623
1624         LOCK_ZONE(zone);
1625         INSIST(zone->irefs > 0);
1626         zone->irefs--;
1627         free_needed = exit_check(zone);
1628         UNLOCK_ZONE(zone);
1629         if (free_needed)
1630                 zone_free(zone);
1631 }
1632
1633 isc_mem_t *
1634 dns_zone_getmctx(dns_zone_t *zone) {
1635         REQUIRE(DNS_ZONE_VALID(zone));
1636
1637         return (zone->mctx);
1638 }
1639
1640 dns_zonemgr_t *
1641 dns_zone_getmgr(dns_zone_t *zone) {
1642         REQUIRE(DNS_ZONE_VALID(zone));
1643
1644         return (zone->zmgr);
1645 }
1646
1647 void
1648 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
1649         REQUIRE(DNS_ZONE_VALID(zone));
1650
1651         LOCK_ZONE(zone);
1652         if (value)
1653                 DNS_ZONE_SETFLAG(zone, flags);
1654         else
1655                 DNS_ZONE_CLRFLAG(zone, flags);
1656         UNLOCK_ZONE(zone);
1657 }
1658
1659 void
1660 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
1661 {
1662         REQUIRE(DNS_ZONE_VALID(zone));
1663
1664         LOCK_ZONE(zone);
1665         if (value)
1666                 zone->options |= option;
1667         else
1668                 zone->options &= ~option;
1669         UNLOCK_ZONE(zone);
1670 }
1671
1672 unsigned int
1673 dns_zone_getoptions(dns_zone_t *zone) {
1674
1675         REQUIRE(DNS_ZONE_VALID(zone));
1676
1677         return (zone->options);
1678 }
1679
1680 isc_result_t
1681 dns_zone_setxfrsource4(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
1682         REQUIRE(DNS_ZONE_VALID(zone));
1683
1684         LOCK_ZONE(zone);
1685         zone->xfrsource4 = *xfrsource;
1686         UNLOCK_ZONE(zone);
1687
1688         return (ISC_R_SUCCESS);
1689 }
1690
1691 isc_sockaddr_t *
1692 dns_zone_getxfrsource4(dns_zone_t *zone) {
1693         REQUIRE(DNS_ZONE_VALID(zone));
1694         return (&zone->xfrsource4);
1695 }
1696
1697 isc_result_t
1698 dns_zone_setxfrsource6(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
1699         REQUIRE(DNS_ZONE_VALID(zone));
1700
1701         LOCK_ZONE(zone);
1702         zone->xfrsource6 = *xfrsource;
1703         UNLOCK_ZONE(zone);
1704
1705         return (ISC_R_SUCCESS);
1706 }
1707
1708 isc_sockaddr_t *
1709 dns_zone_getxfrsource6(dns_zone_t *zone) {
1710         REQUIRE(DNS_ZONE_VALID(zone));
1711         return (&zone->xfrsource6);
1712 }
1713
1714 isc_result_t
1715 dns_zone_setnotifysrc4(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
1716         REQUIRE(DNS_ZONE_VALID(zone));
1717
1718         LOCK_ZONE(zone);
1719         zone->notifysrc4 = *notifysrc;
1720         UNLOCK_ZONE(zone);
1721
1722         return (ISC_R_SUCCESS);
1723 }
1724
1725 isc_sockaddr_t *
1726 dns_zone_getnotifysrc4(dns_zone_t *zone) {
1727         REQUIRE(DNS_ZONE_VALID(zone));
1728         return (&zone->notifysrc4);
1729 }
1730
1731 isc_result_t
1732 dns_zone_setnotifysrc6(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
1733         REQUIRE(DNS_ZONE_VALID(zone));
1734
1735         LOCK_ZONE(zone);
1736         zone->notifysrc6 = *notifysrc;
1737         UNLOCK_ZONE(zone);
1738
1739         return (ISC_R_SUCCESS);
1740 }
1741
1742 isc_sockaddr_t *
1743 dns_zone_getnotifysrc6(dns_zone_t *zone) {
1744         REQUIRE(DNS_ZONE_VALID(zone));
1745         return (&zone->notifysrc6);
1746 }
1747
1748 isc_result_t
1749 dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *notify,
1750                        isc_uint32_t count)
1751 {
1752         isc_sockaddr_t *new;
1753
1754         REQUIRE(DNS_ZONE_VALID(zone));
1755         REQUIRE(count == 0 || notify != NULL);
1756
1757         LOCK_ZONE(zone);
1758         if (zone->notify != NULL) {
1759                 isc_mem_put(zone->mctx, zone->notify,
1760                             zone->notifycnt * sizeof *new);
1761                 zone->notify = NULL;
1762                 zone->notifycnt = 0;
1763         }
1764         if (count != 0) {
1765                 new = isc_mem_get(zone->mctx, count * sizeof *new);
1766                 if (new == NULL) {
1767                         UNLOCK_ZONE(zone);
1768                         return (ISC_R_NOMEMORY);
1769                 }
1770                 memcpy(new, notify, count * sizeof *new);
1771                 zone->notify = new;
1772                 zone->notifycnt = count;
1773         }
1774         UNLOCK_ZONE(zone);
1775         return (ISC_R_SUCCESS);
1776 }
1777
1778 isc_result_t
1779 dns_zone_setmasters(dns_zone_t *zone, isc_sockaddr_t *masters,
1780                     isc_uint32_t count)
1781 {
1782         isc_result_t result;
1783
1784         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
1785         return (result);
1786 }
1787
1788 isc_result_t
1789 dns_zone_setmasterswithkeys(dns_zone_t *zone, isc_sockaddr_t *masters,
1790                             dns_name_t **keynames, isc_uint32_t count)
1791 {
1792         isc_sockaddr_t *new;
1793         isc_result_t result = ISC_R_SUCCESS;
1794         dns_name_t **newname;
1795         unsigned int i;
1796
1797         REQUIRE(DNS_ZONE_VALID(zone));
1798         REQUIRE(count == 0 || masters != NULL);
1799         if (keynames != NULL) {
1800                 REQUIRE(count != 0);
1801         }
1802
1803         LOCK_ZONE(zone);
1804         if (zone->masters != NULL) {
1805                 isc_mem_put(zone->mctx, zone->masters,
1806                             zone->masterscnt * sizeof *new);
1807                 zone->masters = NULL;
1808         }
1809         if (zone->masterkeynames != NULL) {
1810                 for (i = 0; i < zone->masterscnt; i++) {
1811                         if (zone->masterkeynames[i] != NULL) {
1812                                 dns_name_free(zone->masterkeynames[i],
1813                                               zone->mctx);
1814                                 isc_mem_put(zone->mctx,
1815                                             zone->masterkeynames[i],
1816                                             sizeof(dns_name_t));
1817                                 zone->masterkeynames[i] = NULL;
1818                         }
1819                 }
1820                 isc_mem_put(zone->mctx, zone->masterkeynames,
1821                             zone->masterscnt * sizeof(dns_name_t *));
1822                 zone->masterkeynames = NULL;
1823         }
1824         zone->masterscnt = 0;
1825         /*
1826          * If count == 0, don't allocate any space for masters or keynames
1827          * so internally, those pointers are NULL if count == 0
1828          */
1829         if (count == 0)
1830                 goto unlock;
1831
1832         /*
1833          * masters must countain count elements!
1834          */
1835         new = isc_mem_get(zone->mctx,
1836                           count * sizeof(isc_sockaddr_t));
1837         if (new == NULL) {
1838                 result = ISC_R_NOMEMORY;
1839                 goto unlock;
1840         }
1841         memcpy(new, masters, count * sizeof *new);
1842         zone->masters = new;
1843         zone->masterscnt = count;
1844         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
1845
1846         /*
1847          * if keynames is non-NULL, it must contain count elements!
1848          */
1849         if (keynames != NULL) {
1850                 newname = isc_mem_get(zone->mctx,
1851                                       count * sizeof(dns_name_t *));
1852                 if (newname == NULL) {
1853                         result = ISC_R_NOMEMORY;
1854                         isc_mem_put(zone->mctx, zone->masters,
1855                                     count * sizeof *new);
1856                         goto unlock;
1857                 }
1858                 for (i = 0; i < count; i++)
1859                         newname[i] = NULL;
1860                 for (i = 0; i < count; i++) {
1861                         if (keynames[i] != NULL) {
1862                                 newname[i] = isc_mem_get(zone->mctx,
1863                                                          sizeof(dns_name_t));
1864                                 if (newname[i] == NULL)
1865                                         goto allocfail;
1866                                 dns_name_init(newname[i], NULL);
1867                                 result = dns_name_dup(keynames[i], zone->mctx,
1868                                                       newname[i]);
1869                                 if (result != ISC_R_SUCCESS) {
1870                                 allocfail:
1871                                         for (i = 0; i < count; i++)
1872                                                 if (newname[i] != NULL)
1873                                                         dns_name_free(
1874                                                                newname[i],
1875                                                                zone->mctx);
1876                                         isc_mem_put(zone->mctx, zone->masters,
1877                                                     count * sizeof *new);
1878                                         isc_mem_put(zone->mctx, newname,
1879                                                     count * sizeof *newname);
1880                                         goto unlock;
1881                                 }
1882                         }
1883                 }
1884                 zone->masterkeynames = newname;
1885         }
1886  unlock:
1887         UNLOCK_ZONE(zone);
1888         return (result);
1889 }
1890
1891 isc_result_t
1892 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
1893         isc_result_t result = ISC_R_SUCCESS;
1894
1895         REQUIRE(DNS_ZONE_VALID(zone));
1896
1897         LOCK_ZONE(zone);
1898         if (zone->db == NULL)
1899                 result = DNS_R_NOTLOADED;
1900         else
1901                 dns_db_attach(zone->db, dpb);
1902         UNLOCK_ZONE(zone);
1903
1904         return (result);
1905 }
1906
1907 /*
1908  * Co-ordinates the starting of routine jobs.
1909  */
1910
1911 void
1912 dns_zone_maintenance(dns_zone_t *zone) {
1913         const char me[] = "dns_zone_maintenance";
1914         isc_time_t now;
1915
1916         REQUIRE(DNS_ZONE_VALID(zone));
1917         ENTER;
1918
1919         LOCK_ZONE(zone);
1920         isc_time_now(&now);
1921         zone_settimer(zone, &now);
1922         UNLOCK_ZONE(zone);
1923 }
1924
1925 static inline isc_boolean_t
1926 was_dumping(dns_zone_t *zone) {
1927         isc_boolean_t dumping;
1928         
1929         REQUIRE(LOCKED_ZONE(zone));
1930
1931         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
1932         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
1933         if (!dumping) {
1934                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
1935                 isc_time_settoepoch(&zone->dumptime);
1936         }
1937         return (dumping);
1938 }
1939
1940 static void
1941 zone_maintenance(dns_zone_t *zone) {
1942         const char me[] = "zone_maintenance";
1943         isc_time_t now;
1944         isc_result_t result;
1945         isc_boolean_t dumping;
1946
1947         REQUIRE(DNS_ZONE_VALID(zone));
1948         ENTER;
1949
1950         /*
1951          * Configuring the view of this zone may have
1952          * failed, for example because the config file
1953          * had a syntax error.  In that case, the view
1954          * adb or resolver, and we had better not try
1955          * to do maintenance on it.
1956          */
1957         if (zone->view == NULL || zone->view->adb == NULL)
1958                 return;
1959
1960         isc_time_now(&now);
1961
1962         /*
1963          * Expire check.
1964          */
1965         switch (zone->type) {
1966         case dns_zone_slave:
1967         case dns_zone_stub:
1968                 LOCK_ZONE(zone);
1969                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
1970                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1971                         zone_expire(zone);
1972                         zone->refreshtime = now;
1973                 }
1974                 UNLOCK_ZONE(zone);
1975                 break;
1976         default:
1977                 break;
1978         }
1979
1980         /*
1981          * Up to date check.
1982          */
1983         switch (zone->type) {
1984         case dns_zone_slave:
1985         case dns_zone_stub:
1986                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
1987                     isc_time_compare(&now, &zone->refreshtime) >= 0)
1988                         dns_zone_refresh(zone);
1989                 break;
1990         default:
1991                 break;
1992         }
1993
1994         /*
1995          * Do we need to consolidate the backing store?
1996          */
1997         switch (zone->type) {
1998         case dns_zone_master:
1999         case dns_zone_slave:
2000                 LOCK_ZONE(zone);
2001                 if (zone->masterfile != NULL &&
2002                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
2003                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2004                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
2005                         dumping = was_dumping(zone);
2006                 } else
2007                         dumping = ISC_TRUE;
2008                 UNLOCK_ZONE(zone);
2009                 if (!dumping) {
2010                         result = zone_dump(zone);
2011                         if (result != ISC_R_SUCCESS)
2012                                 dns_zone_log(zone, ISC_LOG_WARNING,
2013                                              "dump failed: %s",
2014                                              dns_result_totext(result));
2015                 }
2016                 break;
2017         default:
2018                 break;
2019         }
2020
2021         /*
2022          * Do we need to send out notify messages?
2023          */
2024         switch (zone->type) {
2025         case dns_zone_master:
2026         case dns_zone_slave:
2027                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
2028                         zone_notify(zone);
2029                 break;
2030         default:
2031                 break;
2032         }
2033         zone_settimer(zone, &now);
2034 }
2035
2036 void
2037 dns_zone_markdirty(dns_zone_t *zone) {
2038
2039         LOCK_ZONE(zone);
2040         zone_needdump(zone, DNS_DUMP_DELAY);
2041         UNLOCK_ZONE(zone);
2042 }
2043
2044 void
2045 dns_zone_expire(dns_zone_t *zone) {
2046         REQUIRE(DNS_ZONE_VALID(zone));
2047
2048         LOCK_ZONE(zone);
2049         zone_expire(zone);
2050         UNLOCK_ZONE(zone);
2051 }
2052
2053 static void
2054 zone_expire(dns_zone_t *zone) {
2055         /*
2056          * 'zone' locked by caller.
2057          */
2058
2059         REQUIRE(LOCKED_ZONE(zone));
2060
2061         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
2062
2063         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
2064         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
2065         zone->retry = DNS_ZONE_DEFAULTRETRY;
2066         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
2067         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2068         zone_unload(zone);
2069 }
2070
2071 void
2072 dns_zone_refresh(dns_zone_t *zone) {
2073         isc_interval_t i;
2074         isc_uint32_t oldflags;
2075
2076         REQUIRE(DNS_ZONE_VALID(zone));
2077
2078         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
2079                 return;
2080
2081         /*
2082          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
2083          * in progress at a time.
2084          */
2085
2086         LOCK_ZONE(zone);
2087         oldflags = zone->flags;
2088         if (zone->masterscnt == 0) {
2089                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
2090                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
2091                         dns_zone_log(zone, ISC_LOG_ERROR,
2092                                      "cannot refresh: no masters");
2093                 goto unlock;
2094         }
2095         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
2096         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
2097                 goto unlock;
2098
2099         /*
2100          * Set the next refresh time as if refresh check has failed.
2101          * Setting this to the retry time will do that.  XXXMLG
2102          * If we are successful it will be reset using zone->refresh.
2103          */
2104         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
2105                          0);
2106         isc_time_nowplusinterval(&zone->refreshtime, &i);
2107
2108         /*
2109          * When lacking user-specified timer values from the SOA,
2110          * do exponential backoff of the retry time up to a 
2111          * maximum of six hours.
2112          */
2113         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
2114                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
2115
2116         zone->curmaster = 0;
2117         zone->refreshcnt = 0;
2118         /* initiate soa query */
2119         queue_soa_query(zone);
2120  unlock:
2121         UNLOCK_ZONE(zone);
2122 }
2123
2124 isc_result_t
2125 dns_zone_flush(dns_zone_t *zone) {
2126         isc_result_t result = ISC_R_ALREADYRUNNING;
2127         isc_boolean_t dumping;
2128
2129         REQUIRE(DNS_ZONE_VALID(zone));
2130
2131         LOCK_ZONE(zone);
2132         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
2133         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
2134             zone->masterfile != NULL)
2135                 dumping = was_dumping(zone);
2136         else
2137                 dumping = ISC_TRUE;
2138         UNLOCK_ZONE(zone);
2139         if (!dumping)
2140                 result = zone_dump(zone);
2141         return (result);
2142 }
2143
2144 isc_result_t
2145 dns_zone_dump(dns_zone_t *zone) {
2146         isc_result_t result = ISC_R_ALREADYRUNNING;
2147         isc_boolean_t dumping;
2148
2149         REQUIRE(DNS_ZONE_VALID(zone));
2150
2151         LOCK_ZONE(zone);
2152         dumping = was_dumping(zone);
2153         UNLOCK_ZONE(zone);
2154         if (!dumping)
2155                 result = zone_dump(zone);
2156         return (result);
2157 }
2158
2159 static void
2160 zone_needdump(dns_zone_t *zone, unsigned int delay) {
2161         isc_time_t dumptime;
2162         isc_time_t now;
2163         isc_interval_t i;
2164
2165         /*
2166          * 'zone' locked by caller
2167          */
2168
2169         REQUIRE(DNS_ZONE_VALID(zone));
2170         REQUIRE(LOCKED_ZONE(zone));
2171
2172         /*
2173          * Do we have a place to dump to and are we loaded?
2174          */
2175         if (zone->masterfile == NULL ||
2176             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
2177                 return;
2178
2179         isc_interval_set(&i, delay, 0);
2180         isc_time_now(&now);
2181         isc_time_add(&now, &i, &dumptime);
2182
2183         /* add some noise */
2184         delay = isc_random_jitter(delay, delay/4);
2185
2186         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2187         if (isc_time_isepoch(&zone->dumptime) ||
2188             isc_time_compare(&zone->dumptime, &dumptime) > 0)
2189                 zone->dumptime = dumptime;
2190         if (zone->task != NULL)
2191                 zone_settimer(zone, &now);
2192 }
2193
2194 static isc_result_t
2195 zone_dump(dns_zone_t *zone) {
2196         isc_result_t result;
2197         dns_dbversion_t *version = NULL;
2198         isc_boolean_t again;
2199         dns_db_t *db = NULL;
2200         char *masterfile = NULL;
2201
2202         REQUIRE(DNS_ZONE_VALID(zone));
2203
2204  redo:
2205         LOCK_ZONE(zone);
2206         if (zone->db != NULL)
2207                 dns_db_attach(zone->db, &db);
2208         if (zone->masterfile != NULL)
2209                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
2210         UNLOCK_ZONE(zone);
2211         if (db == NULL) {
2212                 result = DNS_R_NOTLOADED;
2213                 goto fail;
2214         }
2215         if (masterfile == NULL) {
2216                 result = DNS_R_NOMASTERFILE;
2217                 goto fail;
2218         }
2219         dns_db_currentversion(db, &version);
2220
2221         result = dns_master_dump(zone->mctx, db, version,
2222                                  &dns_master_style_default, masterfile);
2223
2224         dns_db_closeversion(db, &version, ISC_FALSE);
2225  fail:
2226         if (db != NULL)
2227                 dns_db_detach(&db);
2228         if (masterfile != NULL)
2229                 isc_mem_free(zone->mctx, masterfile);
2230         masterfile = NULL;
2231
2232         again = ISC_FALSE;
2233         LOCK_ZONE(zone);
2234         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
2235         if (result != ISC_R_SUCCESS) {
2236                 /*
2237                  * Try again in a short while.
2238                  */
2239                 zone_needdump(zone, DNS_DUMP_DELAY);
2240         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
2241                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
2242                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
2243                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
2244                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
2245                 isc_time_settoepoch(&zone->dumptime);
2246                 again = ISC_TRUE;
2247         }
2248         UNLOCK_ZONE(zone);
2249         if (again)
2250                 goto redo;
2251
2252         return (result);
2253 }
2254
2255 isc_result_t
2256 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
2257         isc_result_t result;
2258         dns_dbversion_t *version = NULL;
2259         dns_db_t *db = NULL;
2260
2261         REQUIRE(DNS_ZONE_VALID(zone));
2262
2263         LOCK_ZONE(zone);
2264         if (zone->db != NULL)
2265                 dns_db_attach(zone->db, &db);
2266         UNLOCK_ZONE(zone);
2267         if (db == NULL)
2268                 return (DNS_R_NOTLOADED);
2269
2270         dns_db_currentversion(db, &version);
2271         result = dns_master_dumptostream(zone->mctx, db, version,
2272                                          &dns_master_style_default, fd);
2273         dns_db_closeversion(db, &version, ISC_FALSE);
2274         dns_db_detach(&db);
2275         return (result);
2276 }
2277
2278 void
2279 dns_zone_unload(dns_zone_t *zone) {
2280         REQUIRE(DNS_ZONE_VALID(zone));
2281
2282         LOCK_ZONE(zone);
2283         zone_unload(zone);
2284         UNLOCK_ZONE(zone);
2285 }
2286
2287 static void
2288 notify_cancel(dns_zone_t *zone) {
2289         dns_notify_t *notify;
2290
2291         /*
2292          * 'zone' locked by caller.
2293          */
2294
2295         REQUIRE(LOCKED_ZONE(zone));
2296
2297         for (notify = ISC_LIST_HEAD(zone->notifies);
2298              notify != NULL;
2299              notify = ISC_LIST_NEXT(notify, link)) {
2300                 if (notify->find != NULL)
2301                         dns_adb_cancelfind(notify->find);
2302                 if (notify->request != NULL)
2303                         dns_request_cancel(notify->request);
2304         }
2305 }
2306
2307 static void
2308 zone_unload(dns_zone_t *zone) {
2309
2310         /*
2311          * 'zone' locked by caller.
2312          */ 
2313
2314         REQUIRE(LOCKED_ZONE(zone));
2315
2316         dns_db_detach(&zone->db);
2317         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
2318 }
2319
2320 void
2321 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
2322         REQUIRE(DNS_ZONE_VALID(zone));
2323         REQUIRE(val > 0);
2324
2325         zone->minrefresh = val;
2326 }
2327
2328 void
2329 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
2330         REQUIRE(DNS_ZONE_VALID(zone));
2331         REQUIRE(val > 0);
2332
2333         zone->maxrefresh = val;
2334 }
2335
2336 void
2337 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
2338         REQUIRE(DNS_ZONE_VALID(zone));
2339         REQUIRE(val > 0);
2340
2341         zone->minretry = val;
2342 }
2343
2344 void
2345 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
2346         REQUIRE(DNS_ZONE_VALID(zone));
2347         REQUIRE(val > 0);
2348
2349         zone->maxretry = val;
2350 }
2351
2352 static isc_boolean_t
2353 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
2354         dns_notify_t *notify;
2355
2356         for (notify = ISC_LIST_HEAD(zone->notifies);
2357              notify != NULL;
2358              notify = ISC_LIST_NEXT(notify, link)) {
2359                 if (notify->request != NULL)
2360                         continue;
2361                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
2362                     dns_name_equal(name, &notify->ns))
2363                         return (ISC_TRUE);
2364                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
2365                         return (ISC_TRUE);
2366         }
2367         return (ISC_FALSE);
2368 }
2369
2370 static void
2371 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
2372         isc_mem_t *mctx;
2373
2374         /*
2375          * Caller holds zone lock.
2376          */
2377         REQUIRE(DNS_NOTIFY_VALID(notify));
2378
2379         if (notify->zone != NULL) {
2380                 if (!locked)
2381                         LOCK_ZONE(notify->zone);
2382                 REQUIRE(LOCKED_ZONE(notify->zone));
2383                 if (ISC_LINK_LINKED(notify, link))
2384                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
2385                 if (!locked)
2386                         UNLOCK_ZONE(notify->zone);
2387                 if (locked)
2388                         zone_idetach(&notify->zone);
2389                 else
2390                         dns_zone_idetach(&notify->zone);
2391         }
2392         if (notify->find != NULL)
2393                 dns_adb_destroyfind(&notify->find);
2394         if (notify->request != NULL)
2395                 dns_request_destroy(&notify->request);
2396         if (dns_name_dynamic(&notify->ns))
2397                 dns_name_free(&notify->ns, notify->mctx);
2398         mctx = notify->mctx;
2399         isc_mem_put(notify->mctx, notify, sizeof *notify);
2400         isc_mem_detach(&mctx);
2401 }
2402
2403 static isc_result_t
2404 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
2405         dns_notify_t *notify;
2406
2407         REQUIRE(notifyp != NULL && *notifyp == NULL);
2408
2409         notify = isc_mem_get(mctx, sizeof *notify);
2410         if (notify == NULL)
2411                 return (ISC_R_NOMEMORY);
2412
2413         notify->mctx = NULL;
2414         isc_mem_attach(mctx, &notify->mctx);
2415         notify->flags = flags;
2416         notify->zone = NULL;
2417         notify->find = NULL;
2418         notify->request = NULL;
2419         isc_sockaddr_any(&notify->dst);
2420         dns_name_init(&notify->ns, NULL);
2421         notify->attempt = 0;
2422         ISC_LINK_INIT(notify, link);
2423         notify->magic = NOTIFY_MAGIC;
2424         *notifyp = notify;
2425         return (ISC_R_SUCCESS);
2426 }
2427
2428 /*
2429  * XXXAG should check for DNS_ZONEFLG_EXITING
2430  */
2431 static void
2432 process_adb_event(isc_task_t *task, isc_event_t *ev) {
2433         dns_notify_t *notify;
2434         isc_eventtype_t result;
2435
2436         UNUSED(task);
2437
2438         notify = ev->ev_arg;
2439         REQUIRE(DNS_NOTIFY_VALID(notify));
2440         INSIST(task == notify->zone->task);
2441         result = ev->ev_type;
2442         isc_event_free(&ev);
2443         if (result == DNS_EVENT_ADBMOREADDRESSES) {
2444                 dns_adb_destroyfind(&notify->find);
2445                 notify_find_address(notify);
2446                 return;
2447         }
2448         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
2449                 LOCK_ZONE(notify->zone);
2450                 notify_send(notify);
2451                 UNLOCK_ZONE(notify->zone);
2452         }
2453         notify_destroy(notify, ISC_FALSE);
2454 }
2455
2456 static void
2457 notify_find_address(dns_notify_t *notify) {
2458         isc_result_t result;
2459         unsigned int options;
2460
2461         REQUIRE(DNS_NOTIFY_VALID(notify));
2462         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
2463                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
2464
2465         if (notify->zone->view->adb == NULL)
2466                 goto destroy;
2467         
2468         result = dns_adb_createfind(notify->zone->view->adb,
2469                                     notify->zone->task,
2470                                     process_adb_event, notify,
2471                                     &notify->ns, dns_rootname,
2472                                     options, 0, NULL,
2473                                     notify->zone->view->dstport,
2474                                     &notify->find);
2475
2476         /* Something failed? */
2477         if (result != ISC_R_SUCCESS)
2478                 goto destroy;
2479
2480         /* More addresses pending? */
2481         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
2482                 return;
2483
2484         /* We have as many addresses as we can get. */
2485         LOCK_ZONE(notify->zone);
2486         notify_send(notify);
2487         UNLOCK_ZONE(notify->zone);
2488
2489  destroy:
2490         notify_destroy(notify, ISC_FALSE);
2491 }
2492
2493
2494 static isc_result_t
2495 notify_send_queue(dns_notify_t *notify) {
2496         isc_event_t *e;
2497         isc_result_t result;
2498
2499         e = isc_event_allocate(notify->mctx, NULL,
2500                                DNS_EVENT_NOTIFYSENDTOADDR,
2501                                notify_send_toaddr,
2502                                notify, sizeof(isc_event_t));
2503         if (e == NULL)
2504                 return (ISC_R_NOMEMORY);
2505         e->ev_arg = notify;
2506         e->ev_sender = NULL;
2507         result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
2508                                          notify->zone->task, &e);
2509         if (result != ISC_R_SUCCESS)
2510                 isc_event_free(&e);
2511         return (result);
2512 }
2513
2514 static void
2515 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
2516         dns_notify_t *notify;
2517         isc_result_t result;
2518         dns_message_t *message = NULL;
2519         isc_netaddr_t dstip;
2520         dns_tsigkey_t *key = NULL;
2521         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2522         isc_sockaddr_t src;
2523         int timeout;
2524
2525         notify = event->ev_arg;
2526         REQUIRE(DNS_NOTIFY_VALID(notify));
2527
2528         UNUSED(task);
2529
2530         LOCK_ZONE(notify->zone);
2531
2532         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
2533                 result = ISC_R_CANCELED;
2534                 goto cleanup;
2535         }
2536
2537         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
2538             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
2539             notify->zone->view->requestmgr == NULL ||
2540             notify->zone->db == NULL) {
2541                 result = ISC_R_CANCELED;
2542                 goto cleanup;
2543         }
2544
2545         result = notify_createmessage(notify->zone, notify->flags, &message);
2546         if (result != ISC_R_SUCCESS)
2547                 goto cleanup;
2548
2549         isc_netaddr_fromsockaddr(&dstip, &notify->dst);
2550         (void)dns_view_getpeertsig(notify->zone->view, &dstip, &key);
2551
2552         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
2553         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
2554                    addrbuf);
2555         switch (isc_sockaddr_pf(&notify->dst)) {
2556         case PF_INET:
2557                 src = notify->zone->notifysrc4;
2558                 break;
2559         case PF_INET6:
2560                 src = notify->zone->notifysrc6;
2561                 break;
2562         default:
2563                 result = ISC_R_NOTIMPLEMENTED;
2564                 goto cleanup_key;
2565         }
2566         timeout = 15;
2567         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
2568                 timeout = 30;
2569         result = dns_request_createvia(notify->zone->view->requestmgr, message,
2570                                        &src, &notify->dst, 0, key, timeout,
2571                                        notify->zone->task,
2572                                        notify_done, notify,
2573                                        &notify->request);
2574  cleanup_key:
2575         if (key != NULL)
2576                 dns_tsigkey_detach(&key);
2577         dns_message_destroy(&message);
2578  cleanup:
2579         UNLOCK_ZONE(notify->zone);
2580         if (result != ISC_R_SUCCESS)
2581                 notify_destroy(notify, ISC_FALSE);
2582         isc_event_free(&event);
2583 }
2584
2585 static void
2586 notify_send(dns_notify_t *notify) {
2587         dns_adbaddrinfo_t *ai;
2588         isc_sockaddr_t dst;
2589         isc_result_t result;
2590         dns_notify_t *new = NULL;
2591
2592         /*
2593          * Zone lock held by caller.
2594          */
2595         REQUIRE(DNS_NOTIFY_VALID(notify));
2596         REQUIRE(LOCKED_ZONE(notify->zone));
2597
2598         for (ai = ISC_LIST_HEAD(notify->find->list);
2599              ai != NULL;
2600              ai = ISC_LIST_NEXT(ai, publink)) {
2601                 dst = ai->sockaddr;
2602                 if (notify_isqueued(notify->zone, NULL, &dst))
2603                         continue;
2604                 new = NULL;
2605                 result = notify_create(notify->mctx,
2606                                        (notify->flags & DNS_NOTIFY_NOSOA),
2607                                        &new);
2608                 if (result != ISC_R_SUCCESS)
2609                         goto cleanup;
2610                 zone_iattach(notify->zone, &new->zone);
2611                 ISC_LIST_APPEND(new->zone->notifies, new, link);
2612                 new->dst = dst;
2613                 result = notify_send_queue(new);
2614                 if (result != ISC_R_SUCCESS)
2615                         goto cleanup;
2616                 new = NULL;
2617         }
2618
2619  cleanup:
2620         if (new != NULL)
2621                 notify_destroy(new, ISC_TRUE);
2622 }
2623
2624 void
2625 dns_zone_notify(dns_zone_t *zone) {
2626         isc_time_t now;
2627
2628         REQUIRE(DNS_ZONE_VALID(zone));
2629
2630         LOCK_ZONE(zone);
2631         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
2632
2633         isc_time_now(&now);
2634         zone_settimer(zone, &now);
2635         UNLOCK_ZONE(zone);
2636 }
2637
2638 static void
2639 zone_notify(dns_zone_t *zone) {
2640         dns_dbnode_t *node = NULL;
2641         dns_dbversion_t *version = NULL;
2642         dns_name_t *origin = NULL;
2643         dns_name_t master;
2644         dns_rdata_ns_t ns;
2645         dns_rdata_soa_t soa;
2646         isc_uint32_t serial;
2647         dns_rdata_t rdata = DNS_RDATA_INIT;
2648         dns_rdataset_t nsrdset;
2649         dns_rdataset_t soardset;
2650         isc_result_t result;
2651         dns_notify_t *notify = NULL;
2652         unsigned int i;
2653         isc_sockaddr_t dst;
2654         isc_boolean_t isqueued;
2655         dns_notifytype_t notifytype;
2656         unsigned int flags = 0;
2657         isc_boolean_t loggednotify = ISC_FALSE;
2658
2659         REQUIRE(DNS_ZONE_VALID(zone));
2660
2661         LOCK_ZONE(zone);
2662         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
2663         notifytype = zone->notifytype;
2664         UNLOCK_ZONE(zone);
2665
2666         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2667                 return;
2668
2669         if (notifytype == dns_notifytype_no)
2670                 return;
2671
2672         origin = &zone->origin;
2673
2674         /*
2675          * If the zone is dialup we are done as we don't want to send
2676          * the current soa so as to force a refresh query.
2677          */
2678         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
2679                 flags |= DNS_NOTIFY_NOSOA;
2680
2681         /*
2682          * Get SOA RRset.
2683          */
2684         dns_db_currentversion(zone->db, &version);
2685         result = dns_db_findnode(zone->db, origin, ISC_FALSE, &node);
2686         if (result != ISC_R_SUCCESS)
2687                 goto cleanup1;
2688
2689         dns_rdataset_init(&soardset);
2690         result = dns_db_findrdataset(zone->db, node, version,
2691                                      dns_rdatatype_soa,
2692                                      dns_rdatatype_none, 0, &soardset, NULL);
2693         if (result != ISC_R_SUCCESS)
2694                 goto cleanup2;
2695
2696         /*
2697          * Find serial and master server's name.
2698          */
2699         dns_name_init(&master, NULL);
2700         result = dns_rdataset_first(&soardset);
2701         if (result != ISC_R_SUCCESS)
2702                 goto cleanup3;
2703         dns_rdataset_current(&soardset, &rdata);
2704         result = dns_rdata_tostruct(&rdata, &soa, NULL);
2705         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2706         dns_rdata_reset(&rdata);
2707         result = dns_name_dup(&soa.origin, zone->mctx, &master);
2708         serial = soa.serial;
2709         dns_rdataset_disassociate(&soardset);
2710         if (result != ISC_R_SUCCESS)
2711                 goto cleanup3;
2712
2713         /*
2714          * Enqueue notify requests for 'also-notify' servers.
2715          */
2716         LOCK_ZONE(zone);
2717         for (i = 0; i < zone->notifycnt; i++) {
2718                 dst = zone->notify[i];
2719                 if (notify_isqueued(zone, NULL, &dst))
2720                         continue;
2721                 result = notify_create(zone->mctx, flags, &notify);
2722                 if (result != ISC_R_SUCCESS)
2723                         continue;
2724                 zone_iattach(zone, &notify->zone);
2725                 notify->dst = dst;
2726                 ISC_LIST_APPEND(zone->notifies, notify, link);
2727                 result = notify_send_queue(notify);
2728                 if (result != ISC_R_SUCCESS)
2729                         notify_destroy(notify, ISC_TRUE);
2730                 if (!loggednotify) {
2731                         notify_log(zone, ISC_LOG_INFO,
2732                                    "sending notifies (serial %u)",
2733                                    serial);
2734                         loggednotify = ISC_TRUE;
2735                 }
2736                 notify = NULL;
2737         }
2738         UNLOCK_ZONE(zone);
2739
2740         if (notifytype == dns_notifytype_explicit)
2741                 goto cleanup3;
2742   
2743         /*
2744          * Process NS RRset to generate notifies.
2745          */
2746
2747         dns_rdataset_init(&nsrdset);
2748         result = dns_db_findrdataset(zone->db, node, version,
2749                                      dns_rdatatype_ns,
2750                                      dns_rdatatype_none, 0, &nsrdset, NULL);
2751         if (result != ISC_R_SUCCESS)
2752                 goto cleanup3;
2753
2754         result = dns_rdataset_first(&nsrdset);
2755         while (result == ISC_R_SUCCESS) {
2756                 dns_rdataset_current(&nsrdset, &rdata);
2757                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2758                 dns_rdata_reset(&rdata);
2759                 if (result != ISC_R_SUCCESS)
2760                         continue;
2761                 /*
2762                  * don't notify the master server.
2763                  */
2764                 if (dns_name_compare(&master, &ns.name) == 0) {
2765                         result = dns_rdataset_next(&nsrdset);
2766                         continue;
2767                 }
2768
2769                 if (!loggednotify) {
2770                         notify_log(zone, ISC_LOG_INFO,
2771                                    "sending notifies (serial %u)",
2772                                    serial);
2773                         loggednotify = ISC_TRUE;
2774                 }
2775
2776                 LOCK_ZONE(zone);
2777                 isqueued = notify_isqueued(zone, &ns.name, NULL);
2778                 UNLOCK_ZONE(zone);
2779                 if (isqueued) {
2780                         result = dns_rdataset_next(&nsrdset);
2781                         continue;
2782                 }
2783                 result = notify_create(zone->mctx, flags, &notify);
2784                 if (result != ISC_R_SUCCESS)
2785                         continue;
2786                 dns_zone_iattach(zone, &notify->zone);
2787                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
2788                 if (result != ISC_R_SUCCESS) {
2789                         LOCK_ZONE(zone);
2790                         notify_destroy(notify, ISC_TRUE);
2791                         UNLOCK_ZONE(zone);
2792                         continue;
2793                 }
2794                 LOCK_ZONE(zone);
2795                 ISC_LIST_APPEND(zone->notifies, notify, link);
2796                 UNLOCK_ZONE(zone);
2797                 notify_find_address(notify);
2798                 notify = NULL;
2799                 result = dns_rdataset_next(&nsrdset);
2800         }
2801         dns_rdataset_disassociate(&nsrdset);
2802
2803  cleanup3:
2804         if (dns_name_dynamic(&master))
2805                 dns_name_free(&master, zone->mctx);
2806  cleanup2:
2807         dns_db_detachnode(zone->db, &node);
2808  cleanup1:
2809         dns_db_closeversion(zone->db, &version, ISC_FALSE);
2810 }
2811
2812 /***
2813  *** Private
2814  ***/
2815
2816 static inline isc_result_t
2817 save_nsrrset(dns_message_t *message, dns_name_t *name,
2818              dns_db_t *db, dns_dbversion_t *version)
2819 {
2820         dns_rdataset_t *nsrdataset = NULL;
2821         dns_rdataset_t *rdataset = NULL;
2822         dns_dbnode_t *node = NULL;
2823         dns_rdata_ns_t ns;
2824         isc_result_t result;
2825         dns_rdata_t rdata = DNS_RDATA_INIT;
2826
2827         /*
2828          * Extract NS RRset from message.
2829          */
2830         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
2831                                       dns_rdatatype_ns, dns_rdatatype_none,
2832                                       NULL, &nsrdataset);
2833         if (result != ISC_R_SUCCESS)
2834                 goto fail;
2835
2836         /*
2837          * Add NS rdataset.
2838          */
2839         result = dns_db_findnode(db, name, ISC_TRUE, &node);
2840         if (result != ISC_R_SUCCESS)
2841                 goto fail;
2842         result = dns_db_addrdataset(db, node, version, 0,
2843                                     nsrdataset, 0, NULL);
2844         dns_db_detachnode(db, &node);
2845         if (result != ISC_R_SUCCESS)
2846                 goto fail;
2847         /*
2848          * Add glue rdatasets.
2849          */
2850         for (result = dns_rdataset_first(nsrdataset);
2851              result == ISC_R_SUCCESS;
2852              result = dns_rdataset_next(nsrdataset)) {
2853                 dns_rdataset_current(nsrdataset, &rdata);
2854                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2855                 dns_rdata_reset(&rdata);
2856                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2857                 if (!dns_name_issubdomain(&ns.name, name))
2858                         continue;
2859                 rdataset = NULL;
2860                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
2861                                               &ns.name, dns_rdatatype_a6,
2862                                               dns_rdatatype_none, NULL,
2863                                               &rdataset);
2864                 if (result == ISC_R_SUCCESS) {
2865                         result = dns_db_findnode(db, &ns.name,
2866                                                  ISC_TRUE, &node);
2867                         if (result != ISC_R_SUCCESS)
2868                                 goto fail;
2869                         result = dns_db_addrdataset(db, node, version, 0,
2870                                                     rdataset, 0, NULL);
2871                         dns_db_detachnode(db, &node);
2872                         if (result != ISC_R_SUCCESS)
2873                                 goto fail;
2874                 }
2875                 rdataset = NULL;
2876                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
2877                                               &ns.name, dns_rdatatype_aaaa,
2878                                               dns_rdatatype_none, NULL,
2879                                               &rdataset);
2880                 if (result == ISC_R_SUCCESS) {
2881                         result = dns_db_findnode(db, &ns.name,
2882                                                  ISC_TRUE, &node);
2883                         if (result != ISC_R_SUCCESS)
2884                                 goto fail;
2885                         result = dns_db_addrdataset(db, node, version, 0,
2886                                                     rdataset, 0, NULL);
2887                         dns_db_detachnode(db, &node);
2888                         if (result != ISC_R_SUCCESS)
2889                                 goto fail;
2890                 }
2891                 rdataset = NULL;
2892                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
2893                                               &ns.name, dns_rdatatype_a,
2894                                               dns_rdatatype_none, NULL,
2895                                               &rdataset);
2896                 if (result == ISC_R_SUCCESS) {
2897                         result = dns_db_findnode(db, &ns.name,
2898                                                  ISC_TRUE, &node);
2899                         if (result != ISC_R_SUCCESS)
2900                                 goto fail;
2901                         result = dns_db_addrdataset(db, node, version, 0,
2902                                                     rdataset, 0, NULL);
2903                         dns_db_detachnode(db, &node);
2904                         if (result != ISC_R_SUCCESS)
2905                                 goto fail;
2906                 }
2907         }
2908         if (result != ISC_R_NOMORE)
2909                 goto fail;
2910
2911         return (ISC_R_SUCCESS);
2912
2913 fail:
2914         return (result);
2915 }
2916
2917 static void
2918 stub_callback(isc_task_t *task, isc_event_t *event) {
2919         const char me[] = "stub_callback";
2920         dns_requestevent_t *revent = (dns_requestevent_t *)event;
2921         dns_stub_t *stub = NULL;
2922         dns_message_t *msg = NULL;
2923         dns_zone_t *zone = NULL;
2924         char master[ISC_SOCKADDR_FORMATSIZE];
2925         isc_uint32_t nscnt, cnamecnt;
2926         isc_result_t result;
2927         isc_time_t now;
2928         isc_boolean_t exiting = ISC_FALSE;
2929         isc_interval_t i;
2930
2931         stub = revent->ev_arg;
2932         INSIST(DNS_STUB_VALID(stub));
2933
2934         UNUSED(task);
2935
2936         zone = stub->zone;
2937
2938         ENTER;
2939
2940         isc_time_now(&now);
2941
2942         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
2943                 zone_debuglog(zone, me, 1, "exiting");
2944                 exiting = ISC_TRUE;
2945                 goto next_master;
2946         }
2947
2948         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
2949
2950         if (revent->result != ISC_R_SUCCESS) {
2951                 dns_zone_log(zone, ISC_LOG_INFO,
2952                              "could not refresh stub from master %s: %s",
2953                              master, dns_result_totext(revent->result));
2954                 goto next_master;
2955         }
2956
2957         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
2958         if (result != ISC_R_SUCCESS)
2959                 goto next_master;
2960
2961         result = dns_request_getresponse(revent->request, msg, 0);
2962         if (result != ISC_R_SUCCESS)
2963                 goto next_master;
2964
2965         /*
2966          * Unexpected rcode.
2967          */
2968         if (msg->rcode != dns_rcode_noerror) {
2969                 char rcode[128];
2970                 isc_buffer_t rb;
2971
2972                 isc_buffer_init(&rb, rcode, sizeof(rcode));
2973                 dns_rcode_totext(msg->rcode, &rb);
2974
2975                 dns_zone_log(zone, ISC_LOG_INFO,
2976                              "refreshing stub: "
2977                              "unexpected rcode (%.*s) from %s",
2978                              (int)rb.used, rcode, master);
2979                 goto next_master;
2980         }
2981
2982         /*
2983          * We need complete messages.
2984          */
2985         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
2986                 if (dns_request_usedtcp(revent->request)) {
2987                         dns_zone_log(zone, ISC_LOG_INFO,
2988                                      "refreshing stub: "
2989                                      "truncated TCP response from master %s",
2990                                  master);
2991                         goto next_master;
2992                 }
2993                 LOCK_ZONE(zone);
2994                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
2995                 UNLOCK_ZONE(zone);
2996                 goto same_master;
2997         }
2998
2999         /*
3000          * If non-auth log and next master.
3001          */
3002         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
3003                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
3004                              "non-authoritative answer from master %s",
3005                              master);
3006                 goto next_master;
3007         }
3008
3009         /*
3010          * Sanity checks.
3011          */
3012         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
3013         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
3014
3015         if (cnamecnt != 0) {
3016                 dns_zone_log(zone, ISC_LOG_INFO,
3017                              "refreshing stub: unexpected CNAME response "
3018                              "from master %s", master);
3019                 goto next_master;
3020         }
3021
3022         if (nscnt == 0) {
3023                 dns_zone_log(zone, ISC_LOG_INFO,
3024                              "refreshing stub: no NS records in response "
3025                              "from master %s", master);
3026                 goto next_master;
3027         }
3028
3029         /*
3030          * Save answer.
3031          */
3032         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
3033         if (result != ISC_R_SUCCESS) {
3034                 dns_zone_log(zone, ISC_LOG_INFO,
3035                              "refreshing stub: unable to save NS records "
3036                              "from master %s", master);
3037                 goto next_master;
3038         }
3039
3040         /*
3041          * Tidy up.
3042          */
3043         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
3044         LOCK_ZONE(zone);
3045         if (zone->db == NULL)
3046                 dns_db_attach(stub->db, &zone->db);
3047         UNLOCK_ZONE(zone);
3048         dns_db_detach(&stub->db);
3049
3050         if (zone->masterfile != NULL) {
3051                 dns_zone_dump(zone);
3052                 (void)isc_time_now(&zone->loadtime);
3053         }
3054
3055         dns_message_destroy(&msg);
3056         isc_event_free(&event);
3057         LOCK_ZONE(zone);
3058         dns_request_destroy(&zone->request);
3059         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3060         isc_interval_set(&i, isc_random_jitter(zone->refresh,
3061                          zone->refresh / 4), 0);
3062         isc_time_add(&now, &i, &zone->refreshtime);
3063         isc_interval_set(&i, zone->expire, 0);
3064         isc_time_add(&now, &i, &zone->expiretime);
3065         zone_settimer(zone, &now);
3066         UNLOCK_ZONE(zone);
3067         goto free_stub;
3068
3069  next_master:
3070         if (stub->version != NULL)
3071                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
3072         if (stub->db != NULL)
3073                 dns_db_detach(&stub->db);
3074         if (msg != NULL)
3075                 dns_message_destroy(&msg);
3076         isc_event_free(&event);
3077         LOCK_ZONE(zone);
3078         dns_request_destroy(&zone->request);
3079         zone->curmaster++;
3080         zone->refreshcnt = 0;
3081         if (exiting || zone->curmaster >= zone->masterscnt) {
3082                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3083
3084                 zone_settimer(zone, &now);
3085                 UNLOCK_ZONE(zone);
3086                 goto free_stub;
3087         }
3088         queue_soa_query(zone);
3089         UNLOCK_ZONE(zone);
3090         goto free_stub;
3091
3092  same_master:
3093         if (msg != NULL)
3094                 dns_message_destroy(&msg);
3095         isc_event_free(&event);
3096         LOCK_ZONE(zone);
3097         dns_request_destroy(&zone->request);
3098         UNLOCK_ZONE(zone);
3099         ns_query(zone, NULL, stub);
3100         goto done;
3101
3102  free_stub:
3103         stub->magic = 0;
3104         dns_zone_idetach(&stub->zone);
3105         INSIST(stub->db == NULL);
3106         INSIST(stub->version == NULL);
3107         isc_mem_put(stub->mctx, stub, sizeof(*stub));
3108
3109  done:
3110         INSIST(event == NULL);
3111         return;
3112 }
3113
3114 /*
3115  * An SOA query has finished (successfully or not).
3116  */
3117 static void
3118 refresh_callback(isc_task_t *task, isc_event_t *event) {
3119         const char me[] = "refresh_callback";
3120         dns_requestevent_t *revent = (dns_requestevent_t *)event;
3121         dns_zone_t *zone;
3122         dns_message_t *msg = NULL;
3123         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
3124         isc_time_t now;
3125         char master[ISC_SOCKADDR_FORMATSIZE];
3126         dns_rdataset_t *rdataset;
3127         dns_rdata_t rdata = DNS_RDATA_INIT;
3128         dns_rdata_soa_t soa;
3129         isc_result_t result;
3130         isc_uint32_t serial;
3131         isc_interval_t i;
3132
3133         zone = revent->ev_arg;
3134         INSIST(DNS_ZONE_VALID(zone));
3135
3136         UNUSED(task);
3137
3138         ENTER;
3139
3140         /*
3141          * if timeout log and next master;
3142          */
3143
3144         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
3145
3146         isc_time_now(&now);
3147
3148         if (revent->result != ISC_R_SUCCESS) {
3149                 dns_zone_log(zone, ISC_LOG_INFO,
3150                              "refresh: failure trying master %s: %s",
3151                              master, dns_result_totext(revent->result));
3152                 if (revent->result == ISC_R_TIMEDOUT &&
3153                     !dns_request_usedtcp(revent->request)) {
3154                         if (zone->refreshcnt < 3)
3155                                 goto same_master;
3156                         dns_zone_log(zone, ISC_LOG_INFO,
3157                                      "refresh: retry limit for "
3158                                      "master %s exceeded",
3159                                      master);
3160                 }
3161                 goto next_master;
3162         }
3163
3164         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3165         if (result != ISC_R_SUCCESS)
3166                 goto next_master;
3167         result = dns_request_getresponse(revent->request, msg, 0);
3168         if (result != ISC_R_SUCCESS) {
3169                 dns_zone_log(zone, ISC_LOG_INFO,
3170                              "refresh: failure trying master %s: %s",
3171                              master, dns_result_totext(result));
3172                 goto next_master;
3173         }
3174
3175         /*
3176          * Unexpected rcode.
3177          */
3178         if (msg->rcode != dns_rcode_noerror) {
3179                 char rcode[128];
3180                 isc_buffer_t rb;
3181
3182                 isc_buffer_init(&rb, rcode, sizeof(rcode));
3183                 dns_rcode_totext(msg->rcode, &rb);
3184
3185                 dns_zone_log(zone, ISC_LOG_INFO,
3186                              "refresh: unexpected rcode (%.*s) from master %s",
3187                              (int)rb.used, rcode, master);
3188                 goto next_master;
3189         }
3190
3191         /*
3192          * If truncated punt to zone transfer which will query again.
3193          */
3194         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
3195                 if (zone->type == dns_zone_slave) {
3196                         dns_zone_log(zone, ISC_LOG_INFO,
3197                                      "refresh: truncated UDP answer, "
3198                                      "initiating TCP zone xfer "
3199                                      "for master %s",
3200                                  master);
3201                         goto tcp_transfer;
3202                 } else {
3203                         INSIST(zone->type == dns_zone_stub);
3204                         if (dns_request_usedtcp(revent->request)) {
3205                                 dns_zone_log(zone, ISC_LOG_INFO,
3206                                              "refresh: truncated TCP response "
3207                                              "from master %s",
3208                                              master);
3209                                 goto next_master;
3210                         }
3211                         LOCK_ZONE(zone);
3212                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
3213                         UNLOCK_ZONE(zone);
3214                         goto same_master;
3215                 }
3216         }
3217
3218         /*
3219          * if non-auth log and next master;
3220          */
3221         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
3222                 dns_zone_log(zone, ISC_LOG_INFO,
3223                              "refresh: non-authoritative answer from "
3224                              "master %s", master);
3225                 goto next_master;
3226         }
3227
3228         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
3229         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
3230         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
3231         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
3232                                  dns_rdatatype_soa);
3233
3234         /*
3235          * There should not be a CNAME record at top of zone.
3236          */
3237         if (cnamecnt != 0) {
3238                 dns_zone_log(zone, ISC_LOG_INFO,
3239                              "refresh: CNAME at top of zone "
3240                              "in master %s", master);
3241                 goto next_master;
3242         }
3243
3244         /*
3245          * if referral log and next master;
3246          */
3247         if (soacnt == 0 && soacount == 0 && nscount != 0) {
3248                 dns_zone_log(zone, ISC_LOG_INFO,
3249                              "refresh: referral response "
3250                              "from master %s", master);
3251                 goto next_master;
3252         }
3253
3254         /*
3255          * if nodata log and next master;
3256          */
3257         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
3258                 dns_zone_log(zone, ISC_LOG_INFO,
3259                              "refresh: NODATA response "
3260                              "from master %s", master);
3261                 goto next_master;
3262         }
3263
3264         /*
3265          * Only one soa at top of zone.
3266          */
3267         if (soacnt != 1) {
3268                 dns_zone_log(zone, ISC_LOG_INFO,
3269                              "refresh: answer SOA count (%d) != 1 "
3270                              "from master %s",
3271                          soacnt, master);
3272                 goto next_master;
3273         }
3274         /*
3275          * Extract serial
3276          */
3277         rdataset = NULL;
3278         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
3279                                       dns_rdatatype_soa, dns_rdatatype_none,
3280                                       NULL, &rdataset);
3281         if (result != ISC_R_SUCCESS) {
3282                 dns_zone_log(zone, ISC_LOG_INFO,
3283                              "refresh: unable to get SOA record "
3284                              "from master %s", master);
3285                 goto next_master;
3286         }
3287
3288         result = dns_rdataset_first(rdataset);
3289         if (result != ISC_R_SUCCESS) {
3290                 dns_zone_log(zone, ISC_LOG_INFO,
3291                              "refresh: dns_rdataset_first() failed");
3292                 goto next_master;
3293         }
3294
3295         dns_rdataset_current(rdataset, &rdata);
3296         result = dns_rdata_tostruct(&rdata, &soa, NULL);
3297         if (result != ISC_R_SUCCESS) {
3298                 dns_zone_log(zone, ISC_LOG_INFO,
3299                              "refresh: dns_rdata_tostruct() failed");
3300                 goto next_master;
3301         }
3302
3303         serial = soa.serial;
3304
3305         zone_debuglog(zone, me, 1, "serial: new %u, old %u",
3306                       serial, zone->serial);
3307         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
3308             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
3309             isc_serial_gt(serial, zone->serial)) {
3310  tcp_transfer:
3311                 isc_event_free(&event);
3312                 LOCK_ZONE(zone);
3313                 dns_request_destroy(&zone->request);
3314                 UNLOCK_ZONE(zone);
3315                 if (zone->type == dns_zone_slave) {
3316                         queue_xfrin(zone);
3317                 } else {
3318                         INSIST(zone->type == dns_zone_stub);
3319                         ns_query(zone, rdataset, NULL);
3320                 }
3321                 if (msg != NULL)
3322                         dns_message_destroy(&msg);
3323         } else if (isc_serial_eq(soa.serial, zone->serial)) {
3324                 if (zone->masterfile != NULL) {
3325                         result = ISC_R_FAILURE;
3326                         if (zone->journal != NULL)
3327                                 result = isc_file_settime(zone->journal, &now);
3328                         if (result != ISC_R_SUCCESS)
3329                                 result = isc_file_settime(zone->masterfile,
3330                                                           &now);
3331                         if (result != ISC_R_SUCCESS)
3332                                 dns_zone_log(zone, ISC_LOG_ERROR,
3333                                              "refresh: could not set file "
3334                                              "modification time of '%s': %s",
3335                                              zone->masterfile,
3336                                              dns_result_totext(result));
3337                 }
3338                 isc_interval_set(&i, isc_random_jitter(zone->refresh,
3339                                          zone->refresh / 4), 0);
3340                 isc_time_add(&now, &i, &zone->refreshtime);
3341                 isc_interval_set(&i, zone->expire, 0);
3342                 isc_time_add(&now, &i, &zone->expiretime);
3343                 goto next_master;
3344         } else {
3345                 zone_debuglog(zone, me, 1, "ahead");
3346                 goto next_master;
3347         }
3348         if (msg != NULL)
3349                 dns_message_destroy(&msg);
3350         goto detach;
3351
3352  next_master:
3353         if (msg != NULL)
3354                 dns_message_destroy(&msg);
3355         isc_event_free(&event);
3356         LOCK_ZONE(zone);
3357         dns_request_destroy(&zone->request);
3358         zone->curmaster++;
3359         zone->refreshcnt = 0;
3360         if (zone->curmaster >= zone->masterscnt) {
3361                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3362                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
3363                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
3364                         zone->refreshtime = now;
3365                 }
3366                 zone_settimer(zone, &now);
3367                 UNLOCK_ZONE(zone);
3368                 goto detach;
3369         }
3370         queue_soa_query(zone);
3371         UNLOCK_ZONE(zone);
3372         goto detach;
3373
3374  same_master:
3375         zone->refreshcnt++;
3376         if (msg != NULL)
3377                 dns_message_destroy(&msg);
3378         isc_event_free(&event);
3379         LOCK_ZONE(zone);
3380         dns_request_destroy(&zone->request);
3381         queue_soa_query(zone);
3382         UNLOCK_ZONE(zone);
3383  detach:
3384         dns_zone_idetach(&zone);
3385         return;
3386 }
3387
3388 static void
3389 queue_soa_query(dns_zone_t *zone) {
3390         const char me[] = "queue_soa_query";
3391         isc_event_t *e;
3392         dns_zone_t *dummy = NULL;
3393         isc_result_t result;
3394
3395         ENTER;
3396         /*
3397          * Locked by caller
3398          */
3399         REQUIRE(LOCKED_ZONE(zone));
3400
3401         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
3402                 cancel_refresh(zone);
3403                 return;
3404         }
3405
3406         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
3407                                soa_query, zone, sizeof(isc_event_t));
3408         if (e == NULL) {
3409                 cancel_refresh(zone);
3410                 return;
3411         }
3412
3413         /*
3414          * Attach so that we won't clean up
3415          * until the event is delivered.
3416          */
3417         zone_iattach(zone, &dummy);
3418
3419         e->ev_arg = zone;
3420         e->ev_sender = NULL;
3421         result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
3422         if (result != ISC_R_SUCCESS) {
3423                 zone_idetach(&dummy);
3424                 isc_event_free(&e);
3425                 cancel_refresh(zone);
3426         }
3427 }
3428
3429 static inline isc_result_t
3430 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
3431              dns_message_t **messagep)
3432 {
3433         dns_message_t *message = NULL;
3434         dns_name_t *qname = NULL;
3435         dns_rdataset_t *qrdataset = NULL;
3436         isc_result_t result;
3437
3438         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
3439                                     &message);
3440         if (result != ISC_R_SUCCESS)
3441                 goto cleanup;
3442
3443         message->opcode = dns_opcode_query;
3444         message->rdclass = zone->rdclass;
3445
3446         result = dns_message_gettempname(message, &qname);
3447         if (result != ISC_R_SUCCESS)
3448                 goto cleanup;
3449
3450         result = dns_message_gettemprdataset(message, &qrdataset);
3451         if (result != ISC_R_SUCCESS)
3452                 goto cleanup;
3453
3454         /*
3455          * Make question.
3456          */
3457         dns_name_init(qname, NULL);
3458         dns_name_clone(&zone->origin, qname);
3459         dns_rdataset_init(qrdataset);
3460         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
3461         ISC_LIST_APPEND(qname->list, qrdataset, link);
3462         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
3463
3464         *messagep = message;
3465         return (ISC_R_SUCCESS);
3466
3467  cleanup:
3468         if (qname != NULL)
3469                 dns_message_puttempname(message, &qname);
3470         if (qrdataset != NULL)
3471                 dns_message_puttemprdataset(message, &qrdataset);
3472         if (message != NULL)
3473                 dns_message_destroy(&message);
3474         return (result);
3475 }
3476
3477 static void
3478 soa_query(isc_task_t *task, isc_event_t *event) {
3479         const char me[] = "soa_query";
3480         isc_result_t result;
3481         dns_message_t *message = NULL;
3482         dns_zone_t *zone = event->ev_arg;
3483         dns_zone_t *dummy = NULL;
3484         isc_netaddr_t masterip;
3485         dns_tsigkey_t *key = NULL;
3486         isc_uint32_t options;
3487         isc_sockaddr_t src;
3488         isc_boolean_t cancel = ISC_TRUE;
3489         int timeout;
3490
3491         REQUIRE(DNS_ZONE_VALID(zone));
3492
3493         UNUSED(task);
3494
3495         ENTER;
3496
3497         LOCK_ZONE(zone);
3498         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
3499             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
3500             zone->view->requestmgr == NULL) {
3501                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
3502                         cancel = ISC_FALSE;
3503                 goto cleanup;
3504         }
3505
3506         /*
3507          * XXX Optimisation: Create message when zone is setup and reuse.
3508          */
3509         result = create_query(zone, dns_rdatatype_soa, &message);
3510         if (result != ISC_R_SUCCESS)
3511                 goto cleanup;
3512
3513         INSIST(zone->masterscnt > 0);
3514         INSIST(zone->curmaster < zone->masterscnt);
3515         zone->masteraddr = zone->masters[zone->curmaster];
3516
3517         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
3518         /*
3519          * First, look for a tsig key in the master statement, then
3520          * try for a server key.
3521          */
3522         if ((zone->masterkeynames != NULL) &&
3523             (zone->masterkeynames[zone->curmaster] != NULL)) {
3524                 dns_view_t *view = dns_zone_getview(zone);
3525                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
3526                 result = dns_view_gettsig(view, keyname, &key);
3527                 if (result != ISC_R_SUCCESS) {
3528                         char namebuf[DNS_NAME_FORMATSIZE];
3529                         dns_name_format(keyname, namebuf, sizeof(namebuf));
3530                         dns_zone_log(zone, ISC_LOG_ERROR,
3531                                      "unable to find key: %s", namebuf);
3532                 }
3533         }
3534         if (key == NULL)
3535                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
3536
3537         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
3538                   DNS_REQUESTOPT_TCP : 0;
3539         switch (isc_sockaddr_pf(&zone->masteraddr)) {
3540         case PF_INET:
3541                 src = zone->xfrsource4;
3542                 break;
3543         case PF_INET6:
3544                 src = zone->xfrsource6;
3545                 break;
3546         default:
3547                 result = ISC_R_NOTIMPLEMENTED;
3548                 goto cleanup;
3549         }
3550         zone_iattach(zone, &dummy);
3551         timeout = 15;
3552         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
3553                 timeout = 30;
3554         result = dns_request_createvia(zone->view->requestmgr, message,
3555                                        &src, &zone->masteraddr, options, key,
3556                                        timeout, zone->task,
3557                                        refresh_callback, zone, &zone->request);
3558         if (result != ISC_R_SUCCESS) {
3559                 zone_idetach(&dummy);
3560                 zone_debuglog(zone, me, 1,
3561                               "dns_request_createvia() failed: %s",
3562                               dns_result_totext(result));
3563                 goto cleanup;
3564         }
3565         cancel = ISC_FALSE;
3566
3567  cleanup:
3568         if (key != NULL)
3569                 dns_tsigkey_detach(&key);
3570         if (message != NULL)
3571                 dns_message_destroy(&message);
3572         if (cancel)
3573                 cancel_refresh(zone);
3574         isc_event_free(&event);
3575         UNLOCK_ZONE(zone);
3576         dns_zone_idetach(&zone);
3577         return;
3578 }
3579
3580 static void
3581 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
3582         const char me[] = "ns_query";
3583         isc_result_t result;
3584         dns_message_t *message = NULL;
3585         isc_netaddr_t masterip;
3586         dns_tsigkey_t *key = NULL;
3587         dns_dbnode_t *node = NULL;
3588         isc_sockaddr_t src;
3589         int timeout;
3590
3591         REQUIRE(DNS_ZONE_VALID(zone));
3592         REQUIRE((soardataset != NULL && stub == NULL) ||
3593                 (soardataset == NULL && stub != NULL));
3594         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
3595
3596         ENTER;
3597
3598         LOCK_ZONE(zone);
3599         if (stub == NULL) {
3600                 stub = isc_mem_get(zone->mctx, sizeof *stub);
3601                 if (stub == NULL)
3602                         goto cleanup;
3603                 stub->magic = STUB_MAGIC;
3604                 stub->mctx = zone->mctx;
3605                 stub->zone = NULL;
3606                 stub->db = NULL;
3607                 stub->version = NULL;
3608
3609                 /*
3610                  * Attach so that the zone won't disappear from under us.
3611                  */
3612                 zone_iattach(zone, &stub->zone);
3613
3614                 /*
3615                  * If a db exists we will update it, otherwise we create a
3616                  * new one and attach it to the zone once we have the NS
3617                  * RRset and glue.
3618                  */
3619                 if (zone->db != NULL)
3620                         dns_db_attach(zone->db, &stub->db);
3621                 else {
3622                         INSIST(zone->db_argc >= 1);                     
3623                         result = dns_db_create(zone->mctx, zone->db_argv[0],
3624                                                &zone->origin, dns_dbtype_stub,
3625                                                zone->rdclass,
3626                                                zone->db_argc - 1,
3627                                                zone->db_argv + 1,
3628                                                &stub->db);
3629                         if (result != ISC_R_SUCCESS) {
3630                                 dns_zone_log(zone, ISC_LOG_ERROR,
3631                                              "refreshing stub: "
3632                                              "could not create "
3633                                              "database: %s", 
3634                                              dns_result_totext(result));
3635                                 goto cleanup;
3636                         }
3637                         dns_db_settask(stub->db, zone->task);
3638                 }
3639
3640                 dns_db_newversion(stub->db, &stub->version);
3641
3642                 /*
3643                  * Update SOA record.
3644                  */
3645                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
3646                                          &node);
3647                 if (result != ISC_R_SUCCESS) {
3648                         dns_zone_log(zone, ISC_LOG_INFO,
3649                                      "refreshing stub: "
3650                                      "dns_db_findnode() failed: %s",
3651                                      dns_result_totext(result));
3652                         goto cleanup;
3653                 }
3654
3655                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
3656                                             soardataset, 0, NULL);
3657                 dns_db_detachnode(stub->db, &node);
3658                 if (result != ISC_R_SUCCESS) {
3659                         dns_zone_log(zone, ISC_LOG_INFO,
3660                                      "refreshing stub: "
3661                                      "dns_db_addrdataset() failed: %s",
3662                                      dns_result_totext(result));
3663                         goto cleanup;
3664                 }
3665         }
3666
3667         /*
3668          * XXX Optimisation: Create message when zone is setup and reuse.
3669          */
3670         result = create_query(zone, dns_rdatatype_ns, &message);
3671
3672         INSIST(zone->masterscnt > 0);
3673         INSIST(zone->curmaster < zone->masterscnt);
3674         zone->masteraddr = zone->masters[zone->curmaster];
3675
3676         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
3677         /*
3678          * First, look for a tsig key in the master statement, then
3679          * try for a server key.
3680          */
3681         if ((zone->masterkeynames != NULL) &&
3682             (zone->masterkeynames[zone->curmaster] != NULL)) {
3683                 dns_view_t *view = dns_zone_getview(zone);
3684                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
3685                 result = dns_view_gettsig(view, keyname, &key);
3686                 if (result != ISC_R_SUCCESS) {
3687                         char namebuf[DNS_NAME_FORMATSIZE];
3688                         dns_name_format(keyname, namebuf, sizeof(namebuf));
3689                         dns_zone_log(zone, ISC_LOG_ERROR,
3690                                      "unable to find key: %s", namebuf);
3691                 }
3692         }
3693         if (key == NULL)
3694                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);        
3695
3696         /*
3697          * Always use TCP so that we shouldn't truncate in additional section.
3698          */
3699         switch (isc_sockaddr_pf(&zone->masteraddr)) {
3700         case PF_INET:
3701                 src = zone->xfrsource4;
3702                 break;
3703         case PF_INET6:
3704                 src = zone->xfrsource6;
3705                 break;
3706         default:
3707                 result = ISC_R_NOTIMPLEMENTED;
3708                 goto cleanup;
3709         }
3710         timeout = 15;
3711         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
3712                 timeout = 30;
3713         result = dns_request_createvia(zone->view->requestmgr, message,
3714                                        &src, &zone->masteraddr,
3715                                        DNS_REQUESTOPT_TCP, key, timeout,
3716                                        zone->task, stub_callback, stub,
3717                                        &zone->request);
3718         if (result != ISC_R_SUCCESS) {
3719                 zone_debuglog(zone, me, 1,
3720                               "dns_request_createvia() failed: %s",
3721                               dns_result_totext(result));
3722                 goto cleanup;
3723         }
3724         dns_message_destroy(&message);
3725         goto unlock;
3726
3727  cleanup:
3728         cancel_refresh(zone);
3729         if (stub != NULL) {
3730                 stub->magic = 0;
3731                 if (stub->version != NULL)
3732                         dns_db_closeversion(stub->db, &stub->version,
3733                                             ISC_FALSE);
3734                 if (stub->db != NULL)
3735                         dns_db_detach(&stub->db);
3736                 if (stub->zone != NULL)
3737                         zone_idetach(&stub->zone);
3738                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
3739         }
3740         if (message != NULL)
3741                 dns_message_destroy(&message);
3742   unlock:
3743         if (key != NULL)
3744                 dns_tsigkey_detach(&key);
3745         UNLOCK_ZONE(zone);
3746         return;
3747 }
3748
3749 /*
3750  * Handle the control event.  Note that although this event causes the zone
3751  * to shut down, it is not a shutdown event in the sense of the task library.
3752  */
3753 static void
3754 zone_shutdown(isc_task_t *task, isc_event_t *event) {
3755         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
3756         isc_boolean_t free_needed, linked = ISC_FALSE;
3757
3758         UNUSED(task);
3759         REQUIRE(DNS_ZONE_VALID(zone));
3760         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
3761         INSIST(isc_refcount_current(&zone->erefs) == 0);
3762         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
3763
3764         /*
3765          * Stop things being restarted after we cancel them below.
3766          */
3767         LOCK_ZONE(zone);
3768         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
3769         UNLOCK_ZONE(zone);
3770
3771         /*
3772          * If we were waiting for xfrin quota, step out of
3773          * the queue.
3774          * If there's no zone manager, we can't be waiting for the
3775          * xfrin quota
3776          */
3777         if (zone->zmgr != NULL) {
3778                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
3779                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
3780                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
3781                                         statelink);
3782                         linked = ISC_TRUE;
3783                         zone->statelist = NULL;
3784                 }
3785                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
3786         }
3787
3788         /*
3789          * In task context, no locking required.  See zone_xfrdone().
3790          */
3791         if (zone->xfr != NULL)
3792                 dns_xfrin_shutdown(zone->xfr);
3793
3794         LOCK_ZONE(zone);
3795         if (linked) {
3796                 INSIST(zone->irefs > 0);
3797                 zone->irefs--;
3798         }
3799         if (zone->request != NULL) {
3800                 dns_request_cancel(zone->request);
3801         }
3802
3803         if (zone->readio != NULL)
3804                 zonemgr_cancelio(zone->readio);
3805
3806         if (zone->lctx != NULL)
3807                 dns_loadctx_cancel(zone->lctx);
3808
3809         notify_cancel(zone);
3810
3811         if (zone->timer != NULL) {
3812                 isc_timer_detach(&zone->timer);
3813                 INSIST(zone->irefs > 0);
3814                 zone->irefs--;
3815         }
3816
3817         if (zone->view != NULL)
3818                 dns_view_weakdetach(&zone->view);
3819
3820         /*
3821          * We have now canceled everything set the flag to allow exit_check()
3822          * to succeed.  We must not unlock between setting this flag and
3823          * calling exit_check().
3824          */
3825         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
3826         free_needed = exit_check(zone);
3827         UNLOCK_ZONE(zone);
3828         if (free_needed)
3829                 zone_free(zone);
3830 }
3831
3832 static void
3833 zone_timer(isc_task_t *task, isc_event_t *event) {
3834         const char me[] = "zone_timer";
3835         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
3836
3837         UNUSED(task);
3838         REQUIRE(DNS_ZONE_VALID(zone));
3839
3840         ENTER;
3841
3842         zone_maintenance(zone);
3843
3844         isc_event_free(&event);
3845 }
3846
3847 static void
3848 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
3849         const char me[] = "zone_settimer";
3850         isc_time_t next;
3851         isc_result_t result;
3852
3853         REQUIRE(DNS_ZONE_VALID(zone));
3854         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
3855                 return;
3856
3857         isc_time_settoepoch(&next);
3858
3859         switch (zone->type) {
3860         case dns_zone_master:
3861                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
3862                         next = *now;
3863                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
3864                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
3865                         INSIST(!isc_time_isepoch(&zone->dumptime));
3866                         if (isc_time_isepoch(&next) ||
3867                             isc_time_compare(&zone->dumptime, &next) < 0)
3868                                 next = zone->dumptime;
3869                 }
3870                 break;
3871
3872         case dns_zone_slave:
3873                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
3874                         next = *now;
3875                 /*FALLTHROUGH*/
3876
3877         case dns_zone_stub:
3878                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
3879                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
3880                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
3881                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
3882                         INSIST(!isc_time_isepoch(&zone->refreshtime));
3883                         if (isc_time_isepoch(&next) ||
3884                             isc_time_compare(&zone->refreshtime, &next) < 0)
3885                                 next = zone->refreshtime;
3886                 }
3887                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3888                         INSIST(!isc_time_isepoch(&zone->expiretime));
3889                         if (isc_time_isepoch(&next) ||
3890                             isc_time_compare(&zone->expiretime, &next) < 0)
3891                                 next = zone->expiretime;
3892                 }
3893                 break;
3894
3895         default:
3896                 break;
3897         }
3898
3899         if (isc_time_isepoch(&next)) {
3900                 zone_debuglog(zone, me, 10, "settimer inactive");
3901                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
3902                                           NULL, NULL, ISC_TRUE);
3903                 if (result != ISC_R_SUCCESS)
3904                         dns_zone_log(zone, ISC_LOG_ERROR,
3905                                      "could not deactivate zone timer: %s",
3906                                      isc_result_totext(result));
3907         } else {
3908                 if (isc_time_compare(&next, now) <= 0)
3909                         next = *now;
3910                 result = isc_timer_reset(zone->timer, isc_timertype_once,
3911                                          &next, NULL, ISC_TRUE);
3912                 if (result != ISC_R_SUCCESS)
3913                         dns_zone_log(zone, ISC_LOG_ERROR,
3914                                      "could not reset zone timer: %s",
3915                                      isc_result_totext(result));
3916         }
3917 }
3918
3919 static void
3920 cancel_refresh(dns_zone_t *zone) {
3921         const char me[] = "cancel_refresh";
3922         isc_time_t now;
3923
3924         /*
3925          * 'zone' locked by caller.
3926          */
3927
3928         REQUIRE(DNS_ZONE_VALID(zone));
3929         REQUIRE(LOCKED_ZONE(zone));
3930
3931         ENTER;
3932
3933         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
3934         isc_time_now(&now);
3935         zone_settimer(zone, &now);
3936 }
3937
3938 static isc_result_t
3939 notify_createmessage(dns_zone_t *zone, unsigned int flags,
3940                      dns_message_t **messagep)
3941 {
3942         dns_dbnode_t *node = NULL;
3943         dns_dbversion_t *version = NULL;
3944         dns_message_t *message = NULL;
3945         dns_rdataset_t rdataset;
3946         dns_rdata_t rdata = DNS_RDATA_INIT;
3947
3948         dns_name_t *tempname = NULL;
3949         dns_rdata_t *temprdata = NULL;
3950         dns_rdatalist_t *temprdatalist = NULL;
3951         dns_rdataset_t *temprdataset = NULL;
3952
3953         isc_result_t result;
3954         isc_region_t r;
3955         isc_buffer_t *b = NULL;
3956
3957         REQUIRE(DNS_ZONE_VALID(zone));
3958         REQUIRE(messagep != NULL && *messagep == NULL);
3959
3960         message = NULL;
3961         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
3962                                     &message);
3963         if (result != ISC_R_SUCCESS)
3964                 return (result);
3965
3966         message->opcode = dns_opcode_notify;
3967         message->flags |= DNS_MESSAGEFLAG_AA;
3968         message->rdclass = zone->rdclass;
3969
3970         result = dns_message_gettempname(message, &tempname);
3971         if (result != ISC_R_SUCCESS)
3972                 goto cleanup;
3973
3974         result = dns_message_gettemprdataset(message, &temprdataset);
3975         if (result != ISC_R_SUCCESS)
3976                 goto cleanup;
3977
3978         /*
3979          * Make question.
3980          */
3981         dns_name_init(tempname, NULL);
3982         dns_name_clone(&zone->origin, tempname);
3983         dns_rdataset_init(temprdataset);
3984         dns_rdataset_makequestion(temprdataset, zone->rdclass,
3985                                   dns_rdatatype_soa);
3986         ISC_LIST_APPEND(tempname->list, temprdataset, link);
3987         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
3988         tempname = NULL;
3989         temprdataset = NULL;
3990
3991         if ((flags & DNS_NOTIFY_NOSOA) != 0)
3992                 goto done;
3993
3994         result = dns_message_gettempname(message, &tempname);
3995         if (result != ISC_R_SUCCESS)
3996                 goto soa_cleanup;
3997         result = dns_message_gettemprdata(message, &temprdata);
3998         if (result != ISC_R_SUCCESS)
3999                 goto soa_cleanup;
4000         result = dns_message_gettemprdataset(message, &temprdataset);
4001         if (result != ISC_R_SUCCESS)
4002                 goto soa_cleanup;
4003         result = dns_message_gettemprdatalist(message, &temprdatalist);
4004         if (result != ISC_R_SUCCESS)
4005                 goto soa_cleanup;
4006
4007         dns_name_init(tempname, NULL);
4008         dns_name_clone(&zone->origin, tempname);
4009         dns_db_currentversion(zone->db, &version);
4010         result = dns_db_findnode(zone->db, tempname, ISC_FALSE, &node);
4011         if (result != ISC_R_SUCCESS)
4012                 goto soa_cleanup;
4013
4014         dns_rdataset_init(&rdataset);
4015         result = dns_db_findrdataset(zone->db, node, version,
4016                                      dns_rdatatype_soa,
4017                                      dns_rdatatype_none, 0, &rdataset,
4018                                      NULL);
4019         if (result != ISC_R_SUCCESS)
4020                 goto soa_cleanup;
4021         result = dns_rdataset_first(&rdataset);
4022         if (result != ISC_R_SUCCESS)
4023                 goto soa_cleanup;
4024         dns_rdataset_current(&rdataset, &rdata);
4025         dns_rdata_toregion(&rdata, &r);
4026         result = isc_buffer_allocate(zone->mctx, &b, r.length);
4027         if (result != ISC_R_SUCCESS)
4028                 goto soa_cleanup;
4029         isc_buffer_putmem(b, r.base, r.length);
4030         isc_buffer_usedregion(b, &r);
4031         dns_rdata_init(temprdata);
4032         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
4033         dns_message_takebuffer(message, &b);
4034         result = dns_rdataset_next(&rdataset);
4035         dns_rdataset_disassociate(&rdataset);
4036         if (result != ISC_R_NOMORE)
4037                 goto soa_cleanup;
4038         temprdatalist->rdclass = rdata.rdclass;
4039         temprdatalist->type = rdata.type;
4040         temprdatalist->covers = 0;
4041         temprdatalist->ttl = rdataset.ttl;
4042         ISC_LIST_INIT(temprdatalist->rdata);
4043         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
4044
4045         dns_rdataset_init(temprdataset);
4046         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
4047         if (result != ISC_R_SUCCESS)
4048                 goto soa_cleanup;
4049
4050         ISC_LIST_APPEND(tempname->list, temprdataset, link);
4051         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
4052         temprdatalist = NULL;
4053         temprdataset = NULL;
4054         temprdata = NULL;
4055         tempname = NULL;
4056
4057  soa_cleanup:
4058         if (node != NULL)
4059                 dns_db_detachnode(zone->db, &node);
4060         if (version != NULL)
4061                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
4062         if (tempname != NULL)
4063                 dns_message_puttempname(message, &tempname);
4064         if (temprdata != NULL)
4065                 dns_message_puttemprdata(message, &temprdata);
4066         if (temprdataset != NULL)
4067                 dns_message_puttemprdataset(message, &temprdataset);
4068         if (temprdatalist != NULL)
4069                 dns_message_puttemprdatalist(message, &temprdatalist);
4070
4071  done:
4072         *messagep = message;
4073         return (ISC_R_SUCCESS);
4074
4075  cleanup:
4076         if (tempname != NULL)
4077                 dns_message_puttempname(message, &tempname);
4078         if (temprdataset != NULL)
4079                 dns_message_puttemprdataset(message, &temprdataset);
4080         if (message != NULL)
4081                 dns_message_destroy(&message);
4082         return (result);
4083 }
4084
4085 isc_result_t
4086 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
4087                        dns_message_t *msg)
4088 {
4089         unsigned int i;
4090         dns_rdata_soa_t soa;
4091         dns_rdataset_t *rdataset = NULL;
4092         dns_rdata_t rdata = DNS_RDATA_INIT;
4093         isc_result_t result;
4094         char fromtext[ISC_SOCKADDR_FORMATSIZE];
4095         int match = 0;
4096         isc_netaddr_t netaddr;
4097
4098         REQUIRE(DNS_ZONE_VALID(zone));
4099
4100         /*
4101          * If type != T_SOA return DNS_R_REFUSED.  We don't yet support
4102          * ROLLOVER.
4103          *
4104          * SOA: RFC 1996
4105          * Check that 'from' is a valid notify source, (zone->masters).
4106          *      Return DNS_R_REFUSED if not.
4107          *
4108          * If the notify message contains a serial number check it
4109          * against the zones serial and return if <= current serial
4110          *
4111          * If a refresh check is progress, if so just record the
4112          * fact we received a NOTIFY and from where and return.
4113          * We will perform a new refresh check when the current one
4114          * completes. Return ISC_R_SUCCESS.
4115          *
4116          * Otherwise initiate a refresh check using 'from' as the
4117          * first address to check.  Return ISC_R_SUCCESS.
4118          */
4119
4120         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
4121
4122         /*
4123          *  We only handle NOTIFY (SOA) at the present.
4124          */
4125         LOCK_ZONE(zone);
4126         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
4127             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
4128                                  dns_rdatatype_soa, dns_rdatatype_none,
4129                                  NULL, NULL) != ISC_R_SUCCESS) {
4130                 UNLOCK_ZONE(zone);
4131                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
4132                         dns_zone_log(zone, ISC_LOG_NOTICE,
4133                                      "NOTIFY with no "
4134                                      "question section from: %s", fromtext);
4135                         return (DNS_R_FORMERR);
4136                 }
4137                 dns_zone_log(zone, ISC_LOG_NOTICE,
4138                              "NOTIFY zone does not match");
4139                 return (DNS_R_NOTIMP);
4140         }
4141
4142         /*
4143          * If we are a master zone just succeed.
4144          */
4145         if (zone->type == dns_zone_master) {
4146                 UNLOCK_ZONE(zone);
4147                 return (ISC_R_SUCCESS);
4148         }
4149
4150         isc_netaddr_fromsockaddr(&netaddr, from);
4151         for (i = 0; i < zone->masterscnt; i++) {
4152                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
4153                         break;
4154                 if (zone->view->aclenv.match_mapped &&
4155                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
4156                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
4157                         isc_netaddr_t na1, na2;
4158                         isc_netaddr_fromv4mapped(&na1, &netaddr);
4159                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
4160                         if (isc_netaddr_equal(&na1, &na2))
4161                                 break;
4162                 }
4163         }
4164
4165         /*
4166          * Accept notify requests from non masters if they are on
4167          * 'zone->notify_acl'.
4168          */
4169         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
4170             dns_acl_match(&netaddr, NULL, zone->notify_acl,
4171                           &zone->view->aclenv,
4172                           &match, NULL) == ISC_R_SUCCESS &&
4173             match > 0)
4174         {
4175                 /* Accept notify. */
4176         } else if (i >= zone->masterscnt) {
4177                 UNLOCK_ZONE(zone);
4178                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
4179                              "refused notify from non-master: %s", fromtext);
4180                 return (DNS_R_REFUSED);
4181         }
4182
4183         /*
4184          * If the zone is loaded and there are answers check the serial
4185          * to see if we need to do a refresh.  Do not worry about this
4186          * check if we are a dialup zone as we use the notify request
4187          * to trigger a refresh check.
4188          */
4189         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
4190             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
4191             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
4192                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
4193                                               &zone->origin,
4194                                               dns_rdatatype_soa,
4195                                               dns_rdatatype_none, NULL,
4196                                               &rdataset);
4197                 if (result == ISC_R_SUCCESS)
4198                         result = dns_rdataset_first(rdataset);
4199                 if (result == ISC_R_SUCCESS) {
4200                         isc_uint32_t serial = 0;
4201
4202                         dns_rdataset_current(rdataset, &rdata);
4203                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
4204                         if (result == ISC_R_SUCCESS) {
4205                                 serial = soa.serial;
4206                                 if (isc_serial_le(serial, zone->serial)) {
4207                                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
4208                                                      "notify from %s: "
4209                                                      "zone is up to date",
4210                                                      fromtext);
4211                                         UNLOCK_ZONE(zone);
4212                                         return (ISC_R_SUCCESS);
4213                                 }
4214                         }
4215                 }
4216         }
4217
4218         /*
4219          * If we got this far and there was a refresh in progress just
4220          * let it complete.  Record where we got the notify from so we
4221          * can perform a refresh check when the current one completes
4222          */
4223         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
4224                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
4225                 zone->notifyfrom = *from;
4226                 UNLOCK_ZONE(zone);
4227                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
4228                              "notify from %s: refresh in progress, "
4229                              "refresh check queued",
4230                              fromtext);
4231                 return (ISC_R_SUCCESS);
4232         }
4233         zone->notifyfrom = *from;
4234         UNLOCK_ZONE(zone);
4235         dns_zone_refresh(zone);
4236         return (ISC_R_SUCCESS);
4237 }
4238
4239 void
4240 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
4241
4242         REQUIRE(DNS_ZONE_VALID(zone));
4243
4244         LOCK_ZONE(zone);
4245         if (zone->notify_acl != NULL)
4246                 dns_acl_detach(&zone->notify_acl);
4247         dns_acl_attach(acl, &zone->notify_acl);
4248         UNLOCK_ZONE(zone);
4249 }
4250
4251 void
4252 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
4253
4254         REQUIRE(DNS_ZONE_VALID(zone));
4255
4256         LOCK_ZONE(zone);
4257         if (zone->query_acl != NULL)
4258                 dns_acl_detach(&zone->query_acl);
4259         dns_acl_attach(acl, &zone->query_acl);
4260         UNLOCK_ZONE(zone);
4261 }
4262
4263 void
4264 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
4265
4266         REQUIRE(DNS_ZONE_VALID(zone));
4267
4268         LOCK_ZONE(zone);
4269         if (zone->update_acl != NULL)
4270                 dns_acl_detach(&zone->update_acl);
4271         dns_acl_attach(acl, &zone->update_acl);
4272         UNLOCK_ZONE(zone);
4273 }
4274
4275 void
4276 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
4277
4278         REQUIRE(DNS_ZONE_VALID(zone));
4279
4280         LOCK_ZONE(zone);
4281         if (zone->forward_acl != NULL)
4282                 dns_acl_detach(&zone->forward_acl);
4283         dns_acl_attach(acl, &zone->forward_acl);
4284         UNLOCK_ZONE(zone);
4285 }
4286
4287 void
4288 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
4289
4290         REQUIRE(DNS_ZONE_VALID(zone));
4291
4292         LOCK_ZONE(zone);
4293         if (zone->xfr_acl != NULL)
4294                 dns_acl_detach(&zone->xfr_acl);
4295         dns_acl_attach(acl, &zone->xfr_acl);
4296         UNLOCK_ZONE(zone);
4297 }
4298
4299 dns_acl_t *
4300 dns_zone_getnotifyacl(dns_zone_t *zone) {
4301
4302         REQUIRE(DNS_ZONE_VALID(zone));
4303
4304         return (zone->notify_acl);
4305 }
4306
4307 dns_acl_t *
4308 dns_zone_getqueryacl(dns_zone_t *zone) {
4309
4310         REQUIRE(DNS_ZONE_VALID(zone));
4311
4312         return (zone->query_acl);
4313 }
4314
4315 dns_acl_t *
4316 dns_zone_getupdateacl(dns_zone_t *zone) {
4317
4318         REQUIRE(DNS_ZONE_VALID(zone));
4319
4320         return (zone->update_acl);
4321 }
4322
4323 dns_acl_t *
4324 dns_zone_getforwardacl(dns_zone_t *zone) {
4325
4326         REQUIRE(DNS_ZONE_VALID(zone));
4327
4328         return (zone->forward_acl);
4329 }
4330
4331 dns_acl_t *
4332 dns_zone_getxfracl(dns_zone_t *zone) {
4333
4334         REQUIRE(DNS_ZONE_VALID(zone));
4335
4336         return (zone->xfr_acl);
4337 }
4338
4339 void
4340 dns_zone_clearupdateacl(dns_zone_t *zone) {
4341
4342         REQUIRE(DNS_ZONE_VALID(zone));
4343
4344         LOCK_ZONE(zone);
4345         if (zone->update_acl != NULL)
4346                 dns_acl_detach(&zone->update_acl);
4347         UNLOCK_ZONE(zone);
4348 }
4349
4350 void
4351 dns_zone_clearforwardacl(dns_zone_t *zone) {
4352
4353         REQUIRE(DNS_ZONE_VALID(zone));
4354
4355         LOCK_ZONE(zone);
4356         if (zone->forward_acl != NULL)
4357                 dns_acl_detach(&zone->forward_acl);
4358         UNLOCK_ZONE(zone);
4359 }
4360
4361 void
4362 dns_zone_clearnotifyacl(dns_zone_t *zone) {
4363
4364         REQUIRE(DNS_ZONE_VALID(zone));
4365
4366         LOCK_ZONE(zone);
4367         if (zone->notify_acl != NULL)
4368                 dns_acl_detach(&zone->notify_acl);
4369         UNLOCK_ZONE(zone);
4370 }
4371
4372 void
4373 dns_zone_clearqueryacl(dns_zone_t *zone) {
4374
4375         REQUIRE(DNS_ZONE_VALID(zone));
4376
4377         LOCK_ZONE(zone);
4378         if (zone->query_acl != NULL)
4379                 dns_acl_detach(&zone->query_acl);
4380         UNLOCK_ZONE(zone);
4381 }
4382
4383 void
4384 dns_zone_clearxfracl(dns_zone_t *zone) {
4385
4386         REQUIRE(DNS_ZONE_VALID(zone));
4387
4388         LOCK_ZONE(zone);
4389         if (zone->xfr_acl != NULL)
4390                 dns_acl_detach(&zone->xfr_acl);
4391         UNLOCK_ZONE(zone);
4392 }
4393
4394 void
4395 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
4396
4397         REQUIRE(DNS_ZONE_VALID(zone));
4398
4399         zone->check_names = severity;
4400 }
4401
4402 dns_severity_t
4403 dns_zone_getchecknames(dns_zone_t *zone) {
4404
4405         REQUIRE(DNS_ZONE_VALID(zone));
4406
4407         return (zone->check_names);
4408 }
4409
4410 void
4411 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
4412
4413         REQUIRE(DNS_ZONE_VALID(zone));
4414
4415         zone->journalsize = size;
4416 }
4417
4418 isc_int32_t
4419 dns_zone_getjournalsize(dns_zone_t *zone) {
4420
4421         REQUIRE(DNS_ZONE_VALID(zone));
4422
4423         return (zone->journalsize);
4424 }
4425
4426 static void
4427 zone_tostr(dns_zone_t *zone, char *buf, size_t length) {
4428         isc_result_t result = ISC_R_FAILURE;
4429         isc_buffer_t buffer;
4430
4431         REQUIRE(buf != NULL);
4432         REQUIRE(length > 1U);
4433
4434         /*
4435          * Leave space for terminating '\0'.
4436          */
4437         isc_buffer_init(&buffer, buf, length - 1);
4438         if (dns_name_dynamic(&zone->origin))
4439                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
4440         if (result != ISC_R_SUCCESS)
4441                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
4442
4443         isc_buffer_putstr(&buffer, "/");
4444         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
4445         buf[isc_buffer_usedlength(&buffer)] = '\0';
4446 }
4447
4448 static void
4449 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
4450         va_list ap;
4451         char message[4096];
4452         char namebuf[1024+32];
4453
4454         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
4455                 return;
4456
4457         zone_tostr(zone, namebuf, sizeof(namebuf));
4458
4459         va_start(ap, fmt);
4460         vsnprintf(message, sizeof message, fmt, ap);
4461         va_end(ap);
4462         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
4463                       level, "zone %s: %s", namebuf, message);
4464 }
4465
4466 void
4467 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
4468         va_list ap;
4469         char message[4096];
4470         char namebuf[1024+32];
4471
4472         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
4473                 return;
4474
4475         zone_tostr(zone, namebuf, sizeof(namebuf));
4476
4477         va_start(ap, fmt);
4478         vsnprintf(message, sizeof message, fmt, ap);
4479         va_end(ap);
4480         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
4481                       level, "zone %s: %s", namebuf, message);
4482 }
4483
4484 static void
4485 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
4486               const char *fmt, ...)
4487 {
4488         va_list ap;
4489         char message[4096];
4490         char namebuf[1024+32];
4491         int level = ISC_LOG_DEBUG(debuglevel);
4492
4493         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
4494                 return;
4495
4496         zone_tostr(zone, namebuf, sizeof(namebuf));
4497
4498         va_start(ap, fmt);
4499         vsnprintf(message, sizeof message, fmt, ap);
4500         va_end(ap);
4501         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
4502                       level, "%s: zone %s: %s", me, namebuf, message);
4503 }
4504
4505 static int
4506 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
4507 {
4508         isc_result_t result;
4509         dns_name_t *name;
4510         dns_rdataset_t *curr;
4511         int count = 0;
4512
4513         result = dns_message_firstname(msg, section);
4514         while (result == ISC_R_SUCCESS) {
4515                 name = NULL;
4516                 dns_message_currentname(msg, section, &name);
4517
4518                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
4519                      curr = ISC_LIST_PREV(curr, link)) {
4520                         if (curr->type == type)
4521                                 count++;
4522                 }
4523                 result = dns_message_nextname(msg, section);
4524         }
4525
4526         return (count);
4527 }
4528
4529 void
4530 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
4531         REQUIRE(DNS_ZONE_VALID(zone));
4532
4533         zone->maxxfrin = maxxfrin;
4534 }
4535
4536 isc_uint32_t
4537 dns_zone_getmaxxfrin(dns_zone_t *zone) {
4538         REQUIRE(DNS_ZONE_VALID(zone));
4539
4540         return (zone->maxxfrin);
4541 }
4542
4543 void
4544 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
4545         REQUIRE(DNS_ZONE_VALID(zone));
4546         zone->maxxfrout = maxxfrout;
4547 }
4548
4549 isc_uint32_t
4550 dns_zone_getmaxxfrout(dns_zone_t *zone) {
4551         REQUIRE(DNS_ZONE_VALID(zone));
4552
4553         return (zone->maxxfrout);
4554 }
4555
4556 dns_zonetype_t dns_zone_gettype(dns_zone_t *zone) {
4557         REQUIRE(DNS_ZONE_VALID(zone));
4558
4559         return (zone->type);
4560 }
4561
4562 dns_name_t *
4563 dns_zone_getorigin(dns_zone_t *zone) {
4564         REQUIRE(DNS_ZONE_VALID(zone));
4565
4566         return (&zone->origin);
4567 }
4568
4569 void
4570 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
4571         REQUIRE(DNS_ZONE_VALID(zone));
4572
4573         LOCK_ZONE(zone);
4574         if (zone->task != NULL)
4575                 isc_task_detach(&zone->task);
4576         isc_task_attach(task, &zone->task);
4577         if (zone->db != NULL)
4578                 dns_db_settask(zone->db, zone->task);
4579         UNLOCK_ZONE(zone);
4580 }
4581
4582 void
4583 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
4584         REQUIRE(DNS_ZONE_VALID(zone));
4585         isc_task_attach(zone->task, target);
4586 }
4587
4588 void
4589 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
4590         REQUIRE(DNS_ZONE_VALID(zone));
4591
4592         if (idlein == 0)
4593                 idlein = DNS_DEFAULT_IDLEIN;
4594         zone->idlein = idlein;
4595 }
4596
4597 isc_uint32_t
4598 dns_zone_getidlein(dns_zone_t *zone) {
4599         REQUIRE(DNS_ZONE_VALID(zone));
4600
4601         return (zone->idlein);
4602 }
4603
4604 void
4605 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
4606         REQUIRE(DNS_ZONE_VALID(zone));
4607
4608         zone->idleout = idleout;
4609 }
4610
4611 isc_uint32_t
4612 dns_zone_getidleout(dns_zone_t *zone) {
4613         REQUIRE(DNS_ZONE_VALID(zone));
4614
4615         return (zone->idleout);
4616 }
4617
4618 static void
4619 notify_done(isc_task_t *task, isc_event_t *event) {
4620         dns_requestevent_t *revent = (dns_requestevent_t *)event;
4621         dns_notify_t *notify;
4622         isc_result_t result;
4623         dns_message_t *message = NULL;
4624         isc_buffer_t buf;
4625         char rcode[128];
4626         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
4627
4628         UNUSED(task);
4629
4630         notify = event->ev_arg;
4631         REQUIRE(DNS_NOTIFY_VALID(notify));
4632         INSIST(task == notify->zone->task);
4633
4634         isc_buffer_init(&buf, rcode, sizeof(rcode));
4635         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
4636
4637         result = revent->result;
4638         if (result == ISC_R_SUCCESS)
4639                 result = dns_message_create(notify->zone->mctx,
4640                                             DNS_MESSAGE_INTENTPARSE, &message);
4641         if (result == ISC_R_SUCCESS)
4642                 result = dns_request_getresponse(revent->request, message,
4643                                         DNS_MESSAGEPARSE_PRESERVEORDER);
4644         if (result == ISC_R_SUCCESS)
4645                 result = dns_rcode_totext(message->rcode, &buf);
4646         if (result == ISC_R_SUCCESS)
4647                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
4648                            "notify response from %s: %.*s",
4649                            addrbuf, (int)buf.used, rcode);
4650         else
4651                 notify_log(notify->zone, ISC_LOG_DEBUG(1),
4652                            "notify to %s failed: %s", addrbuf,
4653                            dns_result_totext(result));
4654
4655         /*
4656          * Old bind's return formerr if they see a soa record.  Retry w/o
4657          * the soa if we see a formerr and had sent a SOA.
4658          */
4659         isc_event_free(&event);
4660         if ((result == ISC_R_TIMEDOUT ||
4661              (message != NULL && message->rcode == dns_rcode_formerr &&
4662               (notify->flags & DNS_NOTIFY_NOSOA) == 0)) &&
4663              notify->attempt < 3) {
4664                 notify->flags |= DNS_NOTIFY_NOSOA;
4665                 notify->attempt++;
4666                 dns_request_destroy(&notify->request);
4667                 result = notify_send_queue(notify);
4668                 if (result != ISC_R_SUCCESS)
4669                         notify_destroy(notify, ISC_FALSE);
4670         } else {
4671                 if (result == ISC_R_TIMEDOUT)
4672                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
4673                                    "notify to %s: retries exceeded", addrbuf);
4674                 notify_destroy(notify, ISC_FALSE);
4675         }
4676         if (message != NULL)
4677                 dns_message_destroy(&message);
4678 }
4679
4680 isc_result_t
4681 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
4682         isc_result_t result;
4683
4684         REQUIRE(DNS_ZONE_VALID(zone));
4685         LOCK_ZONE(zone);
4686         result = zone_replacedb(zone, db, dump);
4687         UNLOCK_ZONE(zone);
4688         return (result);
4689 }
4690
4691 static isc_result_t
4692 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
4693         dns_dbversion_t *ver;
4694         isc_result_t result;
4695
4696         /*
4697          * 'zone' locked by caller.
4698          */
4699         REQUIRE(DNS_ZONE_VALID(zone));
4700         REQUIRE(LOCKED_ZONE(zone));
4701
4702         ver = NULL;
4703         dns_db_currentversion(db, &ver);
4704
4705         /*
4706          * The initial version of a slave zone is always dumped;
4707          * subsequent versions may be journalled instead if this
4708          * is enabled in the configuration.
4709          */
4710         if (zone->db != NULL && zone->journal != NULL &&
4711             zone->diff_on_reload) {
4712                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4713                               DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
4714                               "generating diffs");
4715                 result = dns_db_diff(zone->mctx, db, ver,
4716                                      zone->db, NULL /* XXX */,
4717                                      zone->journal);
4718                 if (result != ISC_R_SUCCESS)
4719                         goto fail;
4720         } else {
4721                 if (dump && zone->masterfile != NULL) {
4722                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4723                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
4724                                       "dumping new zone version");
4725                         result = dns_db_dump(db, ver, zone->masterfile);
4726                         if (result != ISC_R_SUCCESS)
4727                                 goto fail;
4728
4729                         /*
4730                          * Update the time the zone was updated, so
4731                          * dns_zone_load can avoid loading it when
4732                          * the server is reloaded.  If isc_time_now
4733                          * fails for some reason, all that happens is
4734                          * the timestamp is not updated.
4735                          */
4736                         (void)isc_time_now(&zone->loadtime);
4737                 }
4738
4739                 if (dump && zone->journal != NULL) {
4740                         /*
4741                          * The in-memory database just changed, and
4742                          * because 'dump' is set, it didn't change by
4743                          * being loaded from disk.  Also, we have not
4744                          * journalled diffs for this change.
4745                          * Therefore, the on-disk journal is missing
4746                          * the deltas for this change.  Since it can
4747                          * no longer be used to bring the zone
4748                          * up-to-date, it is useless and should be
4749                          * removed.
4750                          */
4751                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4752                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
4753                                       "removing journal file");
4754                         (void)remove(zone->journal);
4755                 }
4756         }
4757         
4758         dns_db_closeversion(db, &ver, ISC_FALSE);
4759
4760         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4761                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
4762                       "replacing zone database");
4763
4764         if (zone->db != NULL)
4765                 dns_db_detach(&zone->db);
4766         dns_db_attach(db, &zone->db);
4767         dns_db_settask(zone->db, zone->task);
4768         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
4769         return (ISC_R_SUCCESS);
4770
4771  fail:
4772         dns_db_closeversion(db, &ver, ISC_FALSE);
4773         return (result);
4774 }
4775
4776 static void
4777 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
4778         isc_time_t now;
4779         isc_interval_t i;
4780         isc_boolean_t again = ISC_FALSE;
4781         unsigned int soacount;
4782         unsigned int nscount;
4783         isc_uint32_t serial, refresh, retry, expire, minimum;
4784         isc_result_t xfrresult = result;
4785         isc_boolean_t free_needed;
4786
4787         REQUIRE(DNS_ZONE_VALID(zone));
4788
4789         dns_zone_log(zone, ISC_LOG_DEBUG(1),
4790                      "zone transfer finished: %s", dns_result_totext(result));
4791
4792         LOCK_ZONE(zone);
4793         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
4794         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
4795
4796         isc_time_now(&now);
4797         switch (result) {
4798         case ISC_R_SUCCESS:
4799                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
4800                 /*FALLTHROUGH*/
4801         case DNS_R_UPTODATE:
4802                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
4803                 /*
4804                  * Has the zone expired underneath us?
4805                  */
4806                 if (zone->db == NULL)
4807                         goto same_master;
4808
4809                 /*
4810                  * Update the zone structure's data from the actual
4811                  * SOA received.
4812                  */
4813                 nscount = 0;
4814                 soacount = 0;
4815                 INSIST(zone->db != NULL);
4816                 result = zone_get_from_db(zone->db, &zone->origin, &nscount,
4817                                           &soacount, &serial, &refresh,
4818                                           &retry, &expire, &minimum);
4819                 if (result == ISC_R_SUCCESS) {
4820                         if (soacount != 1)
4821                                 dns_zone_log(zone, ISC_LOG_ERROR,
4822                                              "transferred zone "
4823                                              "has %d SOA record%s", soacount,
4824                                              (soacount != 0) ? "s" : "");
4825                         if (nscount == 0)
4826                                 dns_zone_log(zone, ISC_LOG_ERROR,
4827                                              "transferred zone "
4828                                              "has no NS records");
4829                         zone->serial = serial;
4830                         zone->refresh = RANGE(refresh, zone->minrefresh,
4831                                               zone->maxrefresh);
4832                         zone->retry = RANGE(retry, zone->minretry,
4833                                             zone->maxretry);
4834                         zone->expire = RANGE(expire,
4835                                              zone->refresh + zone->retry,
4836                                              DNS_MAX_EXPIRE);
4837                         zone->minimum = minimum;
4838                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4839                 }
4840
4841                 /*
4842                  * Set our next update/expire times.
4843                  */
4844                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
4845                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
4846                         zone->refreshtime = now;
4847                         isc_interval_set(&i, zone->expire, 0);
4848                         isc_time_add(&now, &i, &zone->expiretime);
4849                 } else {
4850                         isc_interval_set(&i, isc_random_jitter(zone->refresh,
4851                                                   zone->refresh / 4), 0);
4852                         isc_time_add(&now, &i, &zone->refreshtime);
4853                         isc_interval_set(&i, zone->expire, 0);
4854                         isc_time_add(&now, &i, &zone->expiretime);
4855                 }
4856                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS)
4857                         dns_zone_log(zone, ISC_LOG_INFO,
4858                                      "transferred serial %u", zone->serial);
4859
4860                 /*
4861                  * This is not neccessary if we just performed a AXFR
4862                  * however it is necessary for an IXFR / UPTODATE and
4863                  * won't hurt with an AXFR.
4864                  */
4865                 if (zone->masterfile != NULL || zone->journal != NULL) {
4866                         result = ISC_R_FAILURE;
4867                         if (zone->journal != NULL)
4868                                 result = isc_file_settime(zone->journal, &now);
4869                         if (result != ISC_R_SUCCESS &&
4870                             zone->masterfile != NULL)
4871                                 result = isc_file_settime(zone->masterfile,
4872                                                           &now);
4873                         /* Someone removed the file from underneath us! */
4874                         if (result == ISC_R_FILENOTFOUND &&
4875                             zone->masterfile != NULL)
4876                                 zone_needdump(zone, DNS_DUMP_DELAY);
4877                         else if (result != ISC_R_SUCCESS)
4878                                 dns_zone_log(zone, ISC_LOG_ERROR,
4879                                              "transfer: could not set file "
4880                                              "modification time of '%s': %s",
4881                                              zone->masterfile,
4882                                              dns_result_totext(result));
4883                 }
4884
4885                 break;
4886
4887         case DNS_R_BADIXFR:
4888                 /* Force retry with AXFR. */
4889                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
4890                 goto same_master;
4891
4892         default:
4893                 zone->curmaster++;
4894         same_master:
4895                 if (zone->curmaster >= zone->masterscnt)
4896                         zone->curmaster = 0;
4897                 else {
4898                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
4899                         again = ISC_TRUE;
4900                 }
4901                 break;
4902         }
4903         zone_settimer(zone, &now);
4904
4905         /*
4906          * If creating the transfer object failed, zone->xfr is NULL.
4907          * Otherwise, we are called as the done callback of a zone
4908          * transfer object that just entered its shutting-down
4909          * state.  Since we are no longer responsible for shutting
4910          * it down, we can detach our reference.
4911          */
4912         if (zone->xfr != NULL)
4913                 dns_xfrin_detach(&zone->xfr);
4914
4915         /*
4916          * This transfer finishing freed up a transfer quota slot.
4917          * Let any other zones waiting for quota have it.
4918          */
4919         RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
4920         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
4921         zone->statelist = NULL;
4922         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
4923         RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
4924
4925         /*
4926          * Retry with a different server if necessary.
4927          */
4928         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
4929                 queue_soa_query(zone);
4930
4931         INSIST(zone->irefs > 0);
4932         zone->irefs--;
4933         free_needed = exit_check(zone);
4934         UNLOCK_ZONE(zone);
4935         if (free_needed)
4936                 zone_free(zone);
4937 }
4938
4939 static void
4940 zone_loaddone(void *arg, isc_result_t result) {
4941         static char me[] = "zone_loaddone";
4942         dns_load_t *load = arg;
4943         dns_zone_t *zone;
4944         isc_result_t tresult;
4945
4946         REQUIRE(DNS_LOAD_VALID(load));
4947         zone = load->zone;
4948
4949         ENTER;
4950
4951         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
4952         if (tresult != ISC_R_SUCCESS && 
4953             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
4954                 result = tresult;
4955
4956         LOCK_ZONE(load->zone);
4957         (void)zone_postload(load->zone, load->db, load->loadtime, result);
4958         zonemgr_putio(&load->zone->readio);
4959         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
4960         UNLOCK_ZONE(load->zone);
4961
4962         load->magic = 0;
4963         dns_db_detach(&load->db);
4964         if (load->zone->lctx != NULL)
4965                 dns_loadctx_detach(&load->zone->lctx);
4966         dns_zone_idetach(&load->zone);
4967         isc_mem_putanddetach(&load->mctx, load, sizeof (*load));
4968 }
4969
4970 void
4971 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
4972         REQUIRE(DNS_ZONE_VALID(zone));
4973         REQUIRE(table != NULL);
4974         REQUIRE(*table == NULL);
4975
4976         LOCK_ZONE(zone);
4977         if (zone->ssutable != NULL)
4978                 dns_ssutable_attach(zone->ssutable, table);
4979         UNLOCK_ZONE(zone);
4980 }
4981
4982 void
4983 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
4984         REQUIRE(DNS_ZONE_VALID(zone));
4985
4986         LOCK_ZONE(zone);
4987         if (zone->ssutable != NULL)
4988                 dns_ssutable_detach(&zone->ssutable);
4989         if (table != NULL)
4990                 dns_ssutable_attach(table, &zone->ssutable);
4991         UNLOCK_ZONE(zone);
4992 }
4993
4994 void
4995 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
4996         REQUIRE(DNS_ZONE_VALID(zone));
4997
4998         zone->sigvalidityinterval = interval;
4999 }
5000
5001 isc_uint32_t
5002 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
5003         REQUIRE(DNS_ZONE_VALID(zone));
5004
5005         return (zone->sigvalidityinterval);
5006 }
5007
5008 static void
5009 queue_xfrin(dns_zone_t *zone) {
5010         const char me[] = "queue_xfrin";
5011         isc_result_t result;
5012         dns_zonemgr_t *zmgr = zone->zmgr;
5013
5014         ENTER;
5015
5016         INSIST(zone->statelist == NULL);
5017
5018         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5019         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
5020         LOCK_ZONE(zone);
5021         zone->irefs++;
5022         UNLOCK_ZONE(zone);
5023         zone->statelist = &zmgr->waiting_for_xfrin;
5024         result = zmgr_start_xfrin_ifquota(zmgr, zone);
5025         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5026
5027         if (result == ISC_R_QUOTA) {
5028                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
5029                              "zone transfer deferred due to quota");
5030         } else if (result != ISC_R_SUCCESS) {
5031                 dns_zone_log(zone, ISC_LOG_ERROR,
5032                              "starting zone transfer: %s",
5033                              isc_result_totext(result));
5034         }
5035 }
5036
5037 /*
5038  * This event callback is called when a zone has received
5039  * any necessary zone transfer quota.  This is the time
5040  * to go ahead and start the transfer.
5041  */
5042 static void
5043 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
5044         isc_result_t result;
5045         dns_peer_t *peer = NULL;
5046         dns_tsigkey_t *tsigkey = NULL;
5047         char mastertext[256];
5048         dns_rdatatype_t xfrtype;
5049         dns_zone_t *zone = event->ev_arg;
5050         isc_netaddr_t masterip;
5051
5052         UNUSED(task);
5053
5054         INSIST(task == zone->task);
5055
5056         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
5057                 result = ISC_R_CANCELED;
5058                 goto cleanup;
5059         }
5060
5061         isc_sockaddr_format(&zone->masteraddr, mastertext, sizeof(mastertext));
5062
5063         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
5064         (void)dns_peerlist_peerbyaddr(zone->view->peers,
5065                                       &masterip, &peer);
5066
5067         /*
5068          * Decide whether we should request IXFR or AXFR.
5069          */
5070         if (zone->db == NULL) {
5071                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5072                              "no database exists yet, "
5073                              "requesting AXFR of "
5074                              "initial version from %s", mastertext);
5075                 xfrtype = dns_rdatatype_axfr;
5076         } else if (dns_zone_isforced(zone)) {
5077                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5078                              "forced reload, requesting AXFR of "
5079                              "initial version from %s", mastertext);
5080                 xfrtype = dns_rdatatype_axfr;
5081         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
5082                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5083                              "retrying with AXFR from %s due to "
5084                              "previous IXFR failure", mastertext);
5085                 xfrtype = dns_rdatatype_axfr;
5086                 LOCK_ZONE(zone);
5087                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
5088                 UNLOCK_ZONE(zone);
5089         } else {
5090                 isc_boolean_t use_ixfr = ISC_TRUE;
5091                 if (peer != NULL &&
5092                     dns_peer_getrequestixfr(peer, &use_ixfr) ==
5093                     ISC_R_SUCCESS) {
5094                         ; /* Using peer setting */
5095                 } else {
5096                         use_ixfr = zone->view->requestixfr;
5097                 }
5098                 if (use_ixfr == ISC_FALSE) {
5099                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
5100                                      "IXFR disabled, "
5101                                      "requesting AXFR from %s",
5102                                      mastertext);
5103                         xfrtype = dns_rdatatype_axfr;
5104                 } else {
5105                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
5106                                      "requesting IXFR from %s",
5107                                      mastertext);
5108                         xfrtype = dns_rdatatype_ixfr;
5109                 }
5110         }
5111
5112         /*
5113          * Determine if we should attempt to sign the request with TSIG.
5114          */
5115         result = ISC_R_NOTFOUND;
5116         /*
5117          * First, look for a tsig key in the master statement, then
5118          * try for a server key.
5119          */
5120         if ((zone->masterkeynames != NULL) &&
5121             (zone->masterkeynames[zone->curmaster] != NULL)) {
5122                 dns_view_t *view = dns_zone_getview(zone);
5123                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
5124                 result = dns_view_gettsig(view, keyname, &tsigkey);
5125         }
5126         if (tsigkey == NULL)
5127                 result = dns_view_getpeertsig(zone->view, &masterip, &tsigkey);
5128
5129         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
5130                 dns_zone_log(zone, ISC_LOG_ERROR,
5131                              "could not get TSIG key "
5132                              "for zone transfer: %s",
5133                              isc_result_totext(result));
5134         }
5135
5136         result = dns_xfrin_create(zone, xfrtype, &zone->masteraddr,
5137                                   tsigkey, zone->mctx,
5138                                   zone->zmgr->timermgr, zone->zmgr->socketmgr,
5139                                   zone->task, zone_xfrdone, &zone->xfr);
5140  cleanup:
5141         /*
5142          * Any failure in this function is handled like a failed
5143          * zone transfer.  This ensures that we get removed from
5144          * zmgr->xfrin_in_progress.
5145          */
5146         if (result != ISC_R_SUCCESS)
5147                 zone_xfrdone(zone, result);
5148
5149         if (tsigkey != NULL)
5150                 dns_tsigkey_detach(&tsigkey);
5151
5152         isc_event_free(&event);
5153 }
5154
5155 /*
5156  * Update forwarding support.
5157  */
5158
5159 static void
5160 forward_destroy(dns_forward_t *forward) {
5161
5162         forward->magic = 0;
5163         if (forward->request != NULL)
5164                 dns_request_destroy(&forward->request);
5165         if (forward->msgbuf != NULL)
5166                 isc_buffer_free(&forward->msgbuf);
5167         if (forward->zone != NULL)
5168                 dns_zone_idetach(&forward->zone);
5169         isc_mem_putanddetach(&forward->mctx, forward, sizeof (*forward));
5170 }
5171
5172 static isc_result_t
5173 sendtomaster(dns_forward_t *forward) {
5174         isc_result_t result;
5175         isc_sockaddr_t src;
5176
5177         LOCK_ZONE(forward->zone);
5178         if (forward->which >= forward->zone->masterscnt) {
5179                 UNLOCK_ZONE(forward->zone);
5180                 return (ISC_R_NOMORE);
5181         }
5182
5183         forward->addr = forward->zone->masters[forward->which];
5184         /*
5185          * Always use TCP regardless of whether the original update
5186          * used TCP.
5187          * XXX The timeout may but a bit small if we are far down a
5188          * transfer graph and the master has to try several masters.
5189          */
5190         switch (isc_sockaddr_pf(&forward->addr)) {
5191         case PF_INET:
5192                 src = forward->zone->xfrsource4;
5193                 break;
5194         case PF_INET6:
5195                 src = forward->zone->xfrsource6;
5196                 break;
5197         default:
5198                 result = ISC_R_NOTIMPLEMENTED;
5199                 goto unlock;
5200         }
5201         result = dns_request_createraw(forward->zone->view->requestmgr,
5202                                        forward->msgbuf,
5203                                        &src, &forward->addr,
5204                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
5205                                        forward->zone->task,
5206                                        forward_callback, forward,
5207                                        &forward->request);
5208  unlock:
5209         UNLOCK_ZONE(forward->zone);
5210         return (result);
5211 }
5212
5213 static void
5214 forward_callback(isc_task_t *task, isc_event_t *event) {
5215         const char me[] = "forward_callback";
5216         dns_requestevent_t *revent = (dns_requestevent_t *)event;
5217         dns_message_t *msg = NULL;
5218         char master[ISC_SOCKADDR_FORMATSIZE];
5219         isc_result_t result;
5220         dns_forward_t *forward;
5221         dns_zone_t *zone;
5222
5223         UNUSED(task);
5224         
5225         forward = revent->ev_arg;
5226         INSIST(DNS_FORWARD_VALID(forward));
5227         zone = forward->zone;
5228         INSIST(DNS_ZONE_VALID(zone));
5229         
5230         ENTER;
5231         
5232         isc_sockaddr_format(&forward->addr, master, sizeof(master));
5233
5234         if (revent->result != ISC_R_SUCCESS) {
5235                 dns_zone_log(zone, ISC_LOG_INFO,
5236                              "could not forward dynamic update to %s: %s",
5237                              master, dns_result_totext(revent->result));
5238                 goto next_master;
5239         }
5240
5241         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
5242         if (result != ISC_R_SUCCESS)
5243                 goto next_master;
5244
5245         result = dns_request_getresponse(revent->request, msg,
5246                                          DNS_MESSAGEPARSE_PRESERVEORDER |
5247                                          DNS_MESSAGEPARSE_CLONEBUFFER);
5248         if (result != ISC_R_SUCCESS)
5249                 goto next_master;
5250
5251         switch (msg->rcode) {
5252         /*
5253          * Pass these rcodes back to client.
5254          */
5255         case dns_rcode_noerror:
5256         case dns_rcode_yxdomain:
5257         case dns_rcode_yxrrset:
5258         case dns_rcode_nxrrset:
5259         case dns_rcode_refused:
5260         case dns_rcode_nxdomain:
5261                 break;
5262
5263         /* These should not occur if the masters/zone are valid. */
5264         case dns_rcode_notzone:
5265         case dns_rcode_notauth: {
5266                 char rcode[128];
5267                 isc_buffer_t rb;
5268
5269                 isc_buffer_init(&rb, rcode, sizeof(rcode));
5270                 dns_rcode_totext(msg->rcode, &rb);
5271                 dns_zone_log(zone, ISC_LOG_WARNING,
5272                              "forwarding dynamic update: "
5273                              "unexpected response: master %s returned: %.*s",
5274                              master, (int)rb.used, rcode);
5275                 goto next_master;
5276         }
5277
5278         /* Try another server for these rcodes. */
5279         case dns_rcode_formerr:
5280         case dns_rcode_servfail:
5281         case dns_rcode_notimp:
5282         case dns_rcode_badvers:
5283         default:
5284                 goto next_master;
5285         }
5286
5287         /* call callback */
5288         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
5289         msg = NULL;
5290         dns_request_destroy(&forward->request);
5291         forward_destroy(forward);
5292         isc_event_free(&event);
5293         return;
5294
5295  next_master:
5296         if (msg != NULL)
5297                 dns_message_destroy(&msg);
5298         isc_event_free(&event);
5299         forward->which++;
5300         dns_request_destroy(&forward->request);
5301         result = sendtomaster(forward);
5302         if (result != ISC_R_SUCCESS) {
5303                 /* call callback */
5304                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
5305                              "exhausted dynamic update forwarder list");
5306                 (forward->callback)(forward->callback_arg, result, NULL);
5307                 forward_destroy(forward);
5308         }
5309 }
5310
5311 isc_result_t
5312 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
5313                        dns_updatecallback_t callback, void *callback_arg)
5314 {
5315         dns_forward_t *forward;
5316         isc_result_t result;
5317         isc_region_t *mr;
5318
5319         REQUIRE(DNS_ZONE_VALID(zone));
5320         REQUIRE(msg != NULL);
5321         REQUIRE(callback != NULL);
5322
5323         forward = isc_mem_get(zone->mctx, sizeof(*forward));
5324         if (forward == NULL)
5325                 return (ISC_R_NOMEMORY);
5326
5327         forward->request = NULL;
5328         forward->zone = NULL;
5329         forward->msgbuf = NULL;
5330         forward->which = 0;
5331         forward->mctx = 0;
5332         forward->callback = callback;
5333         forward->callback_arg = callback_arg;
5334         forward->magic = FORWARD_MAGIC;
5335         
5336         mr = dns_message_getrawmessage(msg);
5337         if (mr == NULL) {
5338                 result = ISC_R_UNEXPECTEDEND;
5339                 goto cleanup;
5340         }
5341
5342         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
5343         if (result != ISC_R_SUCCESS)
5344                 goto cleanup;
5345         result = isc_buffer_copyregion(forward->msgbuf, mr);
5346         if (result != ISC_R_SUCCESS)
5347                 goto cleanup;
5348         
5349         isc_mem_attach(zone->mctx, &forward->mctx);
5350         dns_zone_iattach(zone, &forward->zone);
5351         result = sendtomaster(forward);
5352
5353  cleanup:
5354         if (result != ISC_R_SUCCESS) {
5355                 forward_destroy(forward);
5356         }
5357         return (result);
5358 }
5359
5360 isc_result_t
5361 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
5362         REQUIRE(DNS_ZONE_VALID(zone));
5363         REQUIRE(next != NULL && *next == NULL);
5364
5365         *next = ISC_LIST_NEXT(zone, link);
5366         if (*next == NULL)
5367                 return (ISC_R_NOMORE);
5368         else
5369                 return (ISC_R_SUCCESS);
5370 }
5371
5372 isc_result_t
5373 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
5374         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5375         REQUIRE(first != NULL && *first == NULL);
5376
5377         *first = ISC_LIST_HEAD(zmgr->zones);
5378         if (*first == NULL)
5379                 return (ISC_R_NOMORE);
5380         else
5381                 return (ISC_R_SUCCESS);
5382 }
5383
5384 /***
5385  ***    Zone manager.
5386  ***/
5387
5388 isc_result_t
5389 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
5390                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
5391                    dns_zonemgr_t **zmgrp)
5392 {
5393         dns_zonemgr_t *zmgr;
5394         isc_result_t result;
5395         isc_interval_t interval;
5396
5397         zmgr = isc_mem_get(mctx, sizeof *zmgr);
5398         if (zmgr == NULL)
5399                 return (ISC_R_NOMEMORY);
5400         zmgr->mctx = NULL;
5401         zmgr->refs = 1;
5402         isc_mem_attach(mctx, &zmgr->mctx);
5403         zmgr->taskmgr = taskmgr;
5404         zmgr->timermgr = timermgr;
5405         zmgr->socketmgr = socketmgr;
5406         zmgr->zonetasks = NULL;
5407         zmgr->task = NULL;
5408         zmgr->rl = NULL;
5409         ISC_LIST_INIT(zmgr->zones);
5410         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
5411         ISC_LIST_INIT(zmgr->xfrin_in_progress);
5412         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
5413         if (result != ISC_R_SUCCESS) {
5414                 UNEXPECTED_ERROR(__FILE__, __LINE__,
5415                                  "isc_rwlock_init() failed: %s",
5416                                  isc_result_totext(result));
5417                 result = ISC_R_UNEXPECTED;
5418                 goto free_mem;
5419         }
5420         zmgr->transfersin = 10;
5421         zmgr->transfersperns = 2;
5422
5423         /* Create the zone task pool. */
5424         result = isc_taskpool_create(taskmgr, mctx,
5425                                      8 /* XXX */, 2, &zmgr->zonetasks);
5426         if (result != ISC_R_SUCCESS)
5427                 goto free_rwlock;
5428
5429         /* Create a single task for queueing of SOA queries. */
5430         result = isc_task_create(taskmgr, 1, &zmgr->task);
5431         if (result != ISC_R_SUCCESS)
5432                 goto free_taskpool;
5433         isc_task_setname(zmgr->task, "zmgr", zmgr);
5434         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
5435                                         &zmgr->rl);
5436         if (result != ISC_R_SUCCESS)
5437                 goto free_task;
5438         /* default to 20 refresh queries / notifies per second. */
5439         isc_interval_set(&interval, 0, 1000000000/2);
5440         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
5441         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5442         isc_ratelimiter_setpertic(zmgr->rl, 10);
5443
5444         zmgr->iolimit = 1;
5445         zmgr->ioactive = 0;
5446         ISC_LIST_INIT(zmgr->high);
5447         ISC_LIST_INIT(zmgr->low);
5448
5449         result = isc_mutex_init(&zmgr->iolock);
5450         if (result != ISC_R_SUCCESS) {
5451                 UNEXPECTED_ERROR(__FILE__, __LINE__,
5452                                  "isc_mutex_init() failed: %s",
5453                                  isc_result_totext(result));
5454                 goto free_rl;
5455         }
5456         zmgr->magic = ZONEMGR_MAGIC;
5457
5458         *zmgrp = zmgr;
5459         return (ISC_R_SUCCESS);
5460
5461 #if 0
5462  free_iolock:
5463         DESTROYLOCK(&zmgr->iolock);
5464 #endif
5465  free_rl:
5466         isc_ratelimiter_detach(&zmgr->rl);
5467  free_task:
5468         isc_task_detach(&zmgr->task);
5469  free_taskpool:
5470         isc_taskpool_destroy(&zmgr->zonetasks);
5471  free_rwlock:
5472         isc_rwlock_destroy(&zmgr->rwlock);
5473  free_mem:
5474         isc_mem_put(zmgr->mctx, zmgr, sizeof *zmgr);
5475         isc_mem_detach(&mctx);
5476         return (result);
5477 }
5478
5479 isc_result_t
5480 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
5481         isc_result_t result;
5482
5483         REQUIRE(DNS_ZONE_VALID(zone));
5484         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5485
5486         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5487         LOCK_ZONE(zone);
5488         REQUIRE(zone->task == NULL);
5489         REQUIRE(zone->timer == NULL);
5490         REQUIRE(zone->zmgr == NULL);
5491
5492         isc_taskpool_gettask(zmgr->zonetasks,
5493                              dns_name_hash(dns_zone_getorigin(zone),
5494                                            ISC_FALSE),
5495                              &zone->task);
5496
5497         /*
5498          * Set the task name.  The tag will arbitrarily point to one
5499          * of the zones sharing the task (in practice, the one
5500          * to be managed last).
5501          */
5502         isc_task_setname(zone->task, "zone", zone);
5503
5504         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
5505                                   NULL, NULL,
5506                                   zone->task, zone_timer, zone,
5507                                   &zone->timer);
5508         if (result != ISC_R_SUCCESS)
5509                 goto cleanup_task;
5510         /*
5511          * The timer "holds" a iref.
5512          */
5513         zone->irefs++;
5514         INSIST(zone->irefs != 0);
5515
5516         ISC_LIST_APPEND(zmgr->zones, zone, link);
5517         zone->zmgr = zmgr;
5518         zmgr->refs++;
5519
5520         goto unlock;
5521
5522  cleanup_task:
5523         isc_task_detach(&zone->task);
5524
5525  unlock:
5526         UNLOCK_ZONE(zone);
5527         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5528         return (result);
5529 }
5530
5531 void
5532 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
5533         isc_boolean_t free_now = ISC_FALSE;
5534
5535         REQUIRE(DNS_ZONE_VALID(zone));
5536         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5537         REQUIRE(zone->zmgr == zmgr);
5538
5539         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5540         LOCK_ZONE(zone);
5541
5542         ISC_LIST_UNLINK(zmgr->zones, zone, link);
5543         zone->zmgr = NULL;
5544         zmgr->refs--;
5545         if (zmgr->refs == 0)
5546                 free_now = ISC_TRUE;
5547
5548         UNLOCK_ZONE(zone);
5549         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5550
5551         if (free_now)
5552                 zonemgr_free(zmgr);
5553         ENSURE(zone->zmgr == NULL);
5554 }
5555
5556 void
5557 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
5558         REQUIRE(DNS_ZONEMGR_VALID(source));
5559         REQUIRE(target != NULL && *target == NULL);
5560
5561         RWLOCK(&source->rwlock, isc_rwlocktype_write);
5562         REQUIRE(source->refs > 0);
5563         source->refs++;
5564         INSIST(source->refs > 0);
5565         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
5566         *target = source;
5567 }
5568
5569 void
5570 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
5571         dns_zonemgr_t *zmgr;
5572         isc_boolean_t free_now = ISC_FALSE;
5573
5574         REQUIRE(zmgrp != NULL);
5575         zmgr = *zmgrp;
5576         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5577
5578         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5579         zmgr->refs--;
5580         if (zmgr->refs == 0)
5581                 free_now = ISC_TRUE;
5582         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5583
5584         if (free_now)
5585                 zonemgr_free(zmgr);
5586 }
5587
5588 isc_result_t
5589 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
5590         dns_zone_t *p;
5591
5592         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5593
5594         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
5595         for (p = ISC_LIST_HEAD(zmgr->zones);
5596              p != NULL;
5597              p = ISC_LIST_NEXT(p, link))
5598         {
5599                 dns_zone_maintenance(p);
5600         }
5601         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
5602
5603         /*
5604          * Recent configuration changes may have increased the
5605          * amount of available transfers quota.  Make sure any
5606          * transfers currently blocked on quota get started if
5607          * possible.
5608          */
5609         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5610         zmgr_resume_xfrs(zmgr, ISC_TRUE);
5611         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
5612         return (ISC_R_SUCCESS);
5613 }
5614
5615 void
5616 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
5617         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5618
5619         isc_ratelimiter_shutdown(zmgr->rl);
5620
5621         if (zmgr->task != NULL)
5622                 isc_task_destroy(&zmgr->task);
5623         if (zmgr->zonetasks != NULL)
5624                 isc_taskpool_destroy(&zmgr->zonetasks);
5625 }
5626
5627 static void
5628 zonemgr_free(dns_zonemgr_t *zmgr) {
5629         isc_mem_t *mctx;
5630
5631         INSIST(zmgr->refs == 0);
5632         INSIST(ISC_LIST_EMPTY(zmgr->zones));
5633
5634         zmgr->magic = 0;
5635
5636         DESTROYLOCK(&zmgr->iolock);
5637         isc_ratelimiter_detach(&zmgr->rl);
5638
5639         isc_rwlock_destroy(&zmgr->rwlock);
5640         mctx = zmgr->mctx;
5641         isc_mem_put(zmgr->mctx, zmgr, sizeof *zmgr);
5642         isc_mem_detach(&mctx);
5643 }
5644
5645 void
5646 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
5647         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5648
5649         zmgr->transfersin = value;
5650 }
5651
5652 isc_uint32_t
5653 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
5654         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5655
5656         return (zmgr->transfersin);
5657 }
5658
5659 void
5660 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
5661         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5662
5663         zmgr->transfersperns = value;
5664 }
5665
5666 isc_uint32_t
5667 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
5668         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5669
5670         return (zmgr->transfersperns);
5671 }
5672
5673 /*
5674  * Try to start a new incoming zone transfer to fill a quota
5675  * slot that was just vacated.
5676  *
5677  * Requires:
5678  *      The zone manager is locked by the caller.
5679  */
5680 static void
5681 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
5682         dns_zone_t *zone;
5683         dns_zone_t *next;
5684
5685         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
5686              zone != NULL;
5687              zone = next)
5688         {
5689                 isc_result_t result;
5690                 next = ISC_LIST_NEXT(zone, statelink);
5691                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
5692                 if (result == ISC_R_SUCCESS) {
5693                         if (multi)
5694                                 continue;
5695                         /*
5696                          * We successfully filled the slot.  We're done.
5697                          */
5698                         break;
5699                 } else if (result == ISC_R_QUOTA) {
5700                         /*
5701                          * Not enough quota.  This is probably the per-server
5702                          * quota, because we usually get called when a unit of
5703                          * global quota has just been freed.  Try the next
5704                          * zone, it may succeed if it uses another master.
5705                          */
5706                         continue;
5707                 } else {
5708                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
5709                                      "starting zone transfer: %s",
5710                                      isc_result_totext(result));
5711                         break;
5712                 }
5713         }
5714 }
5715
5716 /*
5717  * Try to start an incoming zone transfer for 'zone', quota permitting.
5718  *
5719  * Requires:
5720  *      The zone manager is locked by the caller.
5721  *
5722  * Returns:
5723  *      ISC_R_SUCCESS   There was enough quota and we attempted to
5724  *                      start a transfer.  zone_xfrdone() has been or will
5725  *                      be called.
5726  *      ISC_R_QUOTA     Not enough quota.
5727  *      Others          Failure.
5728  */
5729 static isc_result_t
5730 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
5731         dns_peer_t *peer = NULL;
5732         isc_netaddr_t masterip;
5733         isc_uint32_t nxfrsin, nxfrsperns;
5734         dns_zone_t *x;
5735         isc_uint32_t maxtransfersin, maxtransfersperns;
5736         isc_event_t *e;
5737
5738         /*
5739          * Find any configured information about the server we'd
5740          * like to transfer this zone from.
5741          */
5742         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
5743         (void)dns_peerlist_peerbyaddr(zone->view->peers,
5744                                       &masterip, &peer);
5745
5746         /*
5747          * Determine the total maximum number of simultaneous
5748          * transfers allowed, and the maximum for this specific
5749          * master.
5750          */
5751         maxtransfersin = zmgr->transfersin;
5752         maxtransfersperns = zmgr->transfersperns;
5753         if (peer != NULL)
5754                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
5755
5756         /*
5757          * Count the total number of transfers that are in progress,
5758          * and the number of transfers in progress from this master.
5759          * We linearly scan a list of all transfers; if this turns
5760          * out to be too slow, we could hash on the master address.
5761          */
5762         nxfrsin = nxfrsperns = 0;
5763         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
5764              x != NULL;
5765              x = ISC_LIST_NEXT(x, statelink))
5766         {
5767                 isc_netaddr_t xip;
5768                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
5769                 nxfrsin++;
5770                 if (isc_netaddr_equal(&xip, &masterip))
5771                         nxfrsperns++;
5772         }
5773
5774         /* Enforce quota. */
5775         if (nxfrsin >= maxtransfersin)
5776                 return (ISC_R_QUOTA);
5777
5778         if (nxfrsperns >= maxtransfersperns)
5779                 return (ISC_R_QUOTA);
5780
5781         /*
5782          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
5783          * list and send it an event to let it start the actual transfer in the
5784          * context of its own task.
5785          */
5786         e = isc_event_allocate(zmgr->mctx, zmgr,
5787                                DNS_EVENT_ZONESTARTXFRIN,
5788                                got_transfer_quota, zone,
5789                                sizeof(isc_event_t));
5790         if (e == NULL)
5791                 return (ISC_R_NOMEMORY);
5792
5793         LOCK_ZONE(zone);
5794         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
5795         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
5796         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
5797         zone->statelist = &zmgr->xfrin_in_progress;
5798         isc_task_send(zone->task, &e);
5799         UNLOCK_ZONE(zone);
5800
5801         return (ISC_R_SUCCESS);
5802 }
5803
5804 void
5805 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
5806
5807         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5808         REQUIRE(iolimit > 0);
5809
5810         zmgr->iolimit = iolimit;
5811 }
5812
5813 isc_uint32_t
5814 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
5815
5816         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5817
5818         return (zmgr->iolimit);
5819 }
5820
5821 /*
5822  * Get permission to request a file handle from the OS.
5823  * An event will be sent to action when one is available.
5824  * There are two queues available (high and low), the high
5825  * queue will be serviced before the low one.
5826  * 
5827  * zonemgr_putio() must be called after the event is delivered to
5828  * 'action'.
5829  */
5830
5831 static isc_result_t
5832 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
5833               isc_task_t *task, isc_taskaction_t action, void *arg,
5834               dns_io_t **iop)
5835 {
5836         dns_io_t *io;
5837         isc_boolean_t queue;
5838
5839         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5840         REQUIRE(iop != NULL && *iop == NULL);
5841
5842         io = isc_mem_get(zmgr->mctx, sizeof(*io));
5843         if (io == NULL)
5844                 return (ISC_R_NOMEMORY);
5845         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
5846                                        action, arg, sizeof(*io->event));
5847         if (io->event == NULL) {
5848                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
5849                 return (ISC_R_NOMEMORY);
5850         }
5851         io->zmgr = zmgr;
5852         io->high = high; 
5853         io->task = NULL;
5854         isc_task_attach(task, &io->task);
5855         ISC_LINK_INIT(io, link); 
5856         io->magic = IO_MAGIC;
5857
5858         LOCK(&zmgr->iolock);
5859         zmgr->ioactive++;
5860         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
5861         if (queue) {
5862                 if (io->high)
5863                         ISC_LIST_APPEND(zmgr->high, io, link);
5864                 else
5865                         ISC_LIST_APPEND(zmgr->low, io, link);
5866         }
5867         UNLOCK(&zmgr->iolock);
5868         *iop = io;
5869
5870         if (!queue) {
5871                 isc_task_send(io->task, &io->event);
5872         }
5873         return (ISC_R_SUCCESS);
5874 }
5875
5876 static void
5877 zonemgr_putio(dns_io_t **iop) {
5878         dns_io_t *io;
5879         dns_io_t *next;
5880         dns_zonemgr_t *zmgr;
5881
5882         REQUIRE(iop != NULL);
5883         io = *iop;
5884         REQUIRE(DNS_IO_VALID(io));
5885
5886         *iop = NULL;
5887
5888         INSIST(!ISC_LINK_LINKED(io, link));
5889         INSIST(io->event == NULL);
5890
5891         zmgr = io->zmgr;
5892         isc_task_detach(&io->task);
5893         io->magic = 0;
5894         isc_mem_put(zmgr->mctx, io, sizeof(*io));
5895
5896         LOCK(&zmgr->iolock);
5897         INSIST(zmgr->ioactive > 0);
5898         zmgr->ioactive--;
5899         next = HEAD(zmgr->high);
5900         if (next == NULL)
5901                 next = HEAD(zmgr->low);
5902         if (next != NULL) {
5903                 if (next->high)
5904                         ISC_LIST_UNLINK(zmgr->high, next, link);
5905                 else
5906                         ISC_LIST_UNLINK(zmgr->low, next, link);
5907                 INSIST(next->event != NULL);
5908         }
5909         UNLOCK(&zmgr->iolock);
5910         if (next != NULL)
5911                 isc_task_send(next->task, &next->event);
5912 }
5913
5914 static void
5915 zonemgr_cancelio(dns_io_t *io) {
5916         isc_boolean_t send_event = ISC_FALSE;
5917
5918         REQUIRE(DNS_IO_VALID(io));
5919
5920         /*
5921          * If we are queued to be run then dequeue.
5922          */
5923         LOCK(&io->zmgr->iolock);
5924         if (ISC_LINK_LINKED(io, link)) {
5925                 if (io->high)
5926                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
5927                 else
5928                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
5929
5930                 send_event = ISC_TRUE;
5931                 INSIST(io->event != NULL);
5932         } 
5933         UNLOCK(&io->zmgr->iolock);
5934         if (send_event) {
5935                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
5936                 isc_task_send(io->task, &io->event);
5937         }
5938 }
5939
5940 static void
5941 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
5942         char *buf;
5943         int buflen;
5944         isc_result_t result;
5945         
5946         buflen = strlen(path) + strlen(templat) + 2;
5947
5948         buf = isc_mem_get(zone->mctx, buflen);
5949         if (buf == NULL)
5950                 return;
5951
5952         result = isc_file_template(path, templat, buf, buflen);
5953         if (result != ISC_R_SUCCESS)
5954                 goto cleanup;
5955
5956         result = isc_file_renameunique(path, buf);
5957         if (result != ISC_R_SUCCESS)
5958                 goto cleanup;
5959
5960         dns_zone_log(zone, ISC_LOG_INFO, "saved '%s' as '%s'",
5961                      path, buf);
5962
5963  cleanup:
5964         isc_mem_put(zone->mctx, buf, buflen);
5965 }
5966
5967 #if 0
5968 /* Hook for ondestroy notifcation from a database. */
5969
5970 static void
5971 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
5972         dns_db_t *db = event->sender;
5973         UNUSED(task);
5974
5975         isc_event_free(&event);
5976
5977         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5978                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
5979                       "database (%p) destroyed", (void*) db);
5980 }
5981 #endif
5982
5983 void
5984 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
5985         isc_interval_t interval;
5986         isc_uint32_t s, ns;
5987         isc_uint32_t pertic;
5988         isc_result_t result;
5989
5990         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
5991
5992         if (value == 0)
5993                 value = 1;
5994
5995         if (value == 1) {
5996                 s = 1;
5997                 ns = 0;
5998                 pertic = 1;             
5999         } else if (value <= 10) {
6000                 s = 0;
6001                 ns = 1000000000 / value;
6002                 pertic = 1;
6003         } else {
6004                 s = 0;
6005                 ns = (1000000000 / value) * 10;
6006                 pertic = 10;
6007         }
6008
6009         isc_interval_set(&interval, s, ns);
6010         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
6011         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6012         isc_ratelimiter_setpertic(zmgr->rl, pertic);
6013
6014         zmgr->serialqueryrate = value;
6015 }
6016
6017 unsigned int
6018 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
6019         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6020
6021         return (zmgr->serialqueryrate);
6022 }
6023
6024 void
6025 dns_zone_forcereload(dns_zone_t *zone) {
6026         REQUIRE(DNS_ZONE_VALID(zone));
6027
6028         LOCK_ZONE(zone);
6029         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
6030         UNLOCK_ZONE(zone);
6031         dns_zone_refresh(zone);
6032 }
6033
6034 isc_boolean_t
6035 dns_zone_isforced(dns_zone_t *zone) {
6036         REQUIRE(DNS_ZONE_VALID(zone));
6037
6038         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
6039 }
6040
6041 isc_result_t
6042 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
6043         isc_result_t result = ISC_R_SUCCESS;    
6044
6045         LOCK_ZONE(zone);
6046         if (on) {
6047                 if (zone->counters != NULL)
6048                         goto done;
6049                 result = dns_stats_alloccounters(zone->mctx, &zone->counters);
6050         } else {
6051                 if (zone->counters == NULL)
6052                         goto done;
6053                 dns_stats_freecounters(zone->mctx, &zone->counters);            
6054         }
6055  done:
6056         UNLOCK_ZONE(zone);
6057         return (result);
6058 }
6059
6060 isc_uint64_t *
6061 dns_zone_getstatscounters(dns_zone_t *zone) {
6062         return (zone->counters);
6063 }
6064
6065 void
6066 dns_zone_dialup(dns_zone_t *zone) {
6067         
6068         REQUIRE(DNS_ZONE_VALID(zone));
6069
6070         zone_debuglog(zone, "dns_zone_dialup", 3,
6071                       "notify = %d, refresh = %d",
6072                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
6073                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
6074         
6075         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
6076                 dns_zone_notify(zone);
6077         if (zone->type != dns_zone_master &&
6078             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
6079                 dns_zone_refresh(zone);
6080 }
6081
6082 void
6083 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
6084         REQUIRE(DNS_ZONE_VALID(zone));
6085
6086         LOCK_ZONE(zone);
6087         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
6088                          DNS_ZONEFLG_DIALREFRESH |
6089                          DNS_ZONEFLG_NOREFRESH);
6090         switch (dialup) {
6091         case dns_dialuptype_no:
6092                 break;
6093         case dns_dialuptype_yes:
6094                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
6095                                  DNS_ZONEFLG_DIALREFRESH |
6096                                  DNS_ZONEFLG_NOREFRESH));
6097                 break;
6098         case dns_dialuptype_notify:
6099                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
6100                 break;
6101         case dns_dialuptype_notifypassive:
6102                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
6103                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
6104                 break;
6105         case dns_dialuptype_refresh:
6106                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
6107                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
6108                 break;
6109         case dns_dialuptype_passive:
6110                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
6111                 break;
6112         default:
6113                 INSIST(0);
6114         }
6115         UNLOCK_ZONE(zone);
6116 }
6117
6118 unsigned int
6119 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
6120         dns_zone_t *zone;
6121         unsigned int count = 0;
6122
6123         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
6124
6125         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
6126         switch (state) {
6127         case DNS_ZONESTATE_XFERRUNNING:
6128                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
6129                      zone != NULL;
6130                      zone = ISC_LIST_NEXT(zone, statelink))
6131                         count++;
6132                 break;
6133         case DNS_ZONESTATE_XFERDEFERRED:
6134                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
6135                      zone != NULL;
6136                      zone = ISC_LIST_NEXT(zone, statelink))
6137                         count++;
6138                 break;
6139         case DNS_ZONESTATE_SOAQUERY:
6140                 for (zone = ISC_LIST_HEAD(zmgr->zones);
6141                      zone != NULL;
6142                      zone = ISC_LIST_NEXT(zone, link))
6143                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
6144                                 count++;
6145                 break;
6146         case DNS_ZONESTATE_ANY:
6147                 for (zone = ISC_LIST_HEAD(zmgr->zones);
6148                      zone != NULL;
6149                      zone = ISC_LIST_NEXT(zone, link))
6150                         count++;
6151                 break;
6152         default:
6153                 INSIST(0);
6154         }
6155
6156         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
6157
6158         return (count);
6159 }