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