]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - contrib/bind9/lib/dns/zone.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / contrib / bind9 / 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.483.36.6 2009/03/26 22:57:07 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/stdtime.h>
36 #include <isc/string.h>
37 #include <isc/taskpool.h>
38 #include <isc/timer.h>
39 #include <isc/util.h>
40
41 #include <dns/acache.h>
42 #include <dns/acl.h>
43 #include <dns/adb.h>
44 #include <dns/callbacks.h>
45 #include <dns/db.h>
46 #include <dns/dbiterator.h>
47 #include <dns/dnssec.h>
48 #include <dns/events.h>
49 #include <dns/journal.h>
50 #include <dns/keyvalues.h>
51 #include <dns/log.h>
52 #include <dns/master.h>
53 #include <dns/masterdump.h>
54 #include <dns/message.h>
55 #include <dns/name.h>
56 #include <dns/nsec.h>
57 #include <dns/nsec3.h>
58 #include <dns/peer.h>
59 #include <dns/rcode.h>
60 #include <dns/rdataclass.h>
61 #include <dns/rdatalist.h>
62 #include <dns/rdataset.h>
63 #include <dns/rdatasetiter.h>
64 #include <dns/rdatastruct.h>
65 #include <dns/rdatatype.h>
66 #include <dns/request.h>
67 #include <dns/resolver.h>
68 #include <dns/result.h>
69 #include <dns/soa.h>
70 #include <dns/ssu.h>
71 #include <dns/stats.h>
72 #include <dns/tsig.h>
73 #include <dns/xfrin.h>
74 #include <dns/zone.h>
75
76 #include <dst/dst.h>
77
78 #define ZONE_MAGIC                      ISC_MAGIC('Z', 'O', 'N', 'E')
79 #define DNS_ZONE_VALID(zone)            ISC_MAGIC_VALID(zone, ZONE_MAGIC)
80
81 #define NOTIFY_MAGIC                    ISC_MAGIC('N', 't', 'f', 'y')
82 #define DNS_NOTIFY_VALID(notify)        ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
83
84 #define STUB_MAGIC                      ISC_MAGIC('S', 't', 'u', 'b')
85 #define DNS_STUB_VALID(stub)            ISC_MAGIC_VALID(stub, STUB_MAGIC)
86
87 #define ZONEMGR_MAGIC                   ISC_MAGIC('Z', 'm', 'g', 'r')
88 #define DNS_ZONEMGR_VALID(stub)         ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
89
90 #define LOAD_MAGIC                      ISC_MAGIC('L', 'o', 'a', 'd')
91 #define DNS_LOAD_VALID(load)            ISC_MAGIC_VALID(load, LOAD_MAGIC)
92
93 #define FORWARD_MAGIC                   ISC_MAGIC('F', 'o', 'r', 'w')
94 #define DNS_FORWARD_VALID(load)         ISC_MAGIC_VALID(load, FORWARD_MAGIC)
95
96 #define IO_MAGIC                        ISC_MAGIC('Z', 'm', 'I', 'O')
97 #define DNS_IO_VALID(load)              ISC_MAGIC_VALID(load, IO_MAGIC)
98
99 /*%
100  * Ensure 'a' is at least 'min' but not more than 'max'.
101  */
102 #define RANGE(a, min, max) \
103                 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
104
105 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
106
107 /*
108  * Default values.
109  */
110 #define DNS_DEFAULT_IDLEIN 3600         /*%< 1 hour */
111 #define DNS_DEFAULT_IDLEOUT 3600        /*%< 1 hour */
112 #define MAX_XFER_TIME (2*3600)          /*%< Documented default is 2 hours */
113
114 #ifndef DNS_MAX_EXPIRE
115 #define DNS_MAX_EXPIRE  14515200        /*%< 24 weeks */
116 #endif
117
118 #ifndef DNS_DUMP_DELAY
119 #define DNS_DUMP_DELAY 900              /*%< 15 minutes */
120 #endif
121
122 typedef struct dns_notify dns_notify_t;
123 typedef struct dns_stub dns_stub_t;
124 typedef struct dns_load dns_load_t;
125 typedef struct dns_forward dns_forward_t;
126 typedef struct dns_io dns_io_t;
127 typedef ISC_LIST(dns_io_t) dns_iolist_t;
128 typedef struct dns_signing dns_signing_t;
129 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
130 typedef struct dns_nsec3chain dns_nsec3chain_t;
131 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
132
133 #define DNS_ZONE_CHECKLOCK
134 #ifdef DNS_ZONE_CHECKLOCK
135 #define LOCK_ZONE(z) \
136          do { LOCK(&(z)->lock); \
137               INSIST((z)->locked == ISC_FALSE); \
138              (z)->locked = ISC_TRUE; \
139                 } while (0)
140 #define UNLOCK_ZONE(z) \
141         do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
142 #define LOCKED_ZONE(z) ((z)->locked)
143 #else
144 #define LOCK_ZONE(z) LOCK(&(z)->lock)
145 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
146 #define LOCKED_ZONE(z) ISC_TRUE
147 #endif
148
149 #ifdef ISC_RWLOCK_USEATOMIC
150 #define ZONEDB_INITLOCK(l)      isc_rwlock_init((l), 0, 0)
151 #define ZONEDB_DESTROYLOCK(l)   isc_rwlock_destroy(l)
152 #define ZONEDB_LOCK(l, t)       RWLOCK((l), (t))
153 #define ZONEDB_UNLOCK(l, t)     RWUNLOCK((l), (t))
154 #else
155 #define ZONEDB_INITLOCK(l)      isc_mutex_init(l)
156 #define ZONEDB_DESTROYLOCK(l)   DESTROYLOCK(l)
157 #define ZONEDB_LOCK(l, t)       LOCK(l)
158 #define ZONEDB_UNLOCK(l, t)     UNLOCK(l)
159 #endif
160
161 struct dns_zone {
162         /* Unlocked */
163         unsigned int            magic;
164         isc_mutex_t             lock;
165 #ifdef DNS_ZONE_CHECKLOCK
166         isc_boolean_t           locked;
167 #endif
168         isc_mem_t               *mctx;
169         isc_refcount_t          erefs;
170
171 #ifdef ISC_RWLOCK_USEATOMIC
172         isc_rwlock_t            dblock;
173 #else
174         isc_mutex_t             dblock;
175 #endif
176         dns_db_t                *db;            /* Locked by dblock */
177
178         /* Locked */
179         dns_zonemgr_t           *zmgr;
180         ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
181         isc_timer_t             *timer;
182         unsigned int            irefs;
183         dns_name_t              origin;
184         char                    *masterfile;
185         dns_masterformat_t      masterformat;
186         char                    *journal;
187         isc_int32_t             journalsize;
188         dns_rdataclass_t        rdclass;
189         dns_zonetype_t          type;
190         unsigned int            flags;
191         unsigned int            options;
192         unsigned int            db_argc;
193         char                    **db_argv;
194         isc_time_t              expiretime;
195         isc_time_t              refreshtime;
196         isc_time_t              dumptime;
197         isc_time_t              loadtime;
198         isc_time_t              notifytime;
199         isc_time_t              resigntime;
200         isc_time_t              keywarntime;
201         isc_time_t              signingtime;
202         isc_time_t              nsec3chaintime;
203         isc_uint32_t            serial;
204         isc_uint32_t            refresh;
205         isc_uint32_t            retry;
206         isc_uint32_t            expire;
207         isc_uint32_t            minimum;
208         isc_stdtime_t           key_expiry;
209         char                    *keydirectory;
210
211         isc_uint32_t            maxrefresh;
212         isc_uint32_t            minrefresh;
213         isc_uint32_t            maxretry;
214         isc_uint32_t            minretry;
215
216         isc_sockaddr_t          *masters;
217         dns_name_t              **masterkeynames;
218         isc_boolean_t           *mastersok;
219         unsigned int            masterscnt;
220         unsigned int            curmaster;
221         isc_sockaddr_t          masteraddr;
222         dns_notifytype_t        notifytype;
223         isc_sockaddr_t          *notify;
224         unsigned int            notifycnt;
225         isc_sockaddr_t          notifyfrom;
226         isc_task_t              *task;
227         isc_sockaddr_t          notifysrc4;
228         isc_sockaddr_t          notifysrc6;
229         isc_sockaddr_t          xfrsource4;
230         isc_sockaddr_t          xfrsource6;
231         isc_sockaddr_t          altxfrsource4;
232         isc_sockaddr_t          altxfrsource6;
233         isc_sockaddr_t          sourceaddr;
234         dns_xfrin_ctx_t         *xfr;           /* task locked */
235         dns_tsigkey_t           *tsigkey;       /* key used for xfr */
236         /* Access Control Lists */
237         dns_acl_t               *update_acl;
238         dns_acl_t               *forward_acl;
239         dns_acl_t               *notify_acl;
240         dns_acl_t               *query_acl;
241         dns_acl_t               *queryon_acl;
242         dns_acl_t               *xfr_acl;
243         isc_boolean_t           update_disabled;
244         isc_boolean_t           zero_no_soa_ttl;
245         dns_severity_t          check_names;
246         ISC_LIST(dns_notify_t)  notifies;
247         dns_request_t           *request;
248         dns_loadctx_t           *lctx;
249         dns_io_t                *readio;
250         dns_dumpctx_t           *dctx;
251         dns_io_t                *writeio;
252         isc_uint32_t            maxxfrin;
253         isc_uint32_t            maxxfrout;
254         isc_uint32_t            idlein;
255         isc_uint32_t            idleout;
256         isc_event_t             ctlevent;
257         dns_ssutable_t          *ssutable;
258         isc_uint32_t            sigvalidityinterval;
259         isc_uint32_t            sigresigninginterval;
260         dns_view_t              *view;
261         dns_acache_t            *acache;
262         dns_checkmxfunc_t       checkmx;
263         dns_checksrvfunc_t      checksrv;
264         dns_checknsfunc_t       checkns;
265         /*%
266          * Zones in certain states such as "waiting for zone transfer"
267          * or "zone transfer in progress" are kept on per-state linked lists
268          * in the zone manager using the 'statelink' field.  The 'statelist'
269          * field points at the list the zone is currently on.  It the zone
270          * is not on any such list, statelist is NULL.
271          */
272         ISC_LINK(dns_zone_t)    statelink;
273         dns_zonelist_t          *statelist;
274         /*%
275          * Statistics counters about zone management.
276          */
277         isc_stats_t             *stats;
278         /*%
279          * Optional per-zone statistics counters.  Counted outside of this
280          * module.
281          */
282         isc_boolean_t           requeststats_on;
283         isc_stats_t             *requeststats;
284         isc_uint32_t            notifydelay;
285         dns_isselffunc_t        isself;
286         void                    *isselfarg;
287
288         char *                  strnamerd;
289         char *                  strname;
290         char *                  strrdclass;
291         char *                  strviewname;
292
293         /*%
294          * Serial number for deferred journal compaction.
295          */
296         isc_uint32_t            compact_serial;
297         /*%
298          * Keys that are signing the zone for the first time.
299          */
300         dns_signinglist_t       signing;
301         dns_nsec3chainlist_t    nsec3chain;
302         /*%
303          * Signing / re-signing quantum stopping parameters.
304          */
305         isc_uint32_t            signatures;
306         isc_uint32_t            nodes;
307         dns_rdatatype_t         privatetype;
308 };
309
310 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
311 #define DNS_ZONE_SETFLAG(z,f) do { \
312                 INSIST(LOCKED_ZONE(z)); \
313                 (z)->flags |= (f); \
314                 } while (0)
315 #define DNS_ZONE_CLRFLAG(z,f) do { \
316                 INSIST(LOCKED_ZONE(z)); \
317                 (z)->flags &= ~(f); \
318                 } while (0)
319         /* XXX MPA these may need to go back into zone.h */
320 #define DNS_ZONEFLG_REFRESH     0x00000001U     /*%< refresh check in progress */
321 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /*%< zone need consolidation */
322 #define DNS_ZONEFLG_USEVC       0x00000004U     /*%< use tcp for refresh query */
323 #define DNS_ZONEFLG_DUMPING     0x00000008U     /*%< a dump is in progress */
324 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /*%< $INCLUDE in zone file */
325 #define DNS_ZONEFLG_LOADED      0x00000020U     /*%< database has loaded */
326 #define DNS_ZONEFLG_EXITING     0x00000040U     /*%< zone is being destroyed */
327 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /*%< zone has expired */
328 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /*%< refresh check needed */
329 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /*%< zone contents are
330                                                  * uptodate */
331 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /*%< need to send out notify
332                                                  * messages */
333 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /*%< generate a journal diff on
334                                                  * reload */
335 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /*%< an attempt to refresh a
336                                                  * zone with no masters
337                                                  * occurred */
338 #define DNS_ZONEFLG_LOADING     0x00002000U     /*%< load from disk in progress*/
339 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /*%< timer values have been set
340                                                  * from SOA (if not set, we
341                                                  * are still using
342                                                  * default timer values) */
343 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
344 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
345 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
346 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
347 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
348 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /*%< IXFR failed, force AXFR */
349 #define DNS_ZONEFLG_FLUSH       0x00200000U
350 #define DNS_ZONEFLG_NOEDNS      0x00400000U
351 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
352 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
353 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
354
355 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
356
357 /* Flags for zone_load() */
358 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
359
360 #define UNREACH_CHACHE_SIZE     10U
361 #define UNREACH_HOLD_TIME       600     /* 10 minutes */
362
363 #define CHECK(op) \
364         do { result = (op); \
365                 if (result != ISC_R_SUCCESS) goto failure; \
366         } while (0)
367
368 struct dns_unreachable {
369         isc_sockaddr_t  remote;
370         isc_sockaddr_t  local;
371         isc_uint32_t    expire;
372         isc_uint32_t    last;
373 };
374
375 struct dns_zonemgr {
376         unsigned int            magic;
377         isc_mem_t *             mctx;
378         int                     refs;           /* Locked by rwlock */
379         isc_taskmgr_t *         taskmgr;
380         isc_timermgr_t *        timermgr;
381         isc_socketmgr_t *       socketmgr;
382         isc_taskpool_t *        zonetasks;
383         isc_task_t *            task;
384         isc_ratelimiter_t *     rl;
385         isc_rwlock_t            rwlock;
386         isc_mutex_t             iolock;
387
388         /* Locked by rwlock. */
389         dns_zonelist_t          zones;
390         dns_zonelist_t          waiting_for_xfrin;
391         dns_zonelist_t          xfrin_in_progress;
392
393         /* Configuration data. */
394         isc_uint32_t            transfersin;
395         isc_uint32_t            transfersperns;
396         unsigned int            serialqueryrate;
397
398         /* Locked by iolock */
399         isc_uint32_t            iolimit;
400         isc_uint32_t            ioactive;
401         dns_iolist_t            high;
402         dns_iolist_t            low;
403
404         /* Locked by rwlock. */
405         /* LRU cache */
406         struct dns_unreachable  unreachable[UNREACH_CHACHE_SIZE];
407 };
408
409 /*%
410  * Hold notify state.
411  */
412 struct dns_notify {
413         unsigned int            magic;
414         unsigned int            flags;
415         isc_mem_t               *mctx;
416         dns_zone_t              *zone;
417         dns_adbfind_t           *find;
418         dns_request_t           *request;
419         dns_name_t              ns;
420         isc_sockaddr_t          dst;
421         ISC_LINK(dns_notify_t)  link;
422 };
423
424 #define DNS_NOTIFY_NOSOA        0x0001U
425
426 /*%
427  *      dns_stub holds state while performing a 'stub' transfer.
428  *      'db' is the zone's 'db' or a new one if this is the initial
429  *      transfer.
430  */
431
432 struct dns_stub {
433         unsigned int            magic;
434         isc_mem_t               *mctx;
435         dns_zone_t              *zone;
436         dns_db_t                *db;
437         dns_dbversion_t         *version;
438 };
439
440 /*%
441  *      Hold load state.
442  */
443 struct dns_load {
444         unsigned int            magic;
445         isc_mem_t               *mctx;
446         dns_zone_t              *zone;
447         dns_db_t                *db;
448         isc_time_t              loadtime;
449         dns_rdatacallbacks_t    callbacks;
450 };
451
452 /*%
453  *      Hold forward state.
454  */
455 struct dns_forward {
456         unsigned int            magic;
457         isc_mem_t               *mctx;
458         dns_zone_t              *zone;
459         isc_buffer_t            *msgbuf;
460         dns_request_t           *request;
461         isc_uint32_t            which;
462         isc_sockaddr_t          addr;
463         dns_updatecallback_t    callback;
464         void                    *callback_arg;
465 };
466
467 /*%
468  *      Hold IO request state.
469  */
470 struct dns_io {
471         unsigned int    magic;
472         dns_zonemgr_t   *zmgr;
473         isc_boolean_t   high;
474         isc_task_t      *task;
475         ISC_LINK(dns_io_t) link;
476         isc_event_t     *event;
477 };
478
479 /*%
480  *      Hold state for when we are signing a zone with a new
481  *      DNSKEY as result of an update.
482  */
483 struct dns_signing {
484         unsigned int            magic;
485         dns_db_t                *db;
486         dns_dbiterator_t        *dbiterator;
487         dns_secalg_t            algorithm;
488         isc_uint16_t            keyid;
489         isc_boolean_t           delete;
490         isc_boolean_t           done;
491         ISC_LINK(dns_signing_t) link;
492 };
493
494 struct dns_nsec3chain {
495         unsigned int                    magic;
496         dns_db_t                        *db;
497         dns_dbiterator_t                *dbiterator;
498         dns_rdata_nsec3param_t          nsec3param;
499         unsigned char                   salt[255];
500         isc_boolean_t                   done;
501         isc_boolean_t                   seen_nsec;
502         isc_boolean_t                   delete_nsec;
503         isc_boolean_t                   save_delete_nsec;
504         ISC_LINK(dns_nsec3chain_t)      link;
505 };
506 /*%<
507  * 'dbiterator' contains a iterator for the database.  If we are creating
508  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
509  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
510  * iterated.
511  *
512  * 'nsec3param' contains the parameters of the NSEC3 chain being created
513  * or removed.
514  *
515  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
516  *
517  * 'seen_nsec' will be set to true if, while iterating the zone to create a
518  * NSEC3 chain, a NSEC record is seen.
519  *
520  * 'delete_nsec' will be set to true if, at the completion of the creation
521  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
522  * are in the process of deleting the NSEC chain.
523  *
524  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
525  * so it can be recovered in the event of a error.
526  */
527
528
529 #define SEND_BUFFER_SIZE 2048
530
531 static void zone_settimer(dns_zone_t *, isc_time_t *);
532 static void cancel_refresh(dns_zone_t *);
533 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
534                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
535 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
536      ISC_FORMAT_PRINTF(3, 4);
537 static void queue_xfrin(dns_zone_t *zone);
538 static void zone_unload(dns_zone_t *zone);
539 static void zone_expire(dns_zone_t *zone);
540 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
541 static void zone_idetach(dns_zone_t **zonep);
542 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
543                                    isc_boolean_t dump);
544 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
545 static inline void zone_detachdb(dns_zone_t *zone);
546 static isc_result_t default_journal(dns_zone_t *zone);
547 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
548 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
549                                   isc_time_t loadtime, isc_result_t result);
550 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
551 static void zone_shutdown(isc_task_t *, isc_event_t *);
552 static void zone_loaddone(void *arg, isc_result_t result);
553 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
554                                    isc_time_t loadtime);
555 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
556 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
557 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
558 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
559
560 #if 0
561 /* ondestroy example */
562 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
563 #endif
564
565 static void refresh_callback(isc_task_t *, isc_event_t *);
566 static void stub_callback(isc_task_t *, isc_event_t *);
567 static void queue_soa_query(dns_zone_t *zone);
568 static void soa_query(isc_task_t *, isc_event_t *);
569 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
570                      dns_stub_t *stub);
571 static int message_count(dns_message_t *msg, dns_section_t section,
572                          dns_rdatatype_t type);
573 static void notify_cancel(dns_zone_t *zone);
574 static void notify_find_address(dns_notify_t *notify);
575 static void notify_send(dns_notify_t *notify);
576 static isc_result_t notify_createmessage(dns_zone_t *zone,
577                                          unsigned int flags,
578                                          dns_message_t **messagep);
579 static void notify_done(isc_task_t *task, isc_event_t *event);
580 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
581 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
582 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
583 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
584                                              dns_zone_t *zone);
585 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
586 static void zonemgr_free(dns_zonemgr_t *zmgr);
587 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
588                                   isc_task_t *task, isc_taskaction_t action,
589                                   void *arg, dns_io_t **iop);
590 static void zonemgr_putio(dns_io_t **iop);
591 static void zonemgr_cancelio(dns_io_t *io);
592
593 static isc_result_t
594 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
595                  unsigned int *soacount, isc_uint32_t *serial,
596                  isc_uint32_t *refresh, isc_uint32_t *retry,
597                  isc_uint32_t *expire, isc_uint32_t *minimum,
598                  unsigned int *errors);
599
600 static void zone_freedbargs(dns_zone_t *zone);
601 static void forward_callback(isc_task_t *task, isc_event_t *event);
602 static void zone_saveunique(dns_zone_t *zone, const char *path,
603                             const char *templat);
604 static void zone_maintenance(dns_zone_t *zone);
605 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
606 static void dump_done(void *arg, isc_result_t result);
607 static isc_boolean_t dns_zonemgr_unreachable(dns_zonemgr_t *zmgr,
608                                              isc_sockaddr_t *remote,
609                                              isc_sockaddr_t *local,
610                                              isc_time_t *now);
611 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
612                                      isc_uint16_t keyid, isc_boolean_t delete);
613
614 #define ENTER zone_debuglog(zone, me, 1, "enter")
615
616 static const unsigned int dbargc_default = 1;
617 static const char *dbargv_default[] = { "rbt" };
618
619 #define DNS_ZONE_JITTER_ADD(a, b, c) \
620         do { \
621                 isc_interval_t _i; \
622                 isc_uint32_t _j; \
623                 _j = isc_random_jitter((b), (b)/4); \
624                 isc_interval_set(&_i, _j, 0); \
625                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
626                         dns_zone_log(zone, ISC_LOG_WARNING, \
627                                      "epoch approaching: upgrade required: " \
628                                      "now + %s failed", #b); \
629                         isc_interval_set(&_i, _j/2, 0); \
630                         (void)isc_time_add((a), &_i, (c)); \
631                 } \
632         } while (0)
633
634 #define DNS_ZONE_TIME_ADD(a, b, c) \
635         do { \
636                 isc_interval_t _i; \
637                 isc_interval_set(&_i, (b), 0); \
638                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
639                         dns_zone_log(zone, ISC_LOG_WARNING, \
640                                      "epoch approaching: upgrade required: " \
641                                      "now + %s failed", #b); \
642                         isc_interval_set(&_i, (b)/2, 0); \
643                         (void)isc_time_add((a), &_i, (c)); \
644                 } \
645         } while (0)
646
647 /*%
648  * Increment resolver-related statistics counters.  Zone must be locked.
649  */
650 static inline void
651 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
652         if (zone->stats != NULL)
653                 isc_stats_increment(zone->stats, counter);
654 }
655
656 /***
657  ***    Public functions.
658  ***/
659
660 isc_result_t
661 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
662         isc_result_t result;
663         dns_zone_t *zone;
664         isc_time_t now;
665
666         REQUIRE(zonep != NULL && *zonep == NULL);
667         REQUIRE(mctx != NULL);
668
669         TIME_NOW(&now);
670         zone = isc_mem_get(mctx, sizeof(*zone));
671         if (zone == NULL)
672                 return (ISC_R_NOMEMORY);
673
674         zone->mctx = NULL;
675         isc_mem_attach(mctx, &zone->mctx);
676
677         result = isc_mutex_init(&zone->lock);
678         if (result != ISC_R_SUCCESS)
679                 goto free_zone;
680
681         result = ZONEDB_INITLOCK(&zone->dblock);
682         if (result != ISC_R_SUCCESS)
683                 goto free_mutex;
684
685         /* XXX MPA check that all elements are initialised */
686 #ifdef DNS_ZONE_CHECKLOCK
687         zone->locked = ISC_FALSE;
688 #endif
689         zone->db = NULL;
690         zone->zmgr = NULL;
691         ISC_LINK_INIT(zone, link);
692         result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
693         if (result != ISC_R_SUCCESS)
694                 goto free_dblock;
695         zone->irefs = 0;
696         dns_name_init(&zone->origin, NULL);
697         zone->strnamerd = NULL;
698         zone->strname = NULL;
699         zone->strrdclass = NULL;
700         zone->strviewname = NULL;
701         zone->masterfile = NULL;
702         zone->masterformat = dns_masterformat_none;
703         zone->keydirectory = NULL;
704         zone->journalsize = -1;
705         zone->journal = NULL;
706         zone->rdclass = dns_rdataclass_none;
707         zone->type = dns_zone_none;
708         zone->flags = 0;
709         zone->options = 0;
710         zone->db_argc = 0;
711         zone->db_argv = NULL;
712         isc_time_settoepoch(&zone->expiretime);
713         isc_time_settoepoch(&zone->refreshtime);
714         isc_time_settoepoch(&zone->dumptime);
715         isc_time_settoepoch(&zone->loadtime);
716         zone->notifytime = now;
717         isc_time_settoepoch(&zone->resigntime);
718         isc_time_settoepoch(&zone->keywarntime);
719         isc_time_settoepoch(&zone->signingtime);
720         isc_time_settoepoch(&zone->nsec3chaintime);
721         zone->serial = 0;
722         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
723         zone->retry = DNS_ZONE_DEFAULTRETRY;
724         zone->expire = 0;
725         zone->minimum = 0;
726         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
727         zone->minrefresh = DNS_ZONE_MINREFRESH;
728         zone->maxretry = DNS_ZONE_MAXRETRY;
729         zone->minretry = DNS_ZONE_MINRETRY;
730         zone->masters = NULL;
731         zone->masterkeynames = NULL;
732         zone->mastersok = NULL;
733         zone->masterscnt = 0;
734         zone->curmaster = 0;
735         zone->notify = NULL;
736         zone->notifytype = dns_notifytype_yes;
737         zone->notifycnt = 0;
738         zone->task = NULL;
739         zone->update_acl = NULL;
740         zone->forward_acl = NULL;
741         zone->notify_acl = NULL;
742         zone->query_acl = NULL;
743         zone->queryon_acl = NULL;
744         zone->xfr_acl = NULL;
745         zone->update_disabled = ISC_FALSE;
746         zone->zero_no_soa_ttl = ISC_TRUE;
747         zone->check_names = dns_severity_ignore;
748         zone->request = NULL;
749         zone->lctx = NULL;
750         zone->readio = NULL;
751         zone->dctx = NULL;
752         zone->writeio = NULL;
753         zone->timer = NULL;
754         zone->idlein = DNS_DEFAULT_IDLEIN;
755         zone->idleout = DNS_DEFAULT_IDLEOUT;
756         ISC_LIST_INIT(zone->notifies);
757         isc_sockaddr_any(&zone->notifysrc4);
758         isc_sockaddr_any6(&zone->notifysrc6);
759         isc_sockaddr_any(&zone->xfrsource4);
760         isc_sockaddr_any6(&zone->xfrsource6);
761         isc_sockaddr_any(&zone->altxfrsource4);
762         isc_sockaddr_any6(&zone->altxfrsource6);
763         zone->xfr = NULL;
764         zone->tsigkey = NULL;
765         zone->maxxfrin = MAX_XFER_TIME;
766         zone->maxxfrout = MAX_XFER_TIME;
767         zone->ssutable = NULL;
768         zone->sigvalidityinterval = 30 * 24 * 3600;
769         zone->sigresigninginterval = 7 * 24 * 3600;
770         zone->view = NULL;
771         zone->acache = NULL;
772         zone->checkmx = NULL;
773         zone->checksrv = NULL;
774         zone->checkns = NULL;
775         ISC_LINK_INIT(zone, statelink);
776         zone->statelist = NULL;
777         zone->stats = NULL;
778         zone->requeststats_on = ISC_FALSE;
779         zone->requeststats = NULL;
780         zone->notifydelay = 5;
781         zone->isself = NULL;
782         zone->isselfarg = NULL;
783         ISC_LIST_INIT(zone->signing);
784         ISC_LIST_INIT(zone->nsec3chain);
785         zone->signatures = 10;
786         zone->nodes = 100;
787         zone->privatetype = (dns_rdatatype_t)0xffffU;
788
789         zone->magic = ZONE_MAGIC;
790
791         /* Must be after magic is set. */
792         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
793         if (result != ISC_R_SUCCESS)
794                 goto free_erefs;
795
796         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
797                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
798                        NULL, NULL);
799         *zonep = zone;
800         return (ISC_R_SUCCESS);
801
802  free_erefs:
803         isc_refcount_decrement(&zone->erefs, NULL);
804         isc_refcount_destroy(&zone->erefs);
805
806  free_dblock:
807         ZONEDB_DESTROYLOCK(&zone->dblock);
808
809  free_mutex:
810         DESTROYLOCK(&zone->lock);
811
812  free_zone:
813         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
814         return (result);
815 }
816
817 /*
818  * Free a zone.  Because we require that there be no more
819  * outstanding events or references, no locking is necessary.
820  */
821 static void
822 zone_free(dns_zone_t *zone) {
823         isc_mem_t *mctx = NULL;
824         dns_signing_t *signing;
825         dns_nsec3chain_t *nsec3chain;
826
827         REQUIRE(DNS_ZONE_VALID(zone));
828         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
829         REQUIRE(zone->irefs == 0);
830         REQUIRE(!LOCKED_ZONE(zone));
831         REQUIRE(zone->timer == NULL);
832
833         /*
834          * Managed objects.  Order is important.
835          */
836         if (zone->request != NULL)
837                 dns_request_destroy(&zone->request); /* XXXMPA */
838         INSIST(zone->readio == NULL);
839         INSIST(zone->statelist == NULL);
840         INSIST(zone->writeio == NULL);
841
842         if (zone->task != NULL)
843                 isc_task_detach(&zone->task);
844         if (zone->zmgr != NULL)
845                 dns_zonemgr_releasezone(zone->zmgr, zone);
846
847         /* Unmanaged objects */
848         for (signing = ISC_LIST_HEAD(zone->signing);
849              signing != NULL;
850              signing = ISC_LIST_HEAD(zone->signing)) {
851                 ISC_LIST_UNLINK(zone->signing, signing, link);
852                 dns_db_detach(&signing->db);
853                 dns_dbiterator_destroy(&signing->dbiterator);
854                 isc_mem_put(zone->mctx, signing, sizeof *signing);
855         }
856         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
857              nsec3chain != NULL;
858              nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
859                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
860                 dns_db_detach(&nsec3chain->db);
861                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
862                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
863         }
864         if (zone->masterfile != NULL)
865                 isc_mem_free(zone->mctx, zone->masterfile);
866         zone->masterfile = NULL;
867         if (zone->keydirectory != NULL)
868                 isc_mem_free(zone->mctx, zone->keydirectory);
869         zone->keydirectory = NULL;
870         zone->journalsize = -1;
871         if (zone->journal != NULL)
872                 isc_mem_free(zone->mctx, zone->journal);
873         zone->journal = NULL;
874         if (zone->stats != NULL)
875                 isc_stats_detach(&zone->stats);
876         if (zone->requeststats != NULL)
877                 isc_stats_detach(&zone->requeststats);
878         if (zone->db != NULL)
879                 zone_detachdb(zone);
880         if (zone->acache != NULL)
881                 dns_acache_detach(&zone->acache);
882         zone_freedbargs(zone);
883         RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
884                       == ISC_R_SUCCESS);
885         RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
886                       == ISC_R_SUCCESS);
887         zone->check_names = dns_severity_ignore;
888         if (zone->update_acl != NULL)
889                 dns_acl_detach(&zone->update_acl);
890         if (zone->forward_acl != NULL)
891                 dns_acl_detach(&zone->forward_acl);
892         if (zone->notify_acl != NULL)
893                 dns_acl_detach(&zone->notify_acl);
894         if (zone->query_acl != NULL)
895                 dns_acl_detach(&zone->query_acl);
896         if (zone->queryon_acl != NULL)
897                 dns_acl_detach(&zone->queryon_acl);
898         if (zone->xfr_acl != NULL)
899                 dns_acl_detach(&zone->xfr_acl);
900         if (dns_name_dynamic(&zone->origin))
901                 dns_name_free(&zone->origin, zone->mctx);
902         if (zone->strnamerd != NULL)
903                 isc_mem_free(zone->mctx, zone->strnamerd);
904         if (zone->strname != NULL)
905                 isc_mem_free(zone->mctx, zone->strname);
906         if (zone->strrdclass != NULL)
907                 isc_mem_free(zone->mctx, zone->strrdclass);
908         if (zone->strviewname != NULL)
909                 isc_mem_free(zone->mctx, zone->strviewname);
910         if (zone->ssutable != NULL)
911                 dns_ssutable_detach(&zone->ssutable);
912
913         /* last stuff */
914         ZONEDB_DESTROYLOCK(&zone->dblock);
915         DESTROYLOCK(&zone->lock);
916         isc_refcount_destroy(&zone->erefs);
917         zone->magic = 0;
918         mctx = zone->mctx;
919         isc_mem_put(mctx, zone, sizeof(*zone));
920         isc_mem_detach(&mctx);
921 }
922
923 /*
924  *      Single shot.
925  */
926 void
927 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
928         char namebuf[1024];
929
930         REQUIRE(DNS_ZONE_VALID(zone));
931         REQUIRE(rdclass != dns_rdataclass_none);
932
933         /*
934          * Test and set.
935          */
936         LOCK_ZONE(zone);
937         REQUIRE(zone->rdclass == dns_rdataclass_none ||
938                 zone->rdclass == rdclass);
939         zone->rdclass = rdclass;
940
941         if (zone->strnamerd != NULL)
942                 isc_mem_free(zone->mctx, zone->strnamerd);
943         if (zone->strrdclass != NULL)
944                 isc_mem_free(zone->mctx, zone->strrdclass);
945
946         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
947         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
948         zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
949         zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
950
951         UNLOCK_ZONE(zone);
952 }
953
954 dns_rdataclass_t
955 dns_zone_getclass(dns_zone_t *zone) {
956         REQUIRE(DNS_ZONE_VALID(zone));
957
958         return (zone->rdclass);
959 }
960
961 void
962 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
963         REQUIRE(DNS_ZONE_VALID(zone));
964
965         LOCK_ZONE(zone);
966         zone->notifytype = notifytype;
967         UNLOCK_ZONE(zone);
968 }
969
970 isc_uint32_t
971 dns_zone_getserial(dns_zone_t *zone) {
972         isc_uint32_t serial;
973
974         REQUIRE(DNS_ZONE_VALID(zone));
975
976         LOCK_ZONE(zone);
977         serial = zone->serial;
978         UNLOCK_ZONE(zone);
979
980         return (serial);
981 }
982
983 /*
984  *      Single shot.
985  */
986 void
987 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
988
989         REQUIRE(DNS_ZONE_VALID(zone));
990         REQUIRE(type != dns_zone_none);
991
992         /*
993          * Test and set.
994          */
995         LOCK_ZONE(zone);
996         REQUIRE(zone->type == dns_zone_none || zone->type == type);
997         zone->type = type;
998         UNLOCK_ZONE(zone);
999 }
1000
1001 static void
1002 zone_freedbargs(dns_zone_t *zone) {
1003         unsigned int i;
1004
1005         /* Free the old database argument list. */
1006         if (zone->db_argv != NULL) {
1007                 for (i = 0; i < zone->db_argc; i++)
1008                         isc_mem_free(zone->mctx, zone->db_argv[i]);
1009                 isc_mem_put(zone->mctx, zone->db_argv,
1010                             zone->db_argc * sizeof(*zone->db_argv));
1011         }
1012         zone->db_argc = 0;
1013         zone->db_argv = NULL;
1014 }
1015
1016 isc_result_t
1017 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1018         size_t size = 0;
1019         unsigned int i;
1020         isc_result_t result = ISC_R_SUCCESS;
1021         void *mem;
1022         char **tmp, *tmp2;
1023
1024         REQUIRE(DNS_ZONE_VALID(zone));
1025         REQUIRE(argv != NULL && *argv == NULL);
1026
1027         LOCK_ZONE(zone);
1028         size = (zone->db_argc + 1) * sizeof(char *);
1029         for (i = 0; i < zone->db_argc; i++)
1030                 size += strlen(zone->db_argv[i]) + 1;
1031         mem = isc_mem_allocate(mctx, size);
1032         if (mem != NULL) {
1033                 tmp = mem;
1034                 tmp2 = mem;
1035                 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1036                 for (i = 0; i < zone->db_argc; i++) {
1037                         *tmp++ = tmp2;
1038                         strcpy(tmp2, zone->db_argv[i]);
1039                         tmp2 += strlen(tmp2) + 1;
1040                 }
1041                 *tmp = NULL;
1042         } else
1043                 result = ISC_R_NOMEMORY;
1044         UNLOCK_ZONE(zone);
1045         *argv = mem;
1046         return (result);
1047 }
1048
1049 isc_result_t
1050 dns_zone_setdbtype(dns_zone_t *zone,
1051                    unsigned int dbargc, const char * const *dbargv) {
1052         isc_result_t result = ISC_R_SUCCESS;
1053         char **new = NULL;
1054         unsigned int i;
1055
1056         REQUIRE(DNS_ZONE_VALID(zone));
1057         REQUIRE(dbargc >= 1);
1058         REQUIRE(dbargv != NULL);
1059
1060         LOCK_ZONE(zone);
1061
1062         /* Set up a new database argument list. */
1063         new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1064         if (new == NULL)
1065                 goto nomem;
1066         for (i = 0; i < dbargc; i++)
1067                 new[i] = NULL;
1068         for (i = 0; i < dbargc; i++) {
1069                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1070                 if (new[i] == NULL)
1071                         goto nomem;
1072         }
1073
1074         /* Free the old list. */
1075         zone_freedbargs(zone);
1076
1077         zone->db_argc = dbargc;
1078         zone->db_argv = new;
1079         result = ISC_R_SUCCESS;
1080         goto unlock;
1081
1082  nomem:
1083         if (new != NULL) {
1084                 for (i = 0; i < dbargc; i++)
1085                         if (new[i] != NULL)
1086                                 isc_mem_free(zone->mctx, new[i]);
1087                 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1088         }
1089         result = ISC_R_NOMEMORY;
1090
1091  unlock:
1092         UNLOCK_ZONE(zone);
1093         return (result);
1094 }
1095
1096 void
1097 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1098         char namebuf[1024];
1099         REQUIRE(DNS_ZONE_VALID(zone));
1100
1101         LOCK_ZONE(zone);
1102         if (zone->view != NULL)
1103                 dns_view_weakdetach(&zone->view);
1104         dns_view_weakattach(view, &zone->view);
1105
1106         if (zone->strviewname != NULL)
1107                 isc_mem_free(zone->mctx, zone->strviewname);
1108         if (zone->strnamerd != NULL)
1109                 isc_mem_free(zone->mctx, zone->strnamerd);
1110
1111         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1112         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1113         zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1114         zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1115
1116         UNLOCK_ZONE(zone);
1117 }
1118
1119
1120 dns_view_t *
1121 dns_zone_getview(dns_zone_t *zone) {
1122         REQUIRE(DNS_ZONE_VALID(zone));
1123
1124         return (zone->view);
1125 }
1126
1127
1128 isc_result_t
1129 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1130         isc_result_t result;
1131         char namebuf[1024];
1132
1133         REQUIRE(DNS_ZONE_VALID(zone));
1134         REQUIRE(origin != NULL);
1135
1136         LOCK_ZONE(zone);
1137         if (dns_name_dynamic(&zone->origin)) {
1138                 dns_name_free(&zone->origin, zone->mctx);
1139                 dns_name_init(&zone->origin, NULL);
1140         }
1141         result = dns_name_dup(origin, zone->mctx, &zone->origin);
1142
1143         if (zone->strnamerd != NULL)
1144                 isc_mem_free(zone->mctx, zone->strnamerd);
1145         if (zone->strname != NULL)
1146                 isc_mem_free(zone->mctx, zone->strname);
1147
1148         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1149         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1150         zone_name_tostr(zone, namebuf, sizeof namebuf);
1151         zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1152
1153         UNLOCK_ZONE(zone);
1154         return (result);
1155 }
1156
1157 void
1158 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1159         REQUIRE(DNS_ZONE_VALID(zone));
1160         REQUIRE(acache != NULL);
1161
1162         LOCK_ZONE(zone);
1163         if (zone->acache != NULL)
1164                 dns_acache_detach(&zone->acache);
1165         dns_acache_attach(acache, &zone->acache);
1166         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1167         if (zone->db != NULL) {
1168                 isc_result_t result;
1169
1170                 /*
1171                  * If the zone reuses an existing DB, the DB needs to be
1172                  * set in the acache explicitly.  We can safely ignore the
1173                  * case where the DB is already set.  If other error happens,
1174                  * the acache will not work effectively.
1175                  */
1176                 result = dns_acache_setdb(acache, zone->db);
1177                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1178                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1179                                          "dns_acache_setdb() failed: %s",
1180                                          isc_result_totext(result));
1181                 }
1182         }
1183         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1184         UNLOCK_ZONE(zone);
1185 }
1186
1187 static isc_result_t
1188 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1189         char *copy;
1190
1191         if (value != NULL) {
1192                 copy = isc_mem_strdup(zone->mctx, value);
1193                 if (copy == NULL)
1194                         return (ISC_R_NOMEMORY);
1195         } else {
1196                 copy = NULL;
1197         }
1198
1199         if (*field != NULL)
1200                 isc_mem_free(zone->mctx, *field);
1201
1202         *field = copy;
1203         return (ISC_R_SUCCESS);
1204 }
1205
1206 isc_result_t
1207 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1208         return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1209 }
1210
1211 isc_result_t
1212 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1213                   dns_masterformat_t format) {
1214         isc_result_t result = ISC_R_SUCCESS;
1215
1216         REQUIRE(DNS_ZONE_VALID(zone));
1217
1218         LOCK_ZONE(zone);
1219         result = dns_zone_setstring(zone, &zone->masterfile, file);
1220         if (result == ISC_R_SUCCESS) {
1221                 zone->masterformat = format;
1222                 result = default_journal(zone);
1223         }
1224         UNLOCK_ZONE(zone);
1225
1226         return (result);
1227 }
1228
1229 const char *
1230 dns_zone_getfile(dns_zone_t *zone) {
1231         REQUIRE(DNS_ZONE_VALID(zone));
1232
1233         return (zone->masterfile);
1234 }
1235
1236 static isc_result_t
1237 default_journal(dns_zone_t *zone) {
1238         isc_result_t result;
1239         char *journal;
1240
1241         REQUIRE(DNS_ZONE_VALID(zone));
1242         REQUIRE(LOCKED_ZONE(zone));
1243
1244         if (zone->masterfile != NULL) {
1245                 /* Calculate string length including '\0'. */
1246                 int len = strlen(zone->masterfile) + sizeof(".jnl");
1247                 journal = isc_mem_allocate(zone->mctx, len);
1248                 if (journal == NULL)
1249                         return (ISC_R_NOMEMORY);
1250                 strcpy(journal, zone->masterfile);
1251                 strcat(journal, ".jnl");
1252         } else {
1253                 journal = NULL;
1254         }
1255         result = dns_zone_setstring(zone, &zone->journal, journal);
1256         if (journal != NULL)
1257                 isc_mem_free(zone->mctx, journal);
1258         return (result);
1259 }
1260
1261 isc_result_t
1262 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1263         isc_result_t result = ISC_R_SUCCESS;
1264
1265         REQUIRE(DNS_ZONE_VALID(zone));
1266
1267         LOCK_ZONE(zone);
1268         result = dns_zone_setstring(zone, &zone->journal, journal);
1269         UNLOCK_ZONE(zone);
1270
1271         return (result);
1272 }
1273
1274 char *
1275 dns_zone_getjournal(dns_zone_t *zone) {
1276         REQUIRE(DNS_ZONE_VALID(zone));
1277
1278         return (zone->journal);
1279 }
1280
1281 /*
1282  * Return true iff the zone is "dynamic", in the sense that the zone's
1283  * master file (if any) is written by the server, rather than being
1284  * updated manually and read by the server.
1285  *
1286  * This is true for slave zones, stub zones, and zones that allow
1287  * dynamic updates either by having an update policy ("ssutable")
1288  * or an "allow-update" ACL with a value other than exactly "{ none; }".
1289  */
1290 static isc_boolean_t
1291 zone_isdynamic(dns_zone_t *zone) {
1292         REQUIRE(DNS_ZONE_VALID(zone));
1293
1294         return (ISC_TF(zone->type == dns_zone_slave ||
1295                        zone->type == dns_zone_stub ||
1296                        (!zone->update_disabled && zone->ssutable != NULL) ||
1297                        (!zone->update_disabled && zone->update_acl != NULL &&
1298                         !dns_acl_isnone(zone->update_acl))));
1299 }
1300
1301
1302 static isc_result_t
1303 zone_load(dns_zone_t *zone, unsigned int flags) {
1304         isc_result_t result;
1305         isc_time_t now;
1306         isc_time_t loadtime, filetime;
1307         dns_db_t *db = NULL;
1308
1309         REQUIRE(DNS_ZONE_VALID(zone));
1310
1311         LOCK_ZONE(zone);
1312         TIME_NOW(&now);
1313
1314         INSIST(zone->type != dns_zone_none);
1315
1316         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1317                 result = ISC_R_SUCCESS;
1318                 goto cleanup;
1319         }
1320
1321         if (zone->db != NULL && zone->masterfile == NULL) {
1322                 /*
1323                  * The zone has no master file configured, but it already
1324                  * has a database.  It could be the built-in
1325                  * version.bind. CH zone, a zone with a persistent
1326                  * database being reloaded, or maybe a zone that
1327                  * used to have a master file but whose configuration
1328                  * was changed so that it no longer has one.  Do nothing.
1329                  */
1330                 result = ISC_R_SUCCESS;
1331                 goto cleanup;
1332         }
1333
1334         if (zone->db != NULL && zone_isdynamic(zone)) {
1335                 /*
1336                  * This is a slave, stub, or dynamically updated
1337                  * zone being reloaded.  Do nothing - the database
1338                  * we already have is guaranteed to be up-to-date.
1339                  */
1340                 if (zone->type == dns_zone_master)
1341                         result = DNS_R_DYNAMIC;
1342                 else
1343                         result = ISC_R_SUCCESS;
1344                 goto cleanup;
1345         }
1346
1347
1348         /*
1349          * Store the current time before the zone is loaded, so that if the
1350          * file changes between the time of the load and the time that
1351          * zone->loadtime is set, then the file will still be reloaded
1352          * the next time dns_zone_load is called.
1353          */
1354         TIME_NOW(&loadtime);
1355
1356         /*
1357          * Don't do the load if the file that stores the zone is older
1358          * than the last time the zone was loaded.  If the zone has not
1359          * been loaded yet, zone->loadtime will be the epoch.
1360          */
1361         if (zone->masterfile != NULL) {
1362                 /*
1363                  * The file is already loaded.  If we are just doing a
1364                  * "rndc reconfig", we are done.
1365                  */
1366                 if (!isc_time_isepoch(&zone->loadtime) &&
1367                     (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1368                         result = ISC_R_SUCCESS;
1369                         goto cleanup;
1370                 }
1371
1372                 result = isc_file_getmodtime(zone->masterfile, &filetime);
1373                 if (result == ISC_R_SUCCESS) {
1374                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1375                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1376                             isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1377                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1378                                              "skipping load: master file "
1379                                              "older than last load");
1380                                 result = DNS_R_UPTODATE;
1381                                 goto cleanup;
1382                         }
1383                         loadtime = filetime;
1384                 }
1385         }
1386
1387         INSIST(zone->db_argc >= 1);
1388
1389         /*
1390          * Built in zones don't need to be reloaded.
1391          */
1392         if (zone->type == dns_zone_master &&
1393             strcmp(zone->db_argv[0], "_builtin") == 0 &&
1394             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1395                 result = ISC_R_SUCCESS;
1396                 goto cleanup;
1397         }
1398
1399         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
1400             (strcmp(zone->db_argv[0], "rbt") == 0 ||
1401              strcmp(zone->db_argv[0], "rbt64") == 0)) {
1402                 if (zone->masterfile == NULL ||
1403                     !isc_file_exists(zone->masterfile)) {
1404                         if (zone->masterfile != NULL) {
1405                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1406                                              "no master file");
1407                         }
1408                         zone->refreshtime = now;
1409                         if (zone->task != NULL)
1410                                 zone_settimer(zone, &now);
1411                         result = ISC_R_SUCCESS;
1412                         goto cleanup;
1413                 }
1414         }
1415
1416         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1417
1418         result = dns_db_create(zone->mctx, zone->db_argv[0],
1419                                &zone->origin, (zone->type == dns_zone_stub) ?
1420                                dns_dbtype_stub : dns_dbtype_zone,
1421                                zone->rdclass,
1422                                zone->db_argc - 1, zone->db_argv + 1,
1423                                &db);
1424
1425         if (result != ISC_R_SUCCESS) {
1426                 dns_zone_log(zone, ISC_LOG_ERROR,
1427                              "loading zone: creating database: %s",
1428                              isc_result_totext(result));
1429                 goto cleanup;
1430         }
1431         dns_db_settask(db, zone->task);
1432
1433         if (! dns_db_ispersistent(db)) {
1434                 if (zone->masterfile != NULL) {
1435                         result = zone_startload(db, zone, loadtime);
1436                 } else {
1437                         result = DNS_R_NOMASTERFILE;
1438                         if (zone->type == dns_zone_master) {
1439                                 dns_zone_log(zone, ISC_LOG_ERROR,
1440                                              "loading zone: "
1441                                              "no master file configured");
1442                                 goto cleanup;
1443                         }
1444                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1445                                      "no master file configured: continuing");
1446                 }
1447         }
1448
1449         if (result == DNS_R_CONTINUE) {
1450                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1451                 goto cleanup;
1452         }
1453
1454         result = zone_postload(zone, db, loadtime, result);
1455
1456  cleanup:
1457         UNLOCK_ZONE(zone);
1458         if (db != NULL)
1459                 dns_db_detach(&db);
1460         return (result);
1461 }
1462
1463 isc_result_t
1464 dns_zone_load(dns_zone_t *zone) {
1465         return (zone_load(zone, 0));
1466 }
1467
1468 isc_result_t
1469 dns_zone_loadnew(dns_zone_t *zone) {
1470         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1471 }
1472
1473 static unsigned int
1474 get_master_options(dns_zone_t *zone) {
1475         unsigned int options;
1476
1477         options = DNS_MASTER_ZONE;
1478         if (zone->type == dns_zone_slave)
1479                 options |= DNS_MASTER_SLAVE;
1480         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1481                 options |= DNS_MASTER_CHECKNS;
1482         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1483                 options |= DNS_MASTER_FATALNS;
1484         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1485                 options |= DNS_MASTER_CHECKNAMES;
1486         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1487                 options |= DNS_MASTER_CHECKNAMESFAIL;
1488         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1489                 options |= DNS_MASTER_CHECKMX;
1490         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1491                 options |= DNS_MASTER_CHECKMXFAIL;
1492         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1493                 options |= DNS_MASTER_CHECKWILDCARD;
1494         if (zone->type == dns_zone_master &&
1495             (zone->update_acl != NULL || zone->ssutable != NULL))
1496                 options |= DNS_MASTER_RESIGN;
1497         return (options);
1498 }
1499
1500 static void
1501 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1502         dns_load_t *load = event->ev_arg;
1503         isc_result_t result = ISC_R_SUCCESS;
1504         unsigned int options;
1505
1506         REQUIRE(DNS_LOAD_VALID(load));
1507
1508         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1509                 result = ISC_R_CANCELED;
1510         isc_event_free(&event);
1511         if (result == ISC_R_CANCELED)
1512                 goto fail;
1513
1514         options = get_master_options(load->zone);
1515
1516         result = dns_master_loadfileinc3(load->zone->masterfile,
1517                                          dns_db_origin(load->db),
1518                                          dns_db_origin(load->db),
1519                                          load->zone->rdclass,
1520                                          options,
1521                                          load->zone->sigresigninginterval,
1522                                          &load->callbacks, task,
1523                                          zone_loaddone, load,
1524                                          &load->zone->lctx, load->zone->mctx,
1525                                          load->zone->masterformat);
1526         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1527             result != DNS_R_SEENINCLUDE)
1528                 goto fail;
1529         return;
1530
1531  fail:
1532         zone_loaddone(load, result);
1533 }
1534
1535 static void
1536 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1537         const char me[] = "zone_gotwritehandle";
1538         dns_zone_t *zone = event->ev_arg;
1539         isc_result_t result = ISC_R_SUCCESS;
1540         dns_dbversion_t *version = NULL;
1541
1542         REQUIRE(DNS_ZONE_VALID(zone));
1543         INSIST(task == zone->task);
1544         ENTER;
1545
1546         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1547                 result = ISC_R_CANCELED;
1548         isc_event_free(&event);
1549         if (result == ISC_R_CANCELED)
1550                 goto fail;
1551
1552         LOCK_ZONE(zone);
1553         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1554         dns_db_currentversion(zone->db, &version);
1555         result = dns_master_dumpinc2(zone->mctx, zone->db, version,
1556                                      &dns_master_style_default,
1557                                      zone->masterfile, zone->task, dump_done,
1558                                      zone, &zone->dctx, zone->masterformat);
1559         dns_db_closeversion(zone->db, &version, ISC_FALSE);
1560         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1561         UNLOCK_ZONE(zone);
1562         if (result != DNS_R_CONTINUE)
1563                 goto fail;
1564         return;
1565
1566  fail:
1567         dump_done(zone, result);
1568 }
1569
1570 static isc_result_t
1571 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1572         dns_load_t *load;
1573         isc_result_t result;
1574         isc_result_t tresult;
1575         unsigned int options;
1576
1577         options = get_master_options(zone);
1578
1579         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1580                 options |= DNS_MASTER_MANYERRORS;
1581
1582         if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1583                 load = isc_mem_get(zone->mctx, sizeof(*load));
1584                 if (load == NULL)
1585                         return (ISC_R_NOMEMORY);
1586
1587                 load->mctx = NULL;
1588                 load->zone = NULL;
1589                 load->db = NULL;
1590                 load->loadtime = loadtime;
1591                 load->magic = LOAD_MAGIC;
1592
1593                 isc_mem_attach(zone->mctx, &load->mctx);
1594                 zone_iattach(zone, &load->zone);
1595                 dns_db_attach(db, &load->db);
1596                 dns_rdatacallbacks_init(&load->callbacks);
1597                 result = dns_db_beginload(db, &load->callbacks.add,
1598                                           &load->callbacks.add_private);
1599                 if (result != ISC_R_SUCCESS)
1600                         goto cleanup;
1601                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1602                                        zone_gotreadhandle, load,
1603                                        &zone->readio);
1604                 if (result != ISC_R_SUCCESS) {
1605                         /*
1606                          * We can't report multiple errors so ignore
1607                          * the result of dns_db_endload().
1608                          */
1609                         (void)dns_db_endload(load->db,
1610                                              &load->callbacks.add_private);
1611                         goto cleanup;
1612                 } else
1613                         result = DNS_R_CONTINUE;
1614         } else {
1615                 dns_rdatacallbacks_t callbacks;
1616
1617                 dns_rdatacallbacks_init(&callbacks);
1618                 result = dns_db_beginload(db, &callbacks.add,
1619                                           &callbacks.add_private);
1620                 if (result != ISC_R_SUCCESS)
1621                         return (result);
1622                 result = dns_master_loadfile3(zone->masterfile, &zone->origin,
1623                                               &zone->origin, zone->rdclass,
1624                                               options, zone->sigresigninginterval,
1625                                               &callbacks, zone->mctx,
1626                                               zone->masterformat);
1627                 tresult = dns_db_endload(db, &callbacks.add_private);
1628                 if (result == ISC_R_SUCCESS)
1629                         result = tresult;
1630         }
1631
1632         return (result);
1633
1634  cleanup:
1635         load->magic = 0;
1636         dns_db_detach(&load->db);
1637         zone_idetach(&load->zone);
1638         isc_mem_detach(&load->mctx);
1639         isc_mem_put(zone->mctx, load, sizeof(*load));
1640         return (result);
1641 }
1642
1643 static isc_boolean_t
1644 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1645               dns_name_t *owner)
1646 {
1647         isc_result_t result;
1648         char ownerbuf[DNS_NAME_FORMATSIZE];
1649         char namebuf[DNS_NAME_FORMATSIZE];
1650         char altbuf[DNS_NAME_FORMATSIZE];
1651         dns_fixedname_t fixed;
1652         dns_name_t *foundname;
1653         int level;
1654
1655         /*
1656          * Outside of zone.
1657          */
1658         if (!dns_name_issubdomain(name, &zone->origin)) {
1659                 if (zone->checkmx != NULL)
1660                         return ((zone->checkmx)(zone, name, owner));
1661                 return (ISC_TRUE);
1662         }
1663
1664         if (zone->type == dns_zone_master)
1665                 level = ISC_LOG_ERROR;
1666         else
1667                 level = ISC_LOG_WARNING;
1668
1669         dns_fixedname_init(&fixed);
1670         foundname = dns_fixedname_name(&fixed);
1671
1672         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1673                              0, 0, NULL, foundname, NULL, NULL);
1674         if (result == ISC_R_SUCCESS)
1675                 return (ISC_TRUE);
1676
1677         if (result == DNS_R_NXRRSET) {
1678                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1679                                      0, 0, NULL, foundname, NULL, NULL);
1680                 if (result == ISC_R_SUCCESS)
1681                         return (ISC_TRUE);
1682         }
1683
1684         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1685         dns_name_format(name, namebuf, sizeof namebuf);
1686         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1687             result == DNS_R_EMPTYNAME) {
1688                 dns_zone_log(zone, level,
1689                              "%s/MX '%s' has no address records (A or AAAA)",
1690                              ownerbuf, namebuf);
1691                 /* XXX950 make fatal for 9.5.0. */
1692                 return (ISC_TRUE);
1693         }
1694
1695         if (result == DNS_R_CNAME) {
1696                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1697                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1698                         level = ISC_LOG_WARNING;
1699                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1700                         dns_zone_log(zone, level,
1701                                      "%s/MX '%s' is a CNAME (illegal)",
1702                                      ownerbuf, namebuf);
1703                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1704         }
1705
1706         if (result == DNS_R_DNAME) {
1707                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1708                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1709                         level = ISC_LOG_WARNING;
1710                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
1711                         dns_name_format(foundname, altbuf, sizeof altbuf);
1712                         dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
1713                                      " '%s' (illegal)", ownerbuf, namebuf,
1714                                      altbuf);
1715                 }
1716                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1717         }
1718
1719         if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
1720                 return ((zone->checkmx)(zone, name, owner));
1721
1722         return (ISC_TRUE);
1723 }
1724
1725 static isc_boolean_t
1726 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1727                dns_name_t *owner)
1728 {
1729         isc_result_t result;
1730         char ownerbuf[DNS_NAME_FORMATSIZE];
1731         char namebuf[DNS_NAME_FORMATSIZE];
1732         char altbuf[DNS_NAME_FORMATSIZE];
1733         dns_fixedname_t fixed;
1734         dns_name_t *foundname;
1735         int level;
1736
1737         /*
1738          * "." means the services does not exist.
1739          */
1740         if (dns_name_equal(name, dns_rootname))
1741                 return (ISC_TRUE);
1742
1743         /*
1744          * Outside of zone.
1745          */
1746         if (!dns_name_issubdomain(name, &zone->origin)) {
1747                 if (zone->checksrv != NULL)
1748                         return ((zone->checksrv)(zone, name, owner));
1749                 return (ISC_TRUE);
1750         }
1751
1752         if (zone->type == dns_zone_master)
1753                 level = ISC_LOG_ERROR;
1754         else
1755                 level = ISC_LOG_WARNING;
1756
1757         dns_fixedname_init(&fixed);
1758         foundname = dns_fixedname_name(&fixed);
1759
1760         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1761                              0, 0, NULL, foundname, NULL, NULL);
1762         if (result == ISC_R_SUCCESS)
1763                 return (ISC_TRUE);
1764
1765         if (result == DNS_R_NXRRSET) {
1766                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1767                                      0, 0, NULL, foundname, NULL, NULL);
1768                 if (result == ISC_R_SUCCESS)
1769                         return (ISC_TRUE);
1770         }
1771
1772         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1773         dns_name_format(name, namebuf, sizeof namebuf);
1774         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1775             result == DNS_R_EMPTYNAME) {
1776                 dns_zone_log(zone, level,
1777                              "%s/SRV '%s' has no address records (A or AAAA)",
1778                              ownerbuf, namebuf);
1779                 /* XXX950 make fatal for 9.5.0. */
1780                 return (ISC_TRUE);
1781         }
1782
1783         if (result == DNS_R_CNAME) {
1784                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1785                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1786                         level = ISC_LOG_WARNING;
1787                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1788                         dns_zone_log(zone, level,
1789                                      "%s/SRV '%s' is a CNAME (illegal)",
1790                                      ownerbuf, namebuf);
1791                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1792         }
1793
1794         if (result == DNS_R_DNAME) {
1795                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1796                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1797                         level = ISC_LOG_WARNING;
1798                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
1799                         dns_name_format(foundname, altbuf, sizeof altbuf);
1800                         dns_zone_log(zone, level, "%s/SRV '%s' is below a "
1801                                      "DNAME '%s' (illegal)", ownerbuf, namebuf,
1802                                      altbuf);
1803                 }
1804                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1805         }
1806
1807         if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
1808                 return ((zone->checksrv)(zone, name, owner));
1809
1810         return (ISC_TRUE);
1811 }
1812
1813 static isc_boolean_t
1814 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1815                 dns_name_t *owner)
1816 {
1817         isc_boolean_t answer = ISC_TRUE;
1818         isc_result_t result, tresult;
1819         char ownerbuf[DNS_NAME_FORMATSIZE];
1820         char namebuf[DNS_NAME_FORMATSIZE];
1821         char altbuf[DNS_NAME_FORMATSIZE];
1822         dns_fixedname_t fixed;
1823         dns_name_t *foundname;
1824         dns_rdataset_t a;
1825         dns_rdataset_t aaaa;
1826         int level;
1827
1828         /*
1829          * Outside of zone.
1830          */
1831         if (!dns_name_issubdomain(name, &zone->origin)) {
1832                 if (zone->checkns != NULL)
1833                         return ((zone->checkns)(zone, name, owner, NULL, NULL));
1834                 return (ISC_TRUE);
1835         }
1836
1837         if (zone->type == dns_zone_master)
1838                 level = ISC_LOG_ERROR;
1839         else
1840                 level = ISC_LOG_WARNING;
1841
1842         dns_fixedname_init(&fixed);
1843         foundname = dns_fixedname_name(&fixed);
1844         dns_rdataset_init(&a);
1845         dns_rdataset_init(&aaaa);
1846
1847         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1848                              DNS_DBFIND_GLUEOK, 0, NULL,
1849                              foundname, &a, NULL);
1850
1851         if (result == ISC_R_SUCCESS) {
1852                 dns_rdataset_disassociate(&a);
1853                 return (ISC_TRUE);
1854         } else if (result == DNS_R_DELEGATION)
1855                 dns_rdataset_disassociate(&a);
1856
1857         if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
1858             result == DNS_R_GLUE) {
1859                 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1860                                      DNS_DBFIND_GLUEOK, 0, NULL,
1861                                      foundname, &aaaa, NULL);
1862                 if (tresult == ISC_R_SUCCESS) {
1863                         dns_rdataset_disassociate(&aaaa);
1864                         return (ISC_TRUE);
1865                 }
1866                 if (tresult == DNS_R_DELEGATION)
1867                         dns_rdataset_disassociate(&aaaa);
1868                 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
1869                         /*
1870                          * Check glue against child zone.
1871                          */
1872                         if (zone->checkns != NULL)
1873                                 answer = (zone->checkns)(zone, name, owner,
1874                                                          &a, &aaaa);
1875                         if (dns_rdataset_isassociated(&a))
1876                                 dns_rdataset_disassociate(&a);
1877                         if (dns_rdataset_isassociated(&aaaa))
1878                                 dns_rdataset_disassociate(&aaaa);
1879                         return (answer);
1880                 }
1881         } else
1882                 tresult = result;
1883
1884         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1885         dns_name_format(name, namebuf, sizeof namebuf);
1886         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1887             result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
1888                 const char *what;
1889                 isc_boolean_t required = ISC_FALSE;
1890                 if (dns_name_issubdomain(name, owner)) {
1891                         what = "REQUIRED GLUE ";
1892                         required = ISC_TRUE;
1893                  } else if (result == DNS_R_DELEGATION)
1894                         what = "SIBLING GLUE ";
1895                 else
1896                         what = "";
1897
1898                 if (result != DNS_R_DELEGATION || required ||
1899                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
1900                         dns_zone_log(zone, level, "%s/NS '%s' has no %s"
1901                                      "address records (A or AAAA)",
1902                                      ownerbuf, namebuf, what);
1903                         /*
1904                          * Log missing address record.
1905                          */
1906                         if (result == DNS_R_DELEGATION && zone->checkns != NULL)
1907                                 (void)(zone->checkns)(zone, name, owner,
1908                                                       &a, &aaaa);
1909                         /* XXX950 make fatal for 9.5.0. */
1910                         /* answer = ISC_FALSE; */
1911                 }
1912         } else if (result == DNS_R_CNAME) {
1913                 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
1914                              ownerbuf, namebuf);
1915                 /* XXX950 make fatal for 9.5.0. */
1916                 /* answer = ISC_FALSE; */
1917         } else if (result == DNS_R_DNAME) {
1918                 dns_name_format(foundname, altbuf, sizeof altbuf);
1919                 dns_zone_log(zone, level,
1920                              "%s/NS '%s' is below a DNAME '%s' (illegal)",
1921                              ownerbuf, namebuf, altbuf);
1922                 /* XXX950 make fatal for 9.5.0. */
1923                 /* answer = ISC_FALSE; */
1924         }
1925
1926         if (dns_rdataset_isassociated(&a))
1927                 dns_rdataset_disassociate(&a);
1928         if (dns_rdataset_isassociated(&aaaa))
1929                 dns_rdataset_disassociate(&aaaa);
1930         return (answer);
1931 }
1932
1933 static isc_boolean_t
1934 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
1935         dns_dbiterator_t *dbiterator = NULL;
1936         dns_dbnode_t *node = NULL;
1937         dns_rdataset_t rdataset;
1938         dns_fixedname_t fixed;
1939         dns_fixedname_t fixedbottom;
1940         dns_rdata_mx_t mx;
1941         dns_rdata_ns_t ns;
1942         dns_rdata_in_srv_t srv;
1943         dns_rdata_t rdata;
1944         dns_name_t *name;
1945         dns_name_t *bottom;
1946         isc_result_t result;
1947         isc_boolean_t ok = ISC_TRUE;
1948
1949         dns_fixedname_init(&fixed);
1950         name = dns_fixedname_name(&fixed);
1951         dns_fixedname_init(&fixedbottom);
1952         bottom = dns_fixedname_name(&fixedbottom);
1953         dns_rdataset_init(&rdataset);
1954         dns_rdata_init(&rdata);
1955
1956         result = dns_db_createiterator(db, 0, &dbiterator);
1957         if (result != ISC_R_SUCCESS)
1958                 return (ISC_TRUE);
1959
1960         result = dns_dbiterator_first(dbiterator);
1961         while (result == ISC_R_SUCCESS) {
1962                 result = dns_dbiterator_current(dbiterator, &node, name);
1963                 if (result != ISC_R_SUCCESS)
1964                         goto cleanup;
1965
1966                 /*
1967                  * Is this name visible in the zone?
1968                  */
1969                 if (!dns_name_issubdomain(name, &zone->origin) ||
1970                     (dns_name_countlabels(bottom) > 0 &&
1971                      dns_name_issubdomain(name, bottom)))
1972                         goto next;
1973
1974                 /*
1975                  * Don't check the NS records at the origin.
1976                  */
1977                 if (dns_name_equal(name, &zone->origin))
1978                         goto checkmx;
1979
1980                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
1981                                              0, 0, &rdataset, NULL);
1982                 if (result != ISC_R_SUCCESS)
1983                         goto checkmx;
1984                 /*
1985                  * Remember bottom of zone.
1986                  */
1987                 dns_name_copy(name, bottom, NULL);
1988
1989                 result = dns_rdataset_first(&rdataset);
1990                 while (result == ISC_R_SUCCESS) {
1991                         dns_rdataset_current(&rdataset, &rdata);
1992                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
1993                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
1994                         if (!zone_check_glue(zone, db, &ns.name, name))
1995                                 ok = ISC_FALSE;
1996                         dns_rdata_reset(&rdata);
1997                         result = dns_rdataset_next(&rdataset);
1998                 }
1999                 dns_rdataset_disassociate(&rdataset);
2000
2001  checkmx:
2002                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2003                                              0, 0, &rdataset, NULL);
2004                 if (result != ISC_R_SUCCESS)
2005                         goto checksrv;
2006                 result = dns_rdataset_first(&rdataset);
2007                 while (result == ISC_R_SUCCESS) {
2008                         dns_rdataset_current(&rdataset, &rdata);
2009                         result = dns_rdata_tostruct(&rdata, &mx, NULL);
2010                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2011                         if (!zone_check_mx(zone, db, &mx.mx, name))
2012                                 ok = ISC_FALSE;
2013                         dns_rdata_reset(&rdata);
2014                         result = dns_rdataset_next(&rdataset);
2015                 }
2016                 dns_rdataset_disassociate(&rdataset);
2017
2018  checksrv:
2019                 if (zone->rdclass != dns_rdataclass_in)
2020                         goto next;
2021                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2022                                              0, 0, &rdataset, NULL);
2023                 if (result != ISC_R_SUCCESS)
2024                         goto next;
2025                 result = dns_rdataset_first(&rdataset);
2026                 while (result == ISC_R_SUCCESS) {
2027                         dns_rdataset_current(&rdataset, &rdata);
2028                         result = dns_rdata_tostruct(&rdata, &srv, NULL);
2029                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2030                         if (!zone_check_srv(zone, db, &srv.target, name))
2031                                 ok = ISC_FALSE;
2032                         dns_rdata_reset(&rdata);
2033                         result = dns_rdataset_next(&rdataset);
2034                 }
2035                 dns_rdataset_disassociate(&rdataset);
2036
2037  next:
2038                 dns_db_detachnode(db, &node);
2039                 result = dns_dbiterator_next(dbiterator);
2040         }
2041
2042  cleanup:
2043         if (node != NULL)
2044                 dns_db_detachnode(db, &node);
2045         dns_dbiterator_destroy(&dbiterator);
2046
2047         return (ok);
2048 }
2049
2050 /*
2051  * OpenSSL verification of RSA keys with exponent 3 is known to be
2052  * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
2053  * if they are in use.
2054  */
2055 static void
2056 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2057         dns_dbnode_t *node = NULL;
2058         dns_dbversion_t *version = NULL;
2059         dns_rdata_dnskey_t dnskey;
2060         dns_rdata_t rdata = DNS_RDATA_INIT;
2061         dns_rdataset_t rdataset;
2062         isc_result_t result;
2063         isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2064         const char *algorithm;
2065
2066         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2067         if (result != ISC_R_SUCCESS)
2068                 goto cleanup;
2069
2070         dns_db_currentversion(db, &version);
2071         dns_rdataset_init(&rdataset);
2072         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2073                                      dns_rdatatype_none, 0, &rdataset, NULL);
2074         if (result != ISC_R_SUCCESS)
2075                 goto cleanup;
2076
2077         for (result = dns_rdataset_first(&rdataset);
2078              result == ISC_R_SUCCESS;
2079              result = dns_rdataset_next(&rdataset))
2080         {
2081                 dns_rdataset_current(&rdataset, &rdata);
2082                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2083                 INSIST(result == ISC_R_SUCCESS);
2084
2085                 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2086                      dnskey.algorithm == DST_ALG_RSAMD5) &&
2087                      dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2088                      dnskey.data[1] == 3)
2089                 {
2090                         if (dnskey.algorithm == DST_ALG_RSASHA1) {
2091                                 logit = !foundrsa;
2092                                 foundrsa = ISC_TRUE;
2093                                 algorithm = "RSASHA1";
2094                         } else {
2095                                 logit = !foundmd5;
2096                                 foundmd5 = ISC_TRUE;
2097                                 algorithm = "RSAMD5";
2098                         }
2099                         if (logit)
2100                                 dns_zone_log(zone, ISC_LOG_WARNING,
2101                                              "weak %s (%u) key found "
2102                                              "(exponent=3)", algorithm,
2103                                              dnskey.algorithm);
2104                         if (foundrsa && foundmd5)
2105                                 break;
2106                 }
2107                 dns_rdata_reset(&rdata);
2108         }
2109         dns_rdataset_disassociate(&rdataset);
2110
2111  cleanup:
2112         if (node != NULL)
2113                 dns_db_detachnode(db, &node);
2114         if (version != NULL)
2115                 dns_db_closeversion(db, &version, ISC_FALSE);
2116
2117 }
2118
2119 static void
2120 resume_signingwithkey(dns_zone_t *zone) {
2121         dns_dbnode_t *node = NULL;
2122         dns_dbversion_t *version = NULL;
2123         dns_rdata_t rdata = DNS_RDATA_INIT;
2124         dns_rdataset_t rdataset;
2125         isc_result_t result;
2126
2127         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2128         if (result != ISC_R_SUCCESS)
2129                 goto cleanup;
2130
2131         dns_db_currentversion(zone->db, &version);
2132         dns_rdataset_init(&rdataset);
2133         result = dns_db_findrdataset(zone->db, node, version,
2134                                      zone->privatetype,
2135                                      dns_rdatatype_none, 0,
2136                                      &rdataset, NULL);
2137         if (result != ISC_R_SUCCESS)
2138                 goto cleanup;
2139
2140         for (result = dns_rdataset_first(&rdataset);
2141              result == ISC_R_SUCCESS;
2142              result = dns_rdataset_next(&rdataset))
2143         {
2144                 dns_rdataset_current(&rdataset, &rdata);
2145                 if (rdata.length != 5 || rdata.data[4] != 0) {
2146                         dns_rdata_reset(&rdata);
2147                         continue;
2148                 }
2149
2150                 result = zone_signwithkey(zone, rdata.data[0],
2151                                           (rdata.data[1] << 8) | rdata.data[2],                                           ISC_TF(rdata.data[3]));
2152                 if (result != ISC_R_SUCCESS) {
2153                         dns_zone_log(zone, ISC_LOG_ERROR,
2154                                      "zone_signwithkey failed: %s",
2155                                      dns_result_totext(result));
2156                 }
2157                 dns_rdata_reset(&rdata);
2158         }
2159         dns_rdataset_disassociate(&rdataset);
2160
2161  cleanup:
2162         if (node != NULL)
2163                 dns_db_detachnode(zone->db, &node);
2164         if (version != NULL)
2165                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2166
2167 }
2168
2169 static isc_result_t
2170 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2171         dns_nsec3chain_t *nsec3chain, *current;
2172         isc_result_t result;
2173         isc_time_t now;
2174         unsigned int options = 0;
2175
2176         nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2177         if (nsec3chain == NULL)
2178                 return (ISC_R_NOMEMORY);
2179
2180         nsec3chain->magic = 0;
2181         nsec3chain->done = ISC_FALSE;
2182         nsec3chain->db = NULL;
2183         nsec3chain->dbiterator = NULL;
2184         nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2185         nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2186         nsec3chain->nsec3param.hash = nsec3param->hash;
2187         nsec3chain->nsec3param.iterations = nsec3param->iterations;
2188         nsec3chain->nsec3param.flags = nsec3param->flags;
2189         nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2190         memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2191         nsec3chain->nsec3param.salt = nsec3chain->salt;
2192         nsec3chain->seen_nsec = ISC_FALSE;
2193         nsec3chain->delete_nsec = ISC_FALSE;
2194         nsec3chain->save_delete_nsec = ISC_FALSE;
2195
2196         for (current = ISC_LIST_HEAD(zone->nsec3chain);
2197              current != NULL;
2198              current = ISC_LIST_NEXT(current, link)) {
2199                 if (current->db == zone->db &&
2200                     current->nsec3param.hash == nsec3param->hash &&
2201                     current->nsec3param.iterations == nsec3param->iterations &&
2202                     current->nsec3param.salt_length == nsec3param->salt_length
2203                     && !memcmp(current->nsec3param.salt, nsec3param->salt,
2204                                nsec3param->salt_length))
2205                         current->done = ISC_TRUE;
2206         }
2207
2208         if (zone->db != NULL) {
2209                 dns_db_attach(zone->db, &nsec3chain->db);
2210                 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2211                         options = DNS_DB_NONSEC3;
2212                 result = dns_db_createiterator(nsec3chain->db, options,
2213                                                &nsec3chain->dbiterator);
2214                 if (result == ISC_R_SUCCESS)
2215                         dns_dbiterator_first(nsec3chain->dbiterator);
2216                 if (result == ISC_R_SUCCESS) {
2217                         dns_dbiterator_pause(nsec3chain->dbiterator);
2218                         ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2219                                                nsec3chain, link);
2220                         nsec3chain = NULL;
2221                         if (isc_time_isepoch(&zone->nsec3chaintime)) {
2222                                 TIME_NOW(&now);
2223                                 zone->nsec3chaintime = now;
2224                                 if (zone->task != NULL)
2225                                         zone_settimer(zone, &now);
2226                         }
2227                 }
2228         } else
2229                 result = ISC_R_NOTFOUND;
2230
2231         if (nsec3chain != NULL) {
2232                 if (nsec3chain->db != NULL)
2233                         dns_db_detach(&nsec3chain->db);
2234                 if (nsec3chain->dbiterator != NULL)
2235                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
2236                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2237         }
2238         return (result);
2239 }
2240
2241 static void
2242 resume_addnsec3chain(dns_zone_t *zone) {
2243         dns_dbnode_t *node = NULL;
2244         dns_dbversion_t *version = NULL;
2245         dns_rdata_t rdata = DNS_RDATA_INIT;
2246         dns_rdataset_t rdataset;
2247         isc_result_t result;
2248         dns_rdata_nsec3param_t nsec3param;
2249
2250         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2251         if (result != ISC_R_SUCCESS)
2252                 goto cleanup;
2253
2254         dns_db_currentversion(zone->db, &version);
2255         dns_rdataset_init(&rdataset);
2256         result = dns_db_findrdataset(zone->db, node, version,
2257                                      dns_rdatatype_nsec3param,
2258                                      dns_rdatatype_none, 0,
2259                                      &rdataset, NULL);
2260         if (result != ISC_R_SUCCESS)
2261                 goto cleanup;
2262
2263         for (result = dns_rdataset_first(&rdataset);
2264              result == ISC_R_SUCCESS;
2265              result = dns_rdataset_next(&rdataset))
2266         {
2267                 dns_rdataset_current(&rdataset, &rdata);
2268                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2269                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2270                 if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 ||
2271                     (nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
2272                         result = zone_addnsec3chain(zone, &nsec3param);
2273                         if (result != ISC_R_SUCCESS) {
2274                                 dns_zone_log(zone, ISC_LOG_ERROR,
2275                                              "zone_addnsec3chain failed: %s",
2276                                              dns_result_totext(result));
2277                         }
2278                 }
2279                 dns_rdata_reset(&rdata);
2280         }
2281         dns_rdataset_disassociate(&rdataset);
2282
2283  cleanup:
2284         if (node != NULL)
2285                 dns_db_detachnode(zone->db, &node);
2286         if (version != NULL)
2287                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2288 }
2289
2290 static void
2291 set_resigntime(dns_zone_t *zone) {
2292         dns_rdataset_t rdataset;
2293         dns_fixedname_t fixed;
2294         char namebuf[DNS_NAME_FORMATSIZE];
2295         unsigned int resign;
2296         isc_result_t result;
2297         isc_uint32_t nanosecs;
2298
2299         dns_rdataset_init(&rdataset);
2300         dns_fixedname_init(&fixed);
2301         result  = dns_db_getsigningtime(zone->db, &rdataset,
2302                                         dns_fixedname_name(&fixed));
2303         if (result != ISC_R_SUCCESS) {
2304                 isc_time_settoepoch(&zone->resigntime);
2305                 return;
2306         }
2307         resign = rdataset.resign;
2308         dns_name_format(dns_fixedname_name(&fixed), namebuf, sizeof(namebuf));
2309         dns_rdataset_disassociate(&rdataset);
2310         isc_random_get(&nanosecs);
2311         nanosecs %= 1000000000;
2312         isc_time_set(&zone->resigntime, resign, nanosecs);
2313 }
2314
2315 static isc_result_t
2316 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
2317         dns_dbnode_t *node = NULL;
2318         dns_rdataset_t rdataset;
2319         dns_dbversion_t *version = NULL;
2320         dns_rdata_nsec3param_t nsec3param;
2321         isc_boolean_t ok = ISC_FALSE;
2322         isc_result_t result;
2323         dns_rdata_t rdata = DNS_RDATA_INIT;
2324         isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
2325                                 zone_isdynamic(zone) : ISC_FALSE;
2326
2327         dns_rdataset_init(&rdataset);
2328         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2329         if (result != ISC_R_SUCCESS) {
2330                 dns_zone_log(zone, ISC_LOG_ERROR,
2331                              "nsec3param lookup failure: %s",
2332                              dns_result_totext(result));
2333                 return (result);
2334         }
2335         dns_db_currentversion(db, &version);
2336
2337         result = dns_db_findrdataset(db, node, version,
2338                                      dns_rdatatype_nsec3param,
2339                                      dns_rdatatype_none, 0, &rdataset, NULL);
2340         if (result == ISC_R_NOTFOUND) {
2341                 result = ISC_R_SUCCESS;
2342                 goto cleanup;
2343         }
2344         if (result != ISC_R_SUCCESS) {
2345                 dns_zone_log(zone, ISC_LOG_ERROR,
2346                              "nsec3param lookup failure: %s",
2347                              dns_result_totext(result));
2348                 goto cleanup;
2349         }
2350
2351         /*
2352          * For dynamic zones we must support every algorithm so we can
2353          * regenerate all the NSEC3 chains.
2354          * For non-dynamic zones we only need to find a supported algorithm.
2355          */
2356         for (result = dns_rdataset_first(&rdataset);
2357              result == ISC_R_SUCCESS;
2358              result = dns_rdataset_next(&rdataset))
2359         {
2360                 dns_rdataset_current(&rdataset, &rdata);
2361                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2362                 dns_rdata_reset(&rdata);
2363                 INSIST(result == ISC_R_SUCCESS);
2364                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
2365                     nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
2366                 {
2367                         dns_zone_log(zone, ISC_LOG_WARNING,
2368                              "nsec3 test \"unknown\" hash algorithm found: %u",
2369                                      nsec3param.hash);
2370                         ok = ISC_TRUE;
2371                 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
2372                         if (dynamic) {
2373                                 dns_zone_log(zone, ISC_LOG_ERROR,
2374                                              "unsupported nsec3 hash algorithm"
2375                                              " in dynamic zone: %u",
2376                                              nsec3param.hash);
2377                                 result = DNS_R_BADZONE;
2378                                 /* Stop second error message. */
2379                                 ok = ISC_TRUE;
2380                                 break;
2381                         } else
2382                                 dns_zone_log(zone, ISC_LOG_WARNING,
2383                                      "unsupported nsec3 hash algorithm: %u",
2384                                              nsec3param.hash);
2385                 } else
2386                         ok = ISC_TRUE;
2387         }
2388         if (result == ISC_R_NOMORE)
2389                 result = ISC_R_SUCCESS;
2390
2391         if (!ok) {
2392                 result = DNS_R_BADZONE;
2393                 dns_zone_log(zone, ISC_LOG_ERROR,
2394                              "no supported nsec3 hash algorithm");
2395         }
2396
2397  cleanup:
2398         if (dns_rdataset_isassociated(&rdataset))
2399                 dns_rdataset_disassociate(&rdataset);
2400         dns_db_closeversion(db, &version, ISC_FALSE);
2401         dns_db_detachnode(db, &node);
2402         return (result);
2403 }
2404
2405 static isc_result_t
2406 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
2407               isc_result_t result)
2408 {
2409         unsigned int soacount = 0;
2410         unsigned int nscount = 0;
2411         unsigned int errors = 0;
2412         isc_uint32_t serial, refresh, retry, expire, minimum;
2413         isc_time_t now;
2414         isc_boolean_t needdump = ISC_FALSE;
2415         isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
2416         unsigned int options;
2417
2418         TIME_NOW(&now);
2419
2420         /*
2421          * Initiate zone transfer?  We may need a error code that
2422          * indicates that the "permanent" form does not exist.
2423          * XXX better error feedback to log.
2424          */
2425         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
2426                 if (zone->type == dns_zone_slave ||
2427                     zone->type == dns_zone_stub) {
2428                         if (result == ISC_R_FILENOTFOUND)
2429                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2430                                              "no master file");
2431                         else if (result != DNS_R_NOMASTERFILE)
2432                                 dns_zone_log(zone, ISC_LOG_ERROR,
2433                                              "loading from master file %s "
2434                                              "failed: %s",
2435                                              zone->masterfile,
2436                                              dns_result_totext(result));
2437                 } else
2438                         dns_zone_log(zone, ISC_LOG_ERROR,
2439                                      "loading from master file %s failed: %s",
2440                                      zone->masterfile,
2441                                      dns_result_totext(result));
2442                 goto cleanup;
2443         }
2444
2445         dns_zone_log(zone, ISC_LOG_DEBUG(2),
2446                      "number of nodes in database: %u",
2447                      dns_db_nodecount(db));
2448
2449         if (result == DNS_R_SEENINCLUDE)
2450                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
2451         else
2452                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
2453
2454         /*
2455          * Apply update log, if any, on initial load.
2456          */
2457         if (zone->journal != NULL &&
2458             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
2459             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2460         {
2461                 if (zone->type == dns_zone_master &&
2462                     (zone->update_acl != NULL || zone->ssutable != NULL))
2463                         options = DNS_JOURNALOPT_RESIGN;
2464                 else
2465                         options = 0;
2466                 result = dns_journal_rollforward(zone->mctx, db, options,
2467                                                  zone->journal);
2468                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
2469                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
2470                     result != ISC_R_RANGE) {
2471                         dns_zone_log(zone, ISC_LOG_ERROR,
2472                                      "journal rollforward failed: %s",
2473                                      dns_result_totext(result));
2474                         goto cleanup;
2475                 }
2476                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
2477                         dns_zone_log(zone, ISC_LOG_ERROR,
2478                                      "journal rollforward failed: "
2479                                      "journal out of sync with zone");
2480                         goto cleanup;
2481                 }
2482                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2483                              "journal rollforward completed "
2484                              "successfully: %s",
2485                              dns_result_totext(result));
2486                 if (result == ISC_R_SUCCESS)
2487                         needdump = ISC_TRUE;
2488         }
2489
2490         zone->loadtime = loadtime;
2491
2492         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
2493         /*
2494          * Obtain ns, soa and cname counts for top of zone.
2495          */
2496         INSIST(db != NULL);
2497         result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
2498                                   &refresh, &retry, &expire, &minimum,
2499                                   &errors);
2500         if (result != ISC_R_SUCCESS) {
2501                 dns_zone_log(zone, ISC_LOG_ERROR,
2502                              "could not find NS and/or SOA records");
2503         }
2504
2505         /*
2506          * Master / Slave / Stub zones require both NS and SOA records at
2507          * the top of the zone.
2508          */
2509
2510         switch (zone->type) {
2511         case dns_zone_master:
2512         case dns_zone_slave:
2513         case dns_zone_stub:
2514                 if (soacount != 1) {
2515                         dns_zone_log(zone, ISC_LOG_ERROR,
2516                                      "has %d SOA records", soacount);
2517                         result = DNS_R_BADZONE;
2518                 }
2519                 if (nscount == 0) {
2520                         dns_zone_log(zone, ISC_LOG_ERROR,
2521                                      "has no NS records");
2522                         result = DNS_R_BADZONE;
2523                 }
2524                 if (result != ISC_R_SUCCESS)
2525                         goto cleanup;
2526                 if (zone->type == dns_zone_master && errors != 0) {
2527                         result = DNS_R_BADZONE;
2528                         goto cleanup;
2529                 }
2530                 if (zone->type != dns_zone_stub) {
2531                         result = check_nsec3param(zone, db);
2532                         if (result != ISC_R_SUCCESS)
2533                                 goto cleanup;
2534                 }
2535                 if (zone->type == dns_zone_master &&
2536                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
2537                     !integrity_checks(zone, db)) {
2538                         result = DNS_R_BADZONE;
2539                         goto cleanup;
2540                 }
2541
2542                 if (zone->db != NULL) {
2543                         /*
2544                          * This is checked in zone_replacedb() for slave zones
2545                          * as they don't reload from disk.
2546                          */
2547                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
2548                             !isc_serial_gt(serial, zone->serial)) {
2549                                 isc_uint32_t serialmin, serialmax;
2550
2551                                 INSIST(zone->type == dns_zone_master);
2552
2553                                 serialmin = (zone->serial + 1) & 0xffffffffU;
2554                                 serialmax = (zone->serial + 0x7fffffffU) &
2555                                              0xffffffffU;
2556                                 dns_zone_log(zone, ISC_LOG_ERROR,
2557                                              "ixfr-from-differences: "
2558                                              "new serial (%u) out of range "
2559                                              "[%u - %u]", serial, serialmin,
2560                                              serialmax);
2561                                 result = DNS_R_BADZONE;
2562                                 goto cleanup;
2563                         } else if (!isc_serial_ge(serial, zone->serial))
2564                                 dns_zone_log(zone, ISC_LOG_ERROR,
2565                                              "zone serial has gone backwards");
2566                         else if (serial == zone->serial && !hasinclude)
2567                                 dns_zone_log(zone, ISC_LOG_ERROR,
2568                                              "zone serial unchanged. "
2569                                              "zone may fail to transfer "
2570                                              "to slaves.");
2571                 }
2572
2573                 if (zone->type == dns_zone_master &&
2574                     (zone->update_acl != NULL || zone->ssutable != NULL) &&
2575                     zone->sigresigninginterval < (3 * refresh) &&
2576                     dns_db_issecure(db))
2577                 {
2578                         dns_zone_log(zone, ISC_LOG_WARNING,
2579                                      "sig-re-signing-interval less than "
2580                                      "3 * refresh.");
2581                 }
2582
2583                 zone->serial = serial;
2584                 zone->refresh = RANGE(refresh,
2585                                       zone->minrefresh, zone->maxrefresh);
2586                 zone->retry = RANGE(retry,
2587                                     zone->minretry, zone->maxretry);
2588                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
2589                                      DNS_MAX_EXPIRE);
2590                 zone->minimum = minimum;
2591                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
2592
2593                 if (zone->type == dns_zone_slave ||
2594                     zone->type == dns_zone_stub) {
2595                         isc_time_t t;
2596                         isc_uint32_t delay;
2597
2598                         result = isc_file_getmodtime(zone->journal, &t);
2599                         if (result != ISC_R_SUCCESS)
2600                                 result = isc_file_getmodtime(zone->masterfile,
2601                                                              &t);
2602                         if (result == ISC_R_SUCCESS)
2603                                 DNS_ZONE_TIME_ADD(&t, zone->expire,
2604                                                   &zone->expiretime);
2605                         else
2606                                 DNS_ZONE_TIME_ADD(&now, zone->retry,
2607                                                   &zone->expiretime);
2608
2609                         delay = isc_random_jitter(zone->retry,
2610                                                   (zone->retry * 3) / 4);
2611                         DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
2612                         if (isc_time_compare(&zone->refreshtime,
2613                                              &zone->expiretime) >= 0)
2614                                 zone->refreshtime = now;
2615                 }
2616                 break;
2617         default:
2618                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2619                                  "unexpected zone type %d", zone->type);
2620                 result = ISC_R_UNEXPECTED;
2621                 goto cleanup;
2622         }
2623
2624         /*
2625          * Check for weak DNSKEY's.
2626          */
2627         if (zone->type == dns_zone_master)
2628                 zone_check_dnskeys(zone, db);
2629
2630 #if 0
2631         /* destroy notification example. */
2632         {
2633                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
2634                                                     DNS_EVENT_DBDESTROYED,
2635                                                     dns_zonemgr_dbdestroyed,
2636                                                     zone,
2637                                                     sizeof(isc_event_t));
2638                 dns_db_ondestroy(db, zone->task, &e);
2639         }
2640 #endif
2641
2642         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2643         if (zone->db != NULL) {
2644                 result = zone_replacedb(zone, db, ISC_FALSE);
2645                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2646                 if (result != ISC_R_SUCCESS)
2647                         goto cleanup;
2648         } else {
2649                 zone_attachdb(zone, db);
2650                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2651                 DNS_ZONE_SETFLAG(zone,
2652                                  DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
2653         }
2654         result = ISC_R_SUCCESS;
2655         if (needdump)
2656                 zone_needdump(zone, DNS_DUMP_DELAY);
2657         if (zone->task != NULL) {
2658                 if (zone->type == dns_zone_master) {
2659                         set_resigntime(zone);
2660                         resume_signingwithkey(zone);
2661                         resume_addnsec3chain(zone);
2662                 }
2663                 zone_settimer(zone, &now);
2664         }
2665
2666         if (! dns_db_ispersistent(db))
2667                 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s",
2668                              zone->serial,
2669                              dns_db_issecure(db) ? " (signed)" : "");
2670
2671         return (result);
2672
2673  cleanup:
2674         if (zone->type == dns_zone_slave ||
2675             zone->type == dns_zone_stub) {
2676                 if (zone->journal != NULL)
2677                         zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
2678                 if (zone->masterfile != NULL)
2679                         zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
2680
2681                 /* Mark the zone for immediate refresh. */
2682                 zone->refreshtime = now;
2683                 if (zone->task != NULL)
2684                         zone_settimer(zone, &now);
2685                 result = ISC_R_SUCCESS;
2686         }
2687         return (result);
2688 }
2689
2690 static isc_boolean_t
2691 exit_check(dns_zone_t *zone) {
2692
2693         REQUIRE(LOCKED_ZONE(zone));
2694
2695         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
2696             zone->irefs == 0)
2697         {
2698                 /*
2699                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
2700                  */
2701                 INSIST(isc_refcount_current(&zone->erefs) == 0);
2702                 return (ISC_TRUE);
2703         }
2704         return (ISC_FALSE);
2705 }
2706
2707 static isc_boolean_t
2708 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
2709         isc_result_t result;
2710         char namebuf[DNS_NAME_FORMATSIZE];
2711         char altbuf[DNS_NAME_FORMATSIZE];
2712         dns_fixedname_t fixed;
2713         dns_name_t *foundname;
2714         int level;
2715
2716         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
2717                 return (ISC_TRUE);
2718
2719         if (zone->type == dns_zone_master)
2720                 level = ISC_LOG_ERROR;
2721         else
2722                 level = ISC_LOG_WARNING;
2723
2724         dns_fixedname_init(&fixed);
2725         foundname = dns_fixedname_name(&fixed);
2726
2727         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2728                              0, 0, NULL, foundname, NULL, NULL);
2729         if (result == ISC_R_SUCCESS)
2730                 return (ISC_TRUE);
2731
2732         if (result == DNS_R_NXRRSET) {
2733                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2734                                      0, 0, NULL, foundname, NULL, NULL);
2735                 if (result == ISC_R_SUCCESS)
2736                         return (ISC_TRUE);
2737         }
2738
2739         dns_name_format(name, namebuf, sizeof namebuf);
2740         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2741             result == DNS_R_EMPTYNAME) {
2742                 dns_zone_log(zone, level,
2743                              "NS '%s' has no address records (A or AAAA)",
2744                              namebuf);
2745                 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2746                 return (ISC_TRUE);
2747         }
2748
2749         if (result == DNS_R_CNAME) {
2750                 dns_zone_log(zone, level, "NS '%s' is a CNAME (illegal)",
2751                              namebuf);
2752                 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2753                 return (ISC_TRUE);
2754         }
2755
2756         if (result == DNS_R_DNAME) {
2757                 dns_name_format(foundname, altbuf, sizeof altbuf);
2758                 dns_zone_log(zone, level,
2759                              "NS '%s' is below a DNAME '%s' (illegal)",
2760                              namebuf, altbuf);
2761                 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2762                 return (ISC_TRUE);
2763         }
2764
2765         return (ISC_TRUE);
2766 }
2767
2768 static isc_result_t
2769 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
2770                  dns_dbversion_t *version, unsigned int *nscount,
2771                  unsigned int *errors)
2772 {
2773         isc_result_t result;
2774         unsigned int count = 0;
2775         unsigned int ecount = 0;
2776         dns_rdataset_t rdataset;
2777         dns_rdata_t rdata;
2778         dns_rdata_ns_t ns;
2779
2780         dns_rdataset_init(&rdataset);
2781         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
2782                                      dns_rdatatype_none, 0, &rdataset, NULL);
2783         if (result == ISC_R_NOTFOUND)
2784                 goto success;
2785         if (result != ISC_R_SUCCESS)
2786                 goto invalidate_rdataset;
2787
2788         result = dns_rdataset_first(&rdataset);
2789         while (result == ISC_R_SUCCESS) {
2790                 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
2791                     (zone->type == dns_zone_master ||
2792                      zone->type == dns_zone_slave)) {
2793                         dns_rdata_init(&rdata);
2794                         dns_rdataset_current(&rdataset, &rdata);
2795                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
2796                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2797                         if (dns_name_issubdomain(&ns.name, &zone->origin) &&
2798                             !zone_check_ns(zone, db, &ns.name))
2799                                 ecount++;
2800                 }
2801                 count++;
2802                 result = dns_rdataset_next(&rdataset);
2803         }
2804         dns_rdataset_disassociate(&rdataset);
2805
2806  success:
2807         if (nscount != NULL)
2808                 *nscount = count;
2809         if (errors != NULL)
2810                 *errors = ecount;
2811
2812         result = ISC_R_SUCCESS;
2813
2814  invalidate_rdataset:
2815         dns_rdataset_invalidate(&rdataset);
2816
2817         return (result);
2818 }
2819
2820 static isc_result_t
2821 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
2822                  unsigned int *soacount,
2823                  isc_uint32_t *serial, isc_uint32_t *refresh,
2824                  isc_uint32_t *retry, isc_uint32_t *expire,
2825                  isc_uint32_t *minimum)
2826 {
2827         isc_result_t result;
2828         unsigned int count;
2829         dns_rdataset_t rdataset;
2830         dns_rdata_t rdata = DNS_RDATA_INIT;
2831         dns_rdata_soa_t soa;
2832
2833         dns_rdataset_init(&rdataset);
2834         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
2835                                      dns_rdatatype_none, 0, &rdataset, NULL);
2836         if (result == ISC_R_NOTFOUND) {
2837                 if (soacount != NULL)
2838                         *soacount = 0;
2839                 if (serial != NULL)
2840                         *serial = 0;
2841                 if (refresh != NULL)
2842                         *refresh = 0;
2843                 if (retry != NULL)
2844                         *retry = 0;
2845                 if (expire != NULL)
2846                         *expire = 0;
2847                 if (minimum != NULL)
2848                         *minimum = 0;
2849                 result = ISC_R_SUCCESS;
2850                 goto invalidate_rdataset;
2851         }
2852         if (result != ISC_R_SUCCESS)
2853                 goto invalidate_rdataset;
2854
2855         count = 0;
2856         result = dns_rdataset_first(&rdataset);
2857         while (result == ISC_R_SUCCESS) {
2858                 dns_rdata_init(&rdata);
2859                 dns_rdataset_current(&rdataset, &rdata);
2860                 count++;
2861                 if (count == 1) {
2862                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
2863                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2864                 }
2865
2866                 result = dns_rdataset_next(&rdataset);
2867                 dns_rdata_reset(&rdata);
2868         }
2869         dns_rdataset_disassociate(&rdataset);
2870
2871         if (soacount != NULL)
2872                 *soacount = count;
2873
2874         if (count > 0) {
2875                 if (serial != NULL)
2876                         *serial = soa.serial;
2877                 if (refresh != NULL)
2878                         *refresh = soa.refresh;
2879                 if (retry != NULL)
2880                         *retry = soa.retry;
2881                 if (expire != NULL)
2882                         *expire = soa.expire;
2883                 if (minimum != NULL)
2884                         *minimum = soa.minimum;
2885         }
2886
2887         result = ISC_R_SUCCESS;
2888
2889  invalidate_rdataset:
2890         dns_rdataset_invalidate(&rdataset);
2891
2892         return (result);
2893 }
2894
2895 /*
2896  * zone must be locked.
2897  */
2898 static isc_result_t
2899 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
2900                  unsigned int *soacount, isc_uint32_t *serial,
2901                  isc_uint32_t *refresh, isc_uint32_t *retry,
2902                  isc_uint32_t *expire, isc_uint32_t *minimum,
2903                  unsigned int *errors)
2904 {
2905         dns_dbversion_t *version;
2906         isc_result_t result;
2907         isc_result_t answer = ISC_R_SUCCESS;
2908         dns_dbnode_t *node;
2909
2910         REQUIRE(db != NULL);
2911         REQUIRE(zone != NULL);
2912
2913         version = NULL;
2914         dns_db_currentversion(db, &version);
2915
2916         node = NULL;
2917         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2918         if (result != ISC_R_SUCCESS) {
2919                 answer = result;
2920                 goto closeversion;
2921         }
2922
2923         if (nscount != NULL || errors != NULL) {
2924                 result = zone_count_ns_rr(zone, db, node, version,
2925                                           nscount, errors);
2926                 if (result != ISC_R_SUCCESS)
2927                         answer = result;
2928         }
2929
2930         if (soacount != NULL || serial != NULL || refresh != NULL
2931             || retry != NULL || expire != NULL || minimum != NULL) {
2932                 result = zone_load_soa_rr(db, node, version, soacount,
2933                                           serial, refresh, retry, expire,
2934                                           minimum);
2935                 if (result != ISC_R_SUCCESS)
2936                         answer = result;
2937         }
2938
2939         dns_db_detachnode(db, &node);
2940  closeversion:
2941         dns_db_closeversion(db, &version, ISC_FALSE);
2942
2943         return (answer);
2944 }
2945
2946 void
2947 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
2948         REQUIRE(DNS_ZONE_VALID(source));
2949         REQUIRE(target != NULL && *target == NULL);
2950         isc_refcount_increment(&source->erefs, NULL);
2951         *target = source;
2952 }
2953
2954 void
2955 dns_zone_detach(dns_zone_t **zonep) {
2956         dns_zone_t *zone;
2957         unsigned int refs;
2958         isc_boolean_t free_now = ISC_FALSE;
2959
2960         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
2961
2962         zone = *zonep;
2963
2964         isc_refcount_decrement(&zone->erefs, &refs);
2965
2966         if (refs == 0) {
2967                 LOCK_ZONE(zone);
2968                 /*
2969                  * We just detached the last external reference.
2970                  */
2971                 if (zone->task != NULL) {
2972                         /*
2973                          * This zone is being managed.  Post
2974                          * its control event and let it clean
2975                          * up synchronously in the context of
2976                          * its task.
2977                          */
2978                         isc_event_t *ev = &zone->ctlevent;
2979                         isc_task_send(zone->task, &ev);
2980                 } else {
2981                         /*
2982                          * This zone is not being managed; it has
2983                          * no task and can have no outstanding
2984                          * events.  Free it immediately.
2985                          */
2986                         /*
2987                          * Unmanaged zones should not have non-null views;
2988                          * we have no way of detaching from the view here
2989                          * without causing deadlock because this code is called
2990                          * with the view already locked.
2991                          */
2992                         INSIST(zone->view == NULL);
2993                         free_now = ISC_TRUE;
2994                 }
2995                 UNLOCK_ZONE(zone);
2996         }
2997         *zonep = NULL;
2998         if (free_now)
2999                 zone_free(zone);
3000 }
3001
3002 void
3003 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
3004         REQUIRE(DNS_ZONE_VALID(source));
3005         REQUIRE(target != NULL && *target == NULL);
3006         LOCK_ZONE(source);
3007         zone_iattach(source, target);
3008         UNLOCK_ZONE(source);
3009 }
3010
3011 static void
3012 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
3013
3014         /*
3015          * 'source' locked by caller.
3016          */
3017         REQUIRE(LOCKED_ZONE(source));
3018         REQUIRE(DNS_ZONE_VALID(source));
3019         REQUIRE(target != NULL && *target == NULL);
3020         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
3021         source->irefs++;
3022         INSIST(source->irefs != 0);
3023         *target = source;
3024 }
3025
3026 static void
3027 zone_idetach(dns_zone_t **zonep) {
3028         dns_zone_t *zone;
3029
3030         /*
3031          * 'zone' locked by caller.
3032          */
3033         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
3034         zone = *zonep;
3035         REQUIRE(LOCKED_ZONE(*zonep));
3036         *zonep = NULL;
3037
3038         INSIST(zone->irefs > 0);
3039         zone->irefs--;
3040         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
3041 }
3042
3043 void
3044 dns_zone_idetach(dns_zone_t **zonep) {
3045         dns_zone_t *zone;
3046         isc_boolean_t free_needed;
3047
3048         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
3049         zone = *zonep;
3050         *zonep = NULL;
3051
3052         LOCK_ZONE(zone);
3053         INSIST(zone->irefs > 0);
3054         zone->irefs--;
3055         free_needed = exit_check(zone);
3056         UNLOCK_ZONE(zone);
3057         if (free_needed)
3058                 zone_free(zone);
3059 }
3060
3061 isc_mem_t *
3062 dns_zone_getmctx(dns_zone_t *zone) {
3063         REQUIRE(DNS_ZONE_VALID(zone));
3064
3065         return (zone->mctx);
3066 }
3067
3068 dns_zonemgr_t *
3069 dns_zone_getmgr(dns_zone_t *zone) {
3070         REQUIRE(DNS_ZONE_VALID(zone));
3071
3072         return (zone->zmgr);
3073 }
3074
3075 void
3076 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
3077         REQUIRE(DNS_ZONE_VALID(zone));
3078
3079         LOCK_ZONE(zone);
3080         if (value)
3081                 DNS_ZONE_SETFLAG(zone, flags);
3082         else
3083                 DNS_ZONE_CLRFLAG(zone, flags);
3084         UNLOCK_ZONE(zone);
3085 }
3086
3087 void
3088 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
3089 {
3090         REQUIRE(DNS_ZONE_VALID(zone));
3091
3092         LOCK_ZONE(zone);
3093         if (value)
3094                 zone->options |= option;
3095         else
3096                 zone->options &= ~option;
3097         UNLOCK_ZONE(zone);
3098 }
3099
3100 unsigned int
3101 dns_zone_getoptions(dns_zone_t *zone) {
3102
3103         REQUIRE(DNS_ZONE_VALID(zone));
3104
3105         return (zone->options);
3106 }
3107
3108 isc_result_t
3109 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
3110         REQUIRE(DNS_ZONE_VALID(zone));
3111
3112         LOCK_ZONE(zone);
3113         zone->xfrsource4 = *xfrsource;
3114         UNLOCK_ZONE(zone);
3115
3116         return (ISC_R_SUCCESS);
3117 }
3118
3119 isc_sockaddr_t *
3120 dns_zone_getxfrsource4(dns_zone_t *zone) {
3121         REQUIRE(DNS_ZONE_VALID(zone));
3122         return (&zone->xfrsource4);
3123 }
3124
3125 isc_result_t
3126 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
3127         REQUIRE(DNS_ZONE_VALID(zone));
3128
3129         LOCK_ZONE(zone);
3130         zone->xfrsource6 = *xfrsource;
3131         UNLOCK_ZONE(zone);
3132
3133         return (ISC_R_SUCCESS);
3134 }
3135
3136 isc_sockaddr_t *
3137 dns_zone_getxfrsource6(dns_zone_t *zone) {
3138         REQUIRE(DNS_ZONE_VALID(zone));
3139         return (&zone->xfrsource6);
3140 }
3141
3142 isc_result_t
3143 dns_zone_setaltxfrsource4(dns_zone_t *zone,
3144                           const isc_sockaddr_t *altxfrsource)
3145 {
3146         REQUIRE(DNS_ZONE_VALID(zone));
3147
3148         LOCK_ZONE(zone);
3149         zone->altxfrsource4 = *altxfrsource;
3150         UNLOCK_ZONE(zone);
3151
3152         return (ISC_R_SUCCESS);
3153 }
3154
3155 isc_sockaddr_t *
3156 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
3157         REQUIRE(DNS_ZONE_VALID(zone));
3158         return (&zone->altxfrsource4);
3159 }
3160
3161 isc_result_t
3162 dns_zone_setaltxfrsource6(dns_zone_t *zone,
3163                           const isc_sockaddr_t *altxfrsource)
3164 {
3165         REQUIRE(DNS_ZONE_VALID(zone));
3166
3167         LOCK_ZONE(zone);
3168         zone->altxfrsource6 = *altxfrsource;
3169         UNLOCK_ZONE(zone);
3170
3171         return (ISC_R_SUCCESS);
3172 }
3173
3174 isc_sockaddr_t *
3175 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
3176         REQUIRE(DNS_ZONE_VALID(zone));
3177         return (&zone->altxfrsource6);
3178 }
3179
3180 isc_result_t
3181 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
3182         REQUIRE(DNS_ZONE_VALID(zone));
3183
3184         LOCK_ZONE(zone);
3185         zone->notifysrc4 = *notifysrc;
3186         UNLOCK_ZONE(zone);
3187
3188         return (ISC_R_SUCCESS);
3189 }
3190
3191 isc_sockaddr_t *
3192 dns_zone_getnotifysrc4(dns_zone_t *zone) {
3193         REQUIRE(DNS_ZONE_VALID(zone));
3194         return (&zone->notifysrc4);
3195 }
3196
3197 isc_result_t
3198 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
3199         REQUIRE(DNS_ZONE_VALID(zone));
3200
3201         LOCK_ZONE(zone);
3202         zone->notifysrc6 = *notifysrc;
3203         UNLOCK_ZONE(zone);
3204
3205         return (ISC_R_SUCCESS);
3206 }
3207
3208 isc_sockaddr_t *
3209 dns_zone_getnotifysrc6(dns_zone_t *zone) {
3210         REQUIRE(DNS_ZONE_VALID(zone));
3211         return (&zone->notifysrc6);
3212 }
3213
3214 isc_result_t
3215 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
3216                        isc_uint32_t count)
3217 {
3218         isc_sockaddr_t *new;
3219
3220         REQUIRE(DNS_ZONE_VALID(zone));
3221         REQUIRE(count == 0 || notify != NULL);
3222
3223         LOCK_ZONE(zone);
3224         if (zone->notify != NULL) {
3225                 isc_mem_put(zone->mctx, zone->notify,
3226                             zone->notifycnt * sizeof(*new));
3227                 zone->notify = NULL;
3228                 zone->notifycnt = 0;
3229         }
3230         if (count != 0) {
3231                 new = isc_mem_get(zone->mctx, count * sizeof(*new));
3232                 if (new == NULL) {
3233                         UNLOCK_ZONE(zone);
3234                         return (ISC_R_NOMEMORY);
3235                 }
3236                 memcpy(new, notify, count * sizeof(*new));
3237                 zone->notify = new;
3238                 zone->notifycnt = count;
3239         }
3240         UNLOCK_ZONE(zone);
3241         return (ISC_R_SUCCESS);
3242 }
3243
3244 isc_result_t
3245 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
3246                     isc_uint32_t count)
3247 {
3248         isc_result_t result;
3249
3250         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
3251         return (result);
3252 }
3253
3254 static isc_boolean_t
3255 same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
3256              isc_uint32_t count)
3257 {
3258         unsigned int i;
3259
3260         for (i = 0; i < count; i++)
3261                 if (!isc_sockaddr_equal(&old[i], &new[i]))
3262                         return (ISC_FALSE);
3263         return (ISC_TRUE);
3264 }
3265
3266 static isc_boolean_t
3267 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
3268         unsigned int i;
3269
3270         if (old == NULL && new == NULL)
3271                 return (ISC_TRUE);
3272         if (old == NULL || new == NULL)
3273                 return (ISC_FALSE);
3274
3275         for (i = 0; i < count; i++) {
3276                 if (old[i] == NULL && new[i] == NULL)
3277                         continue;
3278                 if (old[i] == NULL || new[i] == NULL ||
3279                      !dns_name_equal(old[i], new[i]))
3280                         return (ISC_FALSE);
3281         }
3282         return (ISC_TRUE);
3283 }
3284
3285 isc_result_t
3286 dns_zone_setmasterswithkeys(dns_zone_t *zone,
3287                             const isc_sockaddr_t *masters,
3288                             dns_name_t **keynames,
3289                             isc_uint32_t count)
3290 {
3291         isc_sockaddr_t *new;
3292         isc_result_t result = ISC_R_SUCCESS;
3293         dns_name_t **newname;
3294         isc_boolean_t *newok;
3295         unsigned int i;
3296
3297         REQUIRE(DNS_ZONE_VALID(zone));
3298         REQUIRE(count == 0 || masters != NULL);
3299         if (keynames != NULL) {
3300                 REQUIRE(count != 0);
3301         }
3302
3303         LOCK_ZONE(zone);
3304         /*
3305          * The refresh code assumes that 'masters' wouldn't change under it.
3306          * If it will change then kill off any current refresh in progress
3307          * and update the masters info.  If it won't change then we can just
3308          * unlock and exit.
3309          */
3310         if (count != zone->masterscnt ||
3311             !same_masters(zone->masters, masters, count) ||
3312             !same_keynames(zone->masterkeynames, keynames, count)) {
3313                 if (zone->request != NULL)
3314                         dns_request_cancel(zone->request);
3315         } else
3316                 goto unlock;
3317         if (zone->masters != NULL) {
3318                 isc_mem_put(zone->mctx, zone->masters,
3319                             zone->masterscnt * sizeof(*new));
3320                 zone->masters = NULL;
3321         }
3322         if (zone->masterkeynames != NULL) {
3323                 for (i = 0; i < zone->masterscnt; i++) {
3324                         if (zone->masterkeynames[i] != NULL) {
3325                                 dns_name_free(zone->masterkeynames[i],
3326                                               zone->mctx);
3327                                 isc_mem_put(zone->mctx,
3328                                             zone->masterkeynames[i],
3329                                             sizeof(dns_name_t));
3330                                 zone->masterkeynames[i] = NULL;
3331                         }
3332                 }
3333                 isc_mem_put(zone->mctx, zone->masterkeynames,
3334                             zone->masterscnt * sizeof(dns_name_t *));
3335                 zone->masterkeynames = NULL;
3336         }
3337         if (zone->mastersok != NULL) {
3338                 isc_mem_put(zone->mctx, zone->mastersok,
3339                             zone->masterscnt * sizeof(isc_boolean_t));
3340                 zone->mastersok = NULL;
3341         }
3342         zone->masterscnt = 0;
3343         /*
3344          * If count == 0, don't allocate any space for masters, mastersok or
3345          * keynames so internally, those pointers are NULL if count == 0
3346          */
3347         if (count == 0)
3348                 goto unlock;
3349
3350         /*
3351          * masters must contain count elements!
3352          */
3353         new = isc_mem_get(zone->mctx, count * sizeof(*new));
3354         if (new == NULL) {
3355                 result = ISC_R_NOMEMORY;
3356                 goto unlock;
3357         }
3358         memcpy(new, masters, count * sizeof(*new));
3359
3360         /*
3361          * Similarly for mastersok.
3362          */
3363         newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
3364         if (newok == NULL) {
3365                 result = ISC_R_NOMEMORY;
3366                 isc_mem_put(zone->mctx, new, count * sizeof(*new));
3367                 goto unlock;
3368         };
3369         for (i = 0; i < count; i++)
3370                 newok[i] = ISC_FALSE;
3371
3372         /*
3373          * if keynames is non-NULL, it must contain count elements!
3374          */
3375         newname = NULL;
3376         if (keynames != NULL) {
3377                 newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
3378                 if (newname == NULL) {
3379                         result = ISC_R_NOMEMORY;
3380                         isc_mem_put(zone->mctx, new, count * sizeof(*new));
3381                         isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
3382                         goto unlock;
3383                 }
3384                 for (i = 0; i < count; i++)
3385                         newname[i] = NULL;
3386                 for (i = 0; i < count; i++) {
3387                         if (keynames[i] != NULL) {
3388                                 newname[i] = isc_mem_get(zone->mctx,
3389                                                          sizeof(dns_name_t));
3390                                 if (newname[i] == NULL)
3391                                         goto allocfail;
3392                                 dns_name_init(newname[i], NULL);
3393                                 result = dns_name_dup(keynames[i], zone->mctx,
3394                                                       newname[i]);
3395                                 if (result != ISC_R_SUCCESS) {
3396                                 allocfail:
3397                                         for (i = 0; i < count; i++)
3398                                                 if (newname[i] != NULL)
3399                                                         dns_name_free(
3400                                                                newname[i],
3401                                                                zone->mctx);
3402                                         isc_mem_put(zone->mctx, new,
3403                                                     count * sizeof(*new));
3404                                         isc_mem_put(zone->mctx, newok,
3405                                                     count * sizeof(*newok));
3406                                         isc_mem_put(zone->mctx, newname,
3407                                                     count * sizeof(*newname));
3408                                         goto unlock;
3409                                 }
3410                         }
3411                 }
3412         }
3413
3414         /*
3415          * Everything is ok so attach to the zone.
3416          */
3417         zone->masters = new;
3418         zone->mastersok = newok;
3419         zone->masterkeynames = newname;
3420         zone->masterscnt = count;
3421         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
3422
3423  unlock:
3424         UNLOCK_ZONE(zone);
3425         return (result);
3426 }
3427
3428 isc_result_t
3429 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
3430         isc_result_t result = ISC_R_SUCCESS;
3431
3432         REQUIRE(DNS_ZONE_VALID(zone));
3433
3434         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3435         if (zone->db == NULL)
3436                 result = DNS_R_NOTLOADED;
3437         else
3438                 dns_db_attach(zone->db, dpb);
3439         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3440
3441         return (result);
3442 }
3443
3444 /*
3445  * Co-ordinates the starting of routine jobs.
3446  */
3447
3448 void
3449 dns_zone_maintenance(dns_zone_t *zone) {
3450         const char me[] = "dns_zone_maintenance";
3451         isc_time_t now;
3452
3453         REQUIRE(DNS_ZONE_VALID(zone));
3454         ENTER;
3455
3456         LOCK_ZONE(zone);
3457         TIME_NOW(&now);
3458         zone_settimer(zone, &now);
3459         UNLOCK_ZONE(zone);
3460 }
3461
3462 static inline isc_boolean_t
3463 was_dumping(dns_zone_t *zone) {
3464         isc_boolean_t dumping;
3465
3466         REQUIRE(LOCKED_ZONE(zone));
3467
3468         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
3469         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
3470         if (!dumping) {
3471                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3472                 isc_time_settoepoch(&zone->dumptime);
3473         }
3474         return (dumping);
3475 }
3476
3477 #define MAXZONEKEYS 10
3478
3479 static isc_result_t
3480 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3481              dns_diff_t *diff)
3482 {
3483         dns_diff_t temp_diff;
3484         isc_result_t result;
3485
3486         /*
3487          * Create a singleton diff.
3488          */
3489         dns_diff_init(diff->mctx, &temp_diff);
3490         temp_diff.resign = diff->resign;
3491         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3492
3493         /*
3494          * Apply it to the database.
3495          */
3496         result = dns_diff_apply(&temp_diff, db, ver);
3497         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3498         if (result != ISC_R_SUCCESS) {
3499                 dns_difftuple_free(tuple);
3500                 return (result);
3501         }
3502
3503         /*
3504          * Merge it into the current pending journal entry.
3505          */
3506         dns_diff_appendminimal(diff, tuple);
3507
3508         /*
3509          * Do not clear temp_diff.
3510          */
3511         return (ISC_R_SUCCESS);
3512 }
3513
3514 static isc_result_t
3515 increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver,
3516                      dns_diff_t *diff, isc_mem_t *mctx)
3517 {
3518         dns_difftuple_t *deltuple = NULL;
3519         dns_difftuple_t *addtuple = NULL;
3520         isc_uint32_t serial;
3521         isc_result_t result;
3522
3523         CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3524         CHECK(dns_difftuple_copy(deltuple, &addtuple));
3525         addtuple->op = DNS_DIFFOP_ADD;
3526
3527         serial = dns_soa_getserial(&addtuple->rdata);
3528
3529         /* RFC1982 */
3530         serial = (serial + 1) & 0xFFFFFFFF;
3531         if (serial == 0)
3532                 serial = 1;
3533
3534         dns_soa_setserial(serial, &addtuple->rdata);
3535         CHECK(do_one_tuple(&deltuple, db, ver, diff));
3536         CHECK(do_one_tuple(&addtuple, db, ver, diff));
3537         result = ISC_R_SUCCESS;
3538
3539         failure:
3540         if (addtuple != NULL)
3541                 dns_difftuple_free(&addtuple);
3542         if (deltuple != NULL)
3543                 dns_difftuple_free(&deltuple);
3544         return (result);
3545 }
3546
3547 static isc_result_t
3548 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3549               dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3550               dns_rdata_t *rdata)
3551 {
3552         dns_difftuple_t *tuple = NULL;
3553         isc_result_t result;
3554         result = dns_difftuple_create(diff->mctx, op,
3555                                       name, ttl, rdata, &tuple);
3556         if (result != ISC_R_SUCCESS)
3557                 return (result);
3558         return (do_one_tuple(&tuple, db, ver, diff));
3559 }
3560
3561 static isc_boolean_t
3562 ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) {
3563         isc_boolean_t ret = ISC_FALSE;
3564         isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE;
3565         isc_result_t result;
3566         dns_dbnode_t *node = NULL;
3567         dns_rdataset_t rdataset;
3568         dns_rdata_t rdata = DNS_RDATA_INIT;
3569         dns_rdata_dnskey_t dnskey;
3570
3571         dns_rdataset_init(&rdataset);
3572         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
3573         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
3574                                    &rdataset, NULL));
3575         CHECK(dns_rdataset_first(&rdataset));
3576         while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) {
3577                 dns_rdataset_current(&rdataset, &rdata);
3578                 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3579                 if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
3580                                  == DNS_KEYOWNER_ZONE) {
3581                         if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0)
3582                                 have_ksk = ISC_TRUE;
3583                         else
3584                                 have_nonksk = ISC_TRUE;
3585                 }
3586                 dns_rdata_reset(&rdata);
3587                 result = dns_rdataset_next(&rdataset);
3588         }
3589         if (have_ksk && have_nonksk)
3590                 ret = ISC_TRUE;
3591  failure:
3592         if (dns_rdataset_isassociated(&rdataset))
3593                 dns_rdataset_disassociate(&rdataset);
3594         if (node != NULL)
3595                 dns_db_detachnode(db, &node);
3596         return (ret);
3597 }
3598
3599 static isc_result_t
3600 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3601                isc_mem_t *mctx, unsigned int maxkeys,
3602                dst_key_t **keys, unsigned int *nkeys)
3603 {
3604         isc_result_t result;
3605         dns_dbnode_t *node = NULL;
3606         const char *directory = dns_zone_getkeydirectory(zone);
3607         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
3608         result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
3609                                           directory, mctx, maxkeys, keys,
3610                                           nkeys);
3611         if (result == ISC_R_NOTFOUND)
3612                 result = ISC_R_SUCCESS;
3613  failure:
3614         if (node != NULL)
3615                 dns_db_detachnode(db, &node);
3616         return (result);
3617 }
3618
3619 static isc_result_t
3620 offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name,
3621         dns_ttl_t ttl, dns_rdata_t *rdata)
3622 {
3623         isc_result_t result;
3624
3625         if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
3626                 return (ISC_R_SUCCESS);
3627         result = update_one_rr(db, ver, diff, DNS_DIFFOP_DELRESIGN,
3628                                name, ttl, rdata);
3629         if (result != ISC_R_SUCCESS)
3630                 return (result);
3631         rdata->flags |= DNS_RDATA_OFFLINE;
3632         result = update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
3633                                name, ttl, rdata);
3634         return (result);
3635 }
3636
3637 static void
3638 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
3639 {
3640         unsigned int delta;
3641
3642         zone->key_expiry = when;
3643         if (when <= now) {
3644                 dns_zone_log(zone, ISC_LOG_ERROR,
3645                              "DNSKEY RRSIG(s) have expired");
3646                 isc_time_settoepoch(&zone->keywarntime);
3647         } else if (when < now + 7 * 24 * 3600) {
3648                 dns_zone_log(zone, ISC_LOG_WARNING,
3649                              "DNSKEY RRSIG(s) will expire at %u",
3650                              when);     /* XXXMPA convert to date. */
3651                 delta = when - now;
3652                 delta--;                /* loop prevention */
3653                 delta /= 24 * 3600;     /* to whole days */
3654                 delta *= 24 * 3600;     /* to seconds */
3655                 isc_time_set(&zone->keywarntime, when - delta, 0);
3656         }  else {
3657                 dns_zone_log(zone, ISC_LOG_NOTICE, /* XXMPA ISC_LOG_DEBUG(1) */
3658                              "setting keywarntime to %u - 7 days",
3659                              when);     /* XXXMPA convert to date. */
3660                 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
3661         }
3662 }
3663
3664 /*
3665  * Delete expired RRsigs and any RRsigs we are about to re-sign.
3666  * See also update.c:del_keysigs().
3667  */
3668 static isc_result_t
3669 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
3670          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
3671          unsigned int nkeys, isc_stdtime_t now)
3672 {
3673         isc_result_t result;
3674         dns_dbnode_t *node = NULL;
3675         dns_rdataset_t rdataset;
3676         dns_rdata_t rdata = DNS_RDATA_INIT;
3677         unsigned int i;
3678         dns_rdata_rrsig_t rrsig;
3679         isc_boolean_t found;
3680         isc_stdtime_t warn = 0, maybe = 0;
3681
3682         dns_rdataset_init(&rdataset);
3683
3684         if (type == dns_rdatatype_nsec3)
3685                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
3686         else
3687                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
3688         if (result == ISC_R_NOTFOUND)
3689                 return (ISC_R_SUCCESS);
3690         if (result != ISC_R_SUCCESS)
3691                 goto failure;
3692         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
3693                                      (isc_stdtime_t) 0, &rdataset, NULL);
3694         dns_db_detachnode(db, &node);
3695
3696         if (result == ISC_R_NOTFOUND)
3697                 return (ISC_R_SUCCESS);
3698         if (result != ISC_R_SUCCESS)
3699                 goto failure;
3700
3701         for (result = dns_rdataset_first(&rdataset);
3702              result == ISC_R_SUCCESS;
3703              result = dns_rdataset_next(&rdataset)) {
3704                 dns_rdataset_current(&rdataset, &rdata);
3705                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
3706                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3707
3708                 if (type != dns_rdatatype_dnskey) {
3709                         result = update_one_rr(db, ver, diff,
3710                                                DNS_DIFFOP_DEL, name,
3711                                                rdataset.ttl, &rdata);
3712                         dns_rdata_reset(&rdata);
3713                         if (result != ISC_R_SUCCESS)
3714                                 break;
3715                         continue;
3716                 }
3717
3718                 /*
3719                  * RRSIG(DNSKEY) requires special processing.
3720                  */
3721                 found = ISC_FALSE;
3722                 for (i = 0; i < nkeys; i++) {
3723                         if (rrsig.algorithm == dst_key_alg(keys[i]) &&
3724                             rrsig.keyid == dst_key_id(keys[i])) {
3725                                 found = ISC_TRUE;
3726                                 /*
3727                                  * Mark offline RRSIG(DNSKEY).
3728                                  * We want the earliest offline expire time
3729                                  * iff there is a new offline signature.
3730                                  */
3731                                 if (!dst_key_isprivate(keys[i])) {
3732                                         if (warn != 0 &&
3733                                             warn > rrsig.timeexpire)
3734                                                 warn = rrsig.timeexpire;
3735                                         if (rdata.flags & DNS_RDATA_OFFLINE) {
3736                                                 if (maybe == 0 ||
3737                                                     maybe > rrsig.timeexpire)
3738                                                         maybe =
3739                                                              rrsig.timeexpire;
3740                                                 break;
3741                                         }
3742                                         if (warn == 0)
3743                                                 warn = maybe;
3744                                         if (warn == 0 ||
3745                                             warn > rrsig.timeexpire)
3746                                                 warn = rrsig.timeexpire;
3747                                         result = offline(db, ver, diff, name,
3748                                                          rdataset.ttl, &rdata);
3749                                         break;
3750                                 }
3751                                 result = update_one_rr(db, ver, diff,
3752                                                        DNS_DIFFOP_DEL,
3753                                                        name, rdataset.ttl,
3754                                                        &rdata);
3755                                 break;
3756                         }
3757                 }
3758                 /*
3759                  * If there is not a matching DNSKEY then
3760                  * delete the RRSIG.
3761                  */
3762                 if (!found)
3763                         result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3764                                                name, rdataset.ttl, &rdata);
3765                 dns_rdata_reset(&rdata);
3766                 if (result != ISC_R_SUCCESS)
3767                         break;
3768         }
3769         dns_rdataset_disassociate(&rdataset);
3770         if (result == ISC_R_NOMORE)
3771                 result = ISC_R_SUCCESS;
3772         if (warn != 0)
3773                 set_key_expiry_warning(zone, warn, now);
3774  failure:
3775         if (node != NULL)
3776                 dns_db_detachnode(db, &node);
3777         return (result);
3778 }
3779
3780 static isc_result_t
3781 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
3782          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
3783          unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
3784          isc_stdtime_t expire, isc_boolean_t check_ksk)
3785 {
3786         isc_result_t result;
3787         dns_dbnode_t *node = NULL;
3788         dns_rdataset_t rdataset;
3789         dns_rdata_t sig_rdata = DNS_RDATA_INIT;
3790         unsigned char data[1024]; /* XXX */
3791         isc_buffer_t buffer;
3792         unsigned int i;
3793
3794         dns_rdataset_init(&rdataset);
3795         isc_buffer_init(&buffer, data, sizeof(data));
3796
3797         if (type == dns_rdatatype_nsec3)
3798                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
3799         else
3800                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
3801         if (result == ISC_R_NOTFOUND)
3802                 return (ISC_R_SUCCESS);
3803         if (result != ISC_R_SUCCESS)
3804                 goto failure;
3805         result = dns_db_findrdataset(db, node, ver, type, 0,
3806                                      (isc_stdtime_t) 0, &rdataset, NULL);
3807         dns_db_detachnode(db, &node);
3808         if (result == ISC_R_NOTFOUND)
3809                 return (ISC_R_SUCCESS);
3810         if (result != ISC_R_SUCCESS)
3811                 goto failure;
3812
3813         for (i = 0; i < nkeys; i++) {
3814                 if (check_ksk && type != dns_rdatatype_dnskey &&
3815                     (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0)
3816                         continue;
3817                 if (!dst_key_isprivate(keys[i]))
3818                         continue;
3819                 /* Calculate the signature, creating a RRSIG RDATA. */
3820                 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
3821                                       &inception, &expire,
3822                                       mctx, &buffer, &sig_rdata));
3823                 /* Update the database and journal with the RRSIG. */
3824                 /* XXX inefficient - will cause dataset merging */
3825                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
3826                                     name, rdataset.ttl, &sig_rdata));
3827                 dns_rdata_reset(&sig_rdata);
3828         }
3829
3830  failure:
3831         if (dns_rdataset_isassociated(&rdataset))
3832                 dns_rdataset_disassociate(&rdataset);
3833         if (node != NULL)
3834                 dns_db_detachnode(db, &node);
3835         return (result);
3836 }
3837
3838 static void
3839 zone_resigninc(dns_zone_t *zone) {
3840         const char *journalfile;
3841         dns_db_t *db = NULL;
3842         dns_dbversion_t *version = NULL;
3843         dns_diff_t sig_diff;
3844         dns_fixedname_t fixed;
3845         dns_name_t *name;
3846         dns_rdataset_t rdataset;
3847         dns_rdatatype_t covers;
3848         dst_key_t *zone_keys[MAXZONEKEYS];
3849         isc_boolean_t check_ksk;
3850         isc_result_t result;
3851         isc_stdtime_t now, inception, soaexpire, expire, stop;
3852         isc_uint32_t jitter;
3853         unsigned int i;
3854         unsigned int nkeys = 0;
3855         unsigned int resign;
3856
3857         dns_rdataset_init(&rdataset);
3858         dns_fixedname_init(&fixed);
3859         dns_diff_init(zone->mctx, &sig_diff);
3860         sig_diff.resign = zone->sigresigninginterval;
3861
3862         /*
3863          * Updates are disabled.  Pause for 5 minutes.
3864          */
3865         if (zone->update_disabled) {
3866                 result = ISC_R_FAILURE;
3867                 goto failure;
3868         }
3869
3870         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3871         dns_db_attach(zone->db, &db);
3872         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3873
3874         result = dns_db_newversion(db, &version);
3875         if (result != ISC_R_SUCCESS) {
3876                 dns_zone_log(zone, ISC_LOG_ERROR,
3877                              "zone_resigninc:dns_db_newversion -> %s\n",
3878                              dns_result_totext(result));
3879                 goto failure;
3880         }
3881
3882         result = find_zone_keys(zone, db, version, zone->mctx, MAXZONEKEYS,
3883                                 zone_keys, &nkeys);
3884         if (result != ISC_R_SUCCESS) {
3885                 dns_zone_log(zone, ISC_LOG_ERROR,
3886                              "zone_resigninc:find_zone_keys -> %s\n",
3887                              dns_result_totext(result));
3888                 goto failure;
3889         }
3890
3891         isc_stdtime_get(&now);
3892         inception = now - 3600; /* Allow for clock skew. */
3893         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
3894         /*
3895          * Spread out signatures over time if they happen to be
3896          * clumped.  We don't do this for each add_sigs() call as
3897          * we still want some clustering to occur.
3898          */
3899         isc_random_get(&jitter);
3900         expire = soaexpire - jitter % 3600;
3901         stop = now + 5;
3902
3903         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
3904         if (check_ksk)
3905                 check_ksk = ksk_sanity(db, version);
3906
3907         name = dns_fixedname_name(&fixed);
3908         result = dns_db_getsigningtime(db, &rdataset, name);
3909         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
3910                 dns_zone_log(zone, ISC_LOG_ERROR,
3911                              "zone_resigninc:dns_db_getsigningtime -> %s\n",
3912                              dns_result_totext(result));
3913         }
3914
3915         i = 0;
3916         while (result == ISC_R_SUCCESS) {
3917                 resign = rdataset.resign;
3918                 covers = rdataset.covers;
3919                 /*
3920                  * Stop if we hit the SOA as that means we have walked the
3921                  * entire zone.  The SOA record should always be the most
3922                  * recent signature.
3923                  */
3924                 /* XXXMPA increase number of RRsets signed pre call */
3925                 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
3926                     resign > stop) {
3927                         /*
3928                          * Ensure that we don't loop resigning the SOA.
3929                          */
3930                         if (covers == dns_rdatatype_soa)
3931                                 dns_db_resigned(db, &rdataset, version);
3932                         dns_rdataset_disassociate(&rdataset);
3933                         break;
3934                 }
3935
3936                 dns_db_resigned(db, &rdataset, version);
3937                 dns_rdataset_disassociate(&rdataset);
3938
3939                 result = del_sigs(zone, db, version, name, covers, &sig_diff,
3940                                   zone_keys, nkeys, now);
3941                 if (result != ISC_R_SUCCESS) {
3942                         dns_zone_log(zone, ISC_LOG_ERROR,
3943                                      "zone_resigninc:del_sigs -> %s\n",
3944                                      dns_result_totext(result));
3945                         break;
3946                 }
3947                 result = add_sigs(db, version, name, covers, &sig_diff,
3948                                   zone_keys, nkeys, zone->mctx, inception,
3949                                   expire, check_ksk);
3950                 if (result != ISC_R_SUCCESS) {
3951                         dns_zone_log(zone, ISC_LOG_ERROR,
3952                                      "zone_resigninc:add_sigs -> %s\n",
3953                                      dns_result_totext(result));
3954                         break;
3955                 }
3956                 result  = dns_db_getsigningtime(db, &rdataset,
3957                                                 dns_fixedname_name(&fixed));
3958                 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
3959                         result = ISC_R_SUCCESS;
3960                         break;
3961                 }
3962                 if (result != ISC_R_SUCCESS)
3963                         dns_zone_log(zone, ISC_LOG_ERROR,
3964                              "zone_resigninc:dns_db_getsigningtime -> %s\n",
3965                                      dns_result_totext(result));
3966         }
3967
3968         if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
3969                 goto failure;
3970
3971         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
3972                           &sig_diff, zone_keys, nkeys, now);
3973         if (result != ISC_R_SUCCESS) {
3974                 dns_zone_log(zone, ISC_LOG_ERROR,
3975                              "zone_resigninc:del_sigs -> %s\n",
3976                              dns_result_totext(result));
3977                 goto failure;
3978         }
3979
3980         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
3981         if (result != ISC_R_SUCCESS) {
3982                 dns_zone_log(zone, ISC_LOG_ERROR,
3983                              "zone_resigninc:increment_soa_serial -> %s\n",
3984                              dns_result_totext(result));
3985                 goto failure;
3986         }
3987
3988         /*
3989          * Generate maximum life time signatures so that the above loop
3990          * termination is sensible.
3991          */
3992         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
3993                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
3994                           soaexpire, check_ksk);
3995         if (result != ISC_R_SUCCESS) {
3996                 dns_zone_log(zone, ISC_LOG_ERROR,
3997                              "zone_resigninc:add_sigs -> %s\n",
3998                              dns_result_totext(result));
3999                 goto failure;
4000         }
4001
4002         journalfile = dns_zone_getjournal(zone);
4003         if (journalfile != NULL) {
4004                 dns_journal_t *journal = NULL;
4005                 result = dns_journal_open(zone->mctx, journalfile,
4006                                           ISC_TRUE, &journal);
4007                 if (result != ISC_R_SUCCESS) {
4008                         dns_zone_log(zone, ISC_LOG_ERROR,
4009                                      "zone_resigninc:dns_journal_open -> %s\n",
4010                                      dns_result_totext(result));
4011                         goto failure;
4012                 }
4013
4014                 result = dns_journal_write_transaction(journal, &sig_diff);
4015                 dns_journal_destroy(&journal);
4016                 if (result != ISC_R_SUCCESS) {
4017                         dns_zone_log(zone, ISC_LOG_ERROR,
4018                          "zone_resigninc:dns_journal_write_transaction -> %s\n",
4019                                      dns_result_totext(result));
4020                         goto failure;
4021                 }
4022         }
4023
4024         /*
4025          * Everything has succeeded. Commit the changes.
4026          */
4027         dns_db_closeversion(db, &version, ISC_TRUE);
4028
4029  failure:
4030         dns_diff_clear(&sig_diff);
4031         for (i = 0; i < nkeys; i++)
4032                 dst_key_free(&zone_keys[i]);
4033         if (version != NULL) {
4034                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
4035                 dns_db_detach(&db);
4036         } else if (db != NULL)
4037                 dns_db_detach(&db);
4038         if (result == ISC_R_SUCCESS) {
4039                 set_resigntime(zone);
4040                 LOCK_ZONE(zone);
4041                 zone_needdump(zone, DNS_DUMP_DELAY);
4042                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
4043                 UNLOCK_ZONE(zone);
4044         } else {
4045                 /*
4046                  * Something failed.  Retry in 5 minutes.
4047                  */
4048                 isc_interval_t ival;
4049                 isc_interval_set(&ival, 300, 0);
4050                 isc_time_nowplusinterval(&zone->resigntime, &ival);
4051         }
4052 }
4053
4054 static isc_result_t
4055 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
4056             dns_name_t *newname, isc_boolean_t bottom)
4057 {
4058         isc_result_t result;
4059         dns_dbiterator_t *dbit = NULL;
4060         dns_rdatasetiter_t *rdsit = NULL;
4061         dns_dbnode_t *node = NULL;
4062
4063         CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
4064         CHECK(dns_dbiterator_seek(dbit, oldname));
4065         do {
4066                 result = dns_dbiterator_next(dbit);
4067                 if (result == ISC_R_NOMORE)
4068                         CHECK(dns_dbiterator_first(dbit));
4069                 CHECK(dns_dbiterator_current(dbit, &node, newname));
4070                 if (bottom && dns_name_issubdomain(newname, oldname) &&
4071                     !dns_name_equal(newname, oldname)) {
4072                         dns_db_detachnode(db, &node);
4073                         continue;
4074                 }
4075                 /*
4076                  * Is this node empty?
4077                  */
4078                 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
4079                 result = dns_rdatasetiter_first(rdsit);
4080                 dns_db_detachnode(db, &node);
4081                 dns_rdatasetiter_destroy(&rdsit);
4082                 if (result != ISC_R_NOMORE)
4083                         break;
4084         } while (1);
4085  failure:
4086         if (node != NULL)
4087                 dns_db_detachnode(db, &node);
4088         if (dbit != NULL)
4089                 dns_dbiterator_destroy(&dbit);
4090         return (result);
4091 }
4092
4093 static void
4094 set_bit(unsigned char *array, unsigned int index) {
4095         unsigned int shift, mask;
4096
4097         shift = 7 - (index % 8);
4098         mask = 1 << shift;
4099
4100         array[index / 8] |= mask;
4101 }
4102
4103 static isc_boolean_t
4104 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
4105                 dns_rdatatype_t type, dst_key_t *key)
4106 {
4107         isc_result_t result;
4108         dns_rdataset_t rdataset;
4109         dns_rdata_t rdata = DNS_RDATA_INIT;
4110         dns_rdata_rrsig_t rrsig;
4111
4112         dns_rdataset_init(&rdataset);
4113         result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
4114                                      type, 0, &rdataset, NULL);
4115         if (result != ISC_R_SUCCESS)
4116                 return (ISC_FALSE);
4117         for (result = dns_rdataset_first(&rdataset);
4118              result == ISC_R_SUCCESS;
4119              result = dns_rdataset_next(&rdataset)) {
4120                 dns_rdataset_current(&rdataset, &rdata);
4121                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
4122                 INSIST(result == ISC_R_SUCCESS);
4123                 if (rrsig.algorithm == dst_key_alg(key) &&
4124                     rrsig.keyid == dst_key_id(key)) {
4125                         dns_rdataset_disassociate(&rdataset);
4126                         return (ISC_TRUE);
4127                 }
4128                 dns_rdata_reset(&rdata);
4129         }
4130         dns_rdataset_disassociate(&rdataset);
4131         return (ISC_FALSE);
4132 }
4133
4134 static isc_result_t
4135 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
4136          dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
4137          dns_diff_t *diff)
4138 {
4139         dns_fixedname_t fixed;
4140         dns_name_t *next;
4141         dns_rdata_t rdata = DNS_RDATA_INIT;
4142         isc_result_t result;
4143         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
4144
4145         dns_fixedname_init(&fixed);
4146         next = dns_fixedname_name(&fixed);
4147
4148         CHECK(next_active(db, version, name, next, bottom));
4149         CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
4150                                   &rdata));
4151         if (dns_name_equal(dns_db_origin(db), name)) {
4152                 /*
4153                  * Set the OPT bit to indicate that this is a
4154                  * partially secure zone.
4155                  */
4156                 isc_region_t region;
4157
4158                 dns_rdata_toregion(&rdata, &region);
4159                 dns_name_fromregion(next, &region);
4160                 isc_region_consume(&region, next->length);
4161                 INSIST(region.length > (2 + dns_rdatatype_opt / 8) &&
4162                        region.base[0] == 0 &&
4163                        region.base[1] > dns_rdatatype_opt / 8);
4164                 set_bit(region.base + 2, dns_rdatatype_opt);
4165         }
4166         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
4167                             &rdata));
4168  failure:
4169         return (result);
4170 }
4171
4172 static isc_result_t
4173 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
4174             dns_dbversion_t *version, isc_boolean_t build_nsec3,
4175             isc_boolean_t build_nsec, dst_key_t *key,
4176             isc_stdtime_t inception, isc_stdtime_t expire,
4177             unsigned int minimum, isc_boolean_t is_ksk,
4178             isc_boolean_t *delegation, dns_diff_t *diff,
4179             isc_int32_t *signatures, isc_mem_t *mctx)
4180 {
4181         isc_result_t result;
4182         dns_rdatasetiter_t *iterator = NULL;
4183         dns_rdataset_t rdataset;
4184         dns_rdata_t rdata = DNS_RDATA_INIT;
4185         isc_buffer_t buffer;
4186         unsigned char data[1024];
4187         isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
4188                       seen_nsec3, seen_ds;
4189         isc_boolean_t bottom;
4190
4191         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
4192         if (result != ISC_R_SUCCESS) {
4193                 if (result == ISC_R_NOTFOUND)
4194                         result = ISC_R_SUCCESS;
4195                 return (result);
4196         }
4197         dns_rdataset_init(&rdataset);
4198         isc_buffer_init(&buffer, data, sizeof(data));
4199         seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
4200         seen_nsec3 = seen_ds = ISC_FALSE;
4201         for (result = dns_rdatasetiter_first(iterator);
4202              result == ISC_R_SUCCESS;
4203              result = dns_rdatasetiter_next(iterator)) {
4204                 dns_rdatasetiter_current(iterator, &rdataset);
4205                 if (rdataset.type == dns_rdatatype_soa)
4206                         seen_soa = ISC_TRUE;
4207                 else if (rdataset.type == dns_rdatatype_ns)
4208                         seen_ns = ISC_TRUE;
4209                 else if (rdataset.type == dns_rdatatype_ds)
4210                         seen_ds = ISC_TRUE;
4211                 else if (rdataset.type == dns_rdatatype_dname)
4212                         seen_dname = ISC_TRUE;
4213                 else if (rdataset.type == dns_rdatatype_nsec)
4214                         seen_nsec = ISC_TRUE;
4215                 else if (rdataset.type == dns_rdatatype_nsec3)
4216                         seen_nsec3 = ISC_TRUE;
4217                 seen_rr = ISC_TRUE;
4218                 dns_rdataset_disassociate(&rdataset);
4219         }
4220         if (result != ISC_R_NOMORE)
4221                 goto failure;
4222         if (seen_ns && !seen_soa)
4223                 *delegation = ISC_TRUE;
4224         /*
4225          * Going from insecure to NSEC3.
4226          * Don't generate NSEC3 records for NSEC3 records.
4227          */
4228         if (build_nsec3 && !seen_nsec3 && seen_rr) {
4229                 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
4230                 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
4231                                           unsecure, diff));
4232                 (*signatures)--;
4233         }
4234         /*
4235          * Going from insecure to NSEC.
4236          * Don't generate NSEC records for NSEC3 records.
4237          */
4238         if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
4239                 /* Build and add NSEC. */
4240                 bottom = (seen_ns && !seen_soa) || seen_dname;
4241                 CHECK(add_nsec(db, version, name, node, minimum, bottom, diff));
4242                 /* Count a NSEC generation as a signature generation. */
4243                 (*signatures)--;
4244         }
4245         result = dns_rdatasetiter_first(iterator);
4246         while (result == ISC_R_SUCCESS) {
4247                 dns_rdatasetiter_current(iterator, &rdataset);
4248                 if (rdataset.type == dns_rdatatype_soa ||
4249                     rdataset.type == dns_rdatatype_rrsig)
4250                         goto next_rdataset;
4251                 if (is_ksk && rdataset.type != dns_rdatatype_dnskey)
4252                         goto next_rdataset;
4253                 if (*delegation &&
4254                     rdataset.type != dns_rdatatype_ds &&
4255                     rdataset.type != dns_rdatatype_nsec)
4256                         goto next_rdataset;
4257                 if (signed_with_key(db, node, version, rdataset.type, key))
4258                         goto next_rdataset;
4259                 /* Calculate the signature, creating a RRSIG RDATA. */
4260                 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
4261                                       &expire, mctx, &buffer, &rdata));
4262                 /* Update the database and journal with the RRSIG. */
4263                 /* XXX inefficient - will cause dataset merging */
4264                 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
4265                                     name, rdataset.ttl, &rdata));
4266                 dns_rdata_reset(&rdata);
4267                 (*signatures)--;
4268  next_rdataset:
4269                 dns_rdataset_disassociate(&rdataset);
4270                 result = dns_rdatasetiter_next(iterator);
4271         }
4272         if (result == ISC_R_NOMORE)
4273                 result = ISC_R_SUCCESS;
4274         if (seen_dname)
4275                 *delegation = ISC_TRUE;
4276 failure:
4277         if (dns_rdataset_isassociated(&rdataset))
4278                 dns_rdataset_disassociate(&rdataset);
4279         if (iterator != NULL)
4280                 dns_rdatasetiter_destroy(&iterator);
4281         return (result);
4282 }
4283
4284 static isc_result_t
4285 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
4286              dns_ttl_t minimum, isc_boolean_t *secureupdated, dns_diff_t *diff)
4287 {
4288         isc_result_t result;
4289         dns_rdata_t rdata = DNS_RDATA_INIT;
4290         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
4291         dns_rdataset_t rdataset;
4292         dns_rdata_nsec_t nsec;
4293         dns_dbnode_t *node = NULL;
4294
4295         /*
4296          * Check to see if the OPT bit has already been cleared.
4297          */
4298         CHECK(dns_db_getoriginnode(db, &node));
4299         dns_rdataset_init(&rdataset);
4300         CHECK(dns_db_findrdataset(db, node, version, dns_rdatatype_nsec,
4301                                   dns_rdatatype_none, 0, &rdataset, NULL));
4302         CHECK(dns_rdataset_first(&rdataset));
4303         dns_rdataset_current(&rdataset, &rdata);
4304
4305         /*
4306          * Find the NEXT name for building the new record.
4307          */
4308         CHECK(dns_rdata_tostruct(&rdata, &nsec, NULL));
4309
4310         /*
4311          * Delete the old NSEC record.
4312          */
4313         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_DEL, name, minimum,
4314                             &rdata));
4315         dns_rdata_reset(&rdata);
4316
4317         /*
4318          * Add the new NSEC record.
4319          */
4320         CHECK(dns_nsec_buildrdata(db, version, node, &nsec.next, nsecbuffer,
4321                                   &rdata));
4322         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, minimum,
4323                             &rdata));
4324         dns_rdata_reset(&rdata);
4325
4326         if (secureupdated != NULL)
4327                 *secureupdated = ISC_TRUE;
4328
4329  failure:
4330         if (node != NULL)
4331                 dns_db_detachnode(db, &node);
4332         if (dns_rdataset_isassociated(&rdataset))
4333                 dns_rdataset_disassociate(&rdataset);
4334         return (result);
4335 }
4336
4337 static isc_result_t
4338 updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version,
4339                   dns_name_t *name, dns_rdatatype_t privatetype,
4340                   dns_diff_t *diff)
4341 {
4342         isc_result_t result;
4343         dns_dbnode_t *node = NULL;
4344         dns_rdataset_t rdataset;
4345         dns_rdata_t rdata = DNS_RDATA_INIT;
4346         unsigned char data[5];
4347         isc_boolean_t seen_done = ISC_FALSE;
4348
4349         dns_rdataset_init(&rdataset);
4350         result = dns_db_getoriginnode(signing->db, &node);
4351         if (result != ISC_R_SUCCESS)
4352                 goto failure;
4353
4354         result = dns_db_findrdataset(signing->db, node, version, privatetype,
4355                                      dns_rdatatype_none, 0, &rdataset, NULL);
4356         if (result == ISC_R_NOTFOUND) {
4357                 result = ISC_R_SUCCESS;
4358                 goto failure;
4359         }
4360         if (result != ISC_R_SUCCESS)
4361                 goto failure;
4362         for (result = dns_rdataset_first(&rdataset);
4363              result == ISC_R_SUCCESS;
4364              result = dns_rdataset_next(&rdataset)) {
4365                 dns_rdataset_current(&rdataset, &rdata);
4366                 if (rdata.length != 5 ||
4367                     rdata.data[0] != signing->algorithm ||
4368                     rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
4369                     rdata.data[2] != (signing->keyid & 0xff)) {
4370                         dns_rdata_reset(&rdata);
4371                         continue;
4372                 }
4373                 if (!signing->delete && rdata.data[4] != 0)
4374                         seen_done = ISC_TRUE;
4375                 else
4376                         CHECK(update_one_rr(signing->db, version, diff,
4377                                             DNS_DIFFOP_DEL, name,                                                           rdataset.ttl, &rdata));
4378                 dns_rdata_reset(&rdata);
4379         }
4380         if (result == ISC_R_NOMORE)
4381                 result = ISC_R_SUCCESS;
4382         if (!signing->delete && !seen_done) {
4383
4384                 data[0] = signing->algorithm;
4385                 data[1] = (signing->keyid >> 8) & 0xff;
4386                 data[2] = signing->keyid & 0xff;
4387                 data[3] = 0;
4388                 data[4] = 1;
4389                 rdata.length = sizeof(data);
4390                 rdata.data = data;
4391                 rdata.type = privatetype;
4392                 rdata.rdclass = dns_db_class(signing->db);
4393                 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
4394                                     name, rdataset.ttl, &rdata));
4395         }
4396  failure:
4397         if (dns_rdataset_isassociated(&rdataset))
4398                 dns_rdataset_disassociate(&rdataset);
4399         if (node != NULL)
4400                 dns_db_detachnode(signing->db, &node);
4401         return (result);
4402 }
4403
4404 static isc_result_t
4405 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
4406                  isc_boolean_t active, dns_diff_t *diff)
4407 {
4408         dns_dbnode_t *node = NULL;
4409         dns_name_t *name = dns_db_origin(db);
4410         dns_rdata_t rdata = DNS_RDATA_INIT;
4411         dns_rdataset_t rdataset;
4412         dns_rdata_nsec3param_t nsec3param;
4413         isc_result_t result;
4414         isc_buffer_t buffer;
4415         unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
4416         dns_ttl_t ttl = 0;
4417
4418         dns_rdataset_init(&rdataset);
4419
4420         result = dns_db_getoriginnode(db, &node);
4421         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4422         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
4423                                      0, 0, &rdataset, NULL);
4424         if (result == ISC_R_NOTFOUND)
4425                 goto add;
4426         if (result != ISC_R_SUCCESS)
4427                 goto failure;
4428
4429         /*
4430          * Preserve the existing ttl.
4431          */
4432         ttl = rdataset.ttl;
4433
4434         /*
4435          * Delete all NSEC3PARAM records which match that in nsec3chain.
4436          */
4437         for (result = dns_rdataset_first(&rdataset);
4438              result == ISC_R_SUCCESS;
4439              result = dns_rdataset_next(&rdataset)) {
4440
4441                 dns_rdataset_current(&rdataset, &rdata);
4442                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
4443
4444                 if (nsec3param.hash != chain->nsec3param.hash ||
4445                     (active && nsec3param.flags != 0) ||
4446                     nsec3param.iterations != chain->nsec3param.iterations ||
4447                     nsec3param.salt_length != chain->nsec3param.salt_length ||
4448                     memcmp(nsec3param.salt, chain->nsec3param.salt,
4449                            nsec3param.salt_length)) {
4450                         dns_rdata_reset(&rdata);
4451                         continue;
4452                 }
4453
4454                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
4455                                     name, rdataset.ttl, &rdata));
4456                 dns_rdata_reset(&rdata);
4457         }
4458         if (result != ISC_R_NOMORE)
4459                 goto failure;
4460
4461   add:
4462         if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
4463                 result = ISC_R_SUCCESS;
4464                 goto failure;
4465         }
4466
4467         /*
4468          * Add a NSEC3PARAM record which matches that in nsec3chain but
4469          * with all flags bits cleared.
4470          *
4471          * Note: we do not clear chain->nsec3param.flags as this change
4472          * may be reversed.
4473          */
4474         isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
4475         CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
4476                                    dns_rdatatype_nsec3param,
4477                                    &chain->nsec3param, &buffer));
4478         rdata.data[1] = 0;      /* Clear flag bits. */
4479         CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
4480
4481   failure:
4482         dns_db_detachnode(db, &node);
4483         if (dns_rdataset_isassociated(&rdataset))
4484                 dns_rdataset_disassociate(&rdataset);
4485         return (result);
4486 }
4487
4488 static isc_result_t
4489 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
4490             dns_name_t *name, dns_diff_t *diff)
4491 {
4492         dns_rdataset_t rdataset;
4493         isc_result_t result;
4494
4495         dns_rdataset_init(&rdataset);
4496
4497         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
4498                                      0, 0, &rdataset, NULL);
4499         if (result == ISC_R_NOTFOUND)
4500                 return (ISC_R_SUCCESS);
4501         if (result != ISC_R_SUCCESS)
4502                 return (result);
4503         for (result = dns_rdataset_first(&rdataset);
4504              result == ISC_R_SUCCESS;
4505              result = dns_rdataset_next(&rdataset)) {
4506                 dns_rdata_t rdata = DNS_RDATA_INIT;
4507
4508                 dns_rdataset_current(&rdataset, &rdata);
4509                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
4510                                     rdataset.ttl, &rdata));
4511         }
4512         if (result == ISC_R_NOMORE)
4513                 result = ISC_R_SUCCESS;
4514  failure:
4515         dns_rdataset_disassociate(&rdataset);
4516         return (result);
4517 }
4518
4519 static isc_result_t
4520 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
4521                     dns_name_t *name, const dns_rdata_nsec3param_t *param,
4522                     dns_diff_t *diff)
4523 {
4524         dns_rdataset_t rdataset;
4525         dns_rdata_nsec3_t nsec3;
4526         isc_result_t result;
4527
4528         dns_rdataset_init(&rdataset);
4529         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
4530                                      0, 0, &rdataset, NULL);
4531         if (result == ISC_R_NOTFOUND)
4532                 return (ISC_R_SUCCESS);
4533         if (result != ISC_R_SUCCESS)
4534                 return (result);
4535
4536         for (result = dns_rdataset_first(&rdataset);
4537              result == ISC_R_SUCCESS;
4538              result = dns_rdataset_next(&rdataset)) {
4539                 dns_rdata_t rdata = DNS_RDATA_INIT;
4540
4541                 dns_rdataset_current(&rdataset, &rdata);
4542                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
4543                 if (nsec3.hash != param->hash ||
4544                     nsec3.iterations != param->iterations ||
4545                     nsec3.salt_length != param->salt_length ||
4546                     memcmp(nsec3.salt, param->salt, nsec3.salt_length))
4547                         continue;
4548                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
4549                                     rdataset.ttl, &rdata));
4550         }
4551         if (result == ISC_R_NOMORE)
4552                 result = ISC_R_SUCCESS;
4553  failure:
4554         dns_rdataset_disassociate(&rdataset);
4555         return (result);
4556 }
4557
4558 static isc_result_t
4559 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
4560                 const dns_rdata_nsec3param_t *param,
4561                 isc_boolean_t *answer, isc_boolean_t *updatensec)
4562 {
4563         dns_dbnode_t *node = NULL;
4564         dns_rdata_t rdata = DNS_RDATA_INIT;
4565         dns_rdata_nsec3param_t myparam;
4566         dns_rdataset_t rdataset;
4567         isc_result_t result;
4568
4569         *answer = ISC_FALSE;
4570
4571         result = dns_db_getoriginnode(db, &node);
4572         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4573
4574         dns_rdataset_init(&rdataset);
4575         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
4576                                      0, 0, &rdataset, NULL);
4577         if (result == ISC_R_NOTFOUND)
4578                 goto check_nsec3param;
4579
4580         if (result != ISC_R_SUCCESS)
4581                 goto failure;
4582
4583         CHECK(dns_rdataset_first(&rdataset));
4584         dns_rdataset_current(&rdataset, &rdata);
4585
4586         if (!dns_nsec_typepresent(&rdata, dns_rdatatype_opt)) {
4587                 /*
4588                  * We have a complete NSEC chain.  Signal to update
4589                  * the apex NSEC record.
4590                  */
4591                 *updatensec = ISC_TRUE;
4592                 goto failure;
4593         }
4594         dns_rdataset_disassociate(&rdataset);
4595         dns_rdata_reset(&rdata);
4596
4597  check_nsec3param:
4598         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
4599                                      0, 0, &rdataset, NULL);
4600         if (result == ISC_R_NOTFOUND) {
4601                 *answer = ISC_TRUE;
4602                 dns_db_detachnode(db, &node);
4603                 return (ISC_R_SUCCESS);
4604         }
4605         if (result != ISC_R_SUCCESS) {
4606                 dns_db_detachnode(db, &node);
4607                 return (result);
4608         }
4609
4610         for (result = dns_rdataset_first(&rdataset);
4611              result == ISC_R_SUCCESS;
4612              result = dns_rdataset_next(&rdataset)) {
4613                 dns_rdataset_current(&rdataset, &rdata);
4614                 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
4615                 dns_rdata_reset(&rdata);
4616                 /*
4617                  * Ignore any NSEC3PARAM removals.
4618                  */
4619                 if (NSEC3REMOVE(myparam.flags))
4620                         continue;
4621                 /*
4622                  * Ignore the chain that we are in the process of deleting.
4623                  */
4624                 if (myparam.hash == param->hash &&
4625                     myparam.iterations == param->iterations &&
4626                     myparam.salt_length == param->salt_length &&
4627                     !memcmp(myparam.salt, param->salt, myparam.salt_length))
4628                         continue;
4629                 /*
4630                  * Found an active NSEC3 chain.
4631                  */
4632                 break;
4633         }
4634         if (result == ISC_R_NOMORE) {
4635                 *answer = ISC_TRUE;
4636                 result = ISC_R_SUCCESS;
4637         }
4638
4639  failure:
4640         if (dns_rdataset_isassociated(&rdataset))
4641                 dns_rdataset_disassociate(&rdataset);
4642         dns_db_detachnode(db, &node);
4643         return (result);
4644 }
4645
4646 /*
4647  * Incrementally build and sign a new NSEC3 chain using the parameters
4648  * requested.
4649  */
4650 static void
4651 zone_nsec3chain(dns_zone_t *zone) {
4652         const char *journalfile;
4653         dns_db_t *db = NULL;
4654         dns_dbnode_t *node = NULL;
4655         dns_dbversion_t *version = NULL;
4656         dns_diff_t sig_diff;
4657         dns_diff_t nsec_diff;
4658         dns_diff_t nsec3_diff;
4659         dns_diff_t param_diff;
4660         dns_fixedname_t fixed;
4661         dns_fixedname_t nextfixed;
4662         dns_name_t *name, *nextname;
4663         dns_rdataset_t rdataset;
4664         dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
4665         dns_nsec3chainlist_t cleanup;
4666         dst_key_t *zone_keys[MAXZONEKEYS];
4667         isc_int32_t signatures;
4668         isc_boolean_t check_ksk, is_ksk;
4669         isc_boolean_t delegation;
4670         isc_boolean_t first;
4671         isc_result_t result;
4672         isc_stdtime_t now, inception, soaexpire, expire, stop;
4673         isc_uint32_t jitter;
4674         unsigned int i;
4675         unsigned int nkeys = 0;
4676         isc_uint32_t nodes;
4677         isc_boolean_t unsecure = ISC_FALSE;
4678         isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
4679         isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
4680         dns_rdatasetiter_t *iterator = NULL;
4681         dns_difftuple_t *tuple;
4682         isc_boolean_t buildnsecchain;
4683         isc_boolean_t updatensec = ISC_FALSE;
4684
4685         dns_rdataset_init(&rdataset);
4686         dns_fixedname_init(&fixed);
4687         name = dns_fixedname_name(&fixed);
4688         dns_fixedname_init(&nextfixed);
4689         nextname = dns_fixedname_name(&nextfixed);
4690         dns_diff_init(zone->mctx, &param_diff);
4691         dns_diff_init(zone->mctx, &nsec3_diff);
4692         dns_diff_init(zone->mctx, &nsec_diff);
4693         dns_diff_init(zone->mctx, &sig_diff);
4694         sig_diff.resign = zone->sigresigninginterval;
4695         ISC_LIST_INIT(cleanup);
4696
4697         /*
4698          * Updates are disabled.  Pause for 5 minutes.
4699          */
4700         if (zone->update_disabled) {
4701                 result = ISC_R_FAILURE;
4702                 goto failure;
4703         }
4704
4705         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4706         dns_db_attach(zone->db, &db);
4707         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4708
4709         result = dns_db_newversion(db, &version);
4710         if (result != ISC_R_SUCCESS) {
4711                 dns_zone_log(zone, ISC_LOG_ERROR,
4712                              "zone_nsec3chain:dns_db_newversion -> %s\n",
4713                              dns_result_totext(result));
4714                 goto failure;
4715         }
4716
4717         result = find_zone_keys(zone, db, version, zone->mctx,
4718                                 MAXZONEKEYS, zone_keys, &nkeys);
4719         if (result != ISC_R_SUCCESS) {
4720                 dns_zone_log(zone, ISC_LOG_ERROR,
4721                              "zone_nsec3chain:find_zone_keys -> %s\n",
4722                              dns_result_totext(result));
4723                 goto failure;
4724         }
4725
4726         isc_stdtime_get(&now);
4727         inception = now - 3600; /* Allow for clock skew. */
4728         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
4729
4730         /*
4731          * Spread out signatures over time if they happen to be
4732          * clumped.  We don't do this for each add_sigs() call as
4733          * we still want some clustering to occur.
4734          */
4735         isc_random_get(&jitter);
4736         expire = soaexpire - jitter % 3600;
4737         stop = now + 5;
4738
4739         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
4740         if (check_ksk)
4741                 check_ksk = ksk_sanity(db, version);
4742
4743         /*
4744          * We keep pulling nodes off each iterator in turn until
4745          * we have no more nodes to pull off or we reach the limits
4746          * for this quantum.
4747          */
4748         nodes = zone->nodes;
4749         signatures = zone->signatures;
4750         LOCK_ZONE(zone);
4751         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
4752         UNLOCK_ZONE(zone);
4753         first = ISC_TRUE;
4754
4755         if (nsec3chain != NULL)
4756                 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
4757         /*
4758          * Generate new NSEC3 chains first.
4759          */
4760         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
4761                 LOCK_ZONE(zone);
4762                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
4763
4764                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4765                 if (nsec3chain->done || nsec3chain->db != zone->db) {
4766                         ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
4767                         ISC_LIST_APPEND(cleanup, nsec3chain, link);
4768                 }
4769                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4770                 UNLOCK_ZONE(zone);
4771                 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
4772                         goto next_addchain;
4773
4774                 /*
4775                  * Possible future db.
4776                  */
4777                 if (nsec3chain->db != db) {
4778                         goto next_addchain;
4779                 }
4780
4781                 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
4782                         goto next_addchain;
4783
4784                 is_ksk = ISC_FALSE;
4785                 delegation = ISC_FALSE;
4786                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
4787
4788                 if (nsec3chain->delete_nsec) {
4789                         delegation = ISC_FALSE;
4790                         dns_dbiterator_pause(nsec3chain->dbiterator);
4791                         CHECK(delete_nsec(db, version, node, name, &nsec_diff));
4792                         goto next_addnode;
4793                 }
4794                 /*
4795                  * On the first pass we need to check if the current node
4796                  * has not been obscured.
4797                  */
4798                 delegation = ISC_FALSE;
4799                 unsecure = ISC_FALSE;
4800                 if (first) {
4801                         dns_fixedname_t ffound;
4802                         dns_name_t *found;
4803                         dns_fixedname_init(&ffound);
4804                         found = dns_fixedname_name(&ffound);
4805                         result = dns_db_find(db, name, version,
4806                                              dns_rdatatype_soa,
4807                                              DNS_DBFIND_NOWILD, 0, NULL, found,
4808                                              NULL, NULL);
4809                         if ((result == DNS_R_DELEGATION ||
4810                             result == DNS_R_DNAME) &&
4811                             !dns_name_equal(name, found)) {
4812                                 /*
4813                                  * Remember the obscuring name so that
4814                                  * we skip all obscured names.
4815                                  */
4816                                 dns_name_copy(found, name, NULL);
4817                                 delegation = ISC_TRUE;
4818                                 goto next_addnode;
4819                         }
4820                 }
4821
4822                 /*
4823                  * Check to see if this is a bottom of zone node.
4824                  */
4825                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
4826                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
4827                         goto next_addnode;
4828                 if (result != ISC_R_SUCCESS)
4829                         goto failure;
4830
4831                 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
4832                         ISC_FALSE;
4833                 for (result = dns_rdatasetiter_first(iterator);
4834                      result == ISC_R_SUCCESS;
4835                      result = dns_rdatasetiter_next(iterator)) {
4836                         dns_rdatasetiter_current(iterator, &rdataset);
4837                         INSIST(rdataset.type != dns_rdatatype_nsec3);
4838                         if (rdataset.type == dns_rdatatype_soa)
4839                                 seen_soa = ISC_TRUE;
4840                         else if (rdataset.type == dns_rdatatype_ns)
4841                                 seen_ns = ISC_TRUE;
4842                         else if (rdataset.type == dns_rdatatype_dname)
4843                                 seen_dname = ISC_TRUE;
4844                         else if (rdataset.type == dns_rdatatype_ds)
4845                                 seen_ds = ISC_TRUE;
4846                         else if (rdataset.type == dns_rdatatype_nsec)
4847                                 seen_nsec = ISC_TRUE;
4848                         dns_rdataset_disassociate(&rdataset);
4849                 }
4850                 dns_rdatasetiter_destroy(&iterator);
4851                 /*
4852                  * Is there a NSEC chain than needs to be cleaned up?
4853                  */
4854                 if (seen_nsec)
4855                         nsec3chain->seen_nsec = ISC_TRUE;
4856                 if (seen_ns && !seen_soa && !seen_ds)
4857                         unsecure = ISC_TRUE;
4858                 if ((seen_ns && !seen_soa) || seen_dname)
4859                         delegation = ISC_TRUE;
4860
4861                 /*
4862                  * Process one node.
4863                  */
4864                 dns_dbiterator_pause(nsec3chain->dbiterator);
4865                 CHECK(dns_nsec3_addnsec3(db, version, name,
4866                                          &nsec3chain->nsec3param,
4867                                          zone->minimum, unsecure, &nsec3_diff));
4868                 /*
4869                  * Treat each call to dns_nsec3_addnsec3() as if it's cost is
4870                  * two signatures.  Additionally there will, in general, be
4871                  * two signature generated below.
4872                  *
4873                  * If we are only changing the optout flag the cost is half
4874                  * that of the cost of generating a completely new chain.
4875                  */
4876                 signatures -= 4;
4877
4878                 /*
4879                  * Go onto next node.
4880                  */
4881  next_addnode:
4882                 first = ISC_FALSE;
4883                 dns_db_detachnode(db, &node);
4884                 do {
4885                         result = dns_dbiterator_next(nsec3chain->dbiterator);
4886
4887                         if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
4888                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
4889                                                        ISC_FALSE, &param_diff));
4890                                 LOCK_ZONE(zone);
4891                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
4892                                                 link);
4893                                 UNLOCK_ZONE(zone);
4894                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
4895                                 goto next_addchain;
4896                         }
4897                         if (result == ISC_R_NOMORE) {
4898                                 dns_dbiterator_pause(nsec3chain->dbiterator);
4899                                 if (nsec3chain->seen_nsec) {
4900                                         CHECK(fixup_nsec3param(db, version,
4901                                                                nsec3chain,
4902                                                                ISC_TRUE,
4903                                                                &param_diff));
4904                                         nsec3chain->delete_nsec = ISC_TRUE;
4905                                         goto same_addchain;
4906                                 }
4907                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
4908                                                        ISC_FALSE, &param_diff));
4909                                 LOCK_ZONE(zone);
4910                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
4911                                                 link);
4912                                 UNLOCK_ZONE(zone);
4913                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
4914                                 goto next_addchain;
4915                         } else if (result != ISC_R_SUCCESS) {
4916                                 dns_zone_log(zone, ISC_LOG_ERROR,
4917                                              "zone_nsec3chain:"
4918                                              "dns_dbiterator_next -> %s\n",
4919                                              dns_result_totext(result));
4920                                 goto failure;
4921                         } else if (delegation) {
4922                                 dns_dbiterator_current(nsec3chain->dbiterator,
4923                                                        &node, nextname);
4924                                 dns_db_detachnode(db, &node);
4925                                 if (!dns_name_issubdomain(nextname, name))
4926                                         break;
4927                         } else
4928                                 break;
4929                 } while (1);
4930                 continue;
4931
4932  same_addchain:
4933                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
4934                 first = ISC_TRUE;
4935                 continue;
4936
4937  next_addchain:
4938                 dns_dbiterator_pause(nsec3chain->dbiterator);
4939                 nsec3chain = nextnsec3chain;
4940                 first = ISC_TRUE;
4941                 if (nsec3chain != NULL)
4942                         nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
4943         }
4944
4945         /*
4946          * Process removals.
4947          */
4948         LOCK_ZONE(zone);
4949         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
4950         UNLOCK_ZONE(zone);
4951         first = ISC_TRUE;
4952         buildnsecchain = ISC_FALSE;
4953         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
4954                 LOCK_ZONE(zone);
4955                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
4956                 UNLOCK_ZONE(zone);
4957
4958                 if (nsec3chain->db != db)
4959                         goto next_removechain;
4960
4961                 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
4962                         goto next_removechain;
4963
4964                 /*
4965                  * Work out if we need to build a NSEC chain as a consequence
4966                  * of removing this NSEC3 chain.
4967                  */
4968                 if (first && !updatensec &&
4969                     (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
4970                         CHECK(need_nsec_chain(db, version,
4971                                               &nsec3chain->nsec3param,
4972                                               &buildnsecchain, &updatensec));
4973
4974                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
4975                 delegation = ISC_FALSE;
4976
4977                 if (!buildnsecchain) {
4978                         /*
4979                          * Delete the NSECPARAM record that matches this chain.
4980                          */
4981                         if (first)
4982                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
4983                                                        ISC_TRUE, &param_diff));
4984
4985                         /*
4986                          *  Delete the NSEC3 records.
4987                          */
4988                         CHECK(deletematchingnsec3(db, version, node, name,
4989                                                   &nsec3chain->nsec3param,
4990                                                   &nsec3_diff));
4991                         goto next_removenode;
4992                 }
4993
4994                 if (first) {
4995                         dns_fixedname_t ffound;
4996                         dns_name_t *found;
4997                         dns_fixedname_init(&ffound);
4998                         found = dns_fixedname_name(&ffound);
4999                         result = dns_db_find(db, name, version,
5000                                              dns_rdatatype_soa,
5001                                              DNS_DBFIND_NOWILD, 0, NULL, found,
5002                                              NULL, NULL);
5003                         if ((result == DNS_R_DELEGATION ||
5004                              result == DNS_R_DNAME) &&
5005                             !dns_name_equal(name, found)) {
5006                                 /*
5007                                  * Remember the obscuring name so that
5008                                  * we skip all obscured names.
5009                                  */
5010                                 dns_name_copy(found, name, NULL);
5011                                 delegation = ISC_TRUE;
5012                                 goto next_removenode;
5013                         }
5014                 }
5015
5016                 /*
5017                  * Check to see if this is a bottom of zone node.
5018                  */
5019                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5020                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
5021                         goto next_removenode;
5022                 if (result != ISC_R_SUCCESS)
5023                         goto failure;
5024
5025                 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
5026                         seen_rr = ISC_FALSE;
5027                 for (result = dns_rdatasetiter_first(iterator);
5028                      result == ISC_R_SUCCESS;
5029                      result = dns_rdatasetiter_next(iterator)) {
5030                         dns_rdatasetiter_current(iterator, &rdataset);
5031                         if (rdataset.type == dns_rdatatype_soa)
5032                                 seen_soa = ISC_TRUE;
5033                         else if (rdataset.type == dns_rdatatype_ns)
5034                                 seen_ns = ISC_TRUE;
5035                         else if (rdataset.type == dns_rdatatype_dname)
5036                                 seen_dname = ISC_TRUE;
5037                         else if (rdataset.type == dns_rdatatype_nsec)
5038                                 seen_nsec = ISC_TRUE;
5039                         else if (rdataset.type == dns_rdatatype_nsec3)
5040                                 seen_nsec3 = ISC_TRUE;
5041                         seen_rr = ISC_TRUE;
5042                         dns_rdataset_disassociate(&rdataset);
5043                 }
5044                 dns_rdatasetiter_destroy(&iterator);
5045
5046                 if (!seen_rr || seen_nsec3 || seen_nsec)
5047                         goto next_removenode;
5048                 if ((seen_ns && !seen_soa) || seen_dname)
5049                         delegation = ISC_TRUE;
5050
5051                 CHECK(add_nsec(db, version, name, node, zone->minimum,
5052                                delegation, &nsec_diff));
5053
5054  next_removenode:
5055                 first = ISC_FALSE;
5056                 dns_db_detachnode(db, &node);
5057                 do {
5058                         result = dns_dbiterator_next(nsec3chain->dbiterator);
5059                         if (result == ISC_R_NOMORE && buildnsecchain) {
5060                                 /*
5061                                  * The NSEC chain should now be built.
5062                                  * We can now remove the NSEC3 chain.
5063                                  */
5064                                 updatensec = ISC_TRUE;
5065                                 goto same_removechain;
5066                         }
5067                         if (result == ISC_R_NOMORE) {
5068                                 LOCK_ZONE(zone);
5069                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
5070                                                 link);
5071                                 UNLOCK_ZONE(zone);
5072                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
5073                                 dns_dbiterator_pause(nsec3chain->dbiterator);
5074                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
5075                                                        ISC_FALSE, &param_diff));
5076                                 goto next_removechain;
5077                         } else if (result != ISC_R_SUCCESS) {
5078                                 dns_zone_log(zone, ISC_LOG_ERROR,
5079                                              "zone_nsec3chain:"
5080                                              "dns_dbiterator_next -> %s\n",
5081                                              dns_result_totext(result));
5082                                 goto failure;
5083                         } else if (delegation) {
5084                                 dns_dbiterator_current(nsec3chain->dbiterator,
5085                                                        &node, nextname);
5086                                 dns_db_detachnode(db, &node);
5087                                 if (!dns_name_issubdomain(nextname, name))
5088                                         break;
5089                         } else
5090                                 break;
5091                 } while (1);
5092                 continue;
5093
5094  same_removechain:
5095                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
5096                 buildnsecchain = ISC_FALSE;
5097                 first = ISC_TRUE;
5098                 continue;
5099
5100  next_removechain:
5101                 dns_dbiterator_pause(nsec3chain->dbiterator);
5102                 nsec3chain = nextnsec3chain;
5103                 first = ISC_TRUE;
5104         }
5105
5106         /*
5107          * Add / update signatures for the NSEC3 records.
5108          */
5109         for (tuple = ISC_LIST_HEAD(nsec3_diff.tuples);
5110              tuple != NULL;
5111              tuple = ISC_LIST_HEAD(nsec3_diff.tuples)) {
5112                 /*
5113                  * We have changed the NSEC3 RRset above so we need to update
5114                  * the signatures.
5115                  */
5116                 result = del_sigs(zone, db, version, &tuple->name,
5117                                   dns_rdatatype_nsec3, &sig_diff,
5118                                   zone_keys, nkeys, now);
5119                 if (result != ISC_R_SUCCESS) {
5120                         dns_zone_log(zone, ISC_LOG_ERROR,
5121                                      "zone_nsec3chain:del_sigs -> %s\n",
5122                                      dns_result_totext(result));
5123                         goto failure;
5124                 }
5125                 result = add_sigs(db, version, &tuple->name,
5126                                   dns_rdatatype_nsec3, &sig_diff, zone_keys,
5127                                   nkeys, zone->mctx, inception, expire,
5128                                   check_ksk);
5129                 if (result != ISC_R_SUCCESS) {
5130                         dns_zone_log(zone, ISC_LOG_ERROR,
5131                                      "zone_nsec3chain:add_sigs -> %s\n",
5132                                      dns_result_totext(result));
5133                         goto failure;
5134                 }
5135
5136                 do {
5137                         dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
5138                         while (next != NULL &&
5139                                !dns_name_equal(&tuple->name, &next->name))
5140                                 next = ISC_LIST_NEXT(next, link);
5141                         ISC_LIST_UNLINK(nsec3_diff.tuples, tuple, link);
5142                         dns_diff_appendminimal(&sig_diff, &tuple);
5143                         INSIST(tuple == NULL);
5144                         tuple = next;
5145                 } while (tuple != NULL);
5146         }
5147
5148         for (tuple = ISC_LIST_HEAD(param_diff.tuples);
5149              tuple != NULL;
5150              tuple = ISC_LIST_HEAD(param_diff.tuples)) {
5151                 /*
5152                  * We have changed the NSEC3PARAM RRset above so we need to
5153                  * update the signatures.
5154                  */
5155                 result = del_sigs(zone, db, version, &tuple->name,
5156                                   dns_rdatatype_nsec3param, &sig_diff,
5157                                   zone_keys, nkeys, now);
5158                 if (result != ISC_R_SUCCESS) {
5159                         dns_zone_log(zone, ISC_LOG_ERROR,
5160                                      "zone_nsec3chain:del_sigs -> %s\n",
5161                                      dns_result_totext(result));
5162                         goto failure;
5163                 }
5164                 result = add_sigs(db, version, &tuple->name,
5165                                   dns_rdatatype_nsec3param, &sig_diff,
5166                                   zone_keys, nkeys, zone->mctx, inception,
5167                                   expire, check_ksk);
5168                 if (result != ISC_R_SUCCESS) {
5169                         dns_zone_log(zone, ISC_LOG_ERROR,
5170                                      "zone_nsec3chain:add_sigs -> %s\n",
5171                                      dns_result_totext(result));
5172                         goto failure;
5173                 }
5174                 ISC_LIST_UNLINK(param_diff.tuples, tuple, link);
5175                 dns_diff_appendminimal(&sig_diff, &tuple);
5176                 INSIST(tuple == NULL);
5177         }
5178
5179         if (updatensec)
5180                 CHECK(updatesecure(db, version, &zone->origin, zone->minimum,
5181                                    NULL, &nsec_diff));
5182
5183         for (tuple = ISC_LIST_HEAD(nsec_diff.tuples);
5184              tuple != NULL;
5185              tuple = ISC_LIST_HEAD(nsec_diff.tuples)) {
5186                 result = del_sigs(zone, db, version, &tuple->name,
5187                                   dns_rdatatype_nsec, &sig_diff,
5188                                   zone_keys, nkeys, now);
5189                 if (result != ISC_R_SUCCESS) {
5190                         dns_zone_log(zone, ISC_LOG_ERROR,
5191                                      "zone_nsec3chain:del_sigs -> %s\n",
5192                                      dns_result_totext(result));
5193                         goto failure;
5194                 }
5195                 result = add_sigs(db, version, &tuple->name,
5196                                   dns_rdatatype_nsec, &sig_diff,
5197                                   zone_keys, nkeys, zone->mctx, inception,
5198                                   expire, check_ksk);
5199                 if (result != ISC_R_SUCCESS) {
5200                         dns_zone_log(zone, ISC_LOG_ERROR,
5201                                      "zone_nsec3chain:add_sigs -> %s\n",
5202                                      dns_result_totext(result));
5203                         goto failure;
5204                 }
5205                 ISC_LIST_UNLINK(nsec_diff.tuples, tuple, link);
5206                 dns_diff_appendminimal(&sig_diff, &tuple);
5207                 INSIST(tuple == NULL);
5208         }
5209
5210         /*
5211          * If we made no effective changes to the zone then we can just
5212          * cleanup otherwise we need to increment the serial.
5213          */
5214         if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
5215                 goto done;
5216
5217         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5218                           &sig_diff, zone_keys, nkeys, now);
5219         if (result != ISC_R_SUCCESS) {
5220                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5221                              "del_sigs -> %s\n", dns_result_totext(result));
5222                 goto failure;
5223         }
5224
5225         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
5226         if (result != ISC_R_SUCCESS) {
5227                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5228                              "increment_soa_serial -> %s\n",
5229                              dns_result_totext(result));
5230                 goto failure;
5231         }
5232
5233         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5234                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
5235                           soaexpire, check_ksk);
5236         if (result != ISC_R_SUCCESS) {
5237                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5238                              "add_sigs -> %s\n", dns_result_totext(result));
5239                 goto failure;
5240         }
5241
5242         journalfile = dns_zone_getjournal(zone);
5243         if (journalfile != NULL) {
5244                 dns_journal_t *journal = NULL;
5245                 result = dns_journal_open(zone->mctx, journalfile,
5246                                           ISC_TRUE, &journal);
5247                 if (result != ISC_R_SUCCESS) {
5248                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5249                                      "dns_journal_open -> %s\n",
5250                                      dns_result_totext(result));
5251                         goto failure;
5252                 }
5253
5254                 result = dns_journal_write_transaction(journal, &sig_diff);
5255                 dns_journal_destroy(&journal);
5256                 if (result != ISC_R_SUCCESS) {
5257                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5258                                      "dns_journal_write_transaction -> %s\n",
5259                                      dns_result_totext(result));
5260                         goto failure;
5261                 }
5262         }
5263
5264         LOCK_ZONE(zone);
5265         zone_needdump(zone, DNS_DUMP_DELAY);
5266         UNLOCK_ZONE(zone);
5267
5268  done:
5269         /*
5270          * Pause all iterators so that dns_db_closeversion() can succeed.
5271          */
5272         LOCK_ZONE(zone);
5273         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
5274              nsec3chain != NULL;
5275              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
5276                 dns_dbiterator_pause(nsec3chain->dbiterator);
5277         UNLOCK_ZONE(zone);
5278
5279         /*
5280          * Everything has succeeded. Commit the changes.
5281          */
5282         dns_db_closeversion(db, &version, ISC_TRUE);
5283
5284         /*
5285          * Everything succeeded so we can clean these up now.
5286          */
5287         nsec3chain = ISC_LIST_HEAD(cleanup);
5288         while (nsec3chain != NULL) {
5289                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
5290                 dns_db_detach(&nsec3chain->db);
5291                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
5292                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
5293                 nsec3chain = ISC_LIST_HEAD(cleanup);
5294         }
5295
5296         set_resigntime(zone);
5297
5298  failure:
5299         /*
5300          * On error roll back the current nsec3chain.
5301          */
5302         if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
5303                 if (nsec3chain->done) {
5304                         dns_db_detach(&nsec3chain->db);
5305                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
5306                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
5307                 } else {
5308                         result = dns_dbiterator_first(nsec3chain->dbiterator);
5309                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5310                         dns_dbiterator_pause(nsec3chain->dbiterator);
5311                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
5312                 }
5313         }
5314
5315         /*
5316          * Rollback the cleanup list.
5317          */
5318         nsec3chain = ISC_LIST_TAIL(cleanup);
5319         while (nsec3chain != NULL) {
5320                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
5321                 if (nsec3chain->done) {
5322                         dns_db_detach(&nsec3chain->db);
5323                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
5324                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
5325                 } else {
5326                         LOCK_ZONE(zone);
5327                         ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
5328                         UNLOCK_ZONE(zone);
5329                         result = dns_dbiterator_first(nsec3chain->dbiterator);
5330                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5331                         dns_dbiterator_pause(nsec3chain->dbiterator);
5332                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
5333                 }
5334                 nsec3chain = ISC_LIST_TAIL(cleanup);
5335         }
5336
5337         LOCK_ZONE(zone);
5338         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
5339              nsec3chain != NULL;
5340              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
5341                 dns_dbiterator_pause(nsec3chain->dbiterator);
5342         UNLOCK_ZONE(zone);
5343
5344         dns_diff_clear(&param_diff);
5345         dns_diff_clear(&nsec3_diff);
5346         dns_diff_clear(&nsec_diff);
5347         dns_diff_clear(&sig_diff);
5348
5349         if (iterator != NULL)
5350                 dns_rdatasetiter_destroy(&iterator);
5351
5352         for (i = 0; i < nkeys; i++)
5353                 dst_key_free(&zone_keys[i]);
5354
5355         if (version != NULL) {
5356                 dns_db_closeversion(db, &version, ISC_FALSE);
5357                 dns_db_detach(&db);
5358         } else if (db != NULL)
5359                 dns_db_detach(&db);
5360
5361         LOCK_ZONE(zone);
5362         if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
5363                 isc_interval_t i;
5364                 if (zone->update_disabled || result != ISC_R_SUCCESS)
5365                         isc_interval_set(&i, 60, 0);            /* 1 minute */
5366                 else
5367                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
5368                 isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
5369         } else
5370                 isc_time_settoepoch(&zone->nsec3chaintime);
5371         UNLOCK_ZONE(zone);
5372 }
5373
5374 static isc_result_t
5375 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5376         dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
5377         isc_uint16_t keyid, dns_diff_t *diff)
5378 {
5379         dns_rdata_rrsig_t rrsig;
5380         dns_rdataset_t rdataset;
5381         dns_rdatasetiter_t *iterator = NULL;
5382         isc_result_t result;
5383
5384         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5385         if (result != ISC_R_SUCCESS) {
5386                 if (result == ISC_R_NOTFOUND)
5387                         result = ISC_R_SUCCESS;
5388                 return (result);
5389         }
5390
5391         dns_rdataset_init(&rdataset);
5392         for (result = dns_rdatasetiter_first(iterator);
5393              result == ISC_R_SUCCESS;
5394              result = dns_rdatasetiter_next(iterator)) {
5395                 dns_rdatasetiter_current(iterator, &rdataset);
5396                 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
5397                         for (result = dns_rdataset_first(&rdataset);
5398                              result == ISC_R_SUCCESS;
5399                              result = dns_rdataset_next(&rdataset)) {
5400                                 dns_rdata_t rdata = DNS_RDATA_INIT;
5401                                 dns_rdataset_current(&rdataset, &rdata);
5402                                 CHECK(update_one_rr(db, version, diff,
5403                                                     DNS_DIFFOP_DEL, name,
5404                                                     rdataset.ttl, &rdata));
5405                         }
5406                         if (result != ISC_R_NOMORE)
5407                                 goto failure;
5408                         dns_rdataset_disassociate(&rdataset);
5409                         continue;
5410                 }
5411                 if (rdataset.type != dns_rdatatype_rrsig) {
5412                         dns_rdataset_disassociate(&rdataset);
5413                         continue;
5414                 }
5415                 for (result = dns_rdataset_first(&rdataset);
5416                      result == ISC_R_SUCCESS;
5417                      result = dns_rdataset_next(&rdataset)) {
5418                         dns_rdata_t rdata = DNS_RDATA_INIT;
5419                         dns_rdataset_current(&rdataset, &rdata);
5420                         CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
5421                         if (rrsig.algorithm != algorithm ||
5422                             rrsig.keyid != keyid)
5423                                 continue;
5424                         CHECK(update_one_rr(db, version, diff,
5425                                             DNS_DIFFOP_DEL, name,
5426                                             rdataset.ttl, &rdata));
5427                 }
5428                 dns_rdataset_disassociate(&rdataset);
5429                 if (result != ISC_R_NOMORE)
5430                         break;
5431         }
5432         if (result == ISC_R_NOMORE)
5433                 result = ISC_R_SUCCESS;
5434  failure:
5435         if (dns_rdataset_isassociated(&rdataset))
5436                 dns_rdataset_disassociate(&rdataset);
5437         dns_rdatasetiter_destroy(&iterator);
5438         return (result);
5439 }
5440
5441 /*
5442  * Incrementally sign the zone using the keys requested.
5443  * Builds the NSEC chain if required.
5444  */
5445 static void
5446 zone_sign(dns_zone_t *zone) {
5447         const char *journalfile;
5448         dns_db_t *db = NULL;
5449         dns_dbnode_t *node = NULL;
5450         dns_dbversion_t *version = NULL;
5451         dns_diff_t sig_diff;
5452         dns_fixedname_t fixed;
5453         dns_fixedname_t nextfixed;
5454         dns_name_t *name, *nextname;
5455         dns_rdataset_t rdataset;
5456         dns_signing_t *signing, *nextsigning;
5457         dns_signinglist_t cleanup;
5458         dst_key_t *zone_keys[MAXZONEKEYS];
5459         isc_int32_t signatures;
5460         isc_boolean_t check_ksk, is_ksk;
5461         isc_boolean_t delegation;
5462         isc_boolean_t finishedakey = ISC_FALSE;
5463         isc_boolean_t secureupdated = ISC_FALSE;
5464         isc_boolean_t build_nsec3 = ISC_FALSE, build_nsec = ISC_FALSE;
5465         isc_boolean_t first;
5466         isc_result_t result;
5467         isc_stdtime_t now, inception, soaexpire, expire, stop;
5468         isc_uint32_t jitter;
5469         unsigned int i;
5470         unsigned int nkeys = 0;
5471         isc_uint32_t nodes;
5472
5473         dns_rdataset_init(&rdataset);
5474         dns_fixedname_init(&fixed);
5475         name = dns_fixedname_name(&fixed);
5476         dns_fixedname_init(&nextfixed);
5477         nextname = dns_fixedname_name(&nextfixed);
5478         dns_diff_init(zone->mctx, &sig_diff);
5479         sig_diff.resign = zone->sigresigninginterval;
5480         ISC_LIST_INIT(cleanup);
5481
5482         /*
5483          * Updates are disabled.  Pause for 5 minutes.
5484          */
5485         if (zone->update_disabled) {
5486                 result = ISC_R_FAILURE;
5487                 goto failure;
5488         }
5489
5490         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5491         dns_db_attach(zone->db, &db);
5492         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5493
5494         result = dns_db_newversion(db, &version);
5495         if (result != ISC_R_SUCCESS) {
5496                 dns_zone_log(zone, ISC_LOG_ERROR,
5497                              "zone_sign:dns_db_newversion -> %s\n",
5498                              dns_result_totext(result));
5499                 goto failure;
5500         }
5501
5502         result = find_zone_keys(zone, db, version, zone->mctx,
5503                                 MAXZONEKEYS, zone_keys, &nkeys);
5504         if (result != ISC_R_SUCCESS) {
5505                 dns_zone_log(zone, ISC_LOG_ERROR,
5506                              "zone_sign:find_zone_keys -> %s\n",
5507                              dns_result_totext(result));
5508                 goto failure;
5509         }
5510
5511         isc_stdtime_get(&now);
5512         inception = now - 3600; /* Allow for clock skew. */
5513         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5514
5515         /*
5516          * Spread out signatures over time if they happen to be
5517          * clumped.  We don't do this for each add_sigs() call as
5518          * we still want some clustering to occur.
5519          */
5520         isc_random_get(&jitter);
5521         expire = soaexpire - jitter % 3600;
5522         stop = now + 5;
5523
5524         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5525         if (check_ksk)
5526                 check_ksk = ksk_sanity(db, version);
5527
5528         /*
5529          * We keep pulling nodes off each iterator in turn until
5530          * we have no more nodes to pull off or we reach the limits
5531          * for this quantum.
5532          */
5533         nodes = zone->nodes;
5534         signatures = zone->signatures;
5535         signing = ISC_LIST_HEAD(zone->signing);
5536         first = ISC_TRUE;
5537         /*
5538          * See if we have a NSEC chain.
5539          */
5540         result = dns_db_getoriginnode(db, &node);
5541         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5542         result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec,
5543                                      dns_rdatatype_none, 0, &rdataset, NULL);
5544         dns_db_detachnode(db, &node);
5545         if (result == ISC_R_SUCCESS) {
5546                 build_nsec = ISC_TRUE;
5547                 dns_rdataset_disassociate(&rdataset);
5548         } else if (result != ISC_R_NOTFOUND) {
5549                 goto failure;
5550         } else {
5551                 /*
5552                  * No NSEC chain present.
5553                  * See if we need to build a NSEC3 chain?
5554                  */
5555                 result = dns_nsec3_active(db, version, ISC_TRUE, &build_nsec3);
5556                 if (result == ISC_R_SUCCESS) {
5557                         if (build_nsec3)
5558                                 build_nsec3 = ISC_FALSE;
5559                         else  {
5560                                 result = dns_nsec3_active(db, version,
5561                                                           ISC_FALSE,
5562                                                           &build_nsec3);
5563                                 if (build_nsec3)
5564                                         secureupdated = ISC_TRUE;
5565                                 else
5566                                         build_nsec = ISC_TRUE;
5567                         }
5568                 }
5569         }
5570
5571         while (signing != NULL && nodes-- > 0 && signatures > 0) {
5572                 nextsigning = ISC_LIST_NEXT(signing, link);
5573
5574                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5575                 if (signing->done || signing->db != zone->db) {
5576                         /*
5577                          * The zone has been reloaded.  We will have
5578                          * created new signings as part of the reload
5579                          * process so we can destroy this one.
5580                          */
5581                         ISC_LIST_UNLINK(zone->signing, signing, link);
5582                         ISC_LIST_APPEND(cleanup, signing, link);
5583                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5584                         goto next_signing;
5585                 }
5586                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5587
5588                 if (signing->db != db)
5589                         goto next_signing;
5590
5591                 is_ksk = ISC_FALSE;
5592                 delegation = ISC_FALSE;
5593
5594                 dns_dbiterator_current(signing->dbiterator, &node, name);
5595
5596                 if (signing->delete) {
5597                         dns_dbiterator_pause(signing->dbiterator);
5598                         CHECK(del_sig(db, version, name, node, nkeys,
5599                                       signing->algorithm, signing->keyid,
5600                                       &sig_diff));
5601                         goto next_node;
5602                 }
5603                 /*
5604                  * On the first pass we need to check if the current node
5605                  * has not been obscured.
5606                  */
5607                 if (first) {
5608                         dns_fixedname_t ffound;
5609                         dns_name_t *found;
5610                         dns_fixedname_init(&ffound);
5611                         found = dns_fixedname_name(&ffound);
5612                         result = dns_db_find(db, name, version,
5613                                              dns_rdatatype_soa,
5614                                              DNS_DBFIND_NOWILD, 0, NULL, found,
5615                                              NULL, NULL);
5616                         if ((result == DNS_R_DELEGATION ||
5617                             result == DNS_R_DNAME) &&
5618                             !dns_name_equal(name, found)) {
5619                                 /*
5620                                  * Remember the obscuring name so that
5621                                  * we skip all obscured names.
5622                                  */
5623                                 dns_name_copy(found, name, NULL);
5624                                 delegation = ISC_TRUE;
5625                                 goto next_node;
5626                         }
5627                 }
5628
5629                 /*
5630                  * Process one node.
5631                  */
5632                 dns_dbiterator_pause(signing->dbiterator);
5633                 for (i = 0; i < nkeys; i++) {
5634                         /*
5635                          * Find the key we want to sign with.
5636                          */
5637                         if (dst_key_alg(zone_keys[i]) != signing->algorithm ||
5638                             dst_key_id(zone_keys[i]) != signing->keyid ||
5639                             !dst_key_isprivate(zone_keys[i]))
5640                                 continue;
5641                         /*
5642                          * Do we do KSK processing?
5643                          */
5644                         if (check_ksk &&
5645                             (dst_key_flags(zone_keys[i]) & DNS_KEYFLAG_KSK) != 0)
5646                                 is_ksk = ISC_TRUE;
5647                         CHECK(sign_a_node(db, name, node, version, build_nsec3,
5648                                           build_nsec, zone_keys[i], inception,
5649                                           expire, zone->minimum, is_ksk,
5650                                           &delegation, &sig_diff, &signatures,
5651                                           zone->mctx));
5652                         break;
5653                 }
5654                 /*
5655                  * Go onto next node.
5656                  */
5657  next_node:
5658                 first = ISC_FALSE;
5659                 dns_db_detachnode(db, &node);
5660                 do {
5661                         result = dns_dbiterator_next(signing->dbiterator);
5662                         if (result == ISC_R_NOMORE) {
5663                                 ISC_LIST_UNLINK(zone->signing, signing, link);
5664                                 ISC_LIST_APPEND(cleanup, signing, link);
5665                                 dns_dbiterator_pause(signing->dbiterator);
5666                                 finishedakey = ISC_TRUE;
5667                                 if (!is_ksk && !secureupdated && nkeys != 0 &&
5668                                     build_nsec) {
5669                                         /*
5670                                          * We have finished regenerating the
5671                                          * zone with a zone signing key.
5672                                          * The NSEC chain is now complete and
5673                                          * there is a full set of signatures
5674                                          * for the zone.  We can now clear the
5675                                          * OPT bit from the NSEC record.
5676                                          */
5677                                         result = updatesecure(db, version,
5678                                                               &zone->origin,
5679                                                               zone->minimum,
5680                                                               &secureupdated,
5681                                                               &sig_diff);
5682                                         if (result != ISC_R_SUCCESS) {
5683                                                 dns_zone_log(zone,
5684                                                              ISC_LOG_ERROR,
5685                                                     "updatesecure -> %s\n",
5686                                                     dns_result_totext(result));
5687                                                 goto failure;
5688                                         }
5689                                 }
5690                                 result = updatesignwithkey(signing, version,
5691                                                            &zone->origin,
5692                                                            zone->privatetype,
5693                                                            &sig_diff);
5694                                 if (result != ISC_R_SUCCESS) {
5695                                         dns_zone_log(zone, ISC_LOG_ERROR,
5696                                                      "updatesignwithkey -> %s\n",
5697                                                      dns_result_totext(result));
5698                                         goto failure;
5699                                 }
5700                                 goto next_signing;
5701                         } else if (result != ISC_R_SUCCESS) {
5702                                 dns_zone_log(zone, ISC_LOG_ERROR,
5703                                         "zone_sign:dns_dbiterator_next -> %s\n",
5704                                              dns_result_totext(result));
5705                                 goto failure;
5706                         } else if (delegation) {
5707                                 dns_dbiterator_current(signing->dbiterator,
5708                                                        &node, nextname);
5709                                 dns_db_detachnode(db, &node);
5710                                 if (!dns_name_issubdomain(nextname, name))
5711                                         break;
5712                         } else
5713                                 break;
5714                 } while (1);
5715                 continue;
5716
5717  next_signing:
5718                 dns_dbiterator_pause(signing->dbiterator);
5719                 signing = nextsigning;
5720                 first = ISC_TRUE;
5721         }
5722
5723         if (secureupdated) {
5724                 /*
5725                  * We have changed the NSEC RRset above so we need to update
5726                  * the signatures.
5727                  */
5728                 result = del_sigs(zone, db, version, &zone->origin,
5729                                   dns_rdatatype_nsec, &sig_diff, zone_keys,
5730                                   nkeys, now);
5731                 if (result != ISC_R_SUCCESS) {
5732                         dns_zone_log(zone, ISC_LOG_ERROR,
5733                                      "zone_sign:del_sigs -> %s\n",
5734                                      dns_result_totext(result));
5735                         goto failure;
5736                 }
5737                 result = add_sigs(db, version, &zone->origin,
5738                                   dns_rdatatype_nsec, &sig_diff, zone_keys,
5739                                   nkeys, zone->mctx, inception, soaexpire,
5740                                   check_ksk);
5741                 if (result != ISC_R_SUCCESS) {
5742                         dns_zone_log(zone, ISC_LOG_ERROR,
5743                                      "zone_sign:add_sigs -> %s\n",
5744                                      dns_result_totext(result));
5745                         goto failure;
5746                 }
5747         }
5748         if (finishedakey) {
5749                 /*
5750                  * We have changed the RRset above so we need to update
5751                  * the signatures.
5752                  */
5753                 result = del_sigs(zone, db, version, &zone->origin,
5754                                   zone->privatetype, &sig_diff,
5755                                   zone_keys, nkeys, now);
5756                 if (result != ISC_R_SUCCESS) {
5757                         dns_zone_log(zone, ISC_LOG_ERROR,
5758                                      "zone_sign:del_sigs -> %s\n",
5759                                      dns_result_totext(result));
5760                         goto failure;
5761                 }
5762                 result = add_sigs(db, version, &zone->origin,
5763                                   zone->privatetype, &sig_diff,
5764                                   zone_keys, nkeys, zone->mctx, inception,
5765                                   soaexpire, check_ksk);
5766                 if (result != ISC_R_SUCCESS) {
5767                         dns_zone_log(zone, ISC_LOG_ERROR,
5768                                      "zone_sign:add_sigs -> %s\n",
5769                                      dns_result_totext(result));
5770                         goto failure;
5771                 }
5772         }
5773         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5774                           &sig_diff, zone_keys, nkeys, now);
5775         if (result != ISC_R_SUCCESS) {
5776                 dns_zone_log(zone, ISC_LOG_ERROR,
5777                              "zone_sign:del_sigs -> %s\n",
5778                              dns_result_totext(result));
5779                 goto failure;
5780         }
5781
5782         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
5783         if (result != ISC_R_SUCCESS) {
5784                 dns_zone_log(zone, ISC_LOG_ERROR,
5785                              "zone_sign:increment_soa_serial -> %s\n",
5786                              dns_result_totext(result));
5787                 goto failure;
5788         }
5789
5790         /*
5791          * Generate maximum life time signatures so that the above loop
5792          * termination is sensible.
5793          */
5794         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5795                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
5796                           soaexpire, check_ksk);
5797         if (result != ISC_R_SUCCESS) {
5798                 dns_zone_log(zone, ISC_LOG_ERROR,
5799                              "zone_sign:add_sigs -> %s\n",
5800                              dns_result_totext(result));
5801                 goto failure;
5802         }
5803
5804         journalfile = dns_zone_getjournal(zone);
5805         if (journalfile != NULL) {
5806                 dns_journal_t *journal = NULL;
5807                 result = dns_journal_open(zone->mctx, journalfile,
5808                                           ISC_TRUE, &journal);
5809                 if (result != ISC_R_SUCCESS) {
5810                         dns_zone_log(zone, ISC_LOG_ERROR,
5811                                      "zone_sign:dns_journal_open -> %s\n",
5812                                      dns_result_totext(result));
5813                         goto failure;
5814                 }
5815
5816                 result = dns_journal_write_transaction(journal, &sig_diff);
5817                 dns_journal_destroy(&journal);
5818                 if (result != ISC_R_SUCCESS) {
5819                         dns_zone_log(zone, ISC_LOG_ERROR,
5820                          "zone_sign:dns_journal_write_transaction -> %s\n",
5821                                      dns_result_totext(result));
5822                         goto failure;
5823                 }
5824         }
5825
5826
5827         /*
5828          * Pause all iterators so that dns_db_closeversion() can succeed.
5829          */
5830         for (signing = ISC_LIST_HEAD(zone->signing);
5831              signing != NULL;
5832              signing = ISC_LIST_NEXT(signing, link))
5833                 dns_dbiterator_pause(signing->dbiterator);
5834
5835         for (signing = ISC_LIST_HEAD(cleanup);
5836              signing != NULL;
5837              signing = ISC_LIST_NEXT(signing, link))
5838                 dns_dbiterator_pause(signing->dbiterator);
5839
5840         /*
5841          * Everything has succeeded. Commit the changes.
5842          */
5843         dns_db_closeversion(db, &version, ISC_TRUE);
5844
5845         /*
5846          * Everything succeeded so we can clean these up now.
5847          */
5848         signing = ISC_LIST_HEAD(cleanup);
5849         while (signing != NULL) {
5850                 ISC_LIST_UNLINK(cleanup, signing, link);
5851                 dns_db_detach(&signing->db);
5852                 dns_dbiterator_destroy(&signing->dbiterator);
5853                 isc_mem_put(zone->mctx, signing, sizeof *signing);
5854                 signing = ISC_LIST_HEAD(cleanup);
5855         }
5856
5857         set_resigntime(zone);
5858
5859         LOCK_ZONE(zone);
5860         zone_needdump(zone, DNS_DUMP_DELAY);
5861         UNLOCK_ZONE(zone);
5862
5863  failure:
5864         /*
5865          * Rollback the cleanup list.
5866          */
5867         signing = ISC_LIST_HEAD(cleanup);
5868         while (signing != NULL) {
5869                 ISC_LIST_UNLINK(cleanup, signing, link);
5870                 ISC_LIST_APPEND(zone->signing, signing, link);
5871                 dns_dbiterator_first(signing->dbiterator);
5872                 dns_dbiterator_pause(signing->dbiterator);
5873                 signing = ISC_LIST_HEAD(cleanup);
5874         }
5875
5876         for (signing = ISC_LIST_HEAD(zone->signing);
5877              signing != NULL;
5878              signing = ISC_LIST_NEXT(signing, link))
5879                 dns_dbiterator_pause(signing->dbiterator);
5880
5881         dns_diff_clear(&sig_diff);
5882
5883         for (i = 0; i < nkeys; i++)
5884                 dst_key_free(&zone_keys[i]);
5885
5886         if (version != NULL) {
5887                 dns_db_closeversion(db, &version, ISC_FALSE);
5888                 dns_db_detach(&db);
5889         } else if (db != NULL)
5890                 dns_db_detach(&db);
5891
5892         if (ISC_LIST_HEAD(zone->signing) != NULL) {
5893                 isc_interval_t i;
5894                 if (zone->update_disabled || result != ISC_R_SUCCESS)
5895                         isc_interval_set(&i, 60, 0);            /* 1 minute */
5896                 else
5897                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
5898                 isc_time_nowplusinterval(&zone->signingtime, &i);
5899         } else
5900                 isc_time_settoepoch(&zone->signingtime);
5901 }
5902
5903 static void
5904 zone_maintenance(dns_zone_t *zone) {
5905         const char me[] = "zone_maintenance";
5906         isc_time_t now;
5907         isc_result_t result;
5908         isc_boolean_t dumping;
5909
5910         REQUIRE(DNS_ZONE_VALID(zone));
5911         ENTER;
5912
5913         /*
5914          * Configuring the view of this zone may have
5915          * failed, for example because the config file
5916          * had a syntax error.  In that case, the view
5917          * adb or resolver, and we had better not try
5918          * to do maintenance on it.
5919          */
5920         if (zone->view == NULL || zone->view->adb == NULL)
5921                 return;
5922
5923         TIME_NOW(&now);
5924
5925         /*
5926          * Expire check.
5927          */
5928         switch (zone->type) {
5929         case dns_zone_slave:
5930         case dns_zone_stub:
5931                 LOCK_ZONE(zone);
5932                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
5933                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
5934                         zone_expire(zone);
5935                         zone->refreshtime = now;
5936                 }
5937                 UNLOCK_ZONE(zone);
5938                 break;
5939         default:
5940                 break;
5941         }
5942
5943         /*
5944          * Up to date check.
5945          */
5946         switch (zone->type) {
5947         case dns_zone_slave:
5948         case dns_zone_stub:
5949                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
5950                     isc_time_compare(&now, &zone->refreshtime) >= 0)
5951                         dns_zone_refresh(zone);
5952                 break;
5953         default:
5954                 break;
5955         }
5956
5957         /*
5958          * Do we need to consolidate the backing store?
5959          */
5960         switch (zone->type) {
5961         case dns_zone_master:
5962         case dns_zone_slave:
5963                 LOCK_ZONE(zone);
5964                 if (zone->masterfile != NULL &&
5965                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
5966                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
5967                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
5968                         dumping = was_dumping(zone);
5969                 } else
5970                         dumping = ISC_TRUE;
5971                 UNLOCK_ZONE(zone);
5972                 if (!dumping) {
5973                         result = zone_dump(zone, ISC_TRUE); /* task locked */
5974                         if (result != ISC_R_SUCCESS)
5975                                 dns_zone_log(zone, ISC_LOG_WARNING,
5976                                              "dump failed: %s",
5977                                              dns_result_totext(result));
5978                 }
5979                 break;
5980         default:
5981                 break;
5982         }
5983
5984         switch (zone->type) {
5985         case dns_zone_master:
5986         case dns_zone_slave:
5987                 /*
5988                  * Do we need to send out notify messages?
5989                  */
5990                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
5991                     isc_time_compare(&now, &zone->notifytime) >= 0)
5992                         zone_notify(zone, &now);
5993                 /*
5994                  * Do we need to sign/resign some RRsets?
5995                  */
5996                 if (!isc_time_isepoch(&zone->signingtime) &&
5997                     isc_time_compare(&now, &zone->signingtime) >= 0)
5998                         zone_sign(zone);
5999                 else if (!isc_time_isepoch(&zone->resigntime) &&
6000                     isc_time_compare(&now, &zone->resigntime) >= 0)
6001                         zone_resigninc(zone);
6002                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
6003                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
6004                         zone_nsec3chain(zone);
6005                 /*
6006                  * Do we need to issue a key expiry warning.
6007                  */
6008                 if (!isc_time_isepoch(&zone->keywarntime) &&
6009                     isc_time_compare(&now, &zone->keywarntime) >= 0)
6010                         set_key_expiry_warning(zone, zone->key_expiry,
6011                                                isc_time_seconds(&now));
6012                 break;
6013         default:
6014                 break;
6015         }
6016         zone_settimer(zone, &now);
6017 }
6018
6019 void
6020 dns_zone_markdirty(dns_zone_t *zone) {
6021
6022         LOCK_ZONE(zone);
6023         set_resigntime(zone);   /* XXXMPA make separate call back */
6024         zone_needdump(zone, DNS_DUMP_DELAY);
6025         UNLOCK_ZONE(zone);
6026 }
6027
6028 void
6029 dns_zone_expire(dns_zone_t *zone) {
6030         REQUIRE(DNS_ZONE_VALID(zone));
6031
6032         LOCK_ZONE(zone);
6033         zone_expire(zone);
6034         UNLOCK_ZONE(zone);
6035 }
6036
6037 static void
6038 zone_expire(dns_zone_t *zone) {
6039         /*
6040          * 'zone' locked by caller.
6041          */
6042
6043         REQUIRE(LOCKED_ZONE(zone));
6044
6045         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
6046
6047         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
6048         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
6049         zone->retry = DNS_ZONE_DEFAULTRETRY;
6050         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
6051         zone_unload(zone);
6052 }
6053
6054 void
6055 dns_zone_refresh(dns_zone_t *zone) {
6056         isc_interval_t i;
6057         isc_uint32_t oldflags;
6058         unsigned int j;
6059         isc_result_t result;
6060
6061         REQUIRE(DNS_ZONE_VALID(zone));
6062
6063         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
6064                 return;
6065
6066         /*
6067          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
6068          * in progress at a time.
6069          */
6070
6071         LOCK_ZONE(zone);
6072         oldflags = zone->flags;
6073         if (zone->masterscnt == 0) {
6074                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
6075                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
6076                         dns_zone_log(zone, ISC_LOG_ERROR,
6077                                      "cannot refresh: no masters");
6078                 goto unlock;
6079         }
6080         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
6081         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
6082         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
6083         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
6084                 goto unlock;
6085
6086         /*
6087          * Set the next refresh time as if refresh check has failed.
6088          * Setting this to the retry time will do that.  XXXMLG
6089          * If we are successful it will be reset using zone->refresh.
6090          */
6091         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
6092                          0);
6093         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
6094         if (result |= ISC_R_SUCCESS)
6095                 dns_zone_log(zone, ISC_LOG_WARNING,
6096                              "isc_time_nowplusinterval() failed: %s",
6097                              dns_result_totext(result));
6098
6099         /*
6100          * When lacking user-specified timer values from the SOA,
6101          * do exponential backoff of the retry time up to a
6102          * maximum of six hours.
6103          */
6104         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
6105                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
6106
6107         zone->curmaster = 0;
6108         for (j = 0; j < zone->masterscnt; j++)
6109                 zone->mastersok[j] = ISC_FALSE;
6110         /* initiate soa query */
6111         queue_soa_query(zone);
6112  unlock:
6113         UNLOCK_ZONE(zone);
6114 }
6115
6116 isc_result_t
6117 dns_zone_flush(dns_zone_t *zone) {
6118         isc_result_t result = ISC_R_SUCCESS;
6119         isc_boolean_t dumping;
6120
6121         REQUIRE(DNS_ZONE_VALID(zone));
6122
6123         LOCK_ZONE(zone);
6124         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
6125         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
6126             zone->masterfile != NULL) {
6127                 result = ISC_R_ALREADYRUNNING;
6128                 dumping = was_dumping(zone);
6129         } else
6130                 dumping = ISC_TRUE;
6131         UNLOCK_ZONE(zone);
6132         if (!dumping)
6133                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
6134         return (result);
6135 }
6136
6137 isc_result_t
6138 dns_zone_dump(dns_zone_t *zone) {
6139         isc_result_t result = ISC_R_ALREADYRUNNING;
6140         isc_boolean_t dumping;
6141
6142         REQUIRE(DNS_ZONE_VALID(zone));
6143
6144         LOCK_ZONE(zone);
6145         dumping = was_dumping(zone);
6146         UNLOCK_ZONE(zone);
6147         if (!dumping)
6148                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
6149         return (result);
6150 }
6151
6152 static void
6153 zone_needdump(dns_zone_t *zone, unsigned int delay) {
6154         isc_time_t dumptime;
6155         isc_time_t now;
6156
6157         /*
6158          * 'zone' locked by caller
6159          */
6160
6161         REQUIRE(DNS_ZONE_VALID(zone));
6162         REQUIRE(LOCKED_ZONE(zone));
6163
6164         /*
6165          * Do we have a place to dump to and are we loaded?
6166          */
6167         if (zone->masterfile == NULL ||
6168             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
6169                 return;
6170
6171         TIME_NOW(&now);
6172         /* add some noise */
6173         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
6174
6175         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6176         if (isc_time_isepoch(&zone->dumptime) ||
6177             isc_time_compare(&zone->dumptime, &dumptime) > 0)
6178                 zone->dumptime = dumptime;
6179         if (zone->task != NULL)
6180                 zone_settimer(zone, &now);
6181 }
6182
6183 static void
6184 dump_done(void *arg, isc_result_t result) {
6185         const char me[] = "dump_done";
6186         dns_zone_t *zone = arg;
6187         dns_db_t *db;
6188         dns_dbversion_t *version;
6189         isc_boolean_t again = ISC_FALSE;
6190         isc_boolean_t compact = ISC_FALSE;
6191         isc_uint32_t serial;
6192         isc_result_t tresult;
6193
6194         REQUIRE(DNS_ZONE_VALID(zone));
6195
6196         ENTER;
6197
6198         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
6199             zone->journalsize != -1) {
6200
6201                 /*
6202                  * We don't own these, zone->dctx must stay valid.
6203                  */
6204                 db = dns_dumpctx_db(zone->dctx);
6205                 version = dns_dumpctx_version(zone->dctx);
6206
6207                 tresult = dns_db_getsoaserial(db, version, &serial);
6208                 /*
6209                  * Note: we are task locked here so we can test
6210                  * zone->xfr safely.
6211                  */
6212                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
6213                         tresult = dns_journal_compact(zone->mctx,
6214                                                       zone->journal,
6215                                                       serial,
6216                                                       zone->journalsize);
6217                         switch (tresult) {
6218                         case ISC_R_SUCCESS:
6219                         case ISC_R_NOSPACE:
6220                         case ISC_R_NOTFOUND:
6221                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
6222                                              "dns_journal_compact: %s",
6223                                              dns_result_totext(tresult));
6224                                 break;
6225                         default:
6226                                 dns_zone_log(zone, ISC_LOG_ERROR,
6227                                              "dns_journal_compact failed: %s",
6228                                              dns_result_totext(tresult));
6229                                 break;
6230                         }
6231                 } else if (tresult == ISC_R_SUCCESS) {
6232                         compact = ISC_TRUE;
6233                         zone->compact_serial = serial;
6234                 }
6235         }
6236
6237         LOCK_ZONE(zone);
6238         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
6239         if (compact)
6240                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
6241         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
6242                 /*
6243                  * Try again in a short while.
6244                  */
6245                 zone_needdump(zone, DNS_DUMP_DELAY);
6246         } else if (result == ISC_R_SUCCESS &&
6247                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
6248                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
6249                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
6250                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6251                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6252                 isc_time_settoepoch(&zone->dumptime);
6253                 again = ISC_TRUE;
6254         } else if (result == ISC_R_SUCCESS)
6255                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
6256
6257         if (zone->dctx != NULL)
6258                 dns_dumpctx_detach(&zone->dctx);
6259         zonemgr_putio(&zone->writeio);
6260         UNLOCK_ZONE(zone);
6261         if (again)
6262                 (void)zone_dump(zone, ISC_FALSE);
6263         dns_zone_idetach(&zone);
6264 }
6265
6266 static isc_result_t
6267 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
6268         const char me[] = "zone_dump";
6269         isc_result_t result;
6270         dns_dbversion_t *version = NULL;
6271         isc_boolean_t again;
6272         dns_db_t *db = NULL;
6273         char *masterfile = NULL;
6274         dns_masterformat_t masterformat = dns_masterformat_none;
6275
6276 /*
6277  * 'compact' MUST only be set if we are task locked.
6278  */
6279
6280         REQUIRE(DNS_ZONE_VALID(zone));
6281         ENTER;
6282
6283  redo:
6284         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6285         if (zone->db != NULL)
6286                 dns_db_attach(zone->db, &db);
6287         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6288         LOCK_ZONE(zone);
6289         if (zone->masterfile != NULL) {
6290                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
6291                 masterformat = zone->masterformat;
6292         }
6293         UNLOCK_ZONE(zone);
6294         if (db == NULL) {
6295                 result = DNS_R_NOTLOADED;
6296                 goto fail;
6297         }
6298         if (masterfile == NULL) {
6299                 result = DNS_R_NOMASTERFILE;
6300                 goto fail;
6301         }
6302
6303         if (compact) {
6304                 dns_zone_t *dummy = NULL;
6305                 LOCK_ZONE(zone);
6306                 zone_iattach(zone, &dummy);
6307                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
6308                                        zone_gotwritehandle, zone,
6309                                        &zone->writeio);
6310                 if (result != ISC_R_SUCCESS)
6311                         zone_idetach(&dummy);
6312                 else
6313                         result = DNS_R_CONTINUE;
6314                 UNLOCK_ZONE(zone);
6315         } else {
6316                 dns_db_currentversion(db, &version);
6317                 result = dns_master_dump2(zone->mctx, db, version,
6318                                           &dns_master_style_default,
6319                                           masterfile, masterformat);
6320                 dns_db_closeversion(db, &version, ISC_FALSE);
6321         }
6322  fail:
6323         if (db != NULL)
6324                 dns_db_detach(&db);
6325         if (masterfile != NULL)
6326                 isc_mem_free(zone->mctx, masterfile);
6327         masterfile = NULL;
6328
6329         if (result == DNS_R_CONTINUE)
6330                 return (ISC_R_SUCCESS); /* XXXMPA */
6331
6332         again = ISC_FALSE;
6333         LOCK_ZONE(zone);
6334         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
6335         if (result != ISC_R_SUCCESS) {
6336                 /*
6337                  * Try again in a short while.
6338                  */
6339                 zone_needdump(zone, DNS_DUMP_DELAY);
6340         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
6341                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
6342                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
6343                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6344                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6345                 isc_time_settoepoch(&zone->dumptime);
6346                 again = ISC_TRUE;
6347         } else
6348                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
6349         UNLOCK_ZONE(zone);
6350         if (again)
6351                 goto redo;
6352
6353         return (result);
6354 }
6355
6356 static isc_result_t
6357 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
6358              dns_masterformat_t format)
6359 {
6360         isc_result_t result;
6361         dns_dbversion_t *version = NULL;
6362         dns_db_t *db = NULL;
6363
6364         REQUIRE(DNS_ZONE_VALID(zone));
6365
6366         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6367         if (zone->db != NULL)
6368                 dns_db_attach(zone->db, &db);
6369         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6370         if (db == NULL)
6371                 return (DNS_R_NOTLOADED);
6372
6373         dns_db_currentversion(db, &version);
6374         result = dns_master_dumptostream2(zone->mctx, db, version, style,
6375                                           format, fd);
6376         dns_db_closeversion(db, &version, ISC_FALSE);
6377         dns_db_detach(&db);
6378         return (result);
6379 }
6380
6381 isc_result_t
6382 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
6383                        const dns_master_style_t *style) {
6384         return dumptostream(zone, fd, style, format);
6385 }
6386
6387 isc_result_t
6388 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
6389         return dumptostream(zone, fd, &dns_master_style_default,
6390                             dns_masterformat_text);
6391 }
6392
6393 isc_result_t
6394 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
6395         return dumptostream(zone, fd, &dns_master_style_full,
6396                             dns_masterformat_text);
6397 }
6398
6399 void
6400 dns_zone_unload(dns_zone_t *zone) {
6401         REQUIRE(DNS_ZONE_VALID(zone));
6402
6403         LOCK_ZONE(zone);
6404         zone_unload(zone);
6405         UNLOCK_ZONE(zone);
6406 }
6407
6408 static void
6409 notify_cancel(dns_zone_t *zone) {
6410         dns_notify_t *notify;
6411
6412         /*
6413          * 'zone' locked by caller.
6414          */
6415
6416         REQUIRE(LOCKED_ZONE(zone));
6417
6418         for (notify = ISC_LIST_HEAD(zone->notifies);
6419              notify != NULL;
6420              notify = ISC_LIST_NEXT(notify, link)) {
6421                 if (notify->find != NULL)
6422                         dns_adb_cancelfind(notify->find);
6423                 if (notify->request != NULL)
6424                         dns_request_cancel(notify->request);
6425         }
6426 }
6427
6428 static void
6429 zone_unload(dns_zone_t *zone) {
6430
6431         /*
6432          * 'zone' locked by caller.
6433          */
6434
6435         REQUIRE(LOCKED_ZONE(zone));
6436
6437         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6438         zone_detachdb(zone);
6439         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6440         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
6441         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6442 }
6443
6444 void
6445 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
6446         REQUIRE(DNS_ZONE_VALID(zone));
6447         REQUIRE(val > 0);
6448
6449         zone->minrefresh = val;
6450 }
6451
6452 void
6453 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
6454         REQUIRE(DNS_ZONE_VALID(zone));
6455         REQUIRE(val > 0);
6456
6457         zone->maxrefresh = val;
6458 }
6459
6460 void
6461 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
6462         REQUIRE(DNS_ZONE_VALID(zone));
6463         REQUIRE(val > 0);
6464
6465         zone->minretry = val;
6466 }
6467
6468 void
6469 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
6470         REQUIRE(DNS_ZONE_VALID(zone));
6471         REQUIRE(val > 0);
6472
6473         zone->maxretry = val;
6474 }
6475
6476 static isc_boolean_t
6477 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
6478         dns_notify_t *notify;
6479
6480         for (notify = ISC_LIST_HEAD(zone->notifies);
6481              notify != NULL;
6482              notify = ISC_LIST_NEXT(notify, link)) {
6483                 if (notify->request != NULL)
6484                         continue;
6485                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
6486                     dns_name_equal(name, &notify->ns))
6487                         return (ISC_TRUE);
6488                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
6489                         return (ISC_TRUE);
6490         }
6491         return (ISC_FALSE);
6492 }
6493
6494 static isc_boolean_t
6495 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
6496         dns_tsigkey_t *key = NULL;
6497         isc_sockaddr_t src;
6498         isc_sockaddr_t any;
6499         isc_boolean_t isself;
6500         isc_netaddr_t dstaddr;
6501
6502         if (zone->view == NULL || zone->isself == NULL)
6503                 return (ISC_FALSE);
6504
6505         switch (isc_sockaddr_pf(dst)) {
6506         case PF_INET:
6507                 src = zone->notifysrc4;
6508                 isc_sockaddr_any(&any);
6509                 break;
6510         case PF_INET6:
6511                 src = zone->notifysrc6;
6512                 isc_sockaddr_any6(&any);
6513                 break;
6514         default:
6515                 return (ISC_FALSE);
6516         }
6517
6518         /*
6519          * When sending from any the kernel will assign a source address
6520          * that matches the destination address.
6521          */
6522         if (isc_sockaddr_eqaddr(&any, &src))
6523                 src = *dst;
6524
6525         isc_netaddr_fromsockaddr(&dstaddr, dst);
6526         (void)dns_view_getpeertsig(zone->view, &dstaddr, &key);
6527         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
6528                                 zone->isselfarg);
6529         if (key != NULL)
6530                 dns_tsigkey_detach(&key);
6531         return (isself);
6532 }
6533
6534 static void
6535 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
6536         isc_mem_t *mctx;
6537
6538         /*
6539          * Caller holds zone lock.
6540          */
6541         REQUIRE(DNS_NOTIFY_VALID(notify));
6542
6543         if (notify->zone != NULL) {
6544                 if (!locked)
6545                         LOCK_ZONE(notify->zone);
6546                 REQUIRE(LOCKED_ZONE(notify->zone));
6547                 if (ISC_LINK_LINKED(notify, link))
6548                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
6549                 if (!locked)
6550                         UNLOCK_ZONE(notify->zone);
6551                 if (locked)
6552                         zone_idetach(&notify->zone);
6553                 else
6554                         dns_zone_idetach(&notify->zone);
6555         }
6556         if (notify->find != NULL)
6557                 dns_adb_destroyfind(&notify->find);
6558         if (notify->request != NULL)
6559                 dns_request_destroy(&notify->request);
6560         if (dns_name_dynamic(&notify->ns))
6561                 dns_name_free(&notify->ns, notify->mctx);
6562         mctx = notify->mctx;
6563         isc_mem_put(notify->mctx, notify, sizeof(*notify));
6564         isc_mem_detach(&mctx);
6565 }
6566
6567 static isc_result_t
6568 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
6569         dns_notify_t *notify;
6570
6571         REQUIRE(notifyp != NULL && *notifyp == NULL);
6572
6573         notify = isc_mem_get(mctx, sizeof(*notify));
6574         if (notify == NULL)
6575                 return (ISC_R_NOMEMORY);
6576
6577         notify->mctx = NULL;
6578         isc_mem_attach(mctx, &notify->mctx);
6579         notify->flags = flags;
6580         notify->zone = NULL;
6581         notify->find = NULL;
6582         notify->request = NULL;
6583         isc_sockaddr_any(&notify->dst);
6584         dns_name_init(&notify->ns, NULL);
6585         ISC_LINK_INIT(notify, link);
6586         notify->magic = NOTIFY_MAGIC;
6587         *notifyp = notify;
6588         return (ISC_R_SUCCESS);
6589 }
6590
6591 /*
6592  * XXXAG should check for DNS_ZONEFLG_EXITING
6593  */
6594 static void
6595 process_adb_event(isc_task_t *task, isc_event_t *ev) {
6596         dns_notify_t *notify;
6597         isc_eventtype_t result;
6598
6599         UNUSED(task);
6600
6601         notify = ev->ev_arg;
6602         REQUIRE(DNS_NOTIFY_VALID(notify));
6603         INSIST(task == notify->zone->task);
6604         result = ev->ev_type;
6605         isc_event_free(&ev);
6606         if (result == DNS_EVENT_ADBMOREADDRESSES) {
6607                 dns_adb_destroyfind(&notify->find);
6608                 notify_find_address(notify);
6609                 return;
6610         }
6611         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
6612                 LOCK_ZONE(notify->zone);
6613                 notify_send(notify);
6614                 UNLOCK_ZONE(notify->zone);
6615         }
6616         notify_destroy(notify, ISC_FALSE);
6617 }
6618
6619 static void
6620 notify_find_address(dns_notify_t *notify) {
6621         isc_result_t result;
6622         unsigned int options;
6623
6624         REQUIRE(DNS_NOTIFY_VALID(notify));
6625         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
6626                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
6627
6628         if (notify->zone->view->adb == NULL)
6629                 goto destroy;
6630
6631         result = dns_adb_createfind(notify->zone->view->adb,
6632                                     notify->zone->task,
6633                                     process_adb_event, notify,
6634                                     &notify->ns, dns_rootname, 0,
6635                                     options, 0, NULL,
6636                                     notify->zone->view->dstport,
6637                                     &notify->find);
6638
6639         /* Something failed? */
6640         if (result != ISC_R_SUCCESS)
6641                 goto destroy;
6642
6643         /* More addresses pending? */
6644         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
6645                 return;
6646
6647         /* We have as many addresses as we can get. */
6648         LOCK_ZONE(notify->zone);
6649         notify_send(notify);
6650         UNLOCK_ZONE(notify->zone);
6651
6652  destroy:
6653         notify_destroy(notify, ISC_FALSE);
6654 }
6655
6656
6657 static isc_result_t
6658 notify_send_queue(dns_notify_t *notify) {
6659         isc_event_t *e;
6660         isc_result_t result;
6661
6662         e = isc_event_allocate(notify->mctx, NULL,
6663                                DNS_EVENT_NOTIFYSENDTOADDR,
6664                                notify_send_toaddr,
6665                                notify, sizeof(isc_event_t));
6666         if (e == NULL)
6667                 return (ISC_R_NOMEMORY);
6668         e->ev_arg = notify;
6669         e->ev_sender = NULL;
6670         result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
6671                                          notify->zone->task, &e);
6672         if (result != ISC_R_SUCCESS)
6673                 isc_event_free(&e);
6674         return (result);
6675 }
6676
6677 static void
6678 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
6679         dns_notify_t *notify;
6680         isc_result_t result;
6681         dns_message_t *message = NULL;
6682         isc_netaddr_t dstip;
6683         dns_tsigkey_t *key = NULL;
6684         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6685         isc_sockaddr_t src;
6686         int timeout;
6687         isc_boolean_t have_notifysource = ISC_FALSE;
6688
6689         notify = event->ev_arg;
6690         REQUIRE(DNS_NOTIFY_VALID(notify));
6691
6692         UNUSED(task);
6693
6694         LOCK_ZONE(notify->zone);
6695
6696         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
6697                 result = ISC_R_CANCELED;
6698                 goto cleanup;
6699         }
6700
6701         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
6702             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
6703             notify->zone->view->requestmgr == NULL ||
6704             notify->zone->db == NULL) {
6705                 result = ISC_R_CANCELED;
6706                 goto cleanup;
6707         }
6708
6709         /*
6710          * The raw IPv4 address should also exist.  Don't send to the
6711          * mapped form.
6712          */
6713         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
6714             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
6715                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
6716                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
6717                            "notify: ignoring IPv6 mapped IPV4 address: %s",
6718                            addrbuf);
6719                 result = ISC_R_CANCELED;
6720                 goto cleanup;
6721         }
6722
6723         result = notify_createmessage(notify->zone, notify->flags, &message);
6724         if (result != ISC_R_SUCCESS)
6725                 goto cleanup;
6726
6727         isc_netaddr_fromsockaddr(&dstip, &notify->dst);
6728         (void)dns_view_getpeertsig(notify->zone->view, &dstip, &key);
6729
6730         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
6731         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
6732                    addrbuf);
6733         if (notify->zone->view->peers != NULL) {
6734                 dns_peer_t *peer = NULL;
6735                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
6736                                                  &dstip, &peer);
6737                 if (result == ISC_R_SUCCESS) {
6738                         result = dns_peer_getnotifysource(peer, &src);
6739                         if (result == ISC_R_SUCCESS)
6740                                 have_notifysource = ISC_TRUE;
6741                 }
6742         }
6743         switch (isc_sockaddr_pf(&notify->dst)) {
6744         case PF_INET:
6745                 if (!have_notifysource)
6746                         src = notify->zone->notifysrc4;
6747                 break;
6748         case PF_INET6:
6749                 if (!have_notifysource)
6750                         src = notify->zone->notifysrc6;
6751                 break;
6752         default:
6753                 result = ISC_R_NOTIMPLEMENTED;
6754                 goto cleanup_key;
6755         }
6756         timeout = 15;
6757         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
6758                 timeout = 30;
6759         result = dns_request_createvia2(notify->zone->view->requestmgr,
6760                                         message, &src, &notify->dst, 0, key,
6761                                         timeout * 3, timeout,
6762                                         notify->zone->task, notify_done,
6763                                         notify, &notify->request);
6764         if (result == ISC_R_SUCCESS) {
6765                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
6766                         inc_stats(notify->zone,
6767                                   dns_zonestatscounter_notifyoutv4);
6768                 } else {
6769                         inc_stats(notify->zone,
6770                                   dns_zonestatscounter_notifyoutv6);
6771                 }
6772         }
6773
6774  cleanup_key:
6775         if (key != NULL)
6776                 dns_tsigkey_detach(&key);
6777         dns_message_destroy(&message);
6778  cleanup:
6779         UNLOCK_ZONE(notify->zone);
6780         if (result != ISC_R_SUCCESS)
6781                 notify_destroy(notify, ISC_FALSE);
6782         isc_event_free(&event);
6783 }
6784
6785 static void
6786 notify_send(dns_notify_t *notify) {
6787         dns_adbaddrinfo_t *ai;
6788         isc_sockaddr_t dst;
6789         isc_result_t result;
6790         dns_notify_t *new = NULL;
6791
6792         /*
6793          * Zone lock held by caller.
6794          */
6795         REQUIRE(DNS_NOTIFY_VALID(notify));
6796         REQUIRE(LOCKED_ZONE(notify->zone));
6797
6798         for (ai = ISC_LIST_HEAD(notify->find->list);
6799              ai != NULL;
6800              ai = ISC_LIST_NEXT(ai, publink)) {
6801                 dst = ai->sockaddr;
6802                 if (notify_isqueued(notify->zone, NULL, &dst))
6803                         continue;
6804                 if (notify_isself(notify->zone, &dst))
6805                         continue;
6806                 new = NULL;
6807                 result = notify_create(notify->mctx,
6808                                        (notify->flags & DNS_NOTIFY_NOSOA),
6809                                        &new);
6810                 if (result != ISC_R_SUCCESS)
6811                         goto cleanup;
6812                 zone_iattach(notify->zone, &new->zone);
6813                 ISC_LIST_APPEND(new->zone->notifies, new, link);
6814                 new->dst = dst;
6815                 result = notify_send_queue(new);
6816                 if (result != ISC_R_SUCCESS)
6817                         goto cleanup;
6818                 new = NULL;
6819         }
6820
6821  cleanup:
6822         if (new != NULL)
6823                 notify_destroy(new, ISC_TRUE);
6824 }
6825
6826 void
6827 dns_zone_notify(dns_zone_t *zone) {
6828         isc_time_t now;
6829
6830         REQUIRE(DNS_ZONE_VALID(zone));
6831
6832         LOCK_ZONE(zone);
6833         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6834
6835         TIME_NOW(&now);
6836         zone_settimer(zone, &now);
6837         UNLOCK_ZONE(zone);
6838 }
6839
6840 static void
6841 zone_notify(dns_zone_t *zone, isc_time_t *now) {
6842         dns_dbnode_t *node = NULL;
6843         dns_db_t *zonedb = NULL;
6844         dns_dbversion_t *version = NULL;
6845         dns_name_t *origin = NULL;
6846         dns_name_t master;
6847         dns_rdata_ns_t ns;
6848         dns_rdata_soa_t soa;
6849         isc_uint32_t serial;
6850         dns_rdata_t rdata = DNS_RDATA_INIT;
6851         dns_rdataset_t nsrdset;
6852         dns_rdataset_t soardset;
6853         isc_result_t result;
6854         dns_notify_t *notify = NULL;
6855         unsigned int i;
6856         isc_sockaddr_t dst;
6857         isc_boolean_t isqueued;
6858         dns_notifytype_t notifytype;
6859         unsigned int flags = 0;
6860         isc_boolean_t loggednotify = ISC_FALSE;
6861
6862         REQUIRE(DNS_ZONE_VALID(zone));
6863
6864         LOCK_ZONE(zone);
6865         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6866         notifytype = zone->notifytype;
6867         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
6868         UNLOCK_ZONE(zone);
6869
6870         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
6871                 return;
6872
6873         if (notifytype == dns_notifytype_no)
6874                 return;
6875
6876         if (notifytype == dns_notifytype_masteronly &&
6877             zone->type != dns_zone_master)
6878                 return;
6879
6880         origin = &zone->origin;
6881
6882         /*
6883          * If the zone is dialup we are done as we don't want to send
6884          * the current soa so as to force a refresh query.
6885          */
6886         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
6887                 flags |= DNS_NOTIFY_NOSOA;
6888
6889         /*
6890          * Get SOA RRset.
6891          */
6892         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6893         if (zone->db != NULL)
6894                 dns_db_attach(zone->db, &zonedb);
6895         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6896         if (zonedb == NULL)
6897                 return;
6898         dns_db_currentversion(zonedb, &version);
6899         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
6900         if (result != ISC_R_SUCCESS)
6901                 goto cleanup1;
6902
6903         dns_rdataset_init(&soardset);
6904         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
6905                                      dns_rdatatype_none, 0, &soardset, NULL);
6906         if (result != ISC_R_SUCCESS)
6907                 goto cleanup2;
6908
6909         /*
6910          * Find serial and master server's name.
6911          */
6912         dns_name_init(&master, NULL);
6913         result = dns_rdataset_first(&soardset);
6914         if (result != ISC_R_SUCCESS)
6915                 goto cleanup3;
6916         dns_rdataset_current(&soardset, &rdata);
6917         result = dns_rdata_tostruct(&rdata, &soa, NULL);
6918         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6919         dns_rdata_reset(&rdata);
6920         result = dns_name_dup(&soa.origin, zone->mctx, &master);
6921         serial = soa.serial;
6922         dns_rdataset_disassociate(&soardset);
6923         if (result != ISC_R_SUCCESS)
6924                 goto cleanup3;
6925
6926         /*
6927          * Enqueue notify requests for 'also-notify' servers.
6928          */
6929         LOCK_ZONE(zone);
6930         for (i = 0; i < zone->notifycnt; i++) {
6931                 dst = zone->notify[i];
6932                 if (notify_isqueued(zone, NULL, &dst))
6933                         continue;
6934                 result = notify_create(zone->mctx, flags, &notify);
6935                 if (result != ISC_R_SUCCESS)
6936                         continue;
6937                 zone_iattach(zone, &notify->zone);
6938                 notify->dst = dst;
6939                 ISC_LIST_APPEND(zone->notifies, notify, link);
6940                 result = notify_send_queue(notify);
6941                 if (result != ISC_R_SUCCESS)
6942                         notify_destroy(notify, ISC_TRUE);
6943                 if (!loggednotify) {
6944                         notify_log(zone, ISC_LOG_INFO,
6945                                    "sending notifies (serial %u)",
6946                                    serial);
6947                         loggednotify = ISC_TRUE;
6948                 }
6949                 notify = NULL;
6950         }
6951         UNLOCK_ZONE(zone);
6952
6953         if (notifytype == dns_notifytype_explicit)
6954                 goto cleanup3;
6955
6956         /*
6957          * Process NS RRset to generate notifies.
6958          */
6959
6960         dns_rdataset_init(&nsrdset);
6961         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
6962                                      dns_rdatatype_none, 0, &nsrdset, NULL);
6963         if (result != ISC_R_SUCCESS)
6964                 goto cleanup3;
6965
6966         result = dns_rdataset_first(&nsrdset);
6967         while (result == ISC_R_SUCCESS) {
6968                 dns_rdataset_current(&nsrdset, &rdata);
6969                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
6970                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6971                 dns_rdata_reset(&rdata);
6972                 /*
6973                  * Don't notify the master server unless explicitly
6974                  * configured to do so.
6975                  */
6976                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
6977                     dns_name_compare(&master, &ns.name) == 0) {
6978                         result = dns_rdataset_next(&nsrdset);
6979                         continue;
6980                 }
6981
6982                 if (!loggednotify) {
6983                         notify_log(zone, ISC_LOG_INFO,
6984                                    "sending notifies (serial %u)",
6985                                    serial);
6986                         loggednotify = ISC_TRUE;
6987                 }
6988
6989                 LOCK_ZONE(zone);
6990                 isqueued = notify_isqueued(zone, &ns.name, NULL);
6991                 UNLOCK_ZONE(zone);
6992                 if (isqueued) {
6993                         result = dns_rdataset_next(&nsrdset);
6994                         continue;
6995                 }
6996                 result = notify_create(zone->mctx, flags, &notify);
6997                 if (result != ISC_R_SUCCESS)
6998                         continue;
6999                 dns_zone_iattach(zone, &notify->zone);
7000                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
7001                 if (result != ISC_R_SUCCESS) {
7002                         LOCK_ZONE(zone);
7003                         notify_destroy(notify, ISC_TRUE);
7004                         UNLOCK_ZONE(zone);
7005                         continue;
7006                 }
7007                 LOCK_ZONE(zone);
7008                 ISC_LIST_APPEND(zone->notifies, notify, link);
7009                 UNLOCK_ZONE(zone);
7010                 notify_find_address(notify);
7011                 notify = NULL;
7012                 result = dns_rdataset_next(&nsrdset);
7013         }
7014         dns_rdataset_disassociate(&nsrdset);
7015
7016  cleanup3:
7017         if (dns_name_dynamic(&master))
7018                 dns_name_free(&master, zone->mctx);
7019  cleanup2:
7020         dns_db_detachnode(zonedb, &node);
7021  cleanup1:
7022         dns_db_closeversion(zonedb, &version, ISC_FALSE);
7023         dns_db_detach(&zonedb);
7024 }
7025
7026 /***
7027  *** Private
7028  ***/
7029
7030 static inline isc_result_t
7031 save_nsrrset(dns_message_t *message, dns_name_t *name,
7032              dns_db_t *db, dns_dbversion_t *version)
7033 {
7034         dns_rdataset_t *nsrdataset = NULL;
7035         dns_rdataset_t *rdataset = NULL;
7036         dns_dbnode_t *node = NULL;
7037         dns_rdata_ns_t ns;
7038         isc_result_t result;
7039         dns_rdata_t rdata = DNS_RDATA_INIT;
7040
7041         /*
7042          * Extract NS RRset from message.
7043          */
7044         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
7045                                       dns_rdatatype_ns, dns_rdatatype_none,
7046                                       NULL, &nsrdataset);
7047         if (result != ISC_R_SUCCESS)
7048                 goto fail;
7049
7050         /*
7051          * Add NS rdataset.
7052          */
7053         result = dns_db_findnode(db, name, ISC_TRUE, &node);
7054         if (result != ISC_R_SUCCESS)
7055                 goto fail;
7056         result = dns_db_addrdataset(db, node, version, 0,
7057                                     nsrdataset, 0, NULL);
7058         dns_db_detachnode(db, &node);
7059         if (result != ISC_R_SUCCESS)
7060                 goto fail;
7061         /*
7062          * Add glue rdatasets.
7063          */
7064         for (result = dns_rdataset_first(nsrdataset);
7065              result == ISC_R_SUCCESS;
7066              result = dns_rdataset_next(nsrdataset)) {
7067                 dns_rdataset_current(nsrdataset, &rdata);
7068                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
7069                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7070                 dns_rdata_reset(&rdata);
7071                 if (!dns_name_issubdomain(&ns.name, name))
7072                         continue;
7073                 rdataset = NULL;
7074                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
7075                                               &ns.name, dns_rdatatype_aaaa,
7076                                               dns_rdatatype_none, NULL,
7077                                               &rdataset);
7078                 if (result == ISC_R_SUCCESS) {
7079                         result = dns_db_findnode(db, &ns.name,
7080                                                  ISC_TRUE, &node);
7081                         if (result != ISC_R_SUCCESS)
7082                                 goto fail;
7083                         result = dns_db_addrdataset(db, node, version, 0,
7084                                                     rdataset, 0, NULL);
7085                         dns_db_detachnode(db, &node);
7086                         if (result != ISC_R_SUCCESS)
7087                                 goto fail;
7088                 }
7089                 rdataset = NULL;
7090                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
7091                                               &ns.name, dns_rdatatype_a,
7092                                               dns_rdatatype_none, NULL,
7093                                               &rdataset);
7094                 if (result == ISC_R_SUCCESS) {
7095                         result = dns_db_findnode(db, &ns.name,
7096                                                  ISC_TRUE, &node);
7097                         if (result != ISC_R_SUCCESS)
7098                                 goto fail;
7099                         result = dns_db_addrdataset(db, node, version, 0,
7100                                                     rdataset, 0, NULL);
7101                         dns_db_detachnode(db, &node);
7102                         if (result != ISC_R_SUCCESS)
7103                                 goto fail;
7104                 }
7105         }
7106         if (result != ISC_R_NOMORE)
7107                 goto fail;
7108
7109         return (ISC_R_SUCCESS);
7110
7111 fail:
7112         return (result);
7113 }
7114
7115 static void
7116 stub_callback(isc_task_t *task, isc_event_t *event) {
7117         const char me[] = "stub_callback";
7118         dns_requestevent_t *revent = (dns_requestevent_t *)event;
7119         dns_stub_t *stub = NULL;
7120         dns_message_t *msg = NULL;
7121         dns_zone_t *zone = NULL;
7122         char master[ISC_SOCKADDR_FORMATSIZE];
7123         char source[ISC_SOCKADDR_FORMATSIZE];
7124         isc_uint32_t nscnt, cnamecnt;
7125         isc_result_t result;
7126         isc_time_t now;
7127         isc_boolean_t exiting = ISC_FALSE;
7128         isc_interval_t i;
7129         unsigned int j;
7130
7131         stub = revent->ev_arg;
7132         INSIST(DNS_STUB_VALID(stub));
7133
7134         UNUSED(task);
7135
7136         zone = stub->zone;
7137
7138         ENTER;
7139
7140         TIME_NOW(&now);
7141
7142         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
7143                 zone_debuglog(zone, me, 1, "exiting");
7144                 exiting = ISC_TRUE;
7145                 goto next_master;
7146         }
7147
7148         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
7149         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
7150
7151         if (revent->result != ISC_R_SUCCESS) {
7152                 if (revent->result == ISC_R_TIMEDOUT &&
7153                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
7154                         LOCK_ZONE(zone);
7155                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
7156                         UNLOCK_ZONE(zone);
7157                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
7158                                      "refreshing stub: timeout retrying "
7159                                      " without EDNS master %s (source %s)",
7160                                      master, source);
7161                         goto same_master;
7162                 }
7163                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
7164                                            &zone->sourceaddr, &now);
7165                 dns_zone_log(zone, ISC_LOG_INFO,
7166                              "could not refresh stub from master %s"
7167                              " (source %s): %s", master, source,
7168                              dns_result_totext(revent->result));
7169                 goto next_master;
7170         }
7171
7172         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
7173         if (result != ISC_R_SUCCESS)
7174                 goto next_master;
7175
7176         result = dns_request_getresponse(revent->request, msg, 0);
7177         if (result != ISC_R_SUCCESS)
7178                 goto next_master;
7179
7180         /*
7181          * Unexpected rcode.
7182          */
7183         if (msg->rcode != dns_rcode_noerror) {
7184                 char rcode[128];
7185                 isc_buffer_t rb;
7186
7187                 isc_buffer_init(&rb, rcode, sizeof(rcode));
7188                 (void)dns_rcode_totext(msg->rcode, &rb);
7189
7190                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
7191                     (msg->rcode == dns_rcode_servfail ||
7192                      msg->rcode == dns_rcode_notimp ||
7193                      msg->rcode == dns_rcode_formerr)) {
7194                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
7195                                      "refreshing stub: rcode (%.*s) retrying "
7196                                      "without EDNS master %s (source %s)",
7197                                      (int)rb.used, rcode, master, source);
7198                         LOCK_ZONE(zone);
7199                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
7200                         UNLOCK_ZONE(zone);
7201                         goto same_master;
7202                 }
7203
7204                 dns_zone_log(zone, ISC_LOG_INFO,
7205                              "refreshing stub: "
7206                              "unexpected rcode (%.*s) from %s (source %s)",
7207                              (int)rb.used, rcode, master, source);
7208                 goto next_master;
7209         }
7210
7211         /*
7212          * We need complete messages.
7213          */
7214         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
7215                 if (dns_request_usedtcp(revent->request)) {
7216                         dns_zone_log(zone, ISC_LOG_INFO,
7217                                      "refreshing stub: truncated TCP "
7218                                      "response from master %s (source %s)",
7219                                      master, source);
7220                         goto next_master;
7221                 }
7222                 LOCK_ZONE(zone);
7223                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
7224                 UNLOCK_ZONE(zone);
7225                 goto same_master;
7226         }
7227
7228         /*
7229          * If non-auth log and next master.
7230          */
7231         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
7232                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
7233                              "non-authoritative answer from "
7234                              "master %s (source %s)", master, source);
7235                 goto next_master;
7236         }
7237
7238         /*
7239          * Sanity checks.
7240          */
7241         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
7242         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
7243
7244         if (cnamecnt != 0) {
7245                 dns_zone_log(zone, ISC_LOG_INFO,
7246                              "refreshing stub: unexpected CNAME response "
7247                              "from master %s (source %s)", master, source);
7248                 goto next_master;
7249         }
7250
7251         if (nscnt == 0) {
7252                 dns_zone_log(zone, ISC_LOG_INFO,
7253                              "refreshing stub: no NS records in response "
7254                              "from master %s (source %s)", master, source);
7255                 goto next_master;
7256         }
7257
7258         /*
7259          * Save answer.
7260          */
7261         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
7262         if (result != ISC_R_SUCCESS) {
7263                 dns_zone_log(zone, ISC_LOG_INFO,
7264                              "refreshing stub: unable to save NS records "
7265                              "from master %s (source %s)", master, source);
7266                 goto next_master;
7267         }
7268
7269         /*
7270          * Tidy up.
7271          */
7272         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
7273         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
7274         if (zone->db == NULL)
7275                 zone_attachdb(zone, stub->db);
7276         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
7277         dns_db_detach(&stub->db);
7278
7279         if (zone->masterfile != NULL) {
7280                 dns_zone_dump(zone);
7281                 TIME_NOW(&zone->loadtime);
7282         }
7283
7284         dns_message_destroy(&msg);
7285         isc_event_free(&event);
7286         LOCK_ZONE(zone);
7287         dns_request_destroy(&zone->request);
7288         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
7289         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
7290         isc_interval_set(&i, zone->expire, 0);
7291         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
7292         zone_settimer(zone, &now);
7293         UNLOCK_ZONE(zone);
7294         goto free_stub;
7295
7296  next_master:
7297         if (stub->version != NULL)
7298                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
7299         if (stub->db != NULL)
7300                 dns_db_detach(&stub->db);
7301         if (msg != NULL)
7302                 dns_message_destroy(&msg);
7303         isc_event_free(&event);
7304         LOCK_ZONE(zone);
7305         dns_request_destroy(&zone->request);
7306         /*
7307          * Skip to next failed / untried master.
7308          */
7309         do {
7310                 zone->curmaster++;
7311         } while (zone->curmaster < zone->masterscnt &&
7312                  zone->mastersok[zone->curmaster]);
7313         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
7314         if (exiting || zone->curmaster >= zone->masterscnt) {
7315                 isc_boolean_t done = ISC_TRUE;
7316                 if (!exiting &&
7317                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
7318                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
7319                         /*
7320                          * Did we get a good answer from all the masters?
7321                          */
7322                         for (j = 0; j < zone->masterscnt; j++)
7323                                 if (zone->mastersok[j] == ISC_FALSE) {
7324                                         done = ISC_FALSE;
7325                                         break;
7326                                 }
7327                 } else
7328                         done = ISC_TRUE;
7329                 if (!done) {
7330                         zone->curmaster = 0;
7331                         /*
7332                          * Find the next failed master.
7333                          */
7334                         while (zone->curmaster < zone->masterscnt &&
7335                                zone->mastersok[zone->curmaster])
7336                                 zone->curmaster++;
7337                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
7338                 } else {
7339                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
7340
7341                         zone_settimer(zone, &now);
7342                         UNLOCK_ZONE(zone);
7343                         goto free_stub;
7344                 }
7345         }
7346         queue_soa_query(zone);
7347         UNLOCK_ZONE(zone);
7348         goto free_stub;
7349
7350  same_master:
7351         if (msg != NULL)
7352                 dns_message_destroy(&msg);
7353         isc_event_free(&event);
7354         LOCK_ZONE(zone);
7355         dns_request_destroy(&zone->request);
7356         UNLOCK_ZONE(zone);
7357         ns_query(zone, NULL, stub);
7358         goto done;
7359
7360  free_stub:
7361         stub->magic = 0;
7362         dns_zone_idetach(&stub->zone);
7363         INSIST(stub->db == NULL);
7364         INSIST(stub->version == NULL);
7365         isc_mem_put(stub->mctx, stub, sizeof(*stub));
7366
7367  done:
7368         INSIST(event == NULL);
7369         return;
7370 }
7371
7372 /*
7373  * An SOA query has finished (successfully or not).
7374  */
7375 static void
7376 refresh_callback(isc_task_t *task, isc_event_t *event) {
7377         const char me[] = "refresh_callback";
7378         dns_requestevent_t *revent = (dns_requestevent_t *)event;
7379         dns_zone_t *zone;
7380         dns_message_t *msg = NULL;
7381         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
7382         isc_time_t now;
7383         char master[ISC_SOCKADDR_FORMATSIZE];
7384         char source[ISC_SOCKADDR_FORMATSIZE];
7385         dns_rdataset_t *rdataset = NULL;
7386         dns_rdata_t rdata = DNS_RDATA_INIT;
7387         dns_rdata_soa_t soa;
7388         isc_result_t result;
7389         isc_uint32_t serial;
7390         unsigned int j;
7391
7392         zone = revent->ev_arg;
7393         INSIST(DNS_ZONE_VALID(zone));
7394
7395         UNUSED(task);
7396
7397         ENTER;
7398
7399         /*
7400          * if timeout log and next master;
7401          */
7402
7403         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
7404         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
7405
7406         TIME_NOW(&now);
7407
7408         if (revent->result != ISC_R_SUCCESS) {
7409                 if (revent->result == ISC_R_TIMEDOUT &&
7410                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
7411                         LOCK_ZONE(zone);
7412                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
7413                         UNLOCK_ZONE(zone);
7414                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
7415                                      "refresh: timeout retrying without EDNS "
7416                                      "master %s (source %s)", master, source);
7417                         goto same_master;
7418                 }
7419                 if (revent->result == ISC_R_TIMEDOUT &&
7420                     !dns_request_usedtcp(revent->request)) {
7421                         dns_zone_log(zone, ISC_LOG_INFO,
7422                                      "refresh: retry limit for "
7423                                      "master %s exceeded (source %s)",
7424                                      master, source);
7425                         /* Try with slave with TCP. */
7426                         if (zone->type == dns_zone_slave &&
7427                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
7428                                 if (!dns_zonemgr_unreachable(zone->zmgr,
7429                                                              &zone->masteraddr,
7430                                                              &zone->sourceaddr,
7431                                                              &now)) {
7432                                         LOCK_ZONE(zone);
7433                                         DNS_ZONE_SETFLAG(zone,
7434                                                      DNS_ZONEFLG_SOABEFOREAXFR);
7435                                         UNLOCK_ZONE(zone);
7436                                         goto tcp_transfer;
7437                                 }
7438                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
7439                                              "refresh: skipped tcp fallback"
7440                                              "as master %s (source %s) is "
7441                                              "unreachable (cached)",
7442                                               master, source);
7443                         }
7444                 } else
7445                         dns_zone_log(zone, ISC_LOG_INFO,
7446                                      "refresh: failure trying master "
7447                                      "%s (source %s): %s", master, source,
7448                                      dns_result_totext(revent->result));
7449                 goto next_master;
7450         }
7451
7452         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
7453         if (result != ISC_R_SUCCESS)
7454                 goto next_master;
7455         result = dns_request_getresponse(revent->request, msg, 0);
7456         if (result != ISC_R_SUCCESS) {
7457                 dns_zone_log(zone, ISC_LOG_INFO,
7458                              "refresh: failure trying master "
7459                              "%s (source %s): %s", master, source,
7460                              dns_result_totext(result));
7461                 goto next_master;
7462         }
7463
7464         /*
7465          * Unexpected rcode.
7466          */
7467         if (msg->rcode != dns_rcode_noerror) {
7468                 char rcode[128];
7469                 isc_buffer_t rb;
7470
7471                 isc_buffer_init(&rb, rcode, sizeof(rcode));
7472                 (void)dns_rcode_totext(msg->rcode, &rb);
7473
7474                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
7475                     (msg->rcode == dns_rcode_servfail ||
7476                      msg->rcode == dns_rcode_notimp ||
7477                      msg->rcode == dns_rcode_formerr)) {
7478                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
7479                                      "refresh: rcode (%.*s) retrying without "
7480                                      "EDNS master %s (source %s)",
7481                                      (int)rb.used, rcode, master, source);
7482                         LOCK_ZONE(zone);
7483                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
7484                         UNLOCK_ZONE(zone);
7485                         goto same_master;
7486                 }
7487                 dns_zone_log(zone, ISC_LOG_INFO,
7488                              "refresh: unexpected rcode (%.*s) from "
7489                              "master %s (source %s)", (int)rb.used, rcode,
7490                              master, source);
7491                 /*
7492                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
7493                  */
7494                 if (msg->rcode == dns_rcode_refused &&
7495                     zone->type == dns_zone_slave)
7496                         goto tcp_transfer;
7497                 goto next_master;
7498         }
7499
7500         /*
7501          * If truncated punt to zone transfer which will query again.
7502          */
7503         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
7504                 if (zone->type == dns_zone_slave) {
7505                         dns_zone_log(zone, ISC_LOG_INFO,
7506                                      "refresh: truncated UDP answer, "
7507                                      "initiating TCP zone xfer "
7508                                      "for master %s (source %s)",
7509                                      master, source);
7510                         LOCK_ZONE(zone);
7511                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
7512                         UNLOCK_ZONE(zone);
7513                         goto tcp_transfer;
7514                 } else {
7515                         INSIST(zone->type == dns_zone_stub);
7516                         if (dns_request_usedtcp(revent->request)) {
7517                                 dns_zone_log(zone, ISC_LOG_INFO,
7518                                              "refresh: truncated TCP response "
7519                                              "from master %s (source %s)",
7520                                              master, source);
7521                                 goto next_master;
7522                         }
7523                         LOCK_ZONE(zone);
7524                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
7525                         UNLOCK_ZONE(zone);
7526                         goto same_master;
7527                 }
7528         }
7529
7530         /*
7531          * if non-auth log and next master;
7532          */
7533         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
7534                 dns_zone_log(zone, ISC_LOG_INFO,
7535                              "refresh: non-authoritative answer from "
7536                              "master %s (source %s)", master, source);
7537                 goto next_master;
7538         }
7539
7540         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
7541         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
7542         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
7543         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
7544                                  dns_rdatatype_soa);
7545
7546         /*
7547          * There should not be a CNAME record at top of zone.
7548          */
7549         if (cnamecnt != 0) {
7550                 dns_zone_log(zone, ISC_LOG_INFO,
7551                              "refresh: CNAME at top of zone "
7552                              "in master %s (source %s)", master, source);
7553                 goto next_master;
7554         }
7555
7556         /*
7557          * if referral log and next master;
7558          */
7559         if (soacnt == 0 && soacount == 0 && nscount != 0) {
7560                 dns_zone_log(zone, ISC_LOG_INFO,
7561                              "refresh: referral response "
7562                              "from master %s (source %s)", master, source);
7563                 goto next_master;
7564         }
7565
7566         /*
7567          * if nodata log and next master;
7568          */
7569         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
7570                 dns_zone_log(zone, ISC_LOG_INFO,
7571                              "refresh: NODATA response "
7572                              "from master %s (source %s)", master, source);
7573                 goto next_master;
7574         }
7575
7576         /*
7577          * Only one soa at top of zone.
7578          */
7579         if (soacnt != 1) {
7580                 dns_zone_log(zone, ISC_LOG_INFO,
7581                              "refresh: answer SOA count (%d) != 1 "
7582                              "from master %s (source %s)",
7583                              soacnt, master, source);
7584                 goto next_master;
7585         }
7586         /*
7587          * Extract serial
7588          */
7589         rdataset = NULL;
7590         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
7591                                       dns_rdatatype_soa, dns_rdatatype_none,
7592                                       NULL, &rdataset);
7593         if (result != ISC_R_SUCCESS) {
7594                 dns_zone_log(zone, ISC_LOG_INFO,
7595                              "refresh: unable to get SOA record "
7596                              "from master %s (source %s)", master, source);
7597                 goto next_master;
7598         }
7599
7600         result = dns_rdataset_first(rdataset);
7601         if (result != ISC_R_SUCCESS) {
7602                 dns_zone_log(zone, ISC_LOG_INFO,
7603                              "refresh: dns_rdataset_first() failed");
7604                 goto next_master;
7605         }
7606
7607         dns_rdataset_current(rdataset, &rdata);
7608         result = dns_rdata_tostruct(&rdata, &soa, NULL);
7609         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7610
7611         serial = soa.serial;
7612
7613         zone_debuglog(zone, me, 1, "serial: new %u, old %u",
7614                       serial, zone->serial);
7615         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
7616             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
7617             isc_serial_gt(serial, zone->serial)) {
7618                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
7619                                             &zone->sourceaddr, &now)) {
7620                         dns_zone_log(zone, ISC_LOG_INFO,
7621                                      "refresh: skipping %s as master %s "
7622                                      "(source %s) is unreachable (cached)",
7623                                      zone->type == dns_zone_slave ?
7624                                      "zone transfer" : "NS query",
7625                                      master, source);
7626                         goto next_master;
7627                 }
7628  tcp_transfer:
7629                 isc_event_free(&event);
7630                 LOCK_ZONE(zone);
7631                 dns_request_destroy(&zone->request);
7632                 UNLOCK_ZONE(zone);
7633                 if (zone->type == dns_zone_slave) {
7634                         queue_xfrin(zone);
7635                 } else {
7636                         INSIST(zone->type == dns_zone_stub);
7637                         ns_query(zone, rdataset, NULL);
7638                 }
7639                 if (msg != NULL)
7640                         dns_message_destroy(&msg);
7641         } else if (isc_serial_eq(soa.serial, zone->serial)) {
7642                 if (zone->masterfile != NULL) {
7643                         result = ISC_R_FAILURE;
7644                         if (zone->journal != NULL)
7645                                 result = isc_file_settime(zone->journal, &now);
7646                         if (result == ISC_R_SUCCESS &&
7647                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
7648                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
7649                                 result = isc_file_settime(zone->masterfile,
7650                                                           &now);
7651                         } else if (result != ISC_R_SUCCESS)
7652                                 result = isc_file_settime(zone->masterfile,
7653                                                           &now);
7654                         /* Someone removed the file from underneath us! */
7655                         if (result == ISC_R_FILENOTFOUND) {
7656                                 LOCK_ZONE(zone);
7657                                 zone_needdump(zone, DNS_DUMP_DELAY);
7658                                 UNLOCK_ZONE(zone);
7659                         } else if (result != ISC_R_SUCCESS)
7660                                 dns_zone_log(zone, ISC_LOG_ERROR,
7661                                              "refresh: could not set file "
7662                                              "modification time of '%s': %s",
7663                                              zone->masterfile,
7664                                              dns_result_totext(result));
7665                 }
7666                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
7667                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
7668                 zone->mastersok[zone->curmaster] = ISC_TRUE;
7669                 goto next_master;
7670         } else {
7671                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
7672                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
7673                                      "received from master %s < ours (%u)",
7674                                      soa.serial, master, zone->serial);
7675                 else
7676                         zone_debuglog(zone, me, 1, "ahead");
7677                 zone->mastersok[zone->curmaster] = ISC_TRUE;
7678                 goto next_master;
7679         }
7680         if (msg != NULL)
7681                 dns_message_destroy(&msg);
7682         goto detach;
7683
7684  next_master:
7685         if (msg != NULL)
7686                 dns_message_destroy(&msg);
7687         isc_event_free(&event);
7688         LOCK_ZONE(zone);
7689         dns_request_destroy(&zone->request);
7690         /*
7691          * Skip to next failed / untried master.
7692          */
7693         do {
7694                 zone->curmaster++;
7695         } while (zone->curmaster < zone->masterscnt &&
7696                  zone->mastersok[zone->curmaster]);
7697         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
7698         if (zone->curmaster >= zone->masterscnt) {
7699                 isc_boolean_t done = ISC_TRUE;
7700                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
7701                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
7702                         /*
7703                          * Did we get a good answer from all the masters?
7704                          */
7705                         for (j = 0; j < zone->masterscnt; j++)
7706                                 if (zone->mastersok[j] == ISC_FALSE) {
7707                                         done = ISC_FALSE;
7708                                         break;
7709                                 }
7710                 } else
7711                         done = ISC_TRUE;
7712                 if (!done) {
7713                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
7714                         zone->curmaster = 0;
7715                         /*
7716                          * Find the next failed master.
7717                          */
7718                         while (zone->curmaster < zone->masterscnt &&
7719                                zone->mastersok[zone->curmaster])
7720                                 zone->curmaster++;
7721                         goto requeue;
7722                 }
7723                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
7724                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
7725                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
7726                         zone->refreshtime = now;
7727                 }
7728                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
7729                 zone_settimer(zone, &now);
7730                 UNLOCK_ZONE(zone);
7731                 goto detach;
7732         }
7733
7734  requeue:
7735         queue_soa_query(zone);
7736         UNLOCK_ZONE(zone);
7737         goto detach;
7738
7739  same_master:
7740         if (msg != NULL)
7741                 dns_message_destroy(&msg);
7742         isc_event_free(&event);
7743         LOCK_ZONE(zone);
7744         dns_request_destroy(&zone->request);
7745         queue_soa_query(zone);
7746         UNLOCK_ZONE(zone);
7747
7748  detach:
7749         dns_zone_idetach(&zone);
7750         return;
7751 }
7752
7753 static void
7754 queue_soa_query(dns_zone_t *zone) {
7755         const char me[] = "queue_soa_query";
7756         isc_event_t *e;
7757         dns_zone_t *dummy = NULL;
7758         isc_result_t result;
7759
7760         ENTER;
7761         /*
7762          * Locked by caller
7763          */
7764         REQUIRE(LOCKED_ZONE(zone));
7765
7766         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
7767                 cancel_refresh(zone);
7768                 return;
7769         }
7770
7771         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
7772                                soa_query, zone, sizeof(isc_event_t));
7773         if (e == NULL) {
7774                 cancel_refresh(zone);
7775                 return;
7776         }
7777
7778         /*
7779          * Attach so that we won't clean up
7780          * until the event is delivered.
7781          */
7782         zone_iattach(zone, &dummy);
7783
7784         e->ev_arg = zone;
7785         e->ev_sender = NULL;
7786         result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
7787         if (result != ISC_R_SUCCESS) {
7788                 zone_idetach(&dummy);
7789                 isc_event_free(&e);
7790                 cancel_refresh(zone);
7791         }
7792 }
7793
7794 static inline isc_result_t
7795 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
7796              dns_message_t **messagep)
7797 {
7798         dns_message_t *message = NULL;
7799         dns_name_t *qname = NULL;
7800         dns_rdataset_t *qrdataset = NULL;
7801         isc_result_t result;
7802
7803         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
7804                                     &message);
7805         if (result != ISC_R_SUCCESS)
7806                 goto cleanup;
7807
7808         message->opcode = dns_opcode_query;
7809         message->rdclass = zone->rdclass;
7810
7811         result = dns_message_gettempname(message, &qname);
7812         if (result != ISC_R_SUCCESS)
7813                 goto cleanup;
7814
7815         result = dns_message_gettemprdataset(message, &qrdataset);
7816         if (result != ISC_R_SUCCESS)
7817                 goto cleanup;
7818
7819         /*
7820          * Make question.
7821          */
7822         dns_name_init(qname, NULL);
7823         dns_name_clone(&zone->origin, qname);
7824         dns_rdataset_init(qrdataset);
7825         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
7826         ISC_LIST_APPEND(qname->list, qrdataset, link);
7827         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
7828
7829         *messagep = message;
7830         return (ISC_R_SUCCESS);
7831
7832  cleanup:
7833         if (qname != NULL)
7834                 dns_message_puttempname(message, &qname);
7835         if (qrdataset != NULL)
7836                 dns_message_puttemprdataset(message, &qrdataset);
7837         if (message != NULL)
7838                 dns_message_destroy(&message);
7839         return (result);
7840 }
7841
7842 static isc_result_t
7843 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
7844         dns_rdataset_t *rdataset = NULL;
7845         dns_rdatalist_t *rdatalist = NULL;
7846         dns_rdata_t *rdata = NULL;
7847         isc_result_t result;
7848
7849         result = dns_message_gettemprdatalist(message, &rdatalist);
7850         if (result != ISC_R_SUCCESS)
7851                 goto cleanup;
7852         result = dns_message_gettemprdata(message, &rdata);
7853         if (result != ISC_R_SUCCESS)
7854                 goto cleanup;
7855         result = dns_message_gettemprdataset(message, &rdataset);
7856         if (result != ISC_R_SUCCESS)
7857                 goto cleanup;
7858         dns_rdataset_init(rdataset);
7859
7860         rdatalist->type = dns_rdatatype_opt;
7861         rdatalist->covers = 0;
7862
7863         /*
7864          * Set Maximum UDP buffer size.
7865          */
7866         rdatalist->rdclass = udpsize;
7867
7868         /*
7869          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
7870          */
7871         rdatalist->ttl = 0;
7872
7873         /* Set EDNS options if applicable */
7874         if (reqnsid) {
7875                 unsigned char data[4];
7876                 isc_buffer_t buf;
7877
7878                 isc_buffer_init(&buf, data, sizeof(data));
7879                 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
7880                 isc_buffer_putuint16(&buf, 0);
7881                 rdata->data = data;
7882                 rdata->length = sizeof(data);
7883         } else {
7884                 rdata->data = NULL;
7885                 rdata->length = 0;
7886         }
7887
7888         rdata->rdclass = rdatalist->rdclass;
7889         rdata->type = rdatalist->type;
7890         rdata->flags = 0;
7891
7892         ISC_LIST_INIT(rdatalist->rdata);
7893         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
7894         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
7895                       == ISC_R_SUCCESS);
7896
7897         return (dns_message_setopt(message, rdataset));
7898
7899  cleanup:
7900         if (rdatalist != NULL)
7901                 dns_message_puttemprdatalist(message, &rdatalist);
7902         if (rdataset != NULL)
7903                 dns_message_puttemprdataset(message, &rdataset);
7904         if (rdata != NULL)
7905                 dns_message_puttemprdata(message, &rdata);
7906
7907         return (result);
7908 }
7909
7910 static void
7911 soa_query(isc_task_t *task, isc_event_t *event) {
7912         const char me[] = "soa_query";
7913         isc_result_t result = ISC_R_FAILURE;
7914         dns_message_t *message = NULL;
7915         dns_zone_t *zone = event->ev_arg;
7916         dns_zone_t *dummy = NULL;
7917         isc_netaddr_t masterip;
7918         dns_tsigkey_t *key = NULL;
7919         isc_uint32_t options;
7920         isc_boolean_t cancel = ISC_TRUE;
7921         int timeout;
7922         isc_boolean_t have_xfrsource, reqnsid;
7923         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
7924
7925         REQUIRE(DNS_ZONE_VALID(zone));
7926
7927         UNUSED(task);
7928
7929         ENTER;
7930
7931         LOCK_ZONE(zone);
7932         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
7933             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
7934             zone->view->requestmgr == NULL) {
7935                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
7936                         cancel = ISC_FALSE;
7937                 goto cleanup;
7938         }
7939
7940         /*
7941          * XXX Optimisation: Create message when zone is setup and reuse.
7942          */
7943         result = create_query(zone, dns_rdatatype_soa, &message);
7944         if (result != ISC_R_SUCCESS)
7945                 goto cleanup;
7946
7947  again:
7948         INSIST(zone->masterscnt > 0);
7949         INSIST(zone->curmaster < zone->masterscnt);
7950
7951         zone->masteraddr = zone->masters[zone->curmaster];
7952
7953         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
7954         /*
7955          * First, look for a tsig key in the master statement, then
7956          * try for a server key.
7957          */
7958         if ((zone->masterkeynames != NULL) &&
7959             (zone->masterkeynames[zone->curmaster] != NULL)) {
7960                 dns_view_t *view = dns_zone_getview(zone);
7961                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
7962                 result = dns_view_gettsig(view, keyname, &key);
7963                 if (result != ISC_R_SUCCESS) {
7964                         char namebuf[DNS_NAME_FORMATSIZE];
7965                         dns_name_format(keyname, namebuf, sizeof(namebuf));
7966                         dns_zone_log(zone, ISC_LOG_ERROR,
7967                                      "unable to find key: %s", namebuf);
7968                 }
7969         }
7970         if (key == NULL)
7971                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
7972
7973         have_xfrsource = ISC_FALSE;
7974         reqnsid = zone->view->requestnsid;
7975         if (zone->view->peers != NULL) {
7976                 dns_peer_t *peer = NULL;
7977                 isc_boolean_t edns;
7978                 result = dns_peerlist_peerbyaddr(zone->view->peers,
7979                                                  &masterip, &peer);
7980                 if (result == ISC_R_SUCCESS) {
7981                         result = dns_peer_getsupportedns(peer, &edns);
7982                         if (result == ISC_R_SUCCESS && !edns)
7983                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
7984                         result = dns_peer_gettransfersource(peer,
7985                                                             &zone->sourceaddr);
7986                         if (result == ISC_R_SUCCESS)
7987                                 have_xfrsource = ISC_TRUE;
7988                         if (zone->view->resolver != NULL)
7989                                 udpsize =
7990                                   dns_resolver_getudpsize(zone->view->resolver);
7991                         (void)dns_peer_getudpsize(peer, &udpsize);
7992                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
7993                 }
7994         }
7995
7996         switch (isc_sockaddr_pf(&zone->masteraddr)) {
7997         case PF_INET:
7998                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
7999                         if (isc_sockaddr_equal(&zone->altxfrsource4,
8000                                                &zone->xfrsource4))
8001                                 goto skip_master;
8002                         zone->sourceaddr = zone->altxfrsource4;
8003                 } else if (!have_xfrsource)
8004                         zone->sourceaddr = zone->xfrsource4;
8005                 break;
8006         case PF_INET6:
8007                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
8008                         if (isc_sockaddr_equal(&zone->altxfrsource6,
8009                                                &zone->xfrsource6))
8010                                 goto skip_master;
8011                         zone->sourceaddr = zone->altxfrsource6;
8012                 } else if (!have_xfrsource)
8013                         zone->sourceaddr = zone->xfrsource6;
8014                 break;
8015         default:
8016                 result = ISC_R_NOTIMPLEMENTED;
8017                 goto cleanup;
8018         }
8019
8020         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
8021                   DNS_REQUESTOPT_TCP : 0;
8022
8023         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
8024                 result = add_opt(message, udpsize, reqnsid);
8025                 if (result != ISC_R_SUCCESS)
8026                         zone_debuglog(zone, me, 1,
8027                                       "unable to add opt record: %s",
8028                                       dns_result_totext(result));
8029         }
8030
8031         zone_iattach(zone, &dummy);
8032         timeout = 15;
8033         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
8034                 timeout = 30;
8035         result = dns_request_createvia2(zone->view->requestmgr, message,
8036                                         &zone->sourceaddr, &zone->masteraddr,
8037                                         options, key, timeout * 3, timeout,
8038                                         zone->task, refresh_callback, zone,
8039                                         &zone->request);
8040         if (result != ISC_R_SUCCESS) {
8041                 zone_idetach(&dummy);
8042                 zone_debuglog(zone, me, 1,
8043                               "dns_request_createvia2() failed: %s",
8044                               dns_result_totext(result));
8045                 goto cleanup;
8046         } else {
8047                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
8048                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
8049                 else
8050                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
8051         }
8052         cancel = ISC_FALSE;
8053
8054  cleanup:
8055         if (key != NULL)
8056                 dns_tsigkey_detach(&key);
8057         if (result != ISC_R_SUCCESS)
8058                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
8059         if (message != NULL)
8060                 dns_message_destroy(&message);
8061         if (cancel)
8062                 cancel_refresh(zone);
8063         isc_event_free(&event);
8064         UNLOCK_ZONE(zone);
8065         dns_zone_idetach(&zone);
8066         return;
8067
8068  skip_master:
8069         if (key != NULL)
8070                 dns_tsigkey_detach(&key);
8071         /*
8072          * Skip to next failed / untried master.
8073          */
8074         do {
8075                 zone->curmaster++;
8076         } while (zone->curmaster < zone->masterscnt &&
8077                  zone->mastersok[zone->curmaster]);
8078         if (zone->curmaster < zone->masterscnt)
8079                 goto again;
8080         zone->curmaster = 0;
8081         goto cleanup;
8082 }
8083
8084 static void
8085 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
8086         const char me[] = "ns_query";
8087         isc_result_t result;
8088         dns_message_t *message = NULL;
8089         isc_netaddr_t masterip;
8090         dns_tsigkey_t *key = NULL;
8091         dns_dbnode_t *node = NULL;
8092         int timeout;
8093         isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
8094         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
8095
8096         REQUIRE(DNS_ZONE_VALID(zone));
8097         REQUIRE((soardataset != NULL && stub == NULL) ||
8098                 (soardataset == NULL && stub != NULL));
8099         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
8100
8101         ENTER;
8102
8103         LOCK_ZONE(zone);
8104         if (stub == NULL) {
8105                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
8106                 if (stub == NULL)
8107                         goto cleanup;
8108                 stub->magic = STUB_MAGIC;
8109                 stub->mctx = zone->mctx;
8110                 stub->zone = NULL;
8111                 stub->db = NULL;
8112                 stub->version = NULL;
8113
8114                 /*
8115                  * Attach so that the zone won't disappear from under us.
8116                  */
8117                 zone_iattach(zone, &stub->zone);
8118
8119                 /*
8120                  * If a db exists we will update it, otherwise we create a
8121                  * new one and attach it to the zone once we have the NS
8122                  * RRset and glue.
8123                  */
8124                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8125                 if (zone->db != NULL) {
8126                         dns_db_attach(zone->db, &stub->db);
8127                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8128                 } else {
8129                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8130
8131                         INSIST(zone->db_argc >= 1);
8132                         result = dns_db_create(zone->mctx, zone->db_argv[0],
8133                                                &zone->origin, dns_dbtype_stub,
8134                                                zone->rdclass,
8135                                                zone->db_argc - 1,
8136                                                zone->db_argv + 1,
8137                                                &stub->db);
8138                         if (result != ISC_R_SUCCESS) {
8139                                 dns_zone_log(zone, ISC_LOG_ERROR,
8140                                              "refreshing stub: "
8141                                              "could not create "
8142                                              "database: %s",
8143                                              dns_result_totext(result));
8144                                 goto cleanup;
8145                         }
8146                         dns_db_settask(stub->db, zone->task);
8147                 }
8148
8149                 dns_db_newversion(stub->db, &stub->version);
8150
8151                 /*
8152                  * Update SOA record.
8153                  */
8154                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
8155                                          &node);
8156                 if (result != ISC_R_SUCCESS) {
8157                         dns_zone_log(zone, ISC_LOG_INFO,
8158                                      "refreshing stub: "
8159                                      "dns_db_findnode() failed: %s",
8160                                      dns_result_totext(result));
8161                         goto cleanup;
8162                 }
8163
8164                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
8165                                             soardataset, 0, NULL);
8166                 dns_db_detachnode(stub->db, &node);
8167                 if (result != ISC_R_SUCCESS) {
8168                         dns_zone_log(zone, ISC_LOG_INFO,
8169                                      "refreshing stub: "
8170                                      "dns_db_addrdataset() failed: %s",
8171                                      dns_result_totext(result));
8172                         goto cleanup;
8173                 }
8174         }
8175
8176         /*
8177          * XXX Optimisation: Create message when zone is setup and reuse.
8178          */
8179         result = create_query(zone, dns_rdatatype_ns, &message);
8180
8181         INSIST(zone->masterscnt > 0);
8182         INSIST(zone->curmaster < zone->masterscnt);
8183         zone->masteraddr = zone->masters[zone->curmaster];
8184
8185         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
8186         /*
8187          * First, look for a tsig key in the master statement, then
8188          * try for a server key.
8189          */
8190         if ((zone->masterkeynames != NULL) &&
8191             (zone->masterkeynames[zone->curmaster] != NULL)) {
8192                 dns_view_t *view = dns_zone_getview(zone);
8193                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
8194                 result = dns_view_gettsig(view, keyname, &key);
8195                 if (result != ISC_R_SUCCESS) {
8196                         char namebuf[DNS_NAME_FORMATSIZE];
8197                         dns_name_format(keyname, namebuf, sizeof(namebuf));
8198                         dns_zone_log(zone, ISC_LOG_ERROR,
8199                                      "unable to find key: %s", namebuf);
8200                 }
8201         }
8202         if (key == NULL)
8203                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
8204
8205         reqnsid = zone->view->requestnsid;
8206         if (zone->view->peers != NULL) {
8207                 dns_peer_t *peer = NULL;
8208                 isc_boolean_t edns;
8209                 result = dns_peerlist_peerbyaddr(zone->view->peers,
8210                                                  &masterip, &peer);
8211                 if (result == ISC_R_SUCCESS) {
8212                         result = dns_peer_getsupportedns(peer, &edns);
8213                         if (result == ISC_R_SUCCESS && !edns)
8214                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
8215                         result = dns_peer_gettransfersource(peer,
8216                                                             &zone->sourceaddr);
8217                         if (result == ISC_R_SUCCESS)
8218                                 have_xfrsource = ISC_TRUE;
8219                         if (zone->view->resolver != NULL)
8220                                 udpsize =
8221                                   dns_resolver_getudpsize(zone->view->resolver);
8222                         (void)dns_peer_getudpsize(peer, &udpsize);
8223                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
8224                 }
8225
8226         }
8227         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
8228                 result = add_opt(message, udpsize, reqnsid);
8229                 if (result != ISC_R_SUCCESS)
8230                         zone_debuglog(zone, me, 1,
8231                                       "unable to add opt record: %s",
8232                                       dns_result_totext(result));
8233         }
8234
8235         /*
8236          * Always use TCP so that we shouldn't truncate in additional section.
8237          */
8238         switch (isc_sockaddr_pf(&zone->masteraddr)) {
8239         case PF_INET:
8240                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
8241                         zone->sourceaddr = zone->altxfrsource4;
8242                 else if (!have_xfrsource)
8243                         zone->sourceaddr = zone->xfrsource4;
8244                 break;
8245         case PF_INET6:
8246                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
8247                         zone->sourceaddr = zone->altxfrsource6;
8248                 else if (!have_xfrsource)
8249                         zone->sourceaddr = zone->xfrsource6;
8250                 break;
8251         default:
8252                 result = ISC_R_NOTIMPLEMENTED;
8253                 goto cleanup;
8254         }
8255         timeout = 15;
8256         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
8257                 timeout = 30;
8258         result = dns_request_createvia2(zone->view->requestmgr, message,
8259                                         &zone->sourceaddr, &zone->masteraddr,
8260                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
8261                                         timeout, zone->task, stub_callback,
8262                                         stub, &zone->request);
8263         if (result != ISC_R_SUCCESS) {
8264                 zone_debuglog(zone, me, 1,
8265                               "dns_request_createvia() failed: %s",
8266                               dns_result_totext(result));
8267                 goto cleanup;
8268         }
8269         dns_message_destroy(&message);
8270         goto unlock;
8271
8272  cleanup:
8273         cancel_refresh(zone);
8274         if (stub != NULL) {
8275                 stub->magic = 0;
8276                 if (stub->version != NULL)
8277                         dns_db_closeversion(stub->db, &stub->version,
8278                                             ISC_FALSE);
8279                 if (stub->db != NULL)
8280                         dns_db_detach(&stub->db);
8281                 if (stub->zone != NULL)
8282                         zone_idetach(&stub->zone);
8283                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
8284         }
8285         if (message != NULL)
8286                 dns_message_destroy(&message);
8287   unlock:
8288         if (key != NULL)
8289                 dns_tsigkey_detach(&key);
8290         UNLOCK_ZONE(zone);
8291         return;
8292 }
8293
8294 /*
8295  * Handle the control event.  Note that although this event causes the zone
8296  * to shut down, it is not a shutdown event in the sense of the task library.
8297  */
8298 static void
8299 zone_shutdown(isc_task_t *task, isc_event_t *event) {
8300         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
8301         isc_boolean_t free_needed, linked = ISC_FALSE;
8302
8303         UNUSED(task);
8304         REQUIRE(DNS_ZONE_VALID(zone));
8305         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
8306         INSIST(isc_refcount_current(&zone->erefs) == 0);
8307         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
8308
8309         /*
8310          * Stop things being restarted after we cancel them below.
8311          */
8312         LOCK_ZONE(zone);
8313         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
8314         UNLOCK_ZONE(zone);
8315
8316         /*
8317          * If we were waiting for xfrin quota, step out of
8318          * the queue.
8319          * If there's no zone manager, we can't be waiting for the
8320          * xfrin quota
8321          */
8322         if (zone->zmgr != NULL) {
8323                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
8324                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
8325                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
8326                                         statelink);
8327                         linked = ISC_TRUE;
8328                         zone->statelist = NULL;
8329                 }
8330                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
8331         }
8332
8333         /*
8334          * In task context, no locking required.  See zone_xfrdone().
8335          */
8336         if (zone->xfr != NULL)
8337                 dns_xfrin_shutdown(zone->xfr);
8338
8339         LOCK_ZONE(zone);
8340         if (linked) {
8341                 INSIST(zone->irefs > 0);
8342                 zone->irefs--;
8343         }
8344         if (zone->request != NULL) {
8345                 dns_request_cancel(zone->request);
8346         }
8347
8348         if (zone->readio != NULL)
8349                 zonemgr_cancelio(zone->readio);
8350
8351         if (zone->lctx != NULL)
8352                 dns_loadctx_cancel(zone->lctx);
8353
8354         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
8355             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
8356                 if (zone->writeio != NULL)
8357                         zonemgr_cancelio(zone->writeio);
8358
8359                 if (zone->dctx != NULL)
8360                         dns_dumpctx_cancel(zone->dctx);
8361         }
8362
8363         notify_cancel(zone);
8364
8365         if (zone->timer != NULL) {
8366                 isc_timer_detach(&zone->timer);
8367                 INSIST(zone->irefs > 0);
8368                 zone->irefs--;
8369         }
8370
8371         if (zone->view != NULL)
8372                 dns_view_weakdetach(&zone->view);
8373
8374         /*
8375          * We have now canceled everything set the flag to allow exit_check()
8376          * to succeed.  We must not unlock between setting this flag and
8377          * calling exit_check().
8378          */
8379         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
8380         free_needed = exit_check(zone);
8381         UNLOCK_ZONE(zone);
8382         if (free_needed)
8383                 zone_free(zone);
8384 }
8385
8386 static void
8387 zone_timer(isc_task_t *task, isc_event_t *event) {
8388         const char me[] = "zone_timer";
8389         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
8390
8391         UNUSED(task);
8392         REQUIRE(DNS_ZONE_VALID(zone));
8393
8394         ENTER;
8395
8396         zone_maintenance(zone);
8397
8398         isc_event_free(&event);
8399 }
8400
8401 static void
8402 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
8403         const char me[] = "zone_settimer";
8404         isc_time_t next;
8405         isc_result_t result;
8406
8407         REQUIRE(DNS_ZONE_VALID(zone));
8408         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
8409                 return;
8410
8411         isc_time_settoepoch(&next);
8412
8413         switch (zone->type) {
8414         case dns_zone_master:
8415                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
8416                         next = zone->notifytime;
8417                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8418                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
8419                         INSIST(!isc_time_isepoch(&zone->dumptime));
8420                         if (isc_time_isepoch(&next) ||
8421                             isc_time_compare(&zone->dumptime, &next) < 0)
8422                                 next = zone->dumptime;
8423                 }
8424                 if (!isc_time_isepoch(&zone->resigntime)) {
8425                         if (isc_time_isepoch(&next) ||
8426                             isc_time_compare(&zone->resigntime, &next) < 0)
8427                                 next = zone->resigntime;
8428                 }
8429                 if (!isc_time_isepoch(&zone->keywarntime)) {
8430                         if (isc_time_isepoch(&next) ||
8431                             isc_time_compare(&zone->keywarntime, &next) < 0)
8432                                 next = zone->keywarntime;
8433                 }
8434                 if (!isc_time_isepoch(&zone->signingtime)) {
8435                         if (isc_time_isepoch(&next) ||
8436                             isc_time_compare(&zone->signingtime, &next) < 0)
8437                                 next = zone->signingtime;
8438                 }
8439                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
8440                         if (isc_time_isepoch(&next) ||
8441                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
8442                                 next = zone->nsec3chaintime;
8443                 }
8444                 break;
8445
8446         case dns_zone_slave:
8447                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
8448                         next = zone->notifytime;
8449                 /*FALLTHROUGH*/
8450
8451         case dns_zone_stub:
8452                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
8453                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
8454                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
8455                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
8456                         INSIST(!isc_time_isepoch(&zone->refreshtime));
8457                         if (isc_time_isepoch(&next) ||
8458                             isc_time_compare(&zone->refreshtime, &next) < 0)
8459                                 next = zone->refreshtime;
8460                 }
8461                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8462                         INSIST(!isc_time_isepoch(&zone->expiretime));
8463                         if (isc_time_isepoch(&next) ||
8464                             isc_time_compare(&zone->expiretime, &next) < 0)
8465                                 next = zone->expiretime;
8466                 }
8467                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8468                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
8469                         INSIST(!isc_time_isepoch(&zone->dumptime));
8470                         if (isc_time_isepoch(&next) ||
8471                             isc_time_compare(&zone->dumptime, &next) < 0)
8472                                 next = zone->dumptime;
8473                 }
8474                 break;
8475
8476         default:
8477                 break;
8478         }
8479
8480         if (isc_time_isepoch(&next)) {
8481                 zone_debuglog(zone, me, 10, "settimer inactive");
8482                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
8483                                           NULL, NULL, ISC_TRUE);
8484                 if (result != ISC_R_SUCCESS)
8485                         dns_zone_log(zone, ISC_LOG_ERROR,
8486                                      "could not deactivate zone timer: %s",
8487                                      isc_result_totext(result));
8488         } else {
8489                 if (isc_time_compare(&next, now) <= 0)
8490                         next = *now;
8491                 result = isc_timer_reset(zone->timer, isc_timertype_once,
8492                                          &next, NULL, ISC_TRUE);
8493                 if (result != ISC_R_SUCCESS)
8494                         dns_zone_log(zone, ISC_LOG_ERROR,
8495                                      "could not reset zone timer: %s",
8496                                      isc_result_totext(result));
8497         }
8498 }
8499
8500 static void
8501 cancel_refresh(dns_zone_t *zone) {
8502         const char me[] = "cancel_refresh";
8503         isc_time_t now;
8504
8505         /*
8506          * 'zone' locked by caller.
8507          */
8508
8509         REQUIRE(DNS_ZONE_VALID(zone));
8510         REQUIRE(LOCKED_ZONE(zone));
8511
8512         ENTER;
8513
8514         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
8515         TIME_NOW(&now);
8516         zone_settimer(zone, &now);
8517 }
8518
8519 static isc_result_t
8520 notify_createmessage(dns_zone_t *zone, unsigned int flags,
8521                      dns_message_t **messagep)
8522 {
8523         dns_db_t *zonedb = NULL;
8524         dns_dbnode_t *node = NULL;
8525         dns_dbversion_t *version = NULL;
8526         dns_message_t *message = NULL;
8527         dns_rdataset_t rdataset;
8528         dns_rdata_t rdata = DNS_RDATA_INIT;
8529
8530         dns_name_t *tempname = NULL;
8531         dns_rdata_t *temprdata = NULL;
8532         dns_rdatalist_t *temprdatalist = NULL;
8533         dns_rdataset_t *temprdataset = NULL;
8534
8535         isc_result_t result;
8536         isc_region_t r;
8537         isc_buffer_t *b = NULL;
8538
8539         REQUIRE(DNS_ZONE_VALID(zone));
8540         REQUIRE(messagep != NULL && *messagep == NULL);
8541
8542         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
8543                                     &message);
8544         if (result != ISC_R_SUCCESS)
8545                 return (result);
8546
8547         message->opcode = dns_opcode_notify;
8548         message->flags |= DNS_MESSAGEFLAG_AA;
8549         message->rdclass = zone->rdclass;
8550
8551         result = dns_message_gettempname(message, &tempname);
8552         if (result != ISC_R_SUCCESS)
8553                 goto cleanup;
8554
8555         result = dns_message_gettemprdataset(message, &temprdataset);
8556         if (result != ISC_R_SUCCESS)
8557                 goto cleanup;
8558
8559         /*
8560          * Make question.
8561          */
8562         dns_name_init(tempname, NULL);
8563         dns_name_clone(&zone->origin, tempname);
8564         dns_rdataset_init(temprdataset);
8565         dns_rdataset_makequestion(temprdataset, zone->rdclass,
8566                                   dns_rdatatype_soa);
8567         ISC_LIST_APPEND(tempname->list, temprdataset, link);
8568         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
8569         tempname = NULL;
8570         temprdataset = NULL;
8571
8572         if ((flags & DNS_NOTIFY_NOSOA) != 0)
8573                 goto done;
8574
8575         result = dns_message_gettempname(message, &tempname);
8576         if (result != ISC_R_SUCCESS)
8577                 goto soa_cleanup;
8578         result = dns_message_gettemprdata(message, &temprdata);
8579         if (result != ISC_R_SUCCESS)
8580                 goto soa_cleanup;
8581         result = dns_message_gettemprdataset(message, &temprdataset);
8582         if (result != ISC_R_SUCCESS)
8583                 goto soa_cleanup;
8584         result = dns_message_gettemprdatalist(message, &temprdatalist);
8585         if (result != ISC_R_SUCCESS)
8586                 goto soa_cleanup;
8587
8588         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8589         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
8590         dns_db_attach(zone->db, &zonedb);
8591         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8592
8593         dns_name_init(tempname, NULL);
8594         dns_name_clone(&zone->origin, tempname);
8595         dns_db_currentversion(zonedb, &version);
8596         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
8597         if (result != ISC_R_SUCCESS)
8598                 goto soa_cleanup;
8599
8600         dns_rdataset_init(&rdataset);
8601         result = dns_db_findrdataset(zonedb, node, version,
8602                                      dns_rdatatype_soa,
8603                                      dns_rdatatype_none, 0, &rdataset,
8604                                      NULL);
8605         if (result != ISC_R_SUCCESS)
8606                 goto soa_cleanup;
8607         result = dns_rdataset_first(&rdataset);
8608         if (result != ISC_R_SUCCESS)
8609                 goto soa_cleanup;
8610         dns_rdataset_current(&rdataset, &rdata);
8611         dns_rdata_toregion(&rdata, &r);
8612         result = isc_buffer_allocate(zone->mctx, &b, r.length);
8613         if (result != ISC_R_SUCCESS)
8614                 goto soa_cleanup;
8615         isc_buffer_putmem(b, r.base, r.length);
8616         isc_buffer_usedregion(b, &r);
8617         dns_rdata_init(temprdata);
8618         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
8619         dns_message_takebuffer(message, &b);
8620         result = dns_rdataset_next(&rdataset);
8621         dns_rdataset_disassociate(&rdataset);
8622         if (result != ISC_R_NOMORE)
8623                 goto soa_cleanup;
8624         temprdatalist->rdclass = rdata.rdclass;
8625         temprdatalist->type = rdata.type;
8626         temprdatalist->covers = 0;
8627         temprdatalist->ttl = rdataset.ttl;
8628         ISC_LIST_INIT(temprdatalist->rdata);
8629         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
8630
8631         dns_rdataset_init(temprdataset);
8632         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
8633         if (result != ISC_R_SUCCESS)
8634                 goto soa_cleanup;
8635
8636         ISC_LIST_APPEND(tempname->list, temprdataset, link);
8637         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
8638         temprdatalist = NULL;
8639         temprdataset = NULL;
8640         temprdata = NULL;
8641         tempname = NULL;
8642
8643  soa_cleanup:
8644         if (node != NULL)
8645                 dns_db_detachnode(zonedb, &node);
8646         if (version != NULL)
8647                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
8648         if (zonedb != NULL)
8649                 dns_db_detach(&zonedb);
8650         if (tempname != NULL)
8651                 dns_message_puttempname(message, &tempname);
8652         if (temprdata != NULL)
8653                 dns_message_puttemprdata(message, &temprdata);
8654         if (temprdataset != NULL)
8655                 dns_message_puttemprdataset(message, &temprdataset);
8656         if (temprdatalist != NULL)
8657                 dns_message_puttemprdatalist(message, &temprdatalist);
8658
8659  done:
8660         *messagep = message;
8661         return (ISC_R_SUCCESS);
8662
8663  cleanup:
8664         if (tempname != NULL)
8665                 dns_message_puttempname(message, &tempname);
8666         if (temprdataset != NULL)
8667                 dns_message_puttemprdataset(message, &temprdataset);
8668         dns_message_destroy(&message);
8669         return (result);
8670 }
8671
8672 isc_result_t
8673 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
8674                        dns_message_t *msg)
8675 {
8676         unsigned int i;
8677         dns_rdata_soa_t soa;
8678         dns_rdataset_t *rdataset = NULL;
8679         dns_rdata_t rdata = DNS_RDATA_INIT;
8680         isc_result_t result;
8681         char fromtext[ISC_SOCKADDR_FORMATSIZE];
8682         int match = 0;
8683         isc_netaddr_t netaddr;
8684
8685         REQUIRE(DNS_ZONE_VALID(zone));
8686
8687         /*
8688          * If type != T_SOA return DNS_R_REFUSED.  We don't yet support
8689          * ROLLOVER.
8690          *
8691          * SOA: RFC1996
8692          * Check that 'from' is a valid notify source, (zone->masters).
8693          *      Return DNS_R_REFUSED if not.
8694          *
8695          * If the notify message contains a serial number check it
8696          * against the zones serial and return if <= current serial
8697          *
8698          * If a refresh check is progress, if so just record the
8699          * fact we received a NOTIFY and from where and return.
8700          * We will perform a new refresh check when the current one
8701          * completes. Return ISC_R_SUCCESS.
8702          *
8703          * Otherwise initiate a refresh check using 'from' as the
8704          * first address to check.  Return ISC_R_SUCCESS.
8705          */
8706
8707         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
8708
8709         /*
8710          *  We only handle NOTIFY (SOA) at the present.
8711          */
8712         LOCK_ZONE(zone);
8713         if (isc_sockaddr_pf(from) == PF_INET)
8714                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
8715         else
8716                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
8717         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
8718             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
8719                                  dns_rdatatype_soa, dns_rdatatype_none,
8720                                  NULL, NULL) != ISC_R_SUCCESS) {
8721                 UNLOCK_ZONE(zone);
8722                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
8723                         dns_zone_log(zone, ISC_LOG_NOTICE,
8724                                      "NOTIFY with no "
8725                                      "question section from: %s", fromtext);
8726                         return (DNS_R_FORMERR);
8727                 }
8728                 dns_zone_log(zone, ISC_LOG_NOTICE,
8729                              "NOTIFY zone does not match");
8730                 return (DNS_R_NOTIMP);
8731         }
8732
8733         /*
8734          * If we are a master zone just succeed.
8735          */
8736         if (zone->type == dns_zone_master) {
8737                 UNLOCK_ZONE(zone);
8738                 return (ISC_R_SUCCESS);
8739         }
8740
8741         isc_netaddr_fromsockaddr(&netaddr, from);
8742         for (i = 0; i < zone->masterscnt; i++) {
8743                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
8744                         break;
8745                 if (zone->view->aclenv.match_mapped &&
8746                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
8747                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
8748                         isc_netaddr_t na1, na2;
8749                         isc_netaddr_fromv4mapped(&na1, &netaddr);
8750                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
8751                         if (isc_netaddr_equal(&na1, &na2))
8752                                 break;
8753                 }
8754         }
8755
8756         /*
8757          * Accept notify requests from non masters if they are on
8758          * 'zone->notify_acl'.
8759          */
8760         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
8761             dns_acl_match(&netaddr, NULL, zone->notify_acl,
8762                           &zone->view->aclenv,
8763                           &match, NULL) == ISC_R_SUCCESS &&
8764             match > 0)
8765         {
8766                 /* Accept notify. */
8767         } else if (i >= zone->masterscnt) {
8768                 UNLOCK_ZONE(zone);
8769                 dns_zone_log(zone, ISC_LOG_INFO,
8770                              "refused notify from non-master: %s", fromtext);
8771                 inc_stats(zone, dns_zonestatscounter_notifyrej);
8772                 return (DNS_R_REFUSED);
8773         }
8774
8775         /*
8776          * If the zone is loaded and there are answers check the serial
8777          * to see if we need to do a refresh.  Do not worry about this
8778          * check if we are a dialup zone as we use the notify request
8779          * to trigger a refresh check.
8780          */
8781         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
8782             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8783             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
8784                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
8785                                               &zone->origin,
8786                                               dns_rdatatype_soa,
8787                                               dns_rdatatype_none, NULL,
8788                                               &rdataset);
8789                 if (result == ISC_R_SUCCESS)
8790                         result = dns_rdataset_first(rdataset);
8791                 if (result == ISC_R_SUCCESS) {
8792                         isc_uint32_t serial = 0;
8793
8794                         dns_rdataset_current(rdataset, &rdata);
8795                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
8796                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8797                         serial = soa.serial;
8798                         if (isc_serial_le(serial, zone->serial)) {
8799                           dns_zone_log(zone, ISC_LOG_INFO,
8800                                              "notify from %s: "
8801                                              "zone is up to date",
8802                                              fromtext);
8803                                 UNLOCK_ZONE(zone);
8804                                 return (ISC_R_SUCCESS);
8805                         }
8806                 }
8807         }
8808
8809         /*
8810          * If we got this far and there was a refresh in progress just
8811          * let it complete.  Record where we got the notify from so we
8812          * can perform a refresh check when the current one completes
8813          */
8814         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
8815                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
8816                 zone->notifyfrom = *from;
8817                 UNLOCK_ZONE(zone);
8818                 dns_zone_log(zone, ISC_LOG_INFO,
8819                              "notify from %s: refresh in progress, "
8820                              "refresh check queued",
8821                              fromtext);
8822                 return (ISC_R_SUCCESS);
8823         }
8824         zone->notifyfrom = *from;
8825         UNLOCK_ZONE(zone);
8826         dns_zone_refresh(zone);
8827         return (ISC_R_SUCCESS);
8828 }
8829
8830 void
8831 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
8832
8833         REQUIRE(DNS_ZONE_VALID(zone));
8834
8835         LOCK_ZONE(zone);
8836         if (zone->notify_acl != NULL)
8837                 dns_acl_detach(&zone->notify_acl);
8838         dns_acl_attach(acl, &zone->notify_acl);
8839         UNLOCK_ZONE(zone);
8840 }
8841
8842 void
8843 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
8844
8845         REQUIRE(DNS_ZONE_VALID(zone));
8846
8847         LOCK_ZONE(zone);
8848         if (zone->query_acl != NULL)
8849                 dns_acl_detach(&zone->query_acl);
8850         dns_acl_attach(acl, &zone->query_acl);
8851         UNLOCK_ZONE(zone);
8852 }
8853
8854 void
8855 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
8856
8857         REQUIRE(DNS_ZONE_VALID(zone));
8858
8859         LOCK_ZONE(zone);
8860         if (zone->queryon_acl != NULL)
8861                 dns_acl_detach(&zone->queryon_acl);
8862         dns_acl_attach(acl, &zone->queryon_acl);
8863         UNLOCK_ZONE(zone);
8864 }
8865
8866 void
8867 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
8868
8869         REQUIRE(DNS_ZONE_VALID(zone));
8870
8871         LOCK_ZONE(zone);
8872         if (zone->update_acl != NULL)
8873                 dns_acl_detach(&zone->update_acl);
8874         dns_acl_attach(acl, &zone->update_acl);
8875         UNLOCK_ZONE(zone);
8876 }
8877
8878 void
8879 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
8880
8881         REQUIRE(DNS_ZONE_VALID(zone));
8882
8883         LOCK_ZONE(zone);
8884         if (zone->forward_acl != NULL)
8885                 dns_acl_detach(&zone->forward_acl);
8886         dns_acl_attach(acl, &zone->forward_acl);
8887         UNLOCK_ZONE(zone);
8888 }
8889
8890 void
8891 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
8892
8893         REQUIRE(DNS_ZONE_VALID(zone));
8894
8895         LOCK_ZONE(zone);
8896         if (zone->xfr_acl != NULL)
8897                 dns_acl_detach(&zone->xfr_acl);
8898         dns_acl_attach(acl, &zone->xfr_acl);
8899         UNLOCK_ZONE(zone);
8900 }
8901
8902 dns_acl_t *
8903 dns_zone_getnotifyacl(dns_zone_t *zone) {
8904
8905         REQUIRE(DNS_ZONE_VALID(zone));
8906
8907         return (zone->notify_acl);
8908 }
8909
8910 dns_acl_t *
8911 dns_zone_getqueryacl(dns_zone_t *zone) {
8912
8913         REQUIRE(DNS_ZONE_VALID(zone));
8914
8915         return (zone->query_acl);
8916 }
8917
8918 dns_acl_t *
8919 dns_zone_getqueryonacl(dns_zone_t *zone) {
8920
8921         REQUIRE(DNS_ZONE_VALID(zone));
8922
8923         return (zone->queryon_acl);
8924 }
8925
8926 dns_acl_t *
8927 dns_zone_getupdateacl(dns_zone_t *zone) {
8928
8929         REQUIRE(DNS_ZONE_VALID(zone));
8930
8931         return (zone->update_acl);
8932 }
8933
8934 dns_acl_t *
8935 dns_zone_getforwardacl(dns_zone_t *zone) {
8936
8937         REQUIRE(DNS_ZONE_VALID(zone));
8938
8939         return (zone->forward_acl);
8940 }
8941
8942 dns_acl_t *
8943 dns_zone_getxfracl(dns_zone_t *zone) {
8944
8945         REQUIRE(DNS_ZONE_VALID(zone));
8946
8947         return (zone->xfr_acl);
8948 }
8949
8950 void
8951 dns_zone_clearupdateacl(dns_zone_t *zone) {
8952
8953         REQUIRE(DNS_ZONE_VALID(zone));
8954
8955         LOCK_ZONE(zone);
8956         if (zone->update_acl != NULL)
8957                 dns_acl_detach(&zone->update_acl);
8958         UNLOCK_ZONE(zone);
8959 }
8960
8961 void
8962 dns_zone_clearforwardacl(dns_zone_t *zone) {
8963
8964         REQUIRE(DNS_ZONE_VALID(zone));
8965
8966         LOCK_ZONE(zone);
8967         if (zone->forward_acl != NULL)
8968                 dns_acl_detach(&zone->forward_acl);
8969         UNLOCK_ZONE(zone);
8970 }
8971
8972 void
8973 dns_zone_clearnotifyacl(dns_zone_t *zone) {
8974
8975         REQUIRE(DNS_ZONE_VALID(zone));
8976
8977         LOCK_ZONE(zone);
8978         if (zone->notify_acl != NULL)
8979                 dns_acl_detach(&zone->notify_acl);
8980         UNLOCK_ZONE(zone);
8981 }
8982
8983 void
8984 dns_zone_clearqueryacl(dns_zone_t *zone) {
8985
8986         REQUIRE(DNS_ZONE_VALID(zone));
8987
8988         LOCK_ZONE(zone);
8989         if (zone->query_acl != NULL)
8990                 dns_acl_detach(&zone->query_acl);
8991         UNLOCK_ZONE(zone);
8992 }
8993
8994 void
8995 dns_zone_clearqueryonacl(dns_zone_t *zone) {
8996
8997         REQUIRE(DNS_ZONE_VALID(zone));
8998
8999         LOCK_ZONE(zone);
9000         if (zone->queryon_acl != NULL)
9001                 dns_acl_detach(&zone->queryon_acl);
9002         UNLOCK_ZONE(zone);
9003 }
9004
9005 void
9006 dns_zone_clearxfracl(dns_zone_t *zone) {
9007
9008         REQUIRE(DNS_ZONE_VALID(zone));
9009
9010         LOCK_ZONE(zone);
9011         if (zone->xfr_acl != NULL)
9012                 dns_acl_detach(&zone->xfr_acl);
9013         UNLOCK_ZONE(zone);
9014 }
9015
9016 isc_boolean_t
9017 dns_zone_getupdatedisabled(dns_zone_t *zone) {
9018         REQUIRE(DNS_ZONE_VALID(zone));
9019         return (zone->update_disabled);
9020
9021 }
9022
9023 void
9024 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
9025         REQUIRE(DNS_ZONE_VALID(zone));
9026         zone->update_disabled = state;
9027 }
9028
9029 isc_boolean_t
9030 dns_zone_getzeronosoattl(dns_zone_t *zone) {
9031         REQUIRE(DNS_ZONE_VALID(zone));
9032         return (zone->zero_no_soa_ttl);
9033
9034 }
9035
9036 void
9037 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
9038         REQUIRE(DNS_ZONE_VALID(zone));
9039         zone->zero_no_soa_ttl = state;
9040 }
9041
9042 void
9043 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
9044
9045         REQUIRE(DNS_ZONE_VALID(zone));
9046
9047         zone->check_names = severity;
9048 }
9049
9050 dns_severity_t
9051 dns_zone_getchecknames(dns_zone_t *zone) {
9052
9053         REQUIRE(DNS_ZONE_VALID(zone));
9054
9055         return (zone->check_names);
9056 }
9057
9058 void
9059 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
9060
9061         REQUIRE(DNS_ZONE_VALID(zone));
9062
9063         zone->journalsize = size;
9064 }
9065
9066 isc_int32_t
9067 dns_zone_getjournalsize(dns_zone_t *zone) {
9068
9069         REQUIRE(DNS_ZONE_VALID(zone));
9070
9071         return (zone->journalsize);
9072 }
9073
9074 static void
9075 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
9076         isc_result_t result = ISC_R_FAILURE;
9077         isc_buffer_t buffer;
9078
9079         REQUIRE(buf != NULL);
9080         REQUIRE(length > 1U);
9081
9082         /*
9083          * Leave space for terminating '\0'.
9084          */
9085         isc_buffer_init(&buffer, buf, length - 1);
9086         if (dns_name_dynamic(&zone->origin))
9087                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
9088         if (result != ISC_R_SUCCESS &&
9089             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
9090                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
9091
9092         if (isc_buffer_availablelength(&buffer) > 0)
9093                 isc_buffer_putstr(&buffer, "/");
9094         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
9095
9096         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
9097             strcmp(zone->view->name, "_default") != 0 &&
9098             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
9099                 isc_buffer_putstr(&buffer, "/");
9100                 isc_buffer_putstr(&buffer, zone->view->name);
9101         }
9102
9103         buf[isc_buffer_usedlength(&buffer)] = '\0';
9104 }
9105
9106 static void
9107 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
9108         isc_result_t result = ISC_R_FAILURE;
9109         isc_buffer_t buffer;
9110
9111         REQUIRE(buf != NULL);
9112         REQUIRE(length > 1U);
9113
9114         /*
9115          * Leave space for terminating '\0'.
9116          */
9117         isc_buffer_init(&buffer, buf, length - 1);
9118         if (dns_name_dynamic(&zone->origin))
9119                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
9120         if (result != ISC_R_SUCCESS &&
9121             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
9122                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
9123
9124         buf[isc_buffer_usedlength(&buffer)] = '\0';
9125 }
9126
9127 static void
9128 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
9129         isc_buffer_t buffer;
9130
9131         REQUIRE(buf != NULL);
9132         REQUIRE(length > 1U);
9133
9134         /*
9135          * Leave space for terminating '\0'.
9136          */
9137         isc_buffer_init(&buffer, buf, length - 1);
9138         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
9139
9140         buf[isc_buffer_usedlength(&buffer)] = '\0';
9141 }
9142
9143 static void
9144 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
9145         isc_buffer_t buffer;
9146
9147         REQUIRE(buf != NULL);
9148         REQUIRE(length > 1U);
9149
9150
9151         /*
9152          * Leave space for terminating '\0'.
9153          */
9154         isc_buffer_init(&buffer, buf, length - 1);
9155
9156         if (zone->view == NULL) {
9157                 isc_buffer_putstr(&buffer, "_none");
9158         } else if (strlen(zone->view->name)
9159                    < isc_buffer_availablelength(&buffer)) {
9160                 isc_buffer_putstr(&buffer, zone->view->name);
9161         } else {
9162                 isc_buffer_putstr(&buffer, "_toolong");
9163         }
9164
9165         buf[isc_buffer_usedlength(&buffer)] = '\0';
9166 }
9167
9168 void
9169 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
9170         REQUIRE(DNS_ZONE_VALID(zone));
9171         REQUIRE(buf != NULL);
9172         zone_namerd_tostr(zone, buf, length);
9173 }
9174
9175 static void
9176 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
9177         va_list ap;
9178         char message[4096];
9179
9180         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
9181                 return;
9182
9183         va_start(ap, fmt);
9184         vsnprintf(message, sizeof(message), fmt, ap);
9185         va_end(ap);
9186         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
9187                       level, "zone %s: %s", zone->strnamerd, message);
9188 }
9189
9190 void
9191 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
9192               int level, const char *fmt, ...) {
9193         va_list ap;
9194         char message[4096];
9195
9196         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
9197                 return;
9198
9199         va_start(ap, fmt);
9200         vsnprintf(message, sizeof(message), fmt, ap);
9201         va_end(ap);
9202         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
9203                       level, "zone %s: %s", zone->strnamerd, message);
9204 }
9205
9206 void
9207 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
9208         va_list ap;
9209         char message[4096];
9210
9211         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
9212                 return;
9213
9214         va_start(ap, fmt);
9215         vsnprintf(message, sizeof(message), fmt, ap);
9216         va_end(ap);
9217         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
9218                       level, "zone %s: %s", zone->strnamerd, message);
9219 }
9220
9221 static void
9222 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
9223               const char *fmt, ...)
9224 {
9225         va_list ap;
9226         char message[4096];
9227         int level = ISC_LOG_DEBUG(debuglevel);
9228
9229         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
9230                 return;
9231
9232         va_start(ap, fmt);
9233         vsnprintf(message, sizeof(message), fmt, ap);
9234         va_end(ap);
9235         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
9236                       level, "%s: zone %s: %s", me, zone->strnamerd, message);
9237 }
9238
9239 static int
9240 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
9241 {
9242         isc_result_t result;
9243         dns_name_t *name;
9244         dns_rdataset_t *curr;
9245         int count = 0;
9246
9247         result = dns_message_firstname(msg, section);
9248         while (result == ISC_R_SUCCESS) {
9249                 name = NULL;
9250                 dns_message_currentname(msg, section, &name);
9251
9252                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
9253                      curr = ISC_LIST_PREV(curr, link)) {
9254                         if (curr->type == type)
9255                                 count++;
9256                 }
9257                 result = dns_message_nextname(msg, section);
9258         }
9259
9260         return (count);
9261 }
9262
9263 void
9264 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
9265         REQUIRE(DNS_ZONE_VALID(zone));
9266
9267         zone->maxxfrin = maxxfrin;
9268 }
9269
9270 isc_uint32_t
9271 dns_zone_getmaxxfrin(dns_zone_t *zone) {
9272         REQUIRE(DNS_ZONE_VALID(zone));
9273
9274         return (zone->maxxfrin);
9275 }
9276
9277 void
9278 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
9279         REQUIRE(DNS_ZONE_VALID(zone));
9280         zone->maxxfrout = maxxfrout;
9281 }
9282
9283 isc_uint32_t
9284 dns_zone_getmaxxfrout(dns_zone_t *zone) {
9285         REQUIRE(DNS_ZONE_VALID(zone));
9286
9287         return (zone->maxxfrout);
9288 }
9289
9290 dns_zonetype_t
9291 dns_zone_gettype(dns_zone_t *zone) {
9292         REQUIRE(DNS_ZONE_VALID(zone));
9293
9294         return (zone->type);
9295 }
9296
9297 dns_name_t *
9298 dns_zone_getorigin(dns_zone_t *zone) {
9299         REQUIRE(DNS_ZONE_VALID(zone));
9300
9301         return (&zone->origin);
9302 }
9303
9304 void
9305 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
9306         REQUIRE(DNS_ZONE_VALID(zone));
9307
9308         LOCK_ZONE(zone);
9309         if (zone->task != NULL)
9310                 isc_task_detach(&zone->task);
9311         isc_task_attach(task, &zone->task);
9312         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9313         if (zone->db != NULL)
9314                 dns_db_settask(zone->db, zone->task);
9315         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9316         UNLOCK_ZONE(zone);
9317 }
9318
9319 void
9320 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
9321         REQUIRE(DNS_ZONE_VALID(zone));
9322         isc_task_attach(zone->task, target);
9323 }
9324
9325 void
9326 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
9327         REQUIRE(DNS_ZONE_VALID(zone));
9328
9329         if (idlein == 0)
9330                 idlein = DNS_DEFAULT_IDLEIN;
9331         zone->idlein = idlein;
9332 }
9333
9334 isc_uint32_t
9335 dns_zone_getidlein(dns_zone_t *zone) {
9336         REQUIRE(DNS_ZONE_VALID(zone));
9337
9338         return (zone->idlein);
9339 }
9340
9341 void
9342 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
9343         REQUIRE(DNS_ZONE_VALID(zone));
9344
9345         zone->idleout = idleout;
9346 }
9347
9348 isc_uint32_t
9349 dns_zone_getidleout(dns_zone_t *zone) {
9350         REQUIRE(DNS_ZONE_VALID(zone));
9351
9352         return (zone->idleout);
9353 }
9354
9355 static void
9356 notify_done(isc_task_t *task, isc_event_t *event) {
9357         dns_requestevent_t *revent = (dns_requestevent_t *)event;
9358         dns_notify_t *notify;
9359         isc_result_t result;
9360         dns_message_t *message = NULL;
9361         isc_buffer_t buf;
9362         char rcode[128];
9363         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9364
9365         UNUSED(task);
9366
9367         notify = event->ev_arg;
9368         REQUIRE(DNS_NOTIFY_VALID(notify));
9369         INSIST(task == notify->zone->task);
9370
9371         isc_buffer_init(&buf, rcode, sizeof(rcode));
9372         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9373
9374         result = revent->result;
9375         if (result == ISC_R_SUCCESS)
9376                 result = dns_message_create(notify->zone->mctx,
9377                                             DNS_MESSAGE_INTENTPARSE, &message);
9378         if (result == ISC_R_SUCCESS)
9379                 result = dns_request_getresponse(revent->request, message,
9380                                         DNS_MESSAGEPARSE_PRESERVEORDER);
9381         if (result == ISC_R_SUCCESS)
9382                 result = dns_rcode_totext(message->rcode, &buf);
9383         if (result == ISC_R_SUCCESS)
9384                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
9385                            "notify response from %s: %.*s",
9386                            addrbuf, (int)buf.used, rcode);
9387         else
9388                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
9389                            "notify to %s failed: %s", addrbuf,
9390                            dns_result_totext(result));
9391
9392         /*
9393          * Old bind's return formerr if they see a soa record.  Retry w/o
9394          * the soa if we see a formerr and had sent a SOA.
9395          */
9396         isc_event_free(&event);
9397         if (message != NULL && message->rcode == dns_rcode_formerr &&
9398             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
9399                 notify->flags |= DNS_NOTIFY_NOSOA;
9400                 dns_request_destroy(&notify->request);
9401                 result = notify_send_queue(notify);
9402                 if (result != ISC_R_SUCCESS)
9403                         notify_destroy(notify, ISC_FALSE);
9404         } else {
9405                 if (result == ISC_R_TIMEDOUT)
9406                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
9407                                    "notify to %s: retries exceeded", addrbuf);
9408                 notify_destroy(notify, ISC_FALSE);
9409         }
9410         if (message != NULL)
9411                 dns_message_destroy(&message);
9412 }
9413
9414 isc_result_t
9415 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
9416         isc_result_t result;
9417
9418         REQUIRE(DNS_ZONE_VALID(zone));
9419         LOCK_ZONE(zone);
9420         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9421         result = zone_replacedb(zone, db, dump);
9422         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9423         UNLOCK_ZONE(zone);
9424         return (result);
9425 }
9426
9427 static isc_result_t
9428 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
9429         dns_dbversion_t *ver;
9430         isc_result_t result;
9431         unsigned int soacount = 0;
9432         unsigned int nscount = 0;
9433
9434         /*
9435          * 'zone' and 'zonedb' locked by caller.
9436          */
9437         REQUIRE(DNS_ZONE_VALID(zone));
9438         REQUIRE(LOCKED_ZONE(zone));
9439
9440         result = zone_get_from_db(zone, db, &nscount, &soacount,
9441                                   NULL, NULL, NULL, NULL, NULL, NULL);
9442         if (result == ISC_R_SUCCESS) {
9443                 if (soacount != 1) {
9444                         dns_zone_log(zone, ISC_LOG_ERROR,
9445                                      "has %d SOA records", soacount);
9446                         result = DNS_R_BADZONE;
9447                 }
9448                 if (nscount == 0) {
9449                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
9450                         result = DNS_R_BADZONE;
9451                 }
9452                 if (result != ISC_R_SUCCESS)
9453                         return (result);
9454         } else {
9455                 dns_zone_log(zone, ISC_LOG_ERROR,
9456                             "retrieving SOA and NS records failed: %s",
9457                             dns_result_totext(result));
9458                 return (result);
9459         }
9460
9461         result = check_nsec3param(zone, db);
9462         if (result != ISC_R_SUCCESS)
9463                 return (result);
9464
9465         ver = NULL;
9466         dns_db_currentversion(db, &ver);
9467
9468         /*
9469          * The initial version of a slave zone is always dumped;
9470          * subsequent versions may be journaled instead if this
9471          * is enabled in the configuration.
9472          */
9473         if (zone->db != NULL && zone->journal != NULL &&
9474             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
9475             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
9476                 isc_uint32_t serial;
9477
9478                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
9479
9480                 result = dns_db_getsoaserial(db, ver, &serial);
9481                 if (result != ISC_R_SUCCESS) {
9482                         dns_zone_log(zone, ISC_LOG_ERROR,
9483                                      "ixfr-from-differences: unable to get "
9484                                      "new serial");
9485                         goto fail;
9486                 }
9487
9488                 /*
9489                  * This is checked in zone_postload() for master zones.
9490                  */
9491                 if (zone->type == dns_zone_slave &&
9492                     !isc_serial_gt(serial, zone->serial)) {
9493                         isc_uint32_t serialmin, serialmax;
9494                         serialmin = (zone->serial + 1) & 0xffffffffU;
9495                         serialmax = (zone->serial + 0x7fffffffU) & 0xffffffffU;
9496                         dns_zone_log(zone, ISC_LOG_ERROR,
9497                                      "ixfr-from-differences: failed: "
9498                                      "new serial (%u) out of range [%u - %u]",
9499                                      serial, serialmin, serialmax);
9500                         result = ISC_R_RANGE;
9501                         goto fail;
9502                 }
9503
9504                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
9505                                      zone->journal);
9506                 if (result != ISC_R_SUCCESS)
9507                         goto fail;
9508                 if (dump)
9509                         zone_needdump(zone, DNS_DUMP_DELAY);
9510                 else if (zone->journalsize != -1) {
9511                         result = dns_journal_compact(zone->mctx, zone->journal,
9512                                                      serial, zone->journalsize);
9513                         switch (result) {
9514                         case ISC_R_SUCCESS:
9515                         case ISC_R_NOSPACE:
9516                         case ISC_R_NOTFOUND:
9517                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9518                                              "dns_journal_compact: %s",
9519                                              dns_result_totext(result));
9520                                 break;
9521                         default:
9522                                 dns_zone_log(zone, ISC_LOG_ERROR,
9523                                              "dns_journal_compact failed: %s",
9524                                              dns_result_totext(result));
9525                                 break;
9526                         }
9527                 }
9528         } else {
9529                 if (dump && zone->masterfile != NULL) {
9530                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
9531                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
9532                                       "dumping new zone version");
9533                         result = dns_db_dump2(db, ver, zone->masterfile,
9534                                               zone->masterformat);
9535                         if (result != ISC_R_SUCCESS)
9536                                 goto fail;
9537
9538                         /*
9539                          * Update the time the zone was updated, so
9540                          * dns_zone_load can avoid loading it when
9541                          * the server is reloaded.  If isc_time_now
9542                          * fails for some reason, all that happens is
9543                          * the timestamp is not updated.
9544                          */
9545                         TIME_NOW(&zone->loadtime);
9546                 }
9547
9548                 if (dump && zone->journal != NULL) {
9549                         /*
9550                          * The in-memory database just changed, and
9551                          * because 'dump' is set, it didn't change by
9552                          * being loaded from disk.  Also, we have not
9553                          * journaled diffs for this change.
9554                          * Therefore, the on-disk journal is missing
9555                          * the deltas for this change.  Since it can
9556                          * no longer be used to bring the zone
9557                          * up-to-date, it is useless and should be
9558                          * removed.
9559                          */
9560                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
9561                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
9562                                       "removing journal file");
9563                         if (remove(zone->journal) < 0 && errno != ENOENT) {
9564                                 char strbuf[ISC_STRERRORSIZE];
9565                                 isc__strerror(errno, strbuf, sizeof(strbuf));
9566                                 isc_log_write(dns_lctx,
9567                                               DNS_LOGCATEGORY_GENERAL,
9568                                               DNS_LOGMODULE_ZONE,
9569                                               ISC_LOG_WARNING,
9570                                               "unable to remove journal "
9571                                               "'%s': '%s'",
9572                                               zone->journal, strbuf);
9573                         }
9574                 }
9575         }
9576
9577         dns_db_closeversion(db, &ver, ISC_FALSE);
9578
9579         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
9580                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
9581                       "replacing zone database");
9582
9583         if (zone->db != NULL)
9584                 zone_detachdb(zone);
9585         zone_attachdb(zone, db);
9586         dns_db_settask(zone->db, zone->task);
9587         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
9588         return (ISC_R_SUCCESS);
9589
9590  fail:
9591         dns_db_closeversion(db, &ver, ISC_FALSE);
9592         return (result);
9593 }
9594
9595 /* The caller must hold the dblock as a writer. */
9596 static inline void
9597 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
9598         REQUIRE(zone->db == NULL && db != NULL);
9599
9600         dns_db_attach(db, &zone->db);
9601         if (zone->acache != NULL) {
9602                 isc_result_t result;
9603                 result = dns_acache_setdb(zone->acache, db);
9604                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
9605                         UNEXPECTED_ERROR(__FILE__, __LINE__,
9606                                          "dns_acache_setdb() failed: %s",
9607                                          isc_result_totext(result));
9608                 }
9609         }
9610 }
9611
9612 /* The caller must hold the dblock as a writer. */
9613 static inline void
9614 zone_detachdb(dns_zone_t *zone) {
9615         REQUIRE(zone->db != NULL);
9616
9617         if (zone->acache != NULL)
9618                 (void)dns_acache_putdb(zone->acache, zone->db);
9619         dns_db_detach(&zone->db);
9620 }
9621
9622 static void
9623 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
9624         isc_time_t now;
9625         isc_boolean_t again = ISC_FALSE;
9626         unsigned int soacount;
9627         unsigned int nscount;
9628         isc_uint32_t serial, refresh, retry, expire, minimum;
9629         isc_result_t xfrresult = result;
9630         isc_boolean_t free_needed;
9631
9632         REQUIRE(DNS_ZONE_VALID(zone));
9633
9634         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9635                      "zone transfer finished: %s", dns_result_totext(result));
9636
9637         LOCK_ZONE(zone);
9638         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
9639         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9640         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
9641
9642         TIME_NOW(&now);
9643         switch (result) {
9644         case ISC_R_SUCCESS:
9645                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9646                 /*FALLTHROUGH*/
9647         case DNS_R_UPTODATE:
9648                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
9649                 /*
9650                  * Has the zone expired underneath us?
9651                  */
9652                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9653                 if (zone->db == NULL) {
9654                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9655                         goto same_master;
9656                 }
9657
9658                 /*
9659                  * Update the zone structure's data from the actual
9660                  * SOA received.
9661                  */
9662                 nscount = 0;
9663                 soacount = 0;
9664                 INSIST(zone->db != NULL);
9665                 result = zone_get_from_db(zone, zone->db, &nscount,
9666                                           &soacount, &serial, &refresh,
9667                                           &retry, &expire, &minimum, NULL);
9668                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9669                 if (result == ISC_R_SUCCESS) {
9670                         if (soacount != 1)
9671                                 dns_zone_log(zone, ISC_LOG_ERROR,
9672                                              "transferred zone "
9673                                              "has %d SOA record%s", soacount,
9674                                              (soacount != 0) ? "s" : "");
9675                         if (nscount == 0) {
9676                                 dns_zone_log(zone, ISC_LOG_ERROR,
9677                                              "transferred zone "
9678                                              "has no NS records");
9679                                 if (DNS_ZONE_FLAG(zone,
9680                                                   DNS_ZONEFLG_HAVETIMERS)) {
9681                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
9682                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
9683                                 }
9684                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9685                                 zone_unload(zone);
9686                                 goto next_master;
9687                         }
9688                         zone->serial = serial;
9689                         zone->refresh = RANGE(refresh, zone->minrefresh,
9690                                               zone->maxrefresh);
9691                         zone->retry = RANGE(retry, zone->minretry,
9692                                             zone->maxretry);
9693                         zone->expire = RANGE(expire,
9694                                              zone->refresh + zone->retry,
9695                                              DNS_MAX_EXPIRE);
9696                         zone->minimum = minimum;
9697                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9698                 }
9699
9700                 /*
9701                  * Set our next update/expire times.
9702                  */
9703                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
9704                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
9705                         zone->refreshtime = now;
9706                         DNS_ZONE_TIME_ADD(&now, zone->expire,
9707                                           &zone->expiretime);
9708                 } else {
9709                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
9710                                             &zone->refreshtime);
9711                         DNS_ZONE_TIME_ADD(&now, zone->expire,
9712                                           &zone->expiretime);
9713                 }
9714                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
9715                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
9716                         if (zone->tsigkey != NULL) {
9717                                 char namebuf[DNS_NAME_FORMATSIZE];
9718                                 dns_name_format(&zone->tsigkey->name, namebuf,
9719                                                 sizeof(namebuf));
9720                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
9721                                          namebuf);
9722                         } else
9723                                 buf[0] = '\0';
9724                         dns_zone_log(zone, ISC_LOG_INFO,
9725                                      "transferred serial %u%s",
9726                                      zone->serial, buf);
9727                 }
9728
9729                 /*
9730                  * This is not necessary if we just performed a AXFR
9731                  * however it is necessary for an IXFR / UPTODATE and
9732                  * won't hurt with an AXFR.
9733                  */
9734                 if (zone->masterfile != NULL || zone->journal != NULL) {
9735                         result = ISC_R_FAILURE;
9736                         if (zone->journal != NULL)
9737                                 result = isc_file_settime(zone->journal, &now);
9738                         if (result != ISC_R_SUCCESS &&
9739                             zone->masterfile != NULL)
9740                                 result = isc_file_settime(zone->masterfile,
9741                                                           &now);
9742                         /* Someone removed the file from underneath us! */
9743                         if (result == ISC_R_FILENOTFOUND &&
9744                             zone->masterfile != NULL)
9745                                 zone_needdump(zone, DNS_DUMP_DELAY);
9746                         else if (result != ISC_R_SUCCESS)
9747                                 dns_zone_log(zone, ISC_LOG_ERROR,
9748                                              "transfer: could not set file "
9749                                              "modification time of '%s': %s",
9750                                              zone->masterfile,
9751                                              dns_result_totext(result));
9752                 }
9753
9754                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
9755                 break;
9756
9757         case DNS_R_BADIXFR:
9758                 /* Force retry with AXFR. */
9759                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
9760                 goto same_master;
9761
9762         default:
9763         next_master:
9764                 /*
9765                  * Skip to next failed / untried master.
9766                  */
9767                 do {
9768                         zone->curmaster++;
9769                 } while (zone->curmaster < zone->masterscnt &&
9770                          zone->mastersok[zone->curmaster]);
9771                 /* FALLTHROUGH */
9772         same_master:
9773                 if (zone->curmaster >= zone->masterscnt) {
9774                         zone->curmaster = 0;
9775                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9776                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9777                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
9778                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9779                                 while (zone->curmaster < zone->masterscnt &&
9780                                        zone->mastersok[zone->curmaster])
9781                                         zone->curmaster++;
9782                                 again = ISC_TRUE;
9783                         } else
9784                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9785                 } else {
9786                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
9787                         again = ISC_TRUE;
9788                 }
9789                 inc_stats(zone, dns_zonestatscounter_xfrfail);
9790                 break;
9791         }
9792         zone_settimer(zone, &now);
9793
9794         /*
9795          * If creating the transfer object failed, zone->xfr is NULL.
9796          * Otherwise, we are called as the done callback of a zone
9797          * transfer object that just entered its shutting-down
9798          * state.  Since we are no longer responsible for shutting
9799          * it down, we can detach our reference.
9800          */
9801         if (zone->xfr != NULL)
9802                 dns_xfrin_detach(&zone->xfr);
9803
9804         if (zone->tsigkey != NULL)
9805                 dns_tsigkey_detach(&zone->tsigkey);
9806
9807         /*
9808          * Handle any deferred journal compaction.
9809          */
9810         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
9811                 result = dns_journal_compact(zone->mctx, zone->journal,
9812                                              zone->compact_serial,
9813                                              zone->journalsize);
9814                 switch (result) {
9815                 case ISC_R_SUCCESS:
9816                 case ISC_R_NOSPACE:
9817                 case ISC_R_NOTFOUND:
9818                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
9819                                      "dns_journal_compact: %s",
9820                                      dns_result_totext(result));
9821                         break;
9822                 default:
9823                         dns_zone_log(zone, ISC_LOG_ERROR,
9824                                      "dns_journal_compact failed: %s",
9825                                      dns_result_totext(result));
9826                         break;
9827                 }
9828                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
9829         }
9830
9831         /*
9832          * This transfer finishing freed up a transfer quota slot.
9833          * Let any other zones waiting for quota have it.
9834          */
9835         RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
9836         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
9837         zone->statelist = NULL;
9838         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
9839         RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
9840
9841         /*
9842          * Retry with a different server if necessary.
9843          */
9844         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
9845                 queue_soa_query(zone);
9846
9847         INSIST(zone->irefs > 0);
9848         zone->irefs--;
9849         free_needed = exit_check(zone);
9850         UNLOCK_ZONE(zone);
9851         if (free_needed)
9852                 zone_free(zone);
9853 }
9854
9855 static void
9856 zone_loaddone(void *arg, isc_result_t result) {
9857         static char me[] = "zone_loaddone";
9858         dns_load_t *load = arg;
9859         dns_zone_t *zone;
9860         isc_result_t tresult;
9861
9862         REQUIRE(DNS_LOAD_VALID(load));
9863         zone = load->zone;
9864
9865         ENTER;
9866
9867         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
9868         if (tresult != ISC_R_SUCCESS &&
9869             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
9870                 result = tresult;
9871
9872         LOCK_ZONE(load->zone);
9873         (void)zone_postload(load->zone, load->db, load->loadtime, result);
9874         zonemgr_putio(&load->zone->readio);
9875         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
9876         UNLOCK_ZONE(load->zone);
9877
9878         load->magic = 0;
9879         dns_db_detach(&load->db);
9880         if (load->zone->lctx != NULL)
9881                 dns_loadctx_detach(&load->zone->lctx);
9882         dns_zone_idetach(&load->zone);
9883         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
9884 }
9885
9886 void
9887 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
9888         REQUIRE(DNS_ZONE_VALID(zone));
9889         REQUIRE(table != NULL);
9890         REQUIRE(*table == NULL);
9891
9892         LOCK_ZONE(zone);
9893         if (zone->ssutable != NULL)
9894                 dns_ssutable_attach(zone->ssutable, table);
9895         UNLOCK_ZONE(zone);
9896 }
9897
9898 void
9899 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
9900         REQUIRE(DNS_ZONE_VALID(zone));
9901
9902         LOCK_ZONE(zone);
9903         if (zone->ssutable != NULL)
9904                 dns_ssutable_detach(&zone->ssutable);
9905         if (table != NULL)
9906                 dns_ssutable_attach(table, &zone->ssutable);
9907         UNLOCK_ZONE(zone);
9908 }
9909
9910 void
9911 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
9912         REQUIRE(DNS_ZONE_VALID(zone));
9913
9914         zone->sigvalidityinterval = interval;
9915 }
9916
9917 isc_uint32_t
9918 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
9919         REQUIRE(DNS_ZONE_VALID(zone));
9920
9921         return (zone->sigvalidityinterval);
9922 }
9923
9924 void
9925 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
9926         REQUIRE(DNS_ZONE_VALID(zone));
9927
9928         zone->sigresigninginterval = interval;
9929 }
9930
9931 isc_uint32_t
9932 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
9933         REQUIRE(DNS_ZONE_VALID(zone));
9934
9935         return (zone->sigresigninginterval);
9936 }
9937
9938 static void
9939 queue_xfrin(dns_zone_t *zone) {
9940         const char me[] = "queue_xfrin";
9941         isc_result_t result;
9942         dns_zonemgr_t *zmgr = zone->zmgr;
9943
9944         ENTER;
9945
9946         INSIST(zone->statelist == NULL);
9947
9948         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
9949         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
9950         LOCK_ZONE(zone);
9951         zone->irefs++;
9952         UNLOCK_ZONE(zone);
9953         zone->statelist = &zmgr->waiting_for_xfrin;
9954         result = zmgr_start_xfrin_ifquota(zmgr, zone);
9955         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
9956
9957         if (result == ISC_R_QUOTA) {
9958                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
9959                               "zone transfer deferred due to quota");
9960         } else if (result != ISC_R_SUCCESS) {
9961                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
9962                               "starting zone transfer: %s",
9963                               isc_result_totext(result));
9964         }
9965 }
9966
9967 /*
9968  * This event callback is called when a zone has received
9969  * any necessary zone transfer quota.  This is the time
9970  * to go ahead and start the transfer.
9971  */
9972 static void
9973 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
9974         isc_result_t result;
9975         dns_peer_t *peer = NULL;
9976         char master[ISC_SOCKADDR_FORMATSIZE];
9977         char source[ISC_SOCKADDR_FORMATSIZE];
9978         dns_rdatatype_t xfrtype;
9979         dns_zone_t *zone = event->ev_arg;
9980         isc_netaddr_t masterip;
9981         isc_sockaddr_t sourceaddr;
9982         isc_sockaddr_t masteraddr;
9983         isc_time_t now;
9984
9985         UNUSED(task);
9986
9987         INSIST(task == zone->task);
9988
9989         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9990                 result = ISC_R_CANCELED;
9991                 goto cleanup;
9992         }
9993
9994         TIME_NOW(&now);
9995
9996         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9997         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
9998                                     &zone->sourceaddr, &now)) {
9999                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10000                 dns_zone_log(zone, ISC_LOG_INFO,
10001                              "got_transfer_quota: skipping zone transfer as "
10002                              "master %s (source %s) is unreachable (cached)",
10003                              master, source);
10004                 result = ISC_R_CANCELED;
10005                 goto cleanup;
10006         }
10007
10008         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10009         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
10010
10011         /*
10012          * Decide whether we should request IXFR or AXFR.
10013          */
10014         if (zone->db == NULL) {
10015                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10016                              "no database exists yet, requesting AXFR of "
10017                              "initial version from %s", master);
10018                 xfrtype = dns_rdatatype_axfr;
10019         } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
10020                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
10021                              "set, requesting AXFR from %s", master);
10022                 xfrtype = dns_rdatatype_axfr;
10023         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
10024                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10025                              "forced reload, requesting AXFR of "
10026                              "initial version from %s", master);
10027                 xfrtype = dns_rdatatype_axfr;
10028         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
10029                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10030                              "retrying with AXFR from %s due to "
10031                              "previous IXFR failure", master);
10032                 xfrtype = dns_rdatatype_axfr;
10033                 LOCK_ZONE(zone);
10034                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
10035                 UNLOCK_ZONE(zone);
10036         } else {
10037                 isc_boolean_t use_ixfr = ISC_TRUE;
10038                 if (peer != NULL &&
10039                     dns_peer_getrequestixfr(peer, &use_ixfr) ==
10040                     ISC_R_SUCCESS) {
10041                         ; /* Using peer setting */
10042                 } else {
10043                         use_ixfr = zone->view->requestixfr;
10044                 }
10045                 if (use_ixfr == ISC_FALSE) {
10046                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10047                                      "IXFR disabled, requesting AXFR from %s",
10048                                      master);
10049                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
10050                                 xfrtype = dns_rdatatype_soa;
10051                         else
10052                                 xfrtype = dns_rdatatype_axfr;
10053                 } else {
10054                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10055                                      "requesting IXFR from %s", master);
10056                         xfrtype = dns_rdatatype_ixfr;
10057                 }
10058         }
10059
10060         /*
10061          * Determine if we should attempt to sign the request with TSIG.
10062          */
10063         result = ISC_R_NOTFOUND;
10064         /*
10065          * First, look for a tsig key in the master statement, then
10066          * try for a server key.
10067          */
10068         if ((zone->masterkeynames != NULL) &&
10069             (zone->masterkeynames[zone->curmaster] != NULL)) {
10070                 dns_view_t *view = dns_zone_getview(zone);
10071                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10072                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
10073         }
10074         if (zone->tsigkey == NULL)
10075                 result = dns_view_getpeertsig(zone->view, &masterip,
10076                                               &zone->tsigkey);
10077
10078         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
10079                 dns_zone_log(zone, ISC_LOG_ERROR,
10080                              "could not get TSIG key for zone transfer: %s",
10081                              isc_result_totext(result));
10082         }
10083
10084         LOCK_ZONE(zone);
10085         masteraddr = zone->masteraddr;
10086         sourceaddr = zone->sourceaddr;
10087         UNLOCK_ZONE(zone);
10088         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
10089         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
10090                                    zone->tsigkey, zone->mctx,
10091                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
10092                                    zone->task, zone_xfrdone, &zone->xfr);
10093         if (result == ISC_R_SUCCESS) {
10094                 LOCK_ZONE(zone);
10095                 if (xfrtype == dns_rdatatype_axfr) {
10096                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
10097                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
10098                         else
10099                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
10100                 } else if (xfrtype == dns_rdatatype_ixfr) {
10101                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
10102                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
10103                         else
10104                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
10105                 }
10106                 UNLOCK_ZONE(zone);
10107         }
10108  cleanup:
10109         /*
10110          * Any failure in this function is handled like a failed
10111          * zone transfer.  This ensures that we get removed from
10112          * zmgr->xfrin_in_progress.
10113          */
10114         if (result != ISC_R_SUCCESS)
10115                 zone_xfrdone(zone, result);
10116
10117         isc_event_free(&event);
10118 }
10119
10120 /*
10121  * Update forwarding support.
10122  */
10123
10124 static void
10125 forward_destroy(dns_forward_t *forward) {
10126
10127         forward->magic = 0;
10128         if (forward->request != NULL)
10129                 dns_request_destroy(&forward->request);
10130         if (forward->msgbuf != NULL)
10131                 isc_buffer_free(&forward->msgbuf);
10132         if (forward->zone != NULL)
10133                 dns_zone_idetach(&forward->zone);
10134         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
10135 }
10136
10137 static isc_result_t
10138 sendtomaster(dns_forward_t *forward) {
10139         isc_result_t result;
10140         isc_sockaddr_t src;
10141
10142         LOCK_ZONE(forward->zone);
10143         if (forward->which >= forward->zone->masterscnt) {
10144                 UNLOCK_ZONE(forward->zone);
10145                 return (ISC_R_NOMORE);
10146         }
10147
10148         forward->addr = forward->zone->masters[forward->which];
10149         /*
10150          * Always use TCP regardless of whether the original update
10151          * used TCP.
10152          * XXX The timeout may but a bit small if we are far down a
10153          * transfer graph and the master has to try several masters.
10154          */
10155         switch (isc_sockaddr_pf(&forward->addr)) {
10156         case PF_INET:
10157                 src = forward->zone->xfrsource4;
10158                 break;
10159         case PF_INET6:
10160                 src = forward->zone->xfrsource6;
10161                 break;
10162         default:
10163                 result = ISC_R_NOTIMPLEMENTED;
10164                 goto unlock;
10165         }
10166         result = dns_request_createraw(forward->zone->view->requestmgr,
10167                                        forward->msgbuf,
10168                                        &src, &forward->addr,
10169                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
10170                                        forward->zone->task,
10171                                        forward_callback, forward,
10172                                        &forward->request);
10173  unlock:
10174         UNLOCK_ZONE(forward->zone);
10175         return (result);
10176 }
10177
10178 static void
10179 forward_callback(isc_task_t *task, isc_event_t *event) {
10180         const char me[] = "forward_callback";
10181         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10182         dns_message_t *msg = NULL;
10183         char master[ISC_SOCKADDR_FORMATSIZE];
10184         isc_result_t result;
10185         dns_forward_t *forward;
10186         dns_zone_t *zone;
10187
10188         UNUSED(task);
10189
10190         forward = revent->ev_arg;
10191         INSIST(DNS_FORWARD_VALID(forward));
10192         zone = forward->zone;
10193         INSIST(DNS_ZONE_VALID(zone));
10194
10195         ENTER;
10196
10197         isc_sockaddr_format(&forward->addr, master, sizeof(master));
10198
10199         if (revent->result != ISC_R_SUCCESS) {
10200                 dns_zone_log(zone, ISC_LOG_INFO,
10201                              "could not forward dynamic update to %s: %s",
10202                              master, dns_result_totext(revent->result));
10203                 goto next_master;
10204         }
10205
10206         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10207         if (result != ISC_R_SUCCESS)
10208                 goto next_master;
10209
10210         result = dns_request_getresponse(revent->request, msg,
10211                                          DNS_MESSAGEPARSE_PRESERVEORDER |
10212                                          DNS_MESSAGEPARSE_CLONEBUFFER);
10213         if (result != ISC_R_SUCCESS)
10214                 goto next_master;
10215
10216         switch (msg->rcode) {
10217         /*
10218          * Pass these rcodes back to client.
10219          */
10220         case dns_rcode_noerror:
10221         case dns_rcode_yxdomain:
10222         case dns_rcode_yxrrset:
10223         case dns_rcode_nxrrset:
10224         case dns_rcode_refused:
10225         case dns_rcode_nxdomain:
10226                 break;
10227
10228         /* These should not occur if the masters/zone are valid. */
10229         case dns_rcode_notzone:
10230         case dns_rcode_notauth: {
10231                 char rcode[128];
10232                 isc_buffer_t rb;
10233
10234                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10235                 (void)dns_rcode_totext(msg->rcode, &rb);
10236                 dns_zone_log(zone, ISC_LOG_WARNING,
10237                              "forwarding dynamic update: "
10238                              "unexpected response: master %s returned: %.*s",
10239                              master, (int)rb.used, rcode);
10240                 goto next_master;
10241         }
10242
10243         /* Try another server for these rcodes. */
10244         case dns_rcode_formerr:
10245         case dns_rcode_servfail:
10246         case dns_rcode_notimp:
10247         case dns_rcode_badvers:
10248         default:
10249                 goto next_master;
10250         }
10251
10252         /* call callback */
10253         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
10254         msg = NULL;
10255         dns_request_destroy(&forward->request);
10256         forward_destroy(forward);
10257         isc_event_free(&event);
10258         return;
10259
10260  next_master:
10261         if (msg != NULL)
10262                 dns_message_destroy(&msg);
10263         isc_event_free(&event);
10264         forward->which++;
10265         dns_request_destroy(&forward->request);
10266         result = sendtomaster(forward);
10267         if (result != ISC_R_SUCCESS) {
10268                 /* call callback */
10269                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
10270                              "exhausted dynamic update forwarder list");
10271                 (forward->callback)(forward->callback_arg, result, NULL);
10272                 forward_destroy(forward);
10273         }
10274 }
10275
10276 isc_result_t
10277 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
10278                        dns_updatecallback_t callback, void *callback_arg)
10279 {
10280         dns_forward_t *forward;
10281         isc_result_t result;
10282         isc_region_t *mr;
10283
10284         REQUIRE(DNS_ZONE_VALID(zone));
10285         REQUIRE(msg != NULL);
10286         REQUIRE(callback != NULL);
10287
10288         forward = isc_mem_get(zone->mctx, sizeof(*forward));
10289         if (forward == NULL)
10290                 return (ISC_R_NOMEMORY);
10291
10292         forward->request = NULL;
10293         forward->zone = NULL;
10294         forward->msgbuf = NULL;
10295         forward->which = 0;
10296         forward->mctx = 0;
10297         forward->callback = callback;
10298         forward->callback_arg = callback_arg;
10299         forward->magic = FORWARD_MAGIC;
10300
10301         mr = dns_message_getrawmessage(msg);
10302         if (mr == NULL) {
10303                 result = ISC_R_UNEXPECTEDEND;
10304                 goto cleanup;
10305         }
10306
10307         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
10308         if (result != ISC_R_SUCCESS)
10309                 goto cleanup;
10310         result = isc_buffer_copyregion(forward->msgbuf, mr);
10311         if (result != ISC_R_SUCCESS)
10312                 goto cleanup;
10313
10314         isc_mem_attach(zone->mctx, &forward->mctx);
10315         dns_zone_iattach(zone, &forward->zone);
10316         result = sendtomaster(forward);
10317
10318  cleanup:
10319         if (result != ISC_R_SUCCESS) {
10320                 forward_destroy(forward);
10321         }
10322         return (result);
10323 }
10324
10325 isc_result_t
10326 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
10327         REQUIRE(DNS_ZONE_VALID(zone));
10328         REQUIRE(next != NULL && *next == NULL);
10329
10330         *next = ISC_LIST_NEXT(zone, link);
10331         if (*next == NULL)
10332                 return (ISC_R_NOMORE);
10333         else
10334                 return (ISC_R_SUCCESS);
10335 }
10336
10337 isc_result_t
10338 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
10339         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10340         REQUIRE(first != NULL && *first == NULL);
10341
10342         *first = ISC_LIST_HEAD(zmgr->zones);
10343         if (*first == NULL)
10344                 return (ISC_R_NOMORE);
10345         else
10346                 return (ISC_R_SUCCESS);
10347 }
10348
10349 /***
10350  ***    Zone manager.
10351  ***/
10352
10353 isc_result_t
10354 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
10355                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
10356                    dns_zonemgr_t **zmgrp)
10357 {
10358         dns_zonemgr_t *zmgr;
10359         isc_result_t result;
10360         isc_interval_t interval;
10361
10362         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
10363         if (zmgr == NULL)
10364                 return (ISC_R_NOMEMORY);
10365         zmgr->mctx = NULL;
10366         zmgr->refs = 1;
10367         isc_mem_attach(mctx, &zmgr->mctx);
10368         zmgr->taskmgr = taskmgr;
10369         zmgr->timermgr = timermgr;
10370         zmgr->socketmgr = socketmgr;
10371         zmgr->zonetasks = NULL;
10372         zmgr->task = NULL;
10373         zmgr->rl = NULL;
10374         ISC_LIST_INIT(zmgr->zones);
10375         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
10376         ISC_LIST_INIT(zmgr->xfrin_in_progress);
10377         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
10378         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
10379         if (result != ISC_R_SUCCESS)
10380                 goto free_mem;
10381
10382         zmgr->transfersin = 10;
10383         zmgr->transfersperns = 2;
10384
10385         /* Create the zone task pool. */
10386         result = isc_taskpool_create(taskmgr, mctx,
10387                                      8 /* XXX */, 2, &zmgr->zonetasks);
10388         if (result != ISC_R_SUCCESS)
10389                 goto free_rwlock;
10390
10391         /* Create a single task for queueing of SOA queries. */
10392         result = isc_task_create(taskmgr, 1, &zmgr->task);
10393         if (result != ISC_R_SUCCESS)
10394                 goto free_taskpool;
10395         isc_task_setname(zmgr->task, "zmgr", zmgr);
10396         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
10397                                         &zmgr->rl);
10398         if (result != ISC_R_SUCCESS)
10399                 goto free_task;
10400         /* default to 20 refresh queries / notifies per second. */
10401         isc_interval_set(&interval, 0, 1000000000/2);
10402         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
10403         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10404         isc_ratelimiter_setpertic(zmgr->rl, 10);
10405
10406         zmgr->iolimit = 1;
10407         zmgr->ioactive = 0;
10408         ISC_LIST_INIT(zmgr->high);
10409         ISC_LIST_INIT(zmgr->low);
10410
10411         result = isc_mutex_init(&zmgr->iolock);
10412         if (result != ISC_R_SUCCESS)
10413                 goto free_rl;
10414
10415         zmgr->magic = ZONEMGR_MAGIC;
10416
10417         *zmgrp = zmgr;
10418         return (ISC_R_SUCCESS);
10419
10420 #if 0
10421  free_iolock:
10422         DESTROYLOCK(&zmgr->iolock);
10423 #endif
10424  free_rl:
10425         isc_ratelimiter_detach(&zmgr->rl);
10426  free_task:
10427         isc_task_detach(&zmgr->task);
10428  free_taskpool:
10429         isc_taskpool_destroy(&zmgr->zonetasks);
10430  free_rwlock:
10431         isc_rwlock_destroy(&zmgr->rwlock);
10432  free_mem:
10433         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
10434         isc_mem_detach(&mctx);
10435         return (result);
10436 }
10437
10438 isc_result_t
10439 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
10440         isc_result_t result;
10441
10442         REQUIRE(DNS_ZONE_VALID(zone));
10443         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10444
10445         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10446         LOCK_ZONE(zone);
10447         REQUIRE(zone->task == NULL);
10448         REQUIRE(zone->timer == NULL);
10449         REQUIRE(zone->zmgr == NULL);
10450
10451         isc_taskpool_gettask(zmgr->zonetasks,
10452                              dns_name_hash(dns_zone_getorigin(zone),
10453                                            ISC_FALSE),
10454                              &zone->task);
10455
10456         /*
10457          * Set the task name.  The tag will arbitrarily point to one
10458          * of the zones sharing the task (in practice, the one
10459          * to be managed last).
10460          */
10461         isc_task_setname(zone->task, "zone", zone);
10462
10463         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
10464                                   NULL, NULL,
10465                                   zone->task, zone_timer, zone,
10466                                   &zone->timer);
10467
10468         if (result != ISC_R_SUCCESS)
10469                 goto cleanup_task;
10470
10471         /*
10472          * The timer "holds" a iref.
10473          */
10474         zone->irefs++;
10475         INSIST(zone->irefs != 0);
10476
10477         ISC_LIST_APPEND(zmgr->zones, zone, link);
10478         zone->zmgr = zmgr;
10479         zmgr->refs++;
10480
10481         goto unlock;
10482
10483  cleanup_task:
10484         isc_task_detach(&zone->task);
10485
10486  unlock:
10487         UNLOCK_ZONE(zone);
10488         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10489         return (result);
10490 }
10491
10492 void
10493 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
10494         isc_boolean_t free_now = ISC_FALSE;
10495
10496         REQUIRE(DNS_ZONE_VALID(zone));
10497         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10498         REQUIRE(zone->zmgr == zmgr);
10499
10500         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10501         LOCK_ZONE(zone);
10502
10503         ISC_LIST_UNLINK(zmgr->zones, zone, link);
10504         zone->zmgr = NULL;
10505         zmgr->refs--;
10506         if (zmgr->refs == 0)
10507                 free_now = ISC_TRUE;
10508
10509         UNLOCK_ZONE(zone);
10510         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10511
10512         if (free_now)
10513                 zonemgr_free(zmgr);
10514         ENSURE(zone->zmgr == NULL);
10515 }
10516
10517 void
10518 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
10519         REQUIRE(DNS_ZONEMGR_VALID(source));
10520         REQUIRE(target != NULL && *target == NULL);
10521
10522         RWLOCK(&source->rwlock, isc_rwlocktype_write);
10523         REQUIRE(source->refs > 0);
10524         source->refs++;
10525         INSIST(source->refs > 0);
10526         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
10527         *target = source;
10528 }
10529
10530 void
10531 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
10532         dns_zonemgr_t *zmgr;
10533         isc_boolean_t free_now = ISC_FALSE;
10534
10535         REQUIRE(zmgrp != NULL);
10536         zmgr = *zmgrp;
10537         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10538
10539         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10540         zmgr->refs--;
10541         if (zmgr->refs == 0)
10542                 free_now = ISC_TRUE;
10543         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10544
10545         if (free_now)
10546                 zonemgr_free(zmgr);
10547 }
10548
10549 isc_result_t
10550 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
10551         dns_zone_t *p;
10552
10553         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10554
10555         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
10556         for (p = ISC_LIST_HEAD(zmgr->zones);
10557              p != NULL;
10558              p = ISC_LIST_NEXT(p, link))
10559         {
10560                 dns_zone_maintenance(p);
10561         }
10562         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
10563
10564         /*
10565          * Recent configuration changes may have increased the
10566          * amount of available transfers quota.  Make sure any
10567          * transfers currently blocked on quota get started if
10568          * possible.
10569          */
10570         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10571         zmgr_resume_xfrs(zmgr, ISC_TRUE);
10572         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10573         return (ISC_R_SUCCESS);
10574 }
10575
10576 void
10577 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
10578
10579         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10580
10581         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10582         zmgr_resume_xfrs(zmgr, ISC_TRUE);
10583         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10584 }
10585
10586 void
10587 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
10588         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10589
10590         isc_ratelimiter_shutdown(zmgr->rl);
10591
10592         if (zmgr->task != NULL)
10593                 isc_task_destroy(&zmgr->task);
10594         if (zmgr->zonetasks != NULL)
10595                 isc_taskpool_destroy(&zmgr->zonetasks);
10596 }
10597
10598 static void
10599 zonemgr_free(dns_zonemgr_t *zmgr) {
10600         isc_mem_t *mctx;
10601
10602         INSIST(zmgr->refs == 0);
10603         INSIST(ISC_LIST_EMPTY(zmgr->zones));
10604
10605         zmgr->magic = 0;
10606
10607         DESTROYLOCK(&zmgr->iolock);
10608         isc_ratelimiter_detach(&zmgr->rl);
10609
10610         isc_rwlock_destroy(&zmgr->rwlock);
10611         mctx = zmgr->mctx;
10612         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
10613         isc_mem_detach(&mctx);
10614 }
10615
10616 void
10617 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
10618         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10619
10620         zmgr->transfersin = value;
10621 }
10622
10623 isc_uint32_t
10624 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
10625         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10626
10627         return (zmgr->transfersin);
10628 }
10629
10630 void
10631 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
10632         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10633
10634         zmgr->transfersperns = value;
10635 }
10636
10637 isc_uint32_t
10638 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
10639         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10640
10641         return (zmgr->transfersperns);
10642 }
10643
10644 /*
10645  * Try to start a new incoming zone transfer to fill a quota
10646  * slot that was just vacated.
10647  *
10648  * Requires:
10649  *      The zone manager is locked by the caller.
10650  */
10651 static void
10652 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
10653         dns_zone_t *zone;
10654         dns_zone_t *next;
10655
10656         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
10657              zone != NULL;
10658              zone = next)
10659         {
10660                 isc_result_t result;
10661                 next = ISC_LIST_NEXT(zone, statelink);
10662                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
10663                 if (result == ISC_R_SUCCESS) {
10664                         if (multi)
10665                                 continue;
10666                         /*
10667                          * We successfully filled the slot.  We're done.
10668                          */
10669                         break;
10670                 } else if (result == ISC_R_QUOTA) {
10671                         /*
10672                          * Not enough quota.  This is probably the per-server
10673                          * quota, because we usually get called when a unit of
10674                          * global quota has just been freed.  Try the next
10675                          * zone, it may succeed if it uses another master.
10676                          */
10677                         continue;
10678                 } else {
10679                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10680                                      "starting zone transfer: %s",
10681                                      isc_result_totext(result));
10682                         break;
10683                 }
10684         }
10685 }
10686
10687 /*
10688  * Try to start an incoming zone transfer for 'zone', quota permitting.
10689  *
10690  * Requires:
10691  *      The zone manager is locked by the caller.
10692  *
10693  * Returns:
10694  *      ISC_R_SUCCESS   There was enough quota and we attempted to
10695  *                      start a transfer.  zone_xfrdone() has been or will
10696  *                      be called.
10697  *      ISC_R_QUOTA     Not enough quota.
10698  *      Others          Failure.
10699  */
10700 static isc_result_t
10701 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
10702         dns_peer_t *peer = NULL;
10703         isc_netaddr_t masterip;
10704         isc_uint32_t nxfrsin, nxfrsperns;
10705         dns_zone_t *x;
10706         isc_uint32_t maxtransfersin, maxtransfersperns;
10707         isc_event_t *e;
10708
10709         /*
10710          * Find any configured information about the server we'd
10711          * like to transfer this zone from.
10712          */
10713         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10714         (void)dns_peerlist_peerbyaddr(zone->view->peers,
10715                                       &masterip, &peer);
10716
10717         /*
10718          * Determine the total maximum number of simultaneous
10719          * transfers allowed, and the maximum for this specific
10720          * master.
10721          */
10722         maxtransfersin = zmgr->transfersin;
10723         maxtransfersperns = zmgr->transfersperns;
10724         if (peer != NULL)
10725                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
10726
10727         /*
10728          * Count the total number of transfers that are in progress,
10729          * and the number of transfers in progress from this master.
10730          * We linearly scan a list of all transfers; if this turns
10731          * out to be too slow, we could hash on the master address.
10732          */
10733         nxfrsin = nxfrsperns = 0;
10734         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
10735              x != NULL;
10736              x = ISC_LIST_NEXT(x, statelink))
10737         {
10738                 isc_netaddr_t xip;
10739                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
10740                 nxfrsin++;
10741                 if (isc_netaddr_equal(&xip, &masterip))
10742                         nxfrsperns++;
10743         }
10744
10745         /* Enforce quota. */
10746         if (nxfrsin >= maxtransfersin)
10747                 return (ISC_R_QUOTA);
10748
10749         if (nxfrsperns >= maxtransfersperns)
10750                 return (ISC_R_QUOTA);
10751
10752         /*
10753          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
10754          * list and send it an event to let it start the actual transfer in the
10755          * context of its own task.
10756          */
10757         e = isc_event_allocate(zmgr->mctx, zmgr,
10758                                DNS_EVENT_ZONESTARTXFRIN,
10759                                got_transfer_quota, zone,
10760                                sizeof(isc_event_t));
10761         if (e == NULL)
10762                 return (ISC_R_NOMEMORY);
10763
10764         LOCK_ZONE(zone);
10765         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
10766         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
10767         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
10768         zone->statelist = &zmgr->xfrin_in_progress;
10769         isc_task_send(zone->task, &e);
10770         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
10771         UNLOCK_ZONE(zone);
10772
10773         return (ISC_R_SUCCESS);
10774 }
10775
10776 void
10777 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
10778
10779         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10780         REQUIRE(iolimit > 0);
10781
10782         zmgr->iolimit = iolimit;
10783 }
10784
10785 isc_uint32_t
10786 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
10787
10788         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10789
10790         return (zmgr->iolimit);
10791 }
10792
10793 /*
10794  * Get permission to request a file handle from the OS.
10795  * An event will be sent to action when one is available.
10796  * There are two queues available (high and low), the high
10797  * queue will be serviced before the low one.
10798  *
10799  * zonemgr_putio() must be called after the event is delivered to
10800  * 'action'.
10801  */
10802
10803 static isc_result_t
10804 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
10805               isc_task_t *task, isc_taskaction_t action, void *arg,
10806               dns_io_t **iop)
10807 {
10808         dns_io_t *io;
10809         isc_boolean_t queue;
10810
10811         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10812         REQUIRE(iop != NULL && *iop == NULL);
10813
10814         io = isc_mem_get(zmgr->mctx, sizeof(*io));
10815         if (io == NULL)
10816                 return (ISC_R_NOMEMORY);
10817         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
10818                                        action, arg, sizeof(*io->event));
10819         if (io->event == NULL) {
10820                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
10821                 return (ISC_R_NOMEMORY);
10822         }
10823         io->zmgr = zmgr;
10824         io->high = high;
10825         io->task = NULL;
10826         isc_task_attach(task, &io->task);
10827         ISC_LINK_INIT(io, link);
10828         io->magic = IO_MAGIC;
10829
10830         LOCK(&zmgr->iolock);
10831         zmgr->ioactive++;
10832         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
10833         if (queue) {
10834                 if (io->high)
10835                         ISC_LIST_APPEND(zmgr->high, io, link);
10836                 else
10837                         ISC_LIST_APPEND(zmgr->low, io, link);
10838         }
10839         UNLOCK(&zmgr->iolock);
10840         *iop = io;
10841
10842         if (!queue) {
10843                 isc_task_send(io->task, &io->event);
10844         }
10845         return (ISC_R_SUCCESS);
10846 }
10847
10848 static void
10849 zonemgr_putio(dns_io_t **iop) {
10850         dns_io_t *io;
10851         dns_io_t *next;
10852         dns_zonemgr_t *zmgr;
10853
10854         REQUIRE(iop != NULL);
10855         io = *iop;
10856         REQUIRE(DNS_IO_VALID(io));
10857
10858         *iop = NULL;
10859
10860         INSIST(!ISC_LINK_LINKED(io, link));
10861         INSIST(io->event == NULL);
10862
10863         zmgr = io->zmgr;
10864         isc_task_detach(&io->task);
10865         io->magic = 0;
10866         isc_mem_put(zmgr->mctx, io, sizeof(*io));
10867
10868         LOCK(&zmgr->iolock);
10869         INSIST(zmgr->ioactive > 0);
10870         zmgr->ioactive--;
10871         next = HEAD(zmgr->high);
10872         if (next == NULL)
10873                 next = HEAD(zmgr->low);
10874         if (next != NULL) {
10875                 if (next->high)
10876                         ISC_LIST_UNLINK(zmgr->high, next, link);
10877                 else
10878                         ISC_LIST_UNLINK(zmgr->low, next, link);
10879                 INSIST(next->event != NULL);
10880         }
10881         UNLOCK(&zmgr->iolock);
10882         if (next != NULL)
10883                 isc_task_send(next->task, &next->event);
10884 }
10885
10886 static void
10887 zonemgr_cancelio(dns_io_t *io) {
10888         isc_boolean_t send_event = ISC_FALSE;
10889
10890         REQUIRE(DNS_IO_VALID(io));
10891
10892         /*
10893          * If we are queued to be run then dequeue.
10894          */
10895         LOCK(&io->zmgr->iolock);
10896         if (ISC_LINK_LINKED(io, link)) {
10897                 if (io->high)
10898                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
10899                 else
10900                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
10901
10902                 send_event = ISC_TRUE;
10903                 INSIST(io->event != NULL);
10904         }
10905         UNLOCK(&io->zmgr->iolock);
10906         if (send_event) {
10907                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
10908                 isc_task_send(io->task, &io->event);
10909         }
10910 }
10911
10912 static void
10913 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
10914         char *buf;
10915         int buflen;
10916         isc_result_t result;
10917
10918         buflen = strlen(path) + strlen(templat) + 2;
10919
10920         buf = isc_mem_get(zone->mctx, buflen);
10921         if (buf == NULL)
10922                 return;
10923
10924         result = isc_file_template(path, templat, buf, buflen);
10925         if (result != ISC_R_SUCCESS)
10926                 goto cleanup;
10927
10928         result = isc_file_renameunique(path, buf);
10929         if (result != ISC_R_SUCCESS)
10930                 goto cleanup;
10931
10932         dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'",
10933                      path, buf);
10934
10935  cleanup:
10936         isc_mem_put(zone->mctx, buf, buflen);
10937 }
10938
10939 #if 0
10940 /* Hook for ondestroy notification from a database. */
10941
10942 static void
10943 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
10944         dns_db_t *db = event->sender;
10945         UNUSED(task);
10946
10947         isc_event_free(&event);
10948
10949         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
10950                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
10951                       "database (%p) destroyed", (void*) db);
10952 }
10953 #endif
10954
10955 void
10956 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
10957         isc_interval_t interval;
10958         isc_uint32_t s, ns;
10959         isc_uint32_t pertic;
10960         isc_result_t result;
10961
10962         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10963
10964         if (value == 0)
10965                 value = 1;
10966
10967         if (value == 1) {
10968                 s = 1;
10969                 ns = 0;
10970                 pertic = 1;
10971         } else if (value <= 10) {
10972                 s = 0;
10973                 ns = 1000000000 / value;
10974                 pertic = 1;
10975         } else {
10976                 s = 0;
10977                 ns = (1000000000 / value) * 10;
10978                 pertic = 10;
10979         }
10980
10981         isc_interval_set(&interval, s, ns);
10982         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
10983         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10984         isc_ratelimiter_setpertic(zmgr->rl, pertic);
10985
10986         zmgr->serialqueryrate = value;
10987 }
10988
10989 unsigned int
10990 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
10991         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10992
10993         return (zmgr->serialqueryrate);
10994 }
10995
10996 static isc_boolean_t
10997 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
10998                         isc_sockaddr_t *local, isc_time_t *now)
10999 {
11000         unsigned int i;
11001         isc_rwlocktype_t locktype;
11002         isc_result_t result;
11003         isc_uint32_t seconds = isc_time_seconds(now);
11004
11005         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11006
11007         locktype = isc_rwlocktype_read;
11008         RWLOCK(&zmgr->rwlock, locktype);
11009         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
11010                 if (zmgr->unreachable[i].expire >= seconds &&
11011                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
11012                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
11013                         result = isc_rwlock_tryupgrade(&zmgr->rwlock);
11014                         if (result == ISC_R_SUCCESS) {
11015                                 locktype = isc_rwlocktype_write;
11016                                 zmgr->unreachable[i].last = seconds;
11017                         }
11018                         break;
11019                 }
11020         }
11021         RWUNLOCK(&zmgr->rwlock, locktype);
11022         return (ISC_TF(i < UNREACH_CHACHE_SIZE));
11023 }
11024
11025 void
11026 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
11027                            isc_sockaddr_t *local, isc_time_t *now)
11028 {
11029         isc_uint32_t seconds = isc_time_seconds(now);
11030         isc_uint32_t last = seconds;
11031         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
11032
11033         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11034
11035         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
11036         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
11037                 /* Existing entry? */
11038                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
11039                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
11040                         break;
11041                 /* Empty slot? */
11042                 if (zmgr->unreachable[i].expire < seconds)
11043                         slot = i;
11044                 /* Least recently used slot? */
11045                 if (zmgr->unreachable[i].last < last) {
11046                         last = zmgr->unreachable[i].last;
11047                         oldest = i;
11048                 }
11049         }
11050         if (i < UNREACH_CHACHE_SIZE) {
11051                 /*
11052                  * Found a existing entry.  Update the expire timer and
11053                  * last usage timestamps.
11054                  */
11055                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
11056                 zmgr->unreachable[i].last = seconds;
11057         } else if (slot != UNREACH_CHACHE_SIZE) {
11058                 /*
11059                  * Found a empty slot. Add a new entry to the cache.
11060                  */
11061                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
11062                 zmgr->unreachable[slot].last = seconds;
11063                 zmgr->unreachable[slot].remote = *remote;
11064                 zmgr->unreachable[slot].local = *local;
11065         } else {
11066                 /*
11067                  * Replace the least recently used entry in the cache.
11068                  */
11069                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
11070                 zmgr->unreachable[oldest].last = seconds;
11071                 zmgr->unreachable[oldest].remote = *remote;
11072                 zmgr->unreachable[oldest].local = *local;
11073         }
11074         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
11075 }
11076
11077 void
11078 dns_zone_forcereload(dns_zone_t *zone) {
11079         REQUIRE(DNS_ZONE_VALID(zone));
11080
11081         if (zone->type == dns_zone_master)
11082                 return;
11083
11084         LOCK_ZONE(zone);
11085         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
11086         UNLOCK_ZONE(zone);
11087         dns_zone_refresh(zone);
11088 }
11089
11090 isc_boolean_t
11091 dns_zone_isforced(dns_zone_t *zone) {
11092         REQUIRE(DNS_ZONE_VALID(zone));
11093
11094         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
11095 }
11096
11097 isc_result_t
11098 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
11099         /*
11100          * This function is obsoleted.
11101          */
11102         UNUSED(zone);
11103         UNUSED(on);
11104         return (ISC_R_NOTIMPLEMENTED);
11105 }
11106
11107 isc_uint64_t *
11108 dns_zone_getstatscounters(dns_zone_t *zone) {
11109         /*
11110          * This function is obsoleted.
11111          */
11112         UNUSED(zone);
11113         return (NULL);
11114 }
11115
11116 void
11117 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
11118         REQUIRE(DNS_ZONE_VALID(zone));
11119         REQUIRE(zone->stats == NULL);
11120
11121         LOCK_ZONE(zone);
11122         zone->stats = NULL;
11123         isc_stats_attach(stats, &zone->stats);
11124         UNLOCK_ZONE(zone);
11125 }
11126
11127 void
11128 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
11129         REQUIRE(DNS_ZONE_VALID(zone));
11130
11131         LOCK_ZONE(zone);
11132         if (zone->requeststats_on && stats == NULL)
11133                 zone->requeststats_on = ISC_FALSE;
11134         else if (!zone->requeststats_on && stats != NULL) {
11135                 if (zone->requeststats == NULL) {
11136                         isc_stats_attach(stats, &zone->requeststats);
11137                         zone->requeststats_on = ISC_TRUE;
11138                 }
11139         }
11140         UNLOCK_ZONE(zone);
11141
11142         return;
11143 }
11144
11145 isc_stats_t *
11146 dns_zone_getrequeststats(dns_zone_t *zone) {
11147         /*
11148          * We don't lock zone for efficiency reason.  This is not catastrophic
11149          * because requeststats must always be valid when requeststats_on is
11150          * true.
11151          * Some counters may be incremented while requeststats_on is becoming
11152          * false, or some cannot be incremented just after the statistics are
11153          * installed, but it shouldn't matter much in practice.
11154          */
11155         if (zone->requeststats_on)
11156                 return (zone->requeststats);
11157         else
11158                 return (NULL);
11159 }
11160
11161 void
11162 dns_zone_dialup(dns_zone_t *zone) {
11163
11164         REQUIRE(DNS_ZONE_VALID(zone));
11165
11166         zone_debuglog(zone, "dns_zone_dialup", 3,
11167                       "notify = %d, refresh = %d",
11168                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
11169                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
11170
11171         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
11172                 dns_zone_notify(zone);
11173         if (zone->type != dns_zone_master &&
11174             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11175                 dns_zone_refresh(zone);
11176 }
11177
11178 void
11179 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
11180         REQUIRE(DNS_ZONE_VALID(zone));
11181
11182         LOCK_ZONE(zone);
11183         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
11184                          DNS_ZONEFLG_DIALREFRESH |
11185                          DNS_ZONEFLG_NOREFRESH);
11186         switch (dialup) {
11187         case dns_dialuptype_no:
11188                 break;
11189         case dns_dialuptype_yes:
11190                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
11191                                  DNS_ZONEFLG_DIALREFRESH |
11192                                  DNS_ZONEFLG_NOREFRESH));
11193                 break;
11194         case dns_dialuptype_notify:
11195                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
11196                 break;
11197         case dns_dialuptype_notifypassive:
11198                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
11199                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
11200                 break;
11201         case dns_dialuptype_refresh:
11202                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
11203                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
11204                 break;
11205         case dns_dialuptype_passive:
11206                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
11207                 break;
11208         default:
11209                 INSIST(0);
11210         }
11211         UNLOCK_ZONE(zone);
11212 }
11213
11214 isc_result_t
11215 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
11216         isc_result_t result = ISC_R_SUCCESS;
11217
11218         REQUIRE(DNS_ZONE_VALID(zone));
11219
11220         LOCK_ZONE(zone);
11221         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
11222         UNLOCK_ZONE(zone);
11223
11224         return (result);
11225 }
11226
11227 const char *
11228 dns_zone_getkeydirectory(dns_zone_t *zone) {
11229         REQUIRE(DNS_ZONE_VALID(zone));
11230
11231         return (zone->keydirectory);
11232 }
11233
11234 unsigned int
11235 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
11236         dns_zone_t *zone;
11237         unsigned int count = 0;
11238
11239         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11240
11241         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
11242         switch (state) {
11243         case DNS_ZONESTATE_XFERRUNNING:
11244                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
11245                      zone != NULL;
11246                      zone = ISC_LIST_NEXT(zone, statelink))
11247                         count++;
11248                 break;
11249         case DNS_ZONESTATE_XFERDEFERRED:
11250                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
11251                      zone != NULL;
11252                      zone = ISC_LIST_NEXT(zone, statelink))
11253                         count++;
11254                 break;
11255         case DNS_ZONESTATE_SOAQUERY:
11256                 for (zone = ISC_LIST_HEAD(zmgr->zones);
11257                      zone != NULL;
11258                      zone = ISC_LIST_NEXT(zone, link))
11259                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
11260                                 count++;
11261                 break;
11262         case DNS_ZONESTATE_ANY:
11263                 for (zone = ISC_LIST_HEAD(zmgr->zones);
11264                      zone != NULL;
11265                      zone = ISC_LIST_NEXT(zone, link)) {
11266                         dns_view_t *view = zone->view;
11267                         if (view != NULL && strcmp(view->name, "_bind") == 0)
11268                                 continue;
11269                         count++;
11270                 }
11271                 break;
11272         default:
11273                 INSIST(0);
11274         }
11275
11276         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
11277
11278         return (count);
11279 }
11280
11281 isc_result_t
11282 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
11283         isc_boolean_t ok = ISC_TRUE;
11284         isc_boolean_t fail = ISC_FALSE;
11285         char namebuf[DNS_NAME_FORMATSIZE];
11286         char namebuf2[DNS_NAME_FORMATSIZE];
11287         char typebuf[DNS_RDATATYPE_FORMATSIZE];
11288         int level = ISC_LOG_WARNING;
11289         dns_name_t bad;
11290
11291         REQUIRE(DNS_ZONE_VALID(zone));
11292
11293         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
11294                 return (ISC_R_SUCCESS);
11295
11296         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
11297                 level = ISC_LOG_ERROR;
11298                 fail = ISC_TRUE;
11299         }
11300
11301         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
11302         if (!ok) {
11303                 dns_name_format(name, namebuf, sizeof(namebuf));
11304                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
11305                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
11306                              dns_result_totext(DNS_R_BADOWNERNAME));
11307                 if (fail)
11308                         return (DNS_R_BADOWNERNAME);
11309         }
11310
11311         dns_name_init(&bad, NULL);
11312         ok = dns_rdata_checknames(rdata, name, &bad);
11313         if (!ok) {
11314                 dns_name_format(name, namebuf, sizeof(namebuf));
11315                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
11316                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
11317                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
11318                              namebuf2, dns_result_totext(DNS_R_BADNAME));
11319                 if (fail)
11320                         return (DNS_R_BADNAME);
11321         }
11322
11323         return (ISC_R_SUCCESS);
11324 }
11325
11326 void
11327 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
11328         REQUIRE(DNS_ZONE_VALID(zone));
11329         zone->checkmx = checkmx;
11330 }
11331
11332 void
11333 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
11334         REQUIRE(DNS_ZONE_VALID(zone));
11335         zone->checksrv = checksrv;
11336 }
11337
11338 void
11339 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
11340         REQUIRE(DNS_ZONE_VALID(zone));
11341         zone->checkns = checkns;
11342 }
11343
11344 void
11345 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
11346         REQUIRE(DNS_ZONE_VALID(zone));
11347
11348         LOCK_ZONE(zone);
11349         zone->isself = isself;
11350         zone->isselfarg = arg;
11351         UNLOCK_ZONE(zone);
11352 }
11353
11354 void
11355 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
11356         REQUIRE(DNS_ZONE_VALID(zone));
11357
11358         LOCK_ZONE(zone);
11359         zone->notifydelay = delay;
11360         UNLOCK_ZONE(zone);
11361 }
11362
11363 isc_uint32_t
11364 dns_zone_getnotifydelay(dns_zone_t *zone) {
11365         REQUIRE(DNS_ZONE_VALID(zone));
11366
11367         return (zone->notifydelay);
11368 }
11369
11370 isc_result_t
11371 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
11372                      isc_uint16_t keyid, isc_boolean_t delete)
11373 {
11374         isc_result_t result;
11375         REQUIRE(DNS_ZONE_VALID(zone));
11376
11377         dns_zone_log(zone, ISC_LOG_NOTICE,
11378                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
11379                      algorithm, keyid);
11380         LOCK_ZONE(zone);
11381         result = zone_signwithkey(zone, algorithm, keyid, delete);
11382         UNLOCK_ZONE(zone);
11383
11384         return (result);
11385 }
11386
11387 static const char *hex = "0123456789ABCDEF";
11388
11389 isc_result_t
11390 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
11391         isc_result_t result;
11392         char salt[255*2+1];
11393         unsigned int i, j;
11394
11395         REQUIRE(DNS_ZONE_VALID(zone));
11396
11397         if (nsec3param->salt_length != 0) {
11398                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
11399                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
11400                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
11401                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
11402                 }
11403                 salt[j] = '\0';
11404         } else
11405                 strcpy(salt, "-");
11406         dns_zone_log(zone, ISC_LOG_NOTICE,
11407                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
11408                      nsec3param->hash, nsec3param->iterations,
11409                      salt);
11410         LOCK_ZONE(zone);
11411         result = zone_addnsec3chain(zone, nsec3param);
11412         UNLOCK_ZONE(zone);
11413
11414         return (result);
11415 }
11416
11417 void
11418 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
11419         REQUIRE(DNS_ZONE_VALID(zone));
11420
11421         if (nodes == 0)
11422                 nodes = 1;
11423         zone->nodes = nodes;
11424 }
11425
11426 void
11427 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
11428         REQUIRE(DNS_ZONE_VALID(zone));
11429
11430         /*
11431          * We treat signatures as a signed value so explicitly
11432          * limit its range here.
11433          */
11434         if (signatures > ISC_INT32_MAX)
11435                 signatures = ISC_INT32_MAX;
11436         else if (signatures == 0)
11437                 signatures = 1;
11438         zone->signatures = signatures;
11439 }
11440
11441 void
11442 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
11443         REQUIRE(DNS_ZONE_VALID(zone));
11444         zone->privatetype = type;
11445 }
11446
11447 dns_rdatatype_t
11448 dns_zone_getprivatetype(dns_zone_t *zone) {
11449         REQUIRE(DNS_ZONE_VALID(zone));
11450         return (zone->privatetype);
11451 }
11452
11453 static isc_result_t
11454 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
11455                  isc_boolean_t delete)
11456 {
11457         dns_signing_t *signing;
11458         dns_signing_t *current;
11459         isc_result_t result = ISC_R_SUCCESS;
11460         isc_time_t now;
11461
11462         signing = isc_mem_get(zone->mctx, sizeof *signing);
11463         if (signing == NULL)
11464                 return (ISC_R_NOMEMORY);
11465
11466         signing->magic = 0;
11467         signing->db  = NULL;
11468         signing->dbiterator = NULL;
11469         signing->algorithm = algorithm;
11470         signing->keyid = keyid;
11471         signing->delete = delete;
11472         signing->done = ISC_FALSE;
11473
11474         TIME_NOW(&now);
11475
11476         for (current = ISC_LIST_HEAD(zone->signing);
11477              current != NULL;
11478              current = ISC_LIST_NEXT(current, link)) {
11479                 if (current->db == zone->db &&
11480                     current->algorithm == signing->algorithm &&
11481                     current->keyid == signing->keyid) {
11482                         if (current->delete != signing->delete)
11483                                 current->done = ISC_TRUE;
11484                         else
11485                                 goto cleanup;
11486                 }
11487         }
11488
11489         if (zone->db != NULL) {
11490                 dns_db_attach(zone->db, &signing->db);
11491                 result = dns_db_createiterator(signing->db, 0,
11492                                                &signing->dbiterator);
11493
11494                 if (result == ISC_R_SUCCESS)
11495                         result = dns_dbiterator_first(signing->dbiterator);
11496                 if (result == ISC_R_SUCCESS) {
11497                         dns_dbiterator_pause(signing->dbiterator);
11498                         ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
11499                         signing = NULL;
11500                         if (isc_time_isepoch(&zone->signingtime)) {
11501                                 zone->signingtime = now;
11502                                 if (zone->task != NULL)
11503                                         zone_settimer(zone, &now);
11504                         }
11505                 }
11506         } else
11507                 result = ISC_R_NOTFOUND;
11508
11509  cleanup:
11510         if (signing != NULL) {
11511                 dns_db_detach(&signing->db);
11512                 if (signing->dbiterator != NULL)
11513                         dns_dbiterator_destroy(&signing->dbiterator);
11514                 isc_mem_put(zone->mctx, signing, sizeof *signing);
11515         }
11516         return (result);
11517 }