]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - contrib/bind9/lib/dns/zone.c
MFC: r253983-253984
[FreeBSD/stable/8.git] / contrib / bind9 / lib / dns / zone.c
1 /*
2  * Copyright (C) 2004-2014  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$ */
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/keydata.h>
51 #include <dns/keytable.h>
52 #include <dns/keyvalues.h>
53 #include <dns/log.h>
54 #include <dns/master.h>
55 #include <dns/masterdump.h>
56 #include <dns/message.h>
57 #include <dns/name.h>
58 #include <dns/nsec.h>
59 #include <dns/nsec3.h>
60 #include <dns/peer.h>
61 #include <dns/private.h>
62 #include <dns/rbt.h>
63 #include <dns/rcode.h>
64 #include <dns/rdataclass.h>
65 #include <dns/rdatalist.h>
66 #include <dns/rdataset.h>
67 #include <dns/rdatasetiter.h>
68 #include <dns/rdatastruct.h>
69 #include <dns/rdatatype.h>
70 #include <dns/request.h>
71 #include <dns/resolver.h>
72 #include <dns/result.h>
73 #include <dns/rriterator.h>
74 #include <dns/soa.h>
75 #include <dns/ssu.h>
76 #include <dns/stats.h>
77 #include <dns/time.h>
78 #include <dns/tsig.h>
79 #include <dns/xfrin.h>
80 #include <dns/zone.h>
81
82 #include <dst/dst.h>
83
84 #define ZONE_MAGIC                      ISC_MAGIC('Z', 'O', 'N', 'E')
85 #define DNS_ZONE_VALID(zone)            ISC_MAGIC_VALID(zone, ZONE_MAGIC)
86
87 #define NOTIFY_MAGIC                    ISC_MAGIC('N', 't', 'f', 'y')
88 #define DNS_NOTIFY_VALID(notify)        ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
89
90 #define STUB_MAGIC                      ISC_MAGIC('S', 't', 'u', 'b')
91 #define DNS_STUB_VALID(stub)            ISC_MAGIC_VALID(stub, STUB_MAGIC)
92
93 #define ZONEMGR_MAGIC                   ISC_MAGIC('Z', 'm', 'g', 'r')
94 #define DNS_ZONEMGR_VALID(stub)         ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
95
96 #define LOAD_MAGIC                      ISC_MAGIC('L', 'o', 'a', 'd')
97 #define DNS_LOAD_VALID(load)            ISC_MAGIC_VALID(load, LOAD_MAGIC)
98
99 #define FORWARD_MAGIC                   ISC_MAGIC('F', 'o', 'r', 'w')
100 #define DNS_FORWARD_VALID(load)         ISC_MAGIC_VALID(load, FORWARD_MAGIC)
101
102 #define IO_MAGIC                        ISC_MAGIC('Z', 'm', 'I', 'O')
103 #define DNS_IO_VALID(load)              ISC_MAGIC_VALID(load, IO_MAGIC)
104
105 /*%
106  * Ensure 'a' is at least 'min' but not more than 'max'.
107  */
108 #define RANGE(a, min, max) \
109                 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
110
111 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
112
113 /*%
114  * Key flags
115  */
116 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
117 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
118 #define ALG(x) dst_key_alg(x)
119
120 /*
121  * Default values.
122  */
123 #define DNS_DEFAULT_IDLEIN 3600         /*%< 1 hour */
124 #define DNS_DEFAULT_IDLEOUT 3600        /*%< 1 hour */
125 #define MAX_XFER_TIME (2*3600)          /*%< Documented default is 2 hours */
126 #define RESIGN_DELAY 3600               /*%< 1 hour */
127
128 #ifndef DNS_MAX_EXPIRE
129 #define DNS_MAX_EXPIRE  14515200        /*%< 24 weeks */
130 #endif
131
132 #ifndef DNS_DUMP_DELAY
133 #define DNS_DUMP_DELAY 900              /*%< 15 minutes */
134 #endif
135
136 typedef struct dns_notify dns_notify_t;
137 typedef struct dns_stub dns_stub_t;
138 typedef struct dns_load dns_load_t;
139 typedef struct dns_forward dns_forward_t;
140 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
141 typedef struct dns_io dns_io_t;
142 typedef ISC_LIST(dns_io_t) dns_iolist_t;
143 typedef struct dns_signing dns_signing_t;
144 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
145 typedef struct dns_nsec3chain dns_nsec3chain_t;
146 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
147 typedef struct dns_keyfetch dns_keyfetch_t;
148
149 #define DNS_ZONE_CHECKLOCK
150 #ifdef DNS_ZONE_CHECKLOCK
151 #define LOCK_ZONE(z) \
152          do { LOCK(&(z)->lock); \
153               INSIST((z)->locked == ISC_FALSE); \
154              (z)->locked = ISC_TRUE; \
155                 } while (0)
156 #define UNLOCK_ZONE(z) \
157         do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
158 #define LOCKED_ZONE(z) ((z)->locked)
159 #else
160 #define LOCK_ZONE(z) LOCK(&(z)->lock)
161 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
162 #define LOCKED_ZONE(z) ISC_TRUE
163 #endif
164
165 #ifdef ISC_RWLOCK_USEATOMIC
166 #define ZONEDB_INITLOCK(l)      isc_rwlock_init((l), 0, 0)
167 #define ZONEDB_DESTROYLOCK(l)   isc_rwlock_destroy(l)
168 #define ZONEDB_LOCK(l, t)       RWLOCK((l), (t))
169 #define ZONEDB_UNLOCK(l, t)     RWUNLOCK((l), (t))
170 #else
171 #define ZONEDB_INITLOCK(l)      isc_mutex_init(l)
172 #define ZONEDB_DESTROYLOCK(l)   DESTROYLOCK(l)
173 #define ZONEDB_LOCK(l, t)       LOCK(l)
174 #define ZONEDB_UNLOCK(l, t)     UNLOCK(l)
175 #endif
176
177 struct dns_zone {
178         /* Unlocked */
179         unsigned int            magic;
180         isc_mutex_t             lock;
181 #ifdef DNS_ZONE_CHECKLOCK
182         isc_boolean_t           locked;
183 #endif
184         isc_mem_t               *mctx;
185         isc_refcount_t          erefs;
186
187 #ifdef ISC_RWLOCK_USEATOMIC
188         isc_rwlock_t            dblock;
189 #else
190         isc_mutex_t             dblock;
191 #endif
192         dns_db_t                *db;            /* Locked by dblock */
193
194         /* Locked */
195         dns_zonemgr_t           *zmgr;
196         ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
197         isc_timer_t             *timer;
198         unsigned int            irefs;
199         dns_name_t              origin;
200         char                    *masterfile;
201         dns_masterformat_t      masterformat;
202         char                    *journal;
203         isc_int32_t             journalsize;
204         dns_rdataclass_t        rdclass;
205         dns_zonetype_t          type;
206         unsigned int            flags;
207         unsigned int            options;
208         unsigned int            db_argc;
209         char                    **db_argv;
210         isc_time_t              expiretime;
211         isc_time_t              refreshtime;
212         isc_time_t              dumptime;
213         isc_time_t              loadtime;
214         isc_time_t              notifytime;
215         isc_time_t              resigntime;
216         isc_time_t              keywarntime;
217         isc_time_t              signingtime;
218         isc_time_t              nsec3chaintime;
219         isc_time_t              refreshkeytime;
220         isc_uint32_t            refreshkeycount;
221         isc_uint32_t            refresh;
222         isc_uint32_t            retry;
223         isc_uint32_t            expire;
224         isc_uint32_t            minimum;
225         isc_stdtime_t           key_expiry;
226         isc_stdtime_t           log_key_expired_timer;
227         char                    *keydirectory;
228
229         isc_uint32_t            maxrefresh;
230         isc_uint32_t            minrefresh;
231         isc_uint32_t            maxretry;
232         isc_uint32_t            minretry;
233
234         isc_sockaddr_t          *masters;
235         dns_name_t              **masterkeynames;
236         isc_boolean_t           *mastersok;
237         unsigned int            masterscnt;
238         unsigned int            curmaster;
239         isc_sockaddr_t          masteraddr;
240         dns_notifytype_t        notifytype;
241         isc_sockaddr_t          *notify;
242         unsigned int            notifycnt;
243         isc_sockaddr_t          notifyfrom;
244         isc_task_t              *task;
245         isc_sockaddr_t          notifysrc4;
246         isc_sockaddr_t          notifysrc6;
247         isc_sockaddr_t          xfrsource4;
248         isc_sockaddr_t          xfrsource6;
249         isc_sockaddr_t          altxfrsource4;
250         isc_sockaddr_t          altxfrsource6;
251         isc_sockaddr_t          sourceaddr;
252         dns_xfrin_ctx_t         *xfr;           /* task locked */
253         dns_tsigkey_t           *tsigkey;       /* key used for xfr */
254         /* Access Control Lists */
255         dns_acl_t               *update_acl;
256         dns_acl_t               *forward_acl;
257         dns_acl_t               *notify_acl;
258         dns_acl_t               *query_acl;
259         dns_acl_t               *queryon_acl;
260         dns_acl_t               *xfr_acl;
261         isc_boolean_t           update_disabled;
262         isc_boolean_t           zero_no_soa_ttl;
263         dns_severity_t          check_names;
264         ISC_LIST(dns_notify_t)  notifies;
265         dns_request_t           *request;
266         dns_loadctx_t           *lctx;
267         dns_io_t                *readio;
268         dns_dumpctx_t           *dctx;
269         dns_io_t                *writeio;
270         isc_uint32_t            maxxfrin;
271         isc_uint32_t            maxxfrout;
272         isc_uint32_t            idlein;
273         isc_uint32_t            idleout;
274         isc_event_t             ctlevent;
275         dns_ssutable_t          *ssutable;
276         isc_uint32_t            sigvalidityinterval;
277         isc_uint32_t            sigresigninginterval;
278         dns_view_t              *view;
279         dns_acache_t            *acache;
280         dns_checkmxfunc_t       checkmx;
281         dns_checksrvfunc_t      checksrv;
282         dns_checknsfunc_t       checkns;
283         /*%
284          * Zones in certain states such as "waiting for zone transfer"
285          * or "zone transfer in progress" are kept on per-state linked lists
286          * in the zone manager using the 'statelink' field.  The 'statelist'
287          * field points at the list the zone is currently on.  It the zone
288          * is not on any such list, statelist is NULL.
289          */
290         ISC_LINK(dns_zone_t)    statelink;
291         dns_zonelist_t          *statelist;
292         /*%
293          * Statistics counters about zone management.
294          */
295         isc_stats_t             *stats;
296         /*%
297          * Optional per-zone statistics counters.  Counted outside of this
298          * module.
299          */
300         isc_boolean_t           requeststats_on;
301         isc_stats_t             *requeststats;
302         isc_uint32_t            notifydelay;
303         dns_isselffunc_t        isself;
304         void                    *isselfarg;
305
306         char *                  strnamerd;
307         char *                  strname;
308         char *                  strrdclass;
309         char *                  strviewname;
310
311         /*%
312          * Serial number for deferred journal compaction.
313          */
314         isc_uint32_t            compact_serial;
315         /*%
316          * Keys that are signing the zone for the first time.
317          */
318         dns_signinglist_t       signing;
319         dns_nsec3chainlist_t    nsec3chain;
320         /*%
321          * Signing / re-signing quantum stopping parameters.
322          */
323         isc_uint32_t            signatures;
324         isc_uint32_t            nodes;
325         dns_rdatatype_t         privatetype;
326
327         /*%
328          * Autosigning/key-maintenance options
329          */
330         isc_uint32_t            keyopts;
331
332         /*%
333          * True if added by "rndc addzone"
334          */
335         isc_boolean_t           added;
336
337         /*%
338          * whether this is a response policy zone
339          */
340         isc_boolean_t           is_rpz;
341
342         /*%
343          * Outstanding forwarded UPDATE requests.
344          */
345         dns_forwardlist_t       forwards;
346 };
347
348 typedef struct {
349         dns_diff_t      *diff;
350         isc_boolean_t   offline;
351 } zonediff_t;
352
353 #define zonediff_init(z, d) \
354         do { \
355                 zonediff_t *_z = (z); \
356                 (_z)->diff = (d); \
357                 (_z)->offline = ISC_FALSE; \
358         } while (0)
359
360 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
361 #define DNS_ZONE_SETFLAG(z,f) do { \
362                 INSIST(LOCKED_ZONE(z)); \
363                 (z)->flags |= (f); \
364                 } while (0)
365 #define DNS_ZONE_CLRFLAG(z,f) do { \
366                 INSIST(LOCKED_ZONE(z)); \
367                 (z)->flags &= ~(f); \
368                 } while (0)
369         /* XXX MPA these may need to go back into zone.h */
370 #define DNS_ZONEFLG_REFRESH     0x00000001U     /*%< refresh check in progress */
371 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /*%< zone need consolidation */
372 #define DNS_ZONEFLG_USEVC       0x00000004U     /*%< use tcp for refresh query */
373 #define DNS_ZONEFLG_DUMPING     0x00000008U     /*%< a dump is in progress */
374 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /*%< $INCLUDE in zone file */
375 #define DNS_ZONEFLG_LOADED      0x00000020U     /*%< database has loaded */
376 #define DNS_ZONEFLG_EXITING     0x00000040U     /*%< zone is being destroyed */
377 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /*%< zone has expired */
378 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /*%< refresh check needed */
379 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /*%< zone contents are
380                                                  * uptodate */
381 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /*%< need to send out notify
382                                                  * messages */
383 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /*%< generate a journal diff on
384                                                  * reload */
385 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /*%< an attempt to refresh a
386                                                  * zone with no masters
387                                                  * occurred */
388 #define DNS_ZONEFLG_LOADING     0x00002000U     /*%< load from disk in progress*/
389 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /*%< timer values have been set
390                                                  * from SOA (if not set, we
391                                                  * are still using
392                                                  * default timer values) */
393 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
394 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
395 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
396 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
397 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
398 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /*%< IXFR failed, force AXFR */
399 #define DNS_ZONEFLG_FLUSH       0x00200000U
400 #define DNS_ZONEFLG_NOEDNS      0x00400000U
401 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
402 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
403 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
404 #define DNS_ZONEFLG_REFRESHING  0x04000000U     /*%< Refreshing keydata */
405 #define DNS_ZONEFLG_THAW        0x08000000U
406 /* #define DNS_ZONEFLG_XXXXX    0x10000000U   XXXMPA unused. */
407 #define DNS_ZONEFLG_NODELAY     0x20000000U
408
409 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
410 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
411
412 /* Flags for zone_load() */
413 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
414 #define DNS_ZONELOADFLAG_THAW   0x00000002U     /* Thaw the zone on successful
415                                                    load. */
416
417 #define UNREACH_CHACHE_SIZE     10U
418 #define UNREACH_HOLD_TIME       600     /* 10 minutes */
419
420 #define CHECK(op) \
421         do { result = (op); \
422                 if (result != ISC_R_SUCCESS) goto failure; \
423         } while (0)
424
425 struct dns_unreachable {
426         isc_sockaddr_t  remote;
427         isc_sockaddr_t  local;
428         isc_uint32_t    expire;
429         isc_uint32_t    last;
430         isc_uint32_t    count;
431 };
432
433 struct dns_zonemgr {
434         unsigned int            magic;
435         isc_mem_t *             mctx;
436         int                     refs;           /* Locked by rwlock */
437         isc_taskmgr_t *         taskmgr;
438         isc_timermgr_t *        timermgr;
439         isc_socketmgr_t *       socketmgr;
440         isc_taskpool_t *        zonetasks;
441         isc_task_t *            task;
442         isc_ratelimiter_t *     notifyrl;
443         isc_ratelimiter_t *     refreshrl;
444         isc_rwlock_t            rwlock;
445         isc_mutex_t             iolock;
446         isc_rwlock_t            urlock;
447
448         /* Locked by rwlock. */
449         dns_zonelist_t          zones;
450         dns_zonelist_t          waiting_for_xfrin;
451         dns_zonelist_t          xfrin_in_progress;
452
453         /* Configuration data. */
454         isc_uint32_t            transfersin;
455         isc_uint32_t            transfersperns;
456         unsigned int            serialqueryrate;
457
458         /* Locked by iolock */
459         isc_uint32_t            iolimit;
460         isc_uint32_t            ioactive;
461         dns_iolist_t            high;
462         dns_iolist_t            low;
463
464         /* Locked by urlock. */
465         /* LRU cache */
466         struct dns_unreachable  unreachable[UNREACH_CHACHE_SIZE];
467 };
468
469 /*%
470  * Hold notify state.
471  */
472 struct dns_notify {
473         unsigned int            magic;
474         unsigned int            flags;
475         isc_mem_t               *mctx;
476         dns_zone_t              *zone;
477         dns_adbfind_t           *find;
478         dns_request_t           *request;
479         dns_name_t              ns;
480         isc_sockaddr_t          dst;
481         ISC_LINK(dns_notify_t)  link;
482 };
483
484 #define DNS_NOTIFY_NOSOA        0x0001U
485
486 /*%
487  *      dns_stub holds state while performing a 'stub' transfer.
488  *      'db' is the zone's 'db' or a new one if this is the initial
489  *      transfer.
490  */
491
492 struct dns_stub {
493         unsigned int            magic;
494         isc_mem_t               *mctx;
495         dns_zone_t              *zone;
496         dns_db_t                *db;
497         dns_dbversion_t         *version;
498 };
499
500 /*%
501  *      Hold load state.
502  */
503 struct dns_load {
504         unsigned int            magic;
505         isc_mem_t               *mctx;
506         dns_zone_t              *zone;
507         dns_db_t                *db;
508         isc_time_t              loadtime;
509         dns_rdatacallbacks_t    callbacks;
510 };
511
512 /*%
513  *      Hold forward state.
514  */
515 struct dns_forward {
516         unsigned int            magic;
517         isc_mem_t               *mctx;
518         dns_zone_t              *zone;
519         isc_buffer_t            *msgbuf;
520         dns_request_t           *request;
521         isc_uint32_t            which;
522         isc_sockaddr_t          addr;
523         dns_updatecallback_t    callback;
524         void                    *callback_arg;
525         ISC_LINK(dns_forward_t) link;
526 };
527
528 /*%
529  *      Hold IO request state.
530  */
531 struct dns_io {
532         unsigned int    magic;
533         dns_zonemgr_t   *zmgr;
534         isc_boolean_t   high;
535         isc_task_t      *task;
536         ISC_LINK(dns_io_t) link;
537         isc_event_t     *event;
538 };
539
540 /*%
541  *      Hold state for when we are signing a zone with a new
542  *      DNSKEY as result of an update.
543  */
544 struct dns_signing {
545         unsigned int            magic;
546         dns_db_t                *db;
547         dns_dbiterator_t        *dbiterator;
548         dns_secalg_t            algorithm;
549         isc_uint16_t            keyid;
550         isc_boolean_t           delete;
551         isc_boolean_t           done;
552         ISC_LINK(dns_signing_t) link;
553 };
554
555 struct dns_nsec3chain {
556         unsigned int                    magic;
557         dns_db_t                        *db;
558         dns_dbiterator_t                *dbiterator;
559         dns_rdata_nsec3param_t          nsec3param;
560         unsigned char                   salt[255];
561         isc_boolean_t                   done;
562         isc_boolean_t                   seen_nsec;
563         isc_boolean_t                   delete_nsec;
564         isc_boolean_t                   save_delete_nsec;
565         ISC_LINK(dns_nsec3chain_t)      link;
566 };
567 /*%<
568  * 'dbiterator' contains a iterator for the database.  If we are creating
569  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
570  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
571  * iterated.
572  *
573  * 'nsec3param' contains the parameters of the NSEC3 chain being created
574  * or removed.
575  *
576  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
577  *
578  * 'seen_nsec' will be set to true if, while iterating the zone to create a
579  * NSEC3 chain, a NSEC record is seen.
580  *
581  * 'delete_nsec' will be set to true if, at the completion of the creation
582  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
583  * are in the process of deleting the NSEC chain.
584  *
585  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
586  * so it can be recovered in the event of a error.
587  */
588
589 struct dns_keyfetch {
590         dns_fixedname_t name;
591         dns_rdataset_t keydataset;
592         dns_rdataset_t dnskeyset;
593         dns_rdataset_t dnskeysigset;
594         dns_zone_t *zone;
595         dns_db_t *db;
596         dns_fetch_t *fetch;
597 };
598
599 #define HOUR 3600
600 #define DAY (24*HOUR)
601 #define MONTH (30*DAY)
602
603 #define SEND_BUFFER_SIZE 2048
604
605 static void zone_settimer(dns_zone_t *, isc_time_t *);
606 static void cancel_refresh(dns_zone_t *);
607 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
608                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
609 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
610      ISC_FORMAT_PRINTF(3, 4);
611 static void queue_xfrin(dns_zone_t *zone);
612 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
613                                   dns_diff_t *diff, dns_diffop_t op,
614                                   dns_name_t *name, dns_ttl_t ttl,
615                                   dns_rdata_t *rdata);
616 static void zone_unload(dns_zone_t *zone);
617 static void zone_expire(dns_zone_t *zone);
618 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
619 static void zone_idetach(dns_zone_t **zonep);
620 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
621                                    isc_boolean_t dump);
622 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
623 static inline void zone_detachdb(dns_zone_t *zone);
624 static isc_result_t default_journal(dns_zone_t *zone);
625 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
626 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
627                                   isc_time_t loadtime, isc_result_t result);
628 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
629 static void zone_shutdown(isc_task_t *, isc_event_t *);
630 static void zone_loaddone(void *arg, isc_result_t result);
631 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
632                                    isc_time_t loadtime);
633 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
634 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
635 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
636 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
637
638 #if 0
639 /* ondestroy example */
640 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
641 #endif
642
643 static void refresh_callback(isc_task_t *, isc_event_t *);
644 static void stub_callback(isc_task_t *, isc_event_t *);
645 static void queue_soa_query(dns_zone_t *zone);
646 static void soa_query(isc_task_t *, isc_event_t *);
647 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
648                      dns_stub_t *stub);
649 static int message_count(dns_message_t *msg, dns_section_t section,
650                          dns_rdatatype_t type);
651 static void notify_cancel(dns_zone_t *zone);
652 static void notify_find_address(dns_notify_t *notify);
653 static void notify_send(dns_notify_t *notify);
654 static isc_result_t notify_createmessage(dns_zone_t *zone,
655                                          unsigned int flags,
656                                          dns_message_t **messagep);
657 static void notify_done(isc_task_t *task, isc_event_t *event);
658 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
659 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
660 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
661 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
662                                              dns_zone_t *zone);
663 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
664 static void zonemgr_free(dns_zonemgr_t *zmgr);
665 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
666                                   isc_task_t *task, isc_taskaction_t action,
667                                   void *arg, dns_io_t **iop);
668 static void zonemgr_putio(dns_io_t **iop);
669 static void zonemgr_cancelio(dns_io_t *io);
670
671 static isc_result_t
672 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
673                  unsigned int *soacount, isc_uint32_t *serial,
674                  isc_uint32_t *refresh, isc_uint32_t *retry,
675                  isc_uint32_t *expire, isc_uint32_t *minimum,
676                  unsigned int *errors);
677
678 static void zone_freedbargs(dns_zone_t *zone);
679 static void forward_callback(isc_task_t *task, isc_event_t *event);
680 static void zone_saveunique(dns_zone_t *zone, const char *path,
681                             const char *templat);
682 static void zone_maintenance(dns_zone_t *zone);
683 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
684 static void dump_done(void *arg, isc_result_t result);
685 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
686                                      isc_uint16_t keyid, isc_boolean_t delete);
687 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
688                                 dns_dbnode_t *node, dns_name_t *name,
689                                 dns_diff_t *diff);
690 static void zone_rekey(dns_zone_t *zone);
691
692 #define ENTER zone_debuglog(zone, me, 1, "enter")
693
694 static const unsigned int dbargc_default = 1;
695 static const char *dbargv_default[] = { "rbt" };
696
697 #define DNS_ZONE_JITTER_ADD(a, b, c) \
698         do { \
699                 isc_interval_t _i; \
700                 isc_uint32_t _j; \
701                 _j = isc_random_jitter((b), (b)/4); \
702                 isc_interval_set(&_i, _j, 0); \
703                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
704                         dns_zone_log(zone, ISC_LOG_WARNING, \
705                                      "epoch approaching: upgrade required: " \
706                                      "now + %s failed", #b); \
707                         isc_interval_set(&_i, _j/2, 0); \
708                         (void)isc_time_add((a), &_i, (c)); \
709                 } \
710         } while (0)
711
712 #define DNS_ZONE_TIME_ADD(a, b, c) \
713         do { \
714                 isc_interval_t _i; \
715                 isc_interval_set(&_i, (b), 0); \
716                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
717                         dns_zone_log(zone, ISC_LOG_WARNING, \
718                                      "epoch approaching: upgrade required: " \
719                                      "now + %s failed", #b); \
720                         isc_interval_set(&_i, (b)/2, 0); \
721                         (void)isc_time_add((a), &_i, (c)); \
722                 } \
723         } while (0)
724
725 /*%
726  * Increment resolver-related statistics counters.  Zone must be locked.
727  */
728 static inline void
729 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
730         if (zone->stats != NULL)
731                 isc_stats_increment(zone->stats, counter);
732 }
733
734 /***
735  ***    Public functions.
736  ***/
737
738 isc_result_t
739 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
740         isc_result_t result;
741         dns_zone_t *zone;
742         isc_time_t now;
743
744         REQUIRE(zonep != NULL && *zonep == NULL);
745         REQUIRE(mctx != NULL);
746
747         TIME_NOW(&now);
748         zone = isc_mem_get(mctx, sizeof(*zone));
749         if (zone == NULL)
750                 return (ISC_R_NOMEMORY);
751
752         zone->mctx = NULL;
753         isc_mem_attach(mctx, &zone->mctx);
754
755         result = isc_mutex_init(&zone->lock);
756         if (result != ISC_R_SUCCESS)
757                 goto free_zone;
758
759         result = ZONEDB_INITLOCK(&zone->dblock);
760         if (result != ISC_R_SUCCESS)
761                 goto free_mutex;
762
763         /* XXX MPA check that all elements are initialised */
764 #ifdef DNS_ZONE_CHECKLOCK
765         zone->locked = ISC_FALSE;
766 #endif
767         zone->db = NULL;
768         zone->zmgr = NULL;
769         ISC_LINK_INIT(zone, link);
770         result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
771         if (result != ISC_R_SUCCESS)
772                 goto free_dblock;
773         zone->irefs = 0;
774         dns_name_init(&zone->origin, NULL);
775         zone->strnamerd = NULL;
776         zone->strname = NULL;
777         zone->strrdclass = NULL;
778         zone->strviewname = NULL;
779         zone->masterfile = NULL;
780         zone->masterformat = dns_masterformat_none;
781         zone->keydirectory = NULL;
782         zone->journalsize = -1;
783         zone->journal = NULL;
784         zone->rdclass = dns_rdataclass_none;
785         zone->type = dns_zone_none;
786         zone->flags = 0;
787         zone->options = 0;
788         zone->keyopts = 0;
789         zone->db_argc = 0;
790         zone->db_argv = NULL;
791         isc_time_settoepoch(&zone->expiretime);
792         isc_time_settoepoch(&zone->refreshtime);
793         isc_time_settoepoch(&zone->dumptime);
794         isc_time_settoepoch(&zone->loadtime);
795         zone->notifytime = now;
796         isc_time_settoepoch(&zone->resigntime);
797         isc_time_settoepoch(&zone->keywarntime);
798         isc_time_settoepoch(&zone->signingtime);
799         isc_time_settoepoch(&zone->nsec3chaintime);
800         isc_time_settoepoch(&zone->refreshkeytime);
801         zone->refreshkeycount = 0;
802         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
803         zone->retry = DNS_ZONE_DEFAULTRETRY;
804         zone->expire = 0;
805         zone->minimum = 0;
806         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
807         zone->minrefresh = DNS_ZONE_MINREFRESH;
808         zone->maxretry = DNS_ZONE_MAXRETRY;
809         zone->minretry = DNS_ZONE_MINRETRY;
810         zone->masters = NULL;
811         zone->masterkeynames = NULL;
812         zone->mastersok = NULL;
813         zone->masterscnt = 0;
814         zone->curmaster = 0;
815         zone->notify = NULL;
816         zone->notifytype = dns_notifytype_yes;
817         zone->notifycnt = 0;
818         zone->task = NULL;
819         zone->update_acl = NULL;
820         zone->forward_acl = NULL;
821         zone->notify_acl = NULL;
822         zone->query_acl = NULL;
823         zone->queryon_acl = NULL;
824         zone->xfr_acl = NULL;
825         zone->update_disabled = ISC_FALSE;
826         zone->zero_no_soa_ttl = ISC_TRUE;
827         zone->check_names = dns_severity_ignore;
828         zone->request = NULL;
829         zone->lctx = NULL;
830         zone->readio = NULL;
831         zone->dctx = NULL;
832         zone->writeio = NULL;
833         zone->timer = NULL;
834         zone->idlein = DNS_DEFAULT_IDLEIN;
835         zone->idleout = DNS_DEFAULT_IDLEOUT;
836         zone->log_key_expired_timer = 0;
837         ISC_LIST_INIT(zone->notifies);
838         isc_sockaddr_any(&zone->notifysrc4);
839         isc_sockaddr_any6(&zone->notifysrc6);
840         isc_sockaddr_any(&zone->xfrsource4);
841         isc_sockaddr_any6(&zone->xfrsource6);
842         isc_sockaddr_any(&zone->altxfrsource4);
843         isc_sockaddr_any6(&zone->altxfrsource6);
844         zone->xfr = NULL;
845         zone->tsigkey = NULL;
846         zone->maxxfrin = MAX_XFER_TIME;
847         zone->maxxfrout = MAX_XFER_TIME;
848         zone->ssutable = NULL;
849         zone->sigvalidityinterval = 30 * 24 * 3600;
850         zone->sigresigninginterval = 7 * 24 * 3600;
851         zone->view = NULL;
852         zone->acache = NULL;
853         zone->checkmx = NULL;
854         zone->checksrv = NULL;
855         zone->checkns = NULL;
856         ISC_LINK_INIT(zone, statelink);
857         zone->statelist = NULL;
858         zone->stats = NULL;
859         zone->requeststats_on = ISC_FALSE;
860         zone->requeststats = NULL;
861         zone->notifydelay = 5;
862         zone->isself = NULL;
863         zone->isselfarg = NULL;
864         ISC_LIST_INIT(zone->signing);
865         ISC_LIST_INIT(zone->nsec3chain);
866         zone->signatures = 10;
867         zone->nodes = 100;
868         zone->privatetype = (dns_rdatatype_t)0xffffU;
869         zone->added = ISC_FALSE;
870         zone->is_rpz = ISC_FALSE;
871         ISC_LIST_INIT(zone->forwards);
872
873         zone->magic = ZONE_MAGIC;
874
875         /* Must be after magic is set. */
876         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
877         if (result != ISC_R_SUCCESS)
878                 goto free_erefs;
879
880         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
881                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
882                        NULL, NULL);
883         *zonep = zone;
884         return (ISC_R_SUCCESS);
885
886  free_erefs:
887         isc_refcount_decrement(&zone->erefs, NULL);
888         isc_refcount_destroy(&zone->erefs);
889
890  free_dblock:
891         ZONEDB_DESTROYLOCK(&zone->dblock);
892
893  free_mutex:
894         DESTROYLOCK(&zone->lock);
895
896  free_zone:
897         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
898         return (result);
899 }
900
901 /*
902  * Free a zone.  Because we require that there be no more
903  * outstanding events or references, no locking is necessary.
904  */
905 static void
906 zone_free(dns_zone_t *zone) {
907         isc_mem_t *mctx = NULL;
908         dns_signing_t *signing;
909         dns_nsec3chain_t *nsec3chain;
910
911         REQUIRE(DNS_ZONE_VALID(zone));
912         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
913         REQUIRE(zone->irefs == 0);
914         REQUIRE(!LOCKED_ZONE(zone));
915         REQUIRE(zone->timer == NULL);
916
917         /*
918          * Managed objects.  Order is important.
919          */
920         if (zone->request != NULL)
921                 dns_request_destroy(&zone->request); /* XXXMPA */
922         INSIST(zone->readio == NULL);
923         INSIST(zone->statelist == NULL);
924         INSIST(zone->writeio == NULL);
925
926         if (zone->task != NULL)
927                 isc_task_detach(&zone->task);
928         if (zone->zmgr != NULL)
929                 dns_zonemgr_releasezone(zone->zmgr, zone);
930
931         /* Unmanaged objects */
932         for (signing = ISC_LIST_HEAD(zone->signing);
933              signing != NULL;
934              signing = ISC_LIST_HEAD(zone->signing)) {
935                 ISC_LIST_UNLINK(zone->signing, signing, link);
936                 dns_db_detach(&signing->db);
937                 dns_dbiterator_destroy(&signing->dbiterator);
938                 isc_mem_put(zone->mctx, signing, sizeof *signing);
939         }
940         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
941              nsec3chain != NULL;
942              nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
943                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
944                 dns_db_detach(&nsec3chain->db);
945                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
946                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
947         }
948         if (zone->masterfile != NULL)
949                 isc_mem_free(zone->mctx, zone->masterfile);
950         zone->masterfile = NULL;
951         if (zone->keydirectory != NULL)
952                 isc_mem_free(zone->mctx, zone->keydirectory);
953         zone->keydirectory = NULL;
954         zone->journalsize = -1;
955         if (zone->journal != NULL)
956                 isc_mem_free(zone->mctx, zone->journal);
957         zone->journal = NULL;
958         if (zone->stats != NULL)
959                 isc_stats_detach(&zone->stats);
960         if (zone->requeststats != NULL)
961                 isc_stats_detach(&zone->requeststats);
962         if (zone->db != NULL)
963                 zone_detachdb(zone);
964         if (zone->acache != NULL)
965                 dns_acache_detach(&zone->acache);
966         zone_freedbargs(zone);
967         RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
968                       == ISC_R_SUCCESS);
969         RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
970                       == ISC_R_SUCCESS);
971         zone->check_names = dns_severity_ignore;
972         if (zone->update_acl != NULL)
973                 dns_acl_detach(&zone->update_acl);
974         if (zone->forward_acl != NULL)
975                 dns_acl_detach(&zone->forward_acl);
976         if (zone->notify_acl != NULL)
977                 dns_acl_detach(&zone->notify_acl);
978         if (zone->query_acl != NULL)
979                 dns_acl_detach(&zone->query_acl);
980         if (zone->queryon_acl != NULL)
981                 dns_acl_detach(&zone->queryon_acl);
982         if (zone->xfr_acl != NULL)
983                 dns_acl_detach(&zone->xfr_acl);
984         if (dns_name_dynamic(&zone->origin))
985                 dns_name_free(&zone->origin, zone->mctx);
986         if (zone->strnamerd != NULL)
987                 isc_mem_free(zone->mctx, zone->strnamerd);
988         if (zone->strname != NULL)
989                 isc_mem_free(zone->mctx, zone->strname);
990         if (zone->strrdclass != NULL)
991                 isc_mem_free(zone->mctx, zone->strrdclass);
992         if (zone->strviewname != NULL)
993                 isc_mem_free(zone->mctx, zone->strviewname);
994         if (zone->ssutable != NULL)
995                 dns_ssutable_detach(&zone->ssutable);
996
997         /* last stuff */
998         ZONEDB_DESTROYLOCK(&zone->dblock);
999         DESTROYLOCK(&zone->lock);
1000         isc_refcount_destroy(&zone->erefs);
1001         zone->magic = 0;
1002         mctx = zone->mctx;
1003         isc_mem_put(mctx, zone, sizeof(*zone));
1004         isc_mem_detach(&mctx);
1005 }
1006
1007 /*
1008  *      Single shot.
1009  */
1010 void
1011 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1012         char namebuf[1024];
1013
1014         REQUIRE(DNS_ZONE_VALID(zone));
1015         REQUIRE(rdclass != dns_rdataclass_none);
1016
1017         /*
1018          * Test and set.
1019          */
1020         LOCK_ZONE(zone);
1021         REQUIRE(zone->rdclass == dns_rdataclass_none ||
1022                 zone->rdclass == rdclass);
1023         zone->rdclass = rdclass;
1024
1025         if (zone->strnamerd != NULL)
1026                 isc_mem_free(zone->mctx, zone->strnamerd);
1027         if (zone->strrdclass != NULL)
1028                 isc_mem_free(zone->mctx, zone->strrdclass);
1029
1030         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1031         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1032         zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1033         zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1034
1035         UNLOCK_ZONE(zone);
1036 }
1037
1038 dns_rdataclass_t
1039 dns_zone_getclass(dns_zone_t *zone) {
1040         REQUIRE(DNS_ZONE_VALID(zone));
1041
1042         return (zone->rdclass);
1043 }
1044
1045 void
1046 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1047         REQUIRE(DNS_ZONE_VALID(zone));
1048
1049         LOCK_ZONE(zone);
1050         zone->notifytype = notifytype;
1051         UNLOCK_ZONE(zone);
1052 }
1053
1054 isc_result_t
1055 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1056         isc_result_t result;
1057         unsigned int soacount;
1058
1059         REQUIRE(DNS_ZONE_VALID(zone));
1060         REQUIRE(serialp != NULL);
1061
1062         LOCK_ZONE(zone);
1063         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1064         if (zone->db != NULL) {
1065                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1066                                           serialp, NULL, NULL, NULL, NULL,
1067                                           NULL);
1068                 if (result == ISC_R_SUCCESS && soacount == 0)
1069                         result = ISC_R_FAILURE;
1070         } else
1071                 result = DNS_R_NOTLOADED;
1072         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1073         UNLOCK_ZONE(zone);
1074
1075         return (result);
1076 }
1077
1078 isc_uint32_t
1079 dns_zone_getserial(dns_zone_t *zone) {
1080         isc_result_t result;
1081         isc_uint32_t serial;
1082
1083         result = dns_zone_getserial2(zone, &serial);
1084         if (result != ISC_R_SUCCESS)
1085                 serial = 0; /* XXX: not really correct, but no other choice */
1086
1087         return (serial);
1088 }
1089
1090 /*
1091  *      Single shot.
1092  */
1093 void
1094 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1095
1096         REQUIRE(DNS_ZONE_VALID(zone));
1097         REQUIRE(type != dns_zone_none);
1098
1099         /*
1100          * Test and set.
1101          */
1102         LOCK_ZONE(zone);
1103         REQUIRE(zone->type == dns_zone_none || zone->type == type);
1104         zone->type = type;
1105         UNLOCK_ZONE(zone);
1106 }
1107
1108 static void
1109 zone_freedbargs(dns_zone_t *zone) {
1110         unsigned int i;
1111
1112         /* Free the old database argument list. */
1113         if (zone->db_argv != NULL) {
1114                 for (i = 0; i < zone->db_argc; i++)
1115                         isc_mem_free(zone->mctx, zone->db_argv[i]);
1116                 isc_mem_put(zone->mctx, zone->db_argv,
1117                             zone->db_argc * sizeof(*zone->db_argv));
1118         }
1119         zone->db_argc = 0;
1120         zone->db_argv = NULL;
1121 }
1122
1123 isc_result_t
1124 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1125         size_t size = 0;
1126         unsigned int i;
1127         isc_result_t result = ISC_R_SUCCESS;
1128         void *mem;
1129         char **tmp, *tmp2;
1130
1131         REQUIRE(DNS_ZONE_VALID(zone));
1132         REQUIRE(argv != NULL && *argv == NULL);
1133
1134         LOCK_ZONE(zone);
1135         size = (zone->db_argc + 1) * sizeof(char *);
1136         for (i = 0; i < zone->db_argc; i++)
1137                 size += strlen(zone->db_argv[i]) + 1;
1138         mem = isc_mem_allocate(mctx, size);
1139         if (mem != NULL) {
1140                 tmp = mem;
1141                 tmp2 = mem;
1142                 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1143                 for (i = 0; i < zone->db_argc; i++) {
1144                         *tmp++ = tmp2;
1145                         strcpy(tmp2, zone->db_argv[i]);
1146                         tmp2 += strlen(tmp2) + 1;
1147                 }
1148                 *tmp = NULL;
1149         } else
1150                 result = ISC_R_NOMEMORY;
1151         UNLOCK_ZONE(zone);
1152         *argv = mem;
1153         return (result);
1154 }
1155
1156 isc_result_t
1157 dns_zone_setdbtype(dns_zone_t *zone,
1158                    unsigned int dbargc, const char * const *dbargv) {
1159         isc_result_t result = ISC_R_SUCCESS;
1160         char **new = NULL;
1161         unsigned int i;
1162
1163         REQUIRE(DNS_ZONE_VALID(zone));
1164         REQUIRE(dbargc >= 1);
1165         REQUIRE(dbargv != NULL);
1166
1167         LOCK_ZONE(zone);
1168
1169         /* Set up a new database argument list. */
1170         new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1171         if (new == NULL)
1172                 goto nomem;
1173         for (i = 0; i < dbargc; i++)
1174                 new[i] = NULL;
1175         for (i = 0; i < dbargc; i++) {
1176                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1177                 if (new[i] == NULL)
1178                         goto nomem;
1179         }
1180
1181         /* Free the old list. */
1182         zone_freedbargs(zone);
1183
1184         zone->db_argc = dbargc;
1185         zone->db_argv = new;
1186         result = ISC_R_SUCCESS;
1187         goto unlock;
1188
1189  nomem:
1190         if (new != NULL) {
1191                 for (i = 0; i < dbargc; i++)
1192                         if (new[i] != NULL)
1193                                 isc_mem_free(zone->mctx, new[i]);
1194                 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1195         }
1196         result = ISC_R_NOMEMORY;
1197
1198  unlock:
1199         UNLOCK_ZONE(zone);
1200         return (result);
1201 }
1202
1203 void
1204 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1205         char namebuf[1024];
1206         REQUIRE(DNS_ZONE_VALID(zone));
1207
1208         LOCK_ZONE(zone);
1209         if (zone->view != NULL)
1210                 dns_view_weakdetach(&zone->view);
1211         dns_view_weakattach(view, &zone->view);
1212
1213         if (zone->strviewname != NULL)
1214                 isc_mem_free(zone->mctx, zone->strviewname);
1215         if (zone->strnamerd != NULL)
1216                 isc_mem_free(zone->mctx, zone->strnamerd);
1217
1218         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1219         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1220         zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1221         zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1222
1223         UNLOCK_ZONE(zone);
1224 }
1225
1226
1227 dns_view_t *
1228 dns_zone_getview(dns_zone_t *zone) {
1229         REQUIRE(DNS_ZONE_VALID(zone));
1230
1231         return (zone->view);
1232 }
1233
1234
1235 isc_result_t
1236 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1237         isc_result_t result;
1238         char namebuf[1024];
1239
1240         REQUIRE(DNS_ZONE_VALID(zone));
1241         REQUIRE(origin != NULL);
1242
1243         LOCK_ZONE(zone);
1244         if (dns_name_dynamic(&zone->origin)) {
1245                 dns_name_free(&zone->origin, zone->mctx);
1246                 dns_name_init(&zone->origin, NULL);
1247         }
1248         result = dns_name_dup(origin, zone->mctx, &zone->origin);
1249
1250         if (zone->strnamerd != NULL)
1251                 isc_mem_free(zone->mctx, zone->strnamerd);
1252         if (zone->strname != NULL)
1253                 isc_mem_free(zone->mctx, zone->strname);
1254
1255         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1256         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1257         zone_name_tostr(zone, namebuf, sizeof namebuf);
1258         zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1259
1260         UNLOCK_ZONE(zone);
1261         return (result);
1262 }
1263
1264 void
1265 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1266         REQUIRE(DNS_ZONE_VALID(zone));
1267         REQUIRE(acache != NULL);
1268
1269         LOCK_ZONE(zone);
1270         if (zone->acache != NULL)
1271                 dns_acache_detach(&zone->acache);
1272         dns_acache_attach(acache, &zone->acache);
1273         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1274         if (zone->db != NULL) {
1275                 isc_result_t result;
1276
1277                 /*
1278                  * If the zone reuses an existing DB, the DB needs to be
1279                  * set in the acache explicitly.  We can safely ignore the
1280                  * case where the DB is already set.  If other error happens,
1281                  * the acache will not work effectively.
1282                  */
1283                 result = dns_acache_setdb(acache, zone->db);
1284                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1285                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1286                                          "dns_acache_setdb() failed: %s",
1287                                          isc_result_totext(result));
1288                 }
1289         }
1290         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1291         UNLOCK_ZONE(zone);
1292 }
1293
1294 static isc_result_t
1295 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1296         char *copy;
1297
1298         if (value != NULL) {
1299                 copy = isc_mem_strdup(zone->mctx, value);
1300                 if (copy == NULL)
1301                         return (ISC_R_NOMEMORY);
1302         } else {
1303                 copy = NULL;
1304         }
1305
1306         if (*field != NULL)
1307                 isc_mem_free(zone->mctx, *field);
1308
1309         *field = copy;
1310         return (ISC_R_SUCCESS);
1311 }
1312
1313 isc_result_t
1314 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1315         return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1316 }
1317
1318 isc_result_t
1319 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1320                   dns_masterformat_t format) {
1321         isc_result_t result = ISC_R_SUCCESS;
1322
1323         REQUIRE(DNS_ZONE_VALID(zone));
1324
1325         LOCK_ZONE(zone);
1326         result = dns_zone_setstring(zone, &zone->masterfile, file);
1327         if (result == ISC_R_SUCCESS) {
1328                 zone->masterformat = format;
1329                 result = default_journal(zone);
1330         }
1331         UNLOCK_ZONE(zone);
1332
1333         return (result);
1334 }
1335
1336 const char *
1337 dns_zone_getfile(dns_zone_t *zone) {
1338         REQUIRE(DNS_ZONE_VALID(zone));
1339
1340         return (zone->masterfile);
1341 }
1342
1343 static isc_result_t
1344 default_journal(dns_zone_t *zone) {
1345         isc_result_t result;
1346         char *journal;
1347
1348         REQUIRE(DNS_ZONE_VALID(zone));
1349         REQUIRE(LOCKED_ZONE(zone));
1350
1351         if (zone->masterfile != NULL) {
1352                 /* Calculate string length including '\0'. */
1353                 int len = strlen(zone->masterfile) + sizeof(".jnl");
1354                 journal = isc_mem_allocate(zone->mctx, len);
1355                 if (journal == NULL)
1356                         return (ISC_R_NOMEMORY);
1357                 strcpy(journal, zone->masterfile);
1358                 strcat(journal, ".jnl");
1359         } else {
1360                 journal = NULL;
1361         }
1362         result = dns_zone_setstring(zone, &zone->journal, journal);
1363         if (journal != NULL)
1364                 isc_mem_free(zone->mctx, journal);
1365         return (result);
1366 }
1367
1368 isc_result_t
1369 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1370         isc_result_t result = ISC_R_SUCCESS;
1371
1372         REQUIRE(DNS_ZONE_VALID(zone));
1373
1374         LOCK_ZONE(zone);
1375         result = dns_zone_setstring(zone, &zone->journal, journal);
1376         UNLOCK_ZONE(zone);
1377
1378         return (result);
1379 }
1380
1381 char *
1382 dns_zone_getjournal(dns_zone_t *zone) {
1383         REQUIRE(DNS_ZONE_VALID(zone));
1384
1385         return (zone->journal);
1386 }
1387
1388 /*
1389  * Return true iff the zone is "dynamic", in the sense that the zone's
1390  * master file (if any) is written by the server, rather than being
1391  * updated manually and read by the server.
1392  *
1393  * This is true for slave zones, stub zones, key zones, and zones that
1394  * allow dynamic updates either by having an update policy ("ssutable")
1395  * or an "allow-update" ACL with a value other than exactly "{ none; }".
1396  */
1397 static isc_boolean_t
1398 zone_isdynamic(dns_zone_t *zone) {
1399         REQUIRE(DNS_ZONE_VALID(zone));
1400
1401         return (ISC_TF(zone->type == dns_zone_slave ||
1402                        zone->type == dns_zone_stub ||
1403                        zone->type == dns_zone_key ||
1404                        (!zone->update_disabled && zone->ssutable != NULL) ||
1405                        (!zone->update_disabled && zone->update_acl != NULL &&
1406                         !dns_acl_isnone(zone->update_acl))));
1407 }
1408
1409 /*
1410  * Set the response policy index and information for a zone.
1411  */
1412 isc_result_t
1413 dns_zone_rpz_enable(dns_zone_t *zone) {
1414         /*
1415          * Only RBTDB zones can be used for response policy zones,
1416          * because only they have the code to load the create the summary data.
1417          * Only zones that are loaded instead of mmap()ed create the
1418          * summary data and so can be policy zones.
1419          */
1420         if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1421             strcmp(zone->db_argv[0], "rbt64") != 0)
1422                 return (ISC_R_NOTIMPLEMENTED);
1423
1424         zone->is_rpz = ISC_TRUE;
1425
1426         return (ISC_R_SUCCESS);
1427 }
1428
1429 isc_boolean_t
1430 dns_zone_get_rpz(dns_zone_t *zone) {
1431         return (zone->is_rpz);
1432 }
1433
1434 /*
1435  * If a zone is a response policy zone, mark its new database.
1436  */
1437 isc_result_t
1438 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1439 #ifdef BIND9
1440         if (zone->is_rpz)
1441                 return (dns_db_rpz_enabled(db, NULL));
1442 #endif
1443         return (ISC_R_SUCCESS);
1444 }
1445
1446 static isc_result_t
1447 zone_load(dns_zone_t *zone, unsigned int flags) {
1448         isc_result_t result;
1449         isc_time_t now;
1450         isc_time_t loadtime, filetime;
1451         dns_db_t *db = NULL;
1452         isc_boolean_t rbt;
1453
1454         REQUIRE(DNS_ZONE_VALID(zone));
1455
1456         LOCK_ZONE(zone);
1457         TIME_NOW(&now);
1458
1459         INSIST(zone->type != dns_zone_none);
1460
1461         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1462                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1463                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1464                 result = DNS_R_CONTINUE;
1465                 goto cleanup;
1466         }
1467
1468
1469         INSIST(zone->db_argc >= 1);
1470
1471         rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1472               strcmp(zone->db_argv[0], "rbt64") == 0;
1473
1474         if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1475                 /*
1476                  * The zone has no master file configured.
1477                  */
1478                 result = ISC_R_SUCCESS;
1479                 goto cleanup;
1480         }
1481
1482         if (zone->db != NULL && zone_isdynamic(zone)) {
1483                 /*
1484                  * This is a slave, stub, or dynamically updated
1485                  * zone being reloaded.  Do nothing - the database
1486                  * we already have is guaranteed to be up-to-date.
1487                  */
1488                 if (zone->type == dns_zone_master)
1489                         result = DNS_R_DYNAMIC;
1490                 else
1491                         result = ISC_R_SUCCESS;
1492                 goto cleanup;
1493         }
1494
1495         /*
1496          * Store the current time before the zone is loaded, so that if the
1497          * file changes between the time of the load and the time that
1498          * zone->loadtime is set, then the file will still be reloaded
1499          * the next time dns_zone_load is called.
1500          */
1501         TIME_NOW(&loadtime);
1502
1503         /*
1504          * Don't do the load if the file that stores the zone is older
1505          * than the last time the zone was loaded.  If the zone has not
1506          * been loaded yet, zone->loadtime will be the epoch.
1507          */
1508         if (zone->masterfile != NULL) {
1509                 /*
1510                  * The file is already loaded.  If we are just doing a
1511                  * "rndc reconfig", we are done.
1512                  */
1513                 if (!isc_time_isepoch(&zone->loadtime) &&
1514                     (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1515                         result = ISC_R_SUCCESS;
1516                         goto cleanup;
1517                 }
1518
1519                 result = isc_file_getmodtime(zone->masterfile, &filetime);
1520                 if (result == ISC_R_SUCCESS) {
1521                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1522                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1523                             isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1524                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1525                                              "skipping load: master file "
1526                                              "older than last load");
1527                                 result = DNS_R_UPTODATE;
1528                                 goto cleanup;
1529                         }
1530                         loadtime = filetime;
1531                 }
1532         }
1533
1534         /*
1535          * Built in zones (with the exception of empty zones) don't need
1536          * to be reloaded.
1537          */
1538         if (zone->type == dns_zone_master &&
1539             strcmp(zone->db_argv[0], "_builtin") == 0 &&
1540             (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1541             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1542                 result = ISC_R_SUCCESS;
1543                 goto cleanup;
1544         }
1545
1546         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
1547             rbt) {
1548                 if (zone->masterfile == NULL ||
1549                     !isc_file_exists(zone->masterfile)) {
1550                         if (zone->masterfile != NULL) {
1551                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1552                                              "no master file");
1553                         }
1554                         zone->refreshtime = now;
1555                         if (zone->task != NULL)
1556                                 zone_settimer(zone, &now);
1557                         result = ISC_R_SUCCESS;
1558                         goto cleanup;
1559                 }
1560         }
1561
1562         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1563
1564         result = dns_db_create(zone->mctx, zone->db_argv[0],
1565                                &zone->origin, (zone->type == dns_zone_stub) ?
1566                                dns_dbtype_stub : dns_dbtype_zone,
1567                                zone->rdclass,
1568                                zone->db_argc - 1, zone->db_argv + 1,
1569                                &db);
1570
1571         if (result != ISC_R_SUCCESS) {
1572                 dns_zone_log(zone, ISC_LOG_ERROR,
1573                              "loading zone: creating database: %s",
1574                              isc_result_totext(result));
1575                 goto cleanup;
1576         }
1577         dns_db_settask(db, zone->task);
1578
1579         if (! dns_db_ispersistent(db)) {
1580                 if (zone->masterfile != NULL) {
1581                         result = zone_startload(db, zone, loadtime);
1582                 } else {
1583                         result = DNS_R_NOMASTERFILE;
1584                         if (zone->type == dns_zone_master) {
1585                                 dns_zone_log(zone, ISC_LOG_ERROR,
1586                                              "loading zone: "
1587                                              "no master file configured");
1588                                 goto cleanup;
1589                         }
1590                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1591                                      "no master file configured: continuing");
1592                 }
1593         }
1594
1595         if (result == DNS_R_CONTINUE) {
1596                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1597                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1598                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1599                 goto cleanup;
1600         }
1601
1602         result = zone_postload(zone, db, loadtime, result);
1603
1604  cleanup:
1605         UNLOCK_ZONE(zone);
1606         if (db != NULL)
1607                 dns_db_detach(&db);
1608         return (result);
1609 }
1610
1611 isc_result_t
1612 dns_zone_load(dns_zone_t *zone) {
1613         return (zone_load(zone, 0));
1614 }
1615
1616 isc_result_t
1617 dns_zone_loadnew(dns_zone_t *zone) {
1618         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1619 }
1620
1621 isc_result_t
1622 dns_zone_loadandthaw(dns_zone_t *zone) {
1623         isc_result_t result;
1624
1625         result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1626         switch (result) {
1627         case DNS_R_CONTINUE:
1628                 /* Deferred thaw. */
1629                 break;
1630         case ISC_R_SUCCESS:
1631         case DNS_R_UPTODATE:
1632         case DNS_R_SEENINCLUDE:
1633                 zone->update_disabled = ISC_FALSE;
1634                 break;
1635         case DNS_R_NOMASTERFILE:
1636                 zone->update_disabled = ISC_FALSE;
1637                 break;
1638         default:
1639                 /* Error, remain in disabled state. */
1640                 break;
1641         }
1642         return (result);
1643 }
1644
1645 static unsigned int
1646 get_master_options(dns_zone_t *zone) {
1647         unsigned int options;
1648
1649         options = DNS_MASTER_ZONE;
1650         if (zone->type == dns_zone_slave)
1651                 options |= DNS_MASTER_SLAVE;
1652         if (zone->type == dns_zone_key)
1653                 options |= DNS_MASTER_KEY;
1654         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1655                 options |= DNS_MASTER_CHECKNS;
1656         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1657                 options |= DNS_MASTER_FATALNS;
1658         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1659                 options |= DNS_MASTER_CHECKNAMES;
1660         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1661                 options |= DNS_MASTER_CHECKNAMESFAIL;
1662         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1663                 options |= DNS_MASTER_CHECKMX;
1664         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1665                 options |= DNS_MASTER_CHECKMXFAIL;
1666         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1667                 options |= DNS_MASTER_CHECKWILDCARD;
1668         if (zone->type == dns_zone_master &&
1669             ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1670               zone->ssutable != NULL))
1671                 options |= DNS_MASTER_RESIGN;
1672         return (options);
1673 }
1674
1675 static void
1676 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1677         dns_load_t *load = event->ev_arg;
1678         isc_result_t result = ISC_R_SUCCESS;
1679         unsigned int options;
1680
1681         REQUIRE(DNS_LOAD_VALID(load));
1682
1683         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1684                 result = ISC_R_CANCELED;
1685         isc_event_free(&event);
1686         if (result == ISC_R_CANCELED)
1687                 goto fail;
1688
1689         options = get_master_options(load->zone);
1690
1691         result = dns_master_loadfileinc3(load->zone->masterfile,
1692                                          dns_db_origin(load->db),
1693                                          dns_db_origin(load->db),
1694                                          load->zone->rdclass, options, 0,
1695                                          &load->callbacks, task,
1696                                          zone_loaddone, load,
1697                                          &load->zone->lctx, load->zone->mctx,
1698                                          load->zone->masterformat);
1699         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1700             result != DNS_R_SEENINCLUDE)
1701                 goto fail;
1702         return;
1703
1704  fail:
1705         zone_loaddone(load, result);
1706 }
1707
1708 static void
1709 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1710         const char me[] = "zone_gotwritehandle";
1711         dns_zone_t *zone = event->ev_arg;
1712         isc_result_t result = ISC_R_SUCCESS;
1713         dns_dbversion_t *version = NULL;
1714
1715         REQUIRE(DNS_ZONE_VALID(zone));
1716         INSIST(task == zone->task);
1717         ENTER;
1718
1719         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1720                 result = ISC_R_CANCELED;
1721         isc_event_free(&event);
1722         if (result == ISC_R_CANCELED)
1723                 goto fail;
1724
1725         LOCK_ZONE(zone);
1726         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1727         if (zone->db != NULL) {
1728                 const dns_master_style_t *output_style;
1729
1730                 dns_db_currentversion(zone->db, &version);
1731                 if (zone->type == dns_zone_key)
1732                         output_style = &dns_master_style_keyzone;
1733                 else
1734                         output_style = &dns_master_style_default;
1735                 result = dns_master_dumpinc2(zone->mctx, zone->db, version,
1736                                              output_style, zone->masterfile,
1737                                              zone->task, dump_done, zone,
1738                                              &zone->dctx, zone->masterformat);
1739                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
1740         } else
1741                 result = ISC_R_CANCELED;
1742         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1743         UNLOCK_ZONE(zone);
1744         if (result != DNS_R_CONTINUE)
1745                 goto fail;
1746         return;
1747
1748  fail:
1749         dump_done(zone, result);
1750 }
1751
1752 static isc_result_t
1753 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1754         dns_load_t *load;
1755         isc_result_t result;
1756         isc_result_t tresult;
1757         unsigned int options;
1758
1759         result = dns_zone_rpz_enable_db(zone, db);
1760         if (result != ISC_R_SUCCESS)
1761                 return (result);
1762         options = get_master_options(zone);
1763         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1764                 options |= DNS_MASTER_MANYERRORS;
1765
1766         if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1767                 load = isc_mem_get(zone->mctx, sizeof(*load));
1768                 if (load == NULL)
1769                         return (ISC_R_NOMEMORY);
1770
1771                 load->mctx = NULL;
1772                 load->zone = NULL;
1773                 load->db = NULL;
1774                 load->loadtime = loadtime;
1775                 load->magic = LOAD_MAGIC;
1776
1777                 isc_mem_attach(zone->mctx, &load->mctx);
1778                 zone_iattach(zone, &load->zone);
1779                 dns_db_attach(db, &load->db);
1780                 dns_rdatacallbacks_init(&load->callbacks);
1781                 result = dns_db_beginload(db, &load->callbacks.add,
1782                                           &load->callbacks.add_private);
1783                 if (result != ISC_R_SUCCESS)
1784                         goto cleanup;
1785                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1786                                        zone_gotreadhandle, load,
1787                                        &zone->readio);
1788                 if (result != ISC_R_SUCCESS) {
1789                         /*
1790                          * We can't report multiple errors so ignore
1791                          * the result of dns_db_endload().
1792                          */
1793                         (void)dns_db_endload(load->db,
1794                                              &load->callbacks.add_private);
1795                         goto cleanup;
1796                 } else
1797                         result = DNS_R_CONTINUE;
1798         } else {
1799                 dns_rdatacallbacks_t callbacks;
1800
1801                 dns_rdatacallbacks_init(&callbacks);
1802                 result = dns_db_beginload(db, &callbacks.add,
1803                                           &callbacks.add_private);
1804                 if (result != ISC_R_SUCCESS)
1805                         return (result);
1806                 result = dns_master_loadfile3(zone->masterfile, &zone->origin,
1807                                               &zone->origin, zone->rdclass,
1808                                               options, 0, &callbacks,
1809                                               zone->mctx, zone->masterformat);
1810                 tresult = dns_db_endload(db, &callbacks.add_private);
1811                 if (result == ISC_R_SUCCESS)
1812                         result = tresult;
1813         }
1814
1815         return (result);
1816
1817  cleanup:
1818         load->magic = 0;
1819         dns_db_detach(&load->db);
1820         zone_idetach(&load->zone);
1821         isc_mem_detach(&load->mctx);
1822         isc_mem_put(zone->mctx, load, sizeof(*load));
1823         return (result);
1824 }
1825
1826 static isc_boolean_t
1827 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1828               dns_name_t *owner)
1829 {
1830         isc_result_t result;
1831         char ownerbuf[DNS_NAME_FORMATSIZE];
1832         char namebuf[DNS_NAME_FORMATSIZE];
1833         char altbuf[DNS_NAME_FORMATSIZE];
1834         dns_fixedname_t fixed;
1835         dns_name_t *foundname;
1836         int level;
1837
1838         /*
1839          * "." means the services does not exist.
1840          */
1841         if (dns_name_equal(name, dns_rootname))
1842                 return (ISC_TRUE);
1843
1844         /*
1845          * Outside of zone.
1846          */
1847         if (!dns_name_issubdomain(name, &zone->origin)) {
1848                 if (zone->checkmx != NULL)
1849                         return ((zone->checkmx)(zone, name, owner));
1850                 return (ISC_TRUE);
1851         }
1852
1853         if (zone->type == dns_zone_master)
1854                 level = ISC_LOG_ERROR;
1855         else
1856                 level = ISC_LOG_WARNING;
1857
1858         dns_fixedname_init(&fixed);
1859         foundname = dns_fixedname_name(&fixed);
1860
1861         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1862                              0, 0, NULL, foundname, NULL, NULL);
1863         if (result == ISC_R_SUCCESS)
1864                 return (ISC_TRUE);
1865
1866         if (result == DNS_R_NXRRSET) {
1867                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1868                                      0, 0, NULL, foundname, NULL, NULL);
1869                 if (result == ISC_R_SUCCESS)
1870                         return (ISC_TRUE);
1871         }
1872
1873         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1874         dns_name_format(name, namebuf, sizeof namebuf);
1875         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1876             result == DNS_R_EMPTYNAME) {
1877                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1878                         level = ISC_LOG_WARNING;
1879                 dns_zone_log(zone, level,
1880                              "%s/MX '%s' has no address records (A or AAAA)",
1881                              ownerbuf, namebuf);
1882                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1883         }
1884
1885         if (result == DNS_R_CNAME) {
1886                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1887                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1888                         level = ISC_LOG_WARNING;
1889                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1890                         dns_zone_log(zone, level,
1891                                      "%s/MX '%s' is a CNAME (illegal)",
1892                                      ownerbuf, namebuf);
1893                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1894         }
1895
1896         if (result == DNS_R_DNAME) {
1897                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1898                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1899                         level = ISC_LOG_WARNING;
1900                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
1901                         dns_name_format(foundname, altbuf, sizeof altbuf);
1902                         dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
1903                                      " '%s' (illegal)", ownerbuf, namebuf,
1904                                      altbuf);
1905                 }
1906                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1907         }
1908
1909         if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
1910                 return ((zone->checkmx)(zone, name, owner));
1911
1912         return (ISC_TRUE);
1913 }
1914
1915 static isc_boolean_t
1916 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1917                dns_name_t *owner)
1918 {
1919         isc_result_t result;
1920         char ownerbuf[DNS_NAME_FORMATSIZE];
1921         char namebuf[DNS_NAME_FORMATSIZE];
1922         char altbuf[DNS_NAME_FORMATSIZE];
1923         dns_fixedname_t fixed;
1924         dns_name_t *foundname;
1925         int level;
1926
1927         /*
1928          * "." means the services does not exist.
1929          */
1930         if (dns_name_equal(name, dns_rootname))
1931                 return (ISC_TRUE);
1932
1933         /*
1934          * Outside of zone.
1935          */
1936         if (!dns_name_issubdomain(name, &zone->origin)) {
1937                 if (zone->checksrv != NULL)
1938                         return ((zone->checksrv)(zone, name, owner));
1939                 return (ISC_TRUE);
1940         }
1941
1942         if (zone->type == dns_zone_master)
1943                 level = ISC_LOG_ERROR;
1944         else
1945                 level = ISC_LOG_WARNING;
1946
1947         dns_fixedname_init(&fixed);
1948         foundname = dns_fixedname_name(&fixed);
1949
1950         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1951                              0, 0, NULL, foundname, NULL, NULL);
1952         if (result == ISC_R_SUCCESS)
1953                 return (ISC_TRUE);
1954
1955         if (result == DNS_R_NXRRSET) {
1956                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1957                                      0, 0, NULL, foundname, NULL, NULL);
1958                 if (result == ISC_R_SUCCESS)
1959                         return (ISC_TRUE);
1960         }
1961
1962         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1963         dns_name_format(name, namebuf, sizeof namebuf);
1964         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1965             result == DNS_R_EMPTYNAME) {
1966                 dns_zone_log(zone, level,
1967                              "%s/SRV '%s' has no address records (A or AAAA)",
1968                              ownerbuf, namebuf);
1969                 /* XXX950 make fatal for 9.5.0. */
1970                 return (ISC_TRUE);
1971         }
1972
1973         if (result == DNS_R_CNAME) {
1974                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1975                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1976                         level = ISC_LOG_WARNING;
1977                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1978                         dns_zone_log(zone, level,
1979                                      "%s/SRV '%s' is a CNAME (illegal)",
1980                                      ownerbuf, namebuf);
1981                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1982         }
1983
1984         if (result == DNS_R_DNAME) {
1985                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1986                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1987                         level = ISC_LOG_WARNING;
1988                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
1989                         dns_name_format(foundname, altbuf, sizeof altbuf);
1990                         dns_zone_log(zone, level, "%s/SRV '%s' is below a "
1991                                      "DNAME '%s' (illegal)", ownerbuf, namebuf,
1992                                      altbuf);
1993                 }
1994                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1995         }
1996
1997         if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
1998                 return ((zone->checksrv)(zone, name, owner));
1999
2000         return (ISC_TRUE);
2001 }
2002
2003 static isc_boolean_t
2004 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2005                 dns_name_t *owner)
2006 {
2007         isc_boolean_t answer = ISC_TRUE;
2008         isc_result_t result, tresult;
2009         char ownerbuf[DNS_NAME_FORMATSIZE];
2010         char namebuf[DNS_NAME_FORMATSIZE];
2011         char altbuf[DNS_NAME_FORMATSIZE];
2012         dns_fixedname_t fixed;
2013         dns_name_t *foundname;
2014         dns_rdataset_t a;
2015         dns_rdataset_t aaaa;
2016         int level;
2017
2018         /*
2019          * Outside of zone.
2020          */
2021         if (!dns_name_issubdomain(name, &zone->origin)) {
2022                 if (zone->checkns != NULL)
2023                         return ((zone->checkns)(zone, name, owner, NULL, NULL));
2024                 return (ISC_TRUE);
2025         }
2026
2027         if (zone->type == dns_zone_master)
2028                 level = ISC_LOG_ERROR;
2029         else
2030                 level = ISC_LOG_WARNING;
2031
2032         dns_fixedname_init(&fixed);
2033         foundname = dns_fixedname_name(&fixed);
2034         dns_rdataset_init(&a);
2035         dns_rdataset_init(&aaaa);
2036
2037         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2038                              DNS_DBFIND_GLUEOK, 0, NULL,
2039                              foundname, &a, NULL);
2040
2041         if (result == ISC_R_SUCCESS) {
2042                 dns_rdataset_disassociate(&a);
2043                 return (ISC_TRUE);
2044         } else if (result == DNS_R_DELEGATION)
2045                 dns_rdataset_disassociate(&a);
2046
2047         if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2048             result == DNS_R_GLUE) {
2049                 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2050                                      DNS_DBFIND_GLUEOK, 0, NULL,
2051                                      foundname, &aaaa, NULL);
2052                 if (tresult == ISC_R_SUCCESS) {
2053                         dns_rdataset_disassociate(&aaaa);
2054                         return (ISC_TRUE);
2055                 }
2056                 if (tresult == DNS_R_DELEGATION)
2057                         dns_rdataset_disassociate(&aaaa);
2058                 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2059                         /*
2060                          * Check glue against child zone.
2061                          */
2062                         if (zone->checkns != NULL)
2063                                 answer = (zone->checkns)(zone, name, owner,
2064                                                          &a, &aaaa);
2065                         if (dns_rdataset_isassociated(&a))
2066                                 dns_rdataset_disassociate(&a);
2067                         if (dns_rdataset_isassociated(&aaaa))
2068                                 dns_rdataset_disassociate(&aaaa);
2069                         return (answer);
2070                 }
2071         }
2072
2073         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2074         dns_name_format(name, namebuf, sizeof namebuf);
2075         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2076             result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2077                 const char *what;
2078                 isc_boolean_t required = ISC_FALSE;
2079                 if (dns_name_issubdomain(name, owner)) {
2080                         what = "REQUIRED GLUE ";
2081                         required = ISC_TRUE;
2082                  } else if (result == DNS_R_DELEGATION)
2083                         what = "SIBLING GLUE ";
2084                 else
2085                         what = "";
2086
2087                 if (result != DNS_R_DELEGATION || required ||
2088                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2089                         dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2090                                      "address records (A or AAAA)",
2091                                      ownerbuf, namebuf, what);
2092                         /*
2093                          * Log missing address record.
2094                          */
2095                         if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2096                                 (void)(zone->checkns)(zone, name, owner,
2097                                                       &a, &aaaa);
2098                         /* XXX950 make fatal for 9.5.0. */
2099                         /* answer = ISC_FALSE; */
2100                 }
2101         } else if (result == DNS_R_CNAME) {
2102                 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2103                              ownerbuf, namebuf);
2104                 /* XXX950 make fatal for 9.5.0. */
2105                 /* answer = ISC_FALSE; */
2106         } else if (result == DNS_R_DNAME) {
2107                 dns_name_format(foundname, altbuf, sizeof altbuf);
2108                 dns_zone_log(zone, level,
2109                              "%s/NS '%s' is below a DNAME '%s' (illegal)",
2110                              ownerbuf, namebuf, altbuf);
2111                 /* XXX950 make fatal for 9.5.0. */
2112                 /* answer = ISC_FALSE; */
2113         }
2114
2115         if (dns_rdataset_isassociated(&a))
2116                 dns_rdataset_disassociate(&a);
2117         if (dns_rdataset_isassociated(&aaaa))
2118                 dns_rdataset_disassociate(&aaaa);
2119         return (answer);
2120 }
2121
2122 static isc_boolean_t
2123 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2124                      dns_rdataset_t *rdataset)
2125 {
2126         dns_rdataset_t tmprdataset;
2127         isc_result_t result;
2128         isc_boolean_t answer = ISC_TRUE;
2129         isc_boolean_t format = ISC_TRUE;
2130         int level = ISC_LOG_WARNING;
2131         char ownerbuf[DNS_NAME_FORMATSIZE];
2132         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2133         unsigned int count1 = 0;
2134
2135         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2136                 level = ISC_LOG_ERROR;
2137
2138         dns_rdataset_init(&tmprdataset);
2139         for (result = dns_rdataset_first(rdataset);
2140              result == ISC_R_SUCCESS;
2141              result = dns_rdataset_next(rdataset)) {
2142                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2143                 unsigned int count2 = 0;
2144
2145                 count1++;
2146                 dns_rdataset_current(rdataset, &rdata1);
2147                 dns_rdataset_clone(rdataset, &tmprdataset);
2148                 for (result = dns_rdataset_first(&tmprdataset);
2149                      result == ISC_R_SUCCESS;
2150                      result = dns_rdataset_next(&tmprdataset)) {
2151                         dns_rdata_t rdata2 = DNS_RDATA_INIT;
2152                         count2++;
2153                         if (count1 >= count2)
2154                                 continue;
2155                         dns_rdataset_current(&tmprdataset, &rdata2);
2156                         if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2157                                 if (format) {
2158                                         dns_name_format(owner, ownerbuf,
2159                                                         sizeof ownerbuf);
2160                                         dns_rdatatype_format(rdata1.type,
2161                                                              typebuf,
2162                                                              sizeof(typebuf));
2163                                         format = ISC_FALSE;
2164                                 }
2165                                 dns_zone_log(zone, level, "%s/%s has "
2166                                              "semantically identical records",
2167                                              ownerbuf, typebuf);
2168                                 if (level == ISC_LOG_ERROR)
2169                                         answer = ISC_FALSE;
2170                                 break;
2171                         }
2172                 }
2173                 dns_rdataset_disassociate(&tmprdataset);
2174                 if (!format)
2175                         break;
2176         }
2177         return (answer);
2178 }
2179
2180 static isc_boolean_t
2181 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2182         dns_dbiterator_t *dbiterator = NULL;
2183         dns_dbnode_t *node = NULL;
2184         dns_fixedname_t fixed;
2185         dns_name_t *name;
2186         dns_rdataset_t rdataset;
2187         dns_rdatasetiter_t *rdsit = NULL;
2188         isc_boolean_t ok = ISC_TRUE;
2189         isc_result_t result;
2190
2191         dns_fixedname_init(&fixed);
2192         name = dns_fixedname_name(&fixed);
2193         dns_rdataset_init(&rdataset);
2194
2195         result = dns_db_createiterator(db, 0, &dbiterator);
2196         if (result != ISC_R_SUCCESS)
2197                 return (ISC_TRUE);
2198
2199         for (result = dns_dbiterator_first(dbiterator);
2200              result == ISC_R_SUCCESS;
2201              result = dns_dbiterator_next(dbiterator)) {
2202                 result = dns_dbiterator_current(dbiterator, &node, name);
2203                 if (result != ISC_R_SUCCESS)
2204                         continue;
2205
2206                 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2207                 if (result != ISC_R_SUCCESS)
2208                         continue;
2209
2210                 for (result = dns_rdatasetiter_first(rdsit);
2211                      result == ISC_R_SUCCESS;
2212                      result = dns_rdatasetiter_next(rdsit)) {
2213                         dns_rdatasetiter_current(rdsit, &rdataset);
2214                         if (!zone_rrset_check_dup(zone, name, &rdataset))
2215                                 ok = ISC_FALSE;
2216                         dns_rdataset_disassociate(&rdataset);
2217                 }
2218                 dns_rdatasetiter_destroy(&rdsit);
2219                 dns_db_detachnode(db, &node);
2220         }
2221
2222         if (node != NULL)
2223                 dns_db_detachnode(db, &node);
2224         dns_dbiterator_destroy(&dbiterator);
2225
2226         return (ok);
2227 }
2228
2229 static isc_boolean_t
2230 isspf(const dns_rdata_t *rdata) {
2231         char buf[1024];
2232         const unsigned char *data = rdata->data;
2233         unsigned int rdl = rdata->length, i = 0, tl, len;
2234
2235         while (rdl > 0U) {
2236                 len = tl = *data;
2237                 ++data;
2238                 --rdl;
2239                 INSIST(tl <= rdl);
2240                 if (len > sizeof(buf) - i - 1)
2241                         len = sizeof(buf) - i - 1;
2242                 memmove(buf + i, data, len);
2243                 i += len;
2244                 data += tl;
2245                 rdl -= tl;
2246         }
2247
2248         if (i < 6U)
2249                 return(ISC_FALSE);
2250
2251         buf[i] = 0;
2252         if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
2253                 return (ISC_TRUE);
2254         return (ISC_FALSE);
2255 }
2256
2257 static isc_boolean_t
2258 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2259         dns_dbiterator_t *dbiterator = NULL;
2260         dns_dbnode_t *node = NULL;
2261         dns_rdataset_t rdataset;
2262         dns_fixedname_t fixed;
2263         dns_fixedname_t fixedbottom;
2264         dns_rdata_mx_t mx;
2265         dns_rdata_ns_t ns;
2266         dns_rdata_in_srv_t srv;
2267         dns_rdata_t rdata;
2268         dns_name_t *name;
2269         dns_name_t *bottom;
2270         isc_result_t result;
2271         isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
2272
2273         dns_fixedname_init(&fixed);
2274         name = dns_fixedname_name(&fixed);
2275         dns_fixedname_init(&fixedbottom);
2276         bottom = dns_fixedname_name(&fixedbottom);
2277         dns_rdataset_init(&rdataset);
2278         dns_rdata_init(&rdata);
2279
2280         result = dns_db_createiterator(db, 0, &dbiterator);
2281         if (result != ISC_R_SUCCESS)
2282                 return (ISC_TRUE);
2283
2284         result = dns_dbiterator_first(dbiterator);
2285         while (result == ISC_R_SUCCESS) {
2286                 result = dns_dbiterator_current(dbiterator, &node, name);
2287                 if (result != ISC_R_SUCCESS)
2288                         goto cleanup;
2289
2290                 /*
2291                  * Is this name visible in the zone?
2292                  */
2293                 if (!dns_name_issubdomain(name, &zone->origin) ||
2294                     (dns_name_countlabels(bottom) > 0 &&
2295                      dns_name_issubdomain(name, bottom)))
2296                         goto next;
2297
2298                 /*
2299                  * Don't check the NS records at the origin.
2300                  */
2301                 if (dns_name_equal(name, &zone->origin))
2302                         goto checkmx;
2303
2304                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2305                                              0, 0, &rdataset, NULL);
2306                 if (result != ISC_R_SUCCESS)
2307                         goto checkmx;
2308                 /*
2309                  * Remember bottom of zone.
2310                  */
2311                 dns_name_copy(name, bottom, NULL);
2312
2313                 result = dns_rdataset_first(&rdataset);
2314                 while (result == ISC_R_SUCCESS) {
2315                         dns_rdataset_current(&rdataset, &rdata);
2316                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
2317                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2318                         if (!zone_check_glue(zone, db, &ns.name, name))
2319                                 ok = ISC_FALSE;
2320                         dns_rdata_reset(&rdata);
2321                         result = dns_rdataset_next(&rdataset);
2322                 }
2323                 dns_rdataset_disassociate(&rdataset);
2324                 goto next;
2325
2326  checkmx:
2327                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2328                                              0, 0, &rdataset, NULL);
2329                 if (result != ISC_R_SUCCESS)
2330                         goto checksrv;
2331                 result = dns_rdataset_first(&rdataset);
2332                 while (result == ISC_R_SUCCESS) {
2333                         dns_rdataset_current(&rdataset, &rdata);
2334                         result = dns_rdata_tostruct(&rdata, &mx, NULL);
2335                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2336                         if (!zone_check_mx(zone, db, &mx.mx, name))
2337                                 ok = ISC_FALSE;
2338                         dns_rdata_reset(&rdata);
2339                         result = dns_rdataset_next(&rdataset);
2340                 }
2341                 dns_rdataset_disassociate(&rdataset);
2342
2343  checksrv:
2344                 if (zone->rdclass != dns_rdataclass_in)
2345                         goto next;
2346                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2347                                              0, 0, &rdataset, NULL);
2348                 if (result != ISC_R_SUCCESS)
2349                         goto checkspf;
2350                 result = dns_rdataset_first(&rdataset);
2351                 while (result == ISC_R_SUCCESS) {
2352                         dns_rdataset_current(&rdataset, &rdata);
2353                         result = dns_rdata_tostruct(&rdata, &srv, NULL);
2354                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2355                         if (!zone_check_srv(zone, db, &srv.target, name))
2356                                 ok = ISC_FALSE;
2357                         dns_rdata_reset(&rdata);
2358                         result = dns_rdataset_next(&rdataset);
2359                 }
2360                 dns_rdataset_disassociate(&rdataset);
2361
2362  checkspf:
2363                 /*
2364                  * Check if there is a type TXT spf record without a type SPF
2365                  * RRset being present.
2366                  */
2367                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
2368                         goto next;
2369                 if (zone->rdclass != dns_rdataclass_in)
2370                         goto next;
2371                 have_spf = have_txt = ISC_FALSE;
2372                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
2373                                              0, 0, &rdataset, NULL);
2374                 if (result == ISC_R_SUCCESS) {
2375                         dns_rdataset_disassociate(&rdataset);
2376                         have_spf = ISC_TRUE;
2377                 }
2378                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
2379                                              0, 0, &rdataset, NULL);
2380                 if (result != ISC_R_SUCCESS)
2381                         goto notxt;
2382                 result = dns_rdataset_first(&rdataset);
2383                 while (result == ISC_R_SUCCESS) {
2384                         dns_rdataset_current(&rdataset, &rdata);
2385                         have_txt = isspf(&rdata);
2386                         dns_rdata_reset(&rdata);
2387                         if (have_txt)
2388                                 break;
2389                         result = dns_rdataset_next(&rdataset);
2390                 }
2391                 dns_rdataset_disassociate(&rdataset);
2392
2393  notxt:
2394                 if (have_spf != have_txt) {
2395                         char namebuf[DNS_NAME_FORMATSIZE];
2396                         const char *found = have_txt ? "TXT" : "SPF";
2397                         const char *need = have_txt ? "SPF" : "TXT";
2398
2399                         dns_name_format(name, namebuf, sizeof(namebuf));
2400                         dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found SPF/%s "
2401                                      "record but no SPF/%s record found, add "
2402                                      "matching type %s record", namebuf, found,
2403                                      need, need);
2404                 }
2405
2406  next:
2407                 dns_db_detachnode(db, &node);
2408                 result = dns_dbiterator_next(dbiterator);
2409         }
2410
2411  cleanup:
2412         if (node != NULL)
2413                 dns_db_detachnode(db, &node);
2414         dns_dbiterator_destroy(&dbiterator);
2415
2416         return (ok);
2417 }
2418
2419 /*
2420  * OpenSSL verification of RSA keys with exponent 3 is known to be
2421  * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
2422  * if they are in use.
2423  */
2424 static void
2425 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2426         dns_dbnode_t *node = NULL;
2427         dns_dbversion_t *version = NULL;
2428         dns_rdata_dnskey_t dnskey;
2429         dns_rdata_t rdata = DNS_RDATA_INIT;
2430         dns_rdataset_t rdataset;
2431         isc_result_t result;
2432         isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2433         const char *algorithm;
2434
2435         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2436         if (result != ISC_R_SUCCESS)
2437                 goto cleanup;
2438
2439         dns_db_currentversion(db, &version);
2440         dns_rdataset_init(&rdataset);
2441         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2442                                      dns_rdatatype_none, 0, &rdataset, NULL);
2443         if (result != ISC_R_SUCCESS)
2444                 goto cleanup;
2445
2446         for (result = dns_rdataset_first(&rdataset);
2447              result == ISC_R_SUCCESS;
2448              result = dns_rdataset_next(&rdataset))
2449         {
2450                 dns_rdataset_current(&rdataset, &rdata);
2451                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2452                 INSIST(result == ISC_R_SUCCESS);
2453
2454                 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2455                      dnskey.algorithm == DST_ALG_RSAMD5) &&
2456                      dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2457                      dnskey.data[1] == 3)
2458                 {
2459                         if (dnskey.algorithm == DST_ALG_RSASHA1) {
2460                                 logit = !foundrsa;
2461                                 foundrsa = ISC_TRUE;
2462                                 algorithm = "RSASHA1";
2463                         } else {
2464                                 logit = !foundmd5;
2465                                 foundmd5 = ISC_TRUE;
2466                                 algorithm = "RSAMD5";
2467                         }
2468                         if (logit)
2469                                 dns_zone_log(zone, ISC_LOG_WARNING,
2470                                              "weak %s (%u) key found "
2471                                              "(exponent=3)", algorithm,
2472                                              dnskey.algorithm);
2473                         if (foundrsa && foundmd5)
2474                                 break;
2475                 }
2476                 dns_rdata_reset(&rdata);
2477         }
2478         dns_rdataset_disassociate(&rdataset);
2479
2480  cleanup:
2481         if (node != NULL)
2482                 dns_db_detachnode(db, &node);
2483         if (version != NULL)
2484                 dns_db_closeversion(db, &version, ISC_FALSE);
2485 }
2486
2487 static void
2488 resume_signingwithkey(dns_zone_t *zone) {
2489         dns_dbnode_t *node = NULL;
2490         dns_dbversion_t *version = NULL;
2491         dns_rdata_t rdata = DNS_RDATA_INIT;
2492         dns_rdataset_t rdataset;
2493         isc_result_t result;
2494
2495         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2496         if (result != ISC_R_SUCCESS)
2497                 goto cleanup;
2498
2499         dns_db_currentversion(zone->db, &version);
2500         dns_rdataset_init(&rdataset);
2501         result = dns_db_findrdataset(zone->db, node, version,
2502                                      zone->privatetype,
2503                                      dns_rdatatype_none, 0,
2504                                      &rdataset, NULL);
2505         if (result != ISC_R_SUCCESS) {
2506                 INSIST(!dns_rdataset_isassociated(&rdataset));
2507                 goto cleanup;
2508         }
2509
2510         for (result = dns_rdataset_first(&rdataset);
2511              result == ISC_R_SUCCESS;
2512              result = dns_rdataset_next(&rdataset))
2513         {
2514                 dns_rdataset_current(&rdataset, &rdata);
2515                 if (rdata.length != 5 ||
2516                     rdata.data[0] == 0 || rdata.data[4] != 0) {
2517                         dns_rdata_reset(&rdata);
2518                         continue;
2519                 }
2520
2521                 result = zone_signwithkey(zone, rdata.data[0],
2522                                           (rdata.data[1] << 8) | rdata.data[2],
2523                                           ISC_TF(rdata.data[3]));
2524                 if (result != ISC_R_SUCCESS) {
2525                         dns_zone_log(zone, ISC_LOG_ERROR,
2526                                      "zone_signwithkey failed: %s",
2527                                      dns_result_totext(result));
2528                 }
2529                 dns_rdata_reset(&rdata);
2530         }
2531         dns_rdataset_disassociate(&rdataset);
2532
2533  cleanup:
2534         if (node != NULL)
2535                 dns_db_detachnode(zone->db, &node);
2536         if (version != NULL)
2537                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2538 }
2539
2540 static isc_result_t
2541 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2542         dns_nsec3chain_t *nsec3chain, *current;
2543         isc_result_t result;
2544         isc_time_t now;
2545         unsigned int options = 0;
2546         char saltbuf[255*2+1];
2547         char flags[sizeof("REMOVE|CREATE|NONSEC|OPTOUT")];
2548         int i;
2549
2550         nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2551         if (nsec3chain == NULL)
2552                 return (ISC_R_NOMEMORY);
2553
2554         nsec3chain->magic = 0;
2555         nsec3chain->done = ISC_FALSE;
2556         nsec3chain->db = NULL;
2557         nsec3chain->dbiterator = NULL;
2558         nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2559         nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2560         nsec3chain->nsec3param.hash = nsec3param->hash;
2561         nsec3chain->nsec3param.iterations = nsec3param->iterations;
2562         nsec3chain->nsec3param.flags = nsec3param->flags;
2563         nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2564         memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2565         nsec3chain->nsec3param.salt = nsec3chain->salt;
2566         nsec3chain->seen_nsec = ISC_FALSE;
2567         nsec3chain->delete_nsec = ISC_FALSE;
2568         nsec3chain->save_delete_nsec = ISC_FALSE;
2569
2570         if (nsec3param->flags == 0)
2571                 strlcpy(flags, "NONE", sizeof(flags));
2572         else {
2573                 flags[0] = '\0';
2574                 if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2575                         strlcat(flags, "REMOVE", sizeof(flags));
2576                 if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2577                         if (flags[0] == '\0')
2578                                 strlcpy(flags, "CREATE", sizeof(flags));
2579                         else
2580                                 strlcat(flags, "|CREATE", sizeof(flags));
2581                 }
2582                 if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2583                         if (flags[0] == '\0')
2584                                 strlcpy(flags, "NONSEC", sizeof(flags));
2585                         else
2586                                 strlcat(flags, "|NONSEC", sizeof(flags));
2587                 }
2588                 if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2589                         if (flags[0] == '\0')
2590                                 strlcpy(flags, "OPTOUT", sizeof(flags));
2591                         else
2592                                 strlcat(flags, "|OPTOUT", sizeof(flags));
2593                 }
2594         }
2595         if (nsec3param->salt_length == 0)
2596                 strlcpy(saltbuf, "-", sizeof(saltbuf));
2597         else
2598                 for (i = 0; i < nsec3param->salt_length; i++)
2599                         sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2600         dns_zone_log(zone, ISC_LOG_INFO,
2601                      "zone_addnsec3chain(%u,%s,%u,%s)",
2602                       nsec3param->hash, flags, nsec3param->iterations,
2603                       saltbuf);
2604         for (current = ISC_LIST_HEAD(zone->nsec3chain);
2605              current != NULL;
2606              current = ISC_LIST_NEXT(current, link)) {
2607                 if (current->db == zone->db &&
2608                     current->nsec3param.hash == nsec3param->hash &&
2609                     current->nsec3param.iterations == nsec3param->iterations &&
2610                     current->nsec3param.salt_length == nsec3param->salt_length
2611                     && !memcmp(current->nsec3param.salt, nsec3param->salt,
2612                                nsec3param->salt_length))
2613                         current->done = ISC_TRUE;
2614         }
2615
2616         if (zone->db != NULL) {
2617                 dns_db_attach(zone->db, &nsec3chain->db);
2618                 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2619                         options = DNS_DB_NONSEC3;
2620                 result = dns_db_createiterator(nsec3chain->db, options,
2621                                                &nsec3chain->dbiterator);
2622                 if (result == ISC_R_SUCCESS)
2623                         dns_dbiterator_first(nsec3chain->dbiterator);
2624                 if (result == ISC_R_SUCCESS) {
2625                         dns_dbiterator_pause(nsec3chain->dbiterator);
2626                         ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2627                                                nsec3chain, link);
2628                         nsec3chain = NULL;
2629                         if (isc_time_isepoch(&zone->nsec3chaintime)) {
2630                                 TIME_NOW(&now);
2631                                 zone->nsec3chaintime = now;
2632                                 if (zone->task != NULL)
2633                                         zone_settimer(zone, &now);
2634                         }
2635                 }
2636         } else
2637                 result = ISC_R_NOTFOUND;
2638
2639         if (nsec3chain != NULL) {
2640                 if (nsec3chain->db != NULL)
2641                         dns_db_detach(&nsec3chain->db);
2642                 if (nsec3chain->dbiterator != NULL)
2643                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
2644                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2645         }
2646         return (result);
2647 }
2648
2649 static void
2650 resume_addnsec3chain(dns_zone_t *zone) {
2651         dns_dbnode_t *node = NULL;
2652         dns_dbversion_t *version = NULL;
2653         dns_rdataset_t rdataset;
2654         isc_result_t result;
2655         dns_rdata_nsec3param_t nsec3param;
2656
2657         if (zone->privatetype == 0)
2658                 return;
2659
2660         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2661         if (result != ISC_R_SUCCESS)
2662                 goto cleanup;
2663
2664         dns_db_currentversion(zone->db, &version);
2665         dns_rdataset_init(&rdataset);
2666         result = dns_db_findrdataset(zone->db, node, version,
2667                                      zone->privatetype, dns_rdatatype_none,
2668                                      0, &rdataset, NULL);
2669         if (result != ISC_R_SUCCESS) {
2670                 INSIST(!dns_rdataset_isassociated(&rdataset));
2671                 goto cleanup;
2672         }
2673
2674         for (result = dns_rdataset_first(&rdataset);
2675              result == ISC_R_SUCCESS;
2676              result = dns_rdataset_next(&rdataset))
2677         {
2678                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
2679                 dns_rdata_t rdata = DNS_RDATA_INIT;
2680                 dns_rdata_t private = DNS_RDATA_INIT;
2681
2682                 dns_rdataset_current(&rdataset, &private);
2683                 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
2684                                                 sizeof(buf)))
2685                         continue;
2686                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2687                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2688                 if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 ||
2689                     (nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
2690                         result = zone_addnsec3chain(zone, &nsec3param);
2691                         if (result != ISC_R_SUCCESS) {
2692                                 dns_zone_log(zone, ISC_LOG_ERROR,
2693                                              "zone_addnsec3chain failed: %s",
2694                                              dns_result_totext(result));
2695                         }
2696                 }
2697         }
2698         dns_rdataset_disassociate(&rdataset);
2699  cleanup:
2700         if (node != NULL)
2701                 dns_db_detachnode(zone->db, &node);
2702         if (version != NULL)
2703                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2704 }
2705
2706 static void
2707 set_resigntime(dns_zone_t *zone) {
2708         dns_rdataset_t rdataset;
2709         dns_fixedname_t fixed;
2710         unsigned int resign;
2711         isc_result_t result;
2712         isc_uint32_t nanosecs;
2713         dns_db_t *db = NULL;
2714
2715         dns_rdataset_init(&rdataset);
2716         dns_fixedname_init(&fixed);
2717
2718         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2719         if (zone->db != NULL)
2720                 dns_db_attach(zone->db, &db);
2721         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2722         if (db == NULL) {
2723                 isc_time_settoepoch(&zone->resigntime);
2724                 return;
2725         }
2726
2727         result = dns_db_getsigningtime(db, &rdataset,
2728                                        dns_fixedname_name(&fixed));
2729         if (result != ISC_R_SUCCESS) {
2730                 isc_time_settoepoch(&zone->resigntime);
2731                 goto cleanup;
2732         }
2733
2734         resign = rdataset.resign - zone->sigresigninginterval;
2735         dns_rdataset_disassociate(&rdataset);
2736         isc_random_get(&nanosecs);
2737         nanosecs %= 1000000000;
2738         isc_time_set(&zone->resigntime, resign, nanosecs);
2739  cleanup:
2740         dns_db_detach(&db);
2741         return;
2742 }
2743
2744 static isc_result_t
2745 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
2746         dns_dbnode_t *node = NULL;
2747         dns_rdataset_t rdataset;
2748         dns_dbversion_t *version = NULL;
2749         dns_rdata_nsec3param_t nsec3param;
2750         isc_boolean_t ok = ISC_FALSE;
2751         isc_result_t result;
2752         dns_rdata_t rdata = DNS_RDATA_INIT;
2753         isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
2754                                 zone_isdynamic(zone) : ISC_FALSE;
2755
2756         dns_rdataset_init(&rdataset);
2757         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2758         if (result != ISC_R_SUCCESS) {
2759                 dns_zone_log(zone, ISC_LOG_ERROR,
2760                              "nsec3param lookup failure: %s",
2761                              dns_result_totext(result));
2762                 return (result);
2763         }
2764         dns_db_currentversion(db, &version);
2765
2766         result = dns_db_findrdataset(db, node, version,
2767                                      dns_rdatatype_nsec3param,
2768                                      dns_rdatatype_none, 0, &rdataset, NULL);
2769         if (result == ISC_R_NOTFOUND) {
2770                 INSIST(!dns_rdataset_isassociated(&rdataset));
2771                 result = ISC_R_SUCCESS;
2772                 goto cleanup;
2773         }
2774         if (result != ISC_R_SUCCESS) {
2775                 INSIST(!dns_rdataset_isassociated(&rdataset));
2776                 dns_zone_log(zone, ISC_LOG_ERROR,
2777                              "nsec3param lookup failure: %s",
2778                              dns_result_totext(result));
2779                 goto cleanup;
2780         }
2781
2782         /*
2783          * For dynamic zones we must support every algorithm so we can
2784          * regenerate all the NSEC3 chains.
2785          * For non-dynamic zones we only need to find a supported algorithm.
2786          */
2787         for (result = dns_rdataset_first(&rdataset);
2788              result == ISC_R_SUCCESS;
2789              result = dns_rdataset_next(&rdataset))
2790         {
2791                 dns_rdataset_current(&rdataset, &rdata);
2792                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2793                 dns_rdata_reset(&rdata);
2794                 INSIST(result == ISC_R_SUCCESS);
2795                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
2796                     nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
2797                 {
2798                         dns_zone_log(zone, ISC_LOG_WARNING,
2799                              "nsec3 test \"unknown\" hash algorithm found: %u",
2800                                      nsec3param.hash);
2801                         ok = ISC_TRUE;
2802                 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
2803                         if (dynamic) {
2804                                 dns_zone_log(zone, ISC_LOG_ERROR,
2805                                              "unsupported nsec3 hash algorithm"
2806                                              " in dynamic zone: %u",
2807                                              nsec3param.hash);
2808                                 result = DNS_R_BADZONE;
2809                                 /* Stop second error message. */
2810                                 ok = ISC_TRUE;
2811                                 break;
2812                         } else
2813                                 dns_zone_log(zone, ISC_LOG_WARNING,
2814                                      "unsupported nsec3 hash algorithm: %u",
2815                                              nsec3param.hash);
2816                 } else
2817                         ok = ISC_TRUE;
2818         }
2819         if (result == ISC_R_NOMORE)
2820                 result = ISC_R_SUCCESS;
2821
2822         if (!ok) {
2823                 result = DNS_R_BADZONE;
2824                 dns_zone_log(zone, ISC_LOG_ERROR,
2825                              "no supported nsec3 hash algorithm");
2826         }
2827
2828  cleanup:
2829         if (dns_rdataset_isassociated(&rdataset))
2830                 dns_rdataset_disassociate(&rdataset);
2831         dns_db_closeversion(db, &version, ISC_FALSE);
2832         dns_db_detachnode(db, &node);
2833         return (result);
2834 }
2835
2836 /*
2837  * Set the timer for refreshing the key zone to the soonest future time
2838  * of the set (current timer, keydata->refresh, keydata->addhd,
2839  * keydata->removehd).
2840  */
2841 static void
2842 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
2843                     isc_stdtime_t now)
2844 {
2845         const char me[] = "set_refreshkeytimer";
2846         isc_stdtime_t then;
2847         isc_time_t timenow, timethen;
2848         char timebuf[80];
2849
2850         ENTER;
2851         then = key->refresh;
2852         if (key->addhd > now && key->addhd < then)
2853                 then = key->addhd;
2854         if (key->removehd > now && key->removehd < then)
2855                 then = key->removehd;
2856
2857         TIME_NOW(&timenow);
2858         if (then > now)
2859                 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
2860         else
2861                 timethen = timenow;
2862         if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
2863             isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
2864                 zone->refreshkeytime = timethen;
2865
2866         isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
2867         dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
2868         zone_settimer(zone, &timenow);
2869 }
2870
2871 /*
2872  * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
2873  * If the key zone is changed, set '*changed' to ISC_TRUE.
2874  */
2875 static isc_result_t
2876 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
2877                dns_diff_t *diff, dns_keytable_t *keytable,
2878                dns_keynode_t **keynodep, isc_boolean_t *changed)
2879 {
2880         const char me[] = "create_keydata";
2881         isc_result_t result = ISC_R_SUCCESS;
2882         isc_buffer_t keyb, dstb;
2883         unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
2884         dns_rdata_keydata_t keydata;
2885         dns_rdata_dnskey_t dnskey;
2886         dns_rdata_t rdata = DNS_RDATA_INIT;
2887         dns_keynode_t *keynode;
2888         isc_stdtime_t now;
2889         isc_region_t r;
2890         dst_key_t *key;
2891
2892         REQUIRE(keynodep != NULL);
2893         keynode = *keynodep;
2894
2895         ENTER;
2896         isc_stdtime_get(&now);
2897
2898         /* Loop in case there's more than one key. */
2899         while (result == ISC_R_SUCCESS) {
2900                 dns_keynode_t *nextnode = NULL;
2901
2902                 key = dns_keynode_key(keynode);
2903                 if (key == NULL)
2904                         goto skip;
2905
2906                 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
2907                 CHECK(dst_key_todns(key, &dstb));
2908
2909                 /* Convert DST key to DNSKEY. */
2910                 dns_rdata_reset(&rdata);
2911                 isc_buffer_usedregion(&dstb, &r);
2912                 dns_rdata_fromregion(&rdata, dst_key_class(key),
2913                                      dns_rdatatype_dnskey, &r);
2914
2915                 /* DSTKEY to KEYDATA. */
2916                 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
2917                 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
2918                                              NULL));
2919
2920                 /* KEYDATA to rdata. */
2921                 dns_rdata_reset(&rdata);
2922                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
2923                 CHECK(dns_rdata_fromstruct(&rdata,
2924                                            zone->rdclass, dns_rdatatype_keydata,
2925                                            &keydata, &keyb));
2926
2927                 /* Add rdata to zone. */
2928                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
2929                                     dst_key_name(key), 0, &rdata));
2930                 *changed = ISC_TRUE;
2931                 /* Refresh new keys from the zone apex as soon as possible. */
2932                 set_refreshkeytimer(zone, &keydata, now);
2933
2934  skip:
2935                 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
2936                 if (result != ISC_R_NOTFOUND) {
2937                         dns_keytable_detachkeynode(keytable, &keynode);
2938                         keynode = nextnode;
2939                 }
2940         }
2941
2942         if (keynode != NULL)
2943                 dns_keytable_detachkeynode(keytable, &keynode);
2944         *keynodep = NULL;
2945
2946         return (ISC_R_SUCCESS);
2947
2948   failure:
2949         return (result);
2950 }
2951
2952 /*
2953  * Remove from the key zone all the KEYDATA records found in rdataset.
2954  */
2955 static isc_result_t
2956 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
2957                dns_name_t *name, dns_rdataset_t *rdataset)
2958 {
2959         dns_rdata_t rdata = DNS_RDATA_INIT;
2960         isc_result_t result, uresult;
2961
2962         for (result = dns_rdataset_first(rdataset);
2963              result == ISC_R_SUCCESS;
2964              result = dns_rdataset_next(rdataset)) {
2965                 dns_rdata_reset(&rdata);
2966                 dns_rdataset_current(rdataset, &rdata);
2967                 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
2968                                         name, 0, &rdata);
2969                 if (uresult != ISC_R_SUCCESS)
2970                         return (uresult);
2971         }
2972         if (result == ISC_R_NOMORE)
2973                 result = ISC_R_SUCCESS;
2974         return (result);
2975 }
2976
2977 /*
2978  * Compute the DNSSEC key ID for a DNSKEY record.
2979  */
2980 static isc_result_t
2981 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
2982             dns_keytag_t *tag)
2983 {
2984         isc_result_t result;
2985         dns_rdata_t rdata = DNS_RDATA_INIT;
2986         unsigned char data[4096];
2987         isc_buffer_t buffer;
2988         dst_key_t *dstkey = NULL;
2989
2990         isc_buffer_init(&buffer, data, sizeof(data));
2991         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
2992                              dns_rdatatype_dnskey, dnskey, &buffer);
2993
2994         result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
2995         if (result == ISC_R_SUCCESS)
2996                 *tag = dst_key_id(dstkey);
2997         dst_key_free(&dstkey);
2998
2999         return (result);
3000 }
3001
3002 /*
3003  * Add key to the security roots.
3004  */
3005 static void
3006 trust_key(dns_zone_t *zone, dns_name_t *keyname,
3007           dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
3008         isc_result_t result;
3009         dns_rdata_t rdata = DNS_RDATA_INIT;
3010         unsigned char data[4096];
3011         isc_buffer_t buffer;
3012         dns_keytable_t *sr = NULL;
3013         dst_key_t *dstkey = NULL;
3014
3015         /* Convert dnskey to DST key. */
3016         isc_buffer_init(&buffer, data, sizeof(data));
3017         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3018                              dns_rdatatype_dnskey, dnskey, &buffer);
3019
3020         result = dns_view_getsecroots(zone->view, &sr);
3021         if (result != ISC_R_SUCCESS)
3022                 goto failure;
3023
3024         CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
3025         CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
3026         dns_keytable_detach(&sr);
3027
3028   failure:
3029         if (dstkey != NULL)
3030                 dst_key_free(&dstkey);
3031         if (sr != NULL)
3032                 dns_keytable_detach(&sr);
3033         return;
3034 }
3035
3036 /*
3037  * Add a null key to the security roots for so that all queries
3038  * to the zone will fail.
3039  */
3040 static void
3041 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
3042         isc_result_t result;
3043         dns_keytable_t *sr = NULL;
3044
3045         result = dns_view_getsecroots(zone->view, &sr);
3046         if (result == ISC_R_SUCCESS) {
3047                 dns_keytable_marksecure(sr, keyname);
3048                 dns_keytable_detach(&sr);
3049         }
3050 }
3051
3052 /*
3053  * Scan a set of KEYDATA records from the key zone.  The ones that are
3054  * valid (i.e., the add holddown timer has expired) become trusted keys.
3055  */
3056 static void
3057 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
3058         isc_result_t result;
3059         dns_rdata_t rdata = DNS_RDATA_INIT;
3060         dns_rdata_keydata_t keydata;
3061         dns_rdata_dnskey_t dnskey;
3062         isc_mem_t *mctx = zone->mctx;
3063         int trusted = 0, revoked = 0, pending = 0;
3064         isc_stdtime_t now;
3065         dns_keytable_t *sr = NULL;
3066
3067         isc_stdtime_get(&now);
3068
3069         result = dns_view_getsecroots(zone->view, &sr);
3070         if (result == ISC_R_SUCCESS) {
3071                 dns_keytable_delete(sr, name);
3072                 dns_keytable_detach(&sr);
3073         }
3074
3075         /* Now insert all the accepted trust anchors from this keydata set. */
3076         for (result = dns_rdataset_first(rdataset);
3077              result == ISC_R_SUCCESS;
3078              result = dns_rdataset_next(rdataset)) {
3079                 dns_rdata_reset(&rdata);
3080                 dns_rdataset_current(rdataset, &rdata);
3081
3082                 /* Convert rdata to keydata. */
3083                 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
3084                 if (result == ISC_R_UNEXPECTEDEND)
3085                         continue;
3086                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3087
3088                 /* Set the key refresh timer. */
3089                 set_refreshkeytimer(zone, &keydata, now);
3090
3091                 /* If the removal timer is nonzero, this key was revoked. */
3092                 if (keydata.removehd != 0) {
3093                         revoked++;
3094                         continue;
3095                 }
3096
3097                 /*
3098                  * If the add timer is still pending, this key is not
3099                  * trusted yet.
3100                  */
3101                 if (now < keydata.addhd) {
3102                         pending++;
3103                         continue;
3104                 }
3105
3106                 /* Convert keydata to dnskey. */
3107                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
3108
3109                 /* Add to keytables. */
3110                 trusted++;
3111                 trust_key(zone, name, &dnskey, mctx);
3112         }
3113
3114         if (trusted == 0 && pending != 0) {
3115                 char namebuf[DNS_NAME_FORMATSIZE];
3116                 dns_name_format(name, namebuf, sizeof namebuf);
3117                 dns_zone_log(zone, ISC_LOG_ERROR,
3118                              "No valid trust anchors for '%s'!", namebuf);
3119                 dns_zone_log(zone, ISC_LOG_ERROR,
3120                              "%d key(s) revoked, %d still pending",
3121                              revoked, pending);
3122                 dns_zone_log(zone, ISC_LOG_ERROR,
3123                              "All queries to '%s' will fail", namebuf);
3124                 fail_secure(zone, name);
3125         }
3126 }
3127
3128 static isc_result_t
3129 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3130              dns_diff_t *diff)
3131 {
3132         dns_diff_t temp_diff;
3133         isc_result_t result;
3134
3135         /*
3136          * Create a singleton diff.
3137          */
3138         dns_diff_init(diff->mctx, &temp_diff);
3139         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3140
3141         /*
3142          * Apply it to the database.
3143          */
3144         result = dns_diff_apply(&temp_diff, db, ver);
3145         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3146         if (result != ISC_R_SUCCESS) {
3147                 dns_difftuple_free(tuple);
3148                 return (result);
3149         }
3150
3151         /*
3152          * Merge it into the current pending journal entry.
3153          */
3154         dns_diff_appendminimal(diff, tuple);
3155
3156         /*
3157          * Do not clear temp_diff.
3158          */
3159         return (ISC_R_SUCCESS);
3160 }
3161
3162 static isc_result_t
3163 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3164               dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3165               dns_rdata_t *rdata)
3166 {
3167         dns_difftuple_t *tuple = NULL;
3168         isc_result_t result;
3169         result = dns_difftuple_create(diff->mctx, op,
3170                                       name, ttl, rdata, &tuple);
3171         if (result != ISC_R_SUCCESS)
3172                 return (result);
3173         return (do_one_tuple(&tuple, db, ver, diff));
3174 }
3175
3176 static isc_result_t
3177 increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver,
3178                      dns_diff_t *diff, isc_mem_t *mctx) {
3179         dns_difftuple_t *deltuple = NULL;
3180         dns_difftuple_t *addtuple = NULL;
3181         isc_uint32_t serial;
3182         isc_result_t result;
3183
3184         CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3185         CHECK(dns_difftuple_copy(deltuple, &addtuple));
3186         addtuple->op = DNS_DIFFOP_ADD;
3187
3188         serial = dns_soa_getserial(&addtuple->rdata);
3189
3190         /* RFC1982 */
3191         serial = (serial + 1) & 0xFFFFFFFF;
3192         if (serial == 0)
3193                 serial = 1;
3194
3195         dns_soa_setserial(serial, &addtuple->rdata);
3196         CHECK(do_one_tuple(&deltuple, db, ver, diff));
3197         CHECK(do_one_tuple(&addtuple, db, ver, diff));
3198         result = ISC_R_SUCCESS;
3199
3200         failure:
3201         if (addtuple != NULL)
3202                 dns_difftuple_free(&addtuple);
3203         if (deltuple != NULL)
3204                 dns_difftuple_free(&deltuple);
3205         return (result);
3206 }
3207
3208 /*
3209  * Write all transactions in 'diff' to the zone journal file.
3210  */
3211 static isc_result_t
3212 zone_journal(dns_zone_t *zone, dns_diff_t *diff, const char *caller) {
3213         const char me[] = "zone_journal";
3214         const char *journalfile;
3215         isc_result_t result = ISC_R_SUCCESS;
3216         dns_journal_t *journal = NULL;
3217
3218         ENTER;
3219         journalfile = dns_zone_getjournal(zone);
3220         if (journalfile != NULL) {
3221                 result = dns_journal_open(zone->mctx, journalfile,
3222                                           ISC_TRUE, &journal);
3223                 if (result != ISC_R_SUCCESS) {
3224                         dns_zone_log(zone, ISC_LOG_ERROR,
3225                                      "%s:dns_journal_open -> %s",
3226                                      caller, dns_result_totext(result));
3227                         return (result);
3228                 }
3229
3230                 result = dns_journal_write_transaction(journal, diff);
3231                 dns_journal_destroy(&journal);
3232                 if (result != ISC_R_SUCCESS) {
3233                         dns_zone_log(zone, ISC_LOG_ERROR,
3234                                      "%s:dns_journal_write_transaction -> %s",
3235                                      caller, dns_result_totext(result));
3236                         return (result);
3237                 }
3238         }
3239         return (result);
3240 }
3241
3242 /*
3243  * Create an SOA record for a newly-created zone
3244  */
3245 static isc_result_t
3246 add_soa(dns_zone_t *zone, dns_db_t *db) {
3247         isc_result_t result;
3248         dns_rdata_t rdata = DNS_RDATA_INIT;
3249         unsigned char buf[DNS_SOA_BUFFERSIZE];
3250         dns_dbversion_t *ver = NULL;
3251         dns_diff_t diff;
3252
3253         dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3254
3255         dns_diff_init(zone->mctx, &diff);
3256         result = dns_db_newversion(db, &ver);
3257         if (result != ISC_R_SUCCESS) {
3258                 dns_zone_log(zone, ISC_LOG_ERROR,
3259                              "add_soa:dns_db_newversion -> %s",
3260                              dns_result_totext(result));
3261                 goto failure;
3262         }
3263
3264         /* Build SOA record */
3265         result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3266                                     0, 0, 0, 0, 0, buf, &rdata);
3267         if (result != ISC_R_SUCCESS) {
3268                 dns_zone_log(zone, ISC_LOG_ERROR,
3269                              "add_soa:dns_soa_buildrdata -> %s",
3270                              dns_result_totext(result));
3271                 goto failure;
3272         }
3273
3274         result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3275                                &zone->origin, 0, &rdata);
3276
3277 failure:
3278         dns_diff_clear(&diff);
3279         if (ver != NULL)
3280                 dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3281
3282         return (result);
3283 }
3284
3285 /*
3286  * Synchronize the set of initializing keys found in managed-keys {}
3287  * statements with the set of trust anchors found in the managed-keys.bind
3288  * zone.  If a domain is no longer named in managed-keys, delete all keys
3289  * from that domain from the key zone.  If a domain is mentioned in in
3290  * managed-keys but there are no references to it in the key zone, load
3291  * the key zone with the initializing key(s) for that domain.
3292  */
3293 static isc_result_t
3294 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3295         isc_result_t result = ISC_R_SUCCESS;
3296         isc_boolean_t changed = ISC_FALSE;
3297         isc_boolean_t commit = ISC_FALSE;
3298         dns_rbtnodechain_t chain;
3299         dns_fixedname_t fn;
3300         dns_name_t foundname, *origin;
3301         dns_keynode_t *keynode = NULL;
3302         dns_view_t *view = zone->view;
3303         dns_keytable_t *sr = NULL;
3304         dns_dbversion_t *ver = NULL;
3305         dns_diff_t diff;
3306         dns_rriterator_t rrit;
3307
3308         dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3309
3310         dns_name_init(&foundname, NULL);
3311         dns_fixedname_init(&fn);
3312         origin = dns_fixedname_name(&fn);
3313
3314         dns_diff_init(zone->mctx, &diff);
3315
3316         CHECK(dns_view_getsecroots(view, &sr));
3317
3318         result = dns_db_newversion(db, &ver);
3319         if (result != ISC_R_SUCCESS) {
3320                 dns_zone_log(zone, ISC_LOG_ERROR,
3321                              "sync_keyzone:dns_db_newversion -> %s",
3322                              dns_result_totext(result));
3323                 goto failure;
3324         }
3325
3326         /*
3327          * Walk the zone DB.  If we find any keys whose names are no longer
3328          * in managed-keys (or *are* in trusted-keys, meaning they are
3329          * permanent and not RFC5011-maintained), delete them from the
3330          * zone.  Otherwise call load_secroots(), which loads keys into
3331          * secroots as appropriate.
3332          */
3333         dns_rriterator_init(&rrit, db, ver, 0);
3334         for (result = dns_rriterator_first(&rrit);
3335              result == ISC_R_SUCCESS;
3336              result = dns_rriterator_nextrrset(&rrit)) {
3337                 dns_rdataset_t *rdataset = NULL;
3338                 dns_name_t *rrname = NULL;
3339                 isc_uint32_t ttl;
3340
3341                 dns_rriterator_current(&rrit, &rrname, &ttl,
3342                                        &rdataset, NULL);
3343                 if (!dns_rdataset_isassociated(rdataset)) {
3344                         dns_rriterator_destroy(&rrit);
3345                         goto failure;
3346                 }
3347
3348                 if (rdataset->type != dns_rdatatype_keydata)
3349                         continue;
3350
3351                 result = dns_keytable_find(sr, rrname, &keynode);
3352                 if ((result != ISC_R_SUCCESS &&
3353                      result != DNS_R_PARTIALMATCH) ||
3354                     dns_keynode_managed(keynode) == ISC_FALSE) {
3355                         CHECK(delete_keydata(db, ver, &diff,
3356                                              rrname, rdataset));
3357                         changed = ISC_TRUE;
3358                 } else {
3359                         load_secroots(zone, rrname, rdataset);
3360                 }
3361
3362                 if (keynode != NULL)
3363                         dns_keytable_detachkeynode(sr, &keynode);
3364         }
3365         dns_rriterator_destroy(&rrit);
3366
3367         /*
3368          * Now walk secroots to find any managed keys that aren't
3369          * in the zone.  If we find any, we add them to the zone.
3370          */
3371         RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3372         dns_rbtnodechain_init(&chain, zone->mctx);
3373         result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3374         if (result == ISC_R_NOTFOUND)
3375                 result = ISC_R_NOMORE;
3376         while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3377                 dns_rbtnode_t *rbtnode = NULL;
3378
3379                 dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3380                 if (rbtnode->data == NULL)
3381                         goto skip;
3382
3383                 dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3384                 if (dns_keynode_managed(keynode)) {
3385                         dns_fixedname_t fname;
3386                         dns_name_t *keyname;
3387                         dst_key_t *key;
3388
3389                         key = dns_keynode_key(keynode);
3390                         dns_fixedname_init(&fname);
3391
3392                         if (key == NULL)   /* fail_secure() was called. */
3393                                 goto skip;
3394
3395                         keyname = dst_key_name(key);
3396                         result = dns_db_find(db, keyname, ver,
3397                                              dns_rdatatype_keydata,
3398                                              DNS_DBFIND_NOWILD, 0, NULL,
3399                                              dns_fixedname_name(&fname),
3400                                              NULL, NULL);
3401                         if (result != ISC_R_SUCCESS)
3402                                 result = create_keydata(zone, db, ver, &diff,
3403                                                         sr, &keynode, &changed);
3404                         if (result != ISC_R_SUCCESS)
3405                                 break;
3406                 }
3407   skip:
3408                 result = dns_rbtnodechain_next(&chain, &foundname, origin);
3409                 if (keynode != NULL)
3410                         dns_keytable_detachkeynode(sr, &keynode);
3411         }
3412         RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3413
3414         if (result == ISC_R_NOMORE)
3415                 result = ISC_R_SUCCESS;
3416
3417         if (changed) {
3418                 /* Write changes to journal file. */
3419                 CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
3420                 CHECK(zone_journal(zone, &diff, "sync_keyzone"));
3421
3422                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3423                 zone_needdump(zone, 30);
3424                 commit = ISC_TRUE;
3425         }
3426
3427  failure:
3428         if (result != ISC_R_SUCCESS &&
3429             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3430                 dns_zone_log(zone, ISC_LOG_ERROR,
3431                              "unable to synchronize managed keys: %s",
3432                              dns_result_totext(result));
3433                 isc_time_settoepoch(&zone->refreshkeytime);
3434         }
3435         if (keynode != NULL)
3436                 dns_keytable_detachkeynode(sr, &keynode);
3437         if (sr != NULL)
3438                 dns_keytable_detach(&sr);
3439         if (ver != NULL)
3440                 dns_db_closeversion(db, &ver, commit);
3441         dns_diff_clear(&diff);
3442
3443         return (result);
3444 }
3445
3446 static isc_result_t
3447 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3448               isc_result_t result)
3449 {
3450         unsigned int soacount = 0;
3451         unsigned int nscount = 0;
3452         unsigned int errors = 0;
3453         isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3454         isc_time_t now;
3455         isc_boolean_t needdump = ISC_FALSE;
3456         isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3457         isc_boolean_t nomaster = ISC_FALSE;
3458         unsigned int options;
3459
3460         TIME_NOW(&now);
3461
3462         /*
3463          * Initiate zone transfer?  We may need a error code that
3464          * indicates that the "permanent" form does not exist.
3465          * XXX better error feedback to log.
3466          */
3467         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3468                 if (zone->type == dns_zone_slave ||
3469                     zone->type == dns_zone_stub) {
3470                         if (result == ISC_R_FILENOTFOUND)
3471                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3472                                              "no master file");
3473                         else if (result != DNS_R_NOMASTERFILE)
3474                                 dns_zone_log(zone, ISC_LOG_ERROR,
3475                                              "loading from master file %s "
3476                                              "failed: %s",
3477                                              zone->masterfile,
3478                                              dns_result_totext(result));
3479                 } else {
3480                         int level = ISC_LOG_ERROR;
3481                         if (zone->type == dns_zone_key &&
3482                             result == ISC_R_FILENOTFOUND)
3483                                 level = ISC_LOG_DEBUG(1);
3484                         dns_zone_log(zone, level,
3485                                      "loading from master file %s failed: %s",
3486                                      zone->masterfile,
3487                                      dns_result_totext(result));
3488                         nomaster = ISC_TRUE;
3489                 }
3490
3491                 if (zone->type != dns_zone_key)
3492                         goto cleanup;
3493         }
3494
3495         dns_zone_log(zone, ISC_LOG_DEBUG(2),
3496                      "number of nodes in database: %u",
3497                      dns_db_nodecount(db));
3498
3499         if (result == DNS_R_SEENINCLUDE)
3500                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3501         else
3502                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3503
3504         /*
3505          * If there's no master file for a key zone, then the zone is new:
3506          * create an SOA record.  (We do this now, instead of later, so that
3507          * if there happens to be a journal file, we can roll forward from
3508          * a sane starting point.)
3509          */
3510         if (nomaster && zone->type == dns_zone_key) {
3511                 result = add_soa(zone, db);
3512                 if (result != ISC_R_SUCCESS)
3513                         goto cleanup;
3514         }
3515
3516         /*
3517          * Apply update log, if any, on initial load.
3518          */
3519         if (zone->journal != NULL &&
3520             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
3521             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3522         {
3523                 if (zone->type == dns_zone_master &&
3524                     (zone->update_acl != NULL || zone->ssutable != NULL))
3525                         options = DNS_JOURNALOPT_RESIGN;
3526                 else
3527                         options = 0;
3528                 result = dns_journal_rollforward2(zone->mctx, db, options,
3529                                                   0, zone->journal);
3530                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
3531                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
3532                     result != ISC_R_RANGE) {
3533                         dns_zone_log(zone, ISC_LOG_ERROR,
3534                                      "journal rollforward failed: %s",
3535                                      dns_result_totext(result));
3536                         goto cleanup;
3537                 }
3538                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
3539                         dns_zone_log(zone, ISC_LOG_ERROR,
3540                                      "journal rollforward failed: "
3541                                      "journal out of sync with zone");
3542                         goto cleanup;
3543                 }
3544                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3545                              "journal rollforward completed "
3546                              "successfully: %s",
3547                              dns_result_totext(result));
3548                 if (result == ISC_R_SUCCESS)
3549                         needdump = ISC_TRUE;
3550         }
3551
3552         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
3553         /*
3554          * Obtain ns, soa and cname counts for top of zone.
3555          */
3556         INSIST(db != NULL);
3557         result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
3558                                   &refresh, &retry, &expire, &minimum,
3559                                   &errors);
3560         if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
3561                 dns_zone_log(zone, ISC_LOG_ERROR,
3562                              "could not find NS and/or SOA records");
3563         }
3564
3565         /*
3566          * Master / Slave / Stub zones require both NS and SOA records at
3567          * the top of the zone.
3568          */
3569
3570         switch (zone->type) {
3571         case dns_zone_dlz:
3572         case dns_zone_master:
3573         case dns_zone_slave:
3574         case dns_zone_stub:
3575                 if (soacount != 1) {
3576                         dns_zone_log(zone, ISC_LOG_ERROR,
3577                                      "has %d SOA records", soacount);
3578                         result = DNS_R_BADZONE;
3579                 }
3580                 if (nscount == 0) {
3581                         dns_zone_log(zone, ISC_LOG_ERROR,
3582                                      "has no NS records");
3583                         result = DNS_R_BADZONE;
3584                 }
3585                 if (result != ISC_R_SUCCESS)
3586                         goto cleanup;
3587                 if (zone->type == dns_zone_master && errors != 0) {
3588                         result = DNS_R_BADZONE;
3589                         goto cleanup;
3590                 }
3591                 if (zone->type != dns_zone_stub) {
3592                         result = check_nsec3param(zone, db);
3593                         if (result != ISC_R_SUCCESS)
3594                                 goto cleanup;
3595                 }
3596                 if (zone->type == dns_zone_master &&
3597                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
3598                     !integrity_checks(zone, db)) {
3599                         result = DNS_R_BADZONE;
3600                         goto cleanup;
3601                 }
3602
3603                 if (zone->type == dns_zone_master &&
3604                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
3605                     !zone_check_dup(zone, db)) {
3606                         result = DNS_R_BADZONE;
3607                         goto cleanup;
3608                 }
3609
3610                 if (zone->db != NULL) {
3611                         unsigned int oldsoacount;
3612
3613                         /*
3614                          * This is checked in zone_replacedb() for slave zones
3615                          * as they don't reload from disk.
3616                          */
3617                         result = zone_get_from_db(zone, zone->db, NULL,
3618                                                   &oldsoacount, &oldserial,
3619                                                   NULL, NULL, NULL, NULL,
3620                                                   NULL);
3621                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3622                         RUNTIME_CHECK(soacount > 0U);
3623                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
3624                             !isc_serial_gt(serial, oldserial)) {
3625                                 isc_uint32_t serialmin, serialmax;
3626
3627                                 INSIST(zone->type == dns_zone_master);
3628
3629                                 serialmin = (oldserial + 1) & 0xffffffffU;
3630                                 serialmax = (oldserial + 0x7fffffffU) &
3631                                              0xffffffffU;
3632                                 dns_zone_log(zone, ISC_LOG_ERROR,
3633                                              "ixfr-from-differences: "
3634                                              "new serial (%u) out of range "
3635                                              "[%u - %u]", serial, serialmin,
3636                                              serialmax);
3637                                 result = DNS_R_BADZONE;
3638                                 goto cleanup;
3639                         } else if (!isc_serial_ge(serial, oldserial))
3640                                 dns_zone_log(zone, ISC_LOG_ERROR,
3641                                              "zone serial (%u/%u) has gone "
3642                                              "backwards", serial, oldserial);
3643                         else if (serial == oldserial && !hasinclude &&
3644                                  strcmp(zone->db_argv[0], "_builtin") != 0)
3645                                 dns_zone_log(zone, ISC_LOG_ERROR,
3646                                              "zone serial (%u) unchanged. "
3647                                              "zone may fail to transfer "
3648                                              "to slaves.", serial);
3649                 }
3650
3651                 if (zone->type == dns_zone_master &&
3652                     (zone->update_acl != NULL || zone->ssutable != NULL) &&
3653                     zone->sigresigninginterval < (3 * refresh) &&
3654                     dns_db_issecure(db))
3655                 {
3656                         dns_zone_log(zone, ISC_LOG_WARNING,
3657                                      "sig-re-signing-interval less than "
3658                                      "3 * refresh.");
3659                 }
3660
3661                 zone->refresh = RANGE(refresh,
3662                                       zone->minrefresh, zone->maxrefresh);
3663                 zone->retry = RANGE(retry,
3664                                     zone->minretry, zone->maxretry);
3665                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
3666                                      DNS_MAX_EXPIRE);
3667                 zone->minimum = minimum;
3668                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
3669
3670                 if (zone->type == dns_zone_slave ||
3671                     zone->type == dns_zone_stub) {
3672                         isc_time_t t;
3673                         isc_uint32_t delay;
3674
3675                         result = isc_file_getmodtime(zone->journal, &t);
3676                         if (result != ISC_R_SUCCESS)
3677                                 result = isc_file_getmodtime(zone->masterfile,
3678                                                              &t);
3679                         if (result == ISC_R_SUCCESS)
3680                                 DNS_ZONE_TIME_ADD(&t, zone->expire,
3681                                                   &zone->expiretime);
3682                         else
3683                                 DNS_ZONE_TIME_ADD(&now, zone->retry,
3684                                                   &zone->expiretime);
3685
3686                         delay = isc_random_jitter(zone->retry,
3687                                                   (zone->retry * 3) / 4);
3688                         DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
3689                         if (isc_time_compare(&zone->refreshtime,
3690                                              &zone->expiretime) >= 0)
3691                                 zone->refreshtime = now;
3692                 }
3693                 break;
3694
3695         case dns_zone_key:
3696                 result = sync_keyzone(zone, db);
3697                 if (result != ISC_R_SUCCESS)
3698                         goto cleanup;
3699                 break;
3700
3701         default:
3702                 UNEXPECTED_ERROR(__FILE__, __LINE__,
3703                                  "unexpected zone type %d", zone->type);
3704                 result = ISC_R_UNEXPECTED;
3705                 goto cleanup;
3706         }
3707
3708         /*
3709          * Check for weak DNSKEY's.
3710          */
3711         if (zone->type == dns_zone_master)
3712                 zone_check_dnskeys(zone, db);
3713
3714         /*
3715          * Schedule DNSSEC key refresh.
3716          */
3717         if (zone->type == dns_zone_master &&
3718             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
3719                 zone->refreshkeytime = now;
3720
3721 #if 0
3722         /* destroy notification example. */
3723         {
3724                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
3725                                                     DNS_EVENT_DBDESTROYED,
3726                                                     dns_zonemgr_dbdestroyed,
3727                                                     zone,
3728                                                     sizeof(isc_event_t));
3729                 dns_db_ondestroy(db, zone->task, &e);
3730         }
3731 #endif
3732
3733         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
3734         if (zone->db != NULL) {
3735                 result = zone_replacedb(zone, db, ISC_FALSE);
3736                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3737                 if (result != ISC_R_SUCCESS)
3738                         goto cleanup;
3739         } else {
3740                 zone_attachdb(zone, db);
3741                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3742                 DNS_ZONE_SETFLAG(zone,
3743                                  DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
3744         }
3745
3746         result = ISC_R_SUCCESS;
3747
3748         if (needdump) {
3749                 if (zone->type == dns_zone_key)
3750                         zone_needdump(zone, 30);
3751                 else
3752                         zone_needdump(zone, DNS_DUMP_DELAY);
3753         }
3754
3755         if (zone->task != NULL) {
3756                 if (zone->type == dns_zone_master) {
3757                         set_resigntime(zone);
3758                         resume_signingwithkey(zone);
3759                         resume_addnsec3chain(zone);
3760                 }
3761
3762                 if (zone->type == dns_zone_master &&
3763                     zone_isdynamic(zone) &&
3764                     dns_db_issecure(db)) {
3765                         dns_name_t *name;
3766                         dns_fixedname_t fixed;
3767                         dns_rdataset_t next;
3768
3769                         dns_rdataset_init(&next);
3770                         dns_fixedname_init(&fixed);
3771                         name = dns_fixedname_name(&fixed);
3772
3773                         result = dns_db_getsigningtime(db, &next, name);
3774                         if (result == ISC_R_SUCCESS) {
3775                                 isc_stdtime_t timenow;
3776                                 char namebuf[DNS_NAME_FORMATSIZE];
3777                                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3778
3779                                 isc_stdtime_get(&timenow);
3780                                 dns_name_format(name, namebuf, sizeof(namebuf));
3781                                 dns_rdatatype_format(next.covers,
3782                                                      typebuf, sizeof(typebuf));
3783                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
3784                                              "next resign: %s/%s in %d seconds",
3785                                              namebuf, typebuf,
3786                                              next.resign - timenow -
3787                                              zone->sigresigninginterval);
3788                                 dns_rdataset_disassociate(&next);
3789                         } else
3790                                 dns_zone_log(zone, ISC_LOG_WARNING,
3791                                              "signed dynamic zone has no "
3792                                              "resign event scheduled");
3793                 }
3794
3795                 zone_settimer(zone, &now);
3796         }
3797
3798         if (! dns_db_ispersistent(db))
3799                 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
3800                              dns_db_issecure(db) ? " (DNSSEC signed)" : "");
3801
3802         zone->loadtime = loadtime;
3803         return (result);
3804
3805  cleanup:
3806         if (zone->type == dns_zone_slave ||
3807             zone->type == dns_zone_stub ||
3808             zone->type == dns_zone_key) {
3809                 if (zone->journal != NULL)
3810                         zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
3811                 if (zone->masterfile != NULL)
3812                         zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
3813
3814                 /* Mark the zone for immediate refresh. */
3815                 zone->refreshtime = now;
3816                 if (zone->task != NULL)
3817                         zone_settimer(zone, &now);
3818                 result = ISC_R_SUCCESS;
3819         } else if (zone->type == dns_zone_master)
3820                 dns_zone_log(zone, ISC_LOG_ERROR, "not loaded due to errors.");
3821         return (result);
3822 }
3823
3824 static isc_boolean_t
3825 exit_check(dns_zone_t *zone) {
3826
3827         REQUIRE(LOCKED_ZONE(zone));
3828
3829         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
3830             zone->irefs == 0)
3831         {
3832                 /*
3833                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
3834                  */
3835                 INSIST(isc_refcount_current(&zone->erefs) == 0);
3836                 return (ISC_TRUE);
3837         }
3838         return (ISC_FALSE);
3839 }
3840
3841 static isc_boolean_t
3842 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
3843               dns_name_t *name, isc_boolean_t logit)
3844 {
3845         isc_result_t result;
3846         char namebuf[DNS_NAME_FORMATSIZE];
3847         char altbuf[DNS_NAME_FORMATSIZE];
3848         dns_fixedname_t fixed;
3849         dns_name_t *foundname;
3850         int level;
3851
3852         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
3853                 return (ISC_TRUE);
3854
3855         if (zone->type == dns_zone_master)
3856                 level = ISC_LOG_ERROR;
3857         else
3858                 level = ISC_LOG_WARNING;
3859
3860         dns_fixedname_init(&fixed);
3861         foundname = dns_fixedname_name(&fixed);
3862
3863         result = dns_db_find(db, name, version, dns_rdatatype_a,
3864                              0, 0, NULL, foundname, NULL, NULL);
3865         if (result == ISC_R_SUCCESS)
3866                 return (ISC_TRUE);
3867
3868         if (result == DNS_R_NXRRSET) {
3869                 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
3870                                      0, 0, NULL, foundname, NULL, NULL);
3871                 if (result == ISC_R_SUCCESS)
3872                         return (ISC_TRUE);
3873         }
3874
3875         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3876             result == DNS_R_EMPTYNAME) {
3877                 if (logit) {
3878                         dns_name_format(name, namebuf, sizeof namebuf);
3879                         dns_zone_log(zone, level, "NS '%s' has no address "
3880                                      "records (A or AAAA)", namebuf);
3881                 }
3882                 return (ISC_FALSE);
3883         }
3884
3885         if (result == DNS_R_CNAME) {
3886                 if (logit) {
3887                         dns_name_format(name, namebuf, sizeof namebuf);
3888                         dns_zone_log(zone, level, "NS '%s' is a CNAME "
3889                                      "(illegal)", namebuf);
3890                 }
3891                 return (ISC_FALSE);
3892         }
3893
3894         if (result == DNS_R_DNAME) {
3895                 if (logit) {
3896                         dns_name_format(name, namebuf, sizeof namebuf);
3897                         dns_name_format(foundname, altbuf, sizeof altbuf);
3898                         dns_zone_log(zone, level, "NS '%s' is below a DNAME "
3899                                      "'%s' (illegal)", namebuf, altbuf);
3900                 }
3901                 return (ISC_FALSE);
3902         }
3903
3904         return (ISC_TRUE);
3905 }
3906
3907 static isc_result_t
3908 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
3909                  dns_dbversion_t *version, unsigned int *nscount,
3910                  unsigned int *errors, isc_boolean_t logit)
3911 {
3912         isc_result_t result;
3913         unsigned int count = 0;
3914         unsigned int ecount = 0;
3915         dns_rdataset_t rdataset;
3916         dns_rdata_t rdata;
3917         dns_rdata_ns_t ns;
3918
3919         dns_rdataset_init(&rdataset);
3920         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
3921                                      dns_rdatatype_none, 0, &rdataset, NULL);
3922         if (result == ISC_R_NOTFOUND) {
3923                 INSIST(!dns_rdataset_isassociated(&rdataset));
3924                 goto success;
3925         }
3926         if (result != ISC_R_SUCCESS) {
3927                 INSIST(!dns_rdataset_isassociated(&rdataset));
3928                 goto invalidate_rdataset;
3929         }
3930
3931         result = dns_rdataset_first(&rdataset);
3932         while (result == ISC_R_SUCCESS) {
3933                 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
3934                     (zone->type == dns_zone_master ||
3935                      zone->type == dns_zone_slave)) {
3936                         dns_rdata_init(&rdata);
3937                         dns_rdataset_current(&rdataset, &rdata);
3938                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
3939                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3940                         if (dns_name_issubdomain(&ns.name, &zone->origin) &&
3941                             !zone_check_ns(zone, db, version, &ns.name, logit))
3942                                 ecount++;
3943                 }
3944                 count++;
3945                 result = dns_rdataset_next(&rdataset);
3946         }
3947         dns_rdataset_disassociate(&rdataset);
3948
3949  success:
3950         if (nscount != NULL)
3951                 *nscount = count;
3952         if (errors != NULL)
3953                 *errors = ecount;
3954
3955         result = ISC_R_SUCCESS;
3956
3957  invalidate_rdataset:
3958         dns_rdataset_invalidate(&rdataset);
3959
3960         return (result);
3961 }
3962
3963 static isc_result_t
3964 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
3965                  unsigned int *soacount,
3966                  isc_uint32_t *serial, isc_uint32_t *refresh,
3967                  isc_uint32_t *retry, isc_uint32_t *expire,
3968                  isc_uint32_t *minimum)
3969 {
3970         isc_result_t result;
3971         unsigned int count;
3972         dns_rdataset_t rdataset;
3973         dns_rdata_t rdata = DNS_RDATA_INIT;
3974         dns_rdata_soa_t soa;
3975
3976         dns_rdataset_init(&rdataset);
3977         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
3978                                      dns_rdatatype_none, 0, &rdataset, NULL);
3979         if (result == ISC_R_NOTFOUND) {
3980                 INSIST(!dns_rdataset_isassociated(&rdataset));
3981                 if (soacount != NULL)
3982                         *soacount = 0;
3983                 if (serial != NULL)
3984                         *serial = 0;
3985                 if (refresh != NULL)
3986                         *refresh = 0;
3987                 if (retry != NULL)
3988                         *retry = 0;
3989                 if (expire != NULL)
3990                         *expire = 0;
3991                 if (minimum != NULL)
3992                         *minimum = 0;
3993                 result = ISC_R_SUCCESS;
3994                 goto invalidate_rdataset;
3995         }
3996         if (result != ISC_R_SUCCESS) {
3997                 INSIST(!dns_rdataset_isassociated(&rdataset));
3998                 goto invalidate_rdataset;
3999         }
4000
4001         count = 0;
4002         result = dns_rdataset_first(&rdataset);
4003         while (result == ISC_R_SUCCESS) {
4004                 dns_rdata_init(&rdata);
4005                 dns_rdataset_current(&rdataset, &rdata);
4006                 count++;
4007                 if (count == 1) {
4008                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
4009                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4010                 }
4011
4012                 result = dns_rdataset_next(&rdataset);
4013                 dns_rdata_reset(&rdata);
4014         }
4015         dns_rdataset_disassociate(&rdataset);
4016
4017         if (soacount != NULL)
4018                 *soacount = count;
4019
4020         if (count > 0) {
4021                 if (serial != NULL)
4022                         *serial = soa.serial;
4023                 if (refresh != NULL)
4024                         *refresh = soa.refresh;
4025                 if (retry != NULL)
4026                         *retry = soa.retry;
4027                 if (expire != NULL)
4028                         *expire = soa.expire;
4029                 if (minimum != NULL)
4030                         *minimum = soa.minimum;
4031         } else {
4032                 if (soacount != NULL)
4033                         *soacount = 0;
4034                 if (serial != NULL)
4035                         *serial = 0;
4036                 if (refresh != NULL)
4037                         *refresh = 0;
4038                 if (retry != NULL)
4039                         *retry = 0;
4040                 if (expire != NULL)
4041                         *expire = 0;
4042                 if (minimum != NULL)
4043                         *minimum = 0;
4044         }
4045
4046         result = ISC_R_SUCCESS;
4047
4048  invalidate_rdataset:
4049         dns_rdataset_invalidate(&rdataset);
4050
4051         return (result);
4052 }
4053
4054 /*
4055  * zone must be locked.
4056  */
4057 static isc_result_t
4058 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
4059                  unsigned int *soacount, isc_uint32_t *serial,
4060                  isc_uint32_t *refresh, isc_uint32_t *retry,
4061                  isc_uint32_t *expire, isc_uint32_t *minimum,
4062                  unsigned int *errors)
4063 {
4064         isc_result_t result;
4065         isc_result_t answer = ISC_R_SUCCESS;
4066         dns_dbversion_t *version = NULL;
4067         dns_dbnode_t *node;
4068
4069         REQUIRE(db != NULL);
4070         REQUIRE(zone != NULL);
4071
4072         dns_db_currentversion(db, &version);
4073
4074         node = NULL;
4075         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
4076         if (result != ISC_R_SUCCESS) {
4077                 answer = result;
4078                 goto closeversion;
4079         }
4080
4081         if (nscount != NULL || errors != NULL) {
4082                 result = zone_count_ns_rr(zone, db, node, version,
4083                                           nscount, errors, ISC_TRUE);
4084                 if (result != ISC_R_SUCCESS)
4085                         answer = result;
4086         }
4087
4088         if (soacount != NULL || serial != NULL || refresh != NULL
4089             || retry != NULL || expire != NULL || minimum != NULL) {
4090                 result = zone_load_soa_rr(db, node, version, soacount,
4091                                           serial, refresh, retry, expire,
4092                                           minimum);
4093                 if (result != ISC_R_SUCCESS)
4094                         answer = result;
4095         }
4096
4097         dns_db_detachnode(db, &node);
4098  closeversion:
4099         dns_db_closeversion(db, &version, ISC_FALSE);
4100
4101         return (answer);
4102 }
4103
4104 void
4105 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
4106         REQUIRE(DNS_ZONE_VALID(source));
4107         REQUIRE(target != NULL && *target == NULL);
4108         isc_refcount_increment(&source->erefs, NULL);
4109         *target = source;
4110 }
4111
4112 void
4113 dns_zone_detach(dns_zone_t **zonep) {
4114         dns_zone_t *zone;
4115         unsigned int refs;
4116         isc_boolean_t free_now = ISC_FALSE;
4117
4118         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4119
4120         zone = *zonep;
4121
4122         isc_refcount_decrement(&zone->erefs, &refs);
4123
4124         if (refs == 0) {
4125                 LOCK_ZONE(zone);
4126                 /*
4127                  * We just detached the last external reference.
4128                  */
4129                 if (zone->task != NULL) {
4130                         /*
4131                          * This zone is being managed.  Post
4132                          * its control event and let it clean
4133                          * up synchronously in the context of
4134                          * its task.
4135                          */
4136                         isc_event_t *ev = &zone->ctlevent;
4137                         isc_task_send(zone->task, &ev);
4138                 } else {
4139                         /*
4140                          * This zone is not being managed; it has
4141                          * no task and can have no outstanding
4142                          * events.  Free it immediately.
4143                          */
4144                         /*
4145                          * Unmanaged zones should not have non-null views;
4146                          * we have no way of detaching from the view here
4147                          * without causing deadlock because this code is called
4148                          * with the view already locked.
4149                          */
4150                         INSIST(zone->view == NULL);
4151                         free_now = ISC_TRUE;
4152                 }
4153                 UNLOCK_ZONE(zone);
4154         }
4155         *zonep = NULL;
4156         if (free_now)
4157                 zone_free(zone);
4158 }
4159
4160 void
4161 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4162         REQUIRE(DNS_ZONE_VALID(source));
4163         REQUIRE(target != NULL && *target == NULL);
4164         LOCK_ZONE(source);
4165         zone_iattach(source, target);
4166         UNLOCK_ZONE(source);
4167 }
4168
4169 isc_result_t
4170 dns_zone_synckeyzone(dns_zone_t *zone) {
4171         isc_result_t result;
4172         dns_db_t *db = NULL;
4173
4174         if (zone->type != dns_zone_key)
4175                 return (DNS_R_BADZONE);
4176
4177         CHECK(dns_zone_getdb(zone, &db));
4178
4179         LOCK_ZONE(zone);
4180         result = sync_keyzone(zone, db);
4181         UNLOCK_ZONE(zone);
4182
4183  failure:
4184         if (db != NULL)
4185                 dns_db_detach(&db);
4186         return (result);
4187 }
4188
4189 static void
4190 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4191
4192         /*
4193          * 'source' locked by caller.
4194          */
4195         REQUIRE(LOCKED_ZONE(source));
4196         REQUIRE(DNS_ZONE_VALID(source));
4197         REQUIRE(target != NULL && *target == NULL);
4198         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
4199         source->irefs++;
4200         INSIST(source->irefs != 0);
4201         *target = source;
4202 }
4203
4204 static void
4205 zone_idetach(dns_zone_t **zonep) {
4206         dns_zone_t *zone;
4207
4208         /*
4209          * 'zone' locked by caller.
4210          */
4211         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4212         zone = *zonep;
4213         REQUIRE(LOCKED_ZONE(*zonep));
4214         *zonep = NULL;
4215
4216         INSIST(zone->irefs > 0);
4217         zone->irefs--;
4218         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4219 }
4220
4221 void
4222 dns_zone_idetach(dns_zone_t **zonep) {
4223         dns_zone_t *zone;
4224         isc_boolean_t free_needed;
4225
4226         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4227         zone = *zonep;
4228         *zonep = NULL;
4229
4230         LOCK_ZONE(zone);
4231         INSIST(zone->irefs > 0);
4232         zone->irefs--;
4233         free_needed = exit_check(zone);
4234         UNLOCK_ZONE(zone);
4235         if (free_needed)
4236                 zone_free(zone);
4237 }
4238
4239 isc_mem_t *
4240 dns_zone_getmctx(dns_zone_t *zone) {
4241         REQUIRE(DNS_ZONE_VALID(zone));
4242
4243         return (zone->mctx);
4244 }
4245
4246 dns_zonemgr_t *
4247 dns_zone_getmgr(dns_zone_t *zone) {
4248         REQUIRE(DNS_ZONE_VALID(zone));
4249
4250         return (zone->zmgr);
4251 }
4252
4253 void
4254 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4255         REQUIRE(DNS_ZONE_VALID(zone));
4256
4257         LOCK_ZONE(zone);
4258         if (value)
4259                 DNS_ZONE_SETFLAG(zone, flags);
4260         else
4261                 DNS_ZONE_CLRFLAG(zone, flags);
4262         UNLOCK_ZONE(zone);
4263 }
4264
4265 void
4266 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4267 {
4268         REQUIRE(DNS_ZONE_VALID(zone));
4269
4270         LOCK_ZONE(zone);
4271         if (value)
4272                 zone->options |= option;
4273         else
4274                 zone->options &= ~option;
4275         UNLOCK_ZONE(zone);
4276 }
4277
4278 unsigned int
4279 dns_zone_getoptions(dns_zone_t *zone) {
4280
4281         REQUIRE(DNS_ZONE_VALID(zone));
4282
4283         return (zone->options);
4284 }
4285
4286 void
4287 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4288 {
4289         REQUIRE(DNS_ZONE_VALID(zone));
4290
4291         LOCK_ZONE(zone);
4292         if (value)
4293                 zone->keyopts |= keyopt;
4294         else
4295                 zone->keyopts &= ~keyopt;
4296         UNLOCK_ZONE(zone);
4297 }
4298
4299 unsigned int
4300 dns_zone_getkeyopts(dns_zone_t *zone) {
4301
4302         REQUIRE(DNS_ZONE_VALID(zone));
4303
4304         return (zone->keyopts);
4305 }
4306
4307 isc_result_t
4308 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4309         REQUIRE(DNS_ZONE_VALID(zone));
4310
4311         LOCK_ZONE(zone);
4312         zone->xfrsource4 = *xfrsource;
4313         UNLOCK_ZONE(zone);
4314
4315         return (ISC_R_SUCCESS);
4316 }
4317
4318 isc_sockaddr_t *
4319 dns_zone_getxfrsource4(dns_zone_t *zone) {
4320         REQUIRE(DNS_ZONE_VALID(zone));
4321         return (&zone->xfrsource4);
4322 }
4323
4324 isc_result_t
4325 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4326         REQUIRE(DNS_ZONE_VALID(zone));
4327
4328         LOCK_ZONE(zone);
4329         zone->xfrsource6 = *xfrsource;
4330         UNLOCK_ZONE(zone);
4331
4332         return (ISC_R_SUCCESS);
4333 }
4334
4335 isc_sockaddr_t *
4336 dns_zone_getxfrsource6(dns_zone_t *zone) {
4337         REQUIRE(DNS_ZONE_VALID(zone));
4338         return (&zone->xfrsource6);
4339 }
4340
4341 isc_result_t
4342 dns_zone_setaltxfrsource4(dns_zone_t *zone,
4343                           const isc_sockaddr_t *altxfrsource)
4344 {
4345         REQUIRE(DNS_ZONE_VALID(zone));
4346
4347         LOCK_ZONE(zone);
4348         zone->altxfrsource4 = *altxfrsource;
4349         UNLOCK_ZONE(zone);
4350
4351         return (ISC_R_SUCCESS);
4352 }
4353
4354 isc_sockaddr_t *
4355 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4356         REQUIRE(DNS_ZONE_VALID(zone));
4357         return (&zone->altxfrsource4);
4358 }
4359
4360 isc_result_t
4361 dns_zone_setaltxfrsource6(dns_zone_t *zone,
4362                           const isc_sockaddr_t *altxfrsource)
4363 {
4364         REQUIRE(DNS_ZONE_VALID(zone));
4365
4366         LOCK_ZONE(zone);
4367         zone->altxfrsource6 = *altxfrsource;
4368         UNLOCK_ZONE(zone);
4369
4370         return (ISC_R_SUCCESS);
4371 }
4372
4373 isc_sockaddr_t *
4374 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4375         REQUIRE(DNS_ZONE_VALID(zone));
4376         return (&zone->altxfrsource6);
4377 }
4378
4379 isc_result_t
4380 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4381         REQUIRE(DNS_ZONE_VALID(zone));
4382
4383         LOCK_ZONE(zone);
4384         zone->notifysrc4 = *notifysrc;
4385         UNLOCK_ZONE(zone);
4386
4387         return (ISC_R_SUCCESS);
4388 }
4389
4390 isc_sockaddr_t *
4391 dns_zone_getnotifysrc4(dns_zone_t *zone) {
4392         REQUIRE(DNS_ZONE_VALID(zone));
4393         return (&zone->notifysrc4);
4394 }
4395
4396 isc_result_t
4397 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4398         REQUIRE(DNS_ZONE_VALID(zone));
4399
4400         LOCK_ZONE(zone);
4401         zone->notifysrc6 = *notifysrc;
4402         UNLOCK_ZONE(zone);
4403
4404         return (ISC_R_SUCCESS);
4405 }
4406
4407 isc_sockaddr_t *
4408 dns_zone_getnotifysrc6(dns_zone_t *zone) {
4409         REQUIRE(DNS_ZONE_VALID(zone));
4410         return (&zone->notifysrc6);
4411 }
4412
4413 isc_result_t
4414 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
4415                        isc_uint32_t count)
4416 {
4417         isc_sockaddr_t *new;
4418
4419         REQUIRE(DNS_ZONE_VALID(zone));
4420         REQUIRE(count == 0 || notify != NULL);
4421
4422         LOCK_ZONE(zone);
4423         if (zone->notify != NULL) {
4424                 isc_mem_put(zone->mctx, zone->notify,
4425                             zone->notifycnt * sizeof(*new));
4426                 zone->notify = NULL;
4427                 zone->notifycnt = 0;
4428         }
4429         if (count != 0) {
4430                 new = isc_mem_get(zone->mctx, count * sizeof(*new));
4431                 if (new == NULL) {
4432                         UNLOCK_ZONE(zone);
4433                         return (ISC_R_NOMEMORY);
4434                 }
4435                 memmove(new, notify, count * sizeof(*new));
4436                 zone->notify = new;
4437                 zone->notifycnt = count;
4438         }
4439         UNLOCK_ZONE(zone);
4440         return (ISC_R_SUCCESS);
4441 }
4442
4443 isc_result_t
4444 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
4445                     isc_uint32_t count)
4446 {
4447         isc_result_t result;
4448
4449         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
4450         return (result);
4451 }
4452
4453 static isc_boolean_t
4454 same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4455              isc_uint32_t count)
4456 {
4457         unsigned int i;
4458
4459         for (i = 0; i < count; i++)
4460                 if (!isc_sockaddr_equal(&old[i], &new[i]))
4461                         return (ISC_FALSE);
4462         return (ISC_TRUE);
4463 }
4464
4465 static isc_boolean_t
4466 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
4467         unsigned int i;
4468
4469         if (old == NULL && new == NULL)
4470                 return (ISC_TRUE);
4471         if (old == NULL || new == NULL)
4472                 return (ISC_FALSE);
4473
4474         for (i = 0; i < count; i++) {
4475                 if (old[i] == NULL && new[i] == NULL)
4476                         continue;
4477                 if (old[i] == NULL || new[i] == NULL ||
4478                      !dns_name_equal(old[i], new[i]))
4479                         return (ISC_FALSE);
4480         }
4481         return (ISC_TRUE);
4482 }
4483
4484 isc_result_t
4485 dns_zone_setmasterswithkeys(dns_zone_t *zone,
4486                             const isc_sockaddr_t *masters,
4487                             dns_name_t **keynames,
4488                             isc_uint32_t count)
4489 {
4490         isc_sockaddr_t *new;
4491         isc_result_t result = ISC_R_SUCCESS;
4492         dns_name_t **newname;
4493         isc_boolean_t *newok;
4494         unsigned int i;
4495
4496         REQUIRE(DNS_ZONE_VALID(zone));
4497         REQUIRE(count == 0 || masters != NULL);
4498         if (keynames != NULL) {
4499                 REQUIRE(count != 0);
4500         }
4501
4502         LOCK_ZONE(zone);
4503         /*
4504          * The refresh code assumes that 'masters' wouldn't change under it.
4505          * If it will change then kill off any current refresh in progress
4506          * and update the masters info.  If it won't change then we can just
4507          * unlock and exit.
4508          */
4509         if (count != zone->masterscnt ||
4510             !same_masters(zone->masters, masters, count) ||
4511             !same_keynames(zone->masterkeynames, keynames, count)) {
4512                 if (zone->request != NULL)
4513                         dns_request_cancel(zone->request);
4514         } else
4515                 goto unlock;
4516         if (zone->masters != NULL) {
4517                 isc_mem_put(zone->mctx, zone->masters,
4518                             zone->masterscnt * sizeof(*new));
4519                 zone->masters = NULL;
4520         }
4521         if (zone->masterkeynames != NULL) {
4522                 for (i = 0; i < zone->masterscnt; i++) {
4523                         if (zone->masterkeynames[i] != NULL) {
4524                                 dns_name_free(zone->masterkeynames[i],
4525                                               zone->mctx);
4526                                 isc_mem_put(zone->mctx,
4527                                             zone->masterkeynames[i],
4528                                             sizeof(dns_name_t));
4529                                 zone->masterkeynames[i] = NULL;
4530                         }
4531                 }
4532                 isc_mem_put(zone->mctx, zone->masterkeynames,
4533                             zone->masterscnt * sizeof(dns_name_t *));
4534                 zone->masterkeynames = NULL;
4535         }
4536         if (zone->mastersok != NULL) {
4537                 isc_mem_put(zone->mctx, zone->mastersok,
4538                             zone->masterscnt * sizeof(isc_boolean_t));
4539                 zone->mastersok = NULL;
4540         }
4541         zone->masterscnt = 0;
4542         /*
4543          * If count == 0, don't allocate any space for masters, mastersok or
4544          * keynames so internally, those pointers are NULL if count == 0
4545          */
4546         if (count == 0)
4547                 goto unlock;
4548
4549         /*
4550          * masters must contain count elements!
4551          */
4552         new = isc_mem_get(zone->mctx, count * sizeof(*new));
4553         if (new == NULL) {
4554                 result = ISC_R_NOMEMORY;
4555                 goto unlock;
4556         }
4557         memmove(new, masters, count * sizeof(*new));
4558
4559         /*
4560          * Similarly for mastersok.
4561          */
4562         newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
4563         if (newok == NULL) {
4564                 result = ISC_R_NOMEMORY;
4565                 isc_mem_put(zone->mctx, new, count * sizeof(*new));
4566                 goto unlock;
4567         };
4568         for (i = 0; i < count; i++)
4569                 newok[i] = ISC_FALSE;
4570
4571         /*
4572          * if keynames is non-NULL, it must contain count elements!
4573          */
4574         newname = NULL;
4575         if (keynames != NULL) {
4576                 newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
4577                 if (newname == NULL) {
4578                         result = ISC_R_NOMEMORY;
4579                         isc_mem_put(zone->mctx, new, count * sizeof(*new));
4580                         isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
4581                         goto unlock;
4582                 }
4583                 for (i = 0; i < count; i++)
4584                         newname[i] = NULL;
4585                 for (i = 0; i < count; i++) {
4586                         if (keynames[i] != NULL) {
4587                                 newname[i] = isc_mem_get(zone->mctx,
4588                                                          sizeof(dns_name_t));
4589                                 if (newname[i] == NULL)
4590                                         goto allocfail;
4591                                 dns_name_init(newname[i], NULL);
4592                                 result = dns_name_dup(keynames[i], zone->mctx,
4593                                                       newname[i]);
4594                                 if (result != ISC_R_SUCCESS) {
4595                                 allocfail:
4596                                         for (i = 0; i < count; i++)
4597                                                 if (newname[i] != NULL)
4598                                                         dns_name_free(
4599                                                                newname[i],
4600                                                                zone->mctx);
4601                                         isc_mem_put(zone->mctx, new,
4602                                                     count * sizeof(*new));
4603                                         isc_mem_put(zone->mctx, newok,
4604                                                     count * sizeof(*newok));
4605                                         isc_mem_put(zone->mctx, newname,
4606                                                     count * sizeof(*newname));
4607                                         goto unlock;
4608                                 }
4609                         }
4610                 }
4611         }
4612
4613         /*
4614          * Everything is ok so attach to the zone.
4615          */
4616         zone->curmaster = 0;
4617         zone->masters = new;
4618         zone->mastersok = newok;
4619         zone->masterkeynames = newname;
4620         zone->masterscnt = count;
4621         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
4622
4623  unlock:
4624         UNLOCK_ZONE(zone);
4625         return (result);
4626 }
4627
4628 isc_result_t
4629 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
4630         isc_result_t result = ISC_R_SUCCESS;
4631
4632         REQUIRE(DNS_ZONE_VALID(zone));
4633
4634         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4635         if (zone->db == NULL)
4636                 result = DNS_R_NOTLOADED;
4637         else
4638                 dns_db_attach(zone->db, dpb);
4639         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4640
4641         return (result);
4642 }
4643
4644 void
4645 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
4646         REQUIRE(DNS_ZONE_VALID(zone));
4647         REQUIRE(zone->type == dns_zone_staticstub);
4648
4649         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4650         REQUIRE(zone->db == NULL);
4651         dns_db_attach(db, &zone->db);
4652         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4653 }
4654
4655 /*
4656  * Co-ordinates the starting of routine jobs.
4657  */
4658
4659 void
4660 dns_zone_maintenance(dns_zone_t *zone) {
4661         const char me[] = "dns_zone_maintenance";
4662         isc_time_t now;
4663
4664         REQUIRE(DNS_ZONE_VALID(zone));
4665         ENTER;
4666
4667         LOCK_ZONE(zone);
4668         TIME_NOW(&now);
4669         zone_settimer(zone, &now);
4670         UNLOCK_ZONE(zone);
4671 }
4672
4673 static inline isc_boolean_t
4674 was_dumping(dns_zone_t *zone) {
4675         isc_boolean_t dumping;
4676
4677         REQUIRE(LOCKED_ZONE(zone));
4678
4679         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
4680         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
4681         if (!dumping) {
4682                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
4683                 isc_time_settoepoch(&zone->dumptime);
4684         }
4685         return (dumping);
4686 }
4687
4688 static isc_result_t
4689 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4690                isc_mem_t *mctx, unsigned int maxkeys,
4691                dst_key_t **keys, unsigned int *nkeys)
4692 {
4693         isc_result_t result;
4694         dns_dbnode_t *node = NULL;
4695         const char *directory = dns_zone_getkeydirectory(zone);
4696
4697         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
4698         result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
4699                                           directory, mctx, maxkeys, keys,
4700                                           nkeys);
4701         if (result == ISC_R_NOTFOUND)
4702                 result = ISC_R_SUCCESS;
4703  failure:
4704         if (node != NULL)
4705                 dns_db_detachnode(db, &node);
4706         return (result);
4707 }
4708
4709 static isc_result_t
4710 offline(dns_db_t *db, dns_dbversion_t *ver, zonediff_t *zonediff,
4711         dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
4712 {
4713         isc_result_t result;
4714
4715         if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
4716                 return (ISC_R_SUCCESS);
4717         result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
4718                                name, ttl, rdata);
4719         if (result != ISC_R_SUCCESS)
4720                 return (result);
4721         rdata->flags |= DNS_RDATA_OFFLINE;
4722         result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
4723                                name, ttl, rdata);
4724         zonediff->offline = ISC_TRUE;
4725         return (result);
4726 }
4727
4728 static void
4729 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
4730 {
4731         unsigned int delta;
4732         char timebuf[80];
4733
4734         zone->key_expiry = when;
4735         if (when <= now) {
4736                 dns_zone_log(zone, ISC_LOG_ERROR,
4737                              "DNSKEY RRSIG(s) have expired");
4738                 isc_time_settoepoch(&zone->keywarntime);
4739         } else if (when < now + 7 * 24 * 3600) {
4740                 isc_time_t t;
4741                 isc_time_set(&t, when, 0);
4742                 isc_time_formattimestamp(&t, timebuf, 80);
4743                 dns_zone_log(zone, ISC_LOG_WARNING,
4744                              "DNSKEY RRSIG(s) will expire within 7 days: %s",
4745                              timebuf);
4746                 delta = when - now;
4747                 delta--;                /* loop prevention */
4748                 delta /= 24 * 3600;     /* to whole days */
4749                 delta *= 24 * 3600;     /* to seconds */
4750                 isc_time_set(&zone->keywarntime, when - delta, 0);
4751         }  else {
4752                 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
4753                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4754                 dns_zone_log(zone, ISC_LOG_NOTICE,
4755                              "setting keywarntime to %s", timebuf);
4756         }
4757 }
4758
4759 /*
4760  * Helper function to del_sigs(). We don't want to delete RRSIGs that
4761  * have no new key.
4762  */
4763 static isc_boolean_t
4764 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
4765           isc_boolean_t *warn)
4766 {
4767         unsigned int i = 0;
4768         isc_boolean_t have_ksk = ISC_FALSE, have_zsk = ISC_FALSE;
4769         isc_boolean_t have_pksk = ISC_FALSE, have_pzsk = ISC_FALSE;
4770
4771         for (i = 0; i < nkeys; i++) {
4772                 if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
4773                         continue;
4774                 if (dst_key_isprivate(keys[i])) {
4775                         if (KSK(keys[i]))
4776                                 have_ksk = have_pksk = ISC_TRUE;
4777                         else
4778                                 have_zsk = have_pzsk = ISC_TRUE;
4779                 } else {
4780                         if (KSK(keys[i]))
4781                                 have_ksk = ISC_TRUE;
4782                         else
4783                                 have_zsk = ISC_TRUE;
4784                 }
4785         }
4786
4787         if (have_zsk && have_ksk && !have_pzsk)
4788                 *warn = ISC_TRUE;
4789
4790         /*
4791          * It's okay to delete a signature if there is an active key
4792          * with the same algorithm to replace it.
4793          */
4794         if (have_pksk || have_pzsk)
4795                 return (ISC_TRUE);
4796
4797         /*
4798          * Failing that, it is *not* okay to delete a signature
4799          * if the associated public key is still in the DNSKEY RRset
4800          */
4801         for (i = 0; i < nkeys; i++) {
4802                 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
4803                     (rrsig_ptr->keyid == dst_key_id(keys[i])))
4804                         return (ISC_FALSE);
4805         }
4806
4807         /*
4808          * But if the key is gone, then go ahead.
4809          */
4810         return (ISC_TRUE);
4811 }
4812
4813 /*
4814  * Delete expired RRsigs and any RRsigs we are about to re-sign.
4815  * See also update.c:del_keysigs().
4816  */
4817 static isc_result_t
4818 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
4819          dns_rdatatype_t type, zonediff_t *zonediff, dst_key_t **keys,
4820          unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
4821 {
4822         isc_result_t result;
4823         dns_dbnode_t *node = NULL;
4824         dns_rdataset_t rdataset;
4825         unsigned int i;
4826         dns_rdata_rrsig_t rrsig;
4827         isc_boolean_t found, changed;
4828         isc_int64_t warn = 0, maybe = 0;
4829
4830         dns_rdataset_init(&rdataset);
4831
4832         if (type == dns_rdatatype_nsec3)
4833                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
4834         else
4835                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
4836         if (result == ISC_R_NOTFOUND)
4837                 return (ISC_R_SUCCESS);
4838         if (result != ISC_R_SUCCESS)
4839                 goto failure;
4840         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
4841                                      (isc_stdtime_t) 0, &rdataset, NULL);
4842         dns_db_detachnode(db, &node);
4843
4844         if (result == ISC_R_NOTFOUND) {
4845                 INSIST(!dns_rdataset_isassociated(&rdataset));
4846                 return (ISC_R_SUCCESS);
4847         }
4848         if (result != ISC_R_SUCCESS) {
4849                 INSIST(!dns_rdataset_isassociated(&rdataset));
4850                 goto failure;
4851         }
4852
4853         changed = ISC_FALSE;
4854         for (result = dns_rdataset_first(&rdataset);
4855              result == ISC_R_SUCCESS;
4856              result = dns_rdataset_next(&rdataset)) {
4857                 dns_rdata_t rdata = DNS_RDATA_INIT;
4858
4859                 dns_rdataset_current(&rdataset, &rdata);
4860                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
4861                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4862
4863                 if (type != dns_rdatatype_dnskey) {
4864                         isc_boolean_t warn = ISC_FALSE, deleted = ISC_FALSE;
4865                         if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
4866                                 result = update_one_rr(db, ver, zonediff->diff,
4867                                                DNS_DIFFOP_DELRESIGN, name,
4868                                                rdataset.ttl, &rdata);
4869                                 if (incremental)
4870                                         changed = ISC_TRUE;
4871                                 if (result != ISC_R_SUCCESS)
4872                                         break;
4873                                 deleted = ISC_TRUE;
4874                         }
4875                         if (warn) {
4876                                 /*
4877                                  * At this point, we've got an RRSIG,
4878                                  * which is signed by an inactive key.
4879                                  * An administrator needs to provide a new
4880                                  * key/alg, but until that time, we want to
4881                                  * keep the old RRSIG.  Marking the key as
4882                                  * offline will prevent us spinning waiting
4883                                  * for the private part.
4884                                  */
4885                                 if (incremental && !deleted) {
4886                                         result = offline(db, ver, zonediff,
4887                                                          name, rdataset.ttl,
4888                                                          &rdata);
4889                                         changed = ISC_TRUE;
4890                                         if (result != ISC_R_SUCCESS)
4891                                                 break;
4892                                 }
4893
4894                                 /*
4895                                  * Log the key id and algorithm of
4896                                  * the inactive key with no replacement
4897                                  */
4898                                 if (zone->log_key_expired_timer <= now) {
4899                                         char origin[DNS_NAME_FORMATSIZE];
4900                                         char algbuf[DNS_NAME_FORMATSIZE];
4901                                         dns_name_format(&zone->origin, origin,
4902                                                         sizeof(origin));
4903                                         dns_secalg_format(rrsig.algorithm,
4904                                                           algbuf,
4905                                                           sizeof(algbuf));
4906                                         dns_zone_log(zone, ISC_LOG_WARNING,
4907                                                      "Key %s/%s/%d "
4908                                                      "missing or inactive "
4909                                                      "and has no replacement: "
4910                                                      "retaining signatures.",
4911                                                      origin, algbuf,
4912                                                      rrsig.keyid);
4913                                         zone->log_key_expired_timer = now +
4914                                                                         3600;
4915                                 }
4916                         }
4917                         continue;
4918                 }
4919
4920                 /*
4921                  * RRSIG(DNSKEY) requires special processing.
4922                  */
4923                 found = ISC_FALSE;
4924                 for (i = 0; i < nkeys; i++) {
4925                         if (rrsig.algorithm == dst_key_alg(keys[i]) &&
4926                             rrsig.keyid == dst_key_id(keys[i])) {
4927                                 found = ISC_TRUE;
4928                                 /*
4929                                  * Mark offline RRSIG(DNSKEY).
4930                                  * We want the earliest offline expire time
4931                                  * iff there is a new offline signature.
4932                                  */
4933                                 if (!dst_key_inactive(keys[i]) &&
4934                                     !dst_key_isprivate(keys[i]))
4935                                 {
4936                                         isc_int64_t timeexpire =
4937                                            dns_time64_from32(rrsig.timeexpire);
4938                                         if (warn != 0 && warn > timeexpire)
4939                                                 warn = timeexpire;
4940                                         if (rdata.flags & DNS_RDATA_OFFLINE) {
4941                                                 if (maybe == 0 ||
4942                                                     maybe > timeexpire)
4943                                                         maybe = timeexpire;
4944                                                 break;
4945                                         }
4946                                         if (warn == 0)
4947                                                 warn = maybe;
4948                                         if (warn == 0 || warn > timeexpire)
4949                                                 warn = timeexpire;
4950                                         result = offline(db, ver, zonediff,
4951                                                          name, rdataset.ttl,
4952                                                          &rdata);
4953                                         changed = ISC_TRUE;
4954                                         break;
4955                                 }
4956                                 result = update_one_rr(db, ver, zonediff->diff,
4957                                                        DNS_DIFFOP_DELRESIGN,
4958                                                        name, rdataset.ttl,
4959                                                        &rdata);
4960                                 break;
4961                         }
4962                 }
4963
4964                 /*
4965                  * If there is not a matching DNSKEY then
4966                  * delete the RRSIG.
4967                  */
4968                 if (!found)
4969                         result = update_one_rr(db, ver, zonediff->diff,
4970                                                DNS_DIFFOP_DELRESIGN, name,
4971                                                rdataset.ttl, &rdata);
4972                 if (result != ISC_R_SUCCESS)
4973                         break;
4974         }
4975
4976         if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0)
4977                 dns_db_resigned(db, &rdataset, ver);
4978
4979         dns_rdataset_disassociate(&rdataset);
4980         if (result == ISC_R_NOMORE)
4981                 result = ISC_R_SUCCESS;
4982         if (warn > 0) {
4983 #if defined(STDTIME_ON_32BITS)
4984                 isc_stdtime_t stdwarn = (isc_stdtime_t)warn;
4985                 if (warn == stdwarn)
4986 #endif
4987                         set_key_expiry_warning(zone, (isc_stdtime_t)warn, now);
4988 #if defined(STDTIME_ON_32BITS)
4989                 else
4990                         dns_zone_log(zone, ISC_LOG_ERROR,
4991                                      "key expiry warning time out of range");
4992 #endif
4993         }
4994  failure:
4995         if (node != NULL)
4996                 dns_db_detachnode(db, &node);
4997         return (result);
4998 }
4999
5000 static isc_result_t
5001 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5002          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
5003          unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
5004          isc_stdtime_t expire, isc_boolean_t check_ksk,
5005          isc_boolean_t keyset_kskonly)
5006 {
5007         isc_result_t result;
5008         dns_dbnode_t *node = NULL;
5009         dns_rdataset_t rdataset;
5010         dns_rdata_t sig_rdata = DNS_RDATA_INIT;
5011         unsigned char data[1024]; /* XXX */
5012         isc_buffer_t buffer;
5013         unsigned int i, j;
5014
5015         dns_rdataset_init(&rdataset);
5016         isc_buffer_init(&buffer, data, sizeof(data));
5017
5018         if (type == dns_rdatatype_nsec3)
5019                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5020         else
5021                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
5022         if (result == ISC_R_NOTFOUND)
5023                 return (ISC_R_SUCCESS);
5024         if (result != ISC_R_SUCCESS)
5025                 goto failure;
5026         result = dns_db_findrdataset(db, node, ver, type, 0,
5027                                      (isc_stdtime_t) 0, &rdataset, NULL);
5028         dns_db_detachnode(db, &node);
5029         if (result == ISC_R_NOTFOUND) {
5030                 INSIST(!dns_rdataset_isassociated(&rdataset));
5031                 return (ISC_R_SUCCESS);
5032         }
5033         if (result != ISC_R_SUCCESS) {
5034                 INSIST(!dns_rdataset_isassociated(&rdataset));
5035                 goto failure;
5036         }
5037
5038         for (i = 0; i < nkeys; i++) {
5039                 isc_boolean_t both = ISC_FALSE;
5040
5041                 if (!dst_key_isprivate(keys[i]))
5042                         continue;
5043
5044                 if (check_ksk && !REVOKE(keys[i])) {
5045                         isc_boolean_t have_ksk, have_nonksk;
5046                         if (KSK(keys[i])) {
5047                                 have_ksk = ISC_TRUE;
5048                                 have_nonksk = ISC_FALSE;
5049                         } else {
5050                                 have_ksk = ISC_FALSE;
5051                                 have_nonksk = ISC_TRUE;
5052                         }
5053                         for (j = 0; j < nkeys; j++) {
5054                                 if (j == i || ALG(keys[i]) != ALG(keys[j]))
5055                                         continue;
5056                                 if (REVOKE(keys[j]))
5057                                         continue;
5058                                 if (KSK(keys[j]))
5059                                         have_ksk = ISC_TRUE;
5060                                 else
5061                                         have_nonksk = ISC_TRUE;
5062                                 both = have_ksk && have_nonksk;
5063                                 if (both)
5064                                         break;
5065                         }
5066                 }
5067                 if (both) {
5068                         if (type == dns_rdatatype_dnskey) {
5069                                 if (!KSK(keys[i]) && keyset_kskonly)
5070                                         continue;
5071                         } else if (KSK(keys[i]))
5072                                 continue;
5073                 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
5074                                 continue;
5075
5076                 /* Calculate the signature, creating a RRSIG RDATA. */
5077                 isc_buffer_clear(&buffer);
5078                 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
5079                                       &inception, &expire,
5080                                       mctx, &buffer, &sig_rdata));
5081                 /* Update the database and journal with the RRSIG. */
5082                 /* XXX inefficient - will cause dataset merging */
5083                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
5084                                     name, rdataset.ttl, &sig_rdata));
5085                 dns_rdata_reset(&sig_rdata);
5086                 isc_buffer_init(&buffer, data, sizeof(data));
5087         }
5088
5089  failure:
5090         if (dns_rdataset_isassociated(&rdataset))
5091                 dns_rdataset_disassociate(&rdataset);
5092         if (node != NULL)
5093                 dns_db_detachnode(db, &node);
5094         return (result);
5095 }
5096
5097 static void
5098 zone_resigninc(dns_zone_t *zone) {
5099         const char *me = "zone_resigninc";
5100         dns_db_t *db = NULL;
5101         dns_dbversion_t *version = NULL;
5102         dns_diff_t _sig_diff;
5103         zonediff_t zonediff;
5104         dns_fixedname_t fixed;
5105         dns_name_t *name;
5106         dns_rdataset_t rdataset;
5107         dns_rdatatype_t covers;
5108         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
5109         isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
5110         isc_result_t result;
5111         isc_stdtime_t now, inception, soaexpire, expire, stop;
5112         isc_uint32_t jitter;
5113         unsigned int i;
5114         unsigned int nkeys = 0;
5115         unsigned int resign;
5116
5117         ENTER;
5118
5119         dns_rdataset_init(&rdataset);
5120         dns_fixedname_init(&fixed);
5121         dns_diff_init(zone->mctx, &_sig_diff);
5122         zonediff_init(&zonediff, &_sig_diff);
5123
5124         /*
5125          * Updates are disabled.  Pause for 5 minutes.
5126          */
5127         if (zone->update_disabled) {
5128                 result = ISC_R_FAILURE;
5129                 goto failure;
5130         }
5131
5132         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5133         dns_db_attach(zone->db, &db);
5134         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5135
5136         result = dns_db_newversion(db, &version);
5137         if (result != ISC_R_SUCCESS) {
5138                 dns_zone_log(zone, ISC_LOG_ERROR,
5139                              "zone_resigninc:dns_db_newversion -> %s",
5140                              dns_result_totext(result));
5141                 goto failure;
5142         }
5143
5144         result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
5145                                 zone_keys, &nkeys);
5146         if (result != ISC_R_SUCCESS) {
5147                 dns_zone_log(zone, ISC_LOG_ERROR,
5148                              "zone_resigninc:find_zone_keys -> %s",
5149                              dns_result_totext(result));
5150                 goto failure;
5151         }
5152
5153         isc_stdtime_get(&now);
5154         inception = now - 3600; /* Allow for clock skew. */
5155         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5156         /*
5157          * Spread out signatures over time if they happen to be
5158          * clumped.  We don't do this for each add_sigs() call as
5159          * we still want some clustering to occur.
5160          */
5161         isc_random_get(&jitter);
5162         expire = soaexpire - jitter % 3600;
5163         stop = now + 5;
5164
5165         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5166         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5167
5168         name = dns_fixedname_name(&fixed);
5169         result = dns_db_getsigningtime(db, &rdataset, name);
5170         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
5171                 dns_zone_log(zone, ISC_LOG_ERROR,
5172                              "zone_resigninc:dns_db_getsigningtime -> %s",
5173                              dns_result_totext(result));
5174         }
5175
5176         i = 0;
5177         while (result == ISC_R_SUCCESS) {
5178                 resign = rdataset.resign - zone->sigresigninginterval;
5179                 covers = rdataset.covers;
5180                 dns_rdataset_disassociate(&rdataset);
5181
5182                 /*
5183                  * Stop if we hit the SOA as that means we have walked the
5184                  * entire zone.  The SOA record should always be the most
5185                  * recent signature.
5186                  */
5187                 /* XXXMPA increase number of RRsets signed pre call */
5188                 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
5189                     resign > stop)
5190                         break;
5191
5192                 result = del_sigs(zone, db, version, name, covers, &zonediff,
5193                                   zone_keys, nkeys, now, ISC_TRUE);
5194                 if (result != ISC_R_SUCCESS) {
5195                         dns_zone_log(zone, ISC_LOG_ERROR,
5196                                      "zone_resigninc:del_sigs -> %s",
5197                                      dns_result_totext(result));
5198                         break;
5199                 }
5200
5201                 result = add_sigs(db, version, name, covers, zonediff.diff,
5202                                   zone_keys, nkeys, zone->mctx, inception,
5203                                   expire, check_ksk, keyset_kskonly);
5204                 if (result != ISC_R_SUCCESS) {
5205                         dns_zone_log(zone, ISC_LOG_ERROR,
5206                                      "zone_resigninc:add_sigs -> %s",
5207                                      dns_result_totext(result));
5208                         break;
5209                 }
5210                 result  = dns_db_getsigningtime(db, &rdataset,
5211                                                 dns_fixedname_name(&fixed));
5212                 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
5213                         result = ISC_R_SUCCESS;
5214                         break;
5215                 }
5216                 if (result != ISC_R_SUCCESS)
5217                         dns_zone_log(zone, ISC_LOG_ERROR,
5218                              "zone_resigninc:dns_db_getsigningtime -> %s",
5219                                      dns_result_totext(result));
5220         }
5221
5222         if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
5223                 goto failure;
5224
5225         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5226                           &zonediff, zone_keys, nkeys, now, ISC_TRUE);
5227         if (result != ISC_R_SUCCESS) {
5228                 dns_zone_log(zone, ISC_LOG_ERROR,
5229                              "zone_resigninc:del_sigs -> %s",
5230                              dns_result_totext(result));
5231                 goto failure;
5232         }
5233
5234         /*
5235          * Did we change anything in the zone?
5236          */
5237         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
5238                 /*
5239                  * Commit the changes if any key has been marked as offline.
5240                  */
5241                 if (zonediff.offline)
5242                         dns_db_closeversion(db, &version, ISC_TRUE);
5243                 goto failure;
5244         }
5245
5246         /* Increment SOA serial if we have made changes */
5247         result = increment_soa_serial(db, version, zonediff.diff, zone->mctx);
5248         if (result != ISC_R_SUCCESS) {
5249                 dns_zone_log(zone, ISC_LOG_ERROR,
5250                              "zone_resigninc:increment_soa_serial -> %s",
5251                              dns_result_totext(result));
5252                 goto failure;
5253         }
5254
5255         /*
5256          * Generate maximum life time signatures so that the above loop
5257          * termination is sensible.
5258          */
5259         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5260                           zonediff.diff, zone_keys, nkeys, zone->mctx,
5261                           inception, soaexpire, check_ksk, keyset_kskonly);
5262         if (result != ISC_R_SUCCESS) {
5263                 dns_zone_log(zone, ISC_LOG_ERROR,
5264                              "zone_resigninc:add_sigs -> %s",
5265                              dns_result_totext(result));
5266                 goto failure;
5267         }
5268
5269         /* Write changes to journal file. */
5270         CHECK(zone_journal(zone, zonediff.diff, "zone_resigninc"));
5271
5272         /* Everything has succeeded. Commit the changes. */
5273         dns_db_closeversion(db, &version, ISC_TRUE);
5274
5275  failure:
5276         dns_diff_clear(&_sig_diff);
5277         for (i = 0; i < nkeys; i++)
5278                 dst_key_free(&zone_keys[i]);
5279         if (version != NULL) {
5280                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
5281                 dns_db_detach(&db);
5282         } else if (db != NULL)
5283                 dns_db_detach(&db);
5284         if (result == ISC_R_SUCCESS) {
5285                 set_resigntime(zone);
5286                 LOCK_ZONE(zone);
5287                 zone_needdump(zone, DNS_DUMP_DELAY);
5288                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5289                 UNLOCK_ZONE(zone);
5290         } else {
5291                 /*
5292                  * Something failed.  Retry in 5 minutes.
5293                  */
5294                 isc_interval_t ival;
5295                 isc_interval_set(&ival, 300, 0);
5296                 isc_time_nowplusinterval(&zone->resigntime, &ival);
5297         }
5298 }
5299
5300 static isc_result_t
5301 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
5302             dns_name_t *newname, isc_boolean_t bottom)
5303 {
5304         isc_result_t result;
5305         dns_dbiterator_t *dbit = NULL;
5306         dns_rdatasetiter_t *rdsit = NULL;
5307         dns_dbnode_t *node = NULL;
5308
5309         CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
5310         CHECK(dns_dbiterator_seek(dbit, oldname));
5311         do {
5312                 result = dns_dbiterator_next(dbit);
5313                 if (result == ISC_R_NOMORE)
5314                         CHECK(dns_dbiterator_first(dbit));
5315                 CHECK(dns_dbiterator_current(dbit, &node, newname));
5316                 if (bottom && dns_name_issubdomain(newname, oldname) &&
5317                     !dns_name_equal(newname, oldname)) {
5318                         dns_db_detachnode(db, &node);
5319                         continue;
5320                 }
5321                 /*
5322                  * Is this node empty?
5323                  */
5324                 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
5325                 result = dns_rdatasetiter_first(rdsit);
5326                 dns_db_detachnode(db, &node);
5327                 dns_rdatasetiter_destroy(&rdsit);
5328                 if (result != ISC_R_NOMORE)
5329                         break;
5330         } while (1);
5331  failure:
5332         if (node != NULL)
5333                 dns_db_detachnode(db, &node);
5334         if (dbit != NULL)
5335                 dns_dbiterator_destroy(&dbit);
5336         return (result);
5337 }
5338
5339 static isc_boolean_t
5340 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5341                 dns_rdatatype_t type, dst_key_t *key)
5342 {
5343         isc_result_t result;
5344         dns_rdataset_t rdataset;
5345         dns_rdata_t rdata = DNS_RDATA_INIT;
5346         dns_rdata_rrsig_t rrsig;
5347
5348         dns_rdataset_init(&rdataset);
5349         result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
5350                                      type, 0, &rdataset, NULL);
5351         if (result != ISC_R_SUCCESS) {
5352                 INSIST(!dns_rdataset_isassociated(&rdataset));
5353                 return (ISC_FALSE);
5354         }
5355         for (result = dns_rdataset_first(&rdataset);
5356              result == ISC_R_SUCCESS;
5357              result = dns_rdataset_next(&rdataset)) {
5358                 dns_rdataset_current(&rdataset, &rdata);
5359                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5360                 INSIST(result == ISC_R_SUCCESS);
5361                 if (rrsig.algorithm == dst_key_alg(key) &&
5362                     rrsig.keyid == dst_key_id(key)) {
5363                         dns_rdataset_disassociate(&rdataset);
5364                         return (ISC_TRUE);
5365                 }
5366                 dns_rdata_reset(&rdata);
5367         }
5368         dns_rdataset_disassociate(&rdataset);
5369         return (ISC_FALSE);
5370 }
5371
5372 static isc_result_t
5373 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5374          dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
5375          dns_diff_t *diff)
5376 {
5377         dns_fixedname_t fixed;
5378         dns_name_t *next;
5379         dns_rdata_t rdata = DNS_RDATA_INIT;
5380         isc_result_t result;
5381         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
5382
5383         dns_fixedname_init(&fixed);
5384         next = dns_fixedname_name(&fixed);
5385
5386         CHECK(next_active(db, version, name, next, bottom));
5387         CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
5388                                   &rdata));
5389         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
5390                             &rdata));
5391  failure:
5392         return (result);
5393 }
5394
5395 static isc_result_t
5396 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
5397             dns_dbversion_t *version, isc_boolean_t build_nsec3,
5398             isc_boolean_t build_nsec, dst_key_t *key,
5399             isc_stdtime_t inception, isc_stdtime_t expire,
5400             unsigned int minimum, isc_boolean_t is_ksk,
5401             isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
5402             dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
5403 {
5404         isc_result_t result;
5405         dns_rdatasetiter_t *iterator = NULL;
5406         dns_rdataset_t rdataset;
5407         dns_rdata_t rdata = DNS_RDATA_INIT;
5408         isc_buffer_t buffer;
5409         unsigned char data[1024];
5410         isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
5411                       seen_nsec3, seen_ds;
5412         isc_boolean_t bottom;
5413
5414         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5415         if (result != ISC_R_SUCCESS) {
5416                 if (result == ISC_R_NOTFOUND)
5417                         result = ISC_R_SUCCESS;
5418                 return (result);
5419         }
5420
5421         dns_rdataset_init(&rdataset);
5422         isc_buffer_init(&buffer, data, sizeof(data));
5423         seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
5424         seen_nsec3 = seen_ds = ISC_FALSE;
5425         for (result = dns_rdatasetiter_first(iterator);
5426              result == ISC_R_SUCCESS;
5427              result = dns_rdatasetiter_next(iterator)) {
5428                 dns_rdatasetiter_current(iterator, &rdataset);
5429                 if (rdataset.type == dns_rdatatype_soa)
5430                         seen_soa = ISC_TRUE;
5431                 else if (rdataset.type == dns_rdatatype_ns)
5432                         seen_ns = ISC_TRUE;
5433                 else if (rdataset.type == dns_rdatatype_ds)
5434                         seen_ds = ISC_TRUE;
5435                 else if (rdataset.type == dns_rdatatype_dname)
5436                         seen_dname = ISC_TRUE;
5437                 else if (rdataset.type == dns_rdatatype_nsec)
5438                         seen_nsec = ISC_TRUE;
5439                 else if (rdataset.type == dns_rdatatype_nsec3)
5440                         seen_nsec3 = ISC_TRUE;
5441                 if (rdataset.type != dns_rdatatype_rrsig)
5442                         seen_rr = ISC_TRUE;
5443                 dns_rdataset_disassociate(&rdataset);
5444         }
5445         if (result != ISC_R_NOMORE)
5446                 goto failure;
5447         if (seen_ns && !seen_soa)
5448                 *delegation = ISC_TRUE;
5449         /*
5450          * Going from insecure to NSEC3.
5451          * Don't generate NSEC3 records for NSEC3 records.
5452          */
5453         if (build_nsec3 && !seen_nsec3 && seen_rr) {
5454                 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
5455                 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
5456                                           unsecure, diff));
5457                 (*signatures)--;
5458         }
5459         /*
5460          * Going from insecure to NSEC.
5461          * Don't generate NSEC records for NSEC3 records.
5462          */
5463         if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
5464                 /* Build and add NSEC. */
5465                 bottom = (seen_ns && !seen_soa) || seen_dname;
5466                 /*
5467                  * Build a NSEC record except at the origin.
5468                  */
5469                 if (!dns_name_equal(name, dns_db_origin(db))) {
5470                         CHECK(add_nsec(db, version, name, node, minimum,
5471                                        bottom, diff));
5472                         /* Count a NSEC generation as a signature generation. */
5473                         (*signatures)--;
5474                 }
5475         }
5476         result = dns_rdatasetiter_first(iterator);
5477         while (result == ISC_R_SUCCESS) {
5478                 dns_rdatasetiter_current(iterator, &rdataset);
5479                 if (rdataset.type == dns_rdatatype_soa ||
5480                     rdataset.type == dns_rdatatype_rrsig)
5481                         goto next_rdataset;
5482                 if (rdataset.type == dns_rdatatype_dnskey) {
5483                         if (!is_ksk && keyset_kskonly)
5484                                 goto next_rdataset;
5485                 } else if (is_ksk)
5486                         goto next_rdataset;
5487                 if (*delegation &&
5488                     rdataset.type != dns_rdatatype_ds &&
5489                     rdataset.type != dns_rdatatype_nsec)
5490                         goto next_rdataset;
5491                 if (signed_with_key(db, node, version, rdataset.type, key))
5492                         goto next_rdataset;
5493                 /* Calculate the signature, creating a RRSIG RDATA. */
5494                 isc_buffer_clear(&buffer);
5495                 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
5496                                       &expire, mctx, &buffer, &rdata));
5497                 /* Update the database and journal with the RRSIG. */
5498                 /* XXX inefficient - will cause dataset merging */
5499                 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
5500                                     name, rdataset.ttl, &rdata));
5501                 dns_rdata_reset(&rdata);
5502                 (*signatures)--;
5503  next_rdataset:
5504                 dns_rdataset_disassociate(&rdataset);
5505                 result = dns_rdatasetiter_next(iterator);
5506         }
5507         if (result == ISC_R_NOMORE)
5508                 result = ISC_R_SUCCESS;
5509         if (seen_dname)
5510                 *delegation = ISC_TRUE;
5511  failure:
5512         if (dns_rdataset_isassociated(&rdataset))
5513                 dns_rdataset_disassociate(&rdataset);
5514         if (iterator != NULL)
5515                 dns_rdatasetiter_destroy(&iterator);
5516         return (result);
5517 }
5518
5519 /*
5520  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
5521  */
5522 static isc_result_t
5523 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5524              dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
5525 {
5526         isc_result_t result;
5527         dns_rdataset_t rdataset;
5528         dns_dbnode_t *node = NULL;
5529
5530         CHECK(dns_db_getoriginnode(db, &node));
5531         if (update_only) {
5532                 dns_rdataset_init(&rdataset);
5533                 result = dns_db_findrdataset(db, node, version,
5534                                              dns_rdatatype_nsec,
5535                                              dns_rdatatype_none,
5536                                              0, &rdataset, NULL);
5537                 if (dns_rdataset_isassociated(&rdataset))
5538                         dns_rdataset_disassociate(&rdataset);
5539                 if (result == ISC_R_NOTFOUND)
5540                         goto success;
5541                 if (result != ISC_R_SUCCESS)
5542                         goto failure;
5543         }
5544         CHECK(delete_nsec(db, version, node, name, diff));
5545         CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
5546  success:
5547         result = ISC_R_SUCCESS;
5548  failure:
5549         if (node != NULL)
5550                 dns_db_detachnode(db, &node);
5551         return (result);
5552 }
5553
5554 static isc_result_t
5555 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
5556                   dns_dbversion_t *version, isc_boolean_t build_nsec3,
5557                   dns_ttl_t minimum, dns_diff_t *diff)
5558 {
5559         isc_result_t result;
5560         dns_dbnode_t *node = NULL;
5561         dns_rdataset_t rdataset;
5562         dns_rdata_t rdata = DNS_RDATA_INIT;
5563         unsigned char data[5];
5564         isc_boolean_t seen_done = ISC_FALSE;
5565         isc_boolean_t have_rr = ISC_FALSE;
5566
5567         dns_rdataset_init(&rdataset);
5568         result = dns_db_getoriginnode(signing->db, &node);
5569         if (result != ISC_R_SUCCESS)
5570                 goto failure;
5571
5572         result = dns_db_findrdataset(signing->db, node, version,
5573                                      zone->privatetype, dns_rdatatype_none,
5574                                      0, &rdataset, NULL);
5575         if (result == ISC_R_NOTFOUND) {
5576                 INSIST(!dns_rdataset_isassociated(&rdataset));
5577                 result = ISC_R_SUCCESS;
5578                 goto failure;
5579         }
5580         if (result != ISC_R_SUCCESS) {
5581                 INSIST(!dns_rdataset_isassociated(&rdataset));
5582                 goto failure;
5583         }
5584         for (result = dns_rdataset_first(&rdataset);
5585              result == ISC_R_SUCCESS;
5586              result = dns_rdataset_next(&rdataset)) {
5587                 dns_rdataset_current(&rdataset, &rdata);
5588                 /*
5589                  * If we don't match the algorithm or keyid skip the record.
5590                  */
5591                 if (rdata.length != 5 ||
5592                     rdata.data[0] != signing->algorithm ||
5593                     rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
5594                     rdata.data[2] != (signing->keyid & 0xff)) {
5595                         have_rr = ISC_TRUE;
5596                         dns_rdata_reset(&rdata);
5597                         continue;
5598                 }
5599                 /*
5600                  * We have a match.  If we were signing (!signing->delete)
5601                  * and we already have a record indicating that we have
5602                  * finished signing (rdata.data[4] != 0) then keep it.
5603                  * Otherwise it needs to be deleted as we have removed all
5604                  * the signatures (signing->delete), so any record indicating
5605                  * completion is now out of date, or we have finished signing
5606                  * with the new record so we no longer need to remember that
5607                  * we need to sign the zone with the matching key across a
5608                  * nameserver re-start.
5609                  */
5610                 if (!signing->delete && rdata.data[4] != 0) {
5611                         seen_done = ISC_TRUE;
5612                         have_rr = ISC_TRUE;
5613                 } else
5614                         CHECK(update_one_rr(signing->db, version, diff,
5615                                             DNS_DIFFOP_DEL, &zone->origin,
5616                                             rdataset.ttl, &rdata));
5617                 dns_rdata_reset(&rdata);
5618         }
5619         if (result == ISC_R_NOMORE)
5620                 result = ISC_R_SUCCESS;
5621         if (!signing->delete && !seen_done) {
5622                 /*
5623                  * If we were signing then we need to indicate that we have
5624                  * finished signing the zone with this key.  If it is already
5625                  * there we don't need to add it a second time.
5626                  */
5627                 data[0] = signing->algorithm;
5628                 data[1] = (signing->keyid >> 8) & 0xff;
5629                 data[2] = signing->keyid & 0xff;
5630                 data[3] = 0;
5631                 data[4] = 1;
5632                 rdata.length = sizeof(data);
5633                 rdata.data = data;
5634                 rdata.type = zone->privatetype;
5635                 rdata.rdclass = dns_db_class(signing->db);
5636                 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
5637                                     &zone->origin, rdataset.ttl, &rdata));
5638         } else if (!have_rr) {
5639                 dns_name_t *origin = dns_db_origin(signing->db);
5640                 /*
5641                  * Rebuild the NSEC/NSEC3 record for the origin as we no
5642                  * longer have any private records.
5643                  */
5644                 if (build_nsec3)
5645                         CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
5646                                                   minimum, ISC_FALSE, diff));
5647                 CHECK(updatesecure(signing->db, version, origin, minimum,
5648                                    ISC_TRUE, diff));
5649         }
5650
5651  failure:
5652         if (dns_rdataset_isassociated(&rdataset))
5653                 dns_rdataset_disassociate(&rdataset);
5654         if (node != NULL)
5655                 dns_db_detachnode(signing->db, &node);
5656         return (result);
5657 }
5658
5659 /*
5660  * If 'active' is set then we are not done with the chain yet so only
5661  * delete the nsec3param record which indicates a full chain exists
5662  * (flags == 0).
5663  */
5664 static isc_result_t
5665 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
5666                  isc_boolean_t active, dns_rdatatype_t privatetype,
5667                  dns_diff_t *diff)
5668 {
5669         dns_dbnode_t *node = NULL;
5670         dns_name_t *name = dns_db_origin(db);
5671         dns_rdata_t rdata = DNS_RDATA_INIT;
5672         dns_rdataset_t rdataset;
5673         dns_rdata_nsec3param_t nsec3param;
5674         isc_result_t result;
5675         isc_buffer_t buffer;
5676         unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
5677         dns_ttl_t ttl = 0;
5678
5679         dns_rdataset_init(&rdataset);
5680
5681         result = dns_db_getoriginnode(db, &node);
5682         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5683         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5684                                      0, 0, &rdataset, NULL);
5685         if (result == ISC_R_NOTFOUND)
5686                 goto try_private;
5687         if (result != ISC_R_SUCCESS)
5688                 goto failure;
5689
5690         /*
5691          * Preserve the existing ttl.
5692          */
5693         ttl = rdataset.ttl;
5694
5695         /*
5696          * Delete all NSEC3PARAM records which match that in nsec3chain.
5697          */
5698         for (result = dns_rdataset_first(&rdataset);
5699              result == ISC_R_SUCCESS;
5700              result = dns_rdataset_next(&rdataset)) {
5701
5702                 dns_rdataset_current(&rdataset, &rdata);
5703                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5704
5705                 if (nsec3param.hash != chain->nsec3param.hash ||
5706                     (active && nsec3param.flags != 0) ||
5707                     nsec3param.iterations != chain->nsec3param.iterations ||
5708                     nsec3param.salt_length != chain->nsec3param.salt_length ||
5709                     memcmp(nsec3param.salt, chain->nsec3param.salt,
5710                            nsec3param.salt_length)) {
5711                         dns_rdata_reset(&rdata);
5712                         continue;
5713                 }
5714
5715                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5716                                     name, rdataset.ttl, &rdata));
5717                 dns_rdata_reset(&rdata);
5718         }
5719         if (result != ISC_R_NOMORE)
5720                 goto failure;
5721
5722         dns_rdataset_disassociate(&rdataset);
5723
5724  try_private:
5725
5726         if (active)
5727                 goto add;
5728         /*
5729          * Delete all private records which match that in nsec3chain.
5730          */
5731         result = dns_db_findrdataset(db, node, ver, privatetype,
5732                                      0, 0, &rdataset, NULL);
5733         if (result == ISC_R_NOTFOUND)
5734                 goto add;
5735         if (result != ISC_R_SUCCESS)
5736                 goto failure;
5737
5738         for (result = dns_rdataset_first(&rdataset);
5739              result == ISC_R_SUCCESS;
5740              result = dns_rdataset_next(&rdataset)) {
5741                 dns_rdata_t private = DNS_RDATA_INIT;
5742                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
5743
5744                 dns_rdataset_current(&rdataset, &private);
5745                 if (!dns_nsec3param_fromprivate(&private, &rdata,
5746                                                 buf, sizeof(buf)))
5747                         continue;
5748                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5749
5750                 if (nsec3param.hash != chain->nsec3param.hash ||
5751                     nsec3param.iterations != chain->nsec3param.iterations ||
5752                     nsec3param.salt_length != chain->nsec3param.salt_length ||
5753                     memcmp(nsec3param.salt, chain->nsec3param.salt,
5754                            nsec3param.salt_length)) {
5755                         dns_rdata_reset(&rdata);
5756                         continue;
5757                 }
5758
5759                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5760                                     name, rdataset.ttl, &private));
5761                 dns_rdata_reset(&rdata);
5762         }
5763         if (result != ISC_R_NOMORE)
5764                 goto failure;
5765
5766   add:
5767         if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
5768                 result = ISC_R_SUCCESS;
5769                 goto failure;
5770         }
5771
5772         /*
5773          * Add a NSEC3PARAM record which matches that in nsec3chain but
5774          * with all flags bits cleared.
5775          *
5776          * Note: we do not clear chain->nsec3param.flags as this change
5777          * may be reversed.
5778          */
5779         isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
5780         CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
5781                                    dns_rdatatype_nsec3param,
5782                                    &chain->nsec3param, &buffer));
5783         rdata.data[1] = 0;      /* Clear flag bits. */
5784         CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
5785
5786   failure:
5787         dns_db_detachnode(db, &node);
5788         if (dns_rdataset_isassociated(&rdataset))
5789                 dns_rdataset_disassociate(&rdataset);
5790         return (result);
5791 }
5792
5793 static isc_result_t
5794 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
5795             dns_name_t *name, dns_diff_t *diff)
5796 {
5797         dns_rdataset_t rdataset;
5798         isc_result_t result;
5799
5800         dns_rdataset_init(&rdataset);
5801
5802         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
5803                                      0, 0, &rdataset, NULL);
5804         if (result == ISC_R_NOTFOUND)
5805                 return (ISC_R_SUCCESS);
5806         if (result != ISC_R_SUCCESS)
5807                 return (result);
5808         for (result = dns_rdataset_first(&rdataset);
5809              result == ISC_R_SUCCESS;
5810              result = dns_rdataset_next(&rdataset)) {
5811                 dns_rdata_t rdata = DNS_RDATA_INIT;
5812
5813                 dns_rdataset_current(&rdataset, &rdata);
5814                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
5815                                     rdataset.ttl, &rdata));
5816         }
5817         if (result == ISC_R_NOMORE)
5818                 result = ISC_R_SUCCESS;
5819  failure:
5820         dns_rdataset_disassociate(&rdataset);
5821         return (result);
5822 }
5823
5824 static isc_result_t
5825 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
5826                     dns_name_t *name, const dns_rdata_nsec3param_t *param,
5827                     dns_diff_t *diff)
5828 {
5829         dns_rdataset_t rdataset;
5830         dns_rdata_nsec3_t nsec3;
5831         isc_result_t result;
5832
5833         dns_rdataset_init(&rdataset);
5834         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
5835                                      0, 0, &rdataset, NULL);
5836         if (result == ISC_R_NOTFOUND)
5837                 return (ISC_R_SUCCESS);
5838         if (result != ISC_R_SUCCESS)
5839                 return (result);
5840
5841         for (result = dns_rdataset_first(&rdataset);
5842              result == ISC_R_SUCCESS;
5843              result = dns_rdataset_next(&rdataset)) {
5844                 dns_rdata_t rdata = DNS_RDATA_INIT;
5845
5846                 dns_rdataset_current(&rdataset, &rdata);
5847                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
5848                 if (nsec3.hash != param->hash ||
5849                     nsec3.iterations != param->iterations ||
5850                     nsec3.salt_length != param->salt_length ||
5851                     memcmp(nsec3.salt, param->salt, nsec3.salt_length))
5852                         continue;
5853                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
5854                                     rdataset.ttl, &rdata));
5855         }
5856         if (result == ISC_R_NOMORE)
5857                 result = ISC_R_SUCCESS;
5858  failure:
5859         dns_rdataset_disassociate(&rdataset);
5860         return (result);
5861 }
5862
5863 static isc_result_t
5864 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
5865                 const dns_rdata_nsec3param_t *param,
5866                 isc_boolean_t *answer)
5867 {
5868         dns_dbnode_t *node = NULL;
5869         dns_rdata_t rdata = DNS_RDATA_INIT;
5870         dns_rdata_nsec3param_t myparam;
5871         dns_rdataset_t rdataset;
5872         isc_result_t result;
5873
5874         *answer = ISC_FALSE;
5875
5876         result = dns_db_getoriginnode(db, &node);
5877         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5878
5879         dns_rdataset_init(&rdataset);
5880
5881         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
5882                                      0, 0, &rdataset, NULL);
5883         if (result == ISC_R_SUCCESS) {
5884                 dns_rdataset_disassociate(&rdataset);
5885                 dns_db_detachnode(db, &node);
5886                 return (result);
5887         }
5888         if (result != ISC_R_NOTFOUND) {
5889                 dns_db_detachnode(db, &node);
5890                 return (result);
5891         }
5892
5893         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5894                                      0, 0, &rdataset, NULL);
5895         if (result == ISC_R_NOTFOUND) {
5896                 *answer = ISC_TRUE;
5897                 dns_db_detachnode(db, &node);
5898                 return (ISC_R_SUCCESS);
5899         }
5900         if (result != ISC_R_SUCCESS) {
5901                 dns_db_detachnode(db, &node);
5902                 return (result);
5903         }
5904
5905         for (result = dns_rdataset_first(&rdataset);
5906              result == ISC_R_SUCCESS;
5907              result = dns_rdataset_next(&rdataset)) {
5908                 dns_rdataset_current(&rdataset, &rdata);
5909                 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
5910                 dns_rdata_reset(&rdata);
5911                 /*
5912                  * Ignore any NSEC3PARAM removals.
5913                  */
5914                 if (NSEC3REMOVE(myparam.flags))
5915                         continue;
5916                 /*
5917                  * Ignore the chain that we are in the process of deleting.
5918                  */
5919                 if (myparam.hash == param->hash &&
5920                     myparam.iterations == param->iterations &&
5921                     myparam.salt_length == param->salt_length &&
5922                     !memcmp(myparam.salt, param->salt, myparam.salt_length))
5923                         continue;
5924                 /*
5925                  * Found an active NSEC3 chain.
5926                  */
5927                 break;
5928         }
5929         if (result == ISC_R_NOMORE) {
5930                 *answer = ISC_TRUE;
5931                 result = ISC_R_SUCCESS;
5932         }
5933
5934  failure:
5935         if (dns_rdataset_isassociated(&rdataset))
5936                 dns_rdataset_disassociate(&rdataset);
5937         dns_db_detachnode(db, &node);
5938         return (result);
5939 }
5940
5941 static isc_result_t
5942 update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
5943             dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
5944             isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
5945             isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
5946             zonediff_t *zonediff)
5947 {
5948         dns_difftuple_t *tuple;
5949         isc_result_t result;
5950
5951         for (tuple = ISC_LIST_HEAD(diff->tuples);
5952              tuple != NULL;
5953              tuple = ISC_LIST_HEAD(diff->tuples)) {
5954                 result = del_sigs(zone, db, version, &tuple->name,
5955                                   tuple->rdata.type, zonediff,
5956                                   zone_keys, nkeys, now, ISC_FALSE);
5957                 if (result != ISC_R_SUCCESS) {
5958                         dns_zone_log(zone, ISC_LOG_ERROR,
5959                                      "update_sigs:del_sigs -> %s",
5960                                      dns_result_totext(result));
5961                         return (result);
5962                 }
5963                 result = add_sigs(db, version, &tuple->name,
5964                                   tuple->rdata.type, zonediff->diff,
5965                                   zone_keys, nkeys, zone->mctx, inception,
5966                                   expire, check_ksk, keyset_kskonly);
5967                 if (result != ISC_R_SUCCESS) {
5968                         dns_zone_log(zone, ISC_LOG_ERROR,
5969                                      "update_sigs:add_sigs -> %s",
5970                                      dns_result_totext(result));
5971                         return (result);
5972                 }
5973
5974                 do {
5975                         dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
5976                         while (next != NULL &&
5977                                (tuple->rdata.type != next->rdata.type ||
5978                                 !dns_name_equal(&tuple->name, &next->name)))
5979                                 next = ISC_LIST_NEXT(next, link);
5980                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
5981                         dns_diff_appendminimal(zonediff->diff, &tuple);
5982                         INSIST(tuple == NULL);
5983                         tuple = next;
5984                 } while (tuple != NULL);
5985         }
5986         return (ISC_R_SUCCESS);
5987 }
5988
5989 /*
5990  * Incrementally build and sign a new NSEC3 chain using the parameters
5991  * requested.
5992  */
5993 static void
5994 zone_nsec3chain(dns_zone_t *zone) {
5995         const char *me = "zone_nsec3chain";
5996         dns_db_t *db = NULL;
5997         dns_dbnode_t *node = NULL;
5998         dns_dbversion_t *version = NULL;
5999         dns_diff_t _sig_diff;
6000         dns_diff_t nsec_diff;
6001         dns_diff_t nsec3_diff;
6002         dns_diff_t param_diff;
6003         zonediff_t zonediff;
6004         dns_fixedname_t fixed;
6005         dns_fixedname_t nextfixed;
6006         dns_name_t *name, *nextname;
6007         dns_rdataset_t rdataset;
6008         dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
6009         dns_nsec3chainlist_t cleanup;
6010         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6011         isc_int32_t signatures;
6012         isc_boolean_t check_ksk, keyset_kskonly;
6013         isc_boolean_t delegation;
6014         isc_boolean_t first;
6015         isc_result_t result;
6016         isc_stdtime_t now, inception, soaexpire, expire;
6017         isc_uint32_t jitter;
6018         unsigned int i;
6019         unsigned int nkeys = 0;
6020         isc_uint32_t nodes;
6021         isc_boolean_t unsecure = ISC_FALSE;
6022         isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
6023         isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
6024         dns_rdatasetiter_t *iterator = NULL;
6025         isc_boolean_t buildnsecchain;
6026         isc_boolean_t updatensec = ISC_FALSE;
6027         dns_rdatatype_t privatetype = zone->privatetype;
6028
6029         ENTER;
6030
6031         dns_rdataset_init(&rdataset);
6032         dns_fixedname_init(&fixed);
6033         name = dns_fixedname_name(&fixed);
6034         dns_fixedname_init(&nextfixed);
6035         nextname = dns_fixedname_name(&nextfixed);
6036         dns_diff_init(zone->mctx, &param_diff);
6037         dns_diff_init(zone->mctx, &nsec3_diff);
6038         dns_diff_init(zone->mctx, &nsec_diff);
6039         dns_diff_init(zone->mctx, &_sig_diff);
6040         zonediff_init(&zonediff, &_sig_diff);
6041         ISC_LIST_INIT(cleanup);
6042
6043         /*
6044          * Updates are disabled.  Pause for 5 minutes.
6045          */
6046         if (zone->update_disabled) {
6047                 result = ISC_R_FAILURE;
6048                 goto failure;
6049         }
6050
6051         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6052         dns_db_attach(zone->db, &db);
6053         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6054
6055         result = dns_db_newversion(db, &version);
6056         if (result != ISC_R_SUCCESS) {
6057                 dns_zone_log(zone, ISC_LOG_ERROR,
6058                              "zone_nsec3chain:dns_db_newversion -> %s",
6059                              dns_result_totext(result));
6060                 goto failure;
6061         }
6062
6063         result = find_zone_keys(zone, db, version, zone->mctx,
6064                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
6065         if (result != ISC_R_SUCCESS) {
6066                 dns_zone_log(zone, ISC_LOG_ERROR,
6067                              "zone_nsec3chain:find_zone_keys -> %s",
6068                              dns_result_totext(result));
6069                 goto failure;
6070         }
6071
6072         isc_stdtime_get(&now);
6073         inception = now - 3600; /* Allow for clock skew. */
6074         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6075
6076         /*
6077          * Spread out signatures over time if they happen to be
6078          * clumped.  We don't do this for each add_sigs() call as
6079          * we still want some clustering to occur.
6080          */
6081         isc_random_get(&jitter);
6082         expire = soaexpire - jitter % 3600;
6083
6084         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6085         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6086
6087         /*
6088          * We keep pulling nodes off each iterator in turn until
6089          * we have no more nodes to pull off or we reach the limits
6090          * for this quantum.
6091          */
6092         nodes = zone->nodes;
6093         signatures = zone->signatures;
6094         LOCK_ZONE(zone);
6095         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6096         UNLOCK_ZONE(zone);
6097         first = ISC_TRUE;
6098
6099         if (nsec3chain != NULL)
6100                 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6101         /*
6102          * Generate new NSEC3 chains first.
6103          */
6104         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6105                 LOCK_ZONE(zone);
6106                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6107
6108                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6109                 if (nsec3chain->done || nsec3chain->db != zone->db) {
6110                         ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
6111                         ISC_LIST_APPEND(cleanup, nsec3chain, link);
6112                 }
6113                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6114                 UNLOCK_ZONE(zone);
6115                 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
6116                         goto next_addchain;
6117
6118                 /*
6119                  * Possible future db.
6120                  */
6121                 if (nsec3chain->db != db) {
6122                         goto next_addchain;
6123                 }
6124
6125                 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
6126                         goto next_addchain;
6127
6128                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6129
6130                 if (nsec3chain->delete_nsec) {
6131                         delegation = ISC_FALSE;
6132                         dns_dbiterator_pause(nsec3chain->dbiterator);
6133                         CHECK(delete_nsec(db, version, node, name, &nsec_diff));
6134                         goto next_addnode;
6135                 }
6136                 /*
6137                  * On the first pass we need to check if the current node
6138                  * has not been obscured.
6139                  */
6140                 delegation = ISC_FALSE;
6141                 unsecure = ISC_FALSE;
6142                 if (first) {
6143                         dns_fixedname_t ffound;
6144                         dns_name_t *found;
6145                         dns_fixedname_init(&ffound);
6146                         found = dns_fixedname_name(&ffound);
6147                         result = dns_db_find(db, name, version,
6148                                              dns_rdatatype_soa,
6149                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6150                                              NULL, NULL);
6151                         if ((result == DNS_R_DELEGATION ||
6152                             result == DNS_R_DNAME) &&
6153                             !dns_name_equal(name, found)) {
6154                                 /*
6155                                  * Remember the obscuring name so that
6156                                  * we skip all obscured names.
6157                                  */
6158                                 dns_name_copy(found, name, NULL);
6159                                 delegation = ISC_TRUE;
6160                                 goto next_addnode;
6161                         }
6162                 }
6163
6164                 /*
6165                  * Check to see if this is a bottom of zone node.
6166                  */
6167                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6168                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
6169                         goto next_addnode;
6170                 if (result != ISC_R_SUCCESS)
6171                         goto failure;
6172
6173                 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
6174                         ISC_FALSE;
6175                 for (result = dns_rdatasetiter_first(iterator);
6176                      result == ISC_R_SUCCESS;
6177                      result = dns_rdatasetiter_next(iterator)) {
6178                         dns_rdatasetiter_current(iterator, &rdataset);
6179                         INSIST(rdataset.type != dns_rdatatype_nsec3);
6180                         if (rdataset.type == dns_rdatatype_soa)
6181                                 seen_soa = ISC_TRUE;
6182                         else if (rdataset.type == dns_rdatatype_ns)
6183                                 seen_ns = ISC_TRUE;
6184                         else if (rdataset.type == dns_rdatatype_dname)
6185                                 seen_dname = ISC_TRUE;
6186                         else if (rdataset.type == dns_rdatatype_ds)
6187                                 seen_ds = ISC_TRUE;
6188                         else if (rdataset.type == dns_rdatatype_nsec)
6189                                 seen_nsec = ISC_TRUE;
6190                         dns_rdataset_disassociate(&rdataset);
6191                 }
6192                 dns_rdatasetiter_destroy(&iterator);
6193                 /*
6194                  * Is there a NSEC chain than needs to be cleaned up?
6195                  */
6196                 if (seen_nsec)
6197                         nsec3chain->seen_nsec = ISC_TRUE;
6198                 if (seen_ns && !seen_soa && !seen_ds)
6199                         unsecure = ISC_TRUE;
6200                 if ((seen_ns && !seen_soa) || seen_dname)
6201                         delegation = ISC_TRUE;
6202
6203                 /*
6204                  * Process one node.
6205                  */
6206                 dns_dbiterator_pause(nsec3chain->dbiterator);
6207                 result = dns_nsec3_addnsec3(db, version, name,
6208                                             &nsec3chain->nsec3param,
6209                                             zone->minimum, unsecure,
6210                                             &nsec3_diff);
6211                 if (result != ISC_R_SUCCESS) {
6212                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6213                                      "dns_nsec3_addnsec3 -> %s",
6214                                      dns_result_totext(result));
6215                         goto failure;
6216                 }
6217
6218                 /*
6219                  * Treat each call to dns_nsec3_addnsec3() as if it's cost is
6220                  * two signatures.  Additionally there will, in general, be
6221                  * two signature generated below.
6222                  *
6223                  * If we are only changing the optout flag the cost is half
6224                  * that of the cost of generating a completely new chain.
6225                  */
6226                 signatures -= 4;
6227
6228                 /*
6229                  * Go onto next node.
6230                  */
6231  next_addnode:
6232                 first = ISC_FALSE;
6233                 dns_db_detachnode(db, &node);
6234                 do {
6235                         result = dns_dbiterator_next(nsec3chain->dbiterator);
6236
6237                         if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
6238                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6239                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6240                                                        ISC_FALSE, privatetype,
6241                                                        &param_diff));
6242                                 LOCK_ZONE(zone);
6243                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6244                                                 link);
6245                                 UNLOCK_ZONE(zone);
6246                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6247                                 goto next_addchain;
6248                         }
6249                         if (result == ISC_R_NOMORE) {
6250                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6251                                 if (nsec3chain->seen_nsec) {
6252                                         CHECK(fixup_nsec3param(db, version,
6253                                                                nsec3chain,
6254                                                                ISC_TRUE,
6255                                                                privatetype,
6256                                                                &param_diff));
6257                                         nsec3chain->delete_nsec = ISC_TRUE;
6258                                         goto same_addchain;
6259                                 }
6260                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6261                                                        ISC_FALSE, privatetype,
6262                                                        &param_diff));
6263                                 LOCK_ZONE(zone);
6264                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6265                                                 link);
6266                                 UNLOCK_ZONE(zone);
6267                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6268                                 goto next_addchain;
6269                         } else if (result != ISC_R_SUCCESS) {
6270                                 dns_zone_log(zone, ISC_LOG_ERROR,
6271                                              "zone_nsec3chain:"
6272                                              "dns_dbiterator_next -> %s",
6273                                              dns_result_totext(result));
6274                                 goto failure;
6275                         } else if (delegation) {
6276                                 dns_dbiterator_current(nsec3chain->dbiterator,
6277                                                        &node, nextname);
6278                                 dns_db_detachnode(db, &node);
6279                                 if (!dns_name_issubdomain(nextname, name))
6280                                         break;
6281                         } else
6282                                 break;
6283                 } while (1);
6284                 continue;
6285
6286  same_addchain:
6287                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6288                 first = ISC_TRUE;
6289                 continue;
6290
6291  next_addchain:
6292                 dns_dbiterator_pause(nsec3chain->dbiterator);
6293                 nsec3chain = nextnsec3chain;
6294                 first = ISC_TRUE;
6295                 if (nsec3chain != NULL)
6296                         nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6297         }
6298
6299         /*
6300          * Process removals.
6301          */
6302         LOCK_ZONE(zone);
6303         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6304         UNLOCK_ZONE(zone);
6305         first = ISC_TRUE;
6306         buildnsecchain = ISC_FALSE;
6307         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6308                 LOCK_ZONE(zone);
6309                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6310                 UNLOCK_ZONE(zone);
6311
6312                 if (nsec3chain->db != db)
6313                         goto next_removechain;
6314
6315                 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
6316                         goto next_removechain;
6317
6318                 /*
6319                  * Work out if we need to build a NSEC chain as a consequence
6320                  * of removing this NSEC3 chain.
6321                  */
6322                 if (first && !updatensec &&
6323                     (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0) {
6324                         result = need_nsec_chain(db, version,
6325                                                  &nsec3chain->nsec3param,
6326                                                  &buildnsecchain);
6327                         if (result != ISC_R_SUCCESS) {
6328                                 dns_zone_log(zone, ISC_LOG_ERROR,
6329                                              "zone_nsec3chain:"
6330                                              "need_nsec_chain -> %s",
6331                                              dns_result_totext(result));
6332                                 goto failure;
6333                         }
6334                 }
6335
6336                 if (first)
6337                         dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
6338                                      "buildnsecchain = %u\n", buildnsecchain);
6339
6340                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6341                 delegation = ISC_FALSE;
6342
6343                 if (!buildnsecchain) {
6344                         /*
6345                          * Delete the NSECPARAM record that matches this chain.
6346                          */
6347                         if (first) {
6348                                 result = fixup_nsec3param(db, version,
6349                                                           nsec3chain,
6350                                                           ISC_TRUE, privatetype,
6351                                                           &param_diff);
6352                                 if (result != ISC_R_SUCCESS) {
6353                                         dns_zone_log(zone, ISC_LOG_ERROR,
6354                                                      "zone_nsec3chain:"
6355                                                      "fixup_nsec3param -> %s",
6356                                                      dns_result_totext(result));
6357                                         goto failure;
6358                                 }
6359                         }
6360
6361                         /*
6362                          *  Delete the NSEC3 records.
6363                          */
6364                         result = deletematchingnsec3(db, version, node, name,
6365                                                      &nsec3chain->nsec3param,
6366                                                      &nsec3_diff);
6367                         if (result != ISC_R_SUCCESS) {
6368                                 dns_zone_log(zone, ISC_LOG_ERROR,
6369                                              "zone_nsec3chain:"
6370                                              "deletematchingnsec3 -> %s",
6371                                              dns_result_totext(result));
6372                                 goto failure;
6373                         }
6374                         goto next_removenode;
6375                 }
6376
6377                 if (first) {
6378                         dns_fixedname_t ffound;
6379                         dns_name_t *found;
6380                         dns_fixedname_init(&ffound);
6381                         found = dns_fixedname_name(&ffound);
6382                         result = dns_db_find(db, name, version,
6383                                              dns_rdatatype_soa,
6384                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6385                                              NULL, NULL);
6386                         if ((result == DNS_R_DELEGATION ||
6387                              result == DNS_R_DNAME) &&
6388                             !dns_name_equal(name, found)) {
6389                                 /*
6390                                  * Remember the obscuring name so that
6391                                  * we skip all obscured names.
6392                                  */
6393                                 dns_name_copy(found, name, NULL);
6394                                 delegation = ISC_TRUE;
6395                                 goto next_removenode;
6396                         }
6397                 }
6398
6399                 /*
6400                  * Check to see if this is a bottom of zone node.
6401                  */
6402                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6403                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
6404                         goto next_removenode;
6405                 if (result != ISC_R_SUCCESS)
6406                         goto failure;
6407
6408                 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
6409                         seen_rr = ISC_FALSE;
6410                 for (result = dns_rdatasetiter_first(iterator);
6411                      result == ISC_R_SUCCESS;
6412                      result = dns_rdatasetiter_next(iterator)) {
6413                         dns_rdatasetiter_current(iterator, &rdataset);
6414                         if (rdataset.type == dns_rdatatype_soa)
6415                                 seen_soa = ISC_TRUE;
6416                         else if (rdataset.type == dns_rdatatype_ns)
6417                                 seen_ns = ISC_TRUE;
6418                         else if (rdataset.type == dns_rdatatype_dname)
6419                                 seen_dname = ISC_TRUE;
6420                         else if (rdataset.type == dns_rdatatype_nsec)
6421                                 seen_nsec = ISC_TRUE;
6422                         else if (rdataset.type == dns_rdatatype_nsec3)
6423                                 seen_nsec3 = ISC_TRUE;
6424                         if (rdataset.type != dns_rdatatype_rrsig)
6425                                 seen_rr = ISC_TRUE;
6426                         dns_rdataset_disassociate(&rdataset);
6427                 }
6428                 dns_rdatasetiter_destroy(&iterator);
6429
6430                 if (!seen_rr || seen_nsec3 || seen_nsec)
6431                         goto next_removenode;
6432                 if ((seen_ns && !seen_soa) || seen_dname)
6433                         delegation = ISC_TRUE;
6434
6435                 /*
6436                  * Add a NSEC record except at the origin.
6437                  */
6438                 if (!dns_name_equal(name, dns_db_origin(db))) {
6439                         dns_dbiterator_pause(nsec3chain->dbiterator);
6440                         CHECK(add_nsec(db, version, name, node, zone->minimum,
6441                                        delegation, &nsec_diff));
6442                 }
6443
6444  next_removenode:
6445                 first = ISC_FALSE;
6446                 dns_db_detachnode(db, &node);
6447                 do {
6448                         result = dns_dbiterator_next(nsec3chain->dbiterator);
6449                         if (result == ISC_R_NOMORE && buildnsecchain) {
6450                                 /*
6451                                  * The NSEC chain should now be built.
6452                                  * We can now remove the NSEC3 chain.
6453                                  */
6454                                 updatensec = ISC_TRUE;
6455                                 goto same_removechain;
6456                         }
6457                         if (result == ISC_R_NOMORE) {
6458                                 LOCK_ZONE(zone);
6459                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6460                                                 link);
6461                                 UNLOCK_ZONE(zone);
6462                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6463                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6464                                 result = fixup_nsec3param(db, version,
6465                                                           nsec3chain, ISC_FALSE,
6466                                                           privatetype,
6467                                                           &param_diff);
6468                                 if (result != ISC_R_SUCCESS) {
6469                                         dns_zone_log(zone, ISC_LOG_ERROR,
6470                                                      "zone_nsec3chain:"
6471                                                      "fixup_nsec3param -> %s",
6472                                                      dns_result_totext(result));
6473                                         goto failure;
6474                                 }
6475                                 goto next_removechain;
6476                         } else if (result != ISC_R_SUCCESS) {
6477                                 dns_zone_log(zone, ISC_LOG_ERROR,
6478                                              "zone_nsec3chain:"
6479                                              "dns_dbiterator_next -> %s",
6480                                              dns_result_totext(result));
6481                                 goto failure;
6482                         } else if (delegation) {
6483                                 dns_dbiterator_current(nsec3chain->dbiterator,
6484                                                        &node, nextname);
6485                                 dns_db_detachnode(db, &node);
6486                                 if (!dns_name_issubdomain(nextname, name))
6487                                         break;
6488                         } else
6489                                 break;
6490                 } while (1);
6491                 continue;
6492
6493  same_removechain:
6494                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6495                 buildnsecchain = ISC_FALSE;
6496                 first = ISC_TRUE;
6497                 continue;
6498
6499  next_removechain:
6500                 dns_dbiterator_pause(nsec3chain->dbiterator);
6501                 nsec3chain = nextnsec3chain;
6502                 first = ISC_TRUE;
6503         }
6504
6505         /*
6506          * We may need to update the NSEC/NSEC3 records for the zone apex.
6507          */
6508         if (!ISC_LIST_EMPTY(param_diff.tuples)) {
6509                 isc_boolean_t rebuild_nsec = ISC_FALSE,
6510                               rebuild_nsec3 = ISC_FALSE;
6511                 result = dns_db_getoriginnode(db, &node);
6512                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6513                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6514                 if (result != ISC_R_SUCCESS) {
6515                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6516                                      "dns_db_allrdatasets -> %s",
6517                                      dns_result_totext(result));
6518                         goto failure;
6519                 }
6520                 for (result = dns_rdatasetiter_first(iterator);
6521                      result == ISC_R_SUCCESS;
6522                      result = dns_rdatasetiter_next(iterator)) {
6523                         dns_rdatasetiter_current(iterator, &rdataset);
6524                         if (rdataset.type == dns_rdatatype_nsec)
6525                                 rebuild_nsec = ISC_TRUE;
6526                         if (rdataset.type == dns_rdatatype_nsec3param)
6527                                 rebuild_nsec3 = ISC_TRUE;
6528                         dns_rdataset_disassociate(&rdataset);
6529                 }
6530                 dns_rdatasetiter_destroy(&iterator);
6531                 dns_db_detachnode(db, &node);
6532
6533                 if (rebuild_nsec) {
6534                         if (nsec3chain != NULL)
6535                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6536
6537                         result = updatesecure(db, version, &zone->origin,
6538                                               zone->minimum, ISC_TRUE,
6539                                               &nsec_diff);
6540                         if (result != ISC_R_SUCCESS) {
6541                                 dns_zone_log(zone, ISC_LOG_ERROR,
6542                                              "zone_nsec3chain:"
6543                                              "updatesecure -> %s",
6544                                              dns_result_totext(result));
6545                                 goto failure;
6546                         }
6547                 }
6548
6549                 if (rebuild_nsec3) {
6550                         if (nsec3chain != NULL)
6551                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6552
6553                         result = dns_nsec3_addnsec3s(db, version,
6554                                                      dns_db_origin(db),
6555                                                      zone->minimum, ISC_FALSE,
6556                                                      &nsec3_diff);
6557                         if (result != ISC_R_SUCCESS) {
6558                                 dns_zone_log(zone, ISC_LOG_ERROR,
6559                                              "zone_nsec3chain:"
6560                                              "dns_nsec3_addnsec3s -> %s",
6561                                              dns_result_totext(result));
6562                                 goto failure;
6563                         }
6564                 }
6565         }
6566
6567         if (nsec3chain != NULL)
6568                 dns_dbiterator_pause(nsec3chain->dbiterator);
6569
6570         /*
6571          * Add / update signatures for the NSEC3 records.
6572          */
6573         if (nsec3chain != NULL)
6574                 dns_dbiterator_pause(nsec3chain->dbiterator);
6575         result = update_sigs(&nsec3_diff, db, version, zone_keys,
6576                              nkeys, zone, inception, expire, now,
6577                              check_ksk, keyset_kskonly, &zonediff);
6578         if (result != ISC_R_SUCCESS) {
6579                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6580                              "update_sigs -> %s", dns_result_totext(result));
6581                 goto failure;
6582         }
6583
6584         /*
6585          * We have changed the NSEC3PARAM or private RRsets
6586          * above so we need to update the signatures.
6587          */
6588         result = update_sigs(&param_diff, db, version, zone_keys,
6589                              nkeys, zone, inception, expire, now,
6590                              check_ksk, keyset_kskonly, &zonediff);
6591         if (result != ISC_R_SUCCESS) {
6592                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6593                              "update_sigs -> %s", dns_result_totext(result));
6594                 goto failure;
6595         }
6596
6597         if (updatensec) {
6598                 result = updatesecure(db, version, &zone->origin,
6599                                       zone->minimum, ISC_FALSE, &nsec_diff);
6600                 if (result != ISC_R_SUCCESS) {
6601                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6602                                      "updatesecure -> %s",
6603                                      dns_result_totext(result));
6604                         goto failure;
6605                 }
6606         }
6607
6608         result = update_sigs(&nsec_diff, db, version, zone_keys,
6609                              nkeys, zone, inception, expire, now,
6610                              check_ksk, keyset_kskonly, &zonediff);
6611         if (result != ISC_R_SUCCESS) {
6612                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6613                              "update_sigs -> %s", dns_result_totext(result));
6614                 goto failure;
6615         }
6616
6617         /*
6618          * If we made no effective changes to the zone then we can just
6619          * cleanup otherwise we need to increment the serial.
6620          */
6621         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
6622                 /*
6623                  * No need to call dns_db_closeversion() here as it is
6624                  * called with commit = ISC_TRUE below.
6625                  */
6626                 goto done;
6627         }
6628
6629         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6630                           &zonediff, zone_keys, nkeys, now, ISC_FALSE);
6631         if (result != ISC_R_SUCCESS) {
6632                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6633                              "del_sigs -> %s", dns_result_totext(result));
6634                 goto failure;
6635         }
6636
6637         result = increment_soa_serial(db, version, zonediff.diff, zone->mctx);
6638         if (result != ISC_R_SUCCESS) {
6639                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6640                              "increment_soa_serial -> %s",
6641                              dns_result_totext(result));
6642                 goto failure;
6643         }
6644
6645         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6646                           zonediff.diff, zone_keys, nkeys, zone->mctx,
6647                           inception, soaexpire, check_ksk, keyset_kskonly);
6648         if (result != ISC_R_SUCCESS) {
6649                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6650                              "add_sigs -> %s", dns_result_totext(result));
6651                 goto failure;
6652         }
6653
6654         /* Write changes to journal file. */
6655         CHECK(zone_journal(zone, zonediff.diff, "zone_nsec3chain"));
6656
6657         LOCK_ZONE(zone);
6658         zone_needdump(zone, DNS_DUMP_DELAY);
6659         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6660         UNLOCK_ZONE(zone);
6661
6662  done:
6663         /*
6664          * Pause all iterators so that dns_db_closeversion() can succeed.
6665          */
6666         LOCK_ZONE(zone);
6667         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6668              nsec3chain != NULL;
6669              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6670                 dns_dbiterator_pause(nsec3chain->dbiterator);
6671         UNLOCK_ZONE(zone);
6672
6673         /*
6674          * Everything has succeeded. Commit the changes.
6675          * Unconditionally commit as zonediff.offline not checked above.
6676          */
6677         dns_db_closeversion(db, &version, ISC_TRUE);
6678
6679         /*
6680          * Everything succeeded so we can clean these up now.
6681          */
6682         nsec3chain = ISC_LIST_HEAD(cleanup);
6683         while (nsec3chain != NULL) {
6684                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6685                 dns_db_detach(&nsec3chain->db);
6686                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
6687                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6688                 nsec3chain = ISC_LIST_HEAD(cleanup);
6689         }
6690
6691         set_resigntime(zone);
6692
6693  failure:
6694         if (result != ISC_R_SUCCESS)
6695                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
6696                              dns_result_totext(result));
6697         /*
6698          * On error roll back the current nsec3chain.
6699          */
6700         if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
6701                 if (nsec3chain->done) {
6702                         dns_db_detach(&nsec3chain->db);
6703                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
6704                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6705                 } else {
6706                         result = dns_dbiterator_first(nsec3chain->dbiterator);
6707                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6708                         dns_dbiterator_pause(nsec3chain->dbiterator);
6709                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6710                 }
6711         }
6712
6713         /*
6714          * Rollback the cleanup list.
6715          */
6716         nsec3chain = ISC_LIST_TAIL(cleanup);
6717         while (nsec3chain != NULL) {
6718                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6719                 if (nsec3chain->done) {
6720                         dns_db_detach(&nsec3chain->db);
6721                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
6722                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6723                 } else {
6724                         LOCK_ZONE(zone);
6725                         ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
6726                         UNLOCK_ZONE(zone);
6727                         result = dns_dbiterator_first(nsec3chain->dbiterator);
6728                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6729                         dns_dbiterator_pause(nsec3chain->dbiterator);
6730                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6731                 }
6732                 nsec3chain = ISC_LIST_TAIL(cleanup);
6733         }
6734
6735         LOCK_ZONE(zone);
6736         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6737              nsec3chain != NULL;
6738              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6739                 dns_dbiterator_pause(nsec3chain->dbiterator);
6740         UNLOCK_ZONE(zone);
6741
6742         dns_diff_clear(&param_diff);
6743         dns_diff_clear(&nsec3_diff);
6744         dns_diff_clear(&nsec_diff);
6745         dns_diff_clear(&_sig_diff);
6746
6747         if (iterator != NULL)
6748                 dns_rdatasetiter_destroy(&iterator);
6749
6750         for (i = 0; i < nkeys; i++)
6751                 dst_key_free(&zone_keys[i]);
6752
6753         if (node != NULL)
6754                 dns_db_detachnode(db, &node);
6755         if (version != NULL) {
6756                 dns_db_closeversion(db, &version, ISC_FALSE);
6757                 dns_db_detach(&db);
6758         } else if (db != NULL)
6759                 dns_db_detach(&db);
6760
6761         LOCK_ZONE(zone);
6762         if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
6763                 isc_interval_t i;
6764                 if (zone->update_disabled || result != ISC_R_SUCCESS)
6765                         isc_interval_set(&i, 60, 0);            /* 1 minute */
6766                 else
6767                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
6768                 isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
6769         } else
6770                 isc_time_settoepoch(&zone->nsec3chaintime);
6771         UNLOCK_ZONE(zone);
6772 }
6773
6774 static isc_result_t
6775 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6776         dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
6777         isc_uint16_t keyid, dns_diff_t *diff)
6778 {
6779         dns_rdata_rrsig_t rrsig;
6780         dns_rdataset_t rdataset;
6781         dns_rdatasetiter_t *iterator = NULL;
6782         isc_result_t result;
6783
6784         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6785         if (result != ISC_R_SUCCESS) {
6786                 if (result == ISC_R_NOTFOUND)
6787                         result = ISC_R_SUCCESS;
6788                 return (result);
6789         }
6790
6791         dns_rdataset_init(&rdataset);
6792         for (result = dns_rdatasetiter_first(iterator);
6793              result == ISC_R_SUCCESS;
6794              result = dns_rdatasetiter_next(iterator)) {
6795                 dns_rdatasetiter_current(iterator, &rdataset);
6796                 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
6797                         for (result = dns_rdataset_first(&rdataset);
6798                              result == ISC_R_SUCCESS;
6799                              result = dns_rdataset_next(&rdataset)) {
6800                                 dns_rdata_t rdata = DNS_RDATA_INIT;
6801                                 dns_rdataset_current(&rdataset, &rdata);
6802                                 CHECK(update_one_rr(db, version, diff,
6803                                                     DNS_DIFFOP_DEL, name,
6804                                                     rdataset.ttl, &rdata));
6805                         }
6806                         if (result != ISC_R_NOMORE)
6807                                 goto failure;
6808                         dns_rdataset_disassociate(&rdataset);
6809                         continue;
6810                 }
6811                 if (rdataset.type != dns_rdatatype_rrsig) {
6812                         dns_rdataset_disassociate(&rdataset);
6813                         continue;
6814                 }
6815                 for (result = dns_rdataset_first(&rdataset);
6816                      result == ISC_R_SUCCESS;
6817                      result = dns_rdataset_next(&rdataset)) {
6818                         dns_rdata_t rdata = DNS_RDATA_INIT;
6819                         dns_rdataset_current(&rdataset, &rdata);
6820                         CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
6821                         if (rrsig.algorithm != algorithm ||
6822                             rrsig.keyid != keyid)
6823                                 continue;
6824                         CHECK(update_one_rr(db, version, diff,
6825                                             DNS_DIFFOP_DELRESIGN, name,
6826                                             rdataset.ttl, &rdata));
6827                 }
6828                 dns_rdataset_disassociate(&rdataset);
6829                 if (result != ISC_R_NOMORE)
6830                         break;
6831         }
6832         if (result == ISC_R_NOMORE)
6833                 result = ISC_R_SUCCESS;
6834  failure:
6835         if (dns_rdataset_isassociated(&rdataset))
6836                 dns_rdataset_disassociate(&rdataset);
6837         dns_rdatasetiter_destroy(&iterator);
6838         return (result);
6839 }
6840
6841 /*
6842  * Incrementally sign the zone using the keys requested.
6843  * Builds the NSEC chain if required.
6844  */
6845 static void
6846 zone_sign(dns_zone_t *zone) {
6847         const char *me = "zone_sign";
6848         dns_db_t *db = NULL;
6849         dns_dbnode_t *node = NULL;
6850         dns_dbversion_t *version = NULL;
6851         dns_diff_t _sig_diff;
6852         dns_diff_t post_diff;
6853         zonediff_t zonediff;
6854         dns_fixedname_t fixed;
6855         dns_fixedname_t nextfixed;
6856         dns_name_t *name, *nextname;
6857         dns_rdataset_t rdataset;
6858         dns_signing_t *signing, *nextsigning;
6859         dns_signinglist_t cleanup;
6860         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6861         isc_int32_t signatures;
6862         isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
6863         isc_boolean_t commit = ISC_FALSE;
6864         isc_boolean_t delegation;
6865         isc_boolean_t build_nsec = ISC_FALSE;
6866         isc_boolean_t build_nsec3 = ISC_FALSE;
6867         isc_boolean_t first;
6868         isc_result_t result;
6869         isc_stdtime_t now, inception, soaexpire, expire;
6870         isc_uint32_t jitter;
6871         unsigned int i, j;
6872         unsigned int nkeys = 0;
6873         isc_uint32_t nodes;
6874
6875         ENTER;
6876
6877         dns_rdataset_init(&rdataset);
6878         dns_fixedname_init(&fixed);
6879         name = dns_fixedname_name(&fixed);
6880         dns_fixedname_init(&nextfixed);
6881         nextname = dns_fixedname_name(&nextfixed);
6882         dns_diff_init(zone->mctx, &_sig_diff);
6883         dns_diff_init(zone->mctx, &post_diff);
6884         zonediff_init(&zonediff, &_sig_diff);
6885         ISC_LIST_INIT(cleanup);
6886
6887         /*
6888          * Updates are disabled.  Pause for 5 minutes.
6889          */
6890         if (zone->update_disabled) {
6891                 result = ISC_R_FAILURE;
6892                 goto failure;
6893         }
6894
6895         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6896         dns_db_attach(zone->db, &db);
6897         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6898
6899         result = dns_db_newversion(db, &version);
6900         if (result != ISC_R_SUCCESS) {
6901                 dns_zone_log(zone, ISC_LOG_ERROR,
6902                              "zone_sign:dns_db_newversion -> %s",
6903                              dns_result_totext(result));
6904                 goto failure;
6905         }
6906
6907         result = find_zone_keys(zone, db, version, zone->mctx,
6908                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
6909         if (result != ISC_R_SUCCESS) {
6910                 dns_zone_log(zone, ISC_LOG_ERROR,
6911                              "zone_sign:find_zone_keys -> %s",
6912                              dns_result_totext(result));
6913                 goto failure;
6914         }
6915
6916         isc_stdtime_get(&now);
6917         inception = now - 3600; /* Allow for clock skew. */
6918         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6919
6920         /*
6921          * Spread out signatures over time if they happen to be
6922          * clumped.  We don't do this for each add_sigs() call as
6923          * we still want some clustering to occur.
6924          */
6925         isc_random_get(&jitter);
6926         expire = soaexpire - jitter % 3600;
6927
6928         /*
6929          * We keep pulling nodes off each iterator in turn until
6930          * we have no more nodes to pull off or we reach the limits
6931          * for this quantum.
6932          */
6933         nodes = zone->nodes;
6934         signatures = zone->signatures;
6935         signing = ISC_LIST_HEAD(zone->signing);
6936         first = ISC_TRUE;
6937
6938         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6939         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6940
6941         /* Determine which type of chain to build */
6942         CHECK(dns_private_chains(db, version, zone->privatetype,
6943                                  &build_nsec, &build_nsec3));
6944
6945         /* If neither chain is found, default to NSEC */
6946         if (!build_nsec && !build_nsec3)
6947                 build_nsec = ISC_TRUE;
6948
6949         while (signing != NULL && nodes-- > 0 && signatures > 0) {
6950                 nextsigning = ISC_LIST_NEXT(signing, link);
6951
6952                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6953                 if (signing->done || signing->db != zone->db) {
6954                         /*
6955                          * The zone has been reloaded.  We will have
6956                          * created new signings as part of the reload
6957                          * process so we can destroy this one.
6958                          */
6959                         ISC_LIST_UNLINK(zone->signing, signing, link);
6960                         ISC_LIST_APPEND(cleanup, signing, link);
6961                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6962                         goto next_signing;
6963                 }
6964                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6965
6966                 if (signing->db != db)
6967                         goto next_signing;
6968
6969                 delegation = ISC_FALSE;
6970
6971                 if (first && signing->delete) {
6972                         /*
6973                          * Remove the key we are deleting from consideration.
6974                          */
6975                         for (i = 0, j = 0; i < nkeys; i++) {
6976                                 /*
6977                                  * Find the key we want to remove.
6978                                  */
6979                                 if (ALG(zone_keys[i]) == signing->algorithm &&
6980                                     dst_key_id(zone_keys[i]) == signing->keyid)
6981                                 {
6982                                         if (KSK(zone_keys[i]))
6983                                                 dst_key_free(&zone_keys[i]);
6984                                         continue;
6985                                 }
6986                                 zone_keys[j] = zone_keys[i];
6987                                 j++;
6988                         }
6989                         nkeys = j;
6990                 }
6991
6992                 dns_dbiterator_current(signing->dbiterator, &node, name);
6993
6994                 if (signing->delete) {
6995                         dns_dbiterator_pause(signing->dbiterator);
6996                         CHECK(del_sig(db, version, name, node, nkeys,
6997                                       signing->algorithm, signing->keyid,
6998                                       zonediff.diff));
6999                 }
7000
7001                 /*
7002                  * On the first pass we need to check if the current node
7003                  * has not been obscured.
7004                  */
7005                 if (first) {
7006                         dns_fixedname_t ffound;
7007                         dns_name_t *found;
7008                         dns_fixedname_init(&ffound);
7009                         found = dns_fixedname_name(&ffound);
7010                         result = dns_db_find(db, name, version,
7011                                              dns_rdatatype_soa,
7012                                              DNS_DBFIND_NOWILD, 0, NULL, found,
7013                                              NULL, NULL);
7014                         if ((result == DNS_R_DELEGATION ||
7015                             result == DNS_R_DNAME) &&
7016                             !dns_name_equal(name, found)) {
7017                                 /*
7018                                  * Remember the obscuring name so that
7019                                  * we skip all obscured names.
7020                                  */
7021                                 dns_name_copy(found, name, NULL);
7022                                 delegation = ISC_TRUE;
7023                                 goto next_node;
7024                         }
7025                 }
7026
7027                 /*
7028                  * Process one node.
7029                  */
7030                 dns_dbiterator_pause(signing->dbiterator);
7031                 for (i = 0; i < nkeys; i++) {
7032                         isc_boolean_t both = ISC_FALSE;
7033
7034                         /*
7035                          * Find the keys we want to sign with.
7036                          */
7037                         if (!dst_key_isprivate(zone_keys[i]))
7038                                 continue;
7039
7040                         /*
7041                          * When adding look for the specific key.
7042                          */
7043                         if (!signing->delete &&
7044                             (dst_key_alg(zone_keys[i]) != signing->algorithm ||
7045                              dst_key_id(zone_keys[i]) != signing->keyid))
7046                                 continue;
7047
7048                         /*
7049                          * When deleting make sure we are properly signed
7050                          * with the algorithm that was being removed.
7051                          */
7052                         if (signing->delete &&
7053                             ALG(zone_keys[i]) != signing->algorithm)
7054                                 continue;
7055
7056                         /*
7057                          * Do we do KSK processing?
7058                          */
7059                         if (check_ksk && !REVOKE(zone_keys[i])) {
7060                                 isc_boolean_t have_ksk, have_nonksk;
7061                                 if (KSK(zone_keys[i])) {
7062                                         have_ksk = ISC_TRUE;
7063                                         have_nonksk = ISC_FALSE;
7064                                 } else {
7065                                         have_ksk = ISC_FALSE;
7066                                         have_nonksk = ISC_TRUE;
7067                                 }
7068                                 for (j = 0; j < nkeys; j++) {
7069                                         if (j == i ||
7070                                             ALG(zone_keys[i]) !=
7071                                             ALG(zone_keys[j]))
7072                                                 continue;
7073                                         if (REVOKE(zone_keys[j]))
7074                                                 continue;
7075                                         if (KSK(zone_keys[j]))
7076                                                 have_ksk = ISC_TRUE;
7077                                         else
7078                                                 have_nonksk = ISC_TRUE;
7079                                         both = have_ksk && have_nonksk;
7080                                         if (both)
7081                                                 break;
7082                                 }
7083                         }
7084                         if (both || REVOKE(zone_keys[i]))
7085                                 is_ksk = KSK(zone_keys[i]);
7086                         else
7087                                 is_ksk = ISC_FALSE;
7088
7089                         CHECK(sign_a_node(db, name, node, version, build_nsec3,
7090                                           build_nsec, zone_keys[i], inception,
7091                                           expire, zone->minimum, is_ksk,
7092                                           ISC_TF(both && keyset_kskonly),
7093                                           &delegation, zonediff.diff,
7094                                           &signatures, zone->mctx));
7095                         /*
7096                          * If we are adding we are done.  Look for other keys
7097                          * of the same algorithm if deleting.
7098                          */
7099                         if (!signing->delete)
7100                                 break;
7101                 }
7102
7103                 /*
7104                  * Go onto next node.
7105                  */
7106  next_node:
7107                 first = ISC_FALSE;
7108                 dns_db_detachnode(db, &node);
7109                 do {
7110                         result = dns_dbiterator_next(signing->dbiterator);
7111                         if (result == ISC_R_NOMORE) {
7112                                 ISC_LIST_UNLINK(zone->signing, signing, link);
7113                                 ISC_LIST_APPEND(cleanup, signing, link);
7114                                 dns_dbiterator_pause(signing->dbiterator);
7115                                 if (nkeys != 0 && build_nsec) {
7116                                         /*
7117                                          * We have finished regenerating the
7118                                          * zone with a zone signing key.
7119                                          * The NSEC chain is now complete and
7120                                          * there is a full set of signatures
7121                                          * for the zone.  We can now clear the
7122                                          * OPT bit from the NSEC record.
7123                                          */
7124                                         result = updatesecure(db, version,
7125                                                               &zone->origin,
7126                                                               zone->minimum,
7127                                                               ISC_FALSE,
7128                                                               &post_diff);
7129                                         if (result != ISC_R_SUCCESS) {
7130                                                 dns_zone_log(zone,
7131                                                              ISC_LOG_ERROR,
7132                                                     "updatesecure -> %s",
7133                                                     dns_result_totext(result));
7134                                                 goto failure;
7135                                         }
7136                                 }
7137                                 result = updatesignwithkey(zone, signing,
7138                                                            version,
7139                                                            build_nsec3,
7140                                                            zone->minimum,
7141                                                            &post_diff);
7142                                 if (result != ISC_R_SUCCESS) {
7143                                         dns_zone_log(zone, ISC_LOG_ERROR,
7144                                                      "updatesignwithkey -> %s",
7145                                                      dns_result_totext(result));
7146                                         goto failure;
7147                                 }
7148                                 build_nsec = ISC_FALSE;
7149                                 goto next_signing;
7150                         } else if (result != ISC_R_SUCCESS) {
7151                                 dns_zone_log(zone, ISC_LOG_ERROR,
7152                                         "zone_sign:dns_dbiterator_next -> %s",
7153                                              dns_result_totext(result));
7154                                 goto failure;
7155                         } else if (delegation) {
7156                                 dns_dbiterator_current(signing->dbiterator,
7157                                                        &node, nextname);
7158                                 dns_db_detachnode(db, &node);
7159                                 if (!dns_name_issubdomain(nextname, name))
7160                                         break;
7161                         } else
7162                                 break;
7163                 } while (1);
7164                 continue;
7165
7166  next_signing:
7167                 dns_dbiterator_pause(signing->dbiterator);
7168                 signing = nextsigning;
7169                 first = ISC_TRUE;
7170         }
7171
7172         if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
7173                 result = update_sigs(&post_diff, db, version, zone_keys,
7174                                      nkeys, zone, inception, expire, now,
7175                                      check_ksk, keyset_kskonly, &zonediff);
7176                 if (result != ISC_R_SUCCESS) {
7177                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
7178                                      "update_sigs -> %s",
7179                                      dns_result_totext(result));
7180                         goto failure;
7181                 }
7182         }
7183
7184         /*
7185          * Have we changed anything?
7186          */
7187         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7188                 if (zonediff.offline)
7189                         commit = ISC_TRUE;
7190                 result = ISC_R_SUCCESS;
7191                 goto pauseall;
7192         }
7193
7194         commit = ISC_TRUE;
7195
7196         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7197                           &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7198         if (result != ISC_R_SUCCESS) {
7199                 dns_zone_log(zone, ISC_LOG_ERROR,
7200                              "zone_sign:del_sigs -> %s",
7201                              dns_result_totext(result));
7202                 goto failure;
7203         }
7204
7205         result = increment_soa_serial(db, version, zonediff.diff, zone->mctx);
7206         if (result != ISC_R_SUCCESS) {
7207                 dns_zone_log(zone, ISC_LOG_ERROR,
7208                              "zone_sign:increment_soa_serial -> %s",
7209                              dns_result_totext(result));
7210                 goto failure;
7211         }
7212
7213         /*
7214          * Generate maximum life time signatures so that the above loop
7215          * termination is sensible.
7216          */
7217         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7218                           zonediff.diff, zone_keys, nkeys, zone->mctx,
7219                           inception, soaexpire, check_ksk, keyset_kskonly);
7220         if (result != ISC_R_SUCCESS) {
7221                 dns_zone_log(zone, ISC_LOG_ERROR,
7222                              "zone_sign:add_sigs -> %s",
7223                              dns_result_totext(result));
7224                 goto failure;
7225         }
7226
7227         /*
7228          * Write changes to journal file.
7229          */
7230         CHECK(zone_journal(zone, zonediff.diff, "zone_sign"));
7231
7232  pauseall:
7233         /*
7234          * Pause all iterators so that dns_db_closeversion() can succeed.
7235          */
7236         for (signing = ISC_LIST_HEAD(zone->signing);
7237              signing != NULL;
7238              signing = ISC_LIST_NEXT(signing, link))
7239                 dns_dbiterator_pause(signing->dbiterator);
7240
7241         for (signing = ISC_LIST_HEAD(cleanup);
7242              signing != NULL;
7243              signing = ISC_LIST_NEXT(signing, link))
7244                 dns_dbiterator_pause(signing->dbiterator);
7245
7246         /*
7247          * Everything has succeeded. Commit the changes.
7248          */
7249         dns_db_closeversion(db, &version, commit);
7250
7251         /*
7252          * Everything succeeded so we can clean these up now.
7253          */
7254         signing = ISC_LIST_HEAD(cleanup);
7255         while (signing != NULL) {
7256                 ISC_LIST_UNLINK(cleanup, signing, link);
7257                 dns_db_detach(&signing->db);
7258                 dns_dbiterator_destroy(&signing->dbiterator);
7259                 isc_mem_put(zone->mctx, signing, sizeof *signing);
7260                 signing = ISC_LIST_HEAD(cleanup);
7261         }
7262
7263         set_resigntime(zone);
7264
7265         if (commit) {
7266                 LOCK_ZONE(zone);
7267                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7268                 zone_needdump(zone, DNS_DUMP_DELAY);
7269                 UNLOCK_ZONE(zone);
7270         }
7271
7272  failure:
7273         /*
7274          * Rollback the cleanup list.
7275          */
7276         signing = ISC_LIST_HEAD(cleanup);
7277         while (signing != NULL) {
7278                 ISC_LIST_UNLINK(cleanup, signing, link);
7279                 ISC_LIST_PREPEND(zone->signing, signing, link);
7280                 dns_dbiterator_first(signing->dbiterator);
7281                 dns_dbiterator_pause(signing->dbiterator);
7282                 signing = ISC_LIST_HEAD(cleanup);
7283         }
7284
7285         for (signing = ISC_LIST_HEAD(zone->signing);
7286              signing != NULL;
7287              signing = ISC_LIST_NEXT(signing, link))
7288                 dns_dbiterator_pause(signing->dbiterator);
7289
7290         dns_diff_clear(&_sig_diff);
7291
7292         for (i = 0; i < nkeys; i++)
7293                 dst_key_free(&zone_keys[i]);
7294
7295         if (node != NULL)
7296                 dns_db_detachnode(db, &node);
7297
7298         if (version != NULL) {
7299                 dns_db_closeversion(db, &version, ISC_FALSE);
7300                 dns_db_detach(&db);
7301         } else if (db != NULL)
7302                 dns_db_detach(&db);
7303
7304         if (ISC_LIST_HEAD(zone->signing) != NULL) {
7305                 isc_interval_t i;
7306                 if (zone->update_disabled || result != ISC_R_SUCCESS)
7307                         isc_interval_set(&i, 60, 0);            /* 1 minute */
7308                 else
7309                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
7310                 isc_time_nowplusinterval(&zone->signingtime, &i);
7311         } else
7312                 isc_time_settoepoch(&zone->signingtime);
7313 }
7314
7315 static isc_result_t
7316 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
7317               unsigned char *data, int size) {
7318         dns_rdata_dnskey_t dnskey;
7319         dns_rdata_keydata_t keydata;
7320         isc_buffer_t buf;
7321         isc_result_t result;
7322
7323         dns_rdata_reset(target);
7324         isc_buffer_init(&buf, data, size);
7325
7326         switch (rr->type) {
7327             case dns_rdatatype_dnskey:
7328                 result = dns_rdata_tostruct(rr, &dnskey, NULL);
7329                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7330                 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
7331                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7332                                      &dnskey, &buf);
7333                 break;
7334             case dns_rdatatype_keydata:
7335                 result = dns_rdata_tostruct(rr, &keydata, NULL);
7336                 if (result == ISC_R_UNEXPECTEDEND)
7337                         return (result);
7338                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7339                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
7340                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7341                                      &dnskey, &buf);
7342                 break;
7343             default:
7344                 INSIST(0);
7345         }
7346         return (ISC_R_SUCCESS);
7347 }
7348
7349 /*
7350  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
7351  * a KEYDATA rdataset from the key zone.
7352  *
7353  * 'rr' contains either a DNSKEY record, or a KEYDATA record
7354  *
7355  * After normalizing keys to the same format (DNSKEY, with revoke bit
7356  * cleared), return ISC_TRUE if a key that matches 'rr' is found in
7357  * 'rdset', or ISC_FALSE if not.
7358  */
7359
7360 static isc_boolean_t
7361 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
7362         unsigned char data1[4096], data2[4096];
7363         dns_rdata_t rdata, rdata1, rdata2;
7364         isc_result_t result;
7365
7366         dns_rdata_init(&rdata);
7367         dns_rdata_init(&rdata1);
7368         dns_rdata_init(&rdata2);
7369
7370         result = normalize_key(rr, &rdata1, data1, sizeof(data1));
7371         if (result != ISC_R_SUCCESS)
7372                 return (ISC_FALSE);
7373
7374         for (result = dns_rdataset_first(rdset);
7375              result == ISC_R_SUCCESS;
7376              result = dns_rdataset_next(rdset)) {
7377                 dns_rdata_reset(&rdata);
7378                 dns_rdataset_current(rdset, &rdata);
7379                 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
7380                 if (result != ISC_R_SUCCESS)
7381                         continue;
7382                 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
7383                         return (ISC_TRUE);
7384         }
7385
7386         return (ISC_FALSE);
7387 }
7388
7389 /*
7390  * Calculate the refresh interval for a keydata zone, per
7391  * RFC5011: MAX(1 hr,
7392  *              MIN(15 days,
7393  *                  1/2 * OrigTTL,
7394  *                  1/2 * RRSigExpirationInterval))
7395  * or for retries: MAX(1 hr,
7396  *                     MIN(1 day,
7397  *                         1/10 * OrigTTL,
7398  *                         1/10 * RRSigExpirationInterval))
7399  */
7400 static inline isc_stdtime_t
7401 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
7402         isc_result_t result;
7403         isc_uint32_t t;
7404         dns_rdataset_t *rdset;
7405         dns_rdata_t sigrr = DNS_RDATA_INIT;
7406         dns_rdata_sig_t sig;
7407         isc_stdtime_t now;
7408
7409         isc_stdtime_get(&now);
7410
7411         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7412                 rdset = &kfetch->dnskeysigset;
7413         else
7414                 return (now + HOUR);
7415
7416         result = dns_rdataset_first(rdset);
7417         if (result != ISC_R_SUCCESS)
7418                 return (now + HOUR);
7419
7420         dns_rdataset_current(rdset, &sigrr);
7421         result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7422         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7423
7424         if (!retry) {
7425                 t = sig.originalttl / 2;
7426
7427                 if (isc_serial_gt(sig.timeexpire, now)) {
7428                         isc_uint32_t exp = (sig.timeexpire - now) / 2;
7429                         if (t > exp)
7430                                 t = exp;
7431                 }
7432
7433                 if (t > (15*DAY))
7434                         t = (15*DAY);
7435
7436                 if (t < HOUR)
7437                         t = HOUR;
7438         } else {
7439                 t = sig.originalttl / 10;
7440
7441                 if (isc_serial_gt(sig.timeexpire, now)) {
7442                         isc_uint32_t exp = (sig.timeexpire - now) / 10;
7443                         if (t > exp)
7444                                 t = exp;
7445                 }
7446
7447                 if (t > DAY)
7448                         t = DAY;
7449
7450                 if (t < HOUR)
7451                         t = HOUR;
7452         }
7453
7454         return (now + t);
7455 }
7456
7457 /*
7458  * This routine is called when no changes are needed in a KEYDATA
7459  * record except to simply update the refresh timer.  Caller should
7460  * hold zone lock.
7461  */
7462 static isc_result_t
7463 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
7464 {
7465         isc_result_t result;
7466         isc_buffer_t keyb;
7467         unsigned char key_buf[4096];
7468         dns_rdata_t rdata = DNS_RDATA_INIT;
7469         dns_rdata_keydata_t keydata;
7470         dns_name_t *name;
7471         dns_zone_t *zone = kfetch->zone;
7472         isc_stdtime_t now;
7473
7474         name = dns_fixedname_name(&kfetch->name);
7475         isc_stdtime_get(&now);
7476
7477         for (result = dns_rdataset_first(&kfetch->keydataset);
7478              result == ISC_R_SUCCESS;
7479              result = dns_rdataset_next(&kfetch->keydataset)) {
7480                 dns_rdata_reset(&rdata);
7481                 dns_rdataset_current(&kfetch->keydataset, &rdata);
7482
7483                 /* Delete old version */
7484                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
7485                                     name, 0, &rdata));
7486
7487                 /* Update refresh timer */
7488                 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
7489                 if (result == ISC_R_UNEXPECTEDEND)
7490                         continue;
7491                 if (result != ISC_R_SUCCESS)
7492                         goto failure;
7493                 keydata.refresh = refresh_time(kfetch, ISC_TRUE);
7494                 set_refreshkeytimer(zone, &keydata, now);
7495
7496                 dns_rdata_reset(&rdata);
7497                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7498                 CHECK(dns_rdata_fromstruct(&rdata,
7499                                            zone->rdclass, dns_rdatatype_keydata,
7500                                            &keydata, &keyb));
7501
7502                 /* Insert updated version */
7503                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
7504                                     name, 0, &rdata));
7505         }
7506         result = ISC_R_SUCCESS;
7507   failure:
7508         return (result);
7509 }
7510
7511 /*
7512  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
7513  */
7514 static isc_boolean_t
7515 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
7516         isc_result_t result;
7517         dns_name_t *keyname;
7518         isc_mem_t *mctx;
7519         dns_rdata_t sigrr = DNS_RDATA_INIT;
7520         dns_rdata_t rr = DNS_RDATA_INIT;
7521         dns_rdata_rrsig_t sig;
7522         dns_rdata_dnskey_t dnskey;
7523         dst_key_t *dstkey = NULL;
7524         unsigned char key_buf[4096];
7525         isc_buffer_t keyb;
7526         isc_boolean_t answer = ISC_FALSE;
7527
7528         REQUIRE(kfetch != NULL && keydata != NULL);
7529         REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
7530
7531         keyname = dns_fixedname_name(&kfetch->name);
7532         mctx = kfetch->zone->view->mctx;
7533
7534         /* Generate a key from keydata */
7535         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7536         dns_keydata_todnskey(keydata, &dnskey, NULL);
7537         dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
7538                                      &dnskey, &keyb);
7539         result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
7540         if (result != ISC_R_SUCCESS)
7541                 return (ISC_FALSE);
7542
7543         /* See if that key generated any of the signatures */
7544         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7545              result == ISC_R_SUCCESS;
7546              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7547                 dns_fixedname_t fixed;
7548                 dns_fixedname_init(&fixed);
7549
7550                 dns_rdata_reset(&sigrr);
7551                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7552                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7553                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7554
7555                 if (dst_key_alg(dstkey) == sig.algorithm &&
7556                     (dst_key_id(dstkey) == sig.keyid ||
7557                      dst_key_rid(dstkey) == sig.keyid)) {
7558                         result = dns_dnssec_verify2(keyname,
7559                                             &kfetch->dnskeyset,
7560                                             dstkey, ISC_FALSE, mctx, &sigrr,
7561                                             dns_fixedname_name(&fixed));
7562
7563                         dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
7564                                      "Confirm revoked DNSKEY is self-signed: "
7565                                      "%s", dns_result_totext(result));
7566
7567                         if (result == ISC_R_SUCCESS) {
7568                                 answer = ISC_TRUE;
7569                                 break;
7570                         }
7571                 }
7572         }
7573
7574         dst_key_free(&dstkey);
7575         return (answer);
7576 }
7577
7578 /*
7579  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
7580  * anchors are being managed; scan the keyset, and update the key zone and the
7581  * local trust anchors according to RFC5011.
7582  */
7583 static void
7584 keyfetch_done(isc_task_t *task, isc_event_t *event) {
7585         isc_result_t result, eresult;
7586         dns_fetchevent_t *devent;
7587         dns_keyfetch_t *kfetch;
7588         dns_zone_t *zone;
7589         isc_mem_t *mctx = NULL;
7590         dns_keytable_t *secroots = NULL;
7591         dns_dbversion_t *ver = NULL;
7592         dns_diff_t diff;
7593         isc_boolean_t alldone = ISC_FALSE;
7594         isc_boolean_t commit = ISC_FALSE;
7595         dns_name_t *keyname;
7596         dns_rdata_t sigrr = DNS_RDATA_INIT;
7597         dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
7598         dns_rdata_t keydatarr = DNS_RDATA_INIT;
7599         dns_rdata_rrsig_t sig;
7600         dns_rdata_dnskey_t dnskey;
7601         dns_rdata_keydata_t keydata;
7602         isc_boolean_t initializing;
7603         char namebuf[DNS_NAME_FORMATSIZE];
7604         unsigned char key_buf[4096];
7605         isc_buffer_t keyb;
7606         dst_key_t *dstkey;
7607         isc_stdtime_t now;
7608         int pending = 0;
7609         isc_boolean_t secure;
7610         isc_boolean_t free_needed;
7611
7612         UNUSED(task);
7613         INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
7614         INSIST(event->ev_arg != NULL);
7615
7616         kfetch = event->ev_arg;
7617         zone = kfetch->zone;
7618         isc_mem_attach(zone->mctx, &mctx);
7619         keyname = dns_fixedname_name(&kfetch->name);
7620
7621         devent = (dns_fetchevent_t *) event;
7622         eresult = devent->result;
7623
7624         /* Free resources which are not of interest */
7625         if (devent->node != NULL)
7626                 dns_db_detachnode(devent->db, &devent->node);
7627         if (devent->db != NULL)
7628                 dns_db_detach(&devent->db);
7629         isc_event_free(&event);
7630         dns_resolver_destroyfetch(&kfetch->fetch);
7631
7632         LOCK_ZONE(zone);
7633         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
7634                 goto cleanup;
7635
7636         isc_stdtime_get(&now);
7637         dns_name_format(keyname, namebuf, sizeof(namebuf));
7638
7639         result = dns_view_getsecroots(zone->view, &secroots);
7640         INSIST(result == ISC_R_SUCCESS);
7641
7642         dns_diff_init(mctx, &diff);
7643
7644         CHECK(dns_db_newversion(kfetch->db, &ver));
7645
7646         zone->refreshkeycount--;
7647         alldone = ISC_TF(zone->refreshkeycount == 0);
7648
7649         if (alldone)
7650                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
7651
7652         /* Fetch failed */
7653         if (eresult != ISC_R_SUCCESS ||
7654             !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
7655                 dns_zone_log(zone, ISC_LOG_WARNING,
7656                              "Unable to fetch DNSKEY set "
7657                              "'%s': %s", namebuf, dns_result_totext(eresult));
7658                 CHECK(minimal_update(kfetch, ver, &diff));
7659                 goto done;
7660         }
7661
7662         /* No RRSIGs found */
7663         if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
7664                 dns_zone_log(zone, ISC_LOG_WARNING,
7665                              "No DNSKEY RRSIGs found for "
7666                              "'%s': %s", namebuf, dns_result_totext(eresult));
7667                 CHECK(minimal_update(kfetch, ver, &diff));
7668                 goto done;
7669         }
7670
7671         /*
7672          * Validate the dnskeyset against the current trusted keys.
7673          */
7674         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7675              result == ISC_R_SUCCESS;
7676              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7677                 dns_keynode_t *keynode = NULL;
7678
7679                 dns_rdata_reset(&sigrr);
7680                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7681                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7682                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7683
7684                 result = dns_keytable_find(secroots, keyname, &keynode);
7685                 while (result == ISC_R_SUCCESS) {
7686                         dns_keynode_t *nextnode = NULL;
7687                         dns_fixedname_t fixed;
7688                         dns_fixedname_init(&fixed);
7689
7690                         dstkey = dns_keynode_key(keynode);
7691                         if (dstkey == NULL) /* fail_secure() was called */
7692                                 break;
7693
7694                         if (dst_key_alg(dstkey) == sig.algorithm &&
7695                             dst_key_id(dstkey) == sig.keyid) {
7696                                 result = dns_dnssec_verify2(keyname,
7697                                                     &kfetch->dnskeyset,
7698                                                     dstkey, ISC_FALSE,
7699                                                     zone->view->mctx, &sigrr,
7700                                                     dns_fixedname_name(&fixed));
7701
7702                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
7703                                              "Verifying DNSKEY set for zone "
7704                                              "'%s': %s", namebuf,
7705                                              dns_result_totext(result));
7706
7707                                 if (result == ISC_R_SUCCESS) {
7708                                         kfetch->dnskeyset.trust =
7709                                                 dns_trust_secure;
7710                                         kfetch->dnskeysigset.trust =
7711                                                 dns_trust_secure;
7712                                         dns_keytable_detachkeynode(secroots,
7713                                                                    &keynode);
7714                                         break;
7715                                 }
7716                         }
7717
7718                         result = dns_keytable_nextkeynode(secroots,
7719                                                           keynode, &nextnode);
7720                         dns_keytable_detachkeynode(secroots, &keynode);
7721                         keynode = nextnode;
7722                 }
7723
7724                 if (kfetch->dnskeyset.trust == dns_trust_secure)
7725                         break;
7726         }
7727
7728         /*
7729          * If we were not able to verify the answer using the current
7730          * trusted keys then all we can do is look at any revoked keys.
7731          */
7732         secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
7733
7734         /*
7735          * First scan keydataset to find keys that are not in dnskeyset
7736          *   - Missing keys which are not scheduled for removal,
7737          *     log a warning
7738          *   - Missing keys which are scheduled for removal and
7739          *     the remove hold-down timer has completed should
7740          *     be removed from the key zone
7741          *   - Missing keys whose acceptance timers have not yet
7742          *     completed, log a warning and reset the acceptance
7743          *     timer to 30 days in the future
7744          *   - All keys not being removed have their refresh timers
7745          *     updated
7746          */
7747         initializing = ISC_TRUE;
7748         for (result = dns_rdataset_first(&kfetch->keydataset);
7749              result == ISC_R_SUCCESS;
7750              result = dns_rdataset_next(&kfetch->keydataset)) {
7751                 dns_rdata_reset(&keydatarr);
7752                 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7753                 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7754                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7755
7756                 /*
7757                  * If any keydata record has a nonzero add holddown, then
7758                  * there was a pre-existing trust anchor for this domain;
7759                  * that means we are *not* initializing it and shouldn't
7760                  * automatically trust all the keys we find at the zone apex.
7761                  */
7762                 initializing = initializing && ISC_TF(keydata.addhd == 0);
7763
7764                 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
7765                         isc_boolean_t deletekey = ISC_FALSE;
7766
7767                         if (!secure) {
7768                                 if (now > keydata.removehd)
7769                                         deletekey = ISC_TRUE;
7770                         } else if (now < keydata.addhd) {
7771                                 dns_zone_log(zone, ISC_LOG_WARNING,
7772                                              "Pending key unexpectedly missing "
7773                                              "from %s; restarting acceptance "
7774                                              "timer", namebuf);
7775                                 keydata.addhd = now + MONTH;
7776                                 keydata.refresh = refresh_time(kfetch,
7777                                                                ISC_FALSE);
7778                         } else if (keydata.addhd == 0) {
7779                                 keydata.addhd = now;
7780                         } else if (keydata.removehd == 0) {
7781                                 dns_zone_log(zone, ISC_LOG_WARNING,
7782                                              "Active key unexpectedly missing "
7783                                              "from %s", namebuf);
7784                                 keydata.refresh = now + HOUR;
7785                         } else if (now > keydata.removehd) {
7786                                 deletekey = ISC_TRUE;
7787                         } else {
7788                                 keydata.refresh = refresh_time(kfetch,
7789                                                                ISC_FALSE);
7790                         }
7791
7792                         if  (secure || deletekey) {
7793                                 /* Delete old version */
7794                                 CHECK(update_one_rr(kfetch->db, ver, &diff,
7795                                                     DNS_DIFFOP_DEL, keyname, 0,
7796                                                     &keydatarr));
7797                         }
7798
7799                         if (!secure || deletekey)
7800                                 continue;
7801
7802                         dns_rdata_reset(&keydatarr);
7803                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7804                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7805                                              dns_rdatatype_keydata,
7806                                              &keydata, &keyb);
7807
7808                         /* Insert updated version */
7809                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7810                                             DNS_DIFFOP_ADD, keyname, 0,
7811                                             &keydatarr));
7812
7813                         set_refreshkeytimer(zone, &keydata, now);
7814                 }
7815         }
7816
7817         /*
7818          * Next scan dnskeyset:
7819          *   - If new keys are found (i.e., lacking a match in keydataset)
7820          *     add them to the key zone and set the acceptance timer
7821          *     to 30 days in the future (or to immediately if we've
7822          *     determined that we're initializing the zone for the
7823          *     first time)
7824          *   - Previously-known keys that have been revoked
7825          *     must be scheduled for removal from the key zone (or,
7826          *     if they hadn't been accepted as trust anchors yet
7827          *     anyway, removed at once)
7828          *   - Previously-known unrevoked keys whose acceptance timers
7829          *     have completed are promoted to trust anchors
7830          *   - All keys not being removed have their refresh
7831          *     timers updated
7832          */
7833         for (result = dns_rdataset_first(&kfetch->dnskeyset);
7834              result == ISC_R_SUCCESS;
7835              result = dns_rdataset_next(&kfetch->dnskeyset)) {
7836                 isc_boolean_t revoked = ISC_FALSE;
7837                 isc_boolean_t newkey = ISC_FALSE;
7838                 isc_boolean_t updatekey = ISC_FALSE;
7839                 isc_boolean_t deletekey = ISC_FALSE;
7840                 isc_boolean_t trustkey = ISC_FALSE;
7841
7842                 dns_rdata_reset(&dnskeyrr);
7843                 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
7844                 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7845                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7846
7847                 /* Skip ZSK's */
7848                 if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
7849                         continue;
7850
7851                 revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
7852
7853                 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
7854                         dns_rdata_reset(&keydatarr);
7855                         dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7856                         result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7857                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7858
7859                         if (revoked && revocable(kfetch, &keydata)) {
7860                                 if (keydata.addhd > now) {
7861                                         /*
7862                                          * Key wasn't trusted yet, and now
7863                                          * it's been revoked?  Just remove it
7864                                          */
7865                                         deletekey = ISC_TRUE;
7866                                 } else if (keydata.removehd == 0) {
7867                                         /* Remove from secroots */
7868                                         dns_view_untrust(zone->view, keyname,
7869                                                          &dnskey, mctx);
7870
7871                                         /* If initializing, delete now */
7872                                         if (keydata.addhd == 0)
7873                                                 deletekey = ISC_TRUE;
7874                                         else
7875                                                 keydata.removehd = now + MONTH;
7876                                 } else if (keydata.removehd < now) {
7877                                         /* Scheduled for removal */
7878                                         deletekey = ISC_TRUE;
7879                                 }
7880                         } else if (revoked) {
7881                                 if (secure && keydata.removehd == 0) {
7882                                         dns_zone_log(zone, ISC_LOG_WARNING,
7883                                                      "Active key for zone "
7884                                                      "'%s' is revoked but "
7885                                                      "did not self-sign; "
7886                                                          "ignoring.", namebuf);
7887                                                 continue;
7888                                 }
7889                         } else if (secure) {
7890                                 if (keydata.removehd != 0) {
7891                                         /*
7892                                          * Key isn't revoked--but it
7893                                          * seems it used to be.
7894                                          * Remove it now and add it
7895                                          * back as if it were a fresh key.
7896                                          */
7897                                         deletekey = ISC_TRUE;
7898                                         newkey = ISC_TRUE;
7899                                 } else if (keydata.addhd > now)
7900                                         pending++;
7901                                 else if (keydata.addhd == 0)
7902                                         keydata.addhd = now;
7903
7904                                 if (keydata.addhd <= now)
7905                                         trustkey = ISC_TRUE;
7906                         }
7907
7908                         if (!deletekey && !newkey)
7909                                 updatekey = ISC_TRUE;
7910                 } else if (secure) {
7911                         /*
7912                          * Key wasn't in the key zone but it's
7913                          * revoked now anyway, so just skip it
7914                          */
7915                         if (revoked)
7916                                 continue;
7917
7918                         /* Key wasn't in the key zone: add it */
7919                         newkey = ISC_TRUE;
7920
7921                         if (initializing) {
7922                                 dns_keytag_t tag = 0;
7923                                 CHECK(compute_tag(keyname, &dnskey,
7924                                                   mctx, &tag));
7925                                 dns_zone_log(zone, ISC_LOG_WARNING,
7926                                              "Initializing automatic trust "
7927                                              "anchor management for zone '%s'; "
7928                                              "DNSKEY ID %d is now trusted, "
7929                                              "waiving the normal 30-day "
7930                                              "waiting period.",
7931                                              namebuf, tag);
7932                                 trustkey = ISC_TRUE;
7933                         }
7934                 }
7935
7936                 /* Delete old version */
7937                 if (deletekey || !newkey)
7938                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7939                                             DNS_DIFFOP_DEL, keyname, 0,
7940                                             &keydatarr));
7941
7942                 if (updatekey) {
7943                         /* Set refresh timer */
7944                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
7945                         dns_rdata_reset(&keydatarr);
7946                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7947                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7948                                              dns_rdatatype_keydata,
7949                                              &keydata, &keyb);
7950
7951                         /* Insert updated version */
7952                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7953                                             DNS_DIFFOP_ADD, keyname, 0,
7954                                             &keydatarr));
7955                 } else if (newkey) {
7956                         /* Convert DNSKEY to KEYDATA */
7957                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7958                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7959                         dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
7960                                                NULL);
7961                         keydata.addhd = initializing ? now : now + MONTH;
7962                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
7963                         dns_rdata_reset(&keydatarr);
7964                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7965                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7966                                              dns_rdatatype_keydata,
7967                                              &keydata, &keyb);
7968
7969                         /* Insert into key zone */
7970                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7971                                             DNS_DIFFOP_ADD, keyname, 0,
7972                                             &keydatarr));
7973                 }
7974
7975                 if (trustkey) {
7976                         /* Trust this key. */
7977                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7978                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7979                         trust_key(zone, keyname, &dnskey, mctx);
7980                 }
7981
7982                 if (!deletekey)
7983                         set_refreshkeytimer(zone, &keydata, now);
7984         }
7985
7986         /*
7987          * RFC5011 says, "A trust point that has all of its trust anchors
7988          * revoked is considered deleted and is treated as if the trust
7989          * point was never configured."  But if someone revoked their
7990          * active key before the standby was trusted, that would mean the
7991          * zone would suddenly be nonsecured.  We avoid this by checking to
7992          * see if there's pending keydata.  If so, we put a null key in
7993          * the security roots; then all queries to the zone will fail.
7994          */
7995         if (pending != 0)
7996                 fail_secure(zone, keyname);
7997
7998  done:
7999
8000         if (!ISC_LIST_EMPTY(diff.tuples)) {
8001                 /* Write changes to journal file. */
8002                 CHECK(increment_soa_serial(kfetch->db, ver, &diff, mctx));
8003                 CHECK(zone_journal(zone, &diff, "keyfetch_done"));
8004                 commit = ISC_TRUE;
8005
8006                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8007                 zone_needdump(zone, 30);
8008         }
8009
8010   failure:
8011
8012         dns_diff_clear(&diff);
8013         if (ver != NULL)
8014                 dns_db_closeversion(kfetch->db, &ver, commit);
8015
8016  cleanup:
8017         dns_db_detach(&kfetch->db);
8018
8019         INSIST(zone->irefs > 0);
8020         zone->irefs--;
8021         kfetch->zone = NULL;
8022
8023         if (dns_rdataset_isassociated(&kfetch->keydataset))
8024                 dns_rdataset_disassociate(&kfetch->keydataset);
8025         if (dns_rdataset_isassociated(&kfetch->dnskeyset))
8026                 dns_rdataset_disassociate(&kfetch->dnskeyset);
8027         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8028                 dns_rdataset_disassociate(&kfetch->dnskeysigset);
8029
8030         dns_name_free(keyname, mctx);
8031         isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
8032         isc_mem_detach(&mctx);
8033
8034         if (secroots != NULL)
8035                 dns_keytable_detach(&secroots);
8036
8037         free_needed = exit_check(zone);
8038         UNLOCK_ZONE(zone);
8039         if (free_needed)
8040                 zone_free(zone);
8041 }
8042
8043 /*
8044  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
8045  * records from the zone apex.
8046  */
8047 static void
8048 zone_refreshkeys(dns_zone_t *zone) {
8049         const char me[] = "zone_refreshkeys";
8050         isc_result_t result;
8051         dns_rriterator_t rrit;
8052         dns_db_t *db = NULL;
8053         dns_dbversion_t *ver = NULL;
8054         dns_diff_t diff;
8055         dns_rdata_t rdata = DNS_RDATA_INIT;
8056         dns_rdata_keydata_t kd;
8057         isc_stdtime_t now;
8058         isc_boolean_t commit = ISC_FALSE;
8059         isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
8060
8061         ENTER;
8062         REQUIRE(zone->db != NULL);
8063
8064         isc_stdtime_get(&now);
8065
8066         LOCK_ZONE(zone);
8067         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
8068                 isc_time_settoepoch(&zone->refreshkeytime);
8069                 UNLOCK_ZONE(zone);
8070                 return;
8071         }
8072
8073         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8074         dns_db_attach(zone->db, &db);
8075         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8076
8077         dns_diff_init(zone->mctx, &diff);
8078
8079         CHECK(dns_db_newversion(db, &ver));
8080
8081         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
8082
8083         dns_rriterator_init(&rrit, db, ver, 0);
8084         for (result = dns_rriterator_first(&rrit);
8085              result == ISC_R_SUCCESS;
8086              result = dns_rriterator_nextrrset(&rrit)) {
8087                 isc_stdtime_t timer = 0xffffffff;
8088                 dns_name_t *name = NULL, *kname = NULL;
8089                 dns_rdataset_t *kdset = NULL;
8090                 dns_keyfetch_t *kfetch;
8091                 isc_uint32_t ttl;
8092
8093                 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
8094                 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
8095                     !dns_rdataset_isassociated(kdset))
8096                         continue;
8097
8098                 /*
8099                  * Scan the stored keys looking for ones that need
8100                  * removal or refreshing
8101                  */
8102                 for (result = dns_rdataset_first(kdset);
8103                      result == ISC_R_SUCCESS;
8104                      result = dns_rdataset_next(kdset)) {
8105                         dns_rdata_reset(&rdata);
8106                         dns_rdataset_current(kdset, &rdata);
8107                         result = dns_rdata_tostruct(&rdata, &kd, NULL);
8108                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8109
8110                         /* Removal timer expired? */
8111                         if (kd.removehd != 0 && kd.removehd < now) {
8112                                 CHECK(update_one_rr(db, ver, &diff,
8113                                                     DNS_DIFFOP_DEL, name, ttl,
8114                                                     &rdata));
8115                                 continue;
8116                         }
8117
8118                         /* Acceptance timer expired? */
8119                         if (kd.addhd != 0 && kd.addhd < now)
8120                                 timer = kd.addhd;
8121
8122                         /* Or do we just need to refresh the keyset? */
8123                         if (timer > kd.refresh)
8124                                 timer = kd.refresh;
8125                 }
8126
8127                 if (timer > now)
8128                         continue;
8129
8130                 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
8131                 if (kfetch == NULL) {
8132                         fetch_err = ISC_TRUE;
8133                         goto failure;
8134                 }
8135
8136                 zone->refreshkeycount++;
8137                 kfetch->zone = zone;
8138                 zone->irefs++;
8139                 INSIST(zone->irefs != 0);
8140                 dns_fixedname_init(&kfetch->name);
8141                 kname = dns_fixedname_name(&kfetch->name);
8142                 dns_name_dup(name, zone->mctx, kname);
8143                 dns_rdataset_init(&kfetch->dnskeyset);
8144                 dns_rdataset_init(&kfetch->dnskeysigset);
8145                 dns_rdataset_init(&kfetch->keydataset);
8146                 dns_rdataset_clone(kdset, &kfetch->keydataset);
8147                 kfetch->db = NULL;
8148                 dns_db_attach(db, &kfetch->db);
8149                 kfetch->fetch = NULL;
8150
8151                 result = dns_resolver_createfetch(zone->view->resolver,
8152                                                   kname, dns_rdatatype_dnskey,
8153                                                   NULL, NULL, NULL,
8154                                                   DNS_FETCHOPT_NOVALIDATE,
8155                                                   zone->task,
8156                                                   keyfetch_done, kfetch,
8157                                                   &kfetch->dnskeyset,
8158                                                   &kfetch->dnskeysigset,
8159                                                   &kfetch->fetch);
8160                 if (result == ISC_R_SUCCESS)
8161                         fetching = ISC_TRUE;
8162                 else {
8163                         zone->refreshkeycount--;
8164                         zone->irefs--;
8165                         dns_db_detach(&kfetch->db);
8166                         dns_rdataset_disassociate(&kfetch->keydataset);
8167                         dns_name_free(kname, zone->mctx);
8168                         isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
8169                         dns_zone_log(zone, ISC_LOG_WARNING,
8170                                      "Failed to create fetch for "
8171                                      "DNSKEY update");
8172                         fetch_err = ISC_TRUE;
8173                 }
8174         }
8175         if (!ISC_LIST_EMPTY(diff.tuples)) {
8176                 CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
8177                 CHECK(zone_journal(zone, &diff, "zone_refreshkeys"));
8178                 commit = ISC_TRUE;
8179                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8180                 zone_needdump(zone, 30);
8181         }
8182
8183   failure:
8184         if (fetch_err) {
8185                 /*
8186                  * Error during a key fetch; retry in an hour.
8187                  */
8188                 isc_time_t timenow, timethen;
8189                 char timebuf[80];
8190
8191                 TIME_NOW(&timenow);
8192                 DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
8193                 zone->refreshkeytime = timethen;
8194                 zone_settimer(zone, &timenow);
8195
8196                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
8197                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
8198                              timebuf);
8199
8200                 if (!fetching)
8201                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8202         }
8203
8204         UNLOCK_ZONE(zone);
8205
8206         dns_diff_clear(&diff);
8207         if (ver != NULL) {
8208                 dns_rriterator_destroy(&rrit);
8209                 dns_db_closeversion(db, &ver, commit);
8210         }
8211         dns_db_detach(&db);
8212 }
8213
8214 static void
8215 zone_maintenance(dns_zone_t *zone) {
8216         const char me[] = "zone_maintenance";
8217         isc_time_t now;
8218         isc_result_t result;
8219         isc_boolean_t dumping;
8220
8221         REQUIRE(DNS_ZONE_VALID(zone));
8222         ENTER;
8223
8224         /*
8225          * Configuring the view of this zone may have
8226          * failed, for example because the config file
8227          * had a syntax error.  In that case, the view
8228          * db or resolver will be NULL, and we had better not try
8229          * to do maintenance on it.
8230          */
8231         if (zone->view == NULL || zone->view->adb == NULL)
8232                 return;
8233
8234         TIME_NOW(&now);
8235
8236         /*
8237          * Expire check.
8238          */
8239         switch (zone->type) {
8240         case dns_zone_slave:
8241         case dns_zone_stub:
8242                 LOCK_ZONE(zone);
8243                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
8244                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8245                         zone_expire(zone);
8246                         zone->refreshtime = now;
8247                 }
8248                 UNLOCK_ZONE(zone);
8249                 break;
8250         default:
8251                 break;
8252         }
8253
8254         /*
8255          * Up to date check.
8256          */
8257         switch (zone->type) {
8258         case dns_zone_slave:
8259         case dns_zone_stub:
8260                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8261                     isc_time_compare(&now, &zone->refreshtime) >= 0)
8262                         dns_zone_refresh(zone);
8263                 break;
8264         default:
8265                 break;
8266         }
8267
8268         /*
8269          * Slaves send notifies before backing up to disk, masters after.
8270          */
8271         if (zone->type == dns_zone_slave &&
8272             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8273             isc_time_compare(&now, &zone->notifytime) >= 0)
8274                 zone_notify(zone, &now);
8275
8276         /*
8277          * Do we need to consolidate the backing store?
8278          */
8279         switch (zone->type) {
8280         case dns_zone_master:
8281         case dns_zone_slave:
8282         case dns_zone_key:
8283         case dns_zone_stub:
8284                 LOCK_ZONE(zone);
8285                 if (zone->masterfile != NULL &&
8286                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
8287                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8288                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
8289                         dumping = was_dumping(zone);
8290                 } else
8291                         dumping = ISC_TRUE;
8292                 UNLOCK_ZONE(zone);
8293                 if (!dumping) {
8294                         result = zone_dump(zone, ISC_TRUE); /* task locked */
8295                         if (result != ISC_R_SUCCESS)
8296                                 dns_zone_log(zone, ISC_LOG_WARNING,
8297                                              "dump failed: %s",
8298                                              dns_result_totext(result));
8299                 }
8300                 break;
8301         default:
8302                 break;
8303         }
8304
8305         /*
8306          * Master/redirect zones send notifies now, if needed
8307          */
8308         switch (zone->type) {
8309         case dns_zone_master:
8310                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8311                     isc_time_compare(&now, &zone->notifytime) >= 0)
8312                         zone_notify(zone, &now);
8313         default:
8314                 break;
8315         }
8316
8317         /*
8318          * Do we need to refresh keys?
8319          */
8320         switch (zone->type) {
8321         case dns_zone_key:
8322                 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
8323                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8324                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
8325                                 zone_refreshkeys(zone);
8326                         }
8327                 }
8328                 break;
8329         case dns_zone_master:
8330                 if (!isc_time_isepoch(&zone->refreshkeytime) &&
8331                     isc_time_compare(&now, &zone->refreshkeytime) >= 0)
8332                         zone_rekey(zone);
8333         default:
8334                 break;
8335         }
8336
8337         switch (zone->type) {
8338         case dns_zone_master:
8339         case dns_zone_slave:
8340                 /*
8341                  * Do we need to sign/resign some RRsets?
8342                  */
8343                 if (!isc_time_isepoch(&zone->signingtime) &&
8344                     isc_time_compare(&now, &zone->signingtime) >= 0)
8345                         zone_sign(zone);
8346                 else if (!isc_time_isepoch(&zone->resigntime) &&
8347                     isc_time_compare(&now, &zone->resigntime) >= 0)
8348                         zone_resigninc(zone);
8349                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
8350                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
8351                         zone_nsec3chain(zone);
8352                 /*
8353                  * Do we need to issue a key expiry warning?
8354                  */
8355                 if (!isc_time_isepoch(&zone->keywarntime) &&
8356                     isc_time_compare(&now, &zone->keywarntime) >= 0)
8357                         set_key_expiry_warning(zone, zone->key_expiry,
8358                                                isc_time_seconds(&now));
8359                 break;
8360         default:
8361                 break;
8362         }
8363         zone_settimer(zone, &now);
8364 }
8365
8366 void
8367 dns_zone_markdirty(dns_zone_t *zone) {
8368
8369         LOCK_ZONE(zone);
8370         if (zone->type == dns_zone_master)
8371                 set_resigntime(zone);   /* XXXMPA make separate call back */
8372         zone_needdump(zone, DNS_DUMP_DELAY);
8373         UNLOCK_ZONE(zone);
8374 }
8375
8376 void
8377 dns_zone_expire(dns_zone_t *zone) {
8378         REQUIRE(DNS_ZONE_VALID(zone));
8379
8380         LOCK_ZONE(zone);
8381         zone_expire(zone);
8382         UNLOCK_ZONE(zone);
8383 }
8384
8385 static void
8386 zone_expire(dns_zone_t *zone) {
8387         /*
8388          * 'zone' locked by caller.
8389          */
8390
8391         REQUIRE(LOCKED_ZONE(zone));
8392
8393         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
8394
8395         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
8396         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
8397         zone->retry = DNS_ZONE_DEFAULTRETRY;
8398         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
8399         zone_unload(zone);
8400 }
8401
8402 void
8403 dns_zone_refresh(dns_zone_t *zone) {
8404         isc_interval_t i;
8405         isc_uint32_t oldflags;
8406         unsigned int j;
8407         isc_result_t result;
8408
8409         REQUIRE(DNS_ZONE_VALID(zone));
8410
8411         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
8412                 return;
8413
8414         /*
8415          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
8416          * in progress at a time.
8417          */
8418
8419         LOCK_ZONE(zone);
8420         oldflags = zone->flags;
8421         if (zone->masterscnt == 0) {
8422                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
8423                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
8424                         dns_zone_log(zone, ISC_LOG_ERROR,
8425                                      "cannot refresh: no masters");
8426                 goto unlock;
8427         }
8428         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
8429         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
8430         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
8431         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
8432                 goto unlock;
8433
8434         /*
8435          * Set the next refresh time as if refresh check has failed.
8436          * Setting this to the retry time will do that.  XXXMLG
8437          * If we are successful it will be reset using zone->refresh.
8438          */
8439         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
8440                          0);
8441         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
8442         if (result != ISC_R_SUCCESS)
8443                 dns_zone_log(zone, ISC_LOG_WARNING,
8444                              "isc_time_nowplusinterval() failed: %s",
8445                              dns_result_totext(result));
8446
8447         /*
8448          * When lacking user-specified timer values from the SOA,
8449          * do exponential backoff of the retry time up to a
8450          * maximum of six hours.
8451          */
8452         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
8453                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
8454
8455         zone->curmaster = 0;
8456         for (j = 0; j < zone->masterscnt; j++)
8457                 zone->mastersok[j] = ISC_FALSE;
8458         /* initiate soa query */
8459         queue_soa_query(zone);
8460  unlock:
8461         UNLOCK_ZONE(zone);
8462 }
8463
8464 isc_result_t
8465 dns_zone_flush(dns_zone_t *zone) {
8466         isc_result_t result = ISC_R_SUCCESS;
8467         isc_boolean_t dumping;
8468
8469         REQUIRE(DNS_ZONE_VALID(zone));
8470
8471         LOCK_ZONE(zone);
8472         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
8473         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8474             zone->masterfile != NULL) {
8475                 result = ISC_R_ALREADYRUNNING;
8476                 dumping = was_dumping(zone);
8477         } else
8478                 dumping = ISC_TRUE;
8479         UNLOCK_ZONE(zone);
8480         if (!dumping)
8481                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
8482         return (result);
8483 }
8484
8485 isc_result_t
8486 dns_zone_dump(dns_zone_t *zone) {
8487         isc_result_t result = ISC_R_ALREADYRUNNING;
8488         isc_boolean_t dumping;
8489
8490         REQUIRE(DNS_ZONE_VALID(zone));
8491
8492         LOCK_ZONE(zone);
8493         dumping = was_dumping(zone);
8494         UNLOCK_ZONE(zone);
8495         if (!dumping)
8496                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
8497         return (result);
8498 }
8499
8500 static void
8501 zone_needdump(dns_zone_t *zone, unsigned int delay) {
8502         const char me[] = "zone_needdump";
8503         isc_time_t dumptime;
8504         isc_time_t now;
8505
8506         /*
8507          * 'zone' locked by caller
8508          */
8509
8510         REQUIRE(DNS_ZONE_VALID(zone));
8511         REQUIRE(LOCKED_ZONE(zone));
8512         ENTER;
8513
8514         /*
8515          * Do we have a place to dump to and are we loaded?
8516          */
8517         if (zone->masterfile == NULL ||
8518             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
8519                 return;
8520
8521         TIME_NOW(&now);
8522         /* add some noise */
8523         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
8524
8525         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8526         if (isc_time_isepoch(&zone->dumptime) ||
8527             isc_time_compare(&zone->dumptime, &dumptime) > 0)
8528                 zone->dumptime = dumptime;
8529         if (zone->task != NULL)
8530                 zone_settimer(zone, &now);
8531 }
8532
8533 static void
8534 dump_done(void *arg, isc_result_t result) {
8535         const char me[] = "dump_done";
8536         dns_zone_t *zone = arg;
8537         dns_db_t *db;
8538         dns_dbversion_t *version;
8539         isc_boolean_t again = ISC_FALSE;
8540         isc_boolean_t compact = ISC_FALSE;
8541         isc_uint32_t serial;
8542         isc_result_t tresult;
8543
8544         REQUIRE(DNS_ZONE_VALID(zone));
8545
8546         ENTER;
8547
8548         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
8549             zone->journalsize != -1) {
8550
8551                 /*
8552                  * We don't own these, zone->dctx must stay valid.
8553                  */
8554                 db = dns_dumpctx_db(zone->dctx);
8555                 version = dns_dumpctx_version(zone->dctx);
8556
8557                 tresult = dns_db_getsoaserial(db, version, &serial);
8558                 /*
8559                  * Note: we are task locked here so we can test
8560                  * zone->xfr safely.
8561                  */
8562                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
8563                         tresult = dns_journal_compact(zone->mctx,
8564                                                       zone->journal,
8565                                                       serial,
8566                                                       zone->journalsize);
8567                         switch (tresult) {
8568                         case ISC_R_SUCCESS:
8569                         case ISC_R_NOSPACE:
8570                         case ISC_R_NOTFOUND:
8571                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
8572                                              "dns_journal_compact: %s",
8573                                              dns_result_totext(tresult));
8574                                 break;
8575                         default:
8576                                 dns_zone_log(zone, ISC_LOG_ERROR,
8577                                              "dns_journal_compact failed: %s",
8578                                              dns_result_totext(tresult));
8579                                 break;
8580                         }
8581                 } else if (tresult == ISC_R_SUCCESS) {
8582                         compact = ISC_TRUE;
8583                         zone->compact_serial = serial;
8584                 }
8585         }
8586
8587         LOCK_ZONE(zone);
8588         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8589         if (compact)
8590                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
8591         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
8592                 /*
8593                  * Try again in a short while.
8594                  */
8595                 zone_needdump(zone, DNS_DUMP_DELAY);
8596         } else if (result == ISC_R_SUCCESS &&
8597                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8598                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8599                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8600                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8601                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8602                 isc_time_settoepoch(&zone->dumptime);
8603                 again = ISC_TRUE;
8604         } else if (result == ISC_R_SUCCESS)
8605                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8606
8607         if (zone->dctx != NULL)
8608                 dns_dumpctx_detach(&zone->dctx);
8609         zonemgr_putio(&zone->writeio);
8610         UNLOCK_ZONE(zone);
8611         if (again)
8612                 (void)zone_dump(zone, ISC_FALSE);
8613         dns_zone_idetach(&zone);
8614 }
8615
8616 static isc_result_t
8617 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
8618         const char me[] = "zone_dump";
8619         isc_result_t result;
8620         dns_dbversion_t *version = NULL;
8621         isc_boolean_t again;
8622         dns_db_t *db = NULL;
8623         char *masterfile = NULL;
8624         dns_masterformat_t masterformat = dns_masterformat_none;
8625
8626 /*
8627  * 'compact' MUST only be set if we are task locked.
8628  */
8629
8630         REQUIRE(DNS_ZONE_VALID(zone));
8631         ENTER;
8632
8633  redo:
8634         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8635         if (zone->db != NULL)
8636                 dns_db_attach(zone->db, &db);
8637         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8638         LOCK_ZONE(zone);
8639         if (zone->masterfile != NULL) {
8640                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
8641                 masterformat = zone->masterformat;
8642         }
8643         UNLOCK_ZONE(zone);
8644         if (db == NULL) {
8645                 result = DNS_R_NOTLOADED;
8646                 goto fail;
8647         }
8648         if (masterfile == NULL) {
8649                 result = DNS_R_NOMASTERFILE;
8650                 goto fail;
8651         }
8652
8653         if (compact && zone->type != dns_zone_stub) {
8654                 dns_zone_t *dummy = NULL;
8655                 LOCK_ZONE(zone);
8656                 zone_iattach(zone, &dummy);
8657                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
8658                                        zone_gotwritehandle, zone,
8659                                        &zone->writeio);
8660                 if (result != ISC_R_SUCCESS)
8661                         zone_idetach(&dummy);
8662                 else
8663                         result = DNS_R_CONTINUE;
8664                 UNLOCK_ZONE(zone);
8665         } else {
8666                 const dns_master_style_t *output_style;
8667
8668                 if (zone->type == dns_zone_key)
8669                         output_style = &dns_master_style_keyzone;
8670                 else
8671                         output_style = &dns_master_style_default;
8672                 dns_db_currentversion(db, &version);
8673                 result = dns_master_dump2(zone->mctx, db, version,
8674                                           output_style, masterfile,
8675                                           masterformat);
8676                 dns_db_closeversion(db, &version, ISC_FALSE);
8677         }
8678  fail:
8679         if (db != NULL)
8680                 dns_db_detach(&db);
8681         if (masterfile != NULL)
8682                 isc_mem_free(zone->mctx, masterfile);
8683         masterfile = NULL;
8684
8685         if (result == DNS_R_CONTINUE)
8686                 return (ISC_R_SUCCESS); /* XXXMPA */
8687
8688         again = ISC_FALSE;
8689         LOCK_ZONE(zone);
8690         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8691         if (result != ISC_R_SUCCESS) {
8692                 /*
8693                  * Try again in a short while.
8694                  */
8695                 zone_needdump(zone, DNS_DUMP_DELAY);
8696         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8697                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8698                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8699                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8700                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8701                 isc_time_settoepoch(&zone->dumptime);
8702                 again = ISC_TRUE;
8703         } else
8704                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8705         UNLOCK_ZONE(zone);
8706         if (again)
8707                 goto redo;
8708
8709         return (result);
8710 }
8711
8712 static isc_result_t
8713 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
8714              dns_masterformat_t format)
8715 {
8716         isc_result_t result;
8717         dns_dbversion_t *version = NULL;
8718         dns_db_t *db = NULL;
8719
8720         REQUIRE(DNS_ZONE_VALID(zone));
8721
8722         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8723         if (zone->db != NULL)
8724                 dns_db_attach(zone->db, &db);
8725         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8726         if (db == NULL)
8727                 return (DNS_R_NOTLOADED);
8728
8729         dns_db_currentversion(db, &version);
8730         result = dns_master_dumptostream2(zone->mctx, db, version, style,
8731                                           format, fd);
8732         dns_db_closeversion(db, &version, ISC_FALSE);
8733         dns_db_detach(&db);
8734         return (result);
8735 }
8736
8737 isc_result_t
8738 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
8739                        const dns_master_style_t *style) {
8740         return dumptostream(zone, fd, style, format);
8741 }
8742
8743 isc_result_t
8744 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
8745         return dumptostream(zone, fd, &dns_master_style_default,
8746                             dns_masterformat_text);
8747 }
8748
8749 isc_result_t
8750 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
8751         return dumptostream(zone, fd, &dns_master_style_full,
8752                             dns_masterformat_text);
8753 }
8754
8755 void
8756 dns_zone_unload(dns_zone_t *zone) {
8757         REQUIRE(DNS_ZONE_VALID(zone));
8758
8759         LOCK_ZONE(zone);
8760         zone_unload(zone);
8761         UNLOCK_ZONE(zone);
8762 }
8763
8764 static void
8765 notify_cancel(dns_zone_t *zone) {
8766         dns_notify_t *notify;
8767
8768         /*
8769          * 'zone' locked by caller.
8770          */
8771
8772         REQUIRE(LOCKED_ZONE(zone));
8773
8774         for (notify = ISC_LIST_HEAD(zone->notifies);
8775              notify != NULL;
8776              notify = ISC_LIST_NEXT(notify, link)) {
8777                 if (notify->find != NULL)
8778                         dns_adb_cancelfind(notify->find);
8779                 if (notify->request != NULL)
8780                         dns_request_cancel(notify->request);
8781         }
8782 }
8783
8784 static void
8785 forward_cancel(dns_zone_t *zone) {
8786         dns_forward_t *forward;
8787
8788         /*
8789          * 'zone' locked by caller.
8790          */
8791
8792         REQUIRE(LOCKED_ZONE(zone));
8793
8794         for (forward = ISC_LIST_HEAD(zone->forwards);
8795              forward != NULL;
8796              forward = ISC_LIST_NEXT(forward, link)) {
8797                 if (forward->request != NULL)
8798                         dns_request_cancel(forward->request);
8799         }
8800 }
8801
8802 static void
8803 zone_unload(dns_zone_t *zone) {
8804
8805         /*
8806          * 'zone' locked by caller.
8807          */
8808
8809         REQUIRE(LOCKED_ZONE(zone));
8810
8811         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
8812             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
8813                 if (zone->writeio != NULL)
8814                         zonemgr_cancelio(zone->writeio);
8815
8816                 if (zone->dctx != NULL)
8817                         dns_dumpctx_cancel(zone->dctx);
8818         }
8819         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
8820         zone_detachdb(zone);
8821         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
8822         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
8823         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8824 }
8825
8826 void
8827 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8828         REQUIRE(DNS_ZONE_VALID(zone));
8829         REQUIRE(val > 0);
8830
8831         zone->minrefresh = val;
8832 }
8833
8834 void
8835 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8836         REQUIRE(DNS_ZONE_VALID(zone));
8837         REQUIRE(val > 0);
8838
8839         zone->maxrefresh = val;
8840 }
8841
8842 void
8843 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
8844         REQUIRE(DNS_ZONE_VALID(zone));
8845         REQUIRE(val > 0);
8846
8847         zone->minretry = val;
8848 }
8849
8850 void
8851 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
8852         REQUIRE(DNS_ZONE_VALID(zone));
8853         REQUIRE(val > 0);
8854
8855         zone->maxretry = val;
8856 }
8857
8858 static isc_boolean_t
8859 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
8860         dns_notify_t *notify;
8861
8862         for (notify = ISC_LIST_HEAD(zone->notifies);
8863              notify != NULL;
8864              notify = ISC_LIST_NEXT(notify, link)) {
8865                 if (notify->request != NULL)
8866                         continue;
8867                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
8868                     dns_name_equal(name, &notify->ns))
8869                         return (ISC_TRUE);
8870                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
8871                         return (ISC_TRUE);
8872         }
8873         return (ISC_FALSE);
8874 }
8875
8876 static isc_boolean_t
8877 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
8878         dns_tsigkey_t *key = NULL;
8879         isc_sockaddr_t src;
8880         isc_sockaddr_t any;
8881         isc_boolean_t isself;
8882         isc_netaddr_t dstaddr;
8883         isc_result_t result;
8884
8885         if (zone->view == NULL || zone->isself == NULL)
8886                 return (ISC_FALSE);
8887
8888         switch (isc_sockaddr_pf(dst)) {
8889         case PF_INET:
8890                 src = zone->notifysrc4;
8891                 isc_sockaddr_any(&any);
8892                 break;
8893         case PF_INET6:
8894                 src = zone->notifysrc6;
8895                 isc_sockaddr_any6(&any);
8896                 break;
8897         default:
8898                 return (ISC_FALSE);
8899         }
8900
8901         /*
8902          * When sending from any the kernel will assign a source address
8903          * that matches the destination address.
8904          */
8905         if (isc_sockaddr_eqaddr(&any, &src))
8906                 src = *dst;
8907
8908         isc_netaddr_fromsockaddr(&dstaddr, dst);
8909         result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
8910         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
8911                 return (ISC_FALSE);
8912         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
8913                                 zone->isselfarg);
8914         if (key != NULL)
8915                 dns_tsigkey_detach(&key);
8916         return (isself);
8917 }
8918
8919 static void
8920 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
8921         isc_mem_t *mctx;
8922
8923         /*
8924          * Caller holds zone lock.
8925          */
8926         REQUIRE(DNS_NOTIFY_VALID(notify));
8927
8928         if (notify->zone != NULL) {
8929                 if (!locked)
8930                         LOCK_ZONE(notify->zone);
8931                 REQUIRE(LOCKED_ZONE(notify->zone));
8932                 if (ISC_LINK_LINKED(notify, link))
8933                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
8934                 if (!locked)
8935                         UNLOCK_ZONE(notify->zone);
8936                 if (locked)
8937                         zone_idetach(&notify->zone);
8938                 else
8939                         dns_zone_idetach(&notify->zone);
8940         }
8941         if (notify->find != NULL)
8942                 dns_adb_destroyfind(&notify->find);
8943         if (notify->request != NULL)
8944                 dns_request_destroy(&notify->request);
8945         if (dns_name_dynamic(&notify->ns))
8946                 dns_name_free(&notify->ns, notify->mctx);
8947         mctx = notify->mctx;
8948         isc_mem_put(notify->mctx, notify, sizeof(*notify));
8949         isc_mem_detach(&mctx);
8950 }
8951
8952 static isc_result_t
8953 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
8954         dns_notify_t *notify;
8955
8956         REQUIRE(notifyp != NULL && *notifyp == NULL);
8957
8958         notify = isc_mem_get(mctx, sizeof(*notify));
8959         if (notify == NULL)
8960                 return (ISC_R_NOMEMORY);
8961
8962         notify->mctx = NULL;
8963         isc_mem_attach(mctx, &notify->mctx);
8964         notify->flags = flags;
8965         notify->zone = NULL;
8966         notify->find = NULL;
8967         notify->request = NULL;
8968         isc_sockaddr_any(&notify->dst);
8969         dns_name_init(&notify->ns, NULL);
8970         ISC_LINK_INIT(notify, link);
8971         notify->magic = NOTIFY_MAGIC;
8972         *notifyp = notify;
8973         return (ISC_R_SUCCESS);
8974 }
8975
8976 /*
8977  * XXXAG should check for DNS_ZONEFLG_EXITING
8978  */
8979 static void
8980 process_adb_event(isc_task_t *task, isc_event_t *ev) {
8981         dns_notify_t *notify;
8982         isc_eventtype_t result;
8983
8984         UNUSED(task);
8985
8986         notify = ev->ev_arg;
8987         REQUIRE(DNS_NOTIFY_VALID(notify));
8988         INSIST(task == notify->zone->task);
8989         result = ev->ev_type;
8990         isc_event_free(&ev);
8991         if (result == DNS_EVENT_ADBMOREADDRESSES) {
8992                 dns_adb_destroyfind(&notify->find);
8993                 notify_find_address(notify);
8994                 return;
8995         }
8996         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
8997                 LOCK_ZONE(notify->zone);
8998                 notify_send(notify);
8999                 UNLOCK_ZONE(notify->zone);
9000         }
9001         notify_destroy(notify, ISC_FALSE);
9002 }
9003
9004 static void
9005 notify_find_address(dns_notify_t *notify) {
9006         isc_result_t result;
9007         unsigned int options;
9008
9009         REQUIRE(DNS_NOTIFY_VALID(notify));
9010         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
9011                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
9012
9013         if (notify->zone->view->adb == NULL)
9014                 goto destroy;
9015
9016         result = dns_adb_createfind(notify->zone->view->adb,
9017                                     notify->zone->task,
9018                                     process_adb_event, notify,
9019                                     &notify->ns, dns_rootname, 0,
9020                                     options, 0, NULL,
9021                                     notify->zone->view->dstport,
9022                                     &notify->find);
9023
9024         /* Something failed? */
9025         if (result != ISC_R_SUCCESS)
9026                 goto destroy;
9027
9028         /* More addresses pending? */
9029         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
9030                 return;
9031
9032         /* We have as many addresses as we can get. */
9033         LOCK_ZONE(notify->zone);
9034         notify_send(notify);
9035         UNLOCK_ZONE(notify->zone);
9036
9037  destroy:
9038         notify_destroy(notify, ISC_FALSE);
9039 }
9040
9041
9042 static isc_result_t
9043 notify_send_queue(dns_notify_t *notify) {
9044         isc_event_t *e;
9045         isc_result_t result;
9046
9047         e = isc_event_allocate(notify->mctx, NULL,
9048                                DNS_EVENT_NOTIFYSENDTOADDR,
9049                                notify_send_toaddr,
9050                                notify, sizeof(isc_event_t));
9051         if (e == NULL)
9052                 return (ISC_R_NOMEMORY);
9053         e->ev_arg = notify;
9054         e->ev_sender = NULL;
9055         result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
9056                                          notify->zone->task, &e);
9057         if (result != ISC_R_SUCCESS)
9058                 isc_event_free(&e);
9059         return (result);
9060 }
9061
9062 static void
9063 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
9064         dns_notify_t *notify;
9065         isc_result_t result;
9066         dns_message_t *message = NULL;
9067         isc_netaddr_t dstip;
9068         dns_tsigkey_t *key = NULL;
9069         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9070         isc_sockaddr_t src;
9071         int timeout;
9072         isc_boolean_t have_notifysource = ISC_FALSE;
9073
9074         notify = event->ev_arg;
9075         REQUIRE(DNS_NOTIFY_VALID(notify));
9076
9077         UNUSED(task);
9078
9079         LOCK_ZONE(notify->zone);
9080
9081         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
9082                 result = ISC_R_CANCELED;
9083                 goto cleanup;
9084         }
9085
9086         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
9087             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
9088             notify->zone->view->requestmgr == NULL ||
9089             notify->zone->db == NULL) {
9090                 result = ISC_R_CANCELED;
9091                 goto cleanup;
9092         }
9093
9094         /*
9095          * The raw IPv4 address should also exist.  Don't send to the
9096          * mapped form.
9097          */
9098         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
9099             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
9100                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9101                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
9102                            "notify: ignoring IPv6 mapped IPV4 address: %s",
9103                            addrbuf);
9104                 result = ISC_R_CANCELED;
9105                 goto cleanup;
9106         }
9107
9108         result = notify_createmessage(notify->zone, notify->flags, &message);
9109         if (result != ISC_R_SUCCESS)
9110                 goto cleanup;
9111
9112         isc_netaddr_fromsockaddr(&dstip, &notify->dst);
9113         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9114         result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
9115         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9116                 notify_log(notify->zone, ISC_LOG_ERROR, "NOTIFY to %s not "
9117                            "sent. Peer TSIG key lookup failure.", addrbuf);
9118                 goto cleanup_message;
9119         }
9120
9121         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
9122                    addrbuf);
9123         if (notify->zone->view->peers != NULL) {
9124                 dns_peer_t *peer = NULL;
9125                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
9126                                                  &dstip, &peer);
9127                 if (result == ISC_R_SUCCESS) {
9128                         result = dns_peer_getnotifysource(peer, &src);
9129                         if (result == ISC_R_SUCCESS)
9130                                 have_notifysource = ISC_TRUE;
9131                 }
9132         }
9133         switch (isc_sockaddr_pf(&notify->dst)) {
9134         case PF_INET:
9135                 if (!have_notifysource)
9136                         src = notify->zone->notifysrc4;
9137                 break;
9138         case PF_INET6:
9139                 if (!have_notifysource)
9140                         src = notify->zone->notifysrc6;
9141                 break;
9142         default:
9143                 result = ISC_R_NOTIMPLEMENTED;
9144                 goto cleanup_key;
9145         }
9146         timeout = 15;
9147         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
9148                 timeout = 30;
9149         result = dns_request_createvia2(notify->zone->view->requestmgr,
9150                                         message, &src, &notify->dst, 0, key,
9151                                         timeout * 3, timeout,
9152                                         notify->zone->task, notify_done,
9153                                         notify, &notify->request);
9154         if (result == ISC_R_SUCCESS) {
9155                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
9156                         inc_stats(notify->zone,
9157                                   dns_zonestatscounter_notifyoutv4);
9158                 } else {
9159                         inc_stats(notify->zone,
9160                                   dns_zonestatscounter_notifyoutv6);
9161                 }
9162         }
9163
9164  cleanup_key:
9165         if (key != NULL)
9166                 dns_tsigkey_detach(&key);
9167  cleanup_message:
9168         dns_message_destroy(&message);
9169  cleanup:
9170         UNLOCK_ZONE(notify->zone);
9171         isc_event_free(&event);
9172         if (result != ISC_R_SUCCESS)
9173                 notify_destroy(notify, ISC_FALSE);
9174 }
9175
9176 static void
9177 notify_send(dns_notify_t *notify) {
9178         dns_adbaddrinfo_t *ai;
9179         isc_sockaddr_t dst;
9180         isc_result_t result;
9181         dns_notify_t *new = NULL;
9182
9183         /*
9184          * Zone lock held by caller.
9185          */
9186         REQUIRE(DNS_NOTIFY_VALID(notify));
9187         REQUIRE(LOCKED_ZONE(notify->zone));
9188
9189         for (ai = ISC_LIST_HEAD(notify->find->list);
9190              ai != NULL;
9191              ai = ISC_LIST_NEXT(ai, publink)) {
9192                 dst = ai->sockaddr;
9193                 if (notify_isqueued(notify->zone, NULL, &dst))
9194                         continue;
9195                 if (notify_isself(notify->zone, &dst))
9196                         continue;
9197                 new = NULL;
9198                 result = notify_create(notify->mctx,
9199                                        (notify->flags & DNS_NOTIFY_NOSOA),
9200                                        &new);
9201                 if (result != ISC_R_SUCCESS)
9202                         goto cleanup;
9203                 zone_iattach(notify->zone, &new->zone);
9204                 ISC_LIST_APPEND(new->zone->notifies, new, link);
9205                 new->dst = dst;
9206                 result = notify_send_queue(new);
9207                 if (result != ISC_R_SUCCESS)
9208                         goto cleanup;
9209                 new = NULL;
9210         }
9211
9212  cleanup:
9213         if (new != NULL)
9214                 notify_destroy(new, ISC_TRUE);
9215 }
9216
9217 void
9218 dns_zone_notify(dns_zone_t *zone) {
9219         isc_time_t now;
9220
9221         REQUIRE(DNS_ZONE_VALID(zone));
9222
9223         LOCK_ZONE(zone);
9224         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9225
9226         TIME_NOW(&now);
9227         zone_settimer(zone, &now);
9228         UNLOCK_ZONE(zone);
9229 }
9230
9231 static void
9232 zone_notify(dns_zone_t *zone, isc_time_t *now) {
9233         dns_dbnode_t *node = NULL;
9234         dns_db_t *zonedb = NULL;
9235         dns_dbversion_t *version = NULL;
9236         dns_name_t *origin = NULL;
9237         dns_name_t master;
9238         dns_rdata_ns_t ns;
9239         dns_rdata_soa_t soa;
9240         isc_uint32_t serial;
9241         dns_rdata_t rdata = DNS_RDATA_INIT;
9242         dns_rdataset_t nsrdset;
9243         dns_rdataset_t soardset;
9244         isc_result_t result;
9245         dns_notify_t *notify = NULL;
9246         unsigned int i;
9247         isc_sockaddr_t dst;
9248         isc_boolean_t isqueued;
9249         dns_notifytype_t notifytype;
9250         unsigned int flags = 0;
9251         isc_boolean_t loggednotify = ISC_FALSE;
9252
9253         REQUIRE(DNS_ZONE_VALID(zone));
9254
9255         LOCK_ZONE(zone);
9256         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9257         notifytype = zone->notifytype;
9258         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
9259         UNLOCK_ZONE(zone);
9260
9261         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
9262                 return;
9263
9264         if (notifytype == dns_notifytype_no)
9265                 return;
9266
9267         if (notifytype == dns_notifytype_masteronly &&
9268             zone->type != dns_zone_master)
9269                 return;
9270
9271         origin = &zone->origin;
9272
9273         /*
9274          * If the zone is dialup we are done as we don't want to send
9275          * the current soa so as to force a refresh query.
9276          */
9277         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
9278                 flags |= DNS_NOTIFY_NOSOA;
9279
9280         /*
9281          * Get SOA RRset.
9282          */
9283         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9284         if (zone->db != NULL)
9285                 dns_db_attach(zone->db, &zonedb);
9286         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9287         if (zonedb == NULL)
9288                 return;
9289         dns_db_currentversion(zonedb, &version);
9290         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
9291         if (result != ISC_R_SUCCESS)
9292                 goto cleanup1;
9293
9294         dns_rdataset_init(&soardset);
9295         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
9296                                      dns_rdatatype_none, 0, &soardset, NULL);
9297         if (result != ISC_R_SUCCESS)
9298                 goto cleanup2;
9299
9300         /*
9301          * Find serial and master server's name.
9302          */
9303         dns_name_init(&master, NULL);
9304         result = dns_rdataset_first(&soardset);
9305         if (result != ISC_R_SUCCESS)
9306                 goto cleanup3;
9307         dns_rdataset_current(&soardset, &rdata);
9308         result = dns_rdata_tostruct(&rdata, &soa, NULL);
9309         RUNTIME_CHECK(result == ISC_R_SUCCESS);
9310         dns_rdata_reset(&rdata);
9311         result = dns_name_dup(&soa.origin, zone->mctx, &master);
9312         serial = soa.serial;
9313         dns_rdataset_disassociate(&soardset);
9314         if (result != ISC_R_SUCCESS)
9315                 goto cleanup3;
9316
9317         /*
9318          * Enqueue notify requests for 'also-notify' servers.
9319          */
9320         LOCK_ZONE(zone);
9321         for (i = 0; i < zone->notifycnt; i++) {
9322                 dst = zone->notify[i];
9323                 if (notify_isqueued(zone, NULL, &dst))
9324                         continue;
9325                 result = notify_create(zone->mctx, flags, &notify);
9326                 if (result != ISC_R_SUCCESS)
9327                         continue;
9328                 zone_iattach(zone, &notify->zone);
9329                 notify->dst = dst;
9330                 ISC_LIST_APPEND(zone->notifies, notify, link);
9331                 result = notify_send_queue(notify);
9332                 if (result != ISC_R_SUCCESS)
9333                         notify_destroy(notify, ISC_TRUE);
9334                 if (!loggednotify) {
9335                         notify_log(zone, ISC_LOG_INFO,
9336                                    "sending notifies (serial %u)",
9337                                    serial);
9338                         loggednotify = ISC_TRUE;
9339                 }
9340                 notify = NULL;
9341         }
9342         UNLOCK_ZONE(zone);
9343
9344         if (notifytype == dns_notifytype_explicit)
9345                 goto cleanup3;
9346
9347         /*
9348          * Process NS RRset to generate notifies.
9349          */
9350
9351         dns_rdataset_init(&nsrdset);
9352         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
9353                                      dns_rdatatype_none, 0, &nsrdset, NULL);
9354         if (result != ISC_R_SUCCESS)
9355                 goto cleanup3;
9356
9357         result = dns_rdataset_first(&nsrdset);
9358         while (result == ISC_R_SUCCESS) {
9359                 dns_rdataset_current(&nsrdset, &rdata);
9360                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
9361                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9362                 dns_rdata_reset(&rdata);
9363                 /*
9364                  * Don't notify the master server unless explicitly
9365                  * configured to do so.
9366                  */
9367                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
9368                     dns_name_compare(&master, &ns.name) == 0) {
9369                         result = dns_rdataset_next(&nsrdset);
9370                         continue;
9371                 }
9372
9373                 if (!loggednotify) {
9374                         notify_log(zone, ISC_LOG_INFO,
9375                                    "sending notifies (serial %u)",
9376                                    serial);
9377                         loggednotify = ISC_TRUE;
9378                 }
9379
9380                 LOCK_ZONE(zone);
9381                 isqueued = notify_isqueued(zone, &ns.name, NULL);
9382                 UNLOCK_ZONE(zone);
9383                 if (isqueued) {
9384                         result = dns_rdataset_next(&nsrdset);
9385                         continue;
9386                 }
9387                 result = notify_create(zone->mctx, flags, &notify);
9388                 if (result != ISC_R_SUCCESS)
9389                         continue;
9390                 dns_zone_iattach(zone, &notify->zone);
9391                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
9392                 if (result != ISC_R_SUCCESS) {
9393                         LOCK_ZONE(zone);
9394                         notify_destroy(notify, ISC_TRUE);
9395                         UNLOCK_ZONE(zone);
9396                         continue;
9397                 }
9398                 LOCK_ZONE(zone);
9399                 ISC_LIST_APPEND(zone->notifies, notify, link);
9400                 UNLOCK_ZONE(zone);
9401                 notify_find_address(notify);
9402                 notify = NULL;
9403                 result = dns_rdataset_next(&nsrdset);
9404         }
9405         dns_rdataset_disassociate(&nsrdset);
9406
9407  cleanup3:
9408         if (dns_name_dynamic(&master))
9409                 dns_name_free(&master, zone->mctx);
9410  cleanup2:
9411         dns_db_detachnode(zonedb, &node);
9412  cleanup1:
9413         dns_db_closeversion(zonedb, &version, ISC_FALSE);
9414         dns_db_detach(&zonedb);
9415 }
9416
9417 /***
9418  *** Private
9419  ***/
9420
9421 static inline isc_result_t
9422 save_nsrrset(dns_message_t *message, dns_name_t *name,
9423              dns_db_t *db, dns_dbversion_t *version)
9424 {
9425         dns_rdataset_t *nsrdataset = NULL;
9426         dns_rdataset_t *rdataset = NULL;
9427         dns_dbnode_t *node = NULL;
9428         dns_rdata_ns_t ns;
9429         isc_result_t result;
9430         dns_rdata_t rdata = DNS_RDATA_INIT;
9431
9432         /*
9433          * Extract NS RRset from message.
9434          */
9435         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
9436                                       dns_rdatatype_ns, dns_rdatatype_none,
9437                                       NULL, &nsrdataset);
9438         if (result != ISC_R_SUCCESS)
9439                 goto fail;
9440
9441         /*
9442          * Add NS rdataset.
9443          */
9444         result = dns_db_findnode(db, name, ISC_TRUE, &node);
9445         if (result != ISC_R_SUCCESS)
9446                 goto fail;
9447         result = dns_db_addrdataset(db, node, version, 0,
9448                                     nsrdataset, 0, NULL);
9449         dns_db_detachnode(db, &node);
9450         if (result != ISC_R_SUCCESS)
9451                 goto fail;
9452         /*
9453          * Add glue rdatasets.
9454          */
9455         for (result = dns_rdataset_first(nsrdataset);
9456              result == ISC_R_SUCCESS;
9457              result = dns_rdataset_next(nsrdataset)) {
9458                 dns_rdataset_current(nsrdataset, &rdata);
9459                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
9460                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9461                 dns_rdata_reset(&rdata);
9462                 if (!dns_name_issubdomain(&ns.name, name))
9463                         continue;
9464                 rdataset = NULL;
9465                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9466                                               &ns.name, dns_rdatatype_aaaa,
9467                                               dns_rdatatype_none, NULL,
9468                                               &rdataset);
9469                 if (result == ISC_R_SUCCESS) {
9470                         result = dns_db_findnode(db, &ns.name,
9471                                                  ISC_TRUE, &node);
9472                         if (result != ISC_R_SUCCESS)
9473                                 goto fail;
9474                         result = dns_db_addrdataset(db, node, version, 0,
9475                                                     rdataset, 0, NULL);
9476                         dns_db_detachnode(db, &node);
9477                         if (result != ISC_R_SUCCESS)
9478                                 goto fail;
9479                 }
9480                 rdataset = NULL;
9481                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9482                                               &ns.name, dns_rdatatype_a,
9483                                               dns_rdatatype_none, NULL,
9484                                               &rdataset);
9485                 if (result == ISC_R_SUCCESS) {
9486                         result = dns_db_findnode(db, &ns.name,
9487                                                  ISC_TRUE, &node);
9488                         if (result != ISC_R_SUCCESS)
9489                                 goto fail;
9490                         result = dns_db_addrdataset(db, node, version, 0,
9491                                                     rdataset, 0, NULL);
9492                         dns_db_detachnode(db, &node);
9493                         if (result != ISC_R_SUCCESS)
9494                                 goto fail;
9495                 }
9496         }
9497         if (result != ISC_R_NOMORE)
9498                 goto fail;
9499
9500         return (ISC_R_SUCCESS);
9501
9502 fail:
9503         return (result);
9504 }
9505
9506 static void
9507 stub_callback(isc_task_t *task, isc_event_t *event) {
9508         const char me[] = "stub_callback";
9509         dns_requestevent_t *revent = (dns_requestevent_t *)event;
9510         dns_stub_t *stub = NULL;
9511         dns_message_t *msg = NULL;
9512         dns_zone_t *zone = NULL;
9513         char master[ISC_SOCKADDR_FORMATSIZE];
9514         char source[ISC_SOCKADDR_FORMATSIZE];
9515         isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
9516         isc_result_t result;
9517         isc_time_t now;
9518         isc_boolean_t exiting = ISC_FALSE;
9519         isc_interval_t i;
9520         unsigned int j, soacount;
9521
9522         stub = revent->ev_arg;
9523         INSIST(DNS_STUB_VALID(stub));
9524
9525         UNUSED(task);
9526
9527         zone = stub->zone;
9528
9529         ENTER;
9530
9531         TIME_NOW(&now);
9532
9533         LOCK_ZONE(zone);
9534
9535         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9536                 zone_debuglog(zone, me, 1, "exiting");
9537                 exiting = ISC_TRUE;
9538                 goto next_master;
9539         }
9540
9541         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9542         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9543
9544         if (revent->result != ISC_R_SUCCESS) {
9545                 if (revent->result == ISC_R_TIMEDOUT &&
9546                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9547                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9548                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9549                                      "refreshing stub: timeout retrying "
9550                                      " without EDNS master %s (source %s)",
9551                                      master, source);
9552                         goto same_master;
9553                 }
9554                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
9555                                            &zone->sourceaddr, &now);
9556                 dns_zone_log(zone, ISC_LOG_INFO,
9557                              "could not refresh stub from master %s"
9558                              " (source %s): %s", master, source,
9559                              dns_result_totext(revent->result));
9560                 goto next_master;
9561         }
9562
9563         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9564         if (result != ISC_R_SUCCESS)
9565                 goto next_master;
9566
9567         result = dns_request_getresponse(revent->request, msg, 0);
9568         if (result != ISC_R_SUCCESS)
9569                 goto next_master;
9570
9571         /*
9572          * Unexpected rcode.
9573          */
9574         if (msg->rcode != dns_rcode_noerror) {
9575                 char rcode[128];
9576                 isc_buffer_t rb;
9577
9578                 isc_buffer_init(&rb, rcode, sizeof(rcode));
9579                 (void)dns_rcode_totext(msg->rcode, &rb);
9580
9581                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9582                     (msg->rcode == dns_rcode_servfail ||
9583                      msg->rcode == dns_rcode_notimp ||
9584                      msg->rcode == dns_rcode_formerr)) {
9585                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9586                                      "refreshing stub: rcode (%.*s) retrying "
9587                                      "without EDNS master %s (source %s)",
9588                                      (int)rb.used, rcode, master, source);
9589                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9590                         goto same_master;
9591                 }
9592
9593                 dns_zone_log(zone, ISC_LOG_INFO,
9594                              "refreshing stub: "
9595                              "unexpected rcode (%.*s) from %s (source %s)",
9596                              (int)rb.used, rcode, master, source);
9597                 goto next_master;
9598         }
9599
9600         /*
9601          * We need complete messages.
9602          */
9603         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9604                 if (dns_request_usedtcp(revent->request)) {
9605                         dns_zone_log(zone, ISC_LOG_INFO,
9606                                      "refreshing stub: truncated TCP "
9607                                      "response from master %s (source %s)",
9608                                      master, source);
9609                         goto next_master;
9610                 }
9611                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9612                 goto same_master;
9613         }
9614
9615         /*
9616          * If non-auth log and next master.
9617          */
9618         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9619                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
9620                              "non-authoritative answer from "
9621                              "master %s (source %s)", master, source);
9622                 goto next_master;
9623         }
9624
9625         /*
9626          * Sanity checks.
9627          */
9628         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9629         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
9630
9631         if (cnamecnt != 0) {
9632                 dns_zone_log(zone, ISC_LOG_INFO,
9633                              "refreshing stub: unexpected CNAME response "
9634                              "from master %s (source %s)", master, source);
9635                 goto next_master;
9636         }
9637
9638         if (nscnt == 0) {
9639                 dns_zone_log(zone, ISC_LOG_INFO,
9640                              "refreshing stub: no NS records in response "
9641                              "from master %s (source %s)", master, source);
9642                 goto next_master;
9643         }
9644
9645         /*
9646          * Save answer.
9647          */
9648         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
9649         if (result != ISC_R_SUCCESS) {
9650                 dns_zone_log(zone, ISC_LOG_INFO,
9651                              "refreshing stub: unable to save NS records "
9652                              "from master %s (source %s)", master, source);
9653                 goto next_master;
9654         }
9655
9656         /*
9657          * Tidy up.
9658          */
9659         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
9660         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9661         if (zone->db == NULL)
9662                 zone_attachdb(zone, stub->db);
9663         result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
9664                                   &refresh, &retry, &expire, NULL, NULL);
9665         if (result == ISC_R_SUCCESS && soacount > 0U) {
9666                 zone->refresh = RANGE(refresh, zone->minrefresh,
9667                                       zone->maxrefresh);
9668                 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
9669                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
9670                                      DNS_MAX_EXPIRE);
9671                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9672         }
9673         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9674         dns_db_detach(&stub->db);
9675
9676         dns_message_destroy(&msg);
9677         isc_event_free(&event);
9678         dns_request_destroy(&zone->request);
9679
9680         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9681         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
9682         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9683         isc_interval_set(&i, zone->expire, 0);
9684         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9685
9686         if (zone->masterfile != NULL)
9687                 zone_needdump(zone, 0);
9688
9689         zone_settimer(zone, &now);
9690         goto free_stub;
9691
9692  next_master:
9693         if (stub->version != NULL)
9694                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
9695         if (stub->db != NULL)
9696                 dns_db_detach(&stub->db);
9697         if (msg != NULL)
9698                 dns_message_destroy(&msg);
9699         isc_event_free(&event);
9700         dns_request_destroy(&zone->request);
9701         /*
9702          * Skip to next failed / untried master.
9703          */
9704         do {
9705                 zone->curmaster++;
9706         } while (zone->curmaster < zone->masterscnt &&
9707                  zone->mastersok[zone->curmaster]);
9708         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9709         if (exiting || zone->curmaster >= zone->masterscnt) {
9710                 isc_boolean_t done = ISC_TRUE;
9711                 if (!exiting &&
9712                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9713                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9714                         /*
9715                          * Did we get a good answer from all the masters?
9716                          */
9717                         for (j = 0; j < zone->masterscnt; j++)
9718                                 if (zone->mastersok[j] == ISC_FALSE) {
9719                                         done = ISC_FALSE;
9720                                         break;
9721                                 }
9722                 } else
9723                         done = ISC_TRUE;
9724                 if (!done) {
9725                         zone->curmaster = 0;
9726                         /*
9727                          * Find the next failed master.
9728                          */
9729                         while (zone->curmaster < zone->masterscnt &&
9730                                zone->mastersok[zone->curmaster])
9731                                 zone->curmaster++;
9732                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9733                 } else {
9734                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9735
9736                         zone_settimer(zone, &now);
9737                         goto free_stub;
9738                 }
9739         }
9740         queue_soa_query(zone);
9741         goto free_stub;
9742
9743  same_master:
9744         if (msg != NULL)
9745                 dns_message_destroy(&msg);
9746         isc_event_free(&event);
9747         dns_request_destroy(&zone->request);
9748         ns_query(zone, NULL, stub);
9749         UNLOCK_ZONE(zone);
9750         goto done;
9751
9752  free_stub:
9753         UNLOCK_ZONE(zone);
9754         stub->magic = 0;
9755         dns_zone_idetach(&stub->zone);
9756         INSIST(stub->db == NULL);
9757         INSIST(stub->version == NULL);
9758         isc_mem_put(stub->mctx, stub, sizeof(*stub));
9759
9760  done:
9761         INSIST(event == NULL);
9762         return;
9763 }
9764
9765 /*
9766  * An SOA query has finished (successfully or not).
9767  */
9768 static void
9769 refresh_callback(isc_task_t *task, isc_event_t *event) {
9770         const char me[] = "refresh_callback";
9771         dns_requestevent_t *revent = (dns_requestevent_t *)event;
9772         dns_zone_t *zone;
9773         dns_message_t *msg = NULL;
9774         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
9775         isc_time_t now;
9776         char master[ISC_SOCKADDR_FORMATSIZE];
9777         char source[ISC_SOCKADDR_FORMATSIZE];
9778         dns_rdataset_t *rdataset = NULL;
9779         dns_rdata_t rdata = DNS_RDATA_INIT;
9780         dns_rdata_soa_t soa;
9781         isc_result_t result;
9782         isc_uint32_t serial, oldserial = 0;
9783         unsigned int j;
9784         isc_boolean_t do_queue_xfrin = ISC_FALSE;
9785
9786         zone = revent->ev_arg;
9787         INSIST(DNS_ZONE_VALID(zone));
9788
9789         UNUSED(task);
9790
9791         ENTER;
9792
9793         TIME_NOW(&now);
9794
9795         LOCK_ZONE(zone);
9796
9797         /*
9798          * if timeout log and next master;
9799          */
9800
9801         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9802         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9803
9804         if (revent->result != ISC_R_SUCCESS) {
9805                 if (revent->result == ISC_R_TIMEDOUT &&
9806                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9807                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9808                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9809                                      "refresh: timeout retrying without EDNS "
9810                                      "master %s (source %s)", master, source);
9811                         goto same_master;
9812                 }
9813                 if (revent->result == ISC_R_TIMEDOUT &&
9814                     !dns_request_usedtcp(revent->request)) {
9815                         dns_zone_log(zone, ISC_LOG_INFO,
9816                                      "refresh: retry limit for "
9817                                      "master %s exceeded (source %s)",
9818                                      master, source);
9819                         /* Try with slave with TCP. */
9820                         if (zone->type == dns_zone_slave &&
9821                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
9822                                 if (!dns_zonemgr_unreachable(zone->zmgr,
9823                                                              &zone->masteraddr,
9824                                                              &zone->sourceaddr,
9825                                                              &now))
9826                                 {
9827                                         DNS_ZONE_SETFLAG(zone,
9828                                                      DNS_ZONEFLG_SOABEFOREAXFR);
9829                                         goto tcp_transfer;
9830                                 }
9831                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
9832                                              "refresh: skipped tcp fallback "
9833                                              "as master %s (source %s) is "
9834                                              "unreachable (cached)",
9835                                               master, source);
9836                         }
9837                 } else
9838                         dns_zone_log(zone, ISC_LOG_INFO,
9839                                      "refresh: failure trying master "
9840                                      "%s (source %s): %s", master, source,
9841                                      dns_result_totext(revent->result));
9842                 goto next_master;
9843         }
9844
9845         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9846         if (result != ISC_R_SUCCESS)
9847                 goto next_master;
9848         result = dns_request_getresponse(revent->request, msg, 0);
9849         if (result != ISC_R_SUCCESS) {
9850                 dns_zone_log(zone, ISC_LOG_INFO,
9851                              "refresh: failure trying master "
9852                              "%s (source %s): %s", master, source,
9853                              dns_result_totext(result));
9854                 goto next_master;
9855         }
9856
9857         /*
9858          * Unexpected rcode.
9859          */
9860         if (msg->rcode != dns_rcode_noerror) {
9861                 char rcode[128];
9862                 isc_buffer_t rb;
9863
9864                 isc_buffer_init(&rb, rcode, sizeof(rcode));
9865                 (void)dns_rcode_totext(msg->rcode, &rb);
9866
9867                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9868                     (msg->rcode == dns_rcode_servfail ||
9869                      msg->rcode == dns_rcode_notimp ||
9870                      msg->rcode == dns_rcode_formerr)) {
9871                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9872                                      "refresh: rcode (%.*s) retrying without "
9873                                      "EDNS master %s (source %s)",
9874                                      (int)rb.used, rcode, master, source);
9875                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9876                         goto same_master;
9877                 }
9878                 dns_zone_log(zone, ISC_LOG_INFO,
9879                              "refresh: unexpected rcode (%.*s) from "
9880                              "master %s (source %s)", (int)rb.used, rcode,
9881                              master, source);
9882                 /*
9883                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
9884                  */
9885                 if (msg->rcode == dns_rcode_refused &&
9886                     zone->type == dns_zone_slave)
9887                         goto tcp_transfer;
9888                 goto next_master;
9889         }
9890
9891         /*
9892          * If truncated punt to zone transfer which will query again.
9893          */
9894         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9895                 if (zone->type == dns_zone_slave) {
9896                         dns_zone_log(zone, ISC_LOG_INFO,
9897                                      "refresh: truncated UDP answer, "
9898                                      "initiating TCP zone xfer "
9899                                      "for master %s (source %s)",
9900                                      master, source);
9901                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
9902                         goto tcp_transfer;
9903                 } else {
9904                         INSIST(zone->type == dns_zone_stub);
9905                         if (dns_request_usedtcp(revent->request)) {
9906                                 dns_zone_log(zone, ISC_LOG_INFO,
9907                                              "refresh: truncated TCP response "
9908                                              "from master %s (source %s)",
9909                                              master, source);
9910                                 goto next_master;
9911                         }
9912                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9913                         goto same_master;
9914                 }
9915         }
9916
9917         /*
9918          * if non-auth log and next master;
9919          */
9920         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9921                 dns_zone_log(zone, ISC_LOG_INFO,
9922                              "refresh: non-authoritative answer from "
9923                              "master %s (source %s)", master, source);
9924                 goto next_master;
9925         }
9926
9927         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9928         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
9929         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
9930         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
9931                                  dns_rdatatype_soa);
9932
9933         /*
9934          * There should not be a CNAME record at top of zone.
9935          */
9936         if (cnamecnt != 0) {
9937                 dns_zone_log(zone, ISC_LOG_INFO,
9938                              "refresh: CNAME at top of zone "
9939                              "in master %s (source %s)", master, source);
9940                 goto next_master;
9941         }
9942
9943         /*
9944          * if referral log and next master;
9945          */
9946         if (soacnt == 0 && soacount == 0 && nscount != 0) {
9947                 dns_zone_log(zone, ISC_LOG_INFO,
9948                              "refresh: referral response "
9949                              "from master %s (source %s)", master, source);
9950                 goto next_master;
9951         }
9952
9953         /*
9954          * if nodata log and next master;
9955          */
9956         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
9957                 dns_zone_log(zone, ISC_LOG_INFO,
9958                              "refresh: NODATA response "
9959                              "from master %s (source %s)", master, source);
9960                 goto next_master;
9961         }
9962
9963         /*
9964          * Only one soa at top of zone.
9965          */
9966         if (soacnt != 1) {
9967                 dns_zone_log(zone, ISC_LOG_INFO,
9968                              "refresh: answer SOA count (%d) != 1 "
9969                              "from master %s (source %s)",
9970                              soacnt, master, source);
9971                 goto next_master;
9972         }
9973
9974         /*
9975          * Extract serial
9976          */
9977         rdataset = NULL;
9978         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
9979                                       dns_rdatatype_soa, dns_rdatatype_none,
9980                                       NULL, &rdataset);
9981         if (result != ISC_R_SUCCESS) {
9982                 dns_zone_log(zone, ISC_LOG_INFO,
9983                              "refresh: unable to get SOA record "
9984                              "from master %s (source %s)", master, source);
9985                 goto next_master;
9986         }
9987
9988         result = dns_rdataset_first(rdataset);
9989         if (result != ISC_R_SUCCESS) {
9990                 dns_zone_log(zone, ISC_LOG_INFO,
9991                              "refresh: dns_rdataset_first() failed");
9992                 goto next_master;
9993         }
9994
9995         dns_rdataset_current(rdataset, &rdata);
9996         result = dns_rdata_tostruct(&rdata, &soa, NULL);
9997         RUNTIME_CHECK(result == ISC_R_SUCCESS);
9998
9999         serial = soa.serial;
10000         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10001                 unsigned int soacount;
10002                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
10003                                           &oldserial, NULL, NULL, NULL, NULL,
10004                                           NULL);
10005                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10006                 RUNTIME_CHECK(soacount > 0U);
10007                 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
10008                               serial, oldserial);
10009         } else
10010                 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
10011                               serial);
10012
10013         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
10014             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
10015             isc_serial_gt(serial, oldserial)) {
10016                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
10017                                             &zone->sourceaddr, &now))
10018                 {
10019                         dns_zone_log(zone, ISC_LOG_INFO,
10020                                      "refresh: skipping %s as master %s "
10021                                      "(source %s) is unreachable (cached)",
10022                                      zone->type == dns_zone_slave ?
10023                                      "zone transfer" : "NS query",
10024                                      master, source);
10025                         goto next_master;
10026                 }
10027  tcp_transfer:
10028                 isc_event_free(&event);
10029                 dns_request_destroy(&zone->request);
10030                 if (zone->type == dns_zone_slave) {
10031                         do_queue_xfrin = ISC_TRUE;
10032                 } else {
10033                         INSIST(zone->type == dns_zone_stub);
10034                         ns_query(zone, rdataset, NULL);
10035                 }
10036                 if (msg != NULL)
10037                         dns_message_destroy(&msg);
10038         } else if (isc_serial_eq(soa.serial, oldserial)) {
10039                 if (zone->masterfile != NULL) {
10040                         result = ISC_R_FAILURE;
10041                         if (zone->journal != NULL)
10042                                 result = isc_file_settime(zone->journal, &now);
10043                         if (result == ISC_R_SUCCESS &&
10044                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10045                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10046                                 result = isc_file_settime(zone->masterfile,
10047                                                           &now);
10048                         } else if (result != ISC_R_SUCCESS)
10049                                 result = isc_file_settime(zone->masterfile,
10050                                                           &now);
10051                         /* Someone removed the file from underneath us! */
10052                         if (result == ISC_R_FILENOTFOUND) {
10053                                 zone_needdump(zone, DNS_DUMP_DELAY);
10054                         } else if (result != ISC_R_SUCCESS)
10055                                 dns_zone_log(zone, ISC_LOG_ERROR,
10056                                              "refresh: could not set file "
10057                                              "modification time of '%s': %s",
10058                                              zone->masterfile,
10059                                              dns_result_totext(result));
10060                 }
10061                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10062                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10063                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10064                 goto next_master;
10065         } else {
10066                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
10067                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
10068                                      "received from master %s < ours (%u)",
10069                                      soa.serial, master, oldserial);
10070                 else
10071                         zone_debuglog(zone, me, 1, "ahead");
10072                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10073                 goto next_master;
10074         }
10075         if (msg != NULL)
10076                 dns_message_destroy(&msg);
10077         goto detach;
10078
10079  next_master:
10080         if (msg != NULL)
10081                 dns_message_destroy(&msg);
10082         isc_event_free(&event);
10083         dns_request_destroy(&zone->request);
10084         /*
10085          * Skip to next failed / untried master.
10086          */
10087         do {
10088                 zone->curmaster++;
10089         } while (zone->curmaster < zone->masterscnt &&
10090                  zone->mastersok[zone->curmaster]);
10091         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10092         if (zone->curmaster >= zone->masterscnt) {
10093                 isc_boolean_t done = ISC_TRUE;
10094                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10095                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10096                         /*
10097                          * Did we get a good answer from all the masters?
10098                          */
10099                         for (j = 0; j < zone->masterscnt; j++)
10100                                 if (zone->mastersok[j] == ISC_FALSE) {
10101                                         done = ISC_FALSE;
10102                                         break;
10103                                 }
10104                 } else
10105                         done = ISC_TRUE;
10106                 if (!done) {
10107                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10108                         zone->curmaster = 0;
10109                         /*
10110                          * Find the next failed master.
10111                          */
10112                         while (zone->curmaster < zone->masterscnt &&
10113                                zone->mastersok[zone->curmaster])
10114                                 zone->curmaster++;
10115                         goto requeue;
10116                 }
10117                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10118                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
10119                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10120                         zone->refreshtime = now;
10121                 }
10122                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10123                 zone_settimer(zone, &now);
10124                 goto detach;
10125         }
10126
10127  requeue:
10128         queue_soa_query(zone);
10129         goto detach;
10130
10131  same_master:
10132         if (msg != NULL)
10133                 dns_message_destroy(&msg);
10134         isc_event_free(&event);
10135         dns_request_destroy(&zone->request);
10136         queue_soa_query(zone);
10137
10138  detach:
10139         UNLOCK_ZONE(zone);
10140         if (do_queue_xfrin)
10141                 queue_xfrin(zone);
10142         dns_zone_idetach(&zone);
10143         return;
10144 }
10145
10146 static void
10147 queue_soa_query(dns_zone_t *zone) {
10148         const char me[] = "queue_soa_query";
10149         isc_event_t *e;
10150         dns_zone_t *dummy = NULL;
10151         isc_result_t result;
10152
10153         ENTER;
10154         /*
10155          * Locked by caller
10156          */
10157         REQUIRE(LOCKED_ZONE(zone));
10158
10159         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10160                 cancel_refresh(zone);
10161                 return;
10162         }
10163
10164         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
10165                                soa_query, zone, sizeof(isc_event_t));
10166         if (e == NULL) {
10167                 cancel_refresh(zone);
10168                 return;
10169         }
10170
10171         /*
10172          * Attach so that we won't clean up
10173          * until the event is delivered.
10174          */
10175         zone_iattach(zone, &dummy);
10176
10177         e->ev_arg = zone;
10178         e->ev_sender = NULL;
10179         result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
10180         if (result != ISC_R_SUCCESS) {
10181                 zone_idetach(&dummy);
10182                 isc_event_free(&e);
10183                 cancel_refresh(zone);
10184         }
10185 }
10186
10187 static inline isc_result_t
10188 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
10189              dns_message_t **messagep)
10190 {
10191         dns_message_t *message = NULL;
10192         dns_name_t *qname = NULL;
10193         dns_rdataset_t *qrdataset = NULL;
10194         isc_result_t result;
10195
10196         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10197                                     &message);
10198         if (result != ISC_R_SUCCESS)
10199                 goto cleanup;
10200
10201         message->opcode = dns_opcode_query;
10202         message->rdclass = zone->rdclass;
10203
10204         result = dns_message_gettempname(message, &qname);
10205         if (result != ISC_R_SUCCESS)
10206                 goto cleanup;
10207
10208         result = dns_message_gettemprdataset(message, &qrdataset);
10209         if (result != ISC_R_SUCCESS)
10210                 goto cleanup;
10211
10212         /*
10213          * Make question.
10214          */
10215         dns_name_init(qname, NULL);
10216         dns_name_clone(&zone->origin, qname);
10217         dns_rdataset_init(qrdataset);
10218         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
10219         ISC_LIST_APPEND(qname->list, qrdataset, link);
10220         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
10221
10222         *messagep = message;
10223         return (ISC_R_SUCCESS);
10224
10225  cleanup:
10226         if (qname != NULL)
10227                 dns_message_puttempname(message, &qname);
10228         if (qrdataset != NULL)
10229                 dns_message_puttemprdataset(message, &qrdataset);
10230         if (message != NULL)
10231                 dns_message_destroy(&message);
10232         return (result);
10233 }
10234
10235 static isc_result_t
10236 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
10237         dns_rdataset_t *rdataset = NULL;
10238         dns_rdatalist_t *rdatalist = NULL;
10239         dns_rdata_t *rdata = NULL;
10240         isc_result_t result;
10241
10242         result = dns_message_gettemprdatalist(message, &rdatalist);
10243         if (result != ISC_R_SUCCESS)
10244                 goto cleanup;
10245         result = dns_message_gettemprdata(message, &rdata);
10246         if (result != ISC_R_SUCCESS)
10247                 goto cleanup;
10248         result = dns_message_gettemprdataset(message, &rdataset);
10249         if (result != ISC_R_SUCCESS)
10250                 goto cleanup;
10251         dns_rdataset_init(rdataset);
10252
10253         rdatalist->type = dns_rdatatype_opt;
10254         rdatalist->covers = 0;
10255
10256         /*
10257          * Set Maximum UDP buffer size.
10258          */
10259         rdatalist->rdclass = udpsize;
10260
10261         /*
10262          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
10263          */
10264         rdatalist->ttl = 0;
10265
10266         /* Set EDNS options if applicable */
10267         if (reqnsid) {
10268                 unsigned char data[4];
10269                 isc_buffer_t buf;
10270
10271                 isc_buffer_init(&buf, data, sizeof(data));
10272                 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
10273                 isc_buffer_putuint16(&buf, 0);
10274                 rdata->data = data;
10275                 rdata->length = sizeof(data);
10276         } else {
10277                 rdata->data = NULL;
10278                 rdata->length = 0;
10279         }
10280
10281         rdata->rdclass = rdatalist->rdclass;
10282         rdata->type = rdatalist->type;
10283         rdata->flags = 0;
10284
10285         ISC_LIST_INIT(rdatalist->rdata);
10286         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
10287         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
10288                       == ISC_R_SUCCESS);
10289
10290         return (dns_message_setopt(message, rdataset));
10291
10292  cleanup:
10293         if (rdatalist != NULL)
10294                 dns_message_puttemprdatalist(message, &rdatalist);
10295         if (rdataset != NULL)
10296                 dns_message_puttemprdataset(message, &rdataset);
10297         if (rdata != NULL)
10298                 dns_message_puttemprdata(message, &rdata);
10299
10300         return (result);
10301 }
10302
10303 static void
10304 soa_query(isc_task_t *task, isc_event_t *event) {
10305         const char me[] = "soa_query";
10306         isc_result_t result = ISC_R_FAILURE;
10307         dns_message_t *message = NULL;
10308         dns_zone_t *zone = event->ev_arg;
10309         dns_zone_t *dummy = NULL;
10310         isc_netaddr_t masterip;
10311         dns_tsigkey_t *key = NULL;
10312         isc_uint32_t options;
10313         isc_boolean_t cancel = ISC_TRUE;
10314         int timeout;
10315         isc_boolean_t have_xfrsource, reqnsid;
10316         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10317
10318         REQUIRE(DNS_ZONE_VALID(zone));
10319
10320         UNUSED(task);
10321
10322         ENTER;
10323
10324         LOCK_ZONE(zone);
10325         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
10326             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
10327             zone->view->requestmgr == NULL) {
10328                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10329                         cancel = ISC_FALSE;
10330                 goto cleanup;
10331         }
10332
10333         /*
10334          * XXX Optimisation: Create message when zone is setup and reuse.
10335          */
10336         result = create_query(zone, dns_rdatatype_soa, &message);
10337         if (result != ISC_R_SUCCESS)
10338                 goto cleanup;
10339
10340  again:
10341         INSIST(zone->masterscnt > 0);
10342         INSIST(zone->curmaster < zone->masterscnt);
10343
10344         zone->masteraddr = zone->masters[zone->curmaster];
10345
10346         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10347         /*
10348          * First, look for a tsig key in the master statement, then
10349          * try for a server key.
10350          */
10351         if ((zone->masterkeynames != NULL) &&
10352             (zone->masterkeynames[zone->curmaster] != NULL)) {
10353                 dns_view_t *view = dns_zone_getview(zone);
10354                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10355                 result = dns_view_gettsig(view, keyname, &key);
10356                 if (result != ISC_R_SUCCESS) {
10357                         char namebuf[DNS_NAME_FORMATSIZE];
10358                         dns_name_format(keyname, namebuf, sizeof(namebuf));
10359                         dns_zone_log(zone, ISC_LOG_ERROR,
10360                                      "unable to find key: %s", namebuf);
10361                         goto skip_master;
10362                 }
10363         }
10364         if (key == NULL) {
10365                 result = dns_view_getpeertsig(zone->view, &masterip, &key);
10366                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
10367                         char addrbuf[ISC_NETADDR_FORMATSIZE];
10368                         isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
10369                         dns_zone_log(zone, ISC_LOG_ERROR,
10370                                      "unable to find TSIG key for %s", addrbuf);
10371                         goto skip_master;
10372                 }
10373         }
10374
10375         have_xfrsource = ISC_FALSE;
10376         reqnsid = zone->view->requestnsid;
10377         if (zone->view->peers != NULL) {
10378                 dns_peer_t *peer = NULL;
10379                 isc_boolean_t edns;
10380                 result = dns_peerlist_peerbyaddr(zone->view->peers,
10381                                                  &masterip, &peer);
10382                 if (result == ISC_R_SUCCESS) {
10383                         result = dns_peer_getsupportedns(peer, &edns);
10384                         if (result == ISC_R_SUCCESS && !edns)
10385                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10386                         result = dns_peer_gettransfersource(peer,
10387                                                             &zone->sourceaddr);
10388                         if (result == ISC_R_SUCCESS)
10389                                 have_xfrsource = ISC_TRUE;
10390                         if (zone->view->resolver != NULL)
10391                                 udpsize =
10392                                   dns_resolver_getudpsize(zone->view->resolver);
10393                         (void)dns_peer_getudpsize(peer, &udpsize);
10394                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
10395                 }
10396         }
10397
10398         switch (isc_sockaddr_pf(&zone->masteraddr)) {
10399         case PF_INET:
10400                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10401                         if (isc_sockaddr_equal(&zone->altxfrsource4,
10402                                                &zone->xfrsource4))
10403                                 goto skip_master;
10404                         zone->sourceaddr = zone->altxfrsource4;
10405                 } else if (!have_xfrsource)
10406                         zone->sourceaddr = zone->xfrsource4;
10407                 break;
10408         case PF_INET6:
10409                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10410                         if (isc_sockaddr_equal(&zone->altxfrsource6,
10411                                                &zone->xfrsource6))
10412                                 goto skip_master;
10413                         zone->sourceaddr = zone->altxfrsource6;
10414                 } else if (!have_xfrsource)
10415                         zone->sourceaddr = zone->xfrsource6;
10416                 break;
10417         default:
10418                 result = ISC_R_NOTIMPLEMENTED;
10419                 goto cleanup;
10420         }
10421
10422         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
10423                   DNS_REQUESTOPT_TCP : 0;
10424
10425         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10426                 result = add_opt(message, udpsize, reqnsid);
10427                 if (result != ISC_R_SUCCESS)
10428                         zone_debuglog(zone, me, 1,
10429                                       "unable to add opt record: %s",
10430                                       dns_result_totext(result));
10431         }
10432
10433         zone_iattach(zone, &dummy);
10434         timeout = 15;
10435         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10436                 timeout = 30;
10437         result = dns_request_createvia2(zone->view->requestmgr, message,
10438                                         &zone->sourceaddr, &zone->masteraddr,
10439                                         options, key, timeout * 3, timeout,
10440                                         zone->task, refresh_callback, zone,
10441                                         &zone->request);
10442         if (result != ISC_R_SUCCESS) {
10443                 zone_idetach(&dummy);
10444                 zone_debuglog(zone, me, 1,
10445                               "dns_request_createvia2() failed: %s",
10446                               dns_result_totext(result));
10447                 goto cleanup;
10448         } else {
10449                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
10450                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
10451                 else
10452                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
10453         }
10454         cancel = ISC_FALSE;
10455
10456  cleanup:
10457         if (key != NULL)
10458                 dns_tsigkey_detach(&key);
10459         if (result != ISC_R_SUCCESS)
10460                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10461         if (message != NULL)
10462                 dns_message_destroy(&message);
10463         if (cancel)
10464                 cancel_refresh(zone);
10465         isc_event_free(&event);
10466         UNLOCK_ZONE(zone);
10467         dns_zone_idetach(&zone);
10468         return;
10469
10470  skip_master:
10471         if (key != NULL)
10472                 dns_tsigkey_detach(&key);
10473         /*
10474          * Skip to next failed / untried master.
10475          */
10476         do {
10477                 zone->curmaster++;
10478         } while (zone->curmaster < zone->masterscnt &&
10479                  zone->mastersok[zone->curmaster]);
10480         if (zone->curmaster < zone->masterscnt)
10481                 goto again;
10482         zone->curmaster = 0;
10483         goto cleanup;
10484 }
10485
10486 static void
10487 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
10488         const char me[] = "ns_query";
10489         isc_result_t result;
10490         dns_message_t *message = NULL;
10491         isc_netaddr_t masterip;
10492         dns_tsigkey_t *key = NULL;
10493         dns_dbnode_t *node = NULL;
10494         int timeout;
10495         isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
10496         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10497
10498         REQUIRE(DNS_ZONE_VALID(zone));
10499         REQUIRE(LOCKED_ZONE(zone));
10500         REQUIRE((soardataset != NULL && stub == NULL) ||
10501                 (soardataset == NULL && stub != NULL));
10502         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
10503
10504         ENTER;
10505
10506         if (stub == NULL) {
10507                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
10508                 if (stub == NULL)
10509                         goto cleanup;
10510                 stub->magic = STUB_MAGIC;
10511                 stub->mctx = zone->mctx;
10512                 stub->zone = NULL;
10513                 stub->db = NULL;
10514                 stub->version = NULL;
10515
10516                 /*
10517                  * Attach so that the zone won't disappear from under us.
10518                  */
10519                 zone_iattach(zone, &stub->zone);
10520
10521                 /*
10522                  * If a db exists we will update it, otherwise we create a
10523                  * new one and attach it to the zone once we have the NS
10524                  * RRset and glue.
10525                  */
10526                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10527                 if (zone->db != NULL) {
10528                         dns_db_attach(zone->db, &stub->db);
10529                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10530                 } else {
10531                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10532
10533                         INSIST(zone->db_argc >= 1);
10534                         result = dns_db_create(zone->mctx, zone->db_argv[0],
10535                                                &zone->origin, dns_dbtype_stub,
10536                                                zone->rdclass,
10537                                                zone->db_argc - 1,
10538                                                zone->db_argv + 1,
10539                                                &stub->db);
10540                         if (result != ISC_R_SUCCESS) {
10541                                 dns_zone_log(zone, ISC_LOG_ERROR,
10542                                              "refreshing stub: "
10543                                              "could not create "
10544                                              "database: %s",
10545                                              dns_result_totext(result));
10546                                 goto cleanup;
10547                         }
10548                         dns_db_settask(stub->db, zone->task);
10549                 }
10550
10551                 result = dns_db_newversion(stub->db, &stub->version);
10552                 if (result != ISC_R_SUCCESS) {
10553                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10554                                      "dns_db_newversion() failed: %s",
10555                                      dns_result_totext(result));
10556                         goto cleanup;
10557                 }
10558
10559                 /*
10560                  * Update SOA record.
10561                  */
10562                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
10563                                          &node);
10564                 if (result != ISC_R_SUCCESS) {
10565                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10566                                      "dns_db_findnode() failed: %s",
10567                                      dns_result_totext(result));
10568                         goto cleanup;
10569                 }
10570
10571                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
10572                                             soardataset, 0, NULL);
10573                 dns_db_detachnode(stub->db, &node);
10574                 if (result != ISC_R_SUCCESS) {
10575                         dns_zone_log(zone, ISC_LOG_INFO,
10576                                      "refreshing stub: "
10577                                      "dns_db_addrdataset() failed: %s",
10578                                      dns_result_totext(result));
10579                         goto cleanup;
10580                 }
10581         }
10582
10583         /*
10584          * XXX Optimisation: Create message when zone is setup and reuse.
10585          */
10586         result = create_query(zone, dns_rdatatype_ns, &message);
10587         INSIST(result == ISC_R_SUCCESS);
10588
10589         INSIST(zone->masterscnt > 0);
10590         INSIST(zone->curmaster < zone->masterscnt);
10591         zone->masteraddr = zone->masters[zone->curmaster];
10592
10593         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10594         /*
10595          * First, look for a tsig key in the master statement, then
10596          * try for a server key.
10597          */
10598         if ((zone->masterkeynames != NULL) &&
10599             (zone->masterkeynames[zone->curmaster] != NULL)) {
10600                 dns_view_t *view = dns_zone_getview(zone);
10601                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10602                 result = dns_view_gettsig(view, keyname, &key);
10603                 if (result != ISC_R_SUCCESS) {
10604                         char namebuf[DNS_NAME_FORMATSIZE];
10605                         dns_name_format(keyname, namebuf, sizeof(namebuf));
10606                         dns_zone_log(zone, ISC_LOG_ERROR,
10607                                      "unable to find key: %s", namebuf);
10608                 }
10609         }
10610         if (key == NULL)
10611                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
10612
10613         reqnsid = zone->view->requestnsid;
10614         if (zone->view->peers != NULL) {
10615                 dns_peer_t *peer = NULL;
10616                 isc_boolean_t edns;
10617                 result = dns_peerlist_peerbyaddr(zone->view->peers,
10618                                                  &masterip, &peer);
10619                 if (result == ISC_R_SUCCESS) {
10620                         result = dns_peer_getsupportedns(peer, &edns);
10621                         if (result == ISC_R_SUCCESS && !edns)
10622                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10623                         result = dns_peer_gettransfersource(peer,
10624                                                             &zone->sourceaddr);
10625                         if (result == ISC_R_SUCCESS)
10626                                 have_xfrsource = ISC_TRUE;
10627                         if (zone->view->resolver != NULL)
10628                                 udpsize =
10629                                   dns_resolver_getudpsize(zone->view->resolver);
10630                         (void)dns_peer_getudpsize(peer, &udpsize);
10631                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
10632                 }
10633
10634         }
10635         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10636                 result = add_opt(message, udpsize, reqnsid);
10637                 if (result != ISC_R_SUCCESS)
10638                         zone_debuglog(zone, me, 1,
10639                                       "unable to add opt record: %s",
10640                                       dns_result_totext(result));
10641         }
10642
10643         /*
10644          * Always use TCP so that we shouldn't truncate in additional section.
10645          */
10646         switch (isc_sockaddr_pf(&zone->masteraddr)) {
10647         case PF_INET:
10648                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10649                         zone->sourceaddr = zone->altxfrsource4;
10650                 else if (!have_xfrsource)
10651                         zone->sourceaddr = zone->xfrsource4;
10652                 break;
10653         case PF_INET6:
10654                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10655                         zone->sourceaddr = zone->altxfrsource6;
10656                 else if (!have_xfrsource)
10657                         zone->sourceaddr = zone->xfrsource6;
10658                 break;
10659         default:
10660                 result = ISC_R_NOTIMPLEMENTED;
10661                 POST(result);
10662                 goto cleanup;
10663         }
10664         timeout = 15;
10665         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10666                 timeout = 30;
10667         result = dns_request_createvia2(zone->view->requestmgr, message,
10668                                         &zone->sourceaddr, &zone->masteraddr,
10669                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
10670                                         timeout, zone->task, stub_callback,
10671                                         stub, &zone->request);
10672         if (result != ISC_R_SUCCESS) {
10673                 zone_debuglog(zone, me, 1,
10674                               "dns_request_createvia() failed: %s",
10675                               dns_result_totext(result));
10676                 goto cleanup;
10677         }
10678         dns_message_destroy(&message);
10679         goto unlock;
10680
10681  cleanup:
10682         cancel_refresh(zone);
10683         if (stub != NULL) {
10684                 stub->magic = 0;
10685                 if (stub->version != NULL)
10686                         dns_db_closeversion(stub->db, &stub->version,
10687                                             ISC_FALSE);
10688                 if (stub->db != NULL)
10689                         dns_db_detach(&stub->db);
10690                 if (stub->zone != NULL)
10691                         zone_idetach(&stub->zone);
10692                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
10693         }
10694         if (message != NULL)
10695                 dns_message_destroy(&message);
10696  unlock:
10697         if (key != NULL)
10698                 dns_tsigkey_detach(&key);
10699         return;
10700 }
10701
10702 /*
10703  * Handle the control event.  Note that although this event causes the zone
10704  * to shut down, it is not a shutdown event in the sense of the task library.
10705  */
10706 static void
10707 zone_shutdown(isc_task_t *task, isc_event_t *event) {
10708         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
10709         isc_boolean_t free_needed, linked = ISC_FALSE;
10710
10711         UNUSED(task);
10712         REQUIRE(DNS_ZONE_VALID(zone));
10713         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
10714         INSIST(isc_refcount_current(&zone->erefs) == 0);
10715
10716         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
10717
10718         /*
10719          * Stop things being restarted after we cancel them below.
10720          */
10721         LOCK_ZONE(zone);
10722         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
10723         UNLOCK_ZONE(zone);
10724
10725         /*
10726          * If we were waiting for xfrin quota, step out of
10727          * the queue.
10728          * If there's no zone manager, we can't be waiting for the
10729          * xfrin quota
10730          */
10731         if (zone->zmgr != NULL) {
10732                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10733                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
10734                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
10735                                         statelink);
10736                         linked = ISC_TRUE;
10737                         zone->statelist = NULL;
10738                 }
10739                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10740         }
10741
10742         /*
10743          * In task context, no locking required.  See zone_xfrdone().
10744          */
10745         if (zone->xfr != NULL)
10746                 dns_xfrin_shutdown(zone->xfr);
10747
10748         LOCK_ZONE(zone);
10749         if (linked) {
10750                 INSIST(zone->irefs > 0);
10751                 zone->irefs--;
10752         }
10753         if (zone->request != NULL) {
10754                 dns_request_cancel(zone->request);
10755         }
10756
10757         if (zone->readio != NULL)
10758                 zonemgr_cancelio(zone->readio);
10759
10760         if (zone->lctx != NULL)
10761                 dns_loadctx_cancel(zone->lctx);
10762
10763         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
10764             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10765                 if (zone->writeio != NULL)
10766                         zonemgr_cancelio(zone->writeio);
10767
10768                 if (zone->dctx != NULL)
10769                         dns_dumpctx_cancel(zone->dctx);
10770         }
10771
10772         notify_cancel(zone);
10773
10774         forward_cancel(zone);
10775
10776         if (zone->timer != NULL) {
10777                 isc_timer_detach(&zone->timer);
10778                 INSIST(zone->irefs > 0);
10779                 zone->irefs--;
10780         }
10781
10782         if (zone->view != NULL)
10783                 dns_view_weakdetach(&zone->view);
10784
10785         /*
10786          * We have now canceled everything set the flag to allow exit_check()
10787          * to succeed.  We must not unlock between setting this flag and
10788          * calling exit_check().
10789          */
10790         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
10791         free_needed = exit_check(zone);
10792         UNLOCK_ZONE(zone);
10793         if (free_needed)
10794                 zone_free(zone);
10795 }
10796
10797 static void
10798 zone_timer(isc_task_t *task, isc_event_t *event) {
10799         const char me[] = "zone_timer";
10800         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
10801
10802         UNUSED(task);
10803         REQUIRE(DNS_ZONE_VALID(zone));
10804
10805         ENTER;
10806
10807         zone_maintenance(zone);
10808
10809         isc_event_free(&event);
10810 }
10811
10812 static void
10813 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
10814         const char me[] = "zone_settimer";
10815         isc_time_t next;
10816         isc_result_t result;
10817
10818         ENTER;
10819         REQUIRE(DNS_ZONE_VALID(zone));
10820         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10821                 return;
10822
10823         isc_time_settoepoch(&next);
10824
10825         switch (zone->type) {
10826         case dns_zone_master:
10827                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10828                         next = zone->notifytime;
10829                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10830                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10831                         INSIST(!isc_time_isepoch(&zone->dumptime));
10832                         if (isc_time_isepoch(&next) ||
10833                             isc_time_compare(&zone->dumptime, &next) < 0)
10834                                 next = zone->dumptime;
10835                 }
10836                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
10837                     !isc_time_isepoch(&zone->refreshkeytime)) {
10838                         if (isc_time_isepoch(&next) ||
10839                             isc_time_compare(&zone->refreshkeytime, &next) < 0)
10840                                 next = zone->refreshkeytime;
10841                 }
10842                 if (!isc_time_isepoch(&zone->resigntime)) {
10843                         if (isc_time_isepoch(&next) ||
10844                             isc_time_compare(&zone->resigntime, &next) < 0)
10845                                 next = zone->resigntime;
10846                 }
10847                 if (!isc_time_isepoch(&zone->keywarntime)) {
10848                         if (isc_time_isepoch(&next) ||
10849                             isc_time_compare(&zone->keywarntime, &next) < 0)
10850                                 next = zone->keywarntime;
10851                 }
10852                 if (!isc_time_isepoch(&zone->signingtime)) {
10853                         if (isc_time_isepoch(&next) ||
10854                             isc_time_compare(&zone->signingtime, &next) < 0)
10855                                 next = zone->signingtime;
10856                 }
10857                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
10858                         if (isc_time_isepoch(&next) ||
10859                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
10860                                 next = zone->nsec3chaintime;
10861                 }
10862                 break;
10863
10864         case dns_zone_slave:
10865                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10866                         next = zone->notifytime;
10867                 /*FALLTHROUGH*/
10868
10869         case dns_zone_stub:
10870                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
10871                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
10872                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
10873                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
10874                         INSIST(!isc_time_isepoch(&zone->refreshtime));
10875                         if (isc_time_isepoch(&next) ||
10876                             isc_time_compare(&zone->refreshtime, &next) < 0)
10877                                 next = zone->refreshtime;
10878                 }
10879                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10880                     !isc_time_isepoch(&zone->expiretime)) {
10881                         if (isc_time_isepoch(&next) ||
10882                              isc_time_compare(&zone->expiretime, &next) < 0)
10883                                 next = zone->expiretime;
10884                 }
10885                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10886                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10887                         INSIST(!isc_time_isepoch(&zone->dumptime));
10888                         if (isc_time_isepoch(&next) ||
10889                             isc_time_compare(&zone->dumptime, &next) < 0)
10890                                 next = zone->dumptime;
10891                 }
10892                 break;
10893
10894         case dns_zone_key:
10895                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10896                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10897                         INSIST(!isc_time_isepoch(&zone->dumptime));
10898                         if (isc_time_isepoch(&next) ||
10899                             isc_time_compare(&zone->dumptime, &next) < 0)
10900                                 next = zone->dumptime;
10901                 }
10902                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10903                         if (isc_time_isepoch(&next) ||
10904                             (!isc_time_isepoch(&zone->refreshkeytime) &&
10905                             isc_time_compare(&zone->refreshkeytime, &next) < 0))
10906                                 next = zone->refreshkeytime;
10907                 }
10908                 break;
10909
10910         default:
10911                 break;
10912         }
10913
10914         if (isc_time_isepoch(&next)) {
10915                 zone_debuglog(zone, me, 10, "settimer inactive");
10916                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
10917                                           NULL, NULL, ISC_TRUE);
10918                 if (result != ISC_R_SUCCESS)
10919                         dns_zone_log(zone, ISC_LOG_ERROR,
10920                                      "could not deactivate zone timer: %s",
10921                                      isc_result_totext(result));
10922         } else {
10923                 if (isc_time_compare(&next, now) <= 0)
10924                         next = *now;
10925                 result = isc_timer_reset(zone->timer, isc_timertype_once,
10926                                          &next, NULL, ISC_TRUE);
10927                 if (result != ISC_R_SUCCESS)
10928                         dns_zone_log(zone, ISC_LOG_ERROR,
10929                                      "could not reset zone timer: %s",
10930                                      isc_result_totext(result));
10931         }
10932 }
10933
10934 static void
10935 cancel_refresh(dns_zone_t *zone) {
10936         const char me[] = "cancel_refresh";
10937         isc_time_t now;
10938
10939         /*
10940          * 'zone' locked by caller.
10941          */
10942
10943         REQUIRE(DNS_ZONE_VALID(zone));
10944         REQUIRE(LOCKED_ZONE(zone));
10945
10946         ENTER;
10947
10948         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10949         TIME_NOW(&now);
10950         zone_settimer(zone, &now);
10951 }
10952
10953 static isc_result_t
10954 notify_createmessage(dns_zone_t *zone, unsigned int flags,
10955                      dns_message_t **messagep)
10956 {
10957         dns_db_t *zonedb = NULL;
10958         dns_dbnode_t *node = NULL;
10959         dns_dbversion_t *version = NULL;
10960         dns_message_t *message = NULL;
10961         dns_rdataset_t rdataset;
10962         dns_rdata_t rdata = DNS_RDATA_INIT;
10963
10964         dns_name_t *tempname = NULL;
10965         dns_rdata_t *temprdata = NULL;
10966         dns_rdatalist_t *temprdatalist = NULL;
10967         dns_rdataset_t *temprdataset = NULL;
10968
10969         isc_result_t result;
10970         isc_region_t r;
10971         isc_buffer_t *b = NULL;
10972
10973         REQUIRE(DNS_ZONE_VALID(zone));
10974         REQUIRE(messagep != NULL && *messagep == NULL);
10975
10976         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10977                                     &message);
10978         if (result != ISC_R_SUCCESS)
10979                 return (result);
10980
10981         message->opcode = dns_opcode_notify;
10982         message->flags |= DNS_MESSAGEFLAG_AA;
10983         message->rdclass = zone->rdclass;
10984
10985         result = dns_message_gettempname(message, &tempname);
10986         if (result != ISC_R_SUCCESS)
10987                 goto cleanup;
10988
10989         result = dns_message_gettemprdataset(message, &temprdataset);
10990         if (result != ISC_R_SUCCESS)
10991                 goto cleanup;
10992
10993         /*
10994          * Make question.
10995          */
10996         dns_name_init(tempname, NULL);
10997         dns_name_clone(&zone->origin, tempname);
10998         dns_rdataset_init(temprdataset);
10999         dns_rdataset_makequestion(temprdataset, zone->rdclass,
11000                                   dns_rdatatype_soa);
11001         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11002         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
11003         tempname = NULL;
11004         temprdataset = NULL;
11005
11006         if ((flags & DNS_NOTIFY_NOSOA) != 0)
11007                 goto done;
11008
11009         result = dns_message_gettempname(message, &tempname);
11010         if (result != ISC_R_SUCCESS)
11011                 goto soa_cleanup;
11012         result = dns_message_gettemprdata(message, &temprdata);
11013         if (result != ISC_R_SUCCESS)
11014                 goto soa_cleanup;
11015         result = dns_message_gettemprdataset(message, &temprdataset);
11016         if (result != ISC_R_SUCCESS)
11017                 goto soa_cleanup;
11018         result = dns_message_gettemprdatalist(message, &temprdatalist);
11019         if (result != ISC_R_SUCCESS)
11020                 goto soa_cleanup;
11021
11022         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11023         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
11024         dns_db_attach(zone->db, &zonedb);
11025         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11026
11027         dns_name_init(tempname, NULL);
11028         dns_name_clone(&zone->origin, tempname);
11029         dns_db_currentversion(zonedb, &version);
11030         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
11031         if (result != ISC_R_SUCCESS)
11032                 goto soa_cleanup;
11033
11034         dns_rdataset_init(&rdataset);
11035         result = dns_db_findrdataset(zonedb, node, version,
11036                                      dns_rdatatype_soa,
11037                                      dns_rdatatype_none, 0, &rdataset,
11038                                      NULL);
11039         if (result != ISC_R_SUCCESS)
11040                 goto soa_cleanup;
11041         result = dns_rdataset_first(&rdataset);
11042         if (result != ISC_R_SUCCESS)
11043                 goto soa_cleanup;
11044         dns_rdataset_current(&rdataset, &rdata);
11045         dns_rdata_toregion(&rdata, &r);
11046         result = isc_buffer_allocate(zone->mctx, &b, r.length);
11047         if (result != ISC_R_SUCCESS)
11048                 goto soa_cleanup;
11049         isc_buffer_putmem(b, r.base, r.length);
11050         isc_buffer_usedregion(b, &r);
11051         dns_rdata_init(temprdata);
11052         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
11053         dns_message_takebuffer(message, &b);
11054         result = dns_rdataset_next(&rdataset);
11055         dns_rdataset_disassociate(&rdataset);
11056         if (result != ISC_R_NOMORE)
11057                 goto soa_cleanup;
11058         temprdatalist->rdclass = rdata.rdclass;
11059         temprdatalist->type = rdata.type;
11060         temprdatalist->covers = 0;
11061         temprdatalist->ttl = rdataset.ttl;
11062         ISC_LIST_INIT(temprdatalist->rdata);
11063         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
11064
11065         dns_rdataset_init(temprdataset);
11066         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
11067         if (result != ISC_R_SUCCESS)
11068                 goto soa_cleanup;
11069
11070         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11071         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
11072         temprdatalist = NULL;
11073         temprdataset = NULL;
11074         temprdata = NULL;
11075         tempname = NULL;
11076
11077  soa_cleanup:
11078         if (node != NULL)
11079                 dns_db_detachnode(zonedb, &node);
11080         if (version != NULL)
11081                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
11082         if (zonedb != NULL)
11083                 dns_db_detach(&zonedb);
11084         if (tempname != NULL)
11085                 dns_message_puttempname(message, &tempname);
11086         if (temprdata != NULL)
11087                 dns_message_puttemprdata(message, &temprdata);
11088         if (temprdataset != NULL)
11089                 dns_message_puttemprdataset(message, &temprdataset);
11090         if (temprdatalist != NULL)
11091                 dns_message_puttemprdatalist(message, &temprdatalist);
11092
11093  done:
11094         *messagep = message;
11095         return (ISC_R_SUCCESS);
11096
11097  cleanup:
11098         if (tempname != NULL)
11099                 dns_message_puttempname(message, &tempname);
11100         if (temprdataset != NULL)
11101                 dns_message_puttemprdataset(message, &temprdataset);
11102         dns_message_destroy(&message);
11103         return (result);
11104 }
11105
11106 isc_result_t
11107 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
11108                        dns_message_t *msg)
11109 {
11110         unsigned int i;
11111         dns_rdata_soa_t soa;
11112         dns_rdataset_t *rdataset = NULL;
11113         dns_rdata_t rdata = DNS_RDATA_INIT;
11114         isc_result_t result;
11115         char fromtext[ISC_SOCKADDR_FORMATSIZE];
11116         int match = 0;
11117         isc_netaddr_t netaddr;
11118         isc_sockaddr_t local, remote;
11119
11120         REQUIRE(DNS_ZONE_VALID(zone));
11121
11122         /*
11123          * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
11124          * ROLLOVER.
11125          *
11126          * SOA: RFC1996
11127          * Check that 'from' is a valid notify source, (zone->masters).
11128          *      Return DNS_R_REFUSED if not.
11129          *
11130          * If the notify message contains a serial number check it
11131          * against the zones serial and return if <= current serial
11132          *
11133          * If a refresh check is progress, if so just record the
11134          * fact we received a NOTIFY and from where and return.
11135          * We will perform a new refresh check when the current one
11136          * completes. Return ISC_R_SUCCESS.
11137          *
11138          * Otherwise initiate a refresh check using 'from' as the
11139          * first address to check.  Return ISC_R_SUCCESS.
11140          */
11141
11142         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
11143
11144         /*
11145          *  We only handle NOTIFY (SOA) at the present.
11146          */
11147         LOCK_ZONE(zone);
11148         if (isc_sockaddr_pf(from) == PF_INET)
11149                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
11150         else
11151                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
11152         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
11153             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
11154                                  dns_rdatatype_soa, dns_rdatatype_none,
11155                                  NULL, NULL) != ISC_R_SUCCESS) {
11156                 UNLOCK_ZONE(zone);
11157                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
11158                         dns_zone_log(zone, ISC_LOG_NOTICE,
11159                                      "NOTIFY with no "
11160                                      "question section from: %s", fromtext);
11161                         return (DNS_R_FORMERR);
11162                 }
11163                 dns_zone_log(zone, ISC_LOG_NOTICE,
11164                              "NOTIFY zone does not match");
11165                 return (DNS_R_NOTIMP);
11166         }
11167
11168         /*
11169          * If we are a master zone just succeed.
11170          */
11171         if (zone->type == dns_zone_master) {
11172                 UNLOCK_ZONE(zone);
11173                 return (ISC_R_SUCCESS);
11174         }
11175
11176         isc_netaddr_fromsockaddr(&netaddr, from);
11177         for (i = 0; i < zone->masterscnt; i++) {
11178                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
11179                         break;
11180                 if (zone->view->aclenv.match_mapped &&
11181                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
11182                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
11183                         isc_netaddr_t na1, na2;
11184                         isc_netaddr_fromv4mapped(&na1, &netaddr);
11185                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
11186                         if (isc_netaddr_equal(&na1, &na2))
11187                                 break;
11188                 }
11189         }
11190
11191         /*
11192          * Accept notify requests from non masters if they are on
11193          * 'zone->notify_acl'.
11194          */
11195         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
11196             dns_acl_match(&netaddr, NULL, zone->notify_acl,
11197                           &zone->view->aclenv,
11198                           &match, NULL) == ISC_R_SUCCESS &&
11199             match > 0)
11200         {
11201                 /* Accept notify. */
11202         } else if (i >= zone->masterscnt) {
11203                 UNLOCK_ZONE(zone);
11204                 dns_zone_log(zone, ISC_LOG_INFO,
11205                              "refused notify from non-master: %s", fromtext);
11206                 inc_stats(zone, dns_zonestatscounter_notifyrej);
11207                 return (DNS_R_REFUSED);
11208         }
11209
11210         /*
11211          * If the zone is loaded and there are answers check the serial
11212          * to see if we need to do a refresh.  Do not worry about this
11213          * check if we are a dialup zone as we use the notify request
11214          * to trigger a refresh check.
11215          */
11216         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
11217             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11218             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
11219                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
11220                                               &zone->origin,
11221                                               dns_rdatatype_soa,
11222                                               dns_rdatatype_none, NULL,
11223                                               &rdataset);
11224                 if (result == ISC_R_SUCCESS)
11225                         result = dns_rdataset_first(rdataset);
11226                 if (result == ISC_R_SUCCESS) {
11227                         isc_uint32_t serial = 0, oldserial;
11228                         unsigned int soacount;
11229
11230                         dns_rdataset_current(rdataset, &rdata);
11231                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
11232                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11233                         serial = soa.serial;
11234                         /*
11235                          * The following should safely be performed without DB
11236                          * lock and succeed in this context.
11237                          */
11238                         result = zone_get_from_db(zone, zone->db, NULL,
11239                                                   &soacount, &oldserial, NULL,
11240                                                   NULL, NULL, NULL, NULL);
11241                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11242                         RUNTIME_CHECK(soacount > 0U);
11243                         if (isc_serial_le(serial, oldserial)) {
11244                                 dns_zone_log(zone,
11245                                              ISC_LOG_INFO,
11246                                              "notify from %s: "
11247                                              "zone is up to date",
11248                                              fromtext);
11249                                 UNLOCK_ZONE(zone);
11250                                 return (ISC_R_SUCCESS);
11251                         }
11252                 }
11253         }
11254
11255         /*
11256          * If we got this far and there was a refresh in progress just
11257          * let it complete.  Record where we got the notify from so we
11258          * can perform a refresh check when the current one completes
11259          */
11260         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
11261                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11262                 zone->notifyfrom = *from;
11263                 UNLOCK_ZONE(zone);
11264                 dns_zone_log(zone, ISC_LOG_INFO,
11265                              "notify from %s: refresh in progress, "
11266                              "refresh check queued",
11267                              fromtext);
11268                 return (ISC_R_SUCCESS);
11269         }
11270         zone->notifyfrom = *from;
11271         local = zone->masteraddr;
11272         remote = zone->sourceaddr;
11273         UNLOCK_ZONE(zone);
11274         dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
11275         dns_zone_refresh(zone);
11276         return (ISC_R_SUCCESS);
11277 }
11278
11279 void
11280 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
11281
11282         REQUIRE(DNS_ZONE_VALID(zone));
11283
11284         LOCK_ZONE(zone);
11285         if (zone->notify_acl != NULL)
11286                 dns_acl_detach(&zone->notify_acl);
11287         dns_acl_attach(acl, &zone->notify_acl);
11288         UNLOCK_ZONE(zone);
11289 }
11290
11291 void
11292 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
11293
11294         REQUIRE(DNS_ZONE_VALID(zone));
11295
11296         LOCK_ZONE(zone);
11297         if (zone->query_acl != NULL)
11298                 dns_acl_detach(&zone->query_acl);
11299         dns_acl_attach(acl, &zone->query_acl);
11300         UNLOCK_ZONE(zone);
11301 }
11302
11303 void
11304 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
11305
11306         REQUIRE(DNS_ZONE_VALID(zone));
11307
11308         LOCK_ZONE(zone);
11309         if (zone->queryon_acl != NULL)
11310                 dns_acl_detach(&zone->queryon_acl);
11311         dns_acl_attach(acl, &zone->queryon_acl);
11312         UNLOCK_ZONE(zone);
11313 }
11314
11315 void
11316 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
11317
11318         REQUIRE(DNS_ZONE_VALID(zone));
11319
11320         LOCK_ZONE(zone);
11321         if (zone->update_acl != NULL)
11322                 dns_acl_detach(&zone->update_acl);
11323         dns_acl_attach(acl, &zone->update_acl);
11324         UNLOCK_ZONE(zone);
11325 }
11326
11327 void
11328 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
11329
11330         REQUIRE(DNS_ZONE_VALID(zone));
11331
11332         LOCK_ZONE(zone);
11333         if (zone->forward_acl != NULL)
11334                 dns_acl_detach(&zone->forward_acl);
11335         dns_acl_attach(acl, &zone->forward_acl);
11336         UNLOCK_ZONE(zone);
11337 }
11338
11339 void
11340 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
11341
11342         REQUIRE(DNS_ZONE_VALID(zone));
11343
11344         LOCK_ZONE(zone);
11345         if (zone->xfr_acl != NULL)
11346                 dns_acl_detach(&zone->xfr_acl);
11347         dns_acl_attach(acl, &zone->xfr_acl);
11348         UNLOCK_ZONE(zone);
11349 }
11350
11351 dns_acl_t *
11352 dns_zone_getnotifyacl(dns_zone_t *zone) {
11353
11354         REQUIRE(DNS_ZONE_VALID(zone));
11355
11356         return (zone->notify_acl);
11357 }
11358
11359 dns_acl_t *
11360 dns_zone_getqueryacl(dns_zone_t *zone) {
11361
11362         REQUIRE(DNS_ZONE_VALID(zone));
11363
11364         return (zone->query_acl);
11365 }
11366
11367 dns_acl_t *
11368 dns_zone_getqueryonacl(dns_zone_t *zone) {
11369
11370         REQUIRE(DNS_ZONE_VALID(zone));
11371
11372         return (zone->queryon_acl);
11373 }
11374
11375 dns_acl_t *
11376 dns_zone_getupdateacl(dns_zone_t *zone) {
11377
11378         REQUIRE(DNS_ZONE_VALID(zone));
11379
11380         return (zone->update_acl);
11381 }
11382
11383 dns_acl_t *
11384 dns_zone_getforwardacl(dns_zone_t *zone) {
11385
11386         REQUIRE(DNS_ZONE_VALID(zone));
11387
11388         return (zone->forward_acl);
11389 }
11390
11391 dns_acl_t *
11392 dns_zone_getxfracl(dns_zone_t *zone) {
11393
11394         REQUIRE(DNS_ZONE_VALID(zone));
11395
11396         return (zone->xfr_acl);
11397 }
11398
11399 void
11400 dns_zone_clearupdateacl(dns_zone_t *zone) {
11401
11402         REQUIRE(DNS_ZONE_VALID(zone));
11403
11404         LOCK_ZONE(zone);
11405         if (zone->update_acl != NULL)
11406                 dns_acl_detach(&zone->update_acl);
11407         UNLOCK_ZONE(zone);
11408 }
11409
11410 void
11411 dns_zone_clearforwardacl(dns_zone_t *zone) {
11412
11413         REQUIRE(DNS_ZONE_VALID(zone));
11414
11415         LOCK_ZONE(zone);
11416         if (zone->forward_acl != NULL)
11417                 dns_acl_detach(&zone->forward_acl);
11418         UNLOCK_ZONE(zone);
11419 }
11420
11421 void
11422 dns_zone_clearnotifyacl(dns_zone_t *zone) {
11423
11424         REQUIRE(DNS_ZONE_VALID(zone));
11425
11426         LOCK_ZONE(zone);
11427         if (zone->notify_acl != NULL)
11428                 dns_acl_detach(&zone->notify_acl);
11429         UNLOCK_ZONE(zone);
11430 }
11431
11432 void
11433 dns_zone_clearqueryacl(dns_zone_t *zone) {
11434
11435         REQUIRE(DNS_ZONE_VALID(zone));
11436
11437         LOCK_ZONE(zone);
11438         if (zone->query_acl != NULL)
11439                 dns_acl_detach(&zone->query_acl);
11440         UNLOCK_ZONE(zone);
11441 }
11442
11443 void
11444 dns_zone_clearqueryonacl(dns_zone_t *zone) {
11445
11446         REQUIRE(DNS_ZONE_VALID(zone));
11447
11448         LOCK_ZONE(zone);
11449         if (zone->queryon_acl != NULL)
11450                 dns_acl_detach(&zone->queryon_acl);
11451         UNLOCK_ZONE(zone);
11452 }
11453
11454 void
11455 dns_zone_clearxfracl(dns_zone_t *zone) {
11456
11457         REQUIRE(DNS_ZONE_VALID(zone));
11458
11459         LOCK_ZONE(zone);
11460         if (zone->xfr_acl != NULL)
11461                 dns_acl_detach(&zone->xfr_acl);
11462         UNLOCK_ZONE(zone);
11463 }
11464
11465 isc_boolean_t
11466 dns_zone_getupdatedisabled(dns_zone_t *zone) {
11467         REQUIRE(DNS_ZONE_VALID(zone));
11468         return (zone->update_disabled);
11469
11470 }
11471
11472 void
11473 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
11474         REQUIRE(DNS_ZONE_VALID(zone));
11475         zone->update_disabled = state;
11476 }
11477
11478 isc_boolean_t
11479 dns_zone_getzeronosoattl(dns_zone_t *zone) {
11480         REQUIRE(DNS_ZONE_VALID(zone));
11481         return (zone->zero_no_soa_ttl);
11482
11483 }
11484
11485 void
11486 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
11487         REQUIRE(DNS_ZONE_VALID(zone));
11488         zone->zero_no_soa_ttl = state;
11489 }
11490
11491 void
11492 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
11493
11494         REQUIRE(DNS_ZONE_VALID(zone));
11495
11496         zone->check_names = severity;
11497 }
11498
11499 dns_severity_t
11500 dns_zone_getchecknames(dns_zone_t *zone) {
11501
11502         REQUIRE(DNS_ZONE_VALID(zone));
11503
11504         return (zone->check_names);
11505 }
11506
11507 void
11508 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
11509
11510         REQUIRE(DNS_ZONE_VALID(zone));
11511
11512         zone->journalsize = size;
11513 }
11514
11515 isc_int32_t
11516 dns_zone_getjournalsize(dns_zone_t *zone) {
11517
11518         REQUIRE(DNS_ZONE_VALID(zone));
11519
11520         return (zone->journalsize);
11521 }
11522
11523 static void
11524 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
11525         isc_result_t result = ISC_R_FAILURE;
11526         isc_buffer_t buffer;
11527
11528         REQUIRE(buf != NULL);
11529         REQUIRE(length > 1U);
11530
11531         /*
11532          * Leave space for terminating '\0'.
11533          */
11534         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
11535         if (dns_name_dynamic(&zone->origin))
11536                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11537         if (result != ISC_R_SUCCESS &&
11538             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11539                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
11540
11541         if (isc_buffer_availablelength(&buffer) > 0)
11542                 isc_buffer_putstr(&buffer, "/");
11543         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
11544
11545         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
11546             strcmp(zone->view->name, "_default") != 0 &&
11547             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
11548                 isc_buffer_putstr(&buffer, "/");
11549                 isc_buffer_putstr(&buffer, zone->view->name);
11550         }
11551
11552         buf[isc_buffer_usedlength(&buffer)] = '\0';
11553 }
11554
11555 static void
11556 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
11557         isc_result_t result = ISC_R_FAILURE;
11558         isc_buffer_t buffer;
11559
11560         REQUIRE(buf != NULL);
11561         REQUIRE(length > 1U);
11562
11563         /*
11564          * Leave space for terminating '\0'.
11565          */
11566         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
11567         if (dns_name_dynamic(&zone->origin))
11568                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11569         if (result != ISC_R_SUCCESS &&
11570             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11571                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
11572
11573         buf[isc_buffer_usedlength(&buffer)] = '\0';
11574 }
11575
11576 static void
11577 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
11578         isc_buffer_t buffer;
11579
11580         REQUIRE(buf != NULL);
11581         REQUIRE(length > 1U);
11582
11583         /*
11584          * Leave space for terminating '\0'.
11585          */
11586         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
11587         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
11588
11589         buf[isc_buffer_usedlength(&buffer)] = '\0';
11590 }
11591
11592 static void
11593 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
11594         isc_buffer_t buffer;
11595
11596         REQUIRE(buf != NULL);
11597         REQUIRE(length > 1U);
11598
11599
11600         /*
11601          * Leave space for terminating '\0'.
11602          */
11603         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
11604
11605         if (zone->view == NULL) {
11606                 isc_buffer_putstr(&buffer, "_none");
11607         } else if (strlen(zone->view->name)
11608                    < isc_buffer_availablelength(&buffer)) {
11609                 isc_buffer_putstr(&buffer, zone->view->name);
11610         } else {
11611                 isc_buffer_putstr(&buffer, "_toolong");
11612         }
11613
11614         buf[isc_buffer_usedlength(&buffer)] = '\0';
11615 }
11616
11617 void
11618 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
11619         REQUIRE(DNS_ZONE_VALID(zone));
11620         REQUIRE(buf != NULL);
11621         zone_namerd_tostr(zone, buf, length);
11622 }
11623
11624 static void
11625 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11626         va_list ap;
11627         char message[4096];
11628
11629         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11630                 return;
11631
11632         va_start(ap, fmt);
11633         vsnprintf(message, sizeof(message), fmt, ap);
11634         va_end(ap);
11635         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
11636                       level, "zone %s: %s", zone->strnamerd, message);
11637 }
11638
11639 void
11640 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
11641               int level, const char *fmt, ...) {
11642         va_list ap;
11643         char message[4096];
11644
11645         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11646                 return;
11647
11648         va_start(ap, fmt);
11649         vsnprintf(message, sizeof(message), fmt, ap);
11650         va_end(ap);
11651         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
11652                       level, "%s %s: %s", (zone->type == dns_zone_key) ?
11653                       "managed-keys-zone" : "zone", zone->strnamerd, message);
11654 }
11655
11656 void
11657 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11658         va_list ap;
11659         char message[4096];
11660
11661         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11662                 return;
11663
11664         va_start(ap, fmt);
11665         vsnprintf(message, sizeof(message), fmt, ap);
11666         va_end(ap);
11667         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11668                       level, "%s %s: %s", (zone->type == dns_zone_key) ?
11669                       "managed-keys-zone" : "zone", zone->strnamerd, message);
11670 }
11671
11672 static void
11673 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
11674               const char *fmt, ...)
11675 {
11676         va_list ap;
11677         char message[4096];
11678         int level = ISC_LOG_DEBUG(debuglevel);
11679
11680         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11681                 return;
11682
11683         va_start(ap, fmt);
11684         vsnprintf(message, sizeof(message), fmt, ap);
11685         va_end(ap);
11686         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11687                       level, "%s: %s %s: %s", me, zone->type != dns_zone_key ?
11688                       "zone" : "managed-keys-zone", zone->strnamerd, message);
11689 }
11690
11691 static int
11692 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
11693 {
11694         isc_result_t result;
11695         dns_name_t *name;
11696         dns_rdataset_t *curr;
11697         int count = 0;
11698
11699         result = dns_message_firstname(msg, section);
11700         while (result == ISC_R_SUCCESS) {
11701                 name = NULL;
11702                 dns_message_currentname(msg, section, &name);
11703
11704                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
11705                      curr = ISC_LIST_PREV(curr, link)) {
11706                         if (curr->type == type)
11707                                 count++;
11708                 }
11709                 result = dns_message_nextname(msg, section);
11710         }
11711
11712         return (count);
11713 }
11714
11715 void
11716 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
11717         REQUIRE(DNS_ZONE_VALID(zone));
11718
11719         zone->maxxfrin = maxxfrin;
11720 }
11721
11722 isc_uint32_t
11723 dns_zone_getmaxxfrin(dns_zone_t *zone) {
11724         REQUIRE(DNS_ZONE_VALID(zone));
11725
11726         return (zone->maxxfrin);
11727 }
11728
11729 void
11730 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
11731         REQUIRE(DNS_ZONE_VALID(zone));
11732         zone->maxxfrout = maxxfrout;
11733 }
11734
11735 isc_uint32_t
11736 dns_zone_getmaxxfrout(dns_zone_t *zone) {
11737         REQUIRE(DNS_ZONE_VALID(zone));
11738
11739         return (zone->maxxfrout);
11740 }
11741
11742 dns_zonetype_t
11743 dns_zone_gettype(dns_zone_t *zone) {
11744         REQUIRE(DNS_ZONE_VALID(zone));
11745
11746         return (zone->type);
11747 }
11748
11749 dns_name_t *
11750 dns_zone_getorigin(dns_zone_t *zone) {
11751         REQUIRE(DNS_ZONE_VALID(zone));
11752
11753         return (&zone->origin);
11754 }
11755
11756 void
11757 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
11758         REQUIRE(DNS_ZONE_VALID(zone));
11759
11760         LOCK_ZONE(zone);
11761         if (zone->task != NULL)
11762                 isc_task_detach(&zone->task);
11763         isc_task_attach(task, &zone->task);
11764         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11765         if (zone->db != NULL)
11766                 dns_db_settask(zone->db, zone->task);
11767         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11768         UNLOCK_ZONE(zone);
11769 }
11770
11771 void
11772 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
11773         REQUIRE(DNS_ZONE_VALID(zone));
11774         isc_task_attach(zone->task, target);
11775 }
11776
11777 void
11778 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
11779         REQUIRE(DNS_ZONE_VALID(zone));
11780
11781         if (idlein == 0)
11782                 idlein = DNS_DEFAULT_IDLEIN;
11783         zone->idlein = idlein;
11784 }
11785
11786 isc_uint32_t
11787 dns_zone_getidlein(dns_zone_t *zone) {
11788         REQUIRE(DNS_ZONE_VALID(zone));
11789
11790         return (zone->idlein);
11791 }
11792
11793 void
11794 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
11795         REQUIRE(DNS_ZONE_VALID(zone));
11796
11797         zone->idleout = idleout;
11798 }
11799
11800 isc_uint32_t
11801 dns_zone_getidleout(dns_zone_t *zone) {
11802         REQUIRE(DNS_ZONE_VALID(zone));
11803
11804         return (zone->idleout);
11805 }
11806
11807 static void
11808 notify_done(isc_task_t *task, isc_event_t *event) {
11809         dns_requestevent_t *revent = (dns_requestevent_t *)event;
11810         dns_notify_t *notify;
11811         isc_result_t result;
11812         dns_message_t *message = NULL;
11813         isc_buffer_t buf;
11814         char rcode[128];
11815         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
11816
11817         UNUSED(task);
11818
11819         notify = event->ev_arg;
11820         REQUIRE(DNS_NOTIFY_VALID(notify));
11821         INSIST(task == notify->zone->task);
11822
11823         isc_buffer_init(&buf, rcode, sizeof(rcode));
11824         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
11825
11826         result = revent->result;
11827         if (result == ISC_R_SUCCESS)
11828                 result = dns_message_create(notify->zone->mctx,
11829                                             DNS_MESSAGE_INTENTPARSE, &message);
11830         if (result == ISC_R_SUCCESS)
11831                 result = dns_request_getresponse(revent->request, message,
11832                                         DNS_MESSAGEPARSE_PRESERVEORDER);
11833         if (result == ISC_R_SUCCESS)
11834                 result = dns_rcode_totext(message->rcode, &buf);
11835         if (result == ISC_R_SUCCESS)
11836                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
11837                            "notify response from %s: %.*s",
11838                            addrbuf, (int)buf.used, rcode);
11839         else
11840                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
11841                            "notify to %s failed: %s", addrbuf,
11842                            dns_result_totext(result));
11843
11844         /*
11845          * Old bind's return formerr if they see a soa record.  Retry w/o
11846          * the soa if we see a formerr and had sent a SOA.
11847          */
11848         isc_event_free(&event);
11849         if (message != NULL && message->rcode == dns_rcode_formerr &&
11850             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
11851                 notify->flags |= DNS_NOTIFY_NOSOA;
11852                 dns_request_destroy(&notify->request);
11853                 result = notify_send_queue(notify);
11854                 if (result != ISC_R_SUCCESS)
11855                         notify_destroy(notify, ISC_FALSE);
11856         } else {
11857                 if (result == ISC_R_TIMEDOUT)
11858                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
11859                                    "notify to %s: retries exceeded", addrbuf);
11860                 notify_destroy(notify, ISC_FALSE);
11861         }
11862         if (message != NULL)
11863                 dns_message_destroy(&message);
11864 }
11865
11866 isc_result_t
11867 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11868         isc_result_t result;
11869
11870         REQUIRE(DNS_ZONE_VALID(zone));
11871         LOCK_ZONE(zone);
11872         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11873         result = zone_replacedb(zone, db, dump);
11874         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11875         UNLOCK_ZONE(zone);
11876         return (result);
11877 }
11878
11879 static isc_result_t
11880 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11881         dns_dbversion_t *ver;
11882         isc_result_t result;
11883         unsigned int soacount = 0;
11884         unsigned int nscount = 0;
11885
11886         /*
11887          * 'zone' and 'zonedb' locked by caller.
11888          */
11889         REQUIRE(DNS_ZONE_VALID(zone));
11890         REQUIRE(LOCKED_ZONE(zone));
11891
11892         result = zone_get_from_db(zone, db, &nscount, &soacount,
11893                                   NULL, NULL, NULL, NULL, NULL, NULL);
11894         if (result == ISC_R_SUCCESS) {
11895                 if (soacount != 1) {
11896                         dns_zone_log(zone, ISC_LOG_ERROR,
11897                                      "has %d SOA records", soacount);
11898                         result = DNS_R_BADZONE;
11899                 }
11900                 if (nscount == 0 && zone->type != dns_zone_key) {
11901                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
11902                         result = DNS_R_BADZONE;
11903                 }
11904                 if (result != ISC_R_SUCCESS)
11905                         return (result);
11906         } else {
11907                 dns_zone_log(zone, ISC_LOG_ERROR,
11908                             "retrieving SOA and NS records failed: %s",
11909                             dns_result_totext(result));
11910                 return (result);
11911         }
11912
11913         result = check_nsec3param(zone, db);
11914         if (result != ISC_R_SUCCESS)
11915                 return (result);
11916
11917         ver = NULL;
11918         dns_db_currentversion(db, &ver);
11919
11920         /*
11921          * The initial version of a slave zone is always dumped;
11922          * subsequent versions may be journaled instead if this
11923          * is enabled in the configuration.
11924          */
11925         if (zone->db != NULL && zone->journal != NULL &&
11926             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
11927             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
11928                 isc_uint32_t serial, oldserial;
11929                 unsigned int soacount;
11930
11931                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
11932
11933                 result = dns_db_getsoaserial(db, ver, &serial);
11934                 if (result != ISC_R_SUCCESS) {
11935                         dns_zone_log(zone, ISC_LOG_ERROR,
11936                                      "ixfr-from-differences: unable to get "
11937                                      "new serial");
11938                         goto fail;
11939                 }
11940
11941                 /*
11942                  * This is checked in zone_postload() for master zones.
11943                  */
11944                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
11945                                           &oldserial, NULL, NULL, NULL, NULL,
11946                                           NULL);
11947                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11948                 RUNTIME_CHECK(soacount > 0U);
11949                 if (zone->type == dns_zone_slave &&
11950                     !isc_serial_gt(serial, oldserial)) {
11951                         isc_uint32_t serialmin, serialmax;
11952                         serialmin = (oldserial + 1) & 0xffffffffU;
11953                         serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
11954                         dns_zone_log(zone, ISC_LOG_ERROR,
11955                                      "ixfr-from-differences: failed: "
11956                                      "new serial (%u) out of range [%u - %u]",
11957                                      serial, serialmin, serialmax);
11958                         result = ISC_R_RANGE;
11959                         goto fail;
11960                 }
11961
11962                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
11963                                      zone->journal);
11964                 if (result != ISC_R_SUCCESS)
11965                         goto fail;
11966                 if (dump)
11967                         zone_needdump(zone, DNS_DUMP_DELAY);
11968                 else if (zone->journalsize != -1) {
11969                         result = dns_journal_compact(zone->mctx, zone->journal,
11970                                                      serial, zone->journalsize);
11971                         switch (result) {
11972                         case ISC_R_SUCCESS:
11973                         case ISC_R_NOSPACE:
11974                         case ISC_R_NOTFOUND:
11975                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
11976                                              "dns_journal_compact: %s",
11977                                              dns_result_totext(result));
11978                                 break;
11979                         default:
11980                                 dns_zone_log(zone, ISC_LOG_ERROR,
11981                                              "dns_journal_compact failed: %s",
11982                                              dns_result_totext(result));
11983                                 break;
11984                         }
11985                 }
11986         } else {
11987                 if (dump && zone->masterfile != NULL) {
11988                         /*
11989                          * If DNS_ZONEFLG_FORCEXFER was set we don't want
11990                          * to keep the old masterfile.
11991                          */
11992                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
11993                             remove(zone->masterfile) < 0 && errno != ENOENT) {
11994                                 char strbuf[ISC_STRERRORSIZE];
11995                                 isc__strerror(errno, strbuf, sizeof(strbuf));
11996                                 isc_log_write(dns_lctx,
11997                                               DNS_LOGCATEGORY_GENERAL,
11998                                               DNS_LOGMODULE_ZONE,
11999                                               ISC_LOG_WARNING,
12000                                               "unable to remove masterfile "
12001                                               "'%s': '%s'",
12002                                               zone->masterfile, strbuf);
12003                         }
12004                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
12005                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
12006                         else
12007                                 zone_needdump(zone, 0);
12008                 }
12009                 if (dump && zone->journal != NULL) {
12010                         /*
12011                          * The in-memory database just changed, and
12012                          * because 'dump' is set, it didn't change by
12013                          * being loaded from disk.  Also, we have not
12014                          * journaled diffs for this change.
12015                          * Therefore, the on-disk journal is missing
12016                          * the deltas for this change.  Since it can
12017                          * no longer be used to bring the zone
12018                          * up-to-date, it is useless and should be
12019                          * removed.
12020                          */
12021                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
12022                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
12023                                       "removing journal file");
12024                         if (remove(zone->journal) < 0 && errno != ENOENT) {
12025                                 char strbuf[ISC_STRERRORSIZE];
12026                                 isc__strerror(errno, strbuf, sizeof(strbuf));
12027                                 isc_log_write(dns_lctx,
12028                                               DNS_LOGCATEGORY_GENERAL,
12029                                               DNS_LOGMODULE_ZONE,
12030                                               ISC_LOG_WARNING,
12031                                               "unable to remove journal "
12032                                               "'%s': '%s'",
12033                                               zone->journal, strbuf);
12034                         }
12035                 }
12036         }
12037
12038         dns_db_closeversion(db, &ver, ISC_FALSE);
12039
12040         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
12041                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
12042                       "replacing zone database");
12043
12044         if (zone->db != NULL)
12045                 zone_detachdb(zone);
12046         zone_attachdb(zone, db);
12047         dns_db_settask(zone->db, zone->task);
12048         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
12049         return (ISC_R_SUCCESS);
12050
12051  fail:
12052         dns_db_closeversion(db, &ver, ISC_FALSE);
12053         return (result);
12054 }
12055
12056 /* The caller must hold the dblock as a writer. */
12057 static inline void
12058 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
12059         REQUIRE(zone->db == NULL && db != NULL);
12060
12061         dns_db_attach(db, &zone->db);
12062         if (zone->acache != NULL) {
12063                 isc_result_t result;
12064                 result = dns_acache_setdb(zone->acache, db);
12065                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
12066                         UNEXPECTED_ERROR(__FILE__, __LINE__,
12067                                          "dns_acache_setdb() failed: %s",
12068                                          isc_result_totext(result));
12069                 }
12070         }
12071 }
12072
12073 /* The caller must hold the dblock as a writer. */
12074 static inline void
12075 zone_detachdb(dns_zone_t *zone) {
12076         REQUIRE(zone->db != NULL);
12077
12078         if (zone->acache != NULL)
12079                 (void)dns_acache_putdb(zone->acache, zone->db);
12080         dns_db_detach(&zone->db);
12081 }
12082
12083 static void
12084 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
12085         isc_time_t now;
12086         isc_boolean_t again = ISC_FALSE;
12087         unsigned int soacount;
12088         unsigned int nscount;
12089         isc_uint32_t serial, refresh, retry, expire, minimum;
12090         isc_result_t xfrresult = result;
12091         isc_boolean_t free_needed;
12092
12093         REQUIRE(DNS_ZONE_VALID(zone));
12094
12095         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12096                      "zone transfer finished: %s", dns_result_totext(result));
12097
12098         LOCK_ZONE(zone);
12099         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
12100         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12101         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
12102
12103         TIME_NOW(&now);
12104         switch (result) {
12105         case ISC_R_SUCCESS:
12106                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12107                 /*FALLTHROUGH*/
12108         case DNS_R_UPTODATE:
12109                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
12110                 /*
12111                  * Has the zone expired underneath us?
12112                  */
12113                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12114                 if (zone->db == NULL) {
12115                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12116                         goto same_master;
12117                 }
12118
12119                 /*
12120                  * Update the zone structure's data from the actual
12121                  * SOA received.
12122                  */
12123                 nscount = 0;
12124                 soacount = 0;
12125                 INSIST(zone->db != NULL);
12126                 result = zone_get_from_db(zone, zone->db, &nscount,
12127                                           &soacount, &serial, &refresh,
12128                                           &retry, &expire, &minimum, NULL);
12129                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12130                 if (result == ISC_R_SUCCESS) {
12131                         if (soacount != 1)
12132                                 dns_zone_log(zone, ISC_LOG_ERROR,
12133                                              "transferred zone "
12134                                              "has %d SOA record%s", soacount,
12135                                              (soacount != 0) ? "s" : "");
12136                         if (nscount == 0) {
12137                                 dns_zone_log(zone, ISC_LOG_ERROR,
12138                                              "transferred zone "
12139                                              "has no NS records");
12140                                 if (DNS_ZONE_FLAG(zone,
12141                                                   DNS_ZONEFLG_HAVETIMERS)) {
12142                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
12143                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
12144                                 }
12145                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
12146                                 zone_unload(zone);
12147                                 goto next_master;
12148                         }
12149                         zone->refresh = RANGE(refresh, zone->minrefresh,
12150                                               zone->maxrefresh);
12151                         zone->retry = RANGE(retry, zone->minretry,
12152                                             zone->maxretry);
12153                         zone->expire = RANGE(expire,
12154                                              zone->refresh + zone->retry,
12155                                              DNS_MAX_EXPIRE);
12156                         zone->minimum = minimum;
12157                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
12158                 }
12159
12160                 /*
12161                  * Set our next update/expire times.
12162                  */
12163                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
12164                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12165                         zone->refreshtime = now;
12166                         DNS_ZONE_TIME_ADD(&now, zone->expire,
12167                                           &zone->expiretime);
12168                 } else {
12169                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
12170                                             &zone->refreshtime);
12171                         DNS_ZONE_TIME_ADD(&now, zone->expire,
12172                                           &zone->expiretime);
12173                 }
12174                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
12175                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
12176                         if (zone->tsigkey != NULL) {
12177                                 char namebuf[DNS_NAME_FORMATSIZE];
12178                                 dns_name_format(&zone->tsigkey->name, namebuf,
12179                                                 sizeof(namebuf));
12180                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
12181                                          namebuf);
12182                         } else
12183                                 buf[0] = '\0';
12184                         dns_zone_log(zone, ISC_LOG_INFO,
12185                                      "transferred serial %u%s",
12186                                      serial, buf);
12187                 }
12188
12189                 /*
12190                  * This is not necessary if we just performed a AXFR
12191                  * however it is necessary for an IXFR / UPTODATE and
12192                  * won't hurt with an AXFR.
12193                  */
12194                 if (zone->masterfile != NULL || zone->journal != NULL) {
12195                         unsigned int delay = DNS_DUMP_DELAY;
12196
12197                         result = ISC_R_FAILURE;
12198                         if (zone->journal != NULL)
12199                                 result = isc_file_settime(zone->journal, &now);
12200                         if (result != ISC_R_SUCCESS &&
12201                             zone->masterfile != NULL)
12202                                 result = isc_file_settime(zone->masterfile,
12203                                                           &now);
12204
12205                         if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
12206                             result == ISC_R_FILENOTFOUND)
12207                                 delay = 0;
12208
12209                         if ((result == ISC_R_SUCCESS ||
12210                             result == ISC_R_FILENOTFOUND) &&
12211                             zone->masterfile != NULL)
12212                                 zone_needdump(zone, delay);
12213                         else if (result != ISC_R_SUCCESS)
12214                                 dns_zone_log(zone, ISC_LOG_ERROR,
12215                                              "transfer: could not set file "
12216                                              "modification time of '%s': %s",
12217                                              zone->masterfile,
12218                                              dns_result_totext(result));
12219                 }
12220                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
12221                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
12222                 break;
12223
12224         case DNS_R_BADIXFR:
12225                 /* Force retry with AXFR. */
12226                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
12227                 goto same_master;
12228
12229         default:
12230         next_master:
12231                 /*
12232                  * Skip to next failed / untried master.
12233                  */
12234                 do {
12235                         zone->curmaster++;
12236                 } while (zone->curmaster < zone->masterscnt &&
12237                          zone->mastersok[zone->curmaster]);
12238                 /* FALLTHROUGH */
12239         same_master:
12240                 if (zone->curmaster >= zone->masterscnt) {
12241                         zone->curmaster = 0;
12242                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
12243                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12244                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
12245                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12246                                 while (zone->curmaster < zone->masterscnt &&
12247                                        zone->mastersok[zone->curmaster])
12248                                         zone->curmaster++;
12249                                 again = ISC_TRUE;
12250                         } else
12251                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12252                 } else {
12253                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
12254                         again = ISC_TRUE;
12255                 }
12256                 inc_stats(zone, dns_zonestatscounter_xfrfail);
12257                 break;
12258         }
12259         zone_settimer(zone, &now);
12260
12261         /*
12262          * If creating the transfer object failed, zone->xfr is NULL.
12263          * Otherwise, we are called as the done callback of a zone
12264          * transfer object that just entered its shutting-down
12265          * state.  Since we are no longer responsible for shutting
12266          * it down, we can detach our reference.
12267          */
12268         if (zone->xfr != NULL)
12269                 dns_xfrin_detach(&zone->xfr);
12270
12271         if (zone->tsigkey != NULL)
12272                 dns_tsigkey_detach(&zone->tsigkey);
12273
12274         /*
12275          * Handle any deferred journal compaction.
12276          */
12277         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
12278                 result = dns_journal_compact(zone->mctx, zone->journal,
12279                                              zone->compact_serial,
12280                                              zone->journalsize);
12281                 switch (result) {
12282                 case ISC_R_SUCCESS:
12283                 case ISC_R_NOSPACE:
12284                 case ISC_R_NOTFOUND:
12285                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
12286                                      "dns_journal_compact: %s",
12287                                      dns_result_totext(result));
12288                         break;
12289                 default:
12290                         dns_zone_log(zone, ISC_LOG_ERROR,
12291                                      "dns_journal_compact failed: %s",
12292                                      dns_result_totext(result));
12293                         break;
12294                 }
12295                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
12296         }
12297
12298         /*
12299          * This transfer finishing freed up a transfer quota slot.
12300          * Let any other zones waiting for quota have it.
12301          */
12302         UNLOCK_ZONE(zone);
12303         RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12304         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
12305         zone->statelist = NULL;
12306         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
12307         RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12308         LOCK_ZONE(zone);
12309
12310         /*
12311          * Retry with a different server if necessary.
12312          */
12313         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12314                 queue_soa_query(zone);
12315
12316         INSIST(zone->irefs > 0);
12317         zone->irefs--;
12318         free_needed = exit_check(zone);
12319         UNLOCK_ZONE(zone);
12320         if (free_needed)
12321                 zone_free(zone);
12322 }
12323
12324 static void
12325 zone_loaddone(void *arg, isc_result_t result) {
12326         static char me[] = "zone_loaddone";
12327         dns_load_t *load = arg;
12328         dns_zone_t *zone;
12329         isc_result_t tresult;
12330
12331         REQUIRE(DNS_LOAD_VALID(load));
12332         zone = load->zone;
12333
12334         ENTER;
12335
12336         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
12337         if (tresult != ISC_R_SUCCESS &&
12338             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
12339                 result = tresult;
12340
12341         LOCK_ZONE(load->zone);
12342         (void)zone_postload(load->zone, load->db, load->loadtime, result);
12343         zonemgr_putio(&load->zone->readio);
12344         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
12345         /*
12346          * Leave the zone frozen if the reload fails.
12347          */
12348         if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
12349              DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW))
12350                 zone->update_disabled = ISC_FALSE;
12351         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW);
12352         UNLOCK_ZONE(load->zone);
12353
12354         load->magic = 0;
12355         dns_db_detach(&load->db);
12356         if (load->zone->lctx != NULL)
12357                 dns_loadctx_detach(&load->zone->lctx);
12358         dns_zone_idetach(&load->zone);
12359         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
12360 }
12361
12362 void
12363 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
12364         REQUIRE(DNS_ZONE_VALID(zone));
12365         REQUIRE(table != NULL);
12366         REQUIRE(*table == NULL);
12367
12368         LOCK_ZONE(zone);
12369         if (zone->ssutable != NULL)
12370                 dns_ssutable_attach(zone->ssutable, table);
12371         UNLOCK_ZONE(zone);
12372 }
12373
12374 void
12375 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
12376         REQUIRE(DNS_ZONE_VALID(zone));
12377
12378         LOCK_ZONE(zone);
12379         if (zone->ssutable != NULL)
12380                 dns_ssutable_detach(&zone->ssutable);
12381         if (table != NULL)
12382                 dns_ssutable_attach(table, &zone->ssutable);
12383         UNLOCK_ZONE(zone);
12384 }
12385
12386 void
12387 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
12388         REQUIRE(DNS_ZONE_VALID(zone));
12389
12390         zone->sigvalidityinterval = interval;
12391 }
12392
12393 isc_uint32_t
12394 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
12395         REQUIRE(DNS_ZONE_VALID(zone));
12396
12397         return (zone->sigvalidityinterval);
12398 }
12399
12400 void
12401 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
12402         isc_time_t now;
12403
12404         REQUIRE(DNS_ZONE_VALID(zone));
12405
12406         LOCK_ZONE(zone);
12407         zone->sigresigninginterval = interval;
12408         set_resigntime(zone);
12409         if (zone->task != NULL) {
12410                 TIME_NOW(&now);
12411                 zone_settimer(zone, &now);
12412         }
12413         UNLOCK_ZONE(zone);
12414 }
12415
12416 isc_uint32_t
12417 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
12418         REQUIRE(DNS_ZONE_VALID(zone));
12419
12420         return (zone->sigresigninginterval);
12421 }
12422
12423 static void
12424 queue_xfrin(dns_zone_t *zone) {
12425         const char me[] = "queue_xfrin";
12426         isc_result_t result;
12427         dns_zonemgr_t *zmgr = zone->zmgr;
12428
12429         ENTER;
12430
12431         INSIST(zone->statelist == NULL);
12432
12433         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12434         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
12435         LOCK_ZONE(zone);
12436         zone->irefs++;
12437         UNLOCK_ZONE(zone);
12438         zone->statelist = &zmgr->waiting_for_xfrin;
12439         result = zmgr_start_xfrin_ifquota(zmgr, zone);
12440         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12441
12442         if (result == ISC_R_QUOTA) {
12443                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
12444                               "zone transfer deferred due to quota");
12445         } else if (result != ISC_R_SUCCESS) {
12446                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
12447                               "starting zone transfer: %s",
12448                               isc_result_totext(result));
12449         }
12450 }
12451
12452 /*
12453  * This event callback is called when a zone has received
12454  * any necessary zone transfer quota.  This is the time
12455  * to go ahead and start the transfer.
12456  */
12457 static void
12458 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
12459         isc_result_t result;
12460         dns_peer_t *peer = NULL;
12461         char master[ISC_SOCKADDR_FORMATSIZE];
12462         char source[ISC_SOCKADDR_FORMATSIZE];
12463         dns_rdatatype_t xfrtype;
12464         dns_zone_t *zone = event->ev_arg;
12465         isc_netaddr_t masterip;
12466         isc_sockaddr_t sourceaddr;
12467         isc_sockaddr_t masteraddr;
12468         isc_time_t now;
12469         const char *soa_before = "";
12470
12471         UNUSED(task);
12472
12473         INSIST(task == zone->task);
12474
12475         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12476                 result = ISC_R_CANCELED;
12477                 goto cleanup;
12478         }
12479
12480         TIME_NOW(&now);
12481
12482         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12483         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
12484                                     &zone->sourceaddr, &now))
12485         {
12486                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12487                 dns_zone_log(zone, ISC_LOG_INFO,
12488                              "got_transfer_quota: skipping zone transfer as "
12489                              "master %s (source %s) is unreachable (cached)",
12490                              master, source);
12491                 result = ISC_R_CANCELED;
12492                 goto cleanup;
12493         }
12494
12495         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12496         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
12497
12498         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12499                 soa_before = "SOA before ";
12500         /*
12501          * Decide whether we should request IXFR or AXFR.
12502          */
12503         if (zone->db == NULL) {
12504                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12505                              "no database exists yet, requesting AXFR of "
12506                              "initial version from %s", master);
12507                 xfrtype = dns_rdatatype_axfr;
12508         } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
12509                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
12510                              "set, requesting %sAXFR from %s", soa_before,
12511                              master);
12512                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12513                         xfrtype = dns_rdatatype_soa;
12514                 else
12515                         xfrtype = dns_rdatatype_axfr;
12516         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
12517                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12518                              "forced reload, requesting AXFR of "
12519                              "initial version from %s", master);
12520                 xfrtype = dns_rdatatype_axfr;
12521         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
12522                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12523                              "retrying with AXFR from %s due to "
12524                              "previous IXFR failure", master);
12525                 xfrtype = dns_rdatatype_axfr;
12526                 LOCK_ZONE(zone);
12527                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
12528                 UNLOCK_ZONE(zone);
12529         } else {
12530                 isc_boolean_t use_ixfr = ISC_TRUE;
12531                 if (peer != NULL &&
12532                     dns_peer_getrequestixfr(peer, &use_ixfr) ==
12533                     ISC_R_SUCCESS) {
12534                         ; /* Using peer setting */
12535                 } else {
12536                         use_ixfr = zone->view->requestixfr;
12537                 }
12538                 if (use_ixfr == ISC_FALSE) {
12539                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12540                                      "IXFR disabled, requesting %sAXFR from %s",
12541                                      soa_before, master);
12542                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12543                                 xfrtype = dns_rdatatype_soa;
12544                         else
12545                                 xfrtype = dns_rdatatype_axfr;
12546                 } else {
12547                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12548                                      "requesting IXFR from %s", master);
12549                         xfrtype = dns_rdatatype_ixfr;
12550                 }
12551         }
12552
12553         /*
12554          * Determine if we should attempt to sign the request with TSIG.
12555          */
12556         result = ISC_R_NOTFOUND;
12557         /*
12558          * First, look for a tsig key in the master statement, then
12559          * try for a server key.
12560          */
12561         if ((zone->masterkeynames != NULL) &&
12562             (zone->masterkeynames[zone->curmaster] != NULL)) {
12563                 dns_view_t *view = dns_zone_getview(zone);
12564                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12565                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
12566         }
12567         if (zone->tsigkey == NULL)
12568                 result = dns_view_getpeertsig(zone->view, &masterip,
12569                                               &zone->tsigkey);
12570
12571         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12572                 dns_zone_log(zone, ISC_LOG_ERROR,
12573                              "could not get TSIG key for zone transfer: %s",
12574                              isc_result_totext(result));
12575         }
12576
12577         LOCK_ZONE(zone);
12578         masteraddr = zone->masteraddr;
12579         sourceaddr = zone->sourceaddr;
12580         UNLOCK_ZONE(zone);
12581         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
12582         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
12583                                    zone->tsigkey, zone->mctx,
12584                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
12585                                    zone->task, zone_xfrdone, &zone->xfr);
12586         if (result == ISC_R_SUCCESS) {
12587                 LOCK_ZONE(zone);
12588                 if (xfrtype == dns_rdatatype_axfr) {
12589                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12590                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
12591                         else
12592                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
12593                 } else if (xfrtype == dns_rdatatype_ixfr) {
12594                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12595                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
12596                         else
12597                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
12598                 }
12599                 UNLOCK_ZONE(zone);
12600         }
12601  cleanup:
12602         /*
12603          * Any failure in this function is handled like a failed
12604          * zone transfer.  This ensures that we get removed from
12605          * zmgr->xfrin_in_progress.
12606          */
12607         if (result != ISC_R_SUCCESS)
12608                 zone_xfrdone(zone, result);
12609
12610         isc_event_free(&event);
12611 }
12612
12613 /*
12614  * Update forwarding support.
12615  */
12616
12617 static void
12618 forward_destroy(dns_forward_t *forward) {
12619
12620         forward->magic = 0;
12621         if (forward->request != NULL)
12622                 dns_request_destroy(&forward->request);
12623         if (forward->msgbuf != NULL)
12624                 isc_buffer_free(&forward->msgbuf);
12625         if (forward->zone != NULL) {
12626                 LOCK(&forward->zone->lock);
12627                 if (ISC_LINK_LINKED(forward, link))
12628                         ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
12629                 UNLOCK(&forward->zone->lock);
12630                 dns_zone_idetach(&forward->zone);
12631         }
12632         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
12633 }
12634
12635 static isc_result_t
12636 sendtomaster(dns_forward_t *forward) {
12637         isc_result_t result;
12638         isc_sockaddr_t src;
12639
12640         LOCK_ZONE(forward->zone);
12641
12642         if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
12643                 UNLOCK_ZONE(forward->zone);
12644                 return (ISC_R_CANCELED);
12645         }
12646
12647         if (forward->which >= forward->zone->masterscnt) {
12648                 UNLOCK_ZONE(forward->zone);
12649                 return (ISC_R_NOMORE);
12650         }
12651
12652         forward->addr = forward->zone->masters[forward->which];
12653         /*
12654          * Always use TCP regardless of whether the original update
12655          * used TCP.
12656          * XXX The timeout may but a bit small if we are far down a
12657          * transfer graph and the master has to try several masters.
12658          */
12659         switch (isc_sockaddr_pf(&forward->addr)) {
12660         case PF_INET:
12661                 src = forward->zone->xfrsource4;
12662                 break;
12663         case PF_INET6:
12664                 src = forward->zone->xfrsource6;
12665                 break;
12666         default:
12667                 result = ISC_R_NOTIMPLEMENTED;
12668                 goto unlock;
12669         }
12670         result = dns_request_createraw(forward->zone->view->requestmgr,
12671                                        forward->msgbuf,
12672                                        &src, &forward->addr,
12673                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
12674                                        forward->zone->task,
12675                                        forward_callback, forward,
12676                                        &forward->request);
12677         if (result == ISC_R_SUCCESS) {
12678                 if (!ISC_LINK_LINKED(forward, link))
12679                         ISC_LIST_APPEND(forward->zone->forwards, forward, link);
12680         }
12681
12682  unlock:
12683         UNLOCK_ZONE(forward->zone);
12684         return (result);
12685 }
12686
12687 static void
12688 forward_callback(isc_task_t *task, isc_event_t *event) {
12689         const char me[] = "forward_callback";
12690         dns_requestevent_t *revent = (dns_requestevent_t *)event;
12691         dns_message_t *msg = NULL;
12692         char master[ISC_SOCKADDR_FORMATSIZE];
12693         isc_result_t result;
12694         dns_forward_t *forward;
12695         dns_zone_t *zone;
12696
12697         UNUSED(task);
12698
12699         forward = revent->ev_arg;
12700         INSIST(DNS_FORWARD_VALID(forward));
12701         zone = forward->zone;
12702         INSIST(DNS_ZONE_VALID(zone));
12703
12704         ENTER;
12705
12706         isc_sockaddr_format(&forward->addr, master, sizeof(master));
12707
12708         if (revent->result != ISC_R_SUCCESS) {
12709                 dns_zone_log(zone, ISC_LOG_INFO,
12710                              "could not forward dynamic update to %s: %s",
12711                              master, dns_result_totext(revent->result));
12712                 goto next_master;
12713         }
12714
12715         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12716         if (result != ISC_R_SUCCESS)
12717                 goto next_master;
12718
12719         result = dns_request_getresponse(revent->request, msg,
12720                                          DNS_MESSAGEPARSE_PRESERVEORDER |
12721                                          DNS_MESSAGEPARSE_CLONEBUFFER);
12722         if (result != ISC_R_SUCCESS)
12723                 goto next_master;
12724
12725         switch (msg->rcode) {
12726         /*
12727          * Pass these rcodes back to client.
12728          */
12729         case dns_rcode_noerror:
12730         case dns_rcode_yxdomain:
12731         case dns_rcode_yxrrset:
12732         case dns_rcode_nxrrset:
12733         case dns_rcode_refused:
12734         case dns_rcode_nxdomain: {
12735                 char rcode[128];
12736                 isc_buffer_t rb;
12737
12738                 isc_buffer_init(&rb, rcode, sizeof(rcode));
12739                 (void)dns_rcode_totext(msg->rcode, &rb);
12740                 dns_zone_log(zone, ISC_LOG_INFO,
12741                              "forwarded dynamic update: "
12742                              "master %s returned: %.*s",
12743                              master, (int)rb.used, rcode);
12744                 break;
12745         }
12746
12747         /* These should not occur if the masters/zone are valid. */
12748         case dns_rcode_notzone:
12749         case dns_rcode_notauth: {
12750                 char rcode[128];
12751                 isc_buffer_t rb;
12752
12753                 isc_buffer_init(&rb, rcode, sizeof(rcode));
12754                 (void)dns_rcode_totext(msg->rcode, &rb);
12755                 dns_zone_log(zone, ISC_LOG_WARNING,
12756                              "forwarding dynamic update: "
12757                              "unexpected response: master %s returned: %.*s",
12758                              master, (int)rb.used, rcode);
12759                 goto next_master;
12760         }
12761
12762         /* Try another server for these rcodes. */
12763         case dns_rcode_formerr:
12764         case dns_rcode_servfail:
12765         case dns_rcode_notimp:
12766         case dns_rcode_badvers:
12767         default:
12768                 goto next_master;
12769         }
12770
12771         /* call callback */
12772         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
12773         msg = NULL;
12774         dns_request_destroy(&forward->request);
12775         forward_destroy(forward);
12776         isc_event_free(&event);
12777         return;
12778
12779  next_master:
12780         if (msg != NULL)
12781                 dns_message_destroy(&msg);
12782         isc_event_free(&event);
12783         forward->which++;
12784         dns_request_destroy(&forward->request);
12785         result = sendtomaster(forward);
12786         if (result != ISC_R_SUCCESS) {
12787                 /* call callback */
12788                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
12789                              "exhausted dynamic update forwarder list");
12790                 (forward->callback)(forward->callback_arg, result, NULL);
12791                 forward_destroy(forward);
12792         }
12793 }
12794
12795 isc_result_t
12796 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
12797                        dns_updatecallback_t callback, void *callback_arg)
12798 {
12799         dns_forward_t *forward;
12800         isc_result_t result;
12801         isc_region_t *mr;
12802
12803         REQUIRE(DNS_ZONE_VALID(zone));
12804         REQUIRE(msg != NULL);
12805         REQUIRE(callback != NULL);
12806
12807         forward = isc_mem_get(zone->mctx, sizeof(*forward));
12808         if (forward == NULL)
12809                 return (ISC_R_NOMEMORY);
12810
12811         forward->request = NULL;
12812         forward->zone = NULL;
12813         forward->msgbuf = NULL;
12814         forward->which = 0;
12815         forward->mctx = 0;
12816         forward->callback = callback;
12817         forward->callback_arg = callback_arg;
12818         ISC_LINK_INIT(forward, link);
12819         forward->magic = FORWARD_MAGIC;
12820
12821         mr = dns_message_getrawmessage(msg);
12822         if (mr == NULL) {
12823                 result = ISC_R_UNEXPECTEDEND;
12824                 goto cleanup;
12825         }
12826
12827         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
12828         if (result != ISC_R_SUCCESS)
12829                 goto cleanup;
12830         result = isc_buffer_copyregion(forward->msgbuf, mr);
12831         if (result != ISC_R_SUCCESS)
12832                 goto cleanup;
12833
12834         isc_mem_attach(zone->mctx, &forward->mctx);
12835         dns_zone_iattach(zone, &forward->zone);
12836         result = sendtomaster(forward);
12837
12838  cleanup:
12839         if (result != ISC_R_SUCCESS) {
12840                 forward_destroy(forward);
12841         }
12842         return (result);
12843 }
12844
12845 isc_result_t
12846 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
12847         REQUIRE(DNS_ZONE_VALID(zone));
12848         REQUIRE(next != NULL && *next == NULL);
12849
12850         *next = ISC_LIST_NEXT(zone, link);
12851         if (*next == NULL)
12852                 return (ISC_R_NOMORE);
12853         else
12854                 return (ISC_R_SUCCESS);
12855 }
12856
12857 isc_result_t
12858 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
12859         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12860         REQUIRE(first != NULL && *first == NULL);
12861
12862         *first = ISC_LIST_HEAD(zmgr->zones);
12863         if (*first == NULL)
12864                 return (ISC_R_NOMORE);
12865         else
12866                 return (ISC_R_SUCCESS);
12867 }
12868
12869 /***
12870  ***    Zone manager.
12871  ***/
12872
12873 isc_result_t
12874 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
12875                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
12876                    dns_zonemgr_t **zmgrp)
12877 {
12878         dns_zonemgr_t *zmgr;
12879         isc_result_t result;
12880         isc_interval_t interval;
12881
12882         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
12883         if (zmgr == NULL)
12884                 return (ISC_R_NOMEMORY);
12885         zmgr->mctx = NULL;
12886         zmgr->refs = 1;
12887         isc_mem_attach(mctx, &zmgr->mctx);
12888         zmgr->taskmgr = taskmgr;
12889         zmgr->timermgr = timermgr;
12890         zmgr->socketmgr = socketmgr;
12891         zmgr->zonetasks = NULL;
12892         zmgr->task = NULL;
12893         zmgr->notifyrl = NULL;
12894         zmgr->refreshrl = NULL;
12895         ISC_LIST_INIT(zmgr->zones);
12896         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
12897         ISC_LIST_INIT(zmgr->xfrin_in_progress);
12898         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
12899         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
12900         if (result != ISC_R_SUCCESS)
12901                 goto free_mem;
12902
12903         zmgr->transfersin = 10;
12904         zmgr->transfersperns = 2;
12905
12906         /* Unreachable lock. */
12907         result = isc_rwlock_init(&zmgr->urlock, 0, 0);
12908         if (result != ISC_R_SUCCESS)
12909                 goto free_rwlock;
12910
12911         /* Create a single task for queueing of SOA queries. */
12912         result = isc_task_create(taskmgr, 1, &zmgr->task);
12913         if (result != ISC_R_SUCCESS)
12914                 goto free_urlock;
12915
12916         isc_task_setname(zmgr->task, "zmgr", zmgr);
12917         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
12918                                         &zmgr->notifyrl);
12919         if (result != ISC_R_SUCCESS)
12920                 goto free_task;
12921
12922         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
12923                                         &zmgr->refreshrl);
12924         if (result != ISC_R_SUCCESS)
12925                 goto free_notifyrl;
12926
12927         /* default to 20 refresh queries / notifies per second. */
12928         isc_interval_set(&interval, 0, 1000000000/2);
12929         result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
12930         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12931         isc_ratelimiter_setpertic(zmgr->notifyrl, 10);
12932
12933         result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
12934         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12935         isc_ratelimiter_setpertic(zmgr->refreshrl, 10);
12936
12937         zmgr->iolimit = 1;
12938         zmgr->ioactive = 0;
12939         ISC_LIST_INIT(zmgr->high);
12940         ISC_LIST_INIT(zmgr->low);
12941
12942         result = isc_mutex_init(&zmgr->iolock);
12943         if (result != ISC_R_SUCCESS)
12944                 goto free_refreshrl;
12945
12946         zmgr->magic = ZONEMGR_MAGIC;
12947
12948         *zmgrp = zmgr;
12949         return (ISC_R_SUCCESS);
12950
12951 #if 0
12952  free_iolock:
12953         DESTROYLOCK(&zmgr->iolock);
12954 #endif
12955  free_refreshrl:
12956         isc_ratelimiter_detach(&zmgr->refreshrl);
12957  free_notifyrl:
12958         isc_ratelimiter_detach(&zmgr->notifyrl);
12959  free_task:
12960         isc_task_detach(&zmgr->task);
12961  free_urlock:
12962         isc_rwlock_destroy(&zmgr->urlock);
12963  free_rwlock:
12964         isc_rwlock_destroy(&zmgr->rwlock);
12965  free_mem:
12966         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
12967         isc_mem_detach(&mctx);
12968         return (result);
12969 }
12970
12971 isc_result_t
12972 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12973         isc_result_t result;
12974
12975         REQUIRE(DNS_ZONE_VALID(zone));
12976         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12977
12978         if (zmgr->zonetasks == NULL)
12979                 return (ISC_R_FAILURE);
12980
12981         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12982         LOCK_ZONE(zone);
12983         REQUIRE(zone->task == NULL);
12984         REQUIRE(zone->timer == NULL);
12985         REQUIRE(zone->zmgr == NULL);
12986
12987         isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
12988
12989         /*
12990          * Set the task name.  The tag will arbitrarily point to one
12991          * of the zones sharing the task (in practice, the one
12992          * to be managed last).
12993          */
12994         isc_task_setname(zone->task, "zone", zone);
12995
12996         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
12997                                   NULL, NULL,
12998                                   zone->task, zone_timer, zone,
12999                                   &zone->timer);
13000
13001         if (result != ISC_R_SUCCESS)
13002                 goto cleanup_task;
13003
13004         /*
13005          * The timer "holds" a iref.
13006          */
13007         zone->irefs++;
13008         INSIST(zone->irefs != 0);
13009
13010         ISC_LIST_APPEND(zmgr->zones, zone, link);
13011         zone->zmgr = zmgr;
13012         zmgr->refs++;
13013
13014         goto unlock;
13015
13016  cleanup_task:
13017         isc_task_detach(&zone->task);
13018
13019  unlock:
13020         UNLOCK_ZONE(zone);
13021         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13022         return (result);
13023 }
13024
13025 void
13026 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
13027         isc_boolean_t free_now = ISC_FALSE;
13028
13029         REQUIRE(DNS_ZONE_VALID(zone));
13030         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13031         REQUIRE(zone->zmgr == zmgr);
13032
13033         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13034         LOCK_ZONE(zone);
13035
13036         ISC_LIST_UNLINK(zmgr->zones, zone, link);
13037         zone->zmgr = NULL;
13038         zmgr->refs--;
13039         if (zmgr->refs == 0)
13040                 free_now = ISC_TRUE;
13041
13042         UNLOCK_ZONE(zone);
13043         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13044
13045         if (free_now)
13046                 zonemgr_free(zmgr);
13047         ENSURE(zone->zmgr == NULL);
13048 }
13049
13050 void
13051 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
13052         REQUIRE(DNS_ZONEMGR_VALID(source));
13053         REQUIRE(target != NULL && *target == NULL);
13054
13055         RWLOCK(&source->rwlock, isc_rwlocktype_write);
13056         REQUIRE(source->refs > 0);
13057         source->refs++;
13058         INSIST(source->refs > 0);
13059         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
13060         *target = source;
13061 }
13062
13063 void
13064 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
13065         dns_zonemgr_t *zmgr;
13066         isc_boolean_t free_now = ISC_FALSE;
13067
13068         REQUIRE(zmgrp != NULL);
13069         zmgr = *zmgrp;
13070         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13071
13072         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13073         zmgr->refs--;
13074         if (zmgr->refs == 0)
13075                 free_now = ISC_TRUE;
13076         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13077
13078         if (free_now)
13079                 zonemgr_free(zmgr);
13080         *zmgrp = NULL;
13081 }
13082
13083 isc_result_t
13084 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
13085         dns_zone_t *p;
13086
13087         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13088
13089         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13090         for (p = ISC_LIST_HEAD(zmgr->zones);
13091              p != NULL;
13092              p = ISC_LIST_NEXT(p, link))
13093         {
13094                 dns_zone_maintenance(p);
13095         }
13096         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13097
13098         /*
13099          * Recent configuration changes may have increased the
13100          * amount of available transfers quota.  Make sure any
13101          * transfers currently blocked on quota get started if
13102          * possible.
13103          */
13104         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13105         zmgr_resume_xfrs(zmgr, ISC_TRUE);
13106         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13107         return (ISC_R_SUCCESS);
13108 }
13109
13110 void
13111 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
13112
13113         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13114
13115         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13116         zmgr_resume_xfrs(zmgr, ISC_TRUE);
13117         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13118 }
13119
13120 void
13121 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
13122         dns_zone_t *zone;
13123
13124         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13125
13126         isc_ratelimiter_shutdown(zmgr->notifyrl);
13127         isc_ratelimiter_shutdown(zmgr->refreshrl);
13128
13129         if (zmgr->task != NULL)
13130                 isc_task_destroy(&zmgr->task);
13131         if (zmgr->zonetasks != NULL)
13132                 isc_taskpool_destroy(&zmgr->zonetasks);
13133
13134         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13135         for (zone = ISC_LIST_HEAD(zmgr->zones);
13136              zone != NULL;
13137              zone = ISC_LIST_NEXT(zone, link))
13138         {
13139                 LOCK_ZONE(zone);
13140                 forward_cancel(zone);
13141                 UNLOCK_ZONE(zone);
13142         }
13143         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13144 }
13145
13146 isc_result_t
13147 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
13148         isc_result_t result;
13149         int ntasks = num_zones / 100;
13150         isc_taskpool_t *pool = NULL;
13151
13152         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13153
13154         /*
13155          * For anything fewer than 1000 zones we use 10 tasks in
13156          * the task pool.  More than that, and we'll scale at one
13157          * task per 100 zones.
13158          */
13159         if (ntasks < 10)
13160                 ntasks = 10;
13161
13162         /* Create or resize the zone task pool. */
13163         if (zmgr->zonetasks == NULL)
13164                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
13165                                              ntasks, 2, &pool);
13166         else
13167                 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
13168
13169         if (result == ISC_R_SUCCESS)
13170                 zmgr->zonetasks = pool;
13171
13172         return (result);
13173 }
13174
13175 static void
13176 zonemgr_free(dns_zonemgr_t *zmgr) {
13177         isc_mem_t *mctx;
13178
13179         INSIST(zmgr->refs == 0);
13180         INSIST(ISC_LIST_EMPTY(zmgr->zones));
13181
13182         zmgr->magic = 0;
13183
13184         DESTROYLOCK(&zmgr->iolock);
13185         isc_ratelimiter_detach(&zmgr->notifyrl);
13186         isc_ratelimiter_detach(&zmgr->refreshrl);
13187
13188         isc_rwlock_destroy(&zmgr->urlock);
13189         isc_rwlock_destroy(&zmgr->rwlock);
13190         mctx = zmgr->mctx;
13191         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
13192         isc_mem_detach(&mctx);
13193 }
13194
13195 void
13196 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
13197         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13198
13199         zmgr->transfersin = value;
13200 }
13201
13202 isc_uint32_t
13203 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
13204         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13205
13206         return (zmgr->transfersin);
13207 }
13208
13209 void
13210 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
13211         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13212
13213         zmgr->transfersperns = value;
13214 }
13215
13216 isc_uint32_t
13217 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
13218         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13219
13220         return (zmgr->transfersperns);
13221 }
13222
13223 /*
13224  * Try to start a new incoming zone transfer to fill a quota
13225  * slot that was just vacated.
13226  *
13227  * Requires:
13228  *      The zone manager is locked by the caller.
13229  */
13230 static void
13231 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
13232         dns_zone_t *zone;
13233         dns_zone_t *next;
13234
13235         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
13236              zone != NULL;
13237              zone = next)
13238         {
13239                 isc_result_t result;
13240                 next = ISC_LIST_NEXT(zone, statelink);
13241                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
13242                 if (result == ISC_R_SUCCESS) {
13243                         if (multi)
13244                                 continue;
13245                         /*
13246                          * We successfully filled the slot.  We're done.
13247                          */
13248                         break;
13249                 } else if (result == ISC_R_QUOTA) {
13250                         /*
13251                          * Not enough quota.  This is probably the per-server
13252                          * quota, because we usually get called when a unit of
13253                          * global quota has just been freed.  Try the next
13254                          * zone, it may succeed if it uses another master.
13255                          */
13256                         continue;
13257                 } else {
13258                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
13259                                      "starting zone transfer: %s",
13260                                      isc_result_totext(result));
13261                         break;
13262                 }
13263         }
13264 }
13265
13266 /*
13267  * Try to start an incoming zone transfer for 'zone', quota permitting.
13268  *
13269  * Requires:
13270  *      The zone manager is locked by the caller.
13271  *
13272  * Returns:
13273  *      ISC_R_SUCCESS   There was enough quota and we attempted to
13274  *                      start a transfer.  zone_xfrdone() has been or will
13275  *                      be called.
13276  *      ISC_R_QUOTA     Not enough quota.
13277  *      Others          Failure.
13278  */
13279 static isc_result_t
13280 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
13281         dns_peer_t *peer = NULL;
13282         isc_netaddr_t masterip;
13283         isc_uint32_t nxfrsin, nxfrsperns;
13284         dns_zone_t *x;
13285         isc_uint32_t maxtransfersin, maxtransfersperns;
13286         isc_event_t *e;
13287
13288         /*
13289          * If we are exiting just pretend we got quota so the zone will
13290          * be cleaned up in the zone's task context.
13291          */
13292         LOCK_ZONE(zone);
13293         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13294                 UNLOCK_ZONE(zone);
13295                 goto gotquota;
13296         }
13297
13298         /*
13299          * Find any configured information about the server we'd
13300          * like to transfer this zone from.
13301          */
13302         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
13303         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
13304         UNLOCK_ZONE(zone);
13305
13306         /*
13307          * Determine the total maximum number of simultaneous
13308          * transfers allowed, and the maximum for this specific
13309          * master.
13310          */
13311         maxtransfersin = zmgr->transfersin;
13312         maxtransfersperns = zmgr->transfersperns;
13313         if (peer != NULL)
13314                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
13315
13316         /*
13317          * Count the total number of transfers that are in progress,
13318          * and the number of transfers in progress from this master.
13319          * We linearly scan a list of all transfers; if this turns
13320          * out to be too slow, we could hash on the master address.
13321          */
13322         nxfrsin = nxfrsperns = 0;
13323         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
13324              x != NULL;
13325              x = ISC_LIST_NEXT(x, statelink))
13326         {
13327                 isc_netaddr_t xip;
13328
13329                 LOCK_ZONE(x);
13330                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
13331                 UNLOCK_ZONE(x);
13332
13333                 nxfrsin++;
13334                 if (isc_netaddr_equal(&xip, &masterip))
13335                         nxfrsperns++;
13336         }
13337
13338         /* Enforce quota. */
13339         if (nxfrsin >= maxtransfersin)
13340                 return (ISC_R_QUOTA);
13341
13342         if (nxfrsperns >= maxtransfersperns)
13343                 return (ISC_R_QUOTA);
13344
13345  gotquota:
13346         /*
13347          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
13348          * list and send it an event to let it start the actual transfer in the
13349          * context of its own task.
13350          */
13351         e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
13352                                got_transfer_quota, zone, sizeof(isc_event_t));
13353         if (e == NULL)
13354                 return (ISC_R_NOMEMORY);
13355
13356         LOCK_ZONE(zone);
13357         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
13358         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
13359         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
13360         zone->statelist = &zmgr->xfrin_in_progress;
13361         isc_task_send(zone->task, &e);
13362         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
13363         UNLOCK_ZONE(zone);
13364
13365         return (ISC_R_SUCCESS);
13366 }
13367
13368 void
13369 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
13370
13371         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13372         REQUIRE(iolimit > 0);
13373
13374         zmgr->iolimit = iolimit;
13375 }
13376
13377 isc_uint32_t
13378 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
13379
13380         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13381
13382         return (zmgr->iolimit);
13383 }
13384
13385 /*
13386  * Get permission to request a file handle from the OS.
13387  * An event will be sent to action when one is available.
13388  * There are two queues available (high and low), the high
13389  * queue will be serviced before the low one.
13390  *
13391  * zonemgr_putio() must be called after the event is delivered to
13392  * 'action'.
13393  */
13394
13395 static isc_result_t
13396 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
13397               isc_task_t *task, isc_taskaction_t action, void *arg,
13398               dns_io_t **iop)
13399 {
13400         dns_io_t *io;
13401         isc_boolean_t queue;
13402
13403         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13404         REQUIRE(iop != NULL && *iop == NULL);
13405
13406         io = isc_mem_get(zmgr->mctx, sizeof(*io));
13407         if (io == NULL)
13408                 return (ISC_R_NOMEMORY);
13409         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
13410                                        action, arg, sizeof(*io->event));
13411         if (io->event == NULL) {
13412                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
13413                 return (ISC_R_NOMEMORY);
13414         }
13415         io->zmgr = zmgr;
13416         io->high = high;
13417         io->task = NULL;
13418         isc_task_attach(task, &io->task);
13419         ISC_LINK_INIT(io, link);
13420         io->magic = IO_MAGIC;
13421
13422         LOCK(&zmgr->iolock);
13423         zmgr->ioactive++;
13424         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
13425         if (queue) {
13426                 if (io->high)
13427                         ISC_LIST_APPEND(zmgr->high, io, link);
13428                 else
13429                         ISC_LIST_APPEND(zmgr->low, io, link);
13430         }
13431         UNLOCK(&zmgr->iolock);
13432         *iop = io;
13433
13434         if (!queue) {
13435                 isc_task_send(io->task, &io->event);
13436         }
13437         return (ISC_R_SUCCESS);
13438 }
13439
13440 static void
13441 zonemgr_putio(dns_io_t **iop) {
13442         dns_io_t *io;
13443         dns_io_t *next;
13444         dns_zonemgr_t *zmgr;
13445
13446         REQUIRE(iop != NULL);
13447         io = *iop;
13448         REQUIRE(DNS_IO_VALID(io));
13449
13450         *iop = NULL;
13451
13452         INSIST(!ISC_LINK_LINKED(io, link));
13453         INSIST(io->event == NULL);
13454
13455         zmgr = io->zmgr;
13456         isc_task_detach(&io->task);
13457         io->magic = 0;
13458         isc_mem_put(zmgr->mctx, io, sizeof(*io));
13459
13460         LOCK(&zmgr->iolock);
13461         INSIST(zmgr->ioactive > 0);
13462         zmgr->ioactive--;
13463         next = HEAD(zmgr->high);
13464         if (next == NULL)
13465                 next = HEAD(zmgr->low);
13466         if (next != NULL) {
13467                 if (next->high)
13468                         ISC_LIST_UNLINK(zmgr->high, next, link);
13469                 else
13470                         ISC_LIST_UNLINK(zmgr->low, next, link);
13471                 INSIST(next->event != NULL);
13472         }
13473         UNLOCK(&zmgr->iolock);
13474         if (next != NULL)
13475                 isc_task_send(next->task, &next->event);
13476 }
13477
13478 static void
13479 zonemgr_cancelio(dns_io_t *io) {
13480         isc_boolean_t send_event = ISC_FALSE;
13481
13482         REQUIRE(DNS_IO_VALID(io));
13483
13484         /*
13485          * If we are queued to be run then dequeue.
13486          */
13487         LOCK(&io->zmgr->iolock);
13488         if (ISC_LINK_LINKED(io, link)) {
13489                 if (io->high)
13490                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
13491                 else
13492                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
13493
13494                 send_event = ISC_TRUE;
13495                 INSIST(io->event != NULL);
13496         }
13497         UNLOCK(&io->zmgr->iolock);
13498         if (send_event) {
13499                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
13500                 isc_task_send(io->task, &io->event);
13501         }
13502 }
13503
13504 static void
13505 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
13506         char *buf;
13507         int buflen;
13508         isc_result_t result;
13509
13510         buflen = strlen(path) + strlen(templat) + 2;
13511
13512         buf = isc_mem_get(zone->mctx, buflen);
13513         if (buf == NULL)
13514                 return;
13515
13516         result = isc_file_template(path, templat, buf, buflen);
13517         if (result != ISC_R_SUCCESS)
13518                 goto cleanup;
13519
13520         result = isc_file_renameunique(path, buf);
13521         if (result != ISC_R_SUCCESS)
13522                 goto cleanup;
13523
13524         dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
13525                      "renaming file to '%s' for failure analysis and "
13526                      "retransferring.", path, buf);
13527
13528  cleanup:
13529         isc_mem_put(zone->mctx, buf, buflen);
13530 }
13531
13532 #if 0
13533 /* Hook for ondestroy notification from a database. */
13534
13535 static void
13536 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
13537         dns_db_t *db = event->sender;
13538         UNUSED(task);
13539
13540         isc_event_free(&event);
13541
13542         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13543                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13544                       "database (%p) destroyed", (void*) db);
13545 }
13546 #endif
13547
13548 void
13549 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
13550         isc_interval_t interval;
13551         isc_uint32_t s, ns;
13552         isc_uint32_t pertic;
13553         isc_result_t result;
13554
13555         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13556
13557         if (value == 0)
13558                 value = 1;
13559
13560         if (value == 1) {
13561                 s = 1;
13562                 ns = 0;
13563                 pertic = 1;
13564         } else if (value <= 10) {
13565                 s = 0;
13566                 ns = 1000000000 / value;
13567                 pertic = 1;
13568         } else {
13569                 s = 0;
13570                 ns = (1000000000 / value) * 10;
13571                 pertic = 10;
13572         }
13573
13574         isc_interval_set(&interval, s, ns);
13575
13576         result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
13577         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13578         isc_ratelimiter_setpertic(zmgr->notifyrl, pertic);
13579
13580         result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
13581         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13582         isc_ratelimiter_setpertic(zmgr->refreshrl, pertic);
13583
13584         zmgr->serialqueryrate = value;
13585 }
13586
13587 unsigned int
13588 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
13589         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13590
13591         return (zmgr->serialqueryrate);
13592 }
13593
13594 isc_boolean_t
13595 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13596                         isc_sockaddr_t *local, isc_time_t *now)
13597 {
13598         unsigned int i;
13599         isc_rwlocktype_t locktype;
13600         isc_result_t result;
13601         isc_uint32_t seconds = isc_time_seconds(now);
13602         isc_uint32_t count = 0;
13603
13604         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13605
13606         locktype = isc_rwlocktype_read;
13607         RWLOCK(&zmgr->urlock, locktype);
13608         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13609                 if (zmgr->unreachable[i].expire >= seconds &&
13610                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13611                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
13612                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
13613                         if (result == ISC_R_SUCCESS) {
13614                                 locktype = isc_rwlocktype_write;
13615                                 zmgr->unreachable[i].last = seconds;
13616                                 count = zmgr->unreachable[i].count;
13617                         }
13618                         break;
13619                 }
13620         }
13621         RWUNLOCK(&zmgr->urlock, locktype);
13622         return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
13623 }
13624
13625 void
13626 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13627                            isc_sockaddr_t *local)
13628 {
13629         unsigned int i;
13630         isc_rwlocktype_t locktype;
13631         isc_result_t result;
13632
13633         char master[ISC_SOCKADDR_FORMATSIZE];
13634         char source[ISC_SOCKADDR_FORMATSIZE];
13635
13636         isc_sockaddr_format(remote, master, sizeof(master));
13637         isc_sockaddr_format(local, source, sizeof(source));
13638
13639         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13640
13641         locktype = isc_rwlocktype_read;
13642         RWLOCK(&zmgr->urlock, locktype);
13643         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13644                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13645                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
13646                         if (zmgr->unreachable[i].expire == 0)
13647                                 break;
13648                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
13649                         if (result == ISC_R_SUCCESS) {
13650                                 locktype = isc_rwlocktype_write;
13651                                 zmgr->unreachable[i].expire = 0;
13652                                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13653                                               DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
13654                                               "master %s (source %s) deleted "
13655                                               "from unreachable cache",
13656                                               master, source);
13657                         }
13658                         break;
13659                 }
13660         }
13661         RWUNLOCK(&zmgr->urlock, locktype);
13662 }
13663
13664 void
13665 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13666                            isc_sockaddr_t *local, isc_time_t *now)
13667 {
13668         isc_uint32_t seconds = isc_time_seconds(now);
13669         isc_uint32_t last = seconds;
13670         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
13671
13672         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13673
13674         RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
13675         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13676                 /* Existing entry? */
13677                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13678                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
13679                         break;
13680                 /* Empty slot? */
13681                 if (zmgr->unreachable[i].expire < seconds)
13682                         slot = i;
13683                 /* Least recently used slot? */
13684                 if (zmgr->unreachable[i].last < last) {
13685                         last = zmgr->unreachable[i].last;
13686                         oldest = i;
13687                 }
13688         }
13689         if (i < UNREACH_CHACHE_SIZE) {
13690                 /*
13691                  * Found a existing entry.  Update the expire timer and
13692                  * last usage timestamps.
13693                  */
13694                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
13695                 zmgr->unreachable[i].last = seconds;
13696                 if (zmgr->unreachable[i].expire < seconds)
13697                         zmgr->unreachable[i].count = 1;
13698                 else
13699                         zmgr->unreachable[i].count++;
13700         } else if (slot != UNREACH_CHACHE_SIZE) {
13701                 /*
13702                  * Found a empty slot. Add a new entry to the cache.
13703                  */
13704                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
13705                 zmgr->unreachable[slot].last = seconds;
13706                 zmgr->unreachable[slot].remote = *remote;
13707                 zmgr->unreachable[slot].local = *local;
13708                 zmgr->unreachable[slot].count = 1;
13709         } else {
13710                 /*
13711                  * Replace the least recently used entry in the cache.
13712                  */
13713                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
13714                 zmgr->unreachable[oldest].last = seconds;
13715                 zmgr->unreachable[oldest].remote = *remote;
13716                 zmgr->unreachable[oldest].local = *local;
13717                 zmgr->unreachable[oldest].count = 1;
13718         }
13719         RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
13720 }
13721
13722 void
13723 dns_zone_forcereload(dns_zone_t *zone) {
13724         REQUIRE(DNS_ZONE_VALID(zone));
13725
13726         if (zone->type == dns_zone_master)
13727                 return;
13728
13729         LOCK_ZONE(zone);
13730         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13731         UNLOCK_ZONE(zone);
13732         dns_zone_refresh(zone);
13733 }
13734
13735 isc_boolean_t
13736 dns_zone_isforced(dns_zone_t *zone) {
13737         REQUIRE(DNS_ZONE_VALID(zone));
13738
13739         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
13740 }
13741
13742 isc_result_t
13743 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
13744         /*
13745          * This function is obsoleted.
13746          */
13747         UNUSED(zone);
13748         UNUSED(on);
13749         return (ISC_R_NOTIMPLEMENTED);
13750 }
13751
13752 isc_uint64_t *
13753 dns_zone_getstatscounters(dns_zone_t *zone) {
13754         /*
13755          * This function is obsoleted.
13756          */
13757         UNUSED(zone);
13758         return (NULL);
13759 }
13760
13761 void
13762 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
13763         REQUIRE(DNS_ZONE_VALID(zone));
13764         REQUIRE(zone->stats == NULL);
13765
13766         LOCK_ZONE(zone);
13767         zone->stats = NULL;
13768         isc_stats_attach(stats, &zone->stats);
13769         UNLOCK_ZONE(zone);
13770 }
13771
13772 void
13773 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
13774         REQUIRE(DNS_ZONE_VALID(zone));
13775
13776         LOCK_ZONE(zone);
13777         if (zone->requeststats_on && stats == NULL)
13778                 zone->requeststats_on = ISC_FALSE;
13779         else if (!zone->requeststats_on && stats != NULL) {
13780                 if (zone->requeststats == NULL) {
13781                         isc_stats_attach(stats, &zone->requeststats);
13782                         zone->requeststats_on = ISC_TRUE;
13783                 }
13784         }
13785         UNLOCK_ZONE(zone);
13786
13787         return;
13788 }
13789
13790 isc_stats_t *
13791 dns_zone_getrequeststats(dns_zone_t *zone) {
13792         /*
13793          * We don't lock zone for efficiency reason.  This is not catastrophic
13794          * because requeststats must always be valid when requeststats_on is
13795          * true.
13796          * Some counters may be incremented while requeststats_on is becoming
13797          * false, or some cannot be incremented just after the statistics are
13798          * installed, but it shouldn't matter much in practice.
13799          */
13800         if (zone->requeststats_on)
13801                 return (zone->requeststats);
13802         else
13803                 return (NULL);
13804 }
13805
13806 void
13807 dns_zone_dialup(dns_zone_t *zone) {
13808
13809         REQUIRE(DNS_ZONE_VALID(zone));
13810
13811         zone_debuglog(zone, "dns_zone_dialup", 3,
13812                       "notify = %d, refresh = %d",
13813                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
13814                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
13815
13816         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
13817                 dns_zone_notify(zone);
13818         if (zone->type != dns_zone_master &&
13819             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
13820                 dns_zone_refresh(zone);
13821 }
13822
13823 void
13824 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
13825         REQUIRE(DNS_ZONE_VALID(zone));
13826
13827         LOCK_ZONE(zone);
13828         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
13829                          DNS_ZONEFLG_DIALREFRESH |
13830                          DNS_ZONEFLG_NOREFRESH);
13831         switch (dialup) {
13832         case dns_dialuptype_no:
13833                 break;
13834         case dns_dialuptype_yes:
13835                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
13836                                  DNS_ZONEFLG_DIALREFRESH |
13837                                  DNS_ZONEFLG_NOREFRESH));
13838                 break;
13839         case dns_dialuptype_notify:
13840                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13841                 break;
13842         case dns_dialuptype_notifypassive:
13843                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13844                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13845                 break;
13846         case dns_dialuptype_refresh:
13847                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
13848                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13849                 break;
13850         case dns_dialuptype_passive:
13851                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13852                 break;
13853         default:
13854                 INSIST(0);
13855         }
13856         UNLOCK_ZONE(zone);
13857 }
13858
13859 isc_result_t
13860 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
13861         isc_result_t result = ISC_R_SUCCESS;
13862
13863         REQUIRE(DNS_ZONE_VALID(zone));
13864
13865         LOCK_ZONE(zone);
13866         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
13867         UNLOCK_ZONE(zone);
13868
13869         return (result);
13870 }
13871
13872 const char *
13873 dns_zone_getkeydirectory(dns_zone_t *zone) {
13874         REQUIRE(DNS_ZONE_VALID(zone));
13875
13876         return (zone->keydirectory);
13877 }
13878
13879 unsigned int
13880 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
13881         dns_zone_t *zone;
13882         unsigned int count = 0;
13883
13884         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13885
13886         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13887         switch (state) {
13888         case DNS_ZONESTATE_XFERRUNNING:
13889                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
13890                      zone != NULL;
13891                      zone = ISC_LIST_NEXT(zone, statelink))
13892                         count++;
13893                 break;
13894         case DNS_ZONESTATE_XFERDEFERRED:
13895                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
13896                      zone != NULL;
13897                      zone = ISC_LIST_NEXT(zone, statelink))
13898                         count++;
13899                 break;
13900         case DNS_ZONESTATE_SOAQUERY:
13901                 for (zone = ISC_LIST_HEAD(zmgr->zones);
13902                      zone != NULL;
13903                      zone = ISC_LIST_NEXT(zone, link))
13904                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
13905                                 count++;
13906                 break;
13907         case DNS_ZONESTATE_ANY:
13908                 for (zone = ISC_LIST_HEAD(zmgr->zones);
13909                      zone != NULL;
13910                      zone = ISC_LIST_NEXT(zone, link)) {
13911                         dns_view_t *view = zone->view;
13912                         if (view != NULL && strcmp(view->name, "_bind") == 0)
13913                                 continue;
13914                         count++;
13915                 }
13916                 break;
13917         default:
13918                 INSIST(0);
13919         }
13920
13921         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13922
13923         return (count);
13924 }
13925
13926 isc_result_t
13927 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
13928         isc_boolean_t ok = ISC_TRUE;
13929         isc_boolean_t fail = ISC_FALSE;
13930         char namebuf[DNS_NAME_FORMATSIZE];
13931         char namebuf2[DNS_NAME_FORMATSIZE];
13932         char typebuf[DNS_RDATATYPE_FORMATSIZE];
13933         int level = ISC_LOG_WARNING;
13934         dns_name_t bad;
13935
13936         REQUIRE(DNS_ZONE_VALID(zone));
13937
13938         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
13939                 return (ISC_R_SUCCESS);
13940
13941         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
13942                 level = ISC_LOG_ERROR;
13943                 fail = ISC_TRUE;
13944         }
13945
13946         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
13947         if (!ok) {
13948                 dns_name_format(name, namebuf, sizeof(namebuf));
13949                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13950                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
13951                              dns_result_totext(DNS_R_BADOWNERNAME));
13952                 if (fail)
13953                         return (DNS_R_BADOWNERNAME);
13954         }
13955
13956         dns_name_init(&bad, NULL);
13957         ok = dns_rdata_checknames(rdata, name, &bad);
13958         if (!ok) {
13959                 dns_name_format(name, namebuf, sizeof(namebuf));
13960                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
13961                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13962                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
13963                              namebuf2, dns_result_totext(DNS_R_BADNAME));
13964                 if (fail)
13965                         return (DNS_R_BADNAME);
13966         }
13967
13968         return (ISC_R_SUCCESS);
13969 }
13970
13971 void
13972 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
13973         REQUIRE(DNS_ZONE_VALID(zone));
13974         zone->checkmx = checkmx;
13975 }
13976
13977 void
13978 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
13979         REQUIRE(DNS_ZONE_VALID(zone));
13980         zone->checksrv = checksrv;
13981 }
13982
13983 void
13984 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
13985         REQUIRE(DNS_ZONE_VALID(zone));
13986         zone->checkns = checkns;
13987 }
13988
13989 void
13990 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
13991         REQUIRE(DNS_ZONE_VALID(zone));
13992
13993         LOCK_ZONE(zone);
13994         zone->isself = isself;
13995         zone->isselfarg = arg;
13996         UNLOCK_ZONE(zone);
13997 }
13998
13999 void
14000 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
14001         REQUIRE(DNS_ZONE_VALID(zone));
14002
14003         LOCK_ZONE(zone);
14004         zone->notifydelay = delay;
14005         UNLOCK_ZONE(zone);
14006 }
14007
14008 isc_uint32_t
14009 dns_zone_getnotifydelay(dns_zone_t *zone) {
14010         REQUIRE(DNS_ZONE_VALID(zone));
14011
14012         return (zone->notifydelay);
14013 }
14014
14015 isc_result_t
14016 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
14017                      isc_uint16_t keyid, isc_boolean_t delete)
14018 {
14019         isc_result_t result;
14020         REQUIRE(DNS_ZONE_VALID(zone));
14021
14022         dns_zone_log(zone, ISC_LOG_NOTICE,
14023                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
14024                      algorithm, keyid);
14025         LOCK_ZONE(zone);
14026         result = zone_signwithkey(zone, algorithm, keyid, delete);
14027         UNLOCK_ZONE(zone);
14028
14029         return (result);
14030 }
14031
14032 static const char *hex = "0123456789ABCDEF";
14033
14034 isc_result_t
14035 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
14036         isc_result_t result;
14037         char salt[255*2+1];
14038         unsigned int i, j;
14039
14040         REQUIRE(DNS_ZONE_VALID(zone));
14041
14042         if (nsec3param->salt_length != 0) {
14043                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
14044                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
14045                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
14046                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
14047                 }
14048                 salt[j] = '\0';
14049         } else
14050                 strcpy(salt, "-");
14051         dns_zone_log(zone, ISC_LOG_NOTICE,
14052                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
14053                      nsec3param->hash, nsec3param->iterations,
14054                      salt);
14055         LOCK_ZONE(zone);
14056         result = zone_addnsec3chain(zone, nsec3param);
14057         UNLOCK_ZONE(zone);
14058
14059         return (result);
14060 }
14061
14062 void
14063 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
14064         REQUIRE(DNS_ZONE_VALID(zone));
14065
14066         if (nodes == 0)
14067                 nodes = 1;
14068         zone->nodes = nodes;
14069 }
14070
14071 void
14072 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
14073         REQUIRE(DNS_ZONE_VALID(zone));
14074
14075         /*
14076          * We treat signatures as a signed value so explicitly
14077          * limit its range here.
14078          */
14079         if (signatures > ISC_INT32_MAX)
14080                 signatures = ISC_INT32_MAX;
14081         else if (signatures == 0)
14082                 signatures = 1;
14083         zone->signatures = signatures;
14084 }
14085
14086 void
14087 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
14088         REQUIRE(DNS_ZONE_VALID(zone));
14089         zone->privatetype = type;
14090 }
14091
14092 dns_rdatatype_t
14093 dns_zone_getprivatetype(dns_zone_t *zone) {
14094         REQUIRE(DNS_ZONE_VALID(zone));
14095         return (zone->privatetype);
14096 }
14097
14098 static isc_result_t
14099 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
14100                  isc_boolean_t delete)
14101 {
14102         dns_signing_t *signing;
14103         dns_signing_t *current;
14104         isc_result_t result = ISC_R_SUCCESS;
14105         isc_time_t now;
14106
14107         signing = isc_mem_get(zone->mctx, sizeof *signing);
14108         if (signing == NULL)
14109                 return (ISC_R_NOMEMORY);
14110
14111         signing->magic = 0;
14112         signing->db  = NULL;
14113         signing->dbiterator = NULL;
14114         signing->algorithm = algorithm;
14115         signing->keyid = keyid;
14116         signing->delete = delete;
14117         signing->done = ISC_FALSE;
14118
14119         TIME_NOW(&now);
14120
14121         for (current = ISC_LIST_HEAD(zone->signing);
14122              current != NULL;
14123              current = ISC_LIST_NEXT(current, link)) {
14124                 if (current->db == zone->db &&
14125                     current->algorithm == signing->algorithm &&
14126                     current->keyid == signing->keyid) {
14127                         if (current->delete != signing->delete)
14128                                 current->done = ISC_TRUE;
14129                         else
14130                                 goto cleanup;
14131                 }
14132         }
14133
14134         if (zone->db != NULL) {
14135                 dns_db_attach(zone->db, &signing->db);
14136                 result = dns_db_createiterator(signing->db, 0,
14137                                                &signing->dbiterator);
14138
14139                 if (result == ISC_R_SUCCESS)
14140                         result = dns_dbiterator_first(signing->dbiterator);
14141                 if (result == ISC_R_SUCCESS) {
14142                         dns_dbiterator_pause(signing->dbiterator);
14143                         ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
14144                         signing = NULL;
14145                         if (isc_time_isepoch(&zone->signingtime)) {
14146                                 zone->signingtime = now;
14147                                 if (zone->task != NULL)
14148                                         zone_settimer(zone, &now);
14149                         }
14150                 }
14151         } else
14152                 result = ISC_R_NOTFOUND;
14153
14154  cleanup:
14155         if (signing != NULL) {
14156                 if (signing->db != NULL)
14157                         dns_db_detach(&signing->db);
14158                 if (signing->dbiterator != NULL)
14159                         dns_dbiterator_destroy(&signing->dbiterator);
14160                 isc_mem_put(zone->mctx, signing, sizeof *signing);
14161         }
14162         return (result);
14163 }
14164
14165 static void
14166 logmsg(const char *format, ...) {
14167         va_list args;
14168         va_start(args, format);
14169         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
14170                        ISC_LOG_DEBUG(1), format, args);
14171         va_end(args);
14172 }
14173
14174 static void
14175 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
14176         dns_dnsseckey_t *key;
14177         while (!ISC_LIST_EMPTY(*list)) {
14178                 key = ISC_LIST_HEAD(*list);
14179                 ISC_LIST_UNLINK(*list, key, link);
14180                 dns_dnsseckey_destroy(mctx, &key);
14181         }
14182 }
14183
14184 /* Called once; *timep should be set to the current time. */
14185 static isc_result_t
14186 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
14187         isc_result_t result;
14188         isc_stdtime_t now, then = 0, event;
14189         int i;
14190
14191         now = *timep;
14192
14193         for (i = 0; i <= DST_MAX_TIMES; i++) {
14194                 result = dst_key_gettime(key, i, &event);
14195                 if (result == ISC_R_SUCCESS && event > now &&
14196                     (then == 0 || event < then))
14197                         then = event;
14198         }
14199
14200         if (then != 0) {
14201                 *timep = then;
14202                 return (ISC_R_SUCCESS);
14203         }
14204
14205         return (ISC_R_NOTFOUND);
14206 }
14207
14208 static isc_result_t
14209 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
14210           const dns_rdata_t *rdata, isc_boolean_t *flag)
14211 {
14212         dns_rdataset_t rdataset;
14213         dns_dbnode_t *node = NULL;
14214         isc_result_t result;
14215
14216         dns_rdataset_init(&rdataset);
14217         if (rdata->type == dns_rdatatype_nsec3)
14218                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
14219         else
14220                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
14221         result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
14222                                      (isc_stdtime_t) 0, &rdataset, NULL);
14223         if (result == ISC_R_NOTFOUND) {
14224                 *flag = ISC_FALSE;
14225                 result = ISC_R_SUCCESS;
14226                 goto failure;
14227         }
14228
14229         for (result = dns_rdataset_first(&rdataset);
14230              result == ISC_R_SUCCESS;
14231              result = dns_rdataset_next(&rdataset)) {
14232                 dns_rdata_t myrdata = DNS_RDATA_INIT;
14233                 dns_rdataset_current(&rdataset, &myrdata);
14234                 if (!dns_rdata_compare(&myrdata, rdata))
14235                         break;
14236         }
14237         dns_rdataset_disassociate(&rdataset);
14238         if (result == ISC_R_SUCCESS) {
14239                 *flag = ISC_TRUE;
14240         } else if (result == ISC_R_NOMORE) {
14241                 *flag = ISC_FALSE;
14242                 result = ISC_R_SUCCESS;
14243         }
14244
14245  failure:
14246         if (node != NULL)
14247                 dns_db_detachnode(db, &node);
14248         return (result);
14249 }
14250
14251 /*
14252  * Add records to signal the state of signing or of key removal.
14253  */
14254 static isc_result_t
14255 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
14256                     dns_dbversion_t *ver, dns_diff_t *diff,
14257                     isc_boolean_t sign_all)
14258 {
14259         dns_difftuple_t *tuple, *newtuple = NULL;
14260         dns_rdata_dnskey_t dnskey;
14261         dns_rdata_t rdata = DNS_RDATA_INIT;
14262         isc_boolean_t flag;
14263         isc_region_t r;
14264         isc_result_t result = ISC_R_SUCCESS;
14265         isc_uint16_t keyid;
14266         unsigned char buf[5];
14267         dns_name_t *name = dns_db_origin(db);
14268
14269         for (tuple = ISC_LIST_HEAD(diff->tuples);
14270              tuple != NULL;
14271              tuple = ISC_LIST_NEXT(tuple, link)) {
14272                 if (tuple->rdata.type != dns_rdatatype_dnskey)
14273                         continue;
14274
14275                 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
14276                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14277                 if ((dnskey.flags &
14278                      (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
14279                          != DNS_KEYOWNER_ZONE)
14280                         continue;
14281
14282                 dns_rdata_toregion(&tuple->rdata, &r);
14283
14284                 keyid = dst_region_computeid(&r, dnskey.algorithm);
14285
14286                 buf[0] = dnskey.algorithm;
14287                 buf[1] = (keyid & 0xff00) >> 8;
14288                 buf[2] = (keyid & 0xff);
14289                 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
14290                 buf[4] = 0;
14291                 rdata.data = buf;
14292                 rdata.length = sizeof(buf);
14293                 rdata.type = privatetype;
14294                 rdata.rdclass = tuple->rdata.rdclass;
14295
14296                 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
14297                         CHECK(rr_exists(db, ver, name, &rdata, &flag));
14298                         if (flag)
14299                                 continue;
14300                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
14301                                                    name, 0, &rdata, &newtuple));
14302                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
14303                         INSIST(newtuple == NULL);
14304                 }
14305
14306                 /*
14307                  * Remove any record which says this operation has already
14308                  * completed.
14309                  */
14310                 buf[4] = 1;
14311                 CHECK(rr_exists(db, ver, name, &rdata, &flag));
14312                 if (flag) {
14313                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
14314                                                    name, 0, &rdata, &newtuple));
14315                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
14316                         INSIST(newtuple == NULL);
14317                 }
14318         }
14319  failure:
14320         return (result);
14321 }
14322
14323 static isc_result_t
14324 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14325           dns_diff_t *diff, zonediff_t *zonediff)
14326 {
14327         isc_result_t result;
14328         isc_stdtime_t now, inception, soaexpire;
14329         isc_boolean_t check_ksk, keyset_kskonly;
14330         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
14331         unsigned int nkeys = 0, i;
14332         dns_difftuple_t *tuple;
14333
14334         result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
14335                                 zone_keys, &nkeys);
14336         if (result != ISC_R_SUCCESS) {
14337                 dns_zone_log(zone, ISC_LOG_ERROR,
14338                              "sign_apex:find_zone_keys -> %s",
14339                              dns_result_totext(result));
14340                 return (result);
14341         }
14342
14343         isc_stdtime_get(&now);
14344         inception = now - 3600; /* Allow for clock skew. */
14345         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
14346
14347         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
14348         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
14349
14350         /*
14351          * See if update_sigs will update DNSKEY signature and if not
14352          * cause them to sign so that so that newly activated keys
14353          * are used.
14354          */
14355         for (tuple = ISC_LIST_HEAD(diff->tuples);
14356              tuple != NULL;
14357              tuple = ISC_LIST_NEXT(tuple, link)) {
14358                 if (tuple->rdata.type == dns_rdatatype_dnskey &&
14359                     dns_name_equal(&tuple->name, &zone->origin))
14360                         break;
14361         }
14362
14363         if (tuple == NULL) {
14364                 result = del_sigs(zone, db, ver, &zone->origin,
14365                                   dns_rdatatype_dnskey, zonediff,
14366                                   zone_keys, nkeys, now, ISC_FALSE);
14367                 if (result != ISC_R_SUCCESS) {
14368                         dns_zone_log(zone, ISC_LOG_ERROR,
14369                                      "sign_apex:del_sigs -> %s",
14370                                      dns_result_totext(result));
14371                         goto failure;
14372                 }
14373                 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
14374                                   zonediff->diff, zone_keys, nkeys, zone->mctx,
14375                                   inception, soaexpire, check_ksk,
14376                                   keyset_kskonly);
14377                 if (result != ISC_R_SUCCESS) {
14378                         dns_zone_log(zone, ISC_LOG_ERROR,
14379                                      "sign_apex:add_sigs -> %s",
14380                                      dns_result_totext(result));
14381                         goto failure;
14382                 }
14383         }
14384
14385         result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
14386                              inception, soaexpire, now, check_ksk,
14387                              keyset_kskonly, zonediff);
14388
14389         if (result != ISC_R_SUCCESS) {
14390                 dns_zone_log(zone, ISC_LOG_ERROR,
14391                              "sign_apex:update_sigs -> %s",
14392                              dns_result_totext(result));
14393                 goto failure;
14394         }
14395
14396  failure:
14397         for (i = 0; i < nkeys; i++)
14398                 dst_key_free(&zone_keys[i]);
14399         return (result);
14400 }
14401
14402 /*
14403  * Prevent the zone entering a inconsistent state where
14404  * NSEC only DNSKEYs are present with NSEC3 chains.
14405  * See update.c:check_dnssec()
14406  */
14407 static isc_boolean_t
14408 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14409             dns_diff_t *diff)
14410 {
14411         isc_result_t result;
14412         dns_difftuple_t *tuple;
14413         isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
14414         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
14415
14416         /* Scan the tuples for an NSEC-only DNSKEY */
14417         for (tuple = ISC_LIST_HEAD(diff->tuples);
14418              tuple != NULL;
14419              tuple = ISC_LIST_NEXT(tuple, link)) {
14420                 isc_uint8_t alg;
14421                 if (tuple->rdata.type != dns_rdatatype_dnskey ||
14422                     tuple->op != DNS_DIFFOP_ADD)
14423                         continue;
14424
14425                 alg = tuple->rdata.data[3];
14426                 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
14427                     alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
14428                         nseconly = ISC_TRUE;
14429                         break;
14430                 }
14431         }
14432
14433         /* Check existing DB for NSEC-only DNSKEY */
14434         if (!nseconly)
14435                 CHECK(dns_nsec_nseconly(db, ver, &nseconly));
14436
14437         /* Check existing DB for NSEC3 */
14438         if (!nsec3)
14439                 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
14440                                         privatetype, &nsec3));
14441
14442         /* Refuse to allow NSEC3 with NSEC-only keys */
14443         if (nseconly && nsec3) {
14444                 dns_zone_log(zone, ISC_LOG_ERROR,
14445                            "NSEC only DNSKEYs and NSEC3 chains not allowed");
14446                 goto failure;
14447         }
14448
14449         return (ISC_TRUE);
14450
14451  failure:
14452         return (ISC_FALSE);
14453 }
14454
14455 static isc_result_t
14456 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14457                  dns_diff_t *diff)
14458 {
14459         isc_result_t result;
14460         dns_dbnode_t *node = NULL;
14461         dns_rdataset_t rdataset;
14462
14463         dns_rdataset_init(&rdataset);
14464         CHECK(dns_db_getoriginnode(db, &node));
14465
14466         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
14467                                      dns_rdatatype_none, 0, &rdataset, NULL);
14468         if (dns_rdataset_isassociated(&rdataset))
14469                 dns_rdataset_disassociate(&rdataset);
14470         if (result != ISC_R_NOTFOUND)
14471                 goto failure;
14472
14473         result = dns_nsec3param_deletechains(db, ver, zone, diff);
14474
14475  failure:
14476         if (node != NULL)
14477                 dns_db_detachnode(db, &node);
14478         return (result);
14479 }
14480
14481 /*
14482  * Given an RRSIG rdataset and an algorithm, determine whether there
14483  * are any signatures using that algorithm.
14484  */
14485 static isc_boolean_t
14486 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
14487         dns_rdata_t rdata = DNS_RDATA_INIT;
14488         dns_rdata_rrsig_t rrsig;
14489         isc_result_t result;
14490
14491         REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
14492         if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
14493                 return (ISC_FALSE);
14494         }
14495
14496         for (result = dns_rdataset_first(rdataset);
14497              result == ISC_R_SUCCESS;
14498              result = dns_rdataset_next(rdataset))
14499         {
14500                 dns_rdataset_current(rdataset, &rdata);
14501                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
14502                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14503                 dns_rdata_reset(&rdata);
14504                 if (rrsig.algorithm == alg)
14505                         return (ISC_TRUE);
14506         }
14507
14508         return (ISC_FALSE);
14509 }
14510
14511 static isc_result_t
14512 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14513            dns_diff_t *diff)
14514 {
14515         dns_name_t *origin;
14516         isc_boolean_t build_nsec3;
14517         isc_result_t result;
14518
14519         origin = dns_db_origin(db);
14520         CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
14521                                  &build_nsec3));
14522         if (build_nsec3)
14523                 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
14524                                            ISC_FALSE, zone->privatetype, diff));
14525         CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
14526
14527  failure:
14528         return (result);
14529 }
14530
14531 static void
14532 zone_rekey(dns_zone_t *zone) {
14533         isc_result_t result;
14534         dns_db_t *db = NULL;
14535         dns_dbnode_t *node = NULL;
14536         dns_dbversion_t *ver = NULL;
14537         dns_rdataset_t soaset, soasigs, keyset, keysigs;
14538         dns_dnsseckeylist_t dnskeys, keys, rmkeys;
14539         dns_dnsseckey_t *key;
14540         dns_diff_t diff, _sig_diff;
14541         zonediff_t zonediff;
14542         isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
14543         isc_boolean_t newalg = ISC_FALSE;
14544         isc_boolean_t fullsign;
14545         dns_ttl_t ttl = 3600;
14546         const char *dir;
14547         isc_mem_t *mctx;
14548         isc_stdtime_t now;
14549         isc_time_t timenow;
14550         isc_interval_t ival;
14551         char timebuf[80];
14552
14553         REQUIRE(DNS_ZONE_VALID(zone));
14554
14555         ISC_LIST_INIT(dnskeys);
14556         ISC_LIST_INIT(keys);
14557         ISC_LIST_INIT(rmkeys);
14558         dns_rdataset_init(&soaset);
14559         dns_rdataset_init(&soasigs);
14560         dns_rdataset_init(&keyset);
14561         dns_rdataset_init(&keysigs);
14562         dir = dns_zone_getkeydirectory(zone);
14563         mctx = zone->mctx;
14564         dns_diff_init(mctx, &diff);
14565         dns_diff_init(mctx, &_sig_diff);
14566         zonediff_init(&zonediff, &_sig_diff);
14567
14568         CHECK(dns_zone_getdb(zone, &db));
14569         CHECK(dns_db_newversion(db, &ver));
14570         CHECK(dns_db_getoriginnode(db, &node));
14571
14572         TIME_NOW(&timenow);
14573         now = isc_time_seconds(&timenow);
14574
14575         dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
14576
14577         /* Get the SOA record's TTL */
14578         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
14579                                   dns_rdatatype_none, 0, &soaset, &soasigs));
14580         ttl = soaset.ttl;
14581         dns_rdataset_disassociate(&soaset);
14582
14583         /* Get the DNSKEY rdataset */
14584         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
14585                                      dns_rdatatype_none, 0, &keyset, &keysigs);
14586         if (result == ISC_R_SUCCESS) {
14587                 ttl = keyset.ttl;
14588                 result = dns_dnssec_keylistfromrdataset(&zone->origin, dir,
14589                                                         mctx, &keyset,
14590                                                         &keysigs, &soasigs,
14591                                                         ISC_FALSE, ISC_FALSE,
14592                                                         &dnskeys);
14593                 /* Can't get keys for some reason; try again later. */
14594                 if (result != ISC_R_SUCCESS)
14595                         goto trylater;
14596         } else if (result != ISC_R_NOTFOUND)
14597                 goto failure;
14598
14599         /*
14600          * True when called from "rndc sign".  Indicates the zone should be
14601          * fully signed now.
14602          */
14603         fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
14604
14605         result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
14606         if (result == ISC_R_SUCCESS) {
14607                 isc_boolean_t check_ksk;
14608                 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
14609
14610                 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
14611                                                &zone->origin, ttl, &diff,
14612                                                ISC_TF(!check_ksk),
14613                                                mctx, logmsg);
14614
14615                 /* Keys couldn't be updated for some reason;
14616                  * try again later. */
14617                 if (result != ISC_R_SUCCESS) {
14618                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
14619                                      "couldn't update zone keys: %s",
14620                                      isc_result_totext(result));
14621                         goto trylater;
14622                 }
14623
14624                 /*
14625                  * See if any pre-existing keys have newly become active;
14626                  * also, see if any new key is for a new algorithm, as in that
14627                  * event, we need to sign the zone fully.  (If there's a new
14628                  * key, but it's for an already-existing algorithm, then
14629                  * the zone signing can be handled incrementally.)
14630                  */
14631                 for (key = ISC_LIST_HEAD(dnskeys);
14632                      key != NULL;
14633                      key = ISC_LIST_NEXT(key, link)) {
14634                         if (!key->first_sign)
14635                                 continue;
14636
14637                         newactive = ISC_TRUE;
14638
14639                         if (!dns_rdataset_isassociated(&keysigs)) {
14640                                 newalg = ISC_TRUE;
14641                                 break;
14642                         }
14643
14644                         if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
14645                                 /*
14646                                  * This isn't a new algorithm; clear
14647                                  * first_sign so we won't sign the
14648                                  * whole zone with this key later
14649                                  */
14650                                 key->first_sign = ISC_FALSE;
14651                         } else {
14652                                 newalg = ISC_TRUE;
14653                                 break;
14654                         }
14655                 }
14656
14657                 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
14658                     dnskey_sane(zone, db, ver, &diff)) {
14659                         CHECK(dns_diff_apply(&diff, db, ver));
14660                         CHECK(clean_nsec3param(zone, db, ver, &diff));
14661                         CHECK(add_signing_records(db, zone->privatetype,
14662                                                   ver, &diff,
14663                                                   ISC_TF(newalg || fullsign)));
14664                         CHECK(increment_soa_serial(db, ver, &diff, mctx));
14665                         CHECK(add_chains(zone, db, ver, &diff));
14666                         CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
14667                         CHECK(zone_journal(zone, zonediff.diff, "zone_rekey"));
14668                         commit = ISC_TRUE;
14669                 }
14670         }
14671
14672         dns_db_closeversion(db, &ver, commit);
14673
14674         if (commit) {
14675                 dns_difftuple_t *tuple;
14676
14677                 LOCK_ZONE(zone);
14678                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14679
14680                 zone_needdump(zone, DNS_DUMP_DELAY);
14681
14682                 zone_settimer(zone, &timenow);
14683
14684                 /* Remove any signatures from removed keys.  */
14685                 if (!ISC_LIST_EMPTY(rmkeys)) {
14686                         for (key = ISC_LIST_HEAD(rmkeys);
14687                              key != NULL;
14688                              key = ISC_LIST_NEXT(key, link)) {
14689                                 result = zone_signwithkey(zone,
14690                                                           dst_key_alg(key->key),
14691                                                           dst_key_id(key->key),
14692                                                           ISC_TRUE);
14693                                 if (result != ISC_R_SUCCESS) {
14694                                         dns_zone_log(zone, ISC_LOG_ERROR,
14695                                              "zone_signwithkey failed: %s",
14696                                              dns_result_totext(result));
14697                                 }
14698                         }
14699                 }
14700
14701                 if (fullsign) {
14702                         /*
14703                          * "rndc sign" was called, so we now sign the zone
14704                          * with all active keys, whether they're new or not.
14705                          */
14706                         for (key = ISC_LIST_HEAD(dnskeys);
14707                              key != NULL;
14708                              key = ISC_LIST_NEXT(key, link)) {
14709                                 if (!key->force_sign && !key->hint_sign)
14710                                         continue;
14711
14712                                 result = zone_signwithkey(zone,
14713                                                           dst_key_alg(key->key),
14714                                                           dst_key_id(key->key),
14715                                                           ISC_FALSE);
14716                                 if (result != ISC_R_SUCCESS) {
14717                                         dns_zone_log(zone, ISC_LOG_ERROR,
14718                                              "zone_signwithkey failed: %s",
14719                                              dns_result_totext(result));
14720                                 }
14721                         }
14722                 } else if (newalg) {
14723                         /*
14724                          * We haven't been told to sign fully, but a new
14725                          * algorithm was added to the DNSKEY.  We sign
14726                          * the full zone, but only with newly active
14727                          * keys.
14728                          */
14729                         for (key = ISC_LIST_HEAD(dnskeys);
14730                              key != NULL;
14731                              key = ISC_LIST_NEXT(key, link)) {
14732                                 if (!key->first_sign)
14733                                         continue;
14734
14735                                 result = zone_signwithkey(zone,
14736                                                           dst_key_alg(key->key),
14737                                                           dst_key_id(key->key),
14738                                                           ISC_FALSE);
14739                                 if (result != ISC_R_SUCCESS) {
14740                                         dns_zone_log(zone, ISC_LOG_ERROR,
14741                                              "zone_signwithkey failed: %s",
14742                                              dns_result_totext(result));
14743                                 }
14744                         }
14745                 }
14746
14747                 /*
14748                  * Clear fullsign flag, if it was set, so we don't do
14749                  * another full signing next time
14750                  */
14751                 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
14752
14753                 /*
14754                  * Cause the zone to add/delete NSEC3 chains for the
14755                  * deferred NSEC3PARAM changes.
14756                  */
14757                 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
14758                      tuple != NULL;
14759                      tuple = ISC_LIST_NEXT(tuple, link)) {
14760                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
14761                         dns_rdata_t rdata = DNS_RDATA_INIT;
14762                         dns_rdata_nsec3param_t nsec3param;
14763
14764                         if (tuple->rdata.type != zone->privatetype ||
14765                             tuple->op != DNS_DIFFOP_ADD)
14766                                 continue;
14767
14768                         if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
14769                                                         buf, sizeof(buf)))
14770                                 continue;
14771                         result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
14772                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
14773                         if (nsec3param.flags == 0)
14774                                 continue;
14775
14776                         result = zone_addnsec3chain(zone, &nsec3param);
14777                         if (result != ISC_R_SUCCESS) {
14778                                 dns_zone_log(zone, ISC_LOG_ERROR,
14779                                              "zone_addnsec3chain failed: %s",
14780                                              dns_result_totext(result));
14781                         }
14782                 }
14783
14784                 /*
14785                  * Schedule the next resigning event
14786                  */
14787                 set_resigntime(zone);
14788                 UNLOCK_ZONE(zone);
14789         }
14790
14791         isc_time_settoepoch(&zone->refreshkeytime);
14792
14793         /*
14794          * If we're doing key maintenance, set the key refresh timer to
14795          * the next scheduled key event or to one hour in the future,
14796          * whichever is sooner.
14797          */
14798         if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
14799                 isc_time_t timethen;
14800                 isc_stdtime_t then;
14801
14802                 LOCK_ZONE(zone);
14803                 DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
14804                 zone->refreshkeytime = timethen;
14805                 UNLOCK_ZONE(zone);
14806
14807                 for (key = ISC_LIST_HEAD(dnskeys);
14808                      key != NULL;
14809                      key = ISC_LIST_NEXT(key, link)) {
14810                         then = now;
14811                         result = next_keyevent(key->key, &then);
14812                         if (result != ISC_R_SUCCESS)
14813                                 continue;
14814
14815                         DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
14816                         LOCK_ZONE(zone);
14817                         if (isc_time_compare(&timethen,
14818                                              &zone->refreshkeytime) < 0) {
14819                                 zone->refreshkeytime = timethen;
14820                         }
14821                         UNLOCK_ZONE(zone);
14822                 }
14823
14824                 zone_settimer(zone, &timenow);
14825
14826                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
14827                 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
14828         }
14829
14830  failure:
14831         dns_diff_clear(&diff);
14832         dns_diff_clear(&_sig_diff);
14833
14834         clear_keylist(&dnskeys, mctx);
14835         clear_keylist(&keys, mctx);
14836         clear_keylist(&rmkeys, mctx);
14837
14838         if (ver != NULL)
14839                 dns_db_closeversion(db, &ver, ISC_FALSE);
14840         if (dns_rdataset_isassociated(&keyset))
14841                 dns_rdataset_disassociate(&keyset);
14842         if (dns_rdataset_isassociated(&keysigs))
14843                 dns_rdataset_disassociate(&keysigs);
14844         if (dns_rdataset_isassociated(&soasigs))
14845                 dns_rdataset_disassociate(&soasigs);
14846         if (node != NULL)
14847                 dns_db_detachnode(db, &node);
14848         if (db != NULL)
14849                 dns_db_detach(&db);
14850         return;
14851
14852  trylater:
14853         isc_interval_set(&ival, HOUR, 0);
14854         isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
14855         goto failure;
14856 }
14857
14858 void
14859 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
14860         isc_time_t now;
14861
14862         if (zone->type == dns_zone_master && zone->task != NULL) {
14863                 LOCK_ZONE(zone);
14864
14865                 if (fullsign)
14866                         zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
14867
14868                 TIME_NOW(&now);
14869                 zone->refreshkeytime = now;
14870                 zone_settimer(zone, &now);
14871
14872                 UNLOCK_ZONE(zone);
14873         }
14874 }
14875
14876 isc_result_t
14877 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
14878                  unsigned int *errors)
14879 {
14880         isc_result_t result;
14881         dns_dbnode_t *node = NULL;
14882
14883         REQUIRE(DNS_ZONE_VALID(zone));
14884         REQUIRE(errors != NULL);
14885
14886         result = dns_db_getoriginnode(db, &node);
14887         if (result != ISC_R_SUCCESS)
14888                 return (result);
14889         result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
14890                                   ISC_FALSE);
14891         dns_db_detachnode(db, &node);
14892         return (result);
14893 }
14894
14895 void
14896 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
14897         REQUIRE(DNS_ZONE_VALID(zone));
14898         LOCK_ZONE(zone);
14899         zone->added = added;
14900         UNLOCK_ZONE(zone);
14901 }
14902
14903 isc_boolean_t
14904 dns_zone_getadded(dns_zone_t *zone) {
14905         REQUIRE(DNS_ZONE_VALID(zone));
14906         return (zone->added);
14907 }
14908
14909 isc_result_t
14910 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
14911 {
14912         isc_time_t loadtime;
14913         isc_result_t result;
14914         TIME_NOW(&loadtime);
14915
14916         LOCK_ZONE(zone);
14917         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
14918         UNLOCK_ZONE(zone);
14919         return result;
14920 }