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