]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - contrib/bind9/lib/dns/zone.c
MFC r362623:
[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                 } else {
7935                         /*
7936                          * No previously known key, and the key is not
7937                          * secure, so skip it.
7938                          */
7939                         continue;
7940                 }
7941
7942                 /* Delete old version */
7943                 if (deletekey || !newkey)
7944                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7945                                             DNS_DIFFOP_DEL, keyname, 0,
7946                                             &keydatarr));
7947
7948                 if (updatekey) {
7949                         /* Set refresh timer */
7950                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
7951                         dns_rdata_reset(&keydatarr);
7952                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7953                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7954                                              dns_rdatatype_keydata,
7955                                              &keydata, &keyb);
7956
7957                         /* Insert updated version */
7958                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7959                                             DNS_DIFFOP_ADD, keyname, 0,
7960                                             &keydatarr));
7961                 } else if (newkey) {
7962                         /* Convert DNSKEY to KEYDATA */
7963                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7964                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7965                         dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
7966                                                NULL);
7967                         keydata.addhd = initializing ? now : now + MONTH;
7968                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
7969                         dns_rdata_reset(&keydatarr);
7970                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7971                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7972                                              dns_rdatatype_keydata,
7973                                              &keydata, &keyb);
7974
7975                         /* Insert into key zone */
7976                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7977                                             DNS_DIFFOP_ADD, keyname, 0,
7978                                             &keydatarr));
7979                 }
7980
7981                 if (trustkey) {
7982                         /* Trust this key. */
7983                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7984                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7985                         trust_key(zone, keyname, &dnskey, mctx);
7986                 }
7987
7988                 if (secure && !deletekey)
7989                         set_refreshkeytimer(zone, &keydata, now);
7990         }
7991
7992         /*
7993          * RFC5011 says, "A trust point that has all of its trust anchors
7994          * revoked is considered deleted and is treated as if the trust
7995          * point was never configured."  But if someone revoked their
7996          * active key before the standby was trusted, that would mean the
7997          * zone would suddenly be nonsecured.  We avoid this by checking to
7998          * see if there's pending keydata.  If so, we put a null key in
7999          * the security roots; then all queries to the zone will fail.
8000          */
8001         if (pending != 0)
8002                 fail_secure(zone, keyname);
8003
8004  done:
8005
8006         if (!ISC_LIST_EMPTY(diff.tuples)) {
8007                 /* Write changes to journal file. */
8008                 CHECK(increment_soa_serial(kfetch->db, ver, &diff, mctx));
8009                 CHECK(zone_journal(zone, &diff, "keyfetch_done"));
8010                 commit = ISC_TRUE;
8011
8012                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8013                 zone_needdump(zone, 30);
8014         }
8015
8016   failure:
8017
8018         dns_diff_clear(&diff);
8019         if (ver != NULL)
8020                 dns_db_closeversion(kfetch->db, &ver, commit);
8021
8022  cleanup:
8023         dns_db_detach(&kfetch->db);
8024
8025         INSIST(zone->irefs > 0);
8026         zone->irefs--;
8027         kfetch->zone = NULL;
8028
8029         if (dns_rdataset_isassociated(&kfetch->keydataset))
8030                 dns_rdataset_disassociate(&kfetch->keydataset);
8031         if (dns_rdataset_isassociated(&kfetch->dnskeyset))
8032                 dns_rdataset_disassociate(&kfetch->dnskeyset);
8033         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8034                 dns_rdataset_disassociate(&kfetch->dnskeysigset);
8035
8036         dns_name_free(keyname, mctx);
8037         isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
8038         isc_mem_detach(&mctx);
8039
8040         if (secroots != NULL)
8041                 dns_keytable_detach(&secroots);
8042
8043         free_needed = exit_check(zone);
8044         UNLOCK_ZONE(zone);
8045         if (free_needed)
8046                 zone_free(zone);
8047 }
8048
8049 /*
8050  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
8051  * records from the zone apex.
8052  */
8053 static void
8054 zone_refreshkeys(dns_zone_t *zone) {
8055         const char me[] = "zone_refreshkeys";
8056         isc_result_t result;
8057         dns_rriterator_t rrit;
8058         dns_db_t *db = NULL;
8059         dns_dbversion_t *ver = NULL;
8060         dns_diff_t diff;
8061         dns_rdata_t rdata = DNS_RDATA_INIT;
8062         dns_rdata_keydata_t kd;
8063         isc_stdtime_t now;
8064         isc_boolean_t commit = ISC_FALSE;
8065         isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
8066
8067         ENTER;
8068         REQUIRE(zone->db != NULL);
8069
8070         isc_stdtime_get(&now);
8071
8072         LOCK_ZONE(zone);
8073         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
8074                 isc_time_settoepoch(&zone->refreshkeytime);
8075                 UNLOCK_ZONE(zone);
8076                 return;
8077         }
8078
8079         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8080         dns_db_attach(zone->db, &db);
8081         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8082
8083         dns_diff_init(zone->mctx, &diff);
8084
8085         CHECK(dns_db_newversion(db, &ver));
8086
8087         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
8088
8089         dns_rriterator_init(&rrit, db, ver, 0);
8090         for (result = dns_rriterator_first(&rrit);
8091              result == ISC_R_SUCCESS;
8092              result = dns_rriterator_nextrrset(&rrit)) {
8093                 isc_stdtime_t timer = 0xffffffff;
8094                 dns_name_t *name = NULL, *kname = NULL;
8095                 dns_rdataset_t *kdset = NULL;
8096                 dns_keyfetch_t *kfetch;
8097                 isc_uint32_t ttl;
8098
8099                 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
8100                 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
8101                     !dns_rdataset_isassociated(kdset))
8102                         continue;
8103
8104                 /*
8105                  * Scan the stored keys looking for ones that need
8106                  * removal or refreshing
8107                  */
8108                 for (result = dns_rdataset_first(kdset);
8109                      result == ISC_R_SUCCESS;
8110                      result = dns_rdataset_next(kdset)) {
8111                         dns_rdata_reset(&rdata);
8112                         dns_rdataset_current(kdset, &rdata);
8113                         result = dns_rdata_tostruct(&rdata, &kd, NULL);
8114                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8115
8116                         /* Removal timer expired? */
8117                         if (kd.removehd != 0 && kd.removehd < now) {
8118                                 CHECK(update_one_rr(db, ver, &diff,
8119                                                     DNS_DIFFOP_DEL, name, ttl,
8120                                                     &rdata));
8121                                 continue;
8122                         }
8123
8124                         /* Acceptance timer expired? */
8125                         if (kd.addhd != 0 && kd.addhd < now)
8126                                 timer = kd.addhd;
8127
8128                         /* Or do we just need to refresh the keyset? */
8129                         if (timer > kd.refresh)
8130                                 timer = kd.refresh;
8131                 }
8132
8133                 if (timer > now)
8134                         continue;
8135
8136                 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
8137                 if (kfetch == NULL) {
8138                         fetch_err = ISC_TRUE;
8139                         goto failure;
8140                 }
8141
8142                 zone->refreshkeycount++;
8143                 kfetch->zone = zone;
8144                 zone->irefs++;
8145                 INSIST(zone->irefs != 0);
8146                 dns_fixedname_init(&kfetch->name);
8147                 kname = dns_fixedname_name(&kfetch->name);
8148                 dns_name_dup(name, zone->mctx, kname);
8149                 dns_rdataset_init(&kfetch->dnskeyset);
8150                 dns_rdataset_init(&kfetch->dnskeysigset);
8151                 dns_rdataset_init(&kfetch->keydataset);
8152                 dns_rdataset_clone(kdset, &kfetch->keydataset);
8153                 kfetch->db = NULL;
8154                 dns_db_attach(db, &kfetch->db);
8155                 kfetch->fetch = NULL;
8156
8157                 result = dns_resolver_createfetch(zone->view->resolver,
8158                                                   kname, dns_rdatatype_dnskey,
8159                                                   NULL, NULL, NULL,
8160                                                   DNS_FETCHOPT_NOVALIDATE,
8161                                                   zone->task,
8162                                                   keyfetch_done, kfetch,
8163                                                   &kfetch->dnskeyset,
8164                                                   &kfetch->dnskeysigset,
8165                                                   &kfetch->fetch);
8166                 if (result == ISC_R_SUCCESS)
8167                         fetching = ISC_TRUE;
8168                 else {
8169                         zone->refreshkeycount--;
8170                         zone->irefs--;
8171                         dns_db_detach(&kfetch->db);
8172                         dns_rdataset_disassociate(&kfetch->keydataset);
8173                         dns_name_free(kname, zone->mctx);
8174                         isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
8175                         dns_zone_log(zone, ISC_LOG_WARNING,
8176                                      "Failed to create fetch for "
8177                                      "DNSKEY update");
8178                         fetch_err = ISC_TRUE;
8179                 }
8180         }
8181         if (!ISC_LIST_EMPTY(diff.tuples)) {
8182                 CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
8183                 CHECK(zone_journal(zone, &diff, "zone_refreshkeys"));
8184                 commit = ISC_TRUE;
8185                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8186                 zone_needdump(zone, 30);
8187         }
8188
8189   failure:
8190         if (fetch_err) {
8191                 /*
8192                  * Error during a key fetch; retry in an hour.
8193                  */
8194                 isc_time_t timenow, timethen;
8195                 char timebuf[80];
8196
8197                 TIME_NOW(&timenow);
8198                 DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
8199                 zone->refreshkeytime = timethen;
8200                 zone_settimer(zone, &timenow);
8201
8202                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
8203                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
8204                              timebuf);
8205
8206                 if (!fetching)
8207                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8208         }
8209
8210         UNLOCK_ZONE(zone);
8211
8212         dns_diff_clear(&diff);
8213         if (ver != NULL) {
8214                 dns_rriterator_destroy(&rrit);
8215                 dns_db_closeversion(db, &ver, commit);
8216         }
8217         dns_db_detach(&db);
8218 }
8219
8220 static void
8221 zone_maintenance(dns_zone_t *zone) {
8222         const char me[] = "zone_maintenance";
8223         isc_time_t now;
8224         isc_result_t result;
8225         isc_boolean_t dumping;
8226
8227         REQUIRE(DNS_ZONE_VALID(zone));
8228         ENTER;
8229
8230         /*
8231          * Configuring the view of this zone may have
8232          * failed, for example because the config file
8233          * had a syntax error.  In that case, the view
8234          * db or resolver will be NULL, and we had better not try
8235          * to do maintenance on it.
8236          */
8237         if (zone->view == NULL || zone->view->adb == NULL)
8238                 return;
8239
8240         TIME_NOW(&now);
8241
8242         /*
8243          * Expire check.
8244          */
8245         switch (zone->type) {
8246         case dns_zone_slave:
8247         case dns_zone_stub:
8248                 LOCK_ZONE(zone);
8249                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
8250                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8251                         zone_expire(zone);
8252                         zone->refreshtime = now;
8253                 }
8254                 UNLOCK_ZONE(zone);
8255                 break;
8256         default:
8257                 break;
8258         }
8259
8260         /*
8261          * Up to date check.
8262          */
8263         switch (zone->type) {
8264         case dns_zone_slave:
8265         case dns_zone_stub:
8266                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8267                     isc_time_compare(&now, &zone->refreshtime) >= 0)
8268                         dns_zone_refresh(zone);
8269                 break;
8270         default:
8271                 break;
8272         }
8273
8274         /*
8275          * Slaves send notifies before backing up to disk, masters after.
8276          */
8277         if (zone->type == dns_zone_slave &&
8278             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8279             isc_time_compare(&now, &zone->notifytime) >= 0)
8280                 zone_notify(zone, &now);
8281
8282         /*
8283          * Do we need to consolidate the backing store?
8284          */
8285         switch (zone->type) {
8286         case dns_zone_master:
8287         case dns_zone_slave:
8288         case dns_zone_key:
8289         case dns_zone_stub:
8290                 LOCK_ZONE(zone);
8291                 if (zone->masterfile != NULL &&
8292                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
8293                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8294                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
8295                         dumping = was_dumping(zone);
8296                 } else
8297                         dumping = ISC_TRUE;
8298                 UNLOCK_ZONE(zone);
8299                 if (!dumping) {
8300                         result = zone_dump(zone, ISC_TRUE); /* task locked */
8301                         if (result != ISC_R_SUCCESS)
8302                                 dns_zone_log(zone, ISC_LOG_WARNING,
8303                                              "dump failed: %s",
8304                                              dns_result_totext(result));
8305                 }
8306                 break;
8307         default:
8308                 break;
8309         }
8310
8311         /*
8312          * Master/redirect zones send notifies now, if needed
8313          */
8314         switch (zone->type) {
8315         case dns_zone_master:
8316                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8317                     isc_time_compare(&now, &zone->notifytime) >= 0)
8318                         zone_notify(zone, &now);
8319         default:
8320                 break;
8321         }
8322
8323         /*
8324          * Do we need to refresh keys?
8325          */
8326         switch (zone->type) {
8327         case dns_zone_key:
8328                 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
8329                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8330                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
8331                                 zone_refreshkeys(zone);
8332                         }
8333                 }
8334                 break;
8335         case dns_zone_master:
8336                 if (!isc_time_isepoch(&zone->refreshkeytime) &&
8337                     isc_time_compare(&now, &zone->refreshkeytime) >= 0)
8338                         zone_rekey(zone);
8339         default:
8340                 break;
8341         }
8342
8343         switch (zone->type) {
8344         case dns_zone_master:
8345         case dns_zone_slave:
8346                 /*
8347                  * Do we need to sign/resign some RRsets?
8348                  */
8349                 if (!isc_time_isepoch(&zone->signingtime) &&
8350                     isc_time_compare(&now, &zone->signingtime) >= 0)
8351                         zone_sign(zone);
8352                 else if (!isc_time_isepoch(&zone->resigntime) &&
8353                     isc_time_compare(&now, &zone->resigntime) >= 0)
8354                         zone_resigninc(zone);
8355                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
8356                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
8357                         zone_nsec3chain(zone);
8358                 /*
8359                  * Do we need to issue a key expiry warning?
8360                  */
8361                 if (!isc_time_isepoch(&zone->keywarntime) &&
8362                     isc_time_compare(&now, &zone->keywarntime) >= 0)
8363                         set_key_expiry_warning(zone, zone->key_expiry,
8364                                                isc_time_seconds(&now));
8365                 break;
8366         default:
8367                 break;
8368         }
8369         zone_settimer(zone, &now);
8370 }
8371
8372 void
8373 dns_zone_markdirty(dns_zone_t *zone) {
8374
8375         LOCK_ZONE(zone);
8376         if (zone->type == dns_zone_master)
8377                 set_resigntime(zone);   /* XXXMPA make separate call back */
8378         zone_needdump(zone, DNS_DUMP_DELAY);
8379         UNLOCK_ZONE(zone);
8380 }
8381
8382 void
8383 dns_zone_expire(dns_zone_t *zone) {
8384         REQUIRE(DNS_ZONE_VALID(zone));
8385
8386         LOCK_ZONE(zone);
8387         zone_expire(zone);
8388         UNLOCK_ZONE(zone);
8389 }
8390
8391 static void
8392 zone_expire(dns_zone_t *zone) {
8393         /*
8394          * 'zone' locked by caller.
8395          */
8396
8397         REQUIRE(LOCKED_ZONE(zone));
8398
8399         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
8400
8401         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
8402         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
8403         zone->retry = DNS_ZONE_DEFAULTRETRY;
8404         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
8405         zone_unload(zone);
8406 }
8407
8408 void
8409 dns_zone_refresh(dns_zone_t *zone) {
8410         isc_interval_t i;
8411         isc_uint32_t oldflags;
8412         unsigned int j;
8413         isc_result_t result;
8414
8415         REQUIRE(DNS_ZONE_VALID(zone));
8416
8417         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
8418                 return;
8419
8420         /*
8421          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
8422          * in progress at a time.
8423          */
8424
8425         LOCK_ZONE(zone);
8426         oldflags = zone->flags;
8427         if (zone->masterscnt == 0) {
8428                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
8429                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
8430                         dns_zone_log(zone, ISC_LOG_ERROR,
8431                                      "cannot refresh: no masters");
8432                 goto unlock;
8433         }
8434         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
8435         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
8436         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
8437         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
8438                 goto unlock;
8439
8440         /*
8441          * Set the next refresh time as if refresh check has failed.
8442          * Setting this to the retry time will do that.  XXXMLG
8443          * If we are successful it will be reset using zone->refresh.
8444          */
8445         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
8446                          0);
8447         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
8448         if (result != ISC_R_SUCCESS)
8449                 dns_zone_log(zone, ISC_LOG_WARNING,
8450                              "isc_time_nowplusinterval() failed: %s",
8451                              dns_result_totext(result));
8452
8453         /*
8454          * When lacking user-specified timer values from the SOA,
8455          * do exponential backoff of the retry time up to a
8456          * maximum of six hours.
8457          */
8458         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
8459                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
8460
8461         zone->curmaster = 0;
8462         for (j = 0; j < zone->masterscnt; j++)
8463                 zone->mastersok[j] = ISC_FALSE;
8464         /* initiate soa query */
8465         queue_soa_query(zone);
8466  unlock:
8467         UNLOCK_ZONE(zone);
8468 }
8469
8470 isc_result_t
8471 dns_zone_flush(dns_zone_t *zone) {
8472         isc_result_t result = ISC_R_SUCCESS;
8473         isc_boolean_t dumping;
8474
8475         REQUIRE(DNS_ZONE_VALID(zone));
8476
8477         LOCK_ZONE(zone);
8478         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
8479         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8480             zone->masterfile != NULL) {
8481                 result = ISC_R_ALREADYRUNNING;
8482                 dumping = was_dumping(zone);
8483         } else
8484                 dumping = ISC_TRUE;
8485         UNLOCK_ZONE(zone);
8486         if (!dumping)
8487                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
8488         return (result);
8489 }
8490
8491 isc_result_t
8492 dns_zone_dump(dns_zone_t *zone) {
8493         isc_result_t result = ISC_R_ALREADYRUNNING;
8494         isc_boolean_t dumping;
8495
8496         REQUIRE(DNS_ZONE_VALID(zone));
8497
8498         LOCK_ZONE(zone);
8499         dumping = was_dumping(zone);
8500         UNLOCK_ZONE(zone);
8501         if (!dumping)
8502                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
8503         return (result);
8504 }
8505
8506 static void
8507 zone_needdump(dns_zone_t *zone, unsigned int delay) {
8508         const char me[] = "zone_needdump";
8509         isc_time_t dumptime;
8510         isc_time_t now;
8511
8512         /*
8513          * 'zone' locked by caller
8514          */
8515
8516         REQUIRE(DNS_ZONE_VALID(zone));
8517         REQUIRE(LOCKED_ZONE(zone));
8518         ENTER;
8519
8520         /*
8521          * Do we have a place to dump to and are we loaded?
8522          */
8523         if (zone->masterfile == NULL ||
8524             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
8525                 return;
8526
8527         TIME_NOW(&now);
8528         /* add some noise */
8529         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
8530
8531         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8532         if (isc_time_isepoch(&zone->dumptime) ||
8533             isc_time_compare(&zone->dumptime, &dumptime) > 0)
8534                 zone->dumptime = dumptime;
8535         if (zone->task != NULL)
8536                 zone_settimer(zone, &now);
8537 }
8538
8539 static void
8540 dump_done(void *arg, isc_result_t result) {
8541         const char me[] = "dump_done";
8542         dns_zone_t *zone = arg;
8543         dns_db_t *db;
8544         dns_dbversion_t *version;
8545         isc_boolean_t again = ISC_FALSE;
8546         isc_boolean_t compact = ISC_FALSE;
8547         isc_uint32_t serial;
8548         isc_result_t tresult;
8549
8550         REQUIRE(DNS_ZONE_VALID(zone));
8551
8552         ENTER;
8553
8554         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
8555             zone->journalsize != -1) {
8556
8557                 /*
8558                  * We don't own these, zone->dctx must stay valid.
8559                  */
8560                 db = dns_dumpctx_db(zone->dctx);
8561                 version = dns_dumpctx_version(zone->dctx);
8562
8563                 tresult = dns_db_getsoaserial(db, version, &serial);
8564                 /*
8565                  * Note: we are task locked here so we can test
8566                  * zone->xfr safely.
8567                  */
8568                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
8569                         tresult = dns_journal_compact(zone->mctx,
8570                                                       zone->journal,
8571                                                       serial,
8572                                                       zone->journalsize);
8573                         switch (tresult) {
8574                         case ISC_R_SUCCESS:
8575                         case ISC_R_NOSPACE:
8576                         case ISC_R_NOTFOUND:
8577                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
8578                                              "dns_journal_compact: %s",
8579                                              dns_result_totext(tresult));
8580                                 break;
8581                         default:
8582                                 dns_zone_log(zone, ISC_LOG_ERROR,
8583                                              "dns_journal_compact failed: %s",
8584                                              dns_result_totext(tresult));
8585                                 break;
8586                         }
8587                 } else if (tresult == ISC_R_SUCCESS) {
8588                         compact = ISC_TRUE;
8589                         zone->compact_serial = serial;
8590                 }
8591         }
8592
8593         LOCK_ZONE(zone);
8594         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8595         if (compact)
8596                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
8597         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
8598                 /*
8599                  * Try again in a short while.
8600                  */
8601                 zone_needdump(zone, DNS_DUMP_DELAY);
8602         } else if (result == ISC_R_SUCCESS &&
8603                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8604                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8605                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8606                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8607                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8608                 isc_time_settoepoch(&zone->dumptime);
8609                 again = ISC_TRUE;
8610         } else if (result == ISC_R_SUCCESS)
8611                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8612
8613         if (zone->dctx != NULL)
8614                 dns_dumpctx_detach(&zone->dctx);
8615         zonemgr_putio(&zone->writeio);
8616         UNLOCK_ZONE(zone);
8617         if (again)
8618                 (void)zone_dump(zone, ISC_FALSE);
8619         dns_zone_idetach(&zone);
8620 }
8621
8622 static isc_result_t
8623 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
8624         const char me[] = "zone_dump";
8625         isc_result_t result;
8626         dns_dbversion_t *version = NULL;
8627         isc_boolean_t again;
8628         dns_db_t *db = NULL;
8629         char *masterfile = NULL;
8630         dns_masterformat_t masterformat = dns_masterformat_none;
8631
8632 /*
8633  * 'compact' MUST only be set if we are task locked.
8634  */
8635
8636         REQUIRE(DNS_ZONE_VALID(zone));
8637         ENTER;
8638
8639  redo:
8640         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8641         if (zone->db != NULL)
8642                 dns_db_attach(zone->db, &db);
8643         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8644         LOCK_ZONE(zone);
8645         if (zone->masterfile != NULL) {
8646                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
8647                 masterformat = zone->masterformat;
8648         }
8649         UNLOCK_ZONE(zone);
8650         if (db == NULL) {
8651                 result = DNS_R_NOTLOADED;
8652                 goto fail;
8653         }
8654         if (masterfile == NULL) {
8655                 result = DNS_R_NOMASTERFILE;
8656                 goto fail;
8657         }
8658
8659         if (compact && zone->type != dns_zone_stub) {
8660                 dns_zone_t *dummy = NULL;
8661                 LOCK_ZONE(zone);
8662                 zone_iattach(zone, &dummy);
8663                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
8664                                        zone_gotwritehandle, zone,
8665                                        &zone->writeio);
8666                 if (result != ISC_R_SUCCESS)
8667                         zone_idetach(&dummy);
8668                 else
8669                         result = DNS_R_CONTINUE;
8670                 UNLOCK_ZONE(zone);
8671         } else {
8672                 const dns_master_style_t *output_style;
8673
8674                 if (zone->type == dns_zone_key)
8675                         output_style = &dns_master_style_keyzone;
8676                 else
8677                         output_style = &dns_master_style_default;
8678                 dns_db_currentversion(db, &version);
8679                 result = dns_master_dump2(zone->mctx, db, version,
8680                                           output_style, masterfile,
8681                                           masterformat);
8682                 dns_db_closeversion(db, &version, ISC_FALSE);
8683         }
8684  fail:
8685         if (db != NULL)
8686                 dns_db_detach(&db);
8687         if (masterfile != NULL)
8688                 isc_mem_free(zone->mctx, masterfile);
8689         masterfile = NULL;
8690
8691         if (result == DNS_R_CONTINUE)
8692                 return (ISC_R_SUCCESS); /* XXXMPA */
8693
8694         again = ISC_FALSE;
8695         LOCK_ZONE(zone);
8696         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8697         if (result != ISC_R_SUCCESS) {
8698                 /*
8699                  * Try again in a short while.
8700                  */
8701                 zone_needdump(zone, DNS_DUMP_DELAY);
8702         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8703                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8704                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8705                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8706                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8707                 isc_time_settoepoch(&zone->dumptime);
8708                 again = ISC_TRUE;
8709         } else
8710                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8711         UNLOCK_ZONE(zone);
8712         if (again)
8713                 goto redo;
8714
8715         return (result);
8716 }
8717
8718 static isc_result_t
8719 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
8720              dns_masterformat_t format)
8721 {
8722         isc_result_t result;
8723         dns_dbversion_t *version = NULL;
8724         dns_db_t *db = NULL;
8725
8726         REQUIRE(DNS_ZONE_VALID(zone));
8727
8728         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8729         if (zone->db != NULL)
8730                 dns_db_attach(zone->db, &db);
8731         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8732         if (db == NULL)
8733                 return (DNS_R_NOTLOADED);
8734
8735         dns_db_currentversion(db, &version);
8736         result = dns_master_dumptostream2(zone->mctx, db, version, style,
8737                                           format, fd);
8738         dns_db_closeversion(db, &version, ISC_FALSE);
8739         dns_db_detach(&db);
8740         return (result);
8741 }
8742
8743 isc_result_t
8744 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
8745                        const dns_master_style_t *style) {
8746         return dumptostream(zone, fd, style, format);
8747 }
8748
8749 isc_result_t
8750 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
8751         return dumptostream(zone, fd, &dns_master_style_default,
8752                             dns_masterformat_text);
8753 }
8754
8755 isc_result_t
8756 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
8757         return dumptostream(zone, fd, &dns_master_style_full,
8758                             dns_masterformat_text);
8759 }
8760
8761 void
8762 dns_zone_unload(dns_zone_t *zone) {
8763         REQUIRE(DNS_ZONE_VALID(zone));
8764
8765         LOCK_ZONE(zone);
8766         zone_unload(zone);
8767         UNLOCK_ZONE(zone);
8768 }
8769
8770 static void
8771 notify_cancel(dns_zone_t *zone) {
8772         dns_notify_t *notify;
8773
8774         /*
8775          * 'zone' locked by caller.
8776          */
8777
8778         REQUIRE(LOCKED_ZONE(zone));
8779
8780         for (notify = ISC_LIST_HEAD(zone->notifies);
8781              notify != NULL;
8782              notify = ISC_LIST_NEXT(notify, link)) {
8783                 if (notify->find != NULL)
8784                         dns_adb_cancelfind(notify->find);
8785                 if (notify->request != NULL)
8786                         dns_request_cancel(notify->request);
8787         }
8788 }
8789
8790 static void
8791 forward_cancel(dns_zone_t *zone) {
8792         dns_forward_t *forward;
8793
8794         /*
8795          * 'zone' locked by caller.
8796          */
8797
8798         REQUIRE(LOCKED_ZONE(zone));
8799
8800         for (forward = ISC_LIST_HEAD(zone->forwards);
8801              forward != NULL;
8802              forward = ISC_LIST_NEXT(forward, link)) {
8803                 if (forward->request != NULL)
8804                         dns_request_cancel(forward->request);
8805         }
8806 }
8807
8808 static void
8809 zone_unload(dns_zone_t *zone) {
8810
8811         /*
8812          * 'zone' locked by caller.
8813          */
8814
8815         REQUIRE(LOCKED_ZONE(zone));
8816
8817         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
8818             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
8819                 if (zone->writeio != NULL)
8820                         zonemgr_cancelio(zone->writeio);
8821
8822                 if (zone->dctx != NULL)
8823                         dns_dumpctx_cancel(zone->dctx);
8824         }
8825         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
8826         zone_detachdb(zone);
8827         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
8828         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
8829         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8830 }
8831
8832 void
8833 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8834         REQUIRE(DNS_ZONE_VALID(zone));
8835         REQUIRE(val > 0);
8836
8837         zone->minrefresh = val;
8838 }
8839
8840 void
8841 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8842         REQUIRE(DNS_ZONE_VALID(zone));
8843         REQUIRE(val > 0);
8844
8845         zone->maxrefresh = val;
8846 }
8847
8848 void
8849 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
8850         REQUIRE(DNS_ZONE_VALID(zone));
8851         REQUIRE(val > 0);
8852
8853         zone->minretry = val;
8854 }
8855
8856 void
8857 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
8858         REQUIRE(DNS_ZONE_VALID(zone));
8859         REQUIRE(val > 0);
8860
8861         zone->maxretry = val;
8862 }
8863
8864 static isc_boolean_t
8865 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
8866         dns_notify_t *notify;
8867
8868         for (notify = ISC_LIST_HEAD(zone->notifies);
8869              notify != NULL;
8870              notify = ISC_LIST_NEXT(notify, link)) {
8871                 if (notify->request != NULL)
8872                         continue;
8873                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
8874                     dns_name_equal(name, &notify->ns))
8875                         return (ISC_TRUE);
8876                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
8877                         return (ISC_TRUE);
8878         }
8879         return (ISC_FALSE);
8880 }
8881
8882 static isc_boolean_t
8883 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
8884         dns_tsigkey_t *key = NULL;
8885         isc_sockaddr_t src;
8886         isc_sockaddr_t any;
8887         isc_boolean_t isself;
8888         isc_netaddr_t dstaddr;
8889         isc_result_t result;
8890
8891         if (zone->view == NULL || zone->isself == NULL)
8892                 return (ISC_FALSE);
8893
8894         switch (isc_sockaddr_pf(dst)) {
8895         case PF_INET:
8896                 src = zone->notifysrc4;
8897                 isc_sockaddr_any(&any);
8898                 break;
8899         case PF_INET6:
8900                 src = zone->notifysrc6;
8901                 isc_sockaddr_any6(&any);
8902                 break;
8903         default:
8904                 return (ISC_FALSE);
8905         }
8906
8907         /*
8908          * When sending from any the kernel will assign a source address
8909          * that matches the destination address.
8910          */
8911         if (isc_sockaddr_eqaddr(&any, &src))
8912                 src = *dst;
8913
8914         isc_netaddr_fromsockaddr(&dstaddr, dst);
8915         result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
8916         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
8917                 return (ISC_FALSE);
8918         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
8919                                 zone->isselfarg);
8920         if (key != NULL)
8921                 dns_tsigkey_detach(&key);
8922         return (isself);
8923 }
8924
8925 static void
8926 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
8927         isc_mem_t *mctx;
8928
8929         /*
8930          * Caller holds zone lock.
8931          */
8932         REQUIRE(DNS_NOTIFY_VALID(notify));
8933
8934         if (notify->zone != NULL) {
8935                 if (!locked)
8936                         LOCK_ZONE(notify->zone);
8937                 REQUIRE(LOCKED_ZONE(notify->zone));
8938                 if (ISC_LINK_LINKED(notify, link))
8939                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
8940                 if (!locked)
8941                         UNLOCK_ZONE(notify->zone);
8942                 if (locked)
8943                         zone_idetach(&notify->zone);
8944                 else
8945                         dns_zone_idetach(&notify->zone);
8946         }
8947         if (notify->find != NULL)
8948                 dns_adb_destroyfind(&notify->find);
8949         if (notify->request != NULL)
8950                 dns_request_destroy(&notify->request);
8951         if (dns_name_dynamic(&notify->ns))
8952                 dns_name_free(&notify->ns, notify->mctx);
8953         mctx = notify->mctx;
8954         isc_mem_put(notify->mctx, notify, sizeof(*notify));
8955         isc_mem_detach(&mctx);
8956 }
8957
8958 static isc_result_t
8959 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
8960         dns_notify_t *notify;
8961
8962         REQUIRE(notifyp != NULL && *notifyp == NULL);
8963
8964         notify = isc_mem_get(mctx, sizeof(*notify));
8965         if (notify == NULL)
8966                 return (ISC_R_NOMEMORY);
8967
8968         notify->mctx = NULL;
8969         isc_mem_attach(mctx, &notify->mctx);
8970         notify->flags = flags;
8971         notify->zone = NULL;
8972         notify->find = NULL;
8973         notify->request = NULL;
8974         isc_sockaddr_any(&notify->dst);
8975         dns_name_init(&notify->ns, NULL);
8976         ISC_LINK_INIT(notify, link);
8977         notify->magic = NOTIFY_MAGIC;
8978         *notifyp = notify;
8979         return (ISC_R_SUCCESS);
8980 }
8981
8982 /*
8983  * XXXAG should check for DNS_ZONEFLG_EXITING
8984  */
8985 static void
8986 process_adb_event(isc_task_t *task, isc_event_t *ev) {
8987         dns_notify_t *notify;
8988         isc_eventtype_t result;
8989
8990         UNUSED(task);
8991
8992         notify = ev->ev_arg;
8993         REQUIRE(DNS_NOTIFY_VALID(notify));
8994         INSIST(task == notify->zone->task);
8995         result = ev->ev_type;
8996         isc_event_free(&ev);
8997         if (result == DNS_EVENT_ADBMOREADDRESSES) {
8998                 dns_adb_destroyfind(&notify->find);
8999                 notify_find_address(notify);
9000                 return;
9001         }
9002         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
9003                 LOCK_ZONE(notify->zone);
9004                 notify_send(notify);
9005                 UNLOCK_ZONE(notify->zone);
9006         }
9007         notify_destroy(notify, ISC_FALSE);
9008 }
9009
9010 static void
9011 notify_find_address(dns_notify_t *notify) {
9012         isc_result_t result;
9013         unsigned int options;
9014
9015         REQUIRE(DNS_NOTIFY_VALID(notify));
9016         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
9017                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
9018
9019         if (notify->zone->view->adb == NULL)
9020                 goto destroy;
9021
9022         result = dns_adb_createfind(notify->zone->view->adb,
9023                                     notify->zone->task,
9024                                     process_adb_event, notify,
9025                                     &notify->ns, dns_rootname, 0,
9026                                     options, 0, NULL,
9027                                     notify->zone->view->dstport,
9028                                     &notify->find);
9029
9030         /* Something failed? */
9031         if (result != ISC_R_SUCCESS)
9032                 goto destroy;
9033
9034         /* More addresses pending? */
9035         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
9036                 return;
9037
9038         /* We have as many addresses as we can get. */
9039         LOCK_ZONE(notify->zone);
9040         notify_send(notify);
9041         UNLOCK_ZONE(notify->zone);
9042
9043  destroy:
9044         notify_destroy(notify, ISC_FALSE);
9045 }
9046
9047
9048 static isc_result_t
9049 notify_send_queue(dns_notify_t *notify) {
9050         isc_event_t *e;
9051         isc_result_t result;
9052
9053         e = isc_event_allocate(notify->mctx, NULL,
9054                                DNS_EVENT_NOTIFYSENDTOADDR,
9055                                notify_send_toaddr,
9056                                notify, sizeof(isc_event_t));
9057         if (e == NULL)
9058                 return (ISC_R_NOMEMORY);
9059         e->ev_arg = notify;
9060         e->ev_sender = NULL;
9061         result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
9062                                          notify->zone->task, &e);
9063         if (result != ISC_R_SUCCESS)
9064                 isc_event_free(&e);
9065         return (result);
9066 }
9067
9068 static void
9069 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
9070         dns_notify_t *notify;
9071         isc_result_t result;
9072         dns_message_t *message = NULL;
9073         isc_netaddr_t dstip;
9074         dns_tsigkey_t *key = NULL;
9075         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9076         isc_sockaddr_t src;
9077         int timeout;
9078         isc_boolean_t have_notifysource = ISC_FALSE;
9079
9080         notify = event->ev_arg;
9081         REQUIRE(DNS_NOTIFY_VALID(notify));
9082
9083         UNUSED(task);
9084
9085         LOCK_ZONE(notify->zone);
9086
9087         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
9088                 result = ISC_R_CANCELED;
9089                 goto cleanup;
9090         }
9091
9092         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
9093             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
9094             notify->zone->view->requestmgr == NULL ||
9095             notify->zone->db == NULL) {
9096                 result = ISC_R_CANCELED;
9097                 goto cleanup;
9098         }
9099
9100         /*
9101          * The raw IPv4 address should also exist.  Don't send to the
9102          * mapped form.
9103          */
9104         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
9105             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
9106                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9107                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
9108                            "notify: ignoring IPv6 mapped IPV4 address: %s",
9109                            addrbuf);
9110                 result = ISC_R_CANCELED;
9111                 goto cleanup;
9112         }
9113
9114         result = notify_createmessage(notify->zone, notify->flags, &message);
9115         if (result != ISC_R_SUCCESS)
9116                 goto cleanup;
9117
9118         isc_netaddr_fromsockaddr(&dstip, &notify->dst);
9119         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9120         result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
9121         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9122                 notify_log(notify->zone, ISC_LOG_ERROR, "NOTIFY to %s not "
9123                            "sent. Peer TSIG key lookup failure.", addrbuf);
9124                 goto cleanup_message;
9125         }
9126
9127         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
9128                    addrbuf);
9129         if (notify->zone->view->peers != NULL) {
9130                 dns_peer_t *peer = NULL;
9131                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
9132                                                  &dstip, &peer);
9133                 if (result == ISC_R_SUCCESS) {
9134                         result = dns_peer_getnotifysource(peer, &src);
9135                         if (result == ISC_R_SUCCESS)
9136                                 have_notifysource = ISC_TRUE;
9137                 }
9138         }
9139         switch (isc_sockaddr_pf(&notify->dst)) {
9140         case PF_INET:
9141                 if (!have_notifysource)
9142                         src = notify->zone->notifysrc4;
9143                 break;
9144         case PF_INET6:
9145                 if (!have_notifysource)
9146                         src = notify->zone->notifysrc6;
9147                 break;
9148         default:
9149                 result = ISC_R_NOTIMPLEMENTED;
9150                 goto cleanup_key;
9151         }
9152         timeout = 15;
9153         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
9154                 timeout = 30;
9155         result = dns_request_createvia2(notify->zone->view->requestmgr,
9156                                         message, &src, &notify->dst, 0, key,
9157                                         timeout * 3, timeout,
9158                                         notify->zone->task, notify_done,
9159                                         notify, &notify->request);
9160         if (result == ISC_R_SUCCESS) {
9161                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
9162                         inc_stats(notify->zone,
9163                                   dns_zonestatscounter_notifyoutv4);
9164                 } else {
9165                         inc_stats(notify->zone,
9166                                   dns_zonestatscounter_notifyoutv6);
9167                 }
9168         }
9169
9170  cleanup_key:
9171         if (key != NULL)
9172                 dns_tsigkey_detach(&key);
9173  cleanup_message:
9174         dns_message_destroy(&message);
9175  cleanup:
9176         UNLOCK_ZONE(notify->zone);
9177         isc_event_free(&event);
9178         if (result != ISC_R_SUCCESS)
9179                 notify_destroy(notify, ISC_FALSE);
9180 }
9181
9182 static void
9183 notify_send(dns_notify_t *notify) {
9184         dns_adbaddrinfo_t *ai;
9185         isc_sockaddr_t dst;
9186         isc_result_t result;
9187         dns_notify_t *new = NULL;
9188
9189         /*
9190          * Zone lock held by caller.
9191          */
9192         REQUIRE(DNS_NOTIFY_VALID(notify));
9193         REQUIRE(LOCKED_ZONE(notify->zone));
9194
9195         for (ai = ISC_LIST_HEAD(notify->find->list);
9196              ai != NULL;
9197              ai = ISC_LIST_NEXT(ai, publink)) {
9198                 dst = ai->sockaddr;
9199                 if (notify_isqueued(notify->zone, NULL, &dst))
9200                         continue;
9201                 if (notify_isself(notify->zone, &dst))
9202                         continue;
9203                 new = NULL;
9204                 result = notify_create(notify->mctx,
9205                                        (notify->flags & DNS_NOTIFY_NOSOA),
9206                                        &new);
9207                 if (result != ISC_R_SUCCESS)
9208                         goto cleanup;
9209                 zone_iattach(notify->zone, &new->zone);
9210                 ISC_LIST_APPEND(new->zone->notifies, new, link);
9211                 new->dst = dst;
9212                 result = notify_send_queue(new);
9213                 if (result != ISC_R_SUCCESS)
9214                         goto cleanup;
9215                 new = NULL;
9216         }
9217
9218  cleanup:
9219         if (new != NULL)
9220                 notify_destroy(new, ISC_TRUE);
9221 }
9222
9223 void
9224 dns_zone_notify(dns_zone_t *zone) {
9225         isc_time_t now;
9226
9227         REQUIRE(DNS_ZONE_VALID(zone));
9228
9229         LOCK_ZONE(zone);
9230         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9231
9232         TIME_NOW(&now);
9233         zone_settimer(zone, &now);
9234         UNLOCK_ZONE(zone);
9235 }
9236
9237 static void
9238 zone_notify(dns_zone_t *zone, isc_time_t *now) {
9239         dns_dbnode_t *node = NULL;
9240         dns_db_t *zonedb = NULL;
9241         dns_dbversion_t *version = NULL;
9242         dns_name_t *origin = NULL;
9243         dns_name_t master;
9244         dns_rdata_ns_t ns;
9245         dns_rdata_soa_t soa;
9246         isc_uint32_t serial;
9247         dns_rdata_t rdata = DNS_RDATA_INIT;
9248         dns_rdataset_t nsrdset;
9249         dns_rdataset_t soardset;
9250         isc_result_t result;
9251         dns_notify_t *notify = NULL;
9252         unsigned int i;
9253         isc_sockaddr_t dst;
9254         isc_boolean_t isqueued;
9255         dns_notifytype_t notifytype;
9256         unsigned int flags = 0;
9257         isc_boolean_t loggednotify = ISC_FALSE;
9258
9259         REQUIRE(DNS_ZONE_VALID(zone));
9260
9261         LOCK_ZONE(zone);
9262         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9263         notifytype = zone->notifytype;
9264         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
9265         UNLOCK_ZONE(zone);
9266
9267         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
9268                 return;
9269
9270         if (notifytype == dns_notifytype_no)
9271                 return;
9272
9273         if (notifytype == dns_notifytype_masteronly &&
9274             zone->type != dns_zone_master)
9275                 return;
9276
9277         origin = &zone->origin;
9278
9279         /*
9280          * If the zone is dialup we are done as we don't want to send
9281          * the current soa so as to force a refresh query.
9282          */
9283         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
9284                 flags |= DNS_NOTIFY_NOSOA;
9285
9286         /*
9287          * Get SOA RRset.
9288          */
9289         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9290         if (zone->db != NULL)
9291                 dns_db_attach(zone->db, &zonedb);
9292         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9293         if (zonedb == NULL)
9294                 return;
9295         dns_db_currentversion(zonedb, &version);
9296         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
9297         if (result != ISC_R_SUCCESS)
9298                 goto cleanup1;
9299
9300         dns_rdataset_init(&soardset);
9301         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
9302                                      dns_rdatatype_none, 0, &soardset, NULL);
9303         if (result != ISC_R_SUCCESS)
9304                 goto cleanup2;
9305
9306         /*
9307          * Find serial and master server's name.
9308          */
9309         dns_name_init(&master, NULL);
9310         result = dns_rdataset_first(&soardset);
9311         if (result != ISC_R_SUCCESS)
9312                 goto cleanup3;
9313         dns_rdataset_current(&soardset, &rdata);
9314         result = dns_rdata_tostruct(&rdata, &soa, NULL);
9315         RUNTIME_CHECK(result == ISC_R_SUCCESS);
9316         dns_rdata_reset(&rdata);
9317         result = dns_name_dup(&soa.origin, zone->mctx, &master);
9318         serial = soa.serial;
9319         dns_rdataset_disassociate(&soardset);
9320         if (result != ISC_R_SUCCESS)
9321                 goto cleanup3;
9322
9323         /*
9324          * Enqueue notify requests for 'also-notify' servers.
9325          */
9326         LOCK_ZONE(zone);
9327         for (i = 0; i < zone->notifycnt; i++) {
9328                 dst = zone->notify[i];
9329                 if (notify_isqueued(zone, NULL, &dst))
9330                         continue;
9331                 result = notify_create(zone->mctx, flags, &notify);
9332                 if (result != ISC_R_SUCCESS)
9333                         continue;
9334                 zone_iattach(zone, &notify->zone);
9335                 notify->dst = dst;
9336                 ISC_LIST_APPEND(zone->notifies, notify, link);
9337                 result = notify_send_queue(notify);
9338                 if (result != ISC_R_SUCCESS)
9339                         notify_destroy(notify, ISC_TRUE);
9340                 if (!loggednotify) {
9341                         notify_log(zone, ISC_LOG_INFO,
9342                                    "sending notifies (serial %u)",
9343                                    serial);
9344                         loggednotify = ISC_TRUE;
9345                 }
9346                 notify = NULL;
9347         }
9348         UNLOCK_ZONE(zone);
9349
9350         if (notifytype == dns_notifytype_explicit)
9351                 goto cleanup3;
9352
9353         /*
9354          * Process NS RRset to generate notifies.
9355          */
9356
9357         dns_rdataset_init(&nsrdset);
9358         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
9359                                      dns_rdatatype_none, 0, &nsrdset, NULL);
9360         if (result != ISC_R_SUCCESS)
9361                 goto cleanup3;
9362
9363         result = dns_rdataset_first(&nsrdset);
9364         while (result == ISC_R_SUCCESS) {
9365                 dns_rdataset_current(&nsrdset, &rdata);
9366                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
9367                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9368                 dns_rdata_reset(&rdata);
9369                 /*
9370                  * Don't notify the master server unless explicitly
9371                  * configured to do so.
9372                  */
9373                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
9374                     dns_name_compare(&master, &ns.name) == 0) {
9375                         result = dns_rdataset_next(&nsrdset);
9376                         continue;
9377                 }
9378
9379                 if (!loggednotify) {
9380                         notify_log(zone, ISC_LOG_INFO,
9381                                    "sending notifies (serial %u)",
9382                                    serial);
9383                         loggednotify = ISC_TRUE;
9384                 }
9385
9386                 LOCK_ZONE(zone);
9387                 isqueued = notify_isqueued(zone, &ns.name, NULL);
9388                 UNLOCK_ZONE(zone);
9389                 if (isqueued) {
9390                         result = dns_rdataset_next(&nsrdset);
9391                         continue;
9392                 }
9393                 result = notify_create(zone->mctx, flags, &notify);
9394                 if (result != ISC_R_SUCCESS)
9395                         continue;
9396                 dns_zone_iattach(zone, &notify->zone);
9397                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
9398                 if (result != ISC_R_SUCCESS) {
9399                         LOCK_ZONE(zone);
9400                         notify_destroy(notify, ISC_TRUE);
9401                         UNLOCK_ZONE(zone);
9402                         continue;
9403                 }
9404                 LOCK_ZONE(zone);
9405                 ISC_LIST_APPEND(zone->notifies, notify, link);
9406                 UNLOCK_ZONE(zone);
9407                 notify_find_address(notify);
9408                 notify = NULL;
9409                 result = dns_rdataset_next(&nsrdset);
9410         }
9411         dns_rdataset_disassociate(&nsrdset);
9412
9413  cleanup3:
9414         if (dns_name_dynamic(&master))
9415                 dns_name_free(&master, zone->mctx);
9416  cleanup2:
9417         dns_db_detachnode(zonedb, &node);
9418  cleanup1:
9419         dns_db_closeversion(zonedb, &version, ISC_FALSE);
9420         dns_db_detach(&zonedb);
9421 }
9422
9423 /***
9424  *** Private
9425  ***/
9426
9427 static inline isc_result_t
9428 save_nsrrset(dns_message_t *message, dns_name_t *name,
9429              dns_db_t *db, dns_dbversion_t *version)
9430 {
9431         dns_rdataset_t *nsrdataset = NULL;
9432         dns_rdataset_t *rdataset = NULL;
9433         dns_dbnode_t *node = NULL;
9434         dns_rdata_ns_t ns;
9435         isc_result_t result;
9436         dns_rdata_t rdata = DNS_RDATA_INIT;
9437
9438         /*
9439          * Extract NS RRset from message.
9440          */
9441         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
9442                                       dns_rdatatype_ns, dns_rdatatype_none,
9443                                       NULL, &nsrdataset);
9444         if (result != ISC_R_SUCCESS)
9445                 goto fail;
9446
9447         /*
9448          * Add NS rdataset.
9449          */
9450         result = dns_db_findnode(db, name, ISC_TRUE, &node);
9451         if (result != ISC_R_SUCCESS)
9452                 goto fail;
9453         result = dns_db_addrdataset(db, node, version, 0,
9454                                     nsrdataset, 0, NULL);
9455         dns_db_detachnode(db, &node);
9456         if (result != ISC_R_SUCCESS)
9457                 goto fail;
9458         /*
9459          * Add glue rdatasets.
9460          */
9461         for (result = dns_rdataset_first(nsrdataset);
9462              result == ISC_R_SUCCESS;
9463              result = dns_rdataset_next(nsrdataset)) {
9464                 dns_rdataset_current(nsrdataset, &rdata);
9465                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
9466                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9467                 dns_rdata_reset(&rdata);
9468                 if (!dns_name_issubdomain(&ns.name, name))
9469                         continue;
9470                 rdataset = NULL;
9471                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9472                                               &ns.name, dns_rdatatype_aaaa,
9473                                               dns_rdatatype_none, NULL,
9474                                               &rdataset);
9475                 if (result == ISC_R_SUCCESS) {
9476                         result = dns_db_findnode(db, &ns.name,
9477                                                  ISC_TRUE, &node);
9478                         if (result != ISC_R_SUCCESS)
9479                                 goto fail;
9480                         result = dns_db_addrdataset(db, node, version, 0,
9481                                                     rdataset, 0, NULL);
9482                         dns_db_detachnode(db, &node);
9483                         if (result != ISC_R_SUCCESS)
9484                                 goto fail;
9485                 }
9486                 rdataset = NULL;
9487                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9488                                               &ns.name, dns_rdatatype_a,
9489                                               dns_rdatatype_none, NULL,
9490                                               &rdataset);
9491                 if (result == ISC_R_SUCCESS) {
9492                         result = dns_db_findnode(db, &ns.name,
9493                                                  ISC_TRUE, &node);
9494                         if (result != ISC_R_SUCCESS)
9495                                 goto fail;
9496                         result = dns_db_addrdataset(db, node, version, 0,
9497                                                     rdataset, 0, NULL);
9498                         dns_db_detachnode(db, &node);
9499                         if (result != ISC_R_SUCCESS)
9500                                 goto fail;
9501                 }
9502         }
9503         if (result != ISC_R_NOMORE)
9504                 goto fail;
9505
9506         return (ISC_R_SUCCESS);
9507
9508 fail:
9509         return (result);
9510 }
9511
9512 static void
9513 stub_callback(isc_task_t *task, isc_event_t *event) {
9514         const char me[] = "stub_callback";
9515         dns_requestevent_t *revent = (dns_requestevent_t *)event;
9516         dns_stub_t *stub = NULL;
9517         dns_message_t *msg = NULL;
9518         dns_zone_t *zone = NULL;
9519         char master[ISC_SOCKADDR_FORMATSIZE];
9520         char source[ISC_SOCKADDR_FORMATSIZE];
9521         isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
9522         isc_result_t result;
9523         isc_time_t now;
9524         isc_boolean_t exiting = ISC_FALSE;
9525         isc_interval_t i;
9526         unsigned int j, soacount;
9527
9528         stub = revent->ev_arg;
9529         INSIST(DNS_STUB_VALID(stub));
9530
9531         UNUSED(task);
9532
9533         zone = stub->zone;
9534
9535         ENTER;
9536
9537         TIME_NOW(&now);
9538
9539         LOCK_ZONE(zone);
9540
9541         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9542                 zone_debuglog(zone, me, 1, "exiting");
9543                 exiting = ISC_TRUE;
9544                 goto next_master;
9545         }
9546
9547         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9548         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9549
9550         if (revent->result != ISC_R_SUCCESS) {
9551                 if (revent->result == ISC_R_TIMEDOUT &&
9552                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9553                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9554                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9555                                      "refreshing stub: timeout retrying "
9556                                      " without EDNS master %s (source %s)",
9557                                      master, source);
9558                         goto same_master;
9559                 }
9560                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
9561                                            &zone->sourceaddr, &now);
9562                 dns_zone_log(zone, ISC_LOG_INFO,
9563                              "could not refresh stub from master %s"
9564                              " (source %s): %s", master, source,
9565                              dns_result_totext(revent->result));
9566                 goto next_master;
9567         }
9568
9569         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9570         if (result != ISC_R_SUCCESS)
9571                 goto next_master;
9572
9573         result = dns_request_getresponse(revent->request, msg, 0);
9574         if (result != ISC_R_SUCCESS)
9575                 goto next_master;
9576
9577         /*
9578          * Unexpected rcode.
9579          */
9580         if (msg->rcode != dns_rcode_noerror) {
9581                 char rcode[128];
9582                 isc_buffer_t rb;
9583
9584                 isc_buffer_init(&rb, rcode, sizeof(rcode));
9585                 (void)dns_rcode_totext(msg->rcode, &rb);
9586
9587                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9588                     (msg->rcode == dns_rcode_servfail ||
9589                      msg->rcode == dns_rcode_notimp ||
9590                      msg->rcode == dns_rcode_formerr)) {
9591                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9592                                      "refreshing stub: rcode (%.*s) retrying "
9593                                      "without EDNS master %s (source %s)",
9594                                      (int)rb.used, rcode, master, source);
9595                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9596                         goto same_master;
9597                 }
9598
9599                 dns_zone_log(zone, ISC_LOG_INFO,
9600                              "refreshing stub: "
9601                              "unexpected rcode (%.*s) from %s (source %s)",
9602                              (int)rb.used, rcode, master, source);
9603                 goto next_master;
9604         }
9605
9606         /*
9607          * We need complete messages.
9608          */
9609         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9610                 if (dns_request_usedtcp(revent->request)) {
9611                         dns_zone_log(zone, ISC_LOG_INFO,
9612                                      "refreshing stub: truncated TCP "
9613                                      "response from master %s (source %s)",
9614                                      master, source);
9615                         goto next_master;
9616                 }
9617                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9618                 goto same_master;
9619         }
9620
9621         /*
9622          * If non-auth log and next master.
9623          */
9624         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9625                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
9626                              "non-authoritative answer from "
9627                              "master %s (source %s)", master, source);
9628                 goto next_master;
9629         }
9630
9631         /*
9632          * Sanity checks.
9633          */
9634         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9635         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
9636
9637         if (cnamecnt != 0) {
9638                 dns_zone_log(zone, ISC_LOG_INFO,
9639                              "refreshing stub: unexpected CNAME response "
9640                              "from master %s (source %s)", master, source);
9641                 goto next_master;
9642         }
9643
9644         if (nscnt == 0) {
9645                 dns_zone_log(zone, ISC_LOG_INFO,
9646                              "refreshing stub: no NS records in response "
9647                              "from master %s (source %s)", master, source);
9648                 goto next_master;
9649         }
9650
9651         /*
9652          * Save answer.
9653          */
9654         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
9655         if (result != ISC_R_SUCCESS) {
9656                 dns_zone_log(zone, ISC_LOG_INFO,
9657                              "refreshing stub: unable to save NS records "
9658                              "from master %s (source %s)", master, source);
9659                 goto next_master;
9660         }
9661
9662         /*
9663          * Tidy up.
9664          */
9665         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
9666         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9667         if (zone->db == NULL)
9668                 zone_attachdb(zone, stub->db);
9669         result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
9670                                   &refresh, &retry, &expire, NULL, NULL);
9671         if (result == ISC_R_SUCCESS && soacount > 0U) {
9672                 zone->refresh = RANGE(refresh, zone->minrefresh,
9673                                       zone->maxrefresh);
9674                 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
9675                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
9676                                      DNS_MAX_EXPIRE);
9677                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9678         }
9679         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9680         dns_db_detach(&stub->db);
9681
9682         dns_message_destroy(&msg);
9683         isc_event_free(&event);
9684         dns_request_destroy(&zone->request);
9685
9686         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9687         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
9688         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9689         isc_interval_set(&i, zone->expire, 0);
9690         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9691
9692         if (zone->masterfile != NULL)
9693                 zone_needdump(zone, 0);
9694
9695         zone_settimer(zone, &now);
9696         goto free_stub;
9697
9698  next_master:
9699         if (stub->version != NULL)
9700                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
9701         if (stub->db != NULL)
9702                 dns_db_detach(&stub->db);
9703         if (msg != NULL)
9704                 dns_message_destroy(&msg);
9705         isc_event_free(&event);
9706         dns_request_destroy(&zone->request);
9707         /*
9708          * Skip to next failed / untried master.
9709          */
9710         do {
9711                 zone->curmaster++;
9712         } while (zone->curmaster < zone->masterscnt &&
9713                  zone->mastersok[zone->curmaster]);
9714         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9715         if (exiting || zone->curmaster >= zone->masterscnt) {
9716                 isc_boolean_t done = ISC_TRUE;
9717                 if (!exiting &&
9718                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9719                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9720                         /*
9721                          * Did we get a good answer from all the masters?
9722                          */
9723                         for (j = 0; j < zone->masterscnt; j++)
9724                                 if (zone->mastersok[j] == ISC_FALSE) {
9725                                         done = ISC_FALSE;
9726                                         break;
9727                                 }
9728                 } else
9729                         done = ISC_TRUE;
9730                 if (!done) {
9731                         zone->curmaster = 0;
9732                         /*
9733                          * Find the next failed master.
9734                          */
9735                         while (zone->curmaster < zone->masterscnt &&
9736                                zone->mastersok[zone->curmaster])
9737                                 zone->curmaster++;
9738                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9739                 } else {
9740                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9741
9742                         zone_settimer(zone, &now);
9743                         goto free_stub;
9744                 }
9745         }
9746         queue_soa_query(zone);
9747         goto free_stub;
9748
9749  same_master:
9750         if (msg != NULL)
9751                 dns_message_destroy(&msg);
9752         isc_event_free(&event);
9753         dns_request_destroy(&zone->request);
9754         ns_query(zone, NULL, stub);
9755         UNLOCK_ZONE(zone);
9756         goto done;
9757
9758  free_stub:
9759         UNLOCK_ZONE(zone);
9760         stub->magic = 0;
9761         dns_zone_idetach(&stub->zone);
9762         INSIST(stub->db == NULL);
9763         INSIST(stub->version == NULL);
9764         isc_mem_put(stub->mctx, stub, sizeof(*stub));
9765
9766  done:
9767         INSIST(event == NULL);
9768         return;
9769 }
9770
9771 /*
9772  * An SOA query has finished (successfully or not).
9773  */
9774 static void
9775 refresh_callback(isc_task_t *task, isc_event_t *event) {
9776         const char me[] = "refresh_callback";
9777         dns_requestevent_t *revent = (dns_requestevent_t *)event;
9778         dns_zone_t *zone;
9779         dns_message_t *msg = NULL;
9780         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
9781         isc_time_t now;
9782         char master[ISC_SOCKADDR_FORMATSIZE];
9783         char source[ISC_SOCKADDR_FORMATSIZE];
9784         dns_rdataset_t *rdataset = NULL;
9785         dns_rdata_t rdata = DNS_RDATA_INIT;
9786         dns_rdata_soa_t soa;
9787         isc_result_t result;
9788         isc_uint32_t serial, oldserial = 0;
9789         unsigned int j;
9790         isc_boolean_t do_queue_xfrin = ISC_FALSE;
9791
9792         zone = revent->ev_arg;
9793         INSIST(DNS_ZONE_VALID(zone));
9794
9795         UNUSED(task);
9796
9797         ENTER;
9798
9799         TIME_NOW(&now);
9800
9801         LOCK_ZONE(zone);
9802
9803         /*
9804          * if timeout log and next master;
9805          */
9806
9807         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9808         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9809
9810         if (revent->result != ISC_R_SUCCESS) {
9811                 if (revent->result == ISC_R_TIMEDOUT &&
9812                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9813                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9814                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9815                                      "refresh: timeout retrying without EDNS "
9816                                      "master %s (source %s)", master, source);
9817                         goto same_master;
9818                 }
9819                 if (revent->result == ISC_R_TIMEDOUT &&
9820                     !dns_request_usedtcp(revent->request)) {
9821                         dns_zone_log(zone, ISC_LOG_INFO,
9822                                      "refresh: retry limit for "
9823                                      "master %s exceeded (source %s)",
9824                                      master, source);
9825                         /* Try with slave with TCP. */
9826                         if (zone->type == dns_zone_slave &&
9827                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
9828                                 if (!dns_zonemgr_unreachable(zone->zmgr,
9829                                                              &zone->masteraddr,
9830                                                              &zone->sourceaddr,
9831                                                              &now))
9832                                 {
9833                                         DNS_ZONE_SETFLAG(zone,
9834                                                      DNS_ZONEFLG_SOABEFOREAXFR);
9835                                         goto tcp_transfer;
9836                                 }
9837                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
9838                                              "refresh: skipped tcp fallback "
9839                                              "as master %s (source %s) is "
9840                                              "unreachable (cached)",
9841                                               master, source);
9842                         }
9843                 } else
9844                         dns_zone_log(zone, ISC_LOG_INFO,
9845                                      "refresh: failure trying master "
9846                                      "%s (source %s): %s", master, source,
9847                                      dns_result_totext(revent->result));
9848                 goto next_master;
9849         }
9850
9851         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9852         if (result != ISC_R_SUCCESS)
9853                 goto next_master;
9854         result = dns_request_getresponse(revent->request, msg, 0);
9855         if (result != ISC_R_SUCCESS) {
9856                 dns_zone_log(zone, ISC_LOG_INFO,
9857                              "refresh: failure trying master "
9858                              "%s (source %s): %s", master, source,
9859                              dns_result_totext(result));
9860                 goto next_master;
9861         }
9862
9863         /*
9864          * Unexpected rcode.
9865          */
9866         if (msg->rcode != dns_rcode_noerror) {
9867                 char rcode[128];
9868                 isc_buffer_t rb;
9869
9870                 isc_buffer_init(&rb, rcode, sizeof(rcode));
9871                 (void)dns_rcode_totext(msg->rcode, &rb);
9872
9873                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9874                     (msg->rcode == dns_rcode_servfail ||
9875                      msg->rcode == dns_rcode_notimp ||
9876                      msg->rcode == dns_rcode_formerr)) {
9877                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9878                                      "refresh: rcode (%.*s) retrying without "
9879                                      "EDNS master %s (source %s)",
9880                                      (int)rb.used, rcode, master, source);
9881                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9882                         goto same_master;
9883                 }
9884                 dns_zone_log(zone, ISC_LOG_INFO,
9885                              "refresh: unexpected rcode (%.*s) from "
9886                              "master %s (source %s)", (int)rb.used, rcode,
9887                              master, source);
9888                 /*
9889                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
9890                  */
9891                 if (msg->rcode == dns_rcode_refused &&
9892                     zone->type == dns_zone_slave)
9893                         goto tcp_transfer;
9894                 goto next_master;
9895         }
9896
9897         /*
9898          * If truncated punt to zone transfer which will query again.
9899          */
9900         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9901                 if (zone->type == dns_zone_slave) {
9902                         dns_zone_log(zone, ISC_LOG_INFO,
9903                                      "refresh: truncated UDP answer, "
9904                                      "initiating TCP zone xfer "
9905                                      "for master %s (source %s)",
9906                                      master, source);
9907                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
9908                         goto tcp_transfer;
9909                 } else {
9910                         INSIST(zone->type == dns_zone_stub);
9911                         if (dns_request_usedtcp(revent->request)) {
9912                                 dns_zone_log(zone, ISC_LOG_INFO,
9913                                              "refresh: truncated TCP response "
9914                                              "from master %s (source %s)",
9915                                              master, source);
9916                                 goto next_master;
9917                         }
9918                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9919                         goto same_master;
9920                 }
9921         }
9922
9923         /*
9924          * if non-auth log and next master;
9925          */
9926         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9927                 dns_zone_log(zone, ISC_LOG_INFO,
9928                              "refresh: non-authoritative answer from "
9929                              "master %s (source %s)", master, source);
9930                 goto next_master;
9931         }
9932
9933         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9934         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
9935         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
9936         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
9937                                  dns_rdatatype_soa);
9938
9939         /*
9940          * There should not be a CNAME record at top of zone.
9941          */
9942         if (cnamecnt != 0) {
9943                 dns_zone_log(zone, ISC_LOG_INFO,
9944                              "refresh: CNAME at top of zone "
9945                              "in master %s (source %s)", master, source);
9946                 goto next_master;
9947         }
9948
9949         /*
9950          * if referral log and next master;
9951          */
9952         if (soacnt == 0 && soacount == 0 && nscount != 0) {
9953                 dns_zone_log(zone, ISC_LOG_INFO,
9954                              "refresh: referral response "
9955                              "from master %s (source %s)", master, source);
9956                 goto next_master;
9957         }
9958
9959         /*
9960          * if nodata log and next master;
9961          */
9962         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
9963                 dns_zone_log(zone, ISC_LOG_INFO,
9964                              "refresh: NODATA response "
9965                              "from master %s (source %s)", master, source);
9966                 goto next_master;
9967         }
9968
9969         /*
9970          * Only one soa at top of zone.
9971          */
9972         if (soacnt != 1) {
9973                 dns_zone_log(zone, ISC_LOG_INFO,
9974                              "refresh: answer SOA count (%d) != 1 "
9975                              "from master %s (source %s)",
9976                              soacnt, master, source);
9977                 goto next_master;
9978         }
9979
9980         /*
9981          * Extract serial
9982          */
9983         rdataset = NULL;
9984         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
9985                                       dns_rdatatype_soa, dns_rdatatype_none,
9986                                       NULL, &rdataset);
9987         if (result != ISC_R_SUCCESS) {
9988                 dns_zone_log(zone, ISC_LOG_INFO,
9989                              "refresh: unable to get SOA record "
9990                              "from master %s (source %s)", master, source);
9991                 goto next_master;
9992         }
9993
9994         result = dns_rdataset_first(rdataset);
9995         if (result != ISC_R_SUCCESS) {
9996                 dns_zone_log(zone, ISC_LOG_INFO,
9997                              "refresh: dns_rdataset_first() failed");
9998                 goto next_master;
9999         }
10000
10001         dns_rdataset_current(rdataset, &rdata);
10002         result = dns_rdata_tostruct(&rdata, &soa, NULL);
10003         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10004
10005         serial = soa.serial;
10006         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10007                 unsigned int soacount;
10008                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
10009                                           &oldserial, NULL, NULL, NULL, NULL,
10010                                           NULL);
10011                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10012                 RUNTIME_CHECK(soacount > 0U);
10013                 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
10014                               serial, oldserial);
10015         } else
10016                 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
10017                               serial);
10018
10019         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
10020             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
10021             isc_serial_gt(serial, oldserial)) {
10022                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
10023                                             &zone->sourceaddr, &now))
10024                 {
10025                         dns_zone_log(zone, ISC_LOG_INFO,
10026                                      "refresh: skipping %s as master %s "
10027                                      "(source %s) is unreachable (cached)",
10028                                      zone->type == dns_zone_slave ?
10029                                      "zone transfer" : "NS query",
10030                                      master, source);
10031                         goto next_master;
10032                 }
10033  tcp_transfer:
10034                 isc_event_free(&event);
10035                 dns_request_destroy(&zone->request);
10036                 if (zone->type == dns_zone_slave) {
10037                         do_queue_xfrin = ISC_TRUE;
10038                 } else {
10039                         INSIST(zone->type == dns_zone_stub);
10040                         ns_query(zone, rdataset, NULL);
10041                 }
10042                 if (msg != NULL)
10043                         dns_message_destroy(&msg);
10044         } else if (isc_serial_eq(soa.serial, oldserial)) {
10045                 if (zone->masterfile != NULL) {
10046                         result = ISC_R_FAILURE;
10047                         if (zone->journal != NULL)
10048                                 result = isc_file_settime(zone->journal, &now);
10049                         if (result == ISC_R_SUCCESS &&
10050                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10051                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10052                                 result = isc_file_settime(zone->masterfile,
10053                                                           &now);
10054                         } else if (result != ISC_R_SUCCESS)
10055                                 result = isc_file_settime(zone->masterfile,
10056                                                           &now);
10057                         /* Someone removed the file from underneath us! */
10058                         if (result == ISC_R_FILENOTFOUND) {
10059                                 zone_needdump(zone, DNS_DUMP_DELAY);
10060                         } else if (result != ISC_R_SUCCESS)
10061                                 dns_zone_log(zone, ISC_LOG_ERROR,
10062                                              "refresh: could not set file "
10063                                              "modification time of '%s': %s",
10064                                              zone->masterfile,
10065                                              dns_result_totext(result));
10066                 }
10067                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10068                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10069                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10070                 goto next_master;
10071         } else {
10072                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
10073                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
10074                                      "received from master %s < ours (%u)",
10075                                      soa.serial, master, oldserial);
10076                 else
10077                         zone_debuglog(zone, me, 1, "ahead");
10078                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10079                 goto next_master;
10080         }
10081         if (msg != NULL)
10082                 dns_message_destroy(&msg);
10083         goto detach;
10084
10085  next_master:
10086         if (msg != NULL)
10087                 dns_message_destroy(&msg);
10088         isc_event_free(&event);
10089         dns_request_destroy(&zone->request);
10090         /*
10091          * Skip to next failed / untried master.
10092          */
10093         do {
10094                 zone->curmaster++;
10095         } while (zone->curmaster < zone->masterscnt &&
10096                  zone->mastersok[zone->curmaster]);
10097         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10098         if (zone->curmaster >= zone->masterscnt) {
10099                 isc_boolean_t done = ISC_TRUE;
10100                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10101                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10102                         /*
10103                          * Did we get a good answer from all the masters?
10104                          */
10105                         for (j = 0; j < zone->masterscnt; j++)
10106                                 if (zone->mastersok[j] == ISC_FALSE) {
10107                                         done = ISC_FALSE;
10108                                         break;
10109                                 }
10110                 } else
10111                         done = ISC_TRUE;
10112                 if (!done) {
10113                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10114                         zone->curmaster = 0;
10115                         /*
10116                          * Find the next failed master.
10117                          */
10118                         while (zone->curmaster < zone->masterscnt &&
10119                                zone->mastersok[zone->curmaster])
10120                                 zone->curmaster++;
10121                         goto requeue;
10122                 }
10123                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10124                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
10125                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10126                         zone->refreshtime = now;
10127                 }
10128                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10129                 zone_settimer(zone, &now);
10130                 goto detach;
10131         }
10132
10133  requeue:
10134         queue_soa_query(zone);
10135         goto detach;
10136
10137  same_master:
10138         if (msg != NULL)
10139                 dns_message_destroy(&msg);
10140         isc_event_free(&event);
10141         dns_request_destroy(&zone->request);
10142         queue_soa_query(zone);
10143
10144  detach:
10145         UNLOCK_ZONE(zone);
10146         if (do_queue_xfrin)
10147                 queue_xfrin(zone);
10148         dns_zone_idetach(&zone);
10149         return;
10150 }
10151
10152 static void
10153 queue_soa_query(dns_zone_t *zone) {
10154         const char me[] = "queue_soa_query";
10155         isc_event_t *e;
10156         dns_zone_t *dummy = NULL;
10157         isc_result_t result;
10158
10159         ENTER;
10160         /*
10161          * Locked by caller
10162          */
10163         REQUIRE(LOCKED_ZONE(zone));
10164
10165         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10166                 cancel_refresh(zone);
10167                 return;
10168         }
10169
10170         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
10171                                soa_query, zone, sizeof(isc_event_t));
10172         if (e == NULL) {
10173                 cancel_refresh(zone);
10174                 return;
10175         }
10176
10177         /*
10178          * Attach so that we won't clean up
10179          * until the event is delivered.
10180          */
10181         zone_iattach(zone, &dummy);
10182
10183         e->ev_arg = zone;
10184         e->ev_sender = NULL;
10185         result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
10186         if (result != ISC_R_SUCCESS) {
10187                 zone_idetach(&dummy);
10188                 isc_event_free(&e);
10189                 cancel_refresh(zone);
10190         }
10191 }
10192
10193 static inline isc_result_t
10194 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
10195              dns_message_t **messagep)
10196 {
10197         dns_message_t *message = NULL;
10198         dns_name_t *qname = NULL;
10199         dns_rdataset_t *qrdataset = NULL;
10200         isc_result_t result;
10201
10202         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10203                                     &message);
10204         if (result != ISC_R_SUCCESS)
10205                 goto cleanup;
10206
10207         message->opcode = dns_opcode_query;
10208         message->rdclass = zone->rdclass;
10209
10210         result = dns_message_gettempname(message, &qname);
10211         if (result != ISC_R_SUCCESS)
10212                 goto cleanup;
10213
10214         result = dns_message_gettemprdataset(message, &qrdataset);
10215         if (result != ISC_R_SUCCESS)
10216                 goto cleanup;
10217
10218         /*
10219          * Make question.
10220          */
10221         dns_name_init(qname, NULL);
10222         dns_name_clone(&zone->origin, qname);
10223         dns_rdataset_init(qrdataset);
10224         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
10225         ISC_LIST_APPEND(qname->list, qrdataset, link);
10226         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
10227
10228         *messagep = message;
10229         return (ISC_R_SUCCESS);
10230
10231  cleanup:
10232         if (qname != NULL)
10233                 dns_message_puttempname(message, &qname);
10234         if (qrdataset != NULL)
10235                 dns_message_puttemprdataset(message, &qrdataset);
10236         if (message != NULL)
10237                 dns_message_destroy(&message);
10238         return (result);
10239 }
10240
10241 static isc_result_t
10242 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
10243         dns_rdataset_t *rdataset = NULL;
10244         dns_rdatalist_t *rdatalist = NULL;
10245         dns_rdata_t *rdata = NULL;
10246         isc_result_t result;
10247
10248         result = dns_message_gettemprdatalist(message, &rdatalist);
10249         if (result != ISC_R_SUCCESS)
10250                 goto cleanup;
10251         result = dns_message_gettemprdata(message, &rdata);
10252         if (result != ISC_R_SUCCESS)
10253                 goto cleanup;
10254         result = dns_message_gettemprdataset(message, &rdataset);
10255         if (result != ISC_R_SUCCESS)
10256                 goto cleanup;
10257         dns_rdataset_init(rdataset);
10258
10259         rdatalist->type = dns_rdatatype_opt;
10260         rdatalist->covers = 0;
10261
10262         /*
10263          * Set Maximum UDP buffer size.
10264          */
10265         rdatalist->rdclass = udpsize;
10266
10267         /*
10268          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
10269          */
10270         rdatalist->ttl = 0;
10271
10272         /* Set EDNS options if applicable */
10273         if (reqnsid) {
10274                 unsigned char data[4];
10275                 isc_buffer_t buf;
10276
10277                 isc_buffer_init(&buf, data, sizeof(data));
10278                 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
10279                 isc_buffer_putuint16(&buf, 0);
10280                 rdata->data = data;
10281                 rdata->length = sizeof(data);
10282         } else {
10283                 rdata->data = NULL;
10284                 rdata->length = 0;
10285         }
10286
10287         rdata->rdclass = rdatalist->rdclass;
10288         rdata->type = rdatalist->type;
10289         rdata->flags = 0;
10290
10291         ISC_LIST_INIT(rdatalist->rdata);
10292         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
10293         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
10294                       == ISC_R_SUCCESS);
10295
10296         return (dns_message_setopt(message, rdataset));
10297
10298  cleanup:
10299         if (rdatalist != NULL)
10300                 dns_message_puttemprdatalist(message, &rdatalist);
10301         if (rdataset != NULL)
10302                 dns_message_puttemprdataset(message, &rdataset);
10303         if (rdata != NULL)
10304                 dns_message_puttemprdata(message, &rdata);
10305
10306         return (result);
10307 }
10308
10309 static void
10310 soa_query(isc_task_t *task, isc_event_t *event) {
10311         const char me[] = "soa_query";
10312         isc_result_t result = ISC_R_FAILURE;
10313         dns_message_t *message = NULL;
10314         dns_zone_t *zone = event->ev_arg;
10315         dns_zone_t *dummy = NULL;
10316         isc_netaddr_t masterip;
10317         dns_tsigkey_t *key = NULL;
10318         isc_uint32_t options;
10319         isc_boolean_t cancel = ISC_TRUE;
10320         int timeout;
10321         isc_boolean_t have_xfrsource, reqnsid;
10322         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10323
10324         REQUIRE(DNS_ZONE_VALID(zone));
10325
10326         UNUSED(task);
10327
10328         ENTER;
10329
10330         LOCK_ZONE(zone);
10331         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
10332             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
10333             zone->view->requestmgr == NULL) {
10334                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10335                         cancel = ISC_FALSE;
10336                 goto cleanup;
10337         }
10338
10339         /*
10340          * XXX Optimisation: Create message when zone is setup and reuse.
10341          */
10342         result = create_query(zone, dns_rdatatype_soa, &message);
10343         if (result != ISC_R_SUCCESS)
10344                 goto cleanup;
10345
10346  again:
10347         INSIST(zone->masterscnt > 0);
10348         INSIST(zone->curmaster < zone->masterscnt);
10349
10350         zone->masteraddr = zone->masters[zone->curmaster];
10351
10352         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10353         /*
10354          * First, look for a tsig key in the master statement, then
10355          * try for a server key.
10356          */
10357         if ((zone->masterkeynames != NULL) &&
10358             (zone->masterkeynames[zone->curmaster] != NULL)) {
10359                 dns_view_t *view = dns_zone_getview(zone);
10360                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10361                 result = dns_view_gettsig(view, keyname, &key);
10362                 if (result != ISC_R_SUCCESS) {
10363                         char namebuf[DNS_NAME_FORMATSIZE];
10364                         dns_name_format(keyname, namebuf, sizeof(namebuf));
10365                         dns_zone_log(zone, ISC_LOG_ERROR,
10366                                      "unable to find key: %s", namebuf);
10367                         goto skip_master;
10368                 }
10369         }
10370         if (key == NULL) {
10371                 result = dns_view_getpeertsig(zone->view, &masterip, &key);
10372                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
10373                         char addrbuf[ISC_NETADDR_FORMATSIZE];
10374                         isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
10375                         dns_zone_log(zone, ISC_LOG_ERROR,
10376                                      "unable to find TSIG key for %s", addrbuf);
10377                         goto skip_master;
10378                 }
10379         }
10380
10381         have_xfrsource = ISC_FALSE;
10382         reqnsid = zone->view->requestnsid;
10383         if (zone->view->peers != NULL) {
10384                 dns_peer_t *peer = NULL;
10385                 isc_boolean_t edns;
10386                 result = dns_peerlist_peerbyaddr(zone->view->peers,
10387                                                  &masterip, &peer);
10388                 if (result == ISC_R_SUCCESS) {
10389                         result = dns_peer_getsupportedns(peer, &edns);
10390                         if (result == ISC_R_SUCCESS && !edns)
10391                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10392                         result = dns_peer_gettransfersource(peer,
10393                                                             &zone->sourceaddr);
10394                         if (result == ISC_R_SUCCESS)
10395                                 have_xfrsource = ISC_TRUE;
10396                         if (zone->view->resolver != NULL)
10397                                 udpsize =
10398                                   dns_resolver_getudpsize(zone->view->resolver);
10399                         (void)dns_peer_getudpsize(peer, &udpsize);
10400                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
10401                 }
10402         }
10403
10404         switch (isc_sockaddr_pf(&zone->masteraddr)) {
10405         case PF_INET:
10406                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10407                         if (isc_sockaddr_equal(&zone->altxfrsource4,
10408                                                &zone->xfrsource4))
10409                                 goto skip_master;
10410                         zone->sourceaddr = zone->altxfrsource4;
10411                 } else if (!have_xfrsource)
10412                         zone->sourceaddr = zone->xfrsource4;
10413                 break;
10414         case PF_INET6:
10415                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10416                         if (isc_sockaddr_equal(&zone->altxfrsource6,
10417                                                &zone->xfrsource6))
10418                                 goto skip_master;
10419                         zone->sourceaddr = zone->altxfrsource6;
10420                 } else if (!have_xfrsource)
10421                         zone->sourceaddr = zone->xfrsource6;
10422                 break;
10423         default:
10424                 result = ISC_R_NOTIMPLEMENTED;
10425                 goto cleanup;
10426         }
10427
10428         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
10429                   DNS_REQUESTOPT_TCP : 0;
10430
10431         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10432                 result = add_opt(message, udpsize, reqnsid);
10433                 if (result != ISC_R_SUCCESS)
10434                         zone_debuglog(zone, me, 1,
10435                                       "unable to add opt record: %s",
10436                                       dns_result_totext(result));
10437         }
10438
10439         zone_iattach(zone, &dummy);
10440         timeout = 15;
10441         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10442                 timeout = 30;
10443         result = dns_request_createvia2(zone->view->requestmgr, message,
10444                                         &zone->sourceaddr, &zone->masteraddr,
10445                                         options, key, timeout * 3, timeout,
10446                                         zone->task, refresh_callback, zone,
10447                                         &zone->request);
10448         if (result != ISC_R_SUCCESS) {
10449                 zone_idetach(&dummy);
10450                 zone_debuglog(zone, me, 1,
10451                               "dns_request_createvia2() failed: %s",
10452                               dns_result_totext(result));
10453                 goto cleanup;
10454         } else {
10455                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
10456                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
10457                 else
10458                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
10459         }
10460         cancel = ISC_FALSE;
10461
10462  cleanup:
10463         if (key != NULL)
10464                 dns_tsigkey_detach(&key);
10465         if (result != ISC_R_SUCCESS)
10466                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10467         if (message != NULL)
10468                 dns_message_destroy(&message);
10469         if (cancel)
10470                 cancel_refresh(zone);
10471         isc_event_free(&event);
10472         UNLOCK_ZONE(zone);
10473         dns_zone_idetach(&zone);
10474         return;
10475
10476  skip_master:
10477         if (key != NULL)
10478                 dns_tsigkey_detach(&key);
10479         /*
10480          * Skip to next failed / untried master.
10481          */
10482         do {
10483                 zone->curmaster++;
10484         } while (zone->curmaster < zone->masterscnt &&
10485                  zone->mastersok[zone->curmaster]);
10486         if (zone->curmaster < zone->masterscnt)
10487                 goto again;
10488         zone->curmaster = 0;
10489         goto cleanup;
10490 }
10491
10492 static void
10493 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
10494         const char me[] = "ns_query";
10495         isc_result_t result;
10496         dns_message_t *message = NULL;
10497         isc_netaddr_t masterip;
10498         dns_tsigkey_t *key = NULL;
10499         dns_dbnode_t *node = NULL;
10500         int timeout;
10501         isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
10502         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10503
10504         REQUIRE(DNS_ZONE_VALID(zone));
10505         REQUIRE(LOCKED_ZONE(zone));
10506         REQUIRE((soardataset != NULL && stub == NULL) ||
10507                 (soardataset == NULL && stub != NULL));
10508         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
10509
10510         ENTER;
10511
10512         if (stub == NULL) {
10513                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
10514                 if (stub == NULL)
10515                         goto cleanup;
10516                 stub->magic = STUB_MAGIC;
10517                 stub->mctx = zone->mctx;
10518                 stub->zone = NULL;
10519                 stub->db = NULL;
10520                 stub->version = NULL;
10521
10522                 /*
10523                  * Attach so that the zone won't disappear from under us.
10524                  */
10525                 zone_iattach(zone, &stub->zone);
10526
10527                 /*
10528                  * If a db exists we will update it, otherwise we create a
10529                  * new one and attach it to the zone once we have the NS
10530                  * RRset and glue.
10531                  */
10532                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10533                 if (zone->db != NULL) {
10534                         dns_db_attach(zone->db, &stub->db);
10535                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10536                 } else {
10537                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10538
10539                         INSIST(zone->db_argc >= 1);
10540                         result = dns_db_create(zone->mctx, zone->db_argv[0],
10541                                                &zone->origin, dns_dbtype_stub,
10542                                                zone->rdclass,
10543                                                zone->db_argc - 1,
10544                                                zone->db_argv + 1,
10545                                                &stub->db);
10546                         if (result != ISC_R_SUCCESS) {
10547                                 dns_zone_log(zone, ISC_LOG_ERROR,
10548                                              "refreshing stub: "
10549                                              "could not create "
10550                                              "database: %s",
10551                                              dns_result_totext(result));
10552                                 goto cleanup;
10553                         }
10554                         dns_db_settask(stub->db, zone->task);
10555                 }
10556
10557                 result = dns_db_newversion(stub->db, &stub->version);
10558                 if (result != ISC_R_SUCCESS) {
10559                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10560                                      "dns_db_newversion() failed: %s",
10561                                      dns_result_totext(result));
10562                         goto cleanup;
10563                 }
10564
10565                 /*
10566                  * Update SOA record.
10567                  */
10568                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
10569                                          &node);
10570                 if (result != ISC_R_SUCCESS) {
10571                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10572                                      "dns_db_findnode() failed: %s",
10573                                      dns_result_totext(result));
10574                         goto cleanup;
10575                 }
10576
10577                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
10578                                             soardataset, 0, NULL);
10579                 dns_db_detachnode(stub->db, &node);
10580                 if (result != ISC_R_SUCCESS) {
10581                         dns_zone_log(zone, ISC_LOG_INFO,
10582                                      "refreshing stub: "
10583                                      "dns_db_addrdataset() failed: %s",
10584                                      dns_result_totext(result));
10585                         goto cleanup;
10586                 }
10587         }
10588
10589         /*
10590          * XXX Optimisation: Create message when zone is setup and reuse.
10591          */
10592         result = create_query(zone, dns_rdatatype_ns, &message);
10593         INSIST(result == ISC_R_SUCCESS);
10594
10595         INSIST(zone->masterscnt > 0);
10596         INSIST(zone->curmaster < zone->masterscnt);
10597         zone->masteraddr = zone->masters[zone->curmaster];
10598
10599         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10600         /*
10601          * First, look for a tsig key in the master statement, then
10602          * try for a server key.
10603          */
10604         if ((zone->masterkeynames != NULL) &&
10605             (zone->masterkeynames[zone->curmaster] != NULL)) {
10606                 dns_view_t *view = dns_zone_getview(zone);
10607                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10608                 result = dns_view_gettsig(view, keyname, &key);
10609                 if (result != ISC_R_SUCCESS) {
10610                         char namebuf[DNS_NAME_FORMATSIZE];
10611                         dns_name_format(keyname, namebuf, sizeof(namebuf));
10612                         dns_zone_log(zone, ISC_LOG_ERROR,
10613                                      "unable to find key: %s", namebuf);
10614                 }
10615         }
10616         if (key == NULL)
10617                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
10618
10619         reqnsid = zone->view->requestnsid;
10620         if (zone->view->peers != NULL) {
10621                 dns_peer_t *peer = NULL;
10622                 isc_boolean_t edns;
10623                 result = dns_peerlist_peerbyaddr(zone->view->peers,
10624                                                  &masterip, &peer);
10625                 if (result == ISC_R_SUCCESS) {
10626                         result = dns_peer_getsupportedns(peer, &edns);
10627                         if (result == ISC_R_SUCCESS && !edns)
10628                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10629                         result = dns_peer_gettransfersource(peer,
10630                                                             &zone->sourceaddr);
10631                         if (result == ISC_R_SUCCESS)
10632                                 have_xfrsource = ISC_TRUE;
10633                         if (zone->view->resolver != NULL)
10634                                 udpsize =
10635                                   dns_resolver_getudpsize(zone->view->resolver);
10636                         (void)dns_peer_getudpsize(peer, &udpsize);
10637                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
10638                 }
10639
10640         }
10641         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10642                 result = add_opt(message, udpsize, reqnsid);
10643                 if (result != ISC_R_SUCCESS)
10644                         zone_debuglog(zone, me, 1,
10645                                       "unable to add opt record: %s",
10646                                       dns_result_totext(result));
10647         }
10648
10649         /*
10650          * Always use TCP so that we shouldn't truncate in additional section.
10651          */
10652         switch (isc_sockaddr_pf(&zone->masteraddr)) {
10653         case PF_INET:
10654                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10655                         zone->sourceaddr = zone->altxfrsource4;
10656                 else if (!have_xfrsource)
10657                         zone->sourceaddr = zone->xfrsource4;
10658                 break;
10659         case PF_INET6:
10660                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10661                         zone->sourceaddr = zone->altxfrsource6;
10662                 else if (!have_xfrsource)
10663                         zone->sourceaddr = zone->xfrsource6;
10664                 break;
10665         default:
10666                 result = ISC_R_NOTIMPLEMENTED;
10667                 POST(result);
10668                 goto cleanup;
10669         }
10670         timeout = 15;
10671         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10672                 timeout = 30;
10673         result = dns_request_createvia2(zone->view->requestmgr, message,
10674                                         &zone->sourceaddr, &zone->masteraddr,
10675                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
10676                                         timeout, zone->task, stub_callback,
10677                                         stub, &zone->request);
10678         if (result != ISC_R_SUCCESS) {
10679                 zone_debuglog(zone, me, 1,
10680                               "dns_request_createvia() failed: %s",
10681                               dns_result_totext(result));
10682                 goto cleanup;
10683         }
10684         dns_message_destroy(&message);
10685         goto unlock;
10686
10687  cleanup:
10688         cancel_refresh(zone);
10689         if (stub != NULL) {
10690                 stub->magic = 0;
10691                 if (stub->version != NULL)
10692                         dns_db_closeversion(stub->db, &stub->version,
10693                                             ISC_FALSE);
10694                 if (stub->db != NULL)
10695                         dns_db_detach(&stub->db);
10696                 if (stub->zone != NULL)
10697                         zone_idetach(&stub->zone);
10698                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
10699         }
10700         if (message != NULL)
10701                 dns_message_destroy(&message);
10702  unlock:
10703         if (key != NULL)
10704                 dns_tsigkey_detach(&key);
10705         return;
10706 }
10707
10708 /*
10709  * Handle the control event.  Note that although this event causes the zone
10710  * to shut down, it is not a shutdown event in the sense of the task library.
10711  */
10712 static void
10713 zone_shutdown(isc_task_t *task, isc_event_t *event) {
10714         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
10715         isc_boolean_t free_needed, linked = ISC_FALSE;
10716
10717         UNUSED(task);
10718         REQUIRE(DNS_ZONE_VALID(zone));
10719         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
10720         INSIST(isc_refcount_current(&zone->erefs) == 0);
10721
10722         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
10723
10724         /*
10725          * Stop things being restarted after we cancel them below.
10726          */
10727         LOCK_ZONE(zone);
10728         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
10729         UNLOCK_ZONE(zone);
10730
10731         /*
10732          * If we were waiting for xfrin quota, step out of
10733          * the queue.
10734          * If there's no zone manager, we can't be waiting for the
10735          * xfrin quota
10736          */
10737         if (zone->zmgr != NULL) {
10738                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10739                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
10740                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
10741                                         statelink);
10742                         linked = ISC_TRUE;
10743                         zone->statelist = NULL;
10744                 }
10745                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10746         }
10747
10748         /*
10749          * In task context, no locking required.  See zone_xfrdone().
10750          */
10751         if (zone->xfr != NULL)
10752                 dns_xfrin_shutdown(zone->xfr);
10753
10754         LOCK_ZONE(zone);
10755         if (linked) {
10756                 INSIST(zone->irefs > 0);
10757                 zone->irefs--;
10758         }
10759         if (zone->request != NULL) {
10760                 dns_request_cancel(zone->request);
10761         }
10762
10763         if (zone->readio != NULL)
10764                 zonemgr_cancelio(zone->readio);
10765
10766         if (zone->lctx != NULL)
10767                 dns_loadctx_cancel(zone->lctx);
10768
10769         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
10770             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10771                 if (zone->writeio != NULL)
10772                         zonemgr_cancelio(zone->writeio);
10773
10774                 if (zone->dctx != NULL)
10775                         dns_dumpctx_cancel(zone->dctx);
10776         }
10777
10778         notify_cancel(zone);
10779
10780         forward_cancel(zone);
10781
10782         if (zone->timer != NULL) {
10783                 isc_timer_detach(&zone->timer);
10784                 INSIST(zone->irefs > 0);
10785                 zone->irefs--;
10786         }
10787
10788         if (zone->view != NULL)
10789                 dns_view_weakdetach(&zone->view);
10790
10791         /*
10792          * We have now canceled everything set the flag to allow exit_check()
10793          * to succeed.  We must not unlock between setting this flag and
10794          * calling exit_check().
10795          */
10796         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
10797         free_needed = exit_check(zone);
10798         UNLOCK_ZONE(zone);
10799         if (free_needed)
10800                 zone_free(zone);
10801 }
10802
10803 static void
10804 zone_timer(isc_task_t *task, isc_event_t *event) {
10805         const char me[] = "zone_timer";
10806         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
10807
10808         UNUSED(task);
10809         REQUIRE(DNS_ZONE_VALID(zone));
10810
10811         ENTER;
10812
10813         zone_maintenance(zone);
10814
10815         isc_event_free(&event);
10816 }
10817
10818 static void
10819 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
10820         const char me[] = "zone_settimer";
10821         isc_time_t next;
10822         isc_result_t result;
10823
10824         ENTER;
10825         REQUIRE(DNS_ZONE_VALID(zone));
10826         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10827                 return;
10828
10829         isc_time_settoepoch(&next);
10830
10831         switch (zone->type) {
10832         case dns_zone_master:
10833                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10834                         next = zone->notifytime;
10835                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10836                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10837                         INSIST(!isc_time_isepoch(&zone->dumptime));
10838                         if (isc_time_isepoch(&next) ||
10839                             isc_time_compare(&zone->dumptime, &next) < 0)
10840                                 next = zone->dumptime;
10841                 }
10842                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
10843                     !isc_time_isepoch(&zone->refreshkeytime)) {
10844                         if (isc_time_isepoch(&next) ||
10845                             isc_time_compare(&zone->refreshkeytime, &next) < 0)
10846                                 next = zone->refreshkeytime;
10847                 }
10848                 if (!isc_time_isepoch(&zone->resigntime)) {
10849                         if (isc_time_isepoch(&next) ||
10850                             isc_time_compare(&zone->resigntime, &next) < 0)
10851                                 next = zone->resigntime;
10852                 }
10853                 if (!isc_time_isepoch(&zone->keywarntime)) {
10854                         if (isc_time_isepoch(&next) ||
10855                             isc_time_compare(&zone->keywarntime, &next) < 0)
10856                                 next = zone->keywarntime;
10857                 }
10858                 if (!isc_time_isepoch(&zone->signingtime)) {
10859                         if (isc_time_isepoch(&next) ||
10860                             isc_time_compare(&zone->signingtime, &next) < 0)
10861                                 next = zone->signingtime;
10862                 }
10863                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
10864                         if (isc_time_isepoch(&next) ||
10865                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
10866                                 next = zone->nsec3chaintime;
10867                 }
10868                 break;
10869
10870         case dns_zone_slave:
10871                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10872                         next = zone->notifytime;
10873                 /*FALLTHROUGH*/
10874
10875         case dns_zone_stub:
10876                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
10877                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
10878                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
10879                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
10880                         INSIST(!isc_time_isepoch(&zone->refreshtime));
10881                         if (isc_time_isepoch(&next) ||
10882                             isc_time_compare(&zone->refreshtime, &next) < 0)
10883                                 next = zone->refreshtime;
10884                 }
10885                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10886                     !isc_time_isepoch(&zone->expiretime)) {
10887                         if (isc_time_isepoch(&next) ||
10888                              isc_time_compare(&zone->expiretime, &next) < 0)
10889                                 next = zone->expiretime;
10890                 }
10891                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10892                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10893                         INSIST(!isc_time_isepoch(&zone->dumptime));
10894                         if (isc_time_isepoch(&next) ||
10895                             isc_time_compare(&zone->dumptime, &next) < 0)
10896                                 next = zone->dumptime;
10897                 }
10898                 break;
10899
10900         case dns_zone_key:
10901                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10902                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10903                         INSIST(!isc_time_isepoch(&zone->dumptime));
10904                         if (isc_time_isepoch(&next) ||
10905                             isc_time_compare(&zone->dumptime, &next) < 0)
10906                                 next = zone->dumptime;
10907                 }
10908                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10909                         if (isc_time_isepoch(&next) ||
10910                             (!isc_time_isepoch(&zone->refreshkeytime) &&
10911                             isc_time_compare(&zone->refreshkeytime, &next) < 0))
10912                                 next = zone->refreshkeytime;
10913                 }
10914                 break;
10915
10916         default:
10917                 break;
10918         }
10919
10920         if (isc_time_isepoch(&next)) {
10921                 zone_debuglog(zone, me, 10, "settimer inactive");
10922                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
10923                                           NULL, NULL, ISC_TRUE);
10924                 if (result != ISC_R_SUCCESS)
10925                         dns_zone_log(zone, ISC_LOG_ERROR,
10926                                      "could not deactivate zone timer: %s",
10927                                      isc_result_totext(result));
10928         } else {
10929                 if (isc_time_compare(&next, now) <= 0)
10930                         next = *now;
10931                 result = isc_timer_reset(zone->timer, isc_timertype_once,
10932                                          &next, NULL, ISC_TRUE);
10933                 if (result != ISC_R_SUCCESS)
10934                         dns_zone_log(zone, ISC_LOG_ERROR,
10935                                      "could not reset zone timer: %s",
10936                                      isc_result_totext(result));
10937         }
10938 }
10939
10940 static void
10941 cancel_refresh(dns_zone_t *zone) {
10942         const char me[] = "cancel_refresh";
10943         isc_time_t now;
10944
10945         /*
10946          * 'zone' locked by caller.
10947          */
10948
10949         REQUIRE(DNS_ZONE_VALID(zone));
10950         REQUIRE(LOCKED_ZONE(zone));
10951
10952         ENTER;
10953
10954         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10955         TIME_NOW(&now);
10956         zone_settimer(zone, &now);
10957 }
10958
10959 static isc_result_t
10960 notify_createmessage(dns_zone_t *zone, unsigned int flags,
10961                      dns_message_t **messagep)
10962 {
10963         dns_db_t *zonedb = NULL;
10964         dns_dbnode_t *node = NULL;
10965         dns_dbversion_t *version = NULL;
10966         dns_message_t *message = NULL;
10967         dns_rdataset_t rdataset;
10968         dns_rdata_t rdata = DNS_RDATA_INIT;
10969
10970         dns_name_t *tempname = NULL;
10971         dns_rdata_t *temprdata = NULL;
10972         dns_rdatalist_t *temprdatalist = NULL;
10973         dns_rdataset_t *temprdataset = NULL;
10974
10975         isc_result_t result;
10976         isc_region_t r;
10977         isc_buffer_t *b = NULL;
10978
10979         REQUIRE(DNS_ZONE_VALID(zone));
10980         REQUIRE(messagep != NULL && *messagep == NULL);
10981
10982         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10983                                     &message);
10984         if (result != ISC_R_SUCCESS)
10985                 return (result);
10986
10987         message->opcode = dns_opcode_notify;
10988         message->flags |= DNS_MESSAGEFLAG_AA;
10989         message->rdclass = zone->rdclass;
10990
10991         result = dns_message_gettempname(message, &tempname);
10992         if (result != ISC_R_SUCCESS)
10993                 goto cleanup;
10994
10995         result = dns_message_gettemprdataset(message, &temprdataset);
10996         if (result != ISC_R_SUCCESS)
10997                 goto cleanup;
10998
10999         /*
11000          * Make question.
11001          */
11002         dns_name_init(tempname, NULL);
11003         dns_name_clone(&zone->origin, tempname);
11004         dns_rdataset_init(temprdataset);
11005         dns_rdataset_makequestion(temprdataset, zone->rdclass,
11006                                   dns_rdatatype_soa);
11007         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11008         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
11009         tempname = NULL;
11010         temprdataset = NULL;
11011
11012         if ((flags & DNS_NOTIFY_NOSOA) != 0)
11013                 goto done;
11014
11015         result = dns_message_gettempname(message, &tempname);
11016         if (result != ISC_R_SUCCESS)
11017                 goto soa_cleanup;
11018         result = dns_message_gettemprdata(message, &temprdata);
11019         if (result != ISC_R_SUCCESS)
11020                 goto soa_cleanup;
11021         result = dns_message_gettemprdataset(message, &temprdataset);
11022         if (result != ISC_R_SUCCESS)
11023                 goto soa_cleanup;
11024         result = dns_message_gettemprdatalist(message, &temprdatalist);
11025         if (result != ISC_R_SUCCESS)
11026                 goto soa_cleanup;
11027
11028         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11029         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
11030         dns_db_attach(zone->db, &zonedb);
11031         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11032
11033         dns_name_init(tempname, NULL);
11034         dns_name_clone(&zone->origin, tempname);
11035         dns_db_currentversion(zonedb, &version);
11036         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
11037         if (result != ISC_R_SUCCESS)
11038                 goto soa_cleanup;
11039
11040         dns_rdataset_init(&rdataset);
11041         result = dns_db_findrdataset(zonedb, node, version,
11042                                      dns_rdatatype_soa,
11043                                      dns_rdatatype_none, 0, &rdataset,
11044                                      NULL);
11045         if (result != ISC_R_SUCCESS)
11046                 goto soa_cleanup;
11047         result = dns_rdataset_first(&rdataset);
11048         if (result != ISC_R_SUCCESS)
11049                 goto soa_cleanup;
11050         dns_rdataset_current(&rdataset, &rdata);
11051         dns_rdata_toregion(&rdata, &r);
11052         result = isc_buffer_allocate(zone->mctx, &b, r.length);
11053         if (result != ISC_R_SUCCESS)
11054                 goto soa_cleanup;
11055         isc_buffer_putmem(b, r.base, r.length);
11056         isc_buffer_usedregion(b, &r);
11057         dns_rdata_init(temprdata);
11058         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
11059         dns_message_takebuffer(message, &b);
11060         result = dns_rdataset_next(&rdataset);
11061         dns_rdataset_disassociate(&rdataset);
11062         if (result != ISC_R_NOMORE)
11063                 goto soa_cleanup;
11064         temprdatalist->rdclass = rdata.rdclass;
11065         temprdatalist->type = rdata.type;
11066         temprdatalist->covers = 0;
11067         temprdatalist->ttl = rdataset.ttl;
11068         ISC_LIST_INIT(temprdatalist->rdata);
11069         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
11070
11071         dns_rdataset_init(temprdataset);
11072         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
11073         if (result != ISC_R_SUCCESS)
11074                 goto soa_cleanup;
11075
11076         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11077         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
11078         temprdatalist = NULL;
11079         temprdataset = NULL;
11080         temprdata = NULL;
11081         tempname = NULL;
11082
11083  soa_cleanup:
11084         if (node != NULL)
11085                 dns_db_detachnode(zonedb, &node);
11086         if (version != NULL)
11087                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
11088         if (zonedb != NULL)
11089                 dns_db_detach(&zonedb);
11090         if (tempname != NULL)
11091                 dns_message_puttempname(message, &tempname);
11092         if (temprdata != NULL)
11093                 dns_message_puttemprdata(message, &temprdata);
11094         if (temprdataset != NULL)
11095                 dns_message_puttemprdataset(message, &temprdataset);
11096         if (temprdatalist != NULL)
11097                 dns_message_puttemprdatalist(message, &temprdatalist);
11098
11099  done:
11100         *messagep = message;
11101         return (ISC_R_SUCCESS);
11102
11103  cleanup:
11104         if (tempname != NULL)
11105                 dns_message_puttempname(message, &tempname);
11106         if (temprdataset != NULL)
11107                 dns_message_puttemprdataset(message, &temprdataset);
11108         dns_message_destroy(&message);
11109         return (result);
11110 }
11111
11112 isc_result_t
11113 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
11114                        dns_message_t *msg)
11115 {
11116         unsigned int i;
11117         dns_rdata_soa_t soa;
11118         dns_rdataset_t *rdataset = NULL;
11119         dns_rdata_t rdata = DNS_RDATA_INIT;
11120         isc_result_t result;
11121         char fromtext[ISC_SOCKADDR_FORMATSIZE];
11122         int match = 0;
11123         isc_netaddr_t netaddr;
11124         isc_sockaddr_t local, remote;
11125
11126         REQUIRE(DNS_ZONE_VALID(zone));
11127
11128         /*
11129          * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
11130          * ROLLOVER.
11131          *
11132          * SOA: RFC1996
11133          * Check that 'from' is a valid notify source, (zone->masters).
11134          *      Return DNS_R_REFUSED if not.
11135          *
11136          * If the notify message contains a serial number check it
11137          * against the zones serial and return if <= current serial
11138          *
11139          * If a refresh check is progress, if so just record the
11140          * fact we received a NOTIFY and from where and return.
11141          * We will perform a new refresh check when the current one
11142          * completes. Return ISC_R_SUCCESS.
11143          *
11144          * Otherwise initiate a refresh check using 'from' as the
11145          * first address to check.  Return ISC_R_SUCCESS.
11146          */
11147
11148         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
11149
11150         /*
11151          *  We only handle NOTIFY (SOA) at the present.
11152          */
11153         LOCK_ZONE(zone);
11154         if (isc_sockaddr_pf(from) == PF_INET)
11155                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
11156         else
11157                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
11158         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
11159             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
11160                                  dns_rdatatype_soa, dns_rdatatype_none,
11161                                  NULL, NULL) != ISC_R_SUCCESS) {
11162                 UNLOCK_ZONE(zone);
11163                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
11164                         dns_zone_log(zone, ISC_LOG_NOTICE,
11165                                      "NOTIFY with no "
11166                                      "question section from: %s", fromtext);
11167                         return (DNS_R_FORMERR);
11168                 }
11169                 dns_zone_log(zone, ISC_LOG_NOTICE,
11170                              "NOTIFY zone does not match");
11171                 return (DNS_R_NOTIMP);
11172         }
11173
11174         /*
11175          * If we are a master zone just succeed.
11176          */
11177         if (zone->type == dns_zone_master) {
11178                 UNLOCK_ZONE(zone);
11179                 return (ISC_R_SUCCESS);
11180         }
11181
11182         isc_netaddr_fromsockaddr(&netaddr, from);
11183         for (i = 0; i < zone->masterscnt; i++) {
11184                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
11185                         break;
11186                 if (zone->view->aclenv.match_mapped &&
11187                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
11188                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
11189                         isc_netaddr_t na1, na2;
11190                         isc_netaddr_fromv4mapped(&na1, &netaddr);
11191                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
11192                         if (isc_netaddr_equal(&na1, &na2))
11193                                 break;
11194                 }
11195         }
11196
11197         /*
11198          * Accept notify requests from non masters if they are on
11199          * 'zone->notify_acl'.
11200          */
11201         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
11202             dns_acl_match(&netaddr, NULL, zone->notify_acl,
11203                           &zone->view->aclenv,
11204                           &match, NULL) == ISC_R_SUCCESS &&
11205             match > 0)
11206         {
11207                 /* Accept notify. */
11208         } else if (i >= zone->masterscnt) {
11209                 UNLOCK_ZONE(zone);
11210                 dns_zone_log(zone, ISC_LOG_INFO,
11211                              "refused notify from non-master: %s", fromtext);
11212                 inc_stats(zone, dns_zonestatscounter_notifyrej);
11213                 return (DNS_R_REFUSED);
11214         }
11215
11216         /*
11217          * If the zone is loaded and there are answers check the serial
11218          * to see if we need to do a refresh.  Do not worry about this
11219          * check if we are a dialup zone as we use the notify request
11220          * to trigger a refresh check.
11221          */
11222         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
11223             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11224             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
11225                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
11226                                               &zone->origin,
11227                                               dns_rdatatype_soa,
11228                                               dns_rdatatype_none, NULL,
11229                                               &rdataset);
11230                 if (result == ISC_R_SUCCESS)
11231                         result = dns_rdataset_first(rdataset);
11232                 if (result == ISC_R_SUCCESS) {
11233                         isc_uint32_t serial = 0, oldserial;
11234                         unsigned int soacount;
11235
11236                         dns_rdataset_current(rdataset, &rdata);
11237                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
11238                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11239                         serial = soa.serial;
11240                         /*
11241                          * The following should safely be performed without DB
11242                          * lock and succeed in this context.
11243                          */
11244                         result = zone_get_from_db(zone, zone->db, NULL,
11245                                                   &soacount, &oldserial, NULL,
11246                                                   NULL, NULL, NULL, NULL);
11247                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11248                         RUNTIME_CHECK(soacount > 0U);
11249                         if (isc_serial_le(serial, oldserial)) {
11250                                 dns_zone_log(zone,
11251                                              ISC_LOG_INFO,
11252                                              "notify from %s: "
11253                                              "zone is up to date",
11254                                              fromtext);
11255                                 UNLOCK_ZONE(zone);
11256                                 return (ISC_R_SUCCESS);
11257                         }
11258                 }
11259         }
11260
11261         /*
11262          * If we got this far and there was a refresh in progress just
11263          * let it complete.  Record where we got the notify from so we
11264          * can perform a refresh check when the current one completes
11265          */
11266         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
11267                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11268                 zone->notifyfrom = *from;
11269                 UNLOCK_ZONE(zone);
11270                 dns_zone_log(zone, ISC_LOG_INFO,
11271                              "notify from %s: refresh in progress, "
11272                              "refresh check queued",
11273                              fromtext);
11274                 return (ISC_R_SUCCESS);
11275         }
11276         zone->notifyfrom = *from;
11277         local = zone->masteraddr;
11278         remote = zone->sourceaddr;
11279         UNLOCK_ZONE(zone);
11280         dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
11281         dns_zone_refresh(zone);
11282         return (ISC_R_SUCCESS);
11283 }
11284
11285 void
11286 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
11287
11288         REQUIRE(DNS_ZONE_VALID(zone));
11289
11290         LOCK_ZONE(zone);
11291         if (zone->notify_acl != NULL)
11292                 dns_acl_detach(&zone->notify_acl);
11293         dns_acl_attach(acl, &zone->notify_acl);
11294         UNLOCK_ZONE(zone);
11295 }
11296
11297 void
11298 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
11299
11300         REQUIRE(DNS_ZONE_VALID(zone));
11301
11302         LOCK_ZONE(zone);
11303         if (zone->query_acl != NULL)
11304                 dns_acl_detach(&zone->query_acl);
11305         dns_acl_attach(acl, &zone->query_acl);
11306         UNLOCK_ZONE(zone);
11307 }
11308
11309 void
11310 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
11311
11312         REQUIRE(DNS_ZONE_VALID(zone));
11313
11314         LOCK_ZONE(zone);
11315         if (zone->queryon_acl != NULL)
11316                 dns_acl_detach(&zone->queryon_acl);
11317         dns_acl_attach(acl, &zone->queryon_acl);
11318         UNLOCK_ZONE(zone);
11319 }
11320
11321 void
11322 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
11323
11324         REQUIRE(DNS_ZONE_VALID(zone));
11325
11326         LOCK_ZONE(zone);
11327         if (zone->update_acl != NULL)
11328                 dns_acl_detach(&zone->update_acl);
11329         dns_acl_attach(acl, &zone->update_acl);
11330         UNLOCK_ZONE(zone);
11331 }
11332
11333 void
11334 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
11335
11336         REQUIRE(DNS_ZONE_VALID(zone));
11337
11338         LOCK_ZONE(zone);
11339         if (zone->forward_acl != NULL)
11340                 dns_acl_detach(&zone->forward_acl);
11341         dns_acl_attach(acl, &zone->forward_acl);
11342         UNLOCK_ZONE(zone);
11343 }
11344
11345 void
11346 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
11347
11348         REQUIRE(DNS_ZONE_VALID(zone));
11349
11350         LOCK_ZONE(zone);
11351         if (zone->xfr_acl != NULL)
11352                 dns_acl_detach(&zone->xfr_acl);
11353         dns_acl_attach(acl, &zone->xfr_acl);
11354         UNLOCK_ZONE(zone);
11355 }
11356
11357 dns_acl_t *
11358 dns_zone_getnotifyacl(dns_zone_t *zone) {
11359
11360         REQUIRE(DNS_ZONE_VALID(zone));
11361
11362         return (zone->notify_acl);
11363 }
11364
11365 dns_acl_t *
11366 dns_zone_getqueryacl(dns_zone_t *zone) {
11367
11368         REQUIRE(DNS_ZONE_VALID(zone));
11369
11370         return (zone->query_acl);
11371 }
11372
11373 dns_acl_t *
11374 dns_zone_getqueryonacl(dns_zone_t *zone) {
11375
11376         REQUIRE(DNS_ZONE_VALID(zone));
11377
11378         return (zone->queryon_acl);
11379 }
11380
11381 dns_acl_t *
11382 dns_zone_getupdateacl(dns_zone_t *zone) {
11383
11384         REQUIRE(DNS_ZONE_VALID(zone));
11385
11386         return (zone->update_acl);
11387 }
11388
11389 dns_acl_t *
11390 dns_zone_getforwardacl(dns_zone_t *zone) {
11391
11392         REQUIRE(DNS_ZONE_VALID(zone));
11393
11394         return (zone->forward_acl);
11395 }
11396
11397 dns_acl_t *
11398 dns_zone_getxfracl(dns_zone_t *zone) {
11399
11400         REQUIRE(DNS_ZONE_VALID(zone));
11401
11402         return (zone->xfr_acl);
11403 }
11404
11405 void
11406 dns_zone_clearupdateacl(dns_zone_t *zone) {
11407
11408         REQUIRE(DNS_ZONE_VALID(zone));
11409
11410         LOCK_ZONE(zone);
11411         if (zone->update_acl != NULL)
11412                 dns_acl_detach(&zone->update_acl);
11413         UNLOCK_ZONE(zone);
11414 }
11415
11416 void
11417 dns_zone_clearforwardacl(dns_zone_t *zone) {
11418
11419         REQUIRE(DNS_ZONE_VALID(zone));
11420
11421         LOCK_ZONE(zone);
11422         if (zone->forward_acl != NULL)
11423                 dns_acl_detach(&zone->forward_acl);
11424         UNLOCK_ZONE(zone);
11425 }
11426
11427 void
11428 dns_zone_clearnotifyacl(dns_zone_t *zone) {
11429
11430         REQUIRE(DNS_ZONE_VALID(zone));
11431
11432         LOCK_ZONE(zone);
11433         if (zone->notify_acl != NULL)
11434                 dns_acl_detach(&zone->notify_acl);
11435         UNLOCK_ZONE(zone);
11436 }
11437
11438 void
11439 dns_zone_clearqueryacl(dns_zone_t *zone) {
11440
11441         REQUIRE(DNS_ZONE_VALID(zone));
11442
11443         LOCK_ZONE(zone);
11444         if (zone->query_acl != NULL)
11445                 dns_acl_detach(&zone->query_acl);
11446         UNLOCK_ZONE(zone);
11447 }
11448
11449 void
11450 dns_zone_clearqueryonacl(dns_zone_t *zone) {
11451
11452         REQUIRE(DNS_ZONE_VALID(zone));
11453
11454         LOCK_ZONE(zone);
11455         if (zone->queryon_acl != NULL)
11456                 dns_acl_detach(&zone->queryon_acl);
11457         UNLOCK_ZONE(zone);
11458 }
11459
11460 void
11461 dns_zone_clearxfracl(dns_zone_t *zone) {
11462
11463         REQUIRE(DNS_ZONE_VALID(zone));
11464
11465         LOCK_ZONE(zone);
11466         if (zone->xfr_acl != NULL)
11467                 dns_acl_detach(&zone->xfr_acl);
11468         UNLOCK_ZONE(zone);
11469 }
11470
11471 isc_boolean_t
11472 dns_zone_getupdatedisabled(dns_zone_t *zone) {
11473         REQUIRE(DNS_ZONE_VALID(zone));
11474         return (zone->update_disabled);
11475
11476 }
11477
11478 void
11479 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
11480         REQUIRE(DNS_ZONE_VALID(zone));
11481         zone->update_disabled = state;
11482 }
11483
11484 isc_boolean_t
11485 dns_zone_getzeronosoattl(dns_zone_t *zone) {
11486         REQUIRE(DNS_ZONE_VALID(zone));
11487         return (zone->zero_no_soa_ttl);
11488
11489 }
11490
11491 void
11492 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
11493         REQUIRE(DNS_ZONE_VALID(zone));
11494         zone->zero_no_soa_ttl = state;
11495 }
11496
11497 void
11498 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
11499
11500         REQUIRE(DNS_ZONE_VALID(zone));
11501
11502         zone->check_names = severity;
11503 }
11504
11505 dns_severity_t
11506 dns_zone_getchecknames(dns_zone_t *zone) {
11507
11508         REQUIRE(DNS_ZONE_VALID(zone));
11509
11510         return (zone->check_names);
11511 }
11512
11513 void
11514 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
11515
11516         REQUIRE(DNS_ZONE_VALID(zone));
11517
11518         zone->journalsize = size;
11519 }
11520
11521 isc_int32_t
11522 dns_zone_getjournalsize(dns_zone_t *zone) {
11523
11524         REQUIRE(DNS_ZONE_VALID(zone));
11525
11526         return (zone->journalsize);
11527 }
11528
11529 static void
11530 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
11531         isc_result_t result = ISC_R_FAILURE;
11532         isc_buffer_t buffer;
11533
11534         REQUIRE(buf != NULL);
11535         REQUIRE(length > 1U);
11536
11537         /*
11538          * Leave space for terminating '\0'.
11539          */
11540         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
11541         if (dns_name_dynamic(&zone->origin))
11542                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11543         if (result != ISC_R_SUCCESS &&
11544             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11545                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
11546
11547         if (isc_buffer_availablelength(&buffer) > 0)
11548                 isc_buffer_putstr(&buffer, "/");
11549         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
11550
11551         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
11552             strcmp(zone->view->name, "_default") != 0 &&
11553             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
11554                 isc_buffer_putstr(&buffer, "/");
11555                 isc_buffer_putstr(&buffer, zone->view->name);
11556         }
11557
11558         buf[isc_buffer_usedlength(&buffer)] = '\0';
11559 }
11560
11561 static void
11562 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
11563         isc_result_t result = ISC_R_FAILURE;
11564         isc_buffer_t buffer;
11565
11566         REQUIRE(buf != NULL);
11567         REQUIRE(length > 1U);
11568
11569         /*
11570          * Leave space for terminating '\0'.
11571          */
11572         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
11573         if (dns_name_dynamic(&zone->origin))
11574                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11575         if (result != ISC_R_SUCCESS &&
11576             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11577                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
11578
11579         buf[isc_buffer_usedlength(&buffer)] = '\0';
11580 }
11581
11582 static void
11583 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
11584         isc_buffer_t buffer;
11585
11586         REQUIRE(buf != NULL);
11587         REQUIRE(length > 1U);
11588
11589         /*
11590          * Leave space for terminating '\0'.
11591          */
11592         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
11593         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
11594
11595         buf[isc_buffer_usedlength(&buffer)] = '\0';
11596 }
11597
11598 static void
11599 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
11600         isc_buffer_t buffer;
11601
11602         REQUIRE(buf != NULL);
11603         REQUIRE(length > 1U);
11604
11605
11606         /*
11607          * Leave space for terminating '\0'.
11608          */
11609         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
11610
11611         if (zone->view == NULL) {
11612                 isc_buffer_putstr(&buffer, "_none");
11613         } else if (strlen(zone->view->name)
11614                    < isc_buffer_availablelength(&buffer)) {
11615                 isc_buffer_putstr(&buffer, zone->view->name);
11616         } else {
11617                 isc_buffer_putstr(&buffer, "_toolong");
11618         }
11619
11620         buf[isc_buffer_usedlength(&buffer)] = '\0';
11621 }
11622
11623 void
11624 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
11625         REQUIRE(DNS_ZONE_VALID(zone));
11626         REQUIRE(buf != NULL);
11627         zone_namerd_tostr(zone, buf, length);
11628 }
11629
11630 static void
11631 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11632         va_list ap;
11633         char message[4096];
11634
11635         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11636                 return;
11637
11638         va_start(ap, fmt);
11639         vsnprintf(message, sizeof(message), fmt, ap);
11640         va_end(ap);
11641         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
11642                       level, "zone %s: %s", zone->strnamerd, message);
11643 }
11644
11645 void
11646 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
11647               int level, const char *fmt, ...) {
11648         va_list ap;
11649         char message[4096];
11650
11651         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11652                 return;
11653
11654         va_start(ap, fmt);
11655         vsnprintf(message, sizeof(message), fmt, ap);
11656         va_end(ap);
11657         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
11658                       level, "%s %s: %s", (zone->type == dns_zone_key) ?
11659                       "managed-keys-zone" : "zone", zone->strnamerd, message);
11660 }
11661
11662 void
11663 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11664         va_list ap;
11665         char message[4096];
11666
11667         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11668                 return;
11669
11670         va_start(ap, fmt);
11671         vsnprintf(message, sizeof(message), fmt, ap);
11672         va_end(ap);
11673         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11674                       level, "%s %s: %s", (zone->type == dns_zone_key) ?
11675                       "managed-keys-zone" : "zone", zone->strnamerd, message);
11676 }
11677
11678 static void
11679 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
11680               const char *fmt, ...)
11681 {
11682         va_list ap;
11683         char message[4096];
11684         int level = ISC_LOG_DEBUG(debuglevel);
11685
11686         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11687                 return;
11688
11689         va_start(ap, fmt);
11690         vsnprintf(message, sizeof(message), fmt, ap);
11691         va_end(ap);
11692         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11693                       level, "%s: %s %s: %s", me, zone->type != dns_zone_key ?
11694                       "zone" : "managed-keys-zone", zone->strnamerd, message);
11695 }
11696
11697 static int
11698 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
11699 {
11700         isc_result_t result;
11701         dns_name_t *name;
11702         dns_rdataset_t *curr;
11703         int count = 0;
11704
11705         result = dns_message_firstname(msg, section);
11706         while (result == ISC_R_SUCCESS) {
11707                 name = NULL;
11708                 dns_message_currentname(msg, section, &name);
11709
11710                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
11711                      curr = ISC_LIST_PREV(curr, link)) {
11712                         if (curr->type == type)
11713                                 count++;
11714                 }
11715                 result = dns_message_nextname(msg, section);
11716         }
11717
11718         return (count);
11719 }
11720
11721 void
11722 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
11723         REQUIRE(DNS_ZONE_VALID(zone));
11724
11725         zone->maxxfrin = maxxfrin;
11726 }
11727
11728 isc_uint32_t
11729 dns_zone_getmaxxfrin(dns_zone_t *zone) {
11730         REQUIRE(DNS_ZONE_VALID(zone));
11731
11732         return (zone->maxxfrin);
11733 }
11734
11735 void
11736 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
11737         REQUIRE(DNS_ZONE_VALID(zone));
11738         zone->maxxfrout = maxxfrout;
11739 }
11740
11741 isc_uint32_t
11742 dns_zone_getmaxxfrout(dns_zone_t *zone) {
11743         REQUIRE(DNS_ZONE_VALID(zone));
11744
11745         return (zone->maxxfrout);
11746 }
11747
11748 dns_zonetype_t
11749 dns_zone_gettype(dns_zone_t *zone) {
11750         REQUIRE(DNS_ZONE_VALID(zone));
11751
11752         return (zone->type);
11753 }
11754
11755 dns_name_t *
11756 dns_zone_getorigin(dns_zone_t *zone) {
11757         REQUIRE(DNS_ZONE_VALID(zone));
11758
11759         return (&zone->origin);
11760 }
11761
11762 void
11763 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
11764         REQUIRE(DNS_ZONE_VALID(zone));
11765
11766         LOCK_ZONE(zone);
11767         if (zone->task != NULL)
11768                 isc_task_detach(&zone->task);
11769         isc_task_attach(task, &zone->task);
11770         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11771         if (zone->db != NULL)
11772                 dns_db_settask(zone->db, zone->task);
11773         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11774         UNLOCK_ZONE(zone);
11775 }
11776
11777 void
11778 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
11779         REQUIRE(DNS_ZONE_VALID(zone));
11780         isc_task_attach(zone->task, target);
11781 }
11782
11783 void
11784 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
11785         REQUIRE(DNS_ZONE_VALID(zone));
11786
11787         if (idlein == 0)
11788                 idlein = DNS_DEFAULT_IDLEIN;
11789         zone->idlein = idlein;
11790 }
11791
11792 isc_uint32_t
11793 dns_zone_getidlein(dns_zone_t *zone) {
11794         REQUIRE(DNS_ZONE_VALID(zone));
11795
11796         return (zone->idlein);
11797 }
11798
11799 void
11800 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
11801         REQUIRE(DNS_ZONE_VALID(zone));
11802
11803         zone->idleout = idleout;
11804 }
11805
11806 isc_uint32_t
11807 dns_zone_getidleout(dns_zone_t *zone) {
11808         REQUIRE(DNS_ZONE_VALID(zone));
11809
11810         return (zone->idleout);
11811 }
11812
11813 static void
11814 notify_done(isc_task_t *task, isc_event_t *event) {
11815         dns_requestevent_t *revent = (dns_requestevent_t *)event;
11816         dns_notify_t *notify;
11817         isc_result_t result;
11818         dns_message_t *message = NULL;
11819         isc_buffer_t buf;
11820         char rcode[128];
11821         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
11822
11823         UNUSED(task);
11824
11825         notify = event->ev_arg;
11826         REQUIRE(DNS_NOTIFY_VALID(notify));
11827         INSIST(task == notify->zone->task);
11828
11829         isc_buffer_init(&buf, rcode, sizeof(rcode));
11830         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
11831
11832         result = revent->result;
11833         if (result == ISC_R_SUCCESS)
11834                 result = dns_message_create(notify->zone->mctx,
11835                                             DNS_MESSAGE_INTENTPARSE, &message);
11836         if (result == ISC_R_SUCCESS)
11837                 result = dns_request_getresponse(revent->request, message,
11838                                         DNS_MESSAGEPARSE_PRESERVEORDER);
11839         if (result == ISC_R_SUCCESS)
11840                 result = dns_rcode_totext(message->rcode, &buf);
11841         if (result == ISC_R_SUCCESS)
11842                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
11843                            "notify response from %s: %.*s",
11844                            addrbuf, (int)buf.used, rcode);
11845         else
11846                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
11847                            "notify to %s failed: %s", addrbuf,
11848                            dns_result_totext(result));
11849
11850         /*
11851          * Old bind's return formerr if they see a soa record.  Retry w/o
11852          * the soa if we see a formerr and had sent a SOA.
11853          */
11854         isc_event_free(&event);
11855         if (message != NULL && message->rcode == dns_rcode_formerr &&
11856             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
11857                 notify->flags |= DNS_NOTIFY_NOSOA;
11858                 dns_request_destroy(&notify->request);
11859                 result = notify_send_queue(notify);
11860                 if (result != ISC_R_SUCCESS)
11861                         notify_destroy(notify, ISC_FALSE);
11862         } else {
11863                 if (result == ISC_R_TIMEDOUT)
11864                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
11865                                    "notify to %s: retries exceeded", addrbuf);
11866                 notify_destroy(notify, ISC_FALSE);
11867         }
11868         if (message != NULL)
11869                 dns_message_destroy(&message);
11870 }
11871
11872 isc_result_t
11873 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11874         isc_result_t result;
11875
11876         REQUIRE(DNS_ZONE_VALID(zone));
11877         LOCK_ZONE(zone);
11878         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11879         result = zone_replacedb(zone, db, dump);
11880         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11881         UNLOCK_ZONE(zone);
11882         return (result);
11883 }
11884
11885 static isc_result_t
11886 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11887         dns_dbversion_t *ver;
11888         isc_result_t result;
11889         unsigned int soacount = 0;
11890         unsigned int nscount = 0;
11891
11892         /*
11893          * 'zone' and 'zonedb' locked by caller.
11894          */
11895         REQUIRE(DNS_ZONE_VALID(zone));
11896         REQUIRE(LOCKED_ZONE(zone));
11897
11898         result = zone_get_from_db(zone, db, &nscount, &soacount,
11899                                   NULL, NULL, NULL, NULL, NULL, NULL);
11900         if (result == ISC_R_SUCCESS) {
11901                 if (soacount != 1) {
11902                         dns_zone_log(zone, ISC_LOG_ERROR,
11903                                      "has %d SOA records", soacount);
11904                         result = DNS_R_BADZONE;
11905                 }
11906                 if (nscount == 0 && zone->type != dns_zone_key) {
11907                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
11908                         result = DNS_R_BADZONE;
11909                 }
11910                 if (result != ISC_R_SUCCESS)
11911                         return (result);
11912         } else {
11913                 dns_zone_log(zone, ISC_LOG_ERROR,
11914                             "retrieving SOA and NS records failed: %s",
11915                             dns_result_totext(result));
11916                 return (result);
11917         }
11918
11919         result = check_nsec3param(zone, db);
11920         if (result != ISC_R_SUCCESS)
11921                 return (result);
11922
11923         ver = NULL;
11924         dns_db_currentversion(db, &ver);
11925
11926         /*
11927          * The initial version of a slave zone is always dumped;
11928          * subsequent versions may be journaled instead if this
11929          * is enabled in the configuration.
11930          */
11931         if (zone->db != NULL && zone->journal != NULL &&
11932             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
11933             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
11934                 isc_uint32_t serial, oldserial;
11935                 unsigned int soacount;
11936
11937                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
11938
11939                 result = dns_db_getsoaserial(db, ver, &serial);
11940                 if (result != ISC_R_SUCCESS) {
11941                         dns_zone_log(zone, ISC_LOG_ERROR,
11942                                      "ixfr-from-differences: unable to get "
11943                                      "new serial");
11944                         goto fail;
11945                 }
11946
11947                 /*
11948                  * This is checked in zone_postload() for master zones.
11949                  */
11950                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
11951                                           &oldserial, NULL, NULL, NULL, NULL,
11952                                           NULL);
11953                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11954                 RUNTIME_CHECK(soacount > 0U);
11955                 if (zone->type == dns_zone_slave &&
11956                     !isc_serial_gt(serial, oldserial)) {
11957                         isc_uint32_t serialmin, serialmax;
11958                         serialmin = (oldserial + 1) & 0xffffffffU;
11959                         serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
11960                         dns_zone_log(zone, ISC_LOG_ERROR,
11961                                      "ixfr-from-differences: failed: "
11962                                      "new serial (%u) out of range [%u - %u]",
11963                                      serial, serialmin, serialmax);
11964                         result = ISC_R_RANGE;
11965                         goto fail;
11966                 }
11967
11968                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
11969                                      zone->journal);
11970                 if (result != ISC_R_SUCCESS)
11971                         goto fail;
11972                 if (dump)
11973                         zone_needdump(zone, DNS_DUMP_DELAY);
11974                 else if (zone->journalsize != -1) {
11975                         result = dns_journal_compact(zone->mctx, zone->journal,
11976                                                      serial, zone->journalsize);
11977                         switch (result) {
11978                         case ISC_R_SUCCESS:
11979                         case ISC_R_NOSPACE:
11980                         case ISC_R_NOTFOUND:
11981                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
11982                                              "dns_journal_compact: %s",
11983                                              dns_result_totext(result));
11984                                 break;
11985                         default:
11986                                 dns_zone_log(zone, ISC_LOG_ERROR,
11987                                              "dns_journal_compact failed: %s",
11988                                              dns_result_totext(result));
11989                                 break;
11990                         }
11991                 }
11992         } else {
11993                 if (dump && zone->masterfile != NULL) {
11994                         /*
11995                          * If DNS_ZONEFLG_FORCEXFER was set we don't want
11996                          * to keep the old masterfile.
11997                          */
11998                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
11999                             remove(zone->masterfile) < 0 && errno != ENOENT) {
12000                                 char strbuf[ISC_STRERRORSIZE];
12001                                 isc__strerror(errno, strbuf, sizeof(strbuf));
12002                                 isc_log_write(dns_lctx,
12003                                               DNS_LOGCATEGORY_GENERAL,
12004                                               DNS_LOGMODULE_ZONE,
12005                                               ISC_LOG_WARNING,
12006                                               "unable to remove masterfile "
12007                                               "'%s': '%s'",
12008                                               zone->masterfile, strbuf);
12009                         }
12010                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
12011                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
12012                         else
12013                                 zone_needdump(zone, 0);
12014                 }
12015                 if (dump && zone->journal != NULL) {
12016                         /*
12017                          * The in-memory database just changed, and
12018                          * because 'dump' is set, it didn't change by
12019                          * being loaded from disk.  Also, we have not
12020                          * journaled diffs for this change.
12021                          * Therefore, the on-disk journal is missing
12022                          * the deltas for this change.  Since it can
12023                          * no longer be used to bring the zone
12024                          * up-to-date, it is useless and should be
12025                          * removed.
12026                          */
12027                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
12028                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
12029                                       "removing journal file");
12030                         if (remove(zone->journal) < 0 && errno != ENOENT) {
12031                                 char strbuf[ISC_STRERRORSIZE];
12032                                 isc__strerror(errno, strbuf, sizeof(strbuf));
12033                                 isc_log_write(dns_lctx,
12034                                               DNS_LOGCATEGORY_GENERAL,
12035                                               DNS_LOGMODULE_ZONE,
12036                                               ISC_LOG_WARNING,
12037                                               "unable to remove journal "
12038                                               "'%s': '%s'",
12039                                               zone->journal, strbuf);
12040                         }
12041                 }
12042         }
12043
12044         dns_db_closeversion(db, &ver, ISC_FALSE);
12045
12046         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
12047                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
12048                       "replacing zone database");
12049
12050         if (zone->db != NULL)
12051                 zone_detachdb(zone);
12052         zone_attachdb(zone, db);
12053         dns_db_settask(zone->db, zone->task);
12054         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
12055         return (ISC_R_SUCCESS);
12056
12057  fail:
12058         dns_db_closeversion(db, &ver, ISC_FALSE);
12059         return (result);
12060 }
12061
12062 /* The caller must hold the dblock as a writer. */
12063 static inline void
12064 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
12065         REQUIRE(zone->db == NULL && db != NULL);
12066
12067         dns_db_attach(db, &zone->db);
12068         if (zone->acache != NULL) {
12069                 isc_result_t result;
12070                 result = dns_acache_setdb(zone->acache, db);
12071                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
12072                         UNEXPECTED_ERROR(__FILE__, __LINE__,
12073                                          "dns_acache_setdb() failed: %s",
12074                                          isc_result_totext(result));
12075                 }
12076         }
12077 }
12078
12079 /* The caller must hold the dblock as a writer. */
12080 static inline void
12081 zone_detachdb(dns_zone_t *zone) {
12082         REQUIRE(zone->db != NULL);
12083
12084         if (zone->acache != NULL)
12085                 (void)dns_acache_putdb(zone->acache, zone->db);
12086         dns_db_detach(&zone->db);
12087 }
12088
12089 static void
12090 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
12091         isc_time_t now;
12092         isc_boolean_t again = ISC_FALSE;
12093         unsigned int soacount;
12094         unsigned int nscount;
12095         isc_uint32_t serial, refresh, retry, expire, minimum;
12096         isc_result_t xfrresult = result;
12097         isc_boolean_t free_needed;
12098
12099         REQUIRE(DNS_ZONE_VALID(zone));
12100
12101         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12102                      "zone transfer finished: %s", dns_result_totext(result));
12103
12104         LOCK_ZONE(zone);
12105         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
12106         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12107         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
12108
12109         TIME_NOW(&now);
12110         switch (result) {
12111         case ISC_R_SUCCESS:
12112                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12113                 /*FALLTHROUGH*/
12114         case DNS_R_UPTODATE:
12115                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
12116                 /*
12117                  * Has the zone expired underneath us?
12118                  */
12119                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12120                 if (zone->db == NULL) {
12121                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12122                         goto same_master;
12123                 }
12124
12125                 /*
12126                  * Update the zone structure's data from the actual
12127                  * SOA received.
12128                  */
12129                 nscount = 0;
12130                 soacount = 0;
12131                 INSIST(zone->db != NULL);
12132                 result = zone_get_from_db(zone, zone->db, &nscount,
12133                                           &soacount, &serial, &refresh,
12134                                           &retry, &expire, &minimum, NULL);
12135                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12136                 if (result == ISC_R_SUCCESS) {
12137                         if (soacount != 1)
12138                                 dns_zone_log(zone, ISC_LOG_ERROR,
12139                                              "transferred zone "
12140                                              "has %d SOA record%s", soacount,
12141                                              (soacount != 0) ? "s" : "");
12142                         if (nscount == 0) {
12143                                 dns_zone_log(zone, ISC_LOG_ERROR,
12144                                              "transferred zone "
12145                                              "has no NS records");
12146                                 if (DNS_ZONE_FLAG(zone,
12147                                                   DNS_ZONEFLG_HAVETIMERS)) {
12148                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
12149                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
12150                                 }
12151                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
12152                                 zone_unload(zone);
12153                                 goto next_master;
12154                         }
12155                         zone->refresh = RANGE(refresh, zone->minrefresh,
12156                                               zone->maxrefresh);
12157                         zone->retry = RANGE(retry, zone->minretry,
12158                                             zone->maxretry);
12159                         zone->expire = RANGE(expire,
12160                                              zone->refresh + zone->retry,
12161                                              DNS_MAX_EXPIRE);
12162                         zone->minimum = minimum;
12163                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
12164                 }
12165
12166                 /*
12167                  * Set our next update/expire times.
12168                  */
12169                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
12170                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12171                         zone->refreshtime = now;
12172                         DNS_ZONE_TIME_ADD(&now, zone->expire,
12173                                           &zone->expiretime);
12174                 } else {
12175                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
12176                                             &zone->refreshtime);
12177                         DNS_ZONE_TIME_ADD(&now, zone->expire,
12178                                           &zone->expiretime);
12179                 }
12180                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
12181                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
12182                         if (zone->tsigkey != NULL) {
12183                                 char namebuf[DNS_NAME_FORMATSIZE];
12184                                 dns_name_format(&zone->tsigkey->name, namebuf,
12185                                                 sizeof(namebuf));
12186                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
12187                                          namebuf);
12188                         } else
12189                                 buf[0] = '\0';
12190                         dns_zone_log(zone, ISC_LOG_INFO,
12191                                      "transferred serial %u%s",
12192                                      serial, buf);
12193                 }
12194
12195                 /*
12196                  * This is not necessary if we just performed a AXFR
12197                  * however it is necessary for an IXFR / UPTODATE and
12198                  * won't hurt with an AXFR.
12199                  */
12200                 if (zone->masterfile != NULL || zone->journal != NULL) {
12201                         unsigned int delay = DNS_DUMP_DELAY;
12202
12203                         result = ISC_R_FAILURE;
12204                         if (zone->journal != NULL)
12205                                 result = isc_file_settime(zone->journal, &now);
12206                         if (result != ISC_R_SUCCESS &&
12207                             zone->masterfile != NULL)
12208                                 result = isc_file_settime(zone->masterfile,
12209                                                           &now);
12210
12211                         if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
12212                             result == ISC_R_FILENOTFOUND)
12213                                 delay = 0;
12214
12215                         if ((result == ISC_R_SUCCESS ||
12216                             result == ISC_R_FILENOTFOUND) &&
12217                             zone->masterfile != NULL)
12218                                 zone_needdump(zone, delay);
12219                         else if (result != ISC_R_SUCCESS)
12220                                 dns_zone_log(zone, ISC_LOG_ERROR,
12221                                              "transfer: could not set file "
12222                                              "modification time of '%s': %s",
12223                                              zone->masterfile,
12224                                              dns_result_totext(result));
12225                 }
12226                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
12227                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
12228                 break;
12229
12230         case DNS_R_BADIXFR:
12231                 /* Force retry with AXFR. */
12232                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
12233                 goto same_master;
12234
12235         default:
12236         next_master:
12237                 /*
12238                  * Skip to next failed / untried master.
12239                  */
12240                 do {
12241                         zone->curmaster++;
12242                 } while (zone->curmaster < zone->masterscnt &&
12243                          zone->mastersok[zone->curmaster]);
12244                 /* FALLTHROUGH */
12245         same_master:
12246                 if (zone->curmaster >= zone->masterscnt) {
12247                         zone->curmaster = 0;
12248                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
12249                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12250                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
12251                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12252                                 while (zone->curmaster < zone->masterscnt &&
12253                                        zone->mastersok[zone->curmaster])
12254                                         zone->curmaster++;
12255                                 again = ISC_TRUE;
12256                         } else
12257                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12258                 } else {
12259                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
12260                         again = ISC_TRUE;
12261                 }
12262                 inc_stats(zone, dns_zonestatscounter_xfrfail);
12263                 break;
12264         }
12265         zone_settimer(zone, &now);
12266
12267         /*
12268          * If creating the transfer object failed, zone->xfr is NULL.
12269          * Otherwise, we are called as the done callback of a zone
12270          * transfer object that just entered its shutting-down
12271          * state.  Since we are no longer responsible for shutting
12272          * it down, we can detach our reference.
12273          */
12274         if (zone->xfr != NULL)
12275                 dns_xfrin_detach(&zone->xfr);
12276
12277         if (zone->tsigkey != NULL)
12278                 dns_tsigkey_detach(&zone->tsigkey);
12279
12280         /*
12281          * Handle any deferred journal compaction.
12282          */
12283         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
12284                 result = dns_journal_compact(zone->mctx, zone->journal,
12285                                              zone->compact_serial,
12286                                              zone->journalsize);
12287                 switch (result) {
12288                 case ISC_R_SUCCESS:
12289                 case ISC_R_NOSPACE:
12290                 case ISC_R_NOTFOUND:
12291                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
12292                                      "dns_journal_compact: %s",
12293                                      dns_result_totext(result));
12294                         break;
12295                 default:
12296                         dns_zone_log(zone, ISC_LOG_ERROR,
12297                                      "dns_journal_compact failed: %s",
12298                                      dns_result_totext(result));
12299                         break;
12300                 }
12301                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
12302         }
12303
12304         /*
12305          * This transfer finishing freed up a transfer quota slot.
12306          * Let any other zones waiting for quota have it.
12307          */
12308         UNLOCK_ZONE(zone);
12309         RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12310         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
12311         zone->statelist = NULL;
12312         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
12313         RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12314         LOCK_ZONE(zone);
12315
12316         /*
12317          * Retry with a different server if necessary.
12318          */
12319         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12320                 queue_soa_query(zone);
12321
12322         INSIST(zone->irefs > 0);
12323         zone->irefs--;
12324         free_needed = exit_check(zone);
12325         UNLOCK_ZONE(zone);
12326         if (free_needed)
12327                 zone_free(zone);
12328 }
12329
12330 static void
12331 zone_loaddone(void *arg, isc_result_t result) {
12332         static char me[] = "zone_loaddone";
12333         dns_load_t *load = arg;
12334         dns_zone_t *zone;
12335         isc_result_t tresult;
12336
12337         REQUIRE(DNS_LOAD_VALID(load));
12338         zone = load->zone;
12339
12340         ENTER;
12341
12342         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
12343         if (tresult != ISC_R_SUCCESS &&
12344             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
12345                 result = tresult;
12346
12347         LOCK_ZONE(load->zone);
12348         (void)zone_postload(load->zone, load->db, load->loadtime, result);
12349         zonemgr_putio(&load->zone->readio);
12350         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
12351         /*
12352          * Leave the zone frozen if the reload fails.
12353          */
12354         if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
12355              DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW))
12356                 zone->update_disabled = ISC_FALSE;
12357         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW);
12358         UNLOCK_ZONE(load->zone);
12359
12360         load->magic = 0;
12361         dns_db_detach(&load->db);
12362         if (load->zone->lctx != NULL)
12363                 dns_loadctx_detach(&load->zone->lctx);
12364         dns_zone_idetach(&load->zone);
12365         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
12366 }
12367
12368 void
12369 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
12370         REQUIRE(DNS_ZONE_VALID(zone));
12371         REQUIRE(table != NULL);
12372         REQUIRE(*table == NULL);
12373
12374         LOCK_ZONE(zone);
12375         if (zone->ssutable != NULL)
12376                 dns_ssutable_attach(zone->ssutable, table);
12377         UNLOCK_ZONE(zone);
12378 }
12379
12380 void
12381 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
12382         REQUIRE(DNS_ZONE_VALID(zone));
12383
12384         LOCK_ZONE(zone);
12385         if (zone->ssutable != NULL)
12386                 dns_ssutable_detach(&zone->ssutable);
12387         if (table != NULL)
12388                 dns_ssutable_attach(table, &zone->ssutable);
12389         UNLOCK_ZONE(zone);
12390 }
12391
12392 void
12393 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
12394         REQUIRE(DNS_ZONE_VALID(zone));
12395
12396         zone->sigvalidityinterval = interval;
12397 }
12398
12399 isc_uint32_t
12400 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
12401         REQUIRE(DNS_ZONE_VALID(zone));
12402
12403         return (zone->sigvalidityinterval);
12404 }
12405
12406 void
12407 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
12408         isc_time_t now;
12409
12410         REQUIRE(DNS_ZONE_VALID(zone));
12411
12412         LOCK_ZONE(zone);
12413         zone->sigresigninginterval = interval;
12414         set_resigntime(zone);
12415         if (zone->task != NULL) {
12416                 TIME_NOW(&now);
12417                 zone_settimer(zone, &now);
12418         }
12419         UNLOCK_ZONE(zone);
12420 }
12421
12422 isc_uint32_t
12423 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
12424         REQUIRE(DNS_ZONE_VALID(zone));
12425
12426         return (zone->sigresigninginterval);
12427 }
12428
12429 static void
12430 queue_xfrin(dns_zone_t *zone) {
12431         const char me[] = "queue_xfrin";
12432         isc_result_t result;
12433         dns_zonemgr_t *zmgr = zone->zmgr;
12434
12435         ENTER;
12436
12437         INSIST(zone->statelist == NULL);
12438
12439         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12440         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
12441         LOCK_ZONE(zone);
12442         zone->irefs++;
12443         UNLOCK_ZONE(zone);
12444         zone->statelist = &zmgr->waiting_for_xfrin;
12445         result = zmgr_start_xfrin_ifquota(zmgr, zone);
12446         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12447
12448         if (result == ISC_R_QUOTA) {
12449                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
12450                               "zone transfer deferred due to quota");
12451         } else if (result != ISC_R_SUCCESS) {
12452                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
12453                               "starting zone transfer: %s",
12454                               isc_result_totext(result));
12455         }
12456 }
12457
12458 /*
12459  * This event callback is called when a zone has received
12460  * any necessary zone transfer quota.  This is the time
12461  * to go ahead and start the transfer.
12462  */
12463 static void
12464 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
12465         isc_result_t result;
12466         dns_peer_t *peer = NULL;
12467         char master[ISC_SOCKADDR_FORMATSIZE];
12468         char source[ISC_SOCKADDR_FORMATSIZE];
12469         dns_rdatatype_t xfrtype;
12470         dns_zone_t *zone = event->ev_arg;
12471         isc_netaddr_t masterip;
12472         isc_sockaddr_t sourceaddr;
12473         isc_sockaddr_t masteraddr;
12474         isc_time_t now;
12475         const char *soa_before = "";
12476
12477         UNUSED(task);
12478
12479         INSIST(task == zone->task);
12480
12481         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12482                 result = ISC_R_CANCELED;
12483                 goto cleanup;
12484         }
12485
12486         TIME_NOW(&now);
12487
12488         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12489         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
12490                                     &zone->sourceaddr, &now))
12491         {
12492                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12493                 dns_zone_log(zone, ISC_LOG_INFO,
12494                              "got_transfer_quota: skipping zone transfer as "
12495                              "master %s (source %s) is unreachable (cached)",
12496                              master, source);
12497                 result = ISC_R_CANCELED;
12498                 goto cleanup;
12499         }
12500
12501         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12502         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
12503
12504         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12505                 soa_before = "SOA before ";
12506         /*
12507          * Decide whether we should request IXFR or AXFR.
12508          */
12509         if (zone->db == NULL) {
12510                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12511                              "no database exists yet, requesting AXFR of "
12512                              "initial version from %s", master);
12513                 xfrtype = dns_rdatatype_axfr;
12514         } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
12515                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
12516                              "set, requesting %sAXFR from %s", soa_before,
12517                              master);
12518                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12519                         xfrtype = dns_rdatatype_soa;
12520                 else
12521                         xfrtype = dns_rdatatype_axfr;
12522         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
12523                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12524                              "forced reload, requesting AXFR of "
12525                              "initial version from %s", master);
12526                 xfrtype = dns_rdatatype_axfr;
12527         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
12528                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12529                              "retrying with AXFR from %s due to "
12530                              "previous IXFR failure", master);
12531                 xfrtype = dns_rdatatype_axfr;
12532                 LOCK_ZONE(zone);
12533                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
12534                 UNLOCK_ZONE(zone);
12535         } else {
12536                 isc_boolean_t use_ixfr = ISC_TRUE;
12537                 if (peer != NULL &&
12538                     dns_peer_getrequestixfr(peer, &use_ixfr) ==
12539                     ISC_R_SUCCESS) {
12540                         ; /* Using peer setting */
12541                 } else {
12542                         use_ixfr = zone->view->requestixfr;
12543                 }
12544                 if (use_ixfr == ISC_FALSE) {
12545                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12546                                      "IXFR disabled, requesting %sAXFR from %s",
12547                                      soa_before, master);
12548                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12549                                 xfrtype = dns_rdatatype_soa;
12550                         else
12551                                 xfrtype = dns_rdatatype_axfr;
12552                 } else {
12553                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12554                                      "requesting IXFR from %s", master);
12555                         xfrtype = dns_rdatatype_ixfr;
12556                 }
12557         }
12558
12559         /*
12560          * Determine if we should attempt to sign the request with TSIG.
12561          */
12562         result = ISC_R_NOTFOUND;
12563         /*
12564          * First, look for a tsig key in the master statement, then
12565          * try for a server key.
12566          */
12567         if ((zone->masterkeynames != NULL) &&
12568             (zone->masterkeynames[zone->curmaster] != NULL)) {
12569                 dns_view_t *view = dns_zone_getview(zone);
12570                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12571                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
12572         }
12573         if (zone->tsigkey == NULL)
12574                 result = dns_view_getpeertsig(zone->view, &masterip,
12575                                               &zone->tsigkey);
12576
12577         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12578                 dns_zone_log(zone, ISC_LOG_ERROR,
12579                              "could not get TSIG key for zone transfer: %s",
12580                              isc_result_totext(result));
12581         }
12582
12583         LOCK_ZONE(zone);
12584         masteraddr = zone->masteraddr;
12585         sourceaddr = zone->sourceaddr;
12586         UNLOCK_ZONE(zone);
12587         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
12588         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
12589                                    zone->tsigkey, zone->mctx,
12590                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
12591                                    zone->task, zone_xfrdone, &zone->xfr);
12592         if (result == ISC_R_SUCCESS) {
12593                 LOCK_ZONE(zone);
12594                 if (xfrtype == dns_rdatatype_axfr) {
12595                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12596                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
12597                         else
12598                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
12599                 } else if (xfrtype == dns_rdatatype_ixfr) {
12600                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12601                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
12602                         else
12603                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
12604                 }
12605                 UNLOCK_ZONE(zone);
12606         }
12607  cleanup:
12608         /*
12609          * Any failure in this function is handled like a failed
12610          * zone transfer.  This ensures that we get removed from
12611          * zmgr->xfrin_in_progress.
12612          */
12613         if (result != ISC_R_SUCCESS)
12614                 zone_xfrdone(zone, result);
12615
12616         isc_event_free(&event);
12617 }
12618
12619 /*
12620  * Update forwarding support.
12621  */
12622
12623 static void
12624 forward_destroy(dns_forward_t *forward) {
12625
12626         forward->magic = 0;
12627         if (forward->request != NULL)
12628                 dns_request_destroy(&forward->request);
12629         if (forward->msgbuf != NULL)
12630                 isc_buffer_free(&forward->msgbuf);
12631         if (forward->zone != NULL) {
12632                 LOCK(&forward->zone->lock);
12633                 if (ISC_LINK_LINKED(forward, link))
12634                         ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
12635                 UNLOCK(&forward->zone->lock);
12636                 dns_zone_idetach(&forward->zone);
12637         }
12638         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
12639 }
12640
12641 static isc_result_t
12642 sendtomaster(dns_forward_t *forward) {
12643         isc_result_t result;
12644         isc_sockaddr_t src;
12645
12646         LOCK_ZONE(forward->zone);
12647
12648         if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
12649                 UNLOCK_ZONE(forward->zone);
12650                 return (ISC_R_CANCELED);
12651         }
12652
12653         if (forward->which >= forward->zone->masterscnt) {
12654                 UNLOCK_ZONE(forward->zone);
12655                 return (ISC_R_NOMORE);
12656         }
12657
12658         forward->addr = forward->zone->masters[forward->which];
12659         /*
12660          * Always use TCP regardless of whether the original update
12661          * used TCP.
12662          * XXX The timeout may but a bit small if we are far down a
12663          * transfer graph and the master has to try several masters.
12664          */
12665         switch (isc_sockaddr_pf(&forward->addr)) {
12666         case PF_INET:
12667                 src = forward->zone->xfrsource4;
12668                 break;
12669         case PF_INET6:
12670                 src = forward->zone->xfrsource6;
12671                 break;
12672         default:
12673                 result = ISC_R_NOTIMPLEMENTED;
12674                 goto unlock;
12675         }
12676         result = dns_request_createraw(forward->zone->view->requestmgr,
12677                                        forward->msgbuf,
12678                                        &src, &forward->addr,
12679                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
12680                                        forward->zone->task,
12681                                        forward_callback, forward,
12682                                        &forward->request);
12683         if (result == ISC_R_SUCCESS) {
12684                 if (!ISC_LINK_LINKED(forward, link))
12685                         ISC_LIST_APPEND(forward->zone->forwards, forward, link);
12686         }
12687
12688  unlock:
12689         UNLOCK_ZONE(forward->zone);
12690         return (result);
12691 }
12692
12693 static void
12694 forward_callback(isc_task_t *task, isc_event_t *event) {
12695         const char me[] = "forward_callback";
12696         dns_requestevent_t *revent = (dns_requestevent_t *)event;
12697         dns_message_t *msg = NULL;
12698         char master[ISC_SOCKADDR_FORMATSIZE];
12699         isc_result_t result;
12700         dns_forward_t *forward;
12701         dns_zone_t *zone;
12702
12703         UNUSED(task);
12704
12705         forward = revent->ev_arg;
12706         INSIST(DNS_FORWARD_VALID(forward));
12707         zone = forward->zone;
12708         INSIST(DNS_ZONE_VALID(zone));
12709
12710         ENTER;
12711
12712         isc_sockaddr_format(&forward->addr, master, sizeof(master));
12713
12714         if (revent->result != ISC_R_SUCCESS) {
12715                 dns_zone_log(zone, ISC_LOG_INFO,
12716                              "could not forward dynamic update to %s: %s",
12717                              master, dns_result_totext(revent->result));
12718                 goto next_master;
12719         }
12720
12721         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12722         if (result != ISC_R_SUCCESS)
12723                 goto next_master;
12724
12725         result = dns_request_getresponse(revent->request, msg,
12726                                          DNS_MESSAGEPARSE_PRESERVEORDER |
12727                                          DNS_MESSAGEPARSE_CLONEBUFFER);
12728         if (result != ISC_R_SUCCESS)
12729                 goto next_master;
12730
12731         switch (msg->rcode) {
12732         /*
12733          * Pass these rcodes back to client.
12734          */
12735         case dns_rcode_noerror:
12736         case dns_rcode_yxdomain:
12737         case dns_rcode_yxrrset:
12738         case dns_rcode_nxrrset:
12739         case dns_rcode_refused:
12740         case dns_rcode_nxdomain: {
12741                 char rcode[128];
12742                 isc_buffer_t rb;
12743
12744                 isc_buffer_init(&rb, rcode, sizeof(rcode));
12745                 (void)dns_rcode_totext(msg->rcode, &rb);
12746                 dns_zone_log(zone, ISC_LOG_INFO,
12747                              "forwarded dynamic update: "
12748                              "master %s returned: %.*s",
12749                              master, (int)rb.used, rcode);
12750                 break;
12751         }
12752
12753         /* These should not occur if the masters/zone are valid. */
12754         case dns_rcode_notzone:
12755         case dns_rcode_notauth: {
12756                 char rcode[128];
12757                 isc_buffer_t rb;
12758
12759                 isc_buffer_init(&rb, rcode, sizeof(rcode));
12760                 (void)dns_rcode_totext(msg->rcode, &rb);
12761                 dns_zone_log(zone, ISC_LOG_WARNING,
12762                              "forwarding dynamic update: "
12763                              "unexpected response: master %s returned: %.*s",
12764                              master, (int)rb.used, rcode);
12765                 goto next_master;
12766         }
12767
12768         /* Try another server for these rcodes. */
12769         case dns_rcode_formerr:
12770         case dns_rcode_servfail:
12771         case dns_rcode_notimp:
12772         case dns_rcode_badvers:
12773         default:
12774                 goto next_master;
12775         }
12776
12777         /* call callback */
12778         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
12779         msg = NULL;
12780         dns_request_destroy(&forward->request);
12781         forward_destroy(forward);
12782         isc_event_free(&event);
12783         return;
12784
12785  next_master:
12786         if (msg != NULL)
12787                 dns_message_destroy(&msg);
12788         isc_event_free(&event);
12789         forward->which++;
12790         dns_request_destroy(&forward->request);
12791         result = sendtomaster(forward);
12792         if (result != ISC_R_SUCCESS) {
12793                 /* call callback */
12794                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
12795                              "exhausted dynamic update forwarder list");
12796                 (forward->callback)(forward->callback_arg, result, NULL);
12797                 forward_destroy(forward);
12798         }
12799 }
12800
12801 isc_result_t
12802 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
12803                        dns_updatecallback_t callback, void *callback_arg)
12804 {
12805         dns_forward_t *forward;
12806         isc_result_t result;
12807         isc_region_t *mr;
12808
12809         REQUIRE(DNS_ZONE_VALID(zone));
12810         REQUIRE(msg != NULL);
12811         REQUIRE(callback != NULL);
12812
12813         forward = isc_mem_get(zone->mctx, sizeof(*forward));
12814         if (forward == NULL)
12815                 return (ISC_R_NOMEMORY);
12816
12817         forward->request = NULL;
12818         forward->zone = NULL;
12819         forward->msgbuf = NULL;
12820         forward->which = 0;
12821         forward->mctx = 0;
12822         forward->callback = callback;
12823         forward->callback_arg = callback_arg;
12824         ISC_LINK_INIT(forward, link);
12825         forward->magic = FORWARD_MAGIC;
12826
12827         mr = dns_message_getrawmessage(msg);
12828         if (mr == NULL) {
12829                 result = ISC_R_UNEXPECTEDEND;
12830                 goto cleanup;
12831         }
12832
12833         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
12834         if (result != ISC_R_SUCCESS)
12835                 goto cleanup;
12836         result = isc_buffer_copyregion(forward->msgbuf, mr);
12837         if (result != ISC_R_SUCCESS)
12838                 goto cleanup;
12839
12840         isc_mem_attach(zone->mctx, &forward->mctx);
12841         dns_zone_iattach(zone, &forward->zone);
12842         result = sendtomaster(forward);
12843
12844  cleanup:
12845         if (result != ISC_R_SUCCESS) {
12846                 forward_destroy(forward);
12847         }
12848         return (result);
12849 }
12850
12851 isc_result_t
12852 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
12853         REQUIRE(DNS_ZONE_VALID(zone));
12854         REQUIRE(next != NULL && *next == NULL);
12855
12856         *next = ISC_LIST_NEXT(zone, link);
12857         if (*next == NULL)
12858                 return (ISC_R_NOMORE);
12859         else
12860                 return (ISC_R_SUCCESS);
12861 }
12862
12863 isc_result_t
12864 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
12865         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12866         REQUIRE(first != NULL && *first == NULL);
12867
12868         *first = ISC_LIST_HEAD(zmgr->zones);
12869         if (*first == NULL)
12870                 return (ISC_R_NOMORE);
12871         else
12872                 return (ISC_R_SUCCESS);
12873 }
12874
12875 /***
12876  ***    Zone manager.
12877  ***/
12878
12879 isc_result_t
12880 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
12881                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
12882                    dns_zonemgr_t **zmgrp)
12883 {
12884         dns_zonemgr_t *zmgr;
12885         isc_result_t result;
12886         isc_interval_t interval;
12887
12888         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
12889         if (zmgr == NULL)
12890                 return (ISC_R_NOMEMORY);
12891         zmgr->mctx = NULL;
12892         zmgr->refs = 1;
12893         isc_mem_attach(mctx, &zmgr->mctx);
12894         zmgr->taskmgr = taskmgr;
12895         zmgr->timermgr = timermgr;
12896         zmgr->socketmgr = socketmgr;
12897         zmgr->zonetasks = NULL;
12898         zmgr->task = NULL;
12899         zmgr->notifyrl = NULL;
12900         zmgr->refreshrl = NULL;
12901         ISC_LIST_INIT(zmgr->zones);
12902         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
12903         ISC_LIST_INIT(zmgr->xfrin_in_progress);
12904         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
12905         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
12906         if (result != ISC_R_SUCCESS)
12907                 goto free_mem;
12908
12909         zmgr->transfersin = 10;
12910         zmgr->transfersperns = 2;
12911
12912         /* Unreachable lock. */
12913         result = isc_rwlock_init(&zmgr->urlock, 0, 0);
12914         if (result != ISC_R_SUCCESS)
12915                 goto free_rwlock;
12916
12917         /* Create a single task for queueing of SOA queries. */
12918         result = isc_task_create(taskmgr, 1, &zmgr->task);
12919         if (result != ISC_R_SUCCESS)
12920                 goto free_urlock;
12921
12922         isc_task_setname(zmgr->task, "zmgr", zmgr);
12923         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
12924                                         &zmgr->notifyrl);
12925         if (result != ISC_R_SUCCESS)
12926                 goto free_task;
12927
12928         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
12929                                         &zmgr->refreshrl);
12930         if (result != ISC_R_SUCCESS)
12931                 goto free_notifyrl;
12932
12933         /* default to 20 refresh queries / notifies per second. */
12934         isc_interval_set(&interval, 0, 1000000000/2);
12935         result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
12936         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12937         isc_ratelimiter_setpertic(zmgr->notifyrl, 10);
12938
12939         result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
12940         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12941         isc_ratelimiter_setpertic(zmgr->refreshrl, 10);
12942
12943         zmgr->iolimit = 1;
12944         zmgr->ioactive = 0;
12945         ISC_LIST_INIT(zmgr->high);
12946         ISC_LIST_INIT(zmgr->low);
12947
12948         result = isc_mutex_init(&zmgr->iolock);
12949         if (result != ISC_R_SUCCESS)
12950                 goto free_refreshrl;
12951
12952         zmgr->magic = ZONEMGR_MAGIC;
12953
12954         *zmgrp = zmgr;
12955         return (ISC_R_SUCCESS);
12956
12957 #if 0
12958  free_iolock:
12959         DESTROYLOCK(&zmgr->iolock);
12960 #endif
12961  free_refreshrl:
12962         isc_ratelimiter_detach(&zmgr->refreshrl);
12963  free_notifyrl:
12964         isc_ratelimiter_detach(&zmgr->notifyrl);
12965  free_task:
12966         isc_task_detach(&zmgr->task);
12967  free_urlock:
12968         isc_rwlock_destroy(&zmgr->urlock);
12969  free_rwlock:
12970         isc_rwlock_destroy(&zmgr->rwlock);
12971  free_mem:
12972         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
12973         isc_mem_detach(&mctx);
12974         return (result);
12975 }
12976
12977 isc_result_t
12978 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12979         isc_result_t result;
12980
12981         REQUIRE(DNS_ZONE_VALID(zone));
12982         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12983
12984         if (zmgr->zonetasks == NULL)
12985                 return (ISC_R_FAILURE);
12986
12987         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12988         LOCK_ZONE(zone);
12989         REQUIRE(zone->task == NULL);
12990         REQUIRE(zone->timer == NULL);
12991         REQUIRE(zone->zmgr == NULL);
12992
12993         isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
12994
12995         /*
12996          * Set the task name.  The tag will arbitrarily point to one
12997          * of the zones sharing the task (in practice, the one
12998          * to be managed last).
12999          */
13000         isc_task_setname(zone->task, "zone", zone);
13001
13002         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
13003                                   NULL, NULL,
13004                                   zone->task, zone_timer, zone,
13005                                   &zone->timer);
13006
13007         if (result != ISC_R_SUCCESS)
13008                 goto cleanup_task;
13009
13010         /*
13011          * The timer "holds" a iref.
13012          */
13013         zone->irefs++;
13014         INSIST(zone->irefs != 0);
13015
13016         ISC_LIST_APPEND(zmgr->zones, zone, link);
13017         zone->zmgr = zmgr;
13018         zmgr->refs++;
13019
13020         goto unlock;
13021
13022  cleanup_task:
13023         isc_task_detach(&zone->task);
13024
13025  unlock:
13026         UNLOCK_ZONE(zone);
13027         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13028         return (result);
13029 }
13030
13031 void
13032 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
13033         isc_boolean_t free_now = ISC_FALSE;
13034
13035         REQUIRE(DNS_ZONE_VALID(zone));
13036         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13037         REQUIRE(zone->zmgr == zmgr);
13038
13039         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13040         LOCK_ZONE(zone);
13041
13042         ISC_LIST_UNLINK(zmgr->zones, zone, link);
13043         zone->zmgr = NULL;
13044         zmgr->refs--;
13045         if (zmgr->refs == 0)
13046                 free_now = ISC_TRUE;
13047
13048         UNLOCK_ZONE(zone);
13049         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13050
13051         if (free_now)
13052                 zonemgr_free(zmgr);
13053         ENSURE(zone->zmgr == NULL);
13054 }
13055
13056 void
13057 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
13058         REQUIRE(DNS_ZONEMGR_VALID(source));
13059         REQUIRE(target != NULL && *target == NULL);
13060
13061         RWLOCK(&source->rwlock, isc_rwlocktype_write);
13062         REQUIRE(source->refs > 0);
13063         source->refs++;
13064         INSIST(source->refs > 0);
13065         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
13066         *target = source;
13067 }
13068
13069 void
13070 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
13071         dns_zonemgr_t *zmgr;
13072         isc_boolean_t free_now = ISC_FALSE;
13073
13074         REQUIRE(zmgrp != NULL);
13075         zmgr = *zmgrp;
13076         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13077
13078         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13079         zmgr->refs--;
13080         if (zmgr->refs == 0)
13081                 free_now = ISC_TRUE;
13082         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13083
13084         if (free_now)
13085                 zonemgr_free(zmgr);
13086         *zmgrp = NULL;
13087 }
13088
13089 isc_result_t
13090 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
13091         dns_zone_t *p;
13092
13093         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13094
13095         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13096         for (p = ISC_LIST_HEAD(zmgr->zones);
13097              p != NULL;
13098              p = ISC_LIST_NEXT(p, link))
13099         {
13100                 dns_zone_maintenance(p);
13101         }
13102         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13103
13104         /*
13105          * Recent configuration changes may have increased the
13106          * amount of available transfers quota.  Make sure any
13107          * transfers currently blocked on quota get started if
13108          * possible.
13109          */
13110         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13111         zmgr_resume_xfrs(zmgr, ISC_TRUE);
13112         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13113         return (ISC_R_SUCCESS);
13114 }
13115
13116 void
13117 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
13118
13119         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13120
13121         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13122         zmgr_resume_xfrs(zmgr, ISC_TRUE);
13123         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13124 }
13125
13126 void
13127 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
13128         dns_zone_t *zone;
13129
13130         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13131
13132         isc_ratelimiter_shutdown(zmgr->notifyrl);
13133         isc_ratelimiter_shutdown(zmgr->refreshrl);
13134
13135         if (zmgr->task != NULL)
13136                 isc_task_destroy(&zmgr->task);
13137         if (zmgr->zonetasks != NULL)
13138                 isc_taskpool_destroy(&zmgr->zonetasks);
13139
13140         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13141         for (zone = ISC_LIST_HEAD(zmgr->zones);
13142              zone != NULL;
13143              zone = ISC_LIST_NEXT(zone, link))
13144         {
13145                 LOCK_ZONE(zone);
13146                 forward_cancel(zone);
13147                 UNLOCK_ZONE(zone);
13148         }
13149         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13150 }
13151
13152 isc_result_t
13153 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
13154         isc_result_t result;
13155         int ntasks = num_zones / 100;
13156         isc_taskpool_t *pool = NULL;
13157
13158         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13159
13160         /*
13161          * For anything fewer than 1000 zones we use 10 tasks in
13162          * the task pool.  More than that, and we'll scale at one
13163          * task per 100 zones.
13164          */
13165         if (ntasks < 10)
13166                 ntasks = 10;
13167
13168         /* Create or resize the zone task pool. */
13169         if (zmgr->zonetasks == NULL)
13170                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
13171                                              ntasks, 2, &pool);
13172         else
13173                 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
13174
13175         if (result == ISC_R_SUCCESS)
13176                 zmgr->zonetasks = pool;
13177
13178         return (result);
13179 }
13180
13181 static void
13182 zonemgr_free(dns_zonemgr_t *zmgr) {
13183         isc_mem_t *mctx;
13184
13185         INSIST(zmgr->refs == 0);
13186         INSIST(ISC_LIST_EMPTY(zmgr->zones));
13187
13188         zmgr->magic = 0;
13189
13190         DESTROYLOCK(&zmgr->iolock);
13191         isc_ratelimiter_detach(&zmgr->notifyrl);
13192         isc_ratelimiter_detach(&zmgr->refreshrl);
13193
13194         isc_rwlock_destroy(&zmgr->urlock);
13195         isc_rwlock_destroy(&zmgr->rwlock);
13196         mctx = zmgr->mctx;
13197         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
13198         isc_mem_detach(&mctx);
13199 }
13200
13201 void
13202 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
13203         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13204
13205         zmgr->transfersin = value;
13206 }
13207
13208 isc_uint32_t
13209 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
13210         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13211
13212         return (zmgr->transfersin);
13213 }
13214
13215 void
13216 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
13217         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13218
13219         zmgr->transfersperns = value;
13220 }
13221
13222 isc_uint32_t
13223 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
13224         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13225
13226         return (zmgr->transfersperns);
13227 }
13228
13229 /*
13230  * Try to start a new incoming zone transfer to fill a quota
13231  * slot that was just vacated.
13232  *
13233  * Requires:
13234  *      The zone manager is locked by the caller.
13235  */
13236 static void
13237 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
13238         dns_zone_t *zone;
13239         dns_zone_t *next;
13240
13241         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
13242              zone != NULL;
13243              zone = next)
13244         {
13245                 isc_result_t result;
13246                 next = ISC_LIST_NEXT(zone, statelink);
13247                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
13248                 if (result == ISC_R_SUCCESS) {
13249                         if (multi)
13250                                 continue;
13251                         /*
13252                          * We successfully filled the slot.  We're done.
13253                          */
13254                         break;
13255                 } else if (result == ISC_R_QUOTA) {
13256                         /*
13257                          * Not enough quota.  This is probably the per-server
13258                          * quota, because we usually get called when a unit of
13259                          * global quota has just been freed.  Try the next
13260                          * zone, it may succeed if it uses another master.
13261                          */
13262                         continue;
13263                 } else {
13264                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
13265                                      "starting zone transfer: %s",
13266                                      isc_result_totext(result));
13267                         break;
13268                 }
13269         }
13270 }
13271
13272 /*
13273  * Try to start an incoming zone transfer for 'zone', quota permitting.
13274  *
13275  * Requires:
13276  *      The zone manager is locked by the caller.
13277  *
13278  * Returns:
13279  *      ISC_R_SUCCESS   There was enough quota and we attempted to
13280  *                      start a transfer.  zone_xfrdone() has been or will
13281  *                      be called.
13282  *      ISC_R_QUOTA     Not enough quota.
13283  *      Others          Failure.
13284  */
13285 static isc_result_t
13286 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
13287         dns_peer_t *peer = NULL;
13288         isc_netaddr_t masterip;
13289         isc_uint32_t nxfrsin, nxfrsperns;
13290         dns_zone_t *x;
13291         isc_uint32_t maxtransfersin, maxtransfersperns;
13292         isc_event_t *e;
13293
13294         /*
13295          * If we are exiting just pretend we got quota so the zone will
13296          * be cleaned up in the zone's task context.
13297          */
13298         LOCK_ZONE(zone);
13299         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13300                 UNLOCK_ZONE(zone);
13301                 goto gotquota;
13302         }
13303
13304         /*
13305          * Find any configured information about the server we'd
13306          * like to transfer this zone from.
13307          */
13308         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
13309         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
13310         UNLOCK_ZONE(zone);
13311
13312         /*
13313          * Determine the total maximum number of simultaneous
13314          * transfers allowed, and the maximum for this specific
13315          * master.
13316          */
13317         maxtransfersin = zmgr->transfersin;
13318         maxtransfersperns = zmgr->transfersperns;
13319         if (peer != NULL)
13320                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
13321
13322         /*
13323          * Count the total number of transfers that are in progress,
13324          * and the number of transfers in progress from this master.
13325          * We linearly scan a list of all transfers; if this turns
13326          * out to be too slow, we could hash on the master address.
13327          */
13328         nxfrsin = nxfrsperns = 0;
13329         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
13330              x != NULL;
13331              x = ISC_LIST_NEXT(x, statelink))
13332         {
13333                 isc_netaddr_t xip;
13334
13335                 LOCK_ZONE(x);
13336                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
13337                 UNLOCK_ZONE(x);
13338
13339                 nxfrsin++;
13340                 if (isc_netaddr_equal(&xip, &masterip))
13341                         nxfrsperns++;
13342         }
13343
13344         /* Enforce quota. */
13345         if (nxfrsin >= maxtransfersin)
13346                 return (ISC_R_QUOTA);
13347
13348         if (nxfrsperns >= maxtransfersperns)
13349                 return (ISC_R_QUOTA);
13350
13351  gotquota:
13352         /*
13353          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
13354          * list and send it an event to let it start the actual transfer in the
13355          * context of its own task.
13356          */
13357         e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
13358                                got_transfer_quota, zone, sizeof(isc_event_t));
13359         if (e == NULL)
13360                 return (ISC_R_NOMEMORY);
13361
13362         LOCK_ZONE(zone);
13363         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
13364         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
13365         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
13366         zone->statelist = &zmgr->xfrin_in_progress;
13367         isc_task_send(zone->task, &e);
13368         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
13369         UNLOCK_ZONE(zone);
13370
13371         return (ISC_R_SUCCESS);
13372 }
13373
13374 void
13375 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
13376
13377         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13378         REQUIRE(iolimit > 0);
13379
13380         zmgr->iolimit = iolimit;
13381 }
13382
13383 isc_uint32_t
13384 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
13385
13386         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13387
13388         return (zmgr->iolimit);
13389 }
13390
13391 /*
13392  * Get permission to request a file handle from the OS.
13393  * An event will be sent to action when one is available.
13394  * There are two queues available (high and low), the high
13395  * queue will be serviced before the low one.
13396  *
13397  * zonemgr_putio() must be called after the event is delivered to
13398  * 'action'.
13399  */
13400
13401 static isc_result_t
13402 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
13403               isc_task_t *task, isc_taskaction_t action, void *arg,
13404               dns_io_t **iop)
13405 {
13406         dns_io_t *io;
13407         isc_boolean_t queue;
13408
13409         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13410         REQUIRE(iop != NULL && *iop == NULL);
13411
13412         io = isc_mem_get(zmgr->mctx, sizeof(*io));
13413         if (io == NULL)
13414                 return (ISC_R_NOMEMORY);
13415         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
13416                                        action, arg, sizeof(*io->event));
13417         if (io->event == NULL) {
13418                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
13419                 return (ISC_R_NOMEMORY);
13420         }
13421         io->zmgr = zmgr;
13422         io->high = high;
13423         io->task = NULL;
13424         isc_task_attach(task, &io->task);
13425         ISC_LINK_INIT(io, link);
13426         io->magic = IO_MAGIC;
13427
13428         LOCK(&zmgr->iolock);
13429         zmgr->ioactive++;
13430         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
13431         if (queue) {
13432                 if (io->high)
13433                         ISC_LIST_APPEND(zmgr->high, io, link);
13434                 else
13435                         ISC_LIST_APPEND(zmgr->low, io, link);
13436         }
13437         UNLOCK(&zmgr->iolock);
13438         *iop = io;
13439
13440         if (!queue) {
13441                 isc_task_send(io->task, &io->event);
13442         }
13443         return (ISC_R_SUCCESS);
13444 }
13445
13446 static void
13447 zonemgr_putio(dns_io_t **iop) {
13448         dns_io_t *io;
13449         dns_io_t *next;
13450         dns_zonemgr_t *zmgr;
13451
13452         REQUIRE(iop != NULL);
13453         io = *iop;
13454         REQUIRE(DNS_IO_VALID(io));
13455
13456         *iop = NULL;
13457
13458         INSIST(!ISC_LINK_LINKED(io, link));
13459         INSIST(io->event == NULL);
13460
13461         zmgr = io->zmgr;
13462         isc_task_detach(&io->task);
13463         io->magic = 0;
13464         isc_mem_put(zmgr->mctx, io, sizeof(*io));
13465
13466         LOCK(&zmgr->iolock);
13467         INSIST(zmgr->ioactive > 0);
13468         zmgr->ioactive--;
13469         next = HEAD(zmgr->high);
13470         if (next == NULL)
13471                 next = HEAD(zmgr->low);
13472         if (next != NULL) {
13473                 if (next->high)
13474                         ISC_LIST_UNLINK(zmgr->high, next, link);
13475                 else
13476                         ISC_LIST_UNLINK(zmgr->low, next, link);
13477                 INSIST(next->event != NULL);
13478         }
13479         UNLOCK(&zmgr->iolock);
13480         if (next != NULL)
13481                 isc_task_send(next->task, &next->event);
13482 }
13483
13484 static void
13485 zonemgr_cancelio(dns_io_t *io) {
13486         isc_boolean_t send_event = ISC_FALSE;
13487
13488         REQUIRE(DNS_IO_VALID(io));
13489
13490         /*
13491          * If we are queued to be run then dequeue.
13492          */
13493         LOCK(&io->zmgr->iolock);
13494         if (ISC_LINK_LINKED(io, link)) {
13495                 if (io->high)
13496                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
13497                 else
13498                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
13499
13500                 send_event = ISC_TRUE;
13501                 INSIST(io->event != NULL);
13502         }
13503         UNLOCK(&io->zmgr->iolock);
13504         if (send_event) {
13505                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
13506                 isc_task_send(io->task, &io->event);
13507         }
13508 }
13509
13510 static void
13511 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
13512         char *buf;
13513         int buflen;
13514         isc_result_t result;
13515
13516         buflen = strlen(path) + strlen(templat) + 2;
13517
13518         buf = isc_mem_get(zone->mctx, buflen);
13519         if (buf == NULL)
13520                 return;
13521
13522         result = isc_file_template(path, templat, buf, buflen);
13523         if (result != ISC_R_SUCCESS)
13524                 goto cleanup;
13525
13526         result = isc_file_renameunique(path, buf);
13527         if (result != ISC_R_SUCCESS)
13528                 goto cleanup;
13529
13530         dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
13531                      "renaming file to '%s' for failure analysis and "
13532                      "retransferring.", path, buf);
13533
13534  cleanup:
13535         isc_mem_put(zone->mctx, buf, buflen);
13536 }
13537
13538 #if 0
13539 /* Hook for ondestroy notification from a database. */
13540
13541 static void
13542 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
13543         dns_db_t *db = event->sender;
13544         UNUSED(task);
13545
13546         isc_event_free(&event);
13547
13548         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13549                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13550                       "database (%p) destroyed", (void*) db);
13551 }
13552 #endif
13553
13554 void
13555 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
13556         isc_interval_t interval;
13557         isc_uint32_t s, ns;
13558         isc_uint32_t pertic;
13559         isc_result_t result;
13560
13561         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13562
13563         if (value == 0)
13564                 value = 1;
13565
13566         if (value == 1) {
13567                 s = 1;
13568                 ns = 0;
13569                 pertic = 1;
13570         } else if (value <= 10) {
13571                 s = 0;
13572                 ns = 1000000000 / value;
13573                 pertic = 1;
13574         } else {
13575                 s = 0;
13576                 ns = (1000000000 / value) * 10;
13577                 pertic = 10;
13578         }
13579
13580         isc_interval_set(&interval, s, ns);
13581
13582         result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
13583         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13584         isc_ratelimiter_setpertic(zmgr->notifyrl, pertic);
13585
13586         result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
13587         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13588         isc_ratelimiter_setpertic(zmgr->refreshrl, pertic);
13589
13590         zmgr->serialqueryrate = value;
13591 }
13592
13593 unsigned int
13594 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
13595         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13596
13597         return (zmgr->serialqueryrate);
13598 }
13599
13600 isc_boolean_t
13601 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13602                         isc_sockaddr_t *local, isc_time_t *now)
13603 {
13604         unsigned int i;
13605         isc_rwlocktype_t locktype;
13606         isc_result_t result;
13607         isc_uint32_t seconds = isc_time_seconds(now);
13608         isc_uint32_t count = 0;
13609
13610         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13611
13612         locktype = isc_rwlocktype_read;
13613         RWLOCK(&zmgr->urlock, locktype);
13614         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13615                 if (zmgr->unreachable[i].expire >= seconds &&
13616                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13617                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
13618                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
13619                         if (result == ISC_R_SUCCESS) {
13620                                 locktype = isc_rwlocktype_write;
13621                                 zmgr->unreachable[i].last = seconds;
13622                                 count = zmgr->unreachable[i].count;
13623                         }
13624                         break;
13625                 }
13626         }
13627         RWUNLOCK(&zmgr->urlock, locktype);
13628         return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
13629 }
13630
13631 void
13632 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13633                            isc_sockaddr_t *local)
13634 {
13635         unsigned int i;
13636         isc_rwlocktype_t locktype;
13637         isc_result_t result;
13638
13639         char master[ISC_SOCKADDR_FORMATSIZE];
13640         char source[ISC_SOCKADDR_FORMATSIZE];
13641
13642         isc_sockaddr_format(remote, master, sizeof(master));
13643         isc_sockaddr_format(local, source, sizeof(source));
13644
13645         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13646
13647         locktype = isc_rwlocktype_read;
13648         RWLOCK(&zmgr->urlock, locktype);
13649         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13650                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13651                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
13652                         if (zmgr->unreachable[i].expire == 0)
13653                                 break;
13654                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
13655                         if (result == ISC_R_SUCCESS) {
13656                                 locktype = isc_rwlocktype_write;
13657                                 zmgr->unreachable[i].expire = 0;
13658                                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13659                                               DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
13660                                               "master %s (source %s) deleted "
13661                                               "from unreachable cache",
13662                                               master, source);
13663                         }
13664                         break;
13665                 }
13666         }
13667         RWUNLOCK(&zmgr->urlock, locktype);
13668 }
13669
13670 void
13671 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13672                            isc_sockaddr_t *local, isc_time_t *now)
13673 {
13674         isc_uint32_t seconds = isc_time_seconds(now);
13675         isc_uint32_t last = seconds;
13676         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
13677
13678         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13679
13680         RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
13681         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13682                 /* Existing entry? */
13683                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13684                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
13685                         break;
13686                 /* Empty slot? */
13687                 if (zmgr->unreachable[i].expire < seconds)
13688                         slot = i;
13689                 /* Least recently used slot? */
13690                 if (zmgr->unreachable[i].last < last) {
13691                         last = zmgr->unreachable[i].last;
13692                         oldest = i;
13693                 }
13694         }
13695         if (i < UNREACH_CHACHE_SIZE) {
13696                 /*
13697                  * Found a existing entry.  Update the expire timer and
13698                  * last usage timestamps.
13699                  */
13700                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
13701                 zmgr->unreachable[i].last = seconds;
13702                 if (zmgr->unreachable[i].expire < seconds)
13703                         zmgr->unreachable[i].count = 1;
13704                 else
13705                         zmgr->unreachable[i].count++;
13706         } else if (slot != UNREACH_CHACHE_SIZE) {
13707                 /*
13708                  * Found a empty slot. Add a new entry to the cache.
13709                  */
13710                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
13711                 zmgr->unreachable[slot].last = seconds;
13712                 zmgr->unreachable[slot].remote = *remote;
13713                 zmgr->unreachable[slot].local = *local;
13714                 zmgr->unreachable[slot].count = 1;
13715         } else {
13716                 /*
13717                  * Replace the least recently used entry in the cache.
13718                  */
13719                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
13720                 zmgr->unreachable[oldest].last = seconds;
13721                 zmgr->unreachable[oldest].remote = *remote;
13722                 zmgr->unreachable[oldest].local = *local;
13723                 zmgr->unreachable[oldest].count = 1;
13724         }
13725         RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
13726 }
13727
13728 void
13729 dns_zone_forcereload(dns_zone_t *zone) {
13730         REQUIRE(DNS_ZONE_VALID(zone));
13731
13732         if (zone->type == dns_zone_master)
13733                 return;
13734
13735         LOCK_ZONE(zone);
13736         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13737         UNLOCK_ZONE(zone);
13738         dns_zone_refresh(zone);
13739 }
13740
13741 isc_boolean_t
13742 dns_zone_isforced(dns_zone_t *zone) {
13743         REQUIRE(DNS_ZONE_VALID(zone));
13744
13745         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
13746 }
13747
13748 isc_result_t
13749 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
13750         /*
13751          * This function is obsoleted.
13752          */
13753         UNUSED(zone);
13754         UNUSED(on);
13755         return (ISC_R_NOTIMPLEMENTED);
13756 }
13757
13758 isc_uint64_t *
13759 dns_zone_getstatscounters(dns_zone_t *zone) {
13760         /*
13761          * This function is obsoleted.
13762          */
13763         UNUSED(zone);
13764         return (NULL);
13765 }
13766
13767 void
13768 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
13769         REQUIRE(DNS_ZONE_VALID(zone));
13770         REQUIRE(zone->stats == NULL);
13771
13772         LOCK_ZONE(zone);
13773         zone->stats = NULL;
13774         isc_stats_attach(stats, &zone->stats);
13775         UNLOCK_ZONE(zone);
13776 }
13777
13778 void
13779 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
13780         REQUIRE(DNS_ZONE_VALID(zone));
13781
13782         LOCK_ZONE(zone);
13783         if (zone->requeststats_on && stats == NULL)
13784                 zone->requeststats_on = ISC_FALSE;
13785         else if (!zone->requeststats_on && stats != NULL) {
13786                 if (zone->requeststats == NULL) {
13787                         isc_stats_attach(stats, &zone->requeststats);
13788                         zone->requeststats_on = ISC_TRUE;
13789                 }
13790         }
13791         UNLOCK_ZONE(zone);
13792
13793         return;
13794 }
13795
13796 isc_stats_t *
13797 dns_zone_getrequeststats(dns_zone_t *zone) {
13798         /*
13799          * We don't lock zone for efficiency reason.  This is not catastrophic
13800          * because requeststats must always be valid when requeststats_on is
13801          * true.
13802          * Some counters may be incremented while requeststats_on is becoming
13803          * false, or some cannot be incremented just after the statistics are
13804          * installed, but it shouldn't matter much in practice.
13805          */
13806         if (zone->requeststats_on)
13807                 return (zone->requeststats);
13808         else
13809                 return (NULL);
13810 }
13811
13812 void
13813 dns_zone_dialup(dns_zone_t *zone) {
13814
13815         REQUIRE(DNS_ZONE_VALID(zone));
13816
13817         zone_debuglog(zone, "dns_zone_dialup", 3,
13818                       "notify = %d, refresh = %d",
13819                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
13820                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
13821
13822         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
13823                 dns_zone_notify(zone);
13824         if (zone->type != dns_zone_master &&
13825             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
13826                 dns_zone_refresh(zone);
13827 }
13828
13829 void
13830 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
13831         REQUIRE(DNS_ZONE_VALID(zone));
13832
13833         LOCK_ZONE(zone);
13834         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
13835                          DNS_ZONEFLG_DIALREFRESH |
13836                          DNS_ZONEFLG_NOREFRESH);
13837         switch (dialup) {
13838         case dns_dialuptype_no:
13839                 break;
13840         case dns_dialuptype_yes:
13841                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
13842                                  DNS_ZONEFLG_DIALREFRESH |
13843                                  DNS_ZONEFLG_NOREFRESH));
13844                 break;
13845         case dns_dialuptype_notify:
13846                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13847                 break;
13848         case dns_dialuptype_notifypassive:
13849                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13850                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13851                 break;
13852         case dns_dialuptype_refresh:
13853                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
13854                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13855                 break;
13856         case dns_dialuptype_passive:
13857                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13858                 break;
13859         default:
13860                 INSIST(0);
13861         }
13862         UNLOCK_ZONE(zone);
13863 }
13864
13865 isc_result_t
13866 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
13867         isc_result_t result = ISC_R_SUCCESS;
13868
13869         REQUIRE(DNS_ZONE_VALID(zone));
13870
13871         LOCK_ZONE(zone);
13872         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
13873         UNLOCK_ZONE(zone);
13874
13875         return (result);
13876 }
13877
13878 const char *
13879 dns_zone_getkeydirectory(dns_zone_t *zone) {
13880         REQUIRE(DNS_ZONE_VALID(zone));
13881
13882         return (zone->keydirectory);
13883 }
13884
13885 unsigned int
13886 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
13887         dns_zone_t *zone;
13888         unsigned int count = 0;
13889
13890         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13891
13892         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13893         switch (state) {
13894         case DNS_ZONESTATE_XFERRUNNING:
13895                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
13896                      zone != NULL;
13897                      zone = ISC_LIST_NEXT(zone, statelink))
13898                         count++;
13899                 break;
13900         case DNS_ZONESTATE_XFERDEFERRED:
13901                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
13902                      zone != NULL;
13903                      zone = ISC_LIST_NEXT(zone, statelink))
13904                         count++;
13905                 break;
13906         case DNS_ZONESTATE_SOAQUERY:
13907                 for (zone = ISC_LIST_HEAD(zmgr->zones);
13908                      zone != NULL;
13909                      zone = ISC_LIST_NEXT(zone, link))
13910                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
13911                                 count++;
13912                 break;
13913         case DNS_ZONESTATE_ANY:
13914                 for (zone = ISC_LIST_HEAD(zmgr->zones);
13915                      zone != NULL;
13916                      zone = ISC_LIST_NEXT(zone, link)) {
13917                         dns_view_t *view = zone->view;
13918                         if (view != NULL && strcmp(view->name, "_bind") == 0)
13919                                 continue;
13920                         count++;
13921                 }
13922                 break;
13923         default:
13924                 INSIST(0);
13925         }
13926
13927         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13928
13929         return (count);
13930 }
13931
13932 isc_result_t
13933 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
13934         isc_boolean_t ok = ISC_TRUE;
13935         isc_boolean_t fail = ISC_FALSE;
13936         char namebuf[DNS_NAME_FORMATSIZE];
13937         char namebuf2[DNS_NAME_FORMATSIZE];
13938         char typebuf[DNS_RDATATYPE_FORMATSIZE];
13939         int level = ISC_LOG_WARNING;
13940         dns_name_t bad;
13941
13942         REQUIRE(DNS_ZONE_VALID(zone));
13943
13944         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
13945                 return (ISC_R_SUCCESS);
13946
13947         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
13948                 level = ISC_LOG_ERROR;
13949                 fail = ISC_TRUE;
13950         }
13951
13952         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
13953         if (!ok) {
13954                 dns_name_format(name, namebuf, sizeof(namebuf));
13955                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13956                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
13957                              dns_result_totext(DNS_R_BADOWNERNAME));
13958                 if (fail)
13959                         return (DNS_R_BADOWNERNAME);
13960         }
13961
13962         dns_name_init(&bad, NULL);
13963         ok = dns_rdata_checknames(rdata, name, &bad);
13964         if (!ok) {
13965                 dns_name_format(name, namebuf, sizeof(namebuf));
13966                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
13967                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13968                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
13969                              namebuf2, dns_result_totext(DNS_R_BADNAME));
13970                 if (fail)
13971                         return (DNS_R_BADNAME);
13972         }
13973
13974         return (ISC_R_SUCCESS);
13975 }
13976
13977 void
13978 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
13979         REQUIRE(DNS_ZONE_VALID(zone));
13980         zone->checkmx = checkmx;
13981 }
13982
13983 void
13984 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
13985         REQUIRE(DNS_ZONE_VALID(zone));
13986         zone->checksrv = checksrv;
13987 }
13988
13989 void
13990 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
13991         REQUIRE(DNS_ZONE_VALID(zone));
13992         zone->checkns = checkns;
13993 }
13994
13995 void
13996 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
13997         REQUIRE(DNS_ZONE_VALID(zone));
13998
13999         LOCK_ZONE(zone);
14000         zone->isself = isself;
14001         zone->isselfarg = arg;
14002         UNLOCK_ZONE(zone);
14003 }
14004
14005 void
14006 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
14007         REQUIRE(DNS_ZONE_VALID(zone));
14008
14009         LOCK_ZONE(zone);
14010         zone->notifydelay = delay;
14011         UNLOCK_ZONE(zone);
14012 }
14013
14014 isc_uint32_t
14015 dns_zone_getnotifydelay(dns_zone_t *zone) {
14016         REQUIRE(DNS_ZONE_VALID(zone));
14017
14018         return (zone->notifydelay);
14019 }
14020
14021 isc_result_t
14022 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
14023                      isc_uint16_t keyid, isc_boolean_t delete)
14024 {
14025         isc_result_t result;
14026         REQUIRE(DNS_ZONE_VALID(zone));
14027
14028         dns_zone_log(zone, ISC_LOG_NOTICE,
14029                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
14030                      algorithm, keyid);
14031         LOCK_ZONE(zone);
14032         result = zone_signwithkey(zone, algorithm, keyid, delete);
14033         UNLOCK_ZONE(zone);
14034
14035         return (result);
14036 }
14037
14038 static const char *hex = "0123456789ABCDEF";
14039
14040 isc_result_t
14041 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
14042         isc_result_t result;
14043         char salt[255*2+1];
14044         unsigned int i, j;
14045
14046         REQUIRE(DNS_ZONE_VALID(zone));
14047
14048         if (nsec3param->salt_length != 0) {
14049                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
14050                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
14051                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
14052                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
14053                 }
14054                 salt[j] = '\0';
14055         } else
14056                 strcpy(salt, "-");
14057         dns_zone_log(zone, ISC_LOG_NOTICE,
14058                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
14059                      nsec3param->hash, nsec3param->iterations,
14060                      salt);
14061         LOCK_ZONE(zone);
14062         result = zone_addnsec3chain(zone, nsec3param);
14063         UNLOCK_ZONE(zone);
14064
14065         return (result);
14066 }
14067
14068 void
14069 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
14070         REQUIRE(DNS_ZONE_VALID(zone));
14071
14072         if (nodes == 0)
14073                 nodes = 1;
14074         zone->nodes = nodes;
14075 }
14076
14077 void
14078 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
14079         REQUIRE(DNS_ZONE_VALID(zone));
14080
14081         /*
14082          * We treat signatures as a signed value so explicitly
14083          * limit its range here.
14084          */
14085         if (signatures > ISC_INT32_MAX)
14086                 signatures = ISC_INT32_MAX;
14087         else if (signatures == 0)
14088                 signatures = 1;
14089         zone->signatures = signatures;
14090 }
14091
14092 void
14093 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
14094         REQUIRE(DNS_ZONE_VALID(zone));
14095         zone->privatetype = type;
14096 }
14097
14098 dns_rdatatype_t
14099 dns_zone_getprivatetype(dns_zone_t *zone) {
14100         REQUIRE(DNS_ZONE_VALID(zone));
14101         return (zone->privatetype);
14102 }
14103
14104 static isc_result_t
14105 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
14106                  isc_boolean_t delete)
14107 {
14108         dns_signing_t *signing;
14109         dns_signing_t *current;
14110         isc_result_t result = ISC_R_SUCCESS;
14111         isc_time_t now;
14112
14113         signing = isc_mem_get(zone->mctx, sizeof *signing);
14114         if (signing == NULL)
14115                 return (ISC_R_NOMEMORY);
14116
14117         signing->magic = 0;
14118         signing->db  = NULL;
14119         signing->dbiterator = NULL;
14120         signing->algorithm = algorithm;
14121         signing->keyid = keyid;
14122         signing->delete = delete;
14123         signing->done = ISC_FALSE;
14124
14125         TIME_NOW(&now);
14126
14127         for (current = ISC_LIST_HEAD(zone->signing);
14128              current != NULL;
14129              current = ISC_LIST_NEXT(current, link)) {
14130                 if (current->db == zone->db &&
14131                     current->algorithm == signing->algorithm &&
14132                     current->keyid == signing->keyid) {
14133                         if (current->delete != signing->delete)
14134                                 current->done = ISC_TRUE;
14135                         else
14136                                 goto cleanup;
14137                 }
14138         }
14139
14140         if (zone->db != NULL) {
14141                 dns_db_attach(zone->db, &signing->db);
14142                 result = dns_db_createiterator(signing->db, 0,
14143                                                &signing->dbiterator);
14144
14145                 if (result == ISC_R_SUCCESS)
14146                         result = dns_dbiterator_first(signing->dbiterator);
14147                 if (result == ISC_R_SUCCESS) {
14148                         dns_dbiterator_pause(signing->dbiterator);
14149                         ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
14150                         signing = NULL;
14151                         if (isc_time_isepoch(&zone->signingtime)) {
14152                                 zone->signingtime = now;
14153                                 if (zone->task != NULL)
14154                                         zone_settimer(zone, &now);
14155                         }
14156                 }
14157         } else
14158                 result = ISC_R_NOTFOUND;
14159
14160  cleanup:
14161         if (signing != NULL) {
14162                 if (signing->db != NULL)
14163                         dns_db_detach(&signing->db);
14164                 if (signing->dbiterator != NULL)
14165                         dns_dbiterator_destroy(&signing->dbiterator);
14166                 isc_mem_put(zone->mctx, signing, sizeof *signing);
14167         }
14168         return (result);
14169 }
14170
14171 static void
14172 logmsg(const char *format, ...) {
14173         va_list args;
14174         va_start(args, format);
14175         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
14176                        ISC_LOG_DEBUG(1), format, args);
14177         va_end(args);
14178 }
14179
14180 static void
14181 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
14182         dns_dnsseckey_t *key;
14183         while (!ISC_LIST_EMPTY(*list)) {
14184                 key = ISC_LIST_HEAD(*list);
14185                 ISC_LIST_UNLINK(*list, key, link);
14186                 dns_dnsseckey_destroy(mctx, &key);
14187         }
14188 }
14189
14190 /* Called once; *timep should be set to the current time. */
14191 static isc_result_t
14192 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
14193         isc_result_t result;
14194         isc_stdtime_t now, then = 0, event;
14195         int i;
14196
14197         now = *timep;
14198
14199         for (i = 0; i <= DST_MAX_TIMES; i++) {
14200                 result = dst_key_gettime(key, i, &event);
14201                 if (result == ISC_R_SUCCESS && event > now &&
14202                     (then == 0 || event < then))
14203                         then = event;
14204         }
14205
14206         if (then != 0) {
14207                 *timep = then;
14208                 return (ISC_R_SUCCESS);
14209         }
14210
14211         return (ISC_R_NOTFOUND);
14212 }
14213
14214 static isc_result_t
14215 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
14216           const dns_rdata_t *rdata, isc_boolean_t *flag)
14217 {
14218         dns_rdataset_t rdataset;
14219         dns_dbnode_t *node = NULL;
14220         isc_result_t result;
14221
14222         dns_rdataset_init(&rdataset);
14223         if (rdata->type == dns_rdatatype_nsec3)
14224                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
14225         else
14226                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
14227         result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
14228                                      (isc_stdtime_t) 0, &rdataset, NULL);
14229         if (result == ISC_R_NOTFOUND) {
14230                 *flag = ISC_FALSE;
14231                 result = ISC_R_SUCCESS;
14232                 goto failure;
14233         }
14234
14235         for (result = dns_rdataset_first(&rdataset);
14236              result == ISC_R_SUCCESS;
14237              result = dns_rdataset_next(&rdataset)) {
14238                 dns_rdata_t myrdata = DNS_RDATA_INIT;
14239                 dns_rdataset_current(&rdataset, &myrdata);
14240                 if (!dns_rdata_compare(&myrdata, rdata))
14241                         break;
14242         }
14243         dns_rdataset_disassociate(&rdataset);
14244         if (result == ISC_R_SUCCESS) {
14245                 *flag = ISC_TRUE;
14246         } else if (result == ISC_R_NOMORE) {
14247                 *flag = ISC_FALSE;
14248                 result = ISC_R_SUCCESS;
14249         }
14250
14251  failure:
14252         if (node != NULL)
14253                 dns_db_detachnode(db, &node);
14254         return (result);
14255 }
14256
14257 /*
14258  * Add records to signal the state of signing or of key removal.
14259  */
14260 static isc_result_t
14261 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
14262                     dns_dbversion_t *ver, dns_diff_t *diff,
14263                     isc_boolean_t sign_all)
14264 {
14265         dns_difftuple_t *tuple, *newtuple = NULL;
14266         dns_rdata_dnskey_t dnskey;
14267         dns_rdata_t rdata = DNS_RDATA_INIT;
14268         isc_boolean_t flag;
14269         isc_region_t r;
14270         isc_result_t result = ISC_R_SUCCESS;
14271         isc_uint16_t keyid;
14272         unsigned char buf[5];
14273         dns_name_t *name = dns_db_origin(db);
14274
14275         for (tuple = ISC_LIST_HEAD(diff->tuples);
14276              tuple != NULL;
14277              tuple = ISC_LIST_NEXT(tuple, link)) {
14278                 if (tuple->rdata.type != dns_rdatatype_dnskey)
14279                         continue;
14280
14281                 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
14282                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14283                 if ((dnskey.flags &
14284                      (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
14285                          != DNS_KEYOWNER_ZONE)
14286                         continue;
14287
14288                 dns_rdata_toregion(&tuple->rdata, &r);
14289
14290                 keyid = dst_region_computeid(&r, dnskey.algorithm);
14291
14292                 buf[0] = dnskey.algorithm;
14293                 buf[1] = (keyid & 0xff00) >> 8;
14294                 buf[2] = (keyid & 0xff);
14295                 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
14296                 buf[4] = 0;
14297                 rdata.data = buf;
14298                 rdata.length = sizeof(buf);
14299                 rdata.type = privatetype;
14300                 rdata.rdclass = tuple->rdata.rdclass;
14301
14302                 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
14303                         CHECK(rr_exists(db, ver, name, &rdata, &flag));
14304                         if (flag)
14305                                 continue;
14306                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
14307                                                    name, 0, &rdata, &newtuple));
14308                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
14309                         INSIST(newtuple == NULL);
14310                 }
14311
14312                 /*
14313                  * Remove any record which says this operation has already
14314                  * completed.
14315                  */
14316                 buf[4] = 1;
14317                 CHECK(rr_exists(db, ver, name, &rdata, &flag));
14318                 if (flag) {
14319                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
14320                                                    name, 0, &rdata, &newtuple));
14321                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
14322                         INSIST(newtuple == NULL);
14323                 }
14324         }
14325  failure:
14326         return (result);
14327 }
14328
14329 static isc_result_t
14330 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14331           dns_diff_t *diff, zonediff_t *zonediff)
14332 {
14333         isc_result_t result;
14334         isc_stdtime_t now, inception, soaexpire;
14335         isc_boolean_t check_ksk, keyset_kskonly;
14336         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
14337         unsigned int nkeys = 0, i;
14338         dns_difftuple_t *tuple;
14339
14340         result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
14341                                 zone_keys, &nkeys);
14342         if (result != ISC_R_SUCCESS) {
14343                 dns_zone_log(zone, ISC_LOG_ERROR,
14344                              "sign_apex:find_zone_keys -> %s",
14345                              dns_result_totext(result));
14346                 return (result);
14347         }
14348
14349         isc_stdtime_get(&now);
14350         inception = now - 3600; /* Allow for clock skew. */
14351         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
14352
14353         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
14354         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
14355
14356         /*
14357          * See if update_sigs will update DNSKEY signature and if not
14358          * cause them to sign so that so that newly activated keys
14359          * are used.
14360          */
14361         for (tuple = ISC_LIST_HEAD(diff->tuples);
14362              tuple != NULL;
14363              tuple = ISC_LIST_NEXT(tuple, link)) {
14364                 if (tuple->rdata.type == dns_rdatatype_dnskey &&
14365                     dns_name_equal(&tuple->name, &zone->origin))
14366                         break;
14367         }
14368
14369         if (tuple == NULL) {
14370                 result = del_sigs(zone, db, ver, &zone->origin,
14371                                   dns_rdatatype_dnskey, zonediff,
14372                                   zone_keys, nkeys, now, ISC_FALSE);
14373                 if (result != ISC_R_SUCCESS) {
14374                         dns_zone_log(zone, ISC_LOG_ERROR,
14375                                      "sign_apex:del_sigs -> %s",
14376                                      dns_result_totext(result));
14377                         goto failure;
14378                 }
14379                 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
14380                                   zonediff->diff, zone_keys, nkeys, zone->mctx,
14381                                   inception, soaexpire, check_ksk,
14382                                   keyset_kskonly);
14383                 if (result != ISC_R_SUCCESS) {
14384                         dns_zone_log(zone, ISC_LOG_ERROR,
14385                                      "sign_apex:add_sigs -> %s",
14386                                      dns_result_totext(result));
14387                         goto failure;
14388                 }
14389         }
14390
14391         result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
14392                              inception, soaexpire, now, check_ksk,
14393                              keyset_kskonly, zonediff);
14394
14395         if (result != ISC_R_SUCCESS) {
14396                 dns_zone_log(zone, ISC_LOG_ERROR,
14397                              "sign_apex:update_sigs -> %s",
14398                              dns_result_totext(result));
14399                 goto failure;
14400         }
14401
14402  failure:
14403         for (i = 0; i < nkeys; i++)
14404                 dst_key_free(&zone_keys[i]);
14405         return (result);
14406 }
14407
14408 /*
14409  * Prevent the zone entering a inconsistent state where
14410  * NSEC only DNSKEYs are present with NSEC3 chains.
14411  * See update.c:check_dnssec()
14412  */
14413 static isc_boolean_t
14414 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14415             dns_diff_t *diff)
14416 {
14417         isc_result_t result;
14418         dns_difftuple_t *tuple;
14419         isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
14420         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
14421
14422         /* Scan the tuples for an NSEC-only DNSKEY */
14423         for (tuple = ISC_LIST_HEAD(diff->tuples);
14424              tuple != NULL;
14425              tuple = ISC_LIST_NEXT(tuple, link)) {
14426                 isc_uint8_t alg;
14427                 if (tuple->rdata.type != dns_rdatatype_dnskey ||
14428                     tuple->op != DNS_DIFFOP_ADD)
14429                         continue;
14430
14431                 alg = tuple->rdata.data[3];
14432                 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
14433                     alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
14434                         nseconly = ISC_TRUE;
14435                         break;
14436                 }
14437         }
14438
14439         /* Check existing DB for NSEC-only DNSKEY */
14440         if (!nseconly)
14441                 CHECK(dns_nsec_nseconly(db, ver, &nseconly));
14442
14443         /* Check existing DB for NSEC3 */
14444         if (!nsec3)
14445                 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
14446                                         privatetype, &nsec3));
14447
14448         /* Refuse to allow NSEC3 with NSEC-only keys */
14449         if (nseconly && nsec3) {
14450                 dns_zone_log(zone, ISC_LOG_ERROR,
14451                            "NSEC only DNSKEYs and NSEC3 chains not allowed");
14452                 goto failure;
14453         }
14454
14455         return (ISC_TRUE);
14456
14457  failure:
14458         return (ISC_FALSE);
14459 }
14460
14461 static isc_result_t
14462 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14463                  dns_diff_t *diff)
14464 {
14465         isc_result_t result;
14466         dns_dbnode_t *node = NULL;
14467         dns_rdataset_t rdataset;
14468
14469         dns_rdataset_init(&rdataset);
14470         CHECK(dns_db_getoriginnode(db, &node));
14471
14472         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
14473                                      dns_rdatatype_none, 0, &rdataset, NULL);
14474         if (dns_rdataset_isassociated(&rdataset))
14475                 dns_rdataset_disassociate(&rdataset);
14476         if (result != ISC_R_NOTFOUND)
14477                 goto failure;
14478
14479         result = dns_nsec3param_deletechains(db, ver, zone, diff);
14480
14481  failure:
14482         if (node != NULL)
14483                 dns_db_detachnode(db, &node);
14484         return (result);
14485 }
14486
14487 /*
14488  * Given an RRSIG rdataset and an algorithm, determine whether there
14489  * are any signatures using that algorithm.
14490  */
14491 static isc_boolean_t
14492 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
14493         dns_rdata_t rdata = DNS_RDATA_INIT;
14494         dns_rdata_rrsig_t rrsig;
14495         isc_result_t result;
14496
14497         REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
14498         if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
14499                 return (ISC_FALSE);
14500         }
14501
14502         for (result = dns_rdataset_first(rdataset);
14503              result == ISC_R_SUCCESS;
14504              result = dns_rdataset_next(rdataset))
14505         {
14506                 dns_rdataset_current(rdataset, &rdata);
14507                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
14508                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14509                 dns_rdata_reset(&rdata);
14510                 if (rrsig.algorithm == alg)
14511                         return (ISC_TRUE);
14512         }
14513
14514         return (ISC_FALSE);
14515 }
14516
14517 static isc_result_t
14518 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14519            dns_diff_t *diff)
14520 {
14521         dns_name_t *origin;
14522         isc_boolean_t build_nsec3;
14523         isc_result_t result;
14524
14525         origin = dns_db_origin(db);
14526         CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
14527                                  &build_nsec3));
14528         if (build_nsec3)
14529                 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
14530                                            ISC_FALSE, zone->privatetype, diff));
14531         CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
14532
14533  failure:
14534         return (result);
14535 }
14536
14537 static void
14538 zone_rekey(dns_zone_t *zone) {
14539         isc_result_t result;
14540         dns_db_t *db = NULL;
14541         dns_dbnode_t *node = NULL;
14542         dns_dbversion_t *ver = NULL;
14543         dns_rdataset_t soaset, soasigs, keyset, keysigs;
14544         dns_dnsseckeylist_t dnskeys, keys, rmkeys;
14545         dns_dnsseckey_t *key;
14546         dns_diff_t diff, _sig_diff;
14547         zonediff_t zonediff;
14548         isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
14549         isc_boolean_t newalg = ISC_FALSE;
14550         isc_boolean_t fullsign;
14551         dns_ttl_t ttl = 3600;
14552         const char *dir;
14553         isc_mem_t *mctx;
14554         isc_stdtime_t now;
14555         isc_time_t timenow;
14556         isc_interval_t ival;
14557         char timebuf[80];
14558
14559         REQUIRE(DNS_ZONE_VALID(zone));
14560
14561         ISC_LIST_INIT(dnskeys);
14562         ISC_LIST_INIT(keys);
14563         ISC_LIST_INIT(rmkeys);
14564         dns_rdataset_init(&soaset);
14565         dns_rdataset_init(&soasigs);
14566         dns_rdataset_init(&keyset);
14567         dns_rdataset_init(&keysigs);
14568         dir = dns_zone_getkeydirectory(zone);
14569         mctx = zone->mctx;
14570         dns_diff_init(mctx, &diff);
14571         dns_diff_init(mctx, &_sig_diff);
14572         zonediff_init(&zonediff, &_sig_diff);
14573
14574         CHECK(dns_zone_getdb(zone, &db));
14575         CHECK(dns_db_newversion(db, &ver));
14576         CHECK(dns_db_getoriginnode(db, &node));
14577
14578         TIME_NOW(&timenow);
14579         now = isc_time_seconds(&timenow);
14580
14581         dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
14582
14583         /* Get the SOA record's TTL */
14584         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
14585                                   dns_rdatatype_none, 0, &soaset, &soasigs));
14586         ttl = soaset.ttl;
14587         dns_rdataset_disassociate(&soaset);
14588
14589         /* Get the DNSKEY rdataset */
14590         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
14591                                      dns_rdatatype_none, 0, &keyset, &keysigs);
14592         if (result == ISC_R_SUCCESS) {
14593                 ttl = keyset.ttl;
14594                 result = dns_dnssec_keylistfromrdataset(&zone->origin, dir,
14595                                                         mctx, &keyset,
14596                                                         &keysigs, &soasigs,
14597                                                         ISC_FALSE, ISC_FALSE,
14598                                                         &dnskeys);
14599                 /* Can't get keys for some reason; try again later. */
14600                 if (result != ISC_R_SUCCESS)
14601                         goto trylater;
14602         } else if (result != ISC_R_NOTFOUND)
14603                 goto failure;
14604
14605         /*
14606          * True when called from "rndc sign".  Indicates the zone should be
14607          * fully signed now.
14608          */
14609         fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
14610
14611         result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
14612         if (result == ISC_R_SUCCESS) {
14613                 isc_boolean_t check_ksk;
14614                 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
14615
14616                 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
14617                                                &zone->origin, ttl, &diff,
14618                                                ISC_TF(!check_ksk),
14619                                                mctx, logmsg);
14620
14621                 /* Keys couldn't be updated for some reason;
14622                  * try again later. */
14623                 if (result != ISC_R_SUCCESS) {
14624                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
14625                                      "couldn't update zone keys: %s",
14626                                      isc_result_totext(result));
14627                         goto trylater;
14628                 }
14629
14630                 /*
14631                  * See if any pre-existing keys have newly become active;
14632                  * also, see if any new key is for a new algorithm, as in that
14633                  * event, we need to sign the zone fully.  (If there's a new
14634                  * key, but it's for an already-existing algorithm, then
14635                  * the zone signing can be handled incrementally.)
14636                  */
14637                 for (key = ISC_LIST_HEAD(dnskeys);
14638                      key != NULL;
14639                      key = ISC_LIST_NEXT(key, link)) {
14640                         if (!key->first_sign)
14641                                 continue;
14642
14643                         newactive = ISC_TRUE;
14644
14645                         if (!dns_rdataset_isassociated(&keysigs)) {
14646                                 newalg = ISC_TRUE;
14647                                 break;
14648                         }
14649
14650                         if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
14651                                 /*
14652                                  * This isn't a new algorithm; clear
14653                                  * first_sign so we won't sign the
14654                                  * whole zone with this key later
14655                                  */
14656                                 key->first_sign = ISC_FALSE;
14657                         } else {
14658                                 newalg = ISC_TRUE;
14659                                 break;
14660                         }
14661                 }
14662
14663                 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
14664                     dnskey_sane(zone, db, ver, &diff)) {
14665                         CHECK(dns_diff_apply(&diff, db, ver));
14666                         CHECK(clean_nsec3param(zone, db, ver, &diff));
14667                         CHECK(add_signing_records(db, zone->privatetype,
14668                                                   ver, &diff,
14669                                                   ISC_TF(newalg || fullsign)));
14670                         CHECK(increment_soa_serial(db, ver, &diff, mctx));
14671                         CHECK(add_chains(zone, db, ver, &diff));
14672                         CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
14673                         CHECK(zone_journal(zone, zonediff.diff, "zone_rekey"));
14674                         commit = ISC_TRUE;
14675                 }
14676         }
14677
14678         dns_db_closeversion(db, &ver, commit);
14679
14680         if (commit) {
14681                 dns_difftuple_t *tuple;
14682
14683                 LOCK_ZONE(zone);
14684                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14685
14686                 zone_needdump(zone, DNS_DUMP_DELAY);
14687
14688                 zone_settimer(zone, &timenow);
14689
14690                 /* Remove any signatures from removed keys.  */
14691                 if (!ISC_LIST_EMPTY(rmkeys)) {
14692                         for (key = ISC_LIST_HEAD(rmkeys);
14693                              key != NULL;
14694                              key = ISC_LIST_NEXT(key, link)) {
14695                                 result = zone_signwithkey(zone,
14696                                                           dst_key_alg(key->key),
14697                                                           dst_key_id(key->key),
14698                                                           ISC_TRUE);
14699                                 if (result != ISC_R_SUCCESS) {
14700                                         dns_zone_log(zone, ISC_LOG_ERROR,
14701                                              "zone_signwithkey failed: %s",
14702                                              dns_result_totext(result));
14703                                 }
14704                         }
14705                 }
14706
14707                 if (fullsign) {
14708                         /*
14709                          * "rndc sign" was called, so we now sign the zone
14710                          * with all active keys, whether they're new or not.
14711                          */
14712                         for (key = ISC_LIST_HEAD(dnskeys);
14713                              key != NULL;
14714                              key = ISC_LIST_NEXT(key, link)) {
14715                                 if (!key->force_sign && !key->hint_sign)
14716                                         continue;
14717
14718                                 result = zone_signwithkey(zone,
14719                                                           dst_key_alg(key->key),
14720                                                           dst_key_id(key->key),
14721                                                           ISC_FALSE);
14722                                 if (result != ISC_R_SUCCESS) {
14723                                         dns_zone_log(zone, ISC_LOG_ERROR,
14724                                              "zone_signwithkey failed: %s",
14725                                              dns_result_totext(result));
14726                                 }
14727                         }
14728                 } else if (newalg) {
14729                         /*
14730                          * We haven't been told to sign fully, but a new
14731                          * algorithm was added to the DNSKEY.  We sign
14732                          * the full zone, but only with newly active
14733                          * keys.
14734                          */
14735                         for (key = ISC_LIST_HEAD(dnskeys);
14736                              key != NULL;
14737                              key = ISC_LIST_NEXT(key, link)) {
14738                                 if (!key->first_sign)
14739                                         continue;
14740
14741                                 result = zone_signwithkey(zone,
14742                                                           dst_key_alg(key->key),
14743                                                           dst_key_id(key->key),
14744                                                           ISC_FALSE);
14745                                 if (result != ISC_R_SUCCESS) {
14746                                         dns_zone_log(zone, ISC_LOG_ERROR,
14747                                              "zone_signwithkey failed: %s",
14748                                              dns_result_totext(result));
14749                                 }
14750                         }
14751                 }
14752
14753                 /*
14754                  * Clear fullsign flag, if it was set, so we don't do
14755                  * another full signing next time
14756                  */
14757                 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
14758
14759                 /*
14760                  * Cause the zone to add/delete NSEC3 chains for the
14761                  * deferred NSEC3PARAM changes.
14762                  */
14763                 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
14764                      tuple != NULL;
14765                      tuple = ISC_LIST_NEXT(tuple, link)) {
14766                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
14767                         dns_rdata_t rdata = DNS_RDATA_INIT;
14768                         dns_rdata_nsec3param_t nsec3param;
14769
14770                         if (tuple->rdata.type != zone->privatetype ||
14771                             tuple->op != DNS_DIFFOP_ADD)
14772                                 continue;
14773
14774                         if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
14775                                                         buf, sizeof(buf)))
14776                                 continue;
14777                         result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
14778                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
14779                         if (nsec3param.flags == 0)
14780                                 continue;
14781
14782                         result = zone_addnsec3chain(zone, &nsec3param);
14783                         if (result != ISC_R_SUCCESS) {
14784                                 dns_zone_log(zone, ISC_LOG_ERROR,
14785                                              "zone_addnsec3chain failed: %s",
14786                                              dns_result_totext(result));
14787                         }
14788                 }
14789
14790                 /*
14791                  * Schedule the next resigning event
14792                  */
14793                 set_resigntime(zone);
14794                 UNLOCK_ZONE(zone);
14795         }
14796
14797         isc_time_settoepoch(&zone->refreshkeytime);
14798
14799         /*
14800          * If we're doing key maintenance, set the key refresh timer to
14801          * the next scheduled key event or to one hour in the future,
14802          * whichever is sooner.
14803          */
14804         if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
14805                 isc_time_t timethen;
14806                 isc_stdtime_t then;
14807
14808                 LOCK_ZONE(zone);
14809                 DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
14810                 zone->refreshkeytime = timethen;
14811                 UNLOCK_ZONE(zone);
14812
14813                 for (key = ISC_LIST_HEAD(dnskeys);
14814                      key != NULL;
14815                      key = ISC_LIST_NEXT(key, link)) {
14816                         then = now;
14817                         result = next_keyevent(key->key, &then);
14818                         if (result != ISC_R_SUCCESS)
14819                                 continue;
14820
14821                         DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
14822                         LOCK_ZONE(zone);
14823                         if (isc_time_compare(&timethen,
14824                                              &zone->refreshkeytime) < 0) {
14825                                 zone->refreshkeytime = timethen;
14826                         }
14827                         UNLOCK_ZONE(zone);
14828                 }
14829
14830                 zone_settimer(zone, &timenow);
14831
14832                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
14833                 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
14834         }
14835
14836  failure:
14837         dns_diff_clear(&diff);
14838         dns_diff_clear(&_sig_diff);
14839
14840         clear_keylist(&dnskeys, mctx);
14841         clear_keylist(&keys, mctx);
14842         clear_keylist(&rmkeys, mctx);
14843
14844         if (ver != NULL)
14845                 dns_db_closeversion(db, &ver, ISC_FALSE);
14846         if (dns_rdataset_isassociated(&keyset))
14847                 dns_rdataset_disassociate(&keyset);
14848         if (dns_rdataset_isassociated(&keysigs))
14849                 dns_rdataset_disassociate(&keysigs);
14850         if (dns_rdataset_isassociated(&soasigs))
14851                 dns_rdataset_disassociate(&soasigs);
14852         if (node != NULL)
14853                 dns_db_detachnode(db, &node);
14854         if (db != NULL)
14855                 dns_db_detach(&db);
14856         return;
14857
14858  trylater:
14859         isc_interval_set(&ival, HOUR, 0);
14860         isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
14861         goto failure;
14862 }
14863
14864 void
14865 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
14866         isc_time_t now;
14867
14868         if (zone->type == dns_zone_master && zone->task != NULL) {
14869                 LOCK_ZONE(zone);
14870
14871                 if (fullsign)
14872                         zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
14873
14874                 TIME_NOW(&now);
14875                 zone->refreshkeytime = now;
14876                 zone_settimer(zone, &now);
14877
14878                 UNLOCK_ZONE(zone);
14879         }
14880 }
14881
14882 isc_result_t
14883 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
14884                  unsigned int *errors)
14885 {
14886         isc_result_t result;
14887         dns_dbnode_t *node = NULL;
14888
14889         REQUIRE(DNS_ZONE_VALID(zone));
14890         REQUIRE(errors != NULL);
14891
14892         result = dns_db_getoriginnode(db, &node);
14893         if (result != ISC_R_SUCCESS)
14894                 return (result);
14895         result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
14896                                   ISC_FALSE);
14897         dns_db_detachnode(db, &node);
14898         return (result);
14899 }
14900
14901 void
14902 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
14903         REQUIRE(DNS_ZONE_VALID(zone));
14904         LOCK_ZONE(zone);
14905         zone->added = added;
14906         UNLOCK_ZONE(zone);
14907 }
14908
14909 isc_boolean_t
14910 dns_zone_getadded(dns_zone_t *zone) {
14911         REQUIRE(DNS_ZONE_VALID(zone));
14912         return (zone->added);
14913 }
14914
14915 isc_result_t
14916 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
14917 {
14918         isc_time_t loadtime;
14919         isc_result_t result;
14920         TIME_NOW(&loadtime);
14921
14922         LOCK_ZONE(zone);
14923         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
14924         UNLOCK_ZONE(zone);
14925         return result;
14926 }