]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/dns/zone.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / dns / zone.c
1 /*
2  * Copyright (C) 2004-2012  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 a rpz radix was needed when last loaded
339          */
340         isc_boolean_t           rpz_zone;
341
342         /*%
343          * Outstanding forwarded UPDATE requests.
344          */
345         dns_forwardlist_t       forwards;
346 };
347
348 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
349 #define DNS_ZONE_SETFLAG(z,f) do { \
350                 INSIST(LOCKED_ZONE(z)); \
351                 (z)->flags |= (f); \
352                 } while (0)
353 #define DNS_ZONE_CLRFLAG(z,f) do { \
354                 INSIST(LOCKED_ZONE(z)); \
355                 (z)->flags &= ~(f); \
356                 } while (0)
357         /* XXX MPA these may need to go back into zone.h */
358 #define DNS_ZONEFLG_REFRESH     0x00000001U     /*%< refresh check in progress */
359 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /*%< zone need consolidation */
360 #define DNS_ZONEFLG_USEVC       0x00000004U     /*%< use tcp for refresh query */
361 #define DNS_ZONEFLG_DUMPING     0x00000008U     /*%< a dump is in progress */
362 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /*%< $INCLUDE in zone file */
363 #define DNS_ZONEFLG_LOADED      0x00000020U     /*%< database has loaded */
364 #define DNS_ZONEFLG_EXITING     0x00000040U     /*%< zone is being destroyed */
365 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /*%< zone has expired */
366 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /*%< refresh check needed */
367 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /*%< zone contents are
368                                                  * uptodate */
369 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /*%< need to send out notify
370                                                  * messages */
371 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /*%< generate a journal diff on
372                                                  * reload */
373 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /*%< an attempt to refresh a
374                                                  * zone with no masters
375                                                  * occurred */
376 #define DNS_ZONEFLG_LOADING     0x00002000U     /*%< load from disk in progress*/
377 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /*%< timer values have been set
378                                                  * from SOA (if not set, we
379                                                  * are still using
380                                                  * default timer values) */
381 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
382 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
383 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
384 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
385 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
386 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /*%< IXFR failed, force AXFR */
387 #define DNS_ZONEFLG_FLUSH       0x00200000U
388 #define DNS_ZONEFLG_NOEDNS      0x00400000U
389 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
390 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
391 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
392 #define DNS_ZONEFLG_REFRESHING  0x04000000U     /*%< Refreshing keydata */
393 #define DNS_ZONEFLG_THAW        0x08000000U
394 /* #define DNS_ZONEFLG_XXXXX    0x10000000U   XXXMPA unused. */
395 #define DNS_ZONEFLG_NODELAY     0x20000000U
396
397 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
398 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
399
400 /* Flags for zone_load() */
401 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
402 #define DNS_ZONELOADFLAG_THAW   0x00000002U     /* Thaw the zone on successful
403                                                    load. */
404
405 #define UNREACH_CHACHE_SIZE     10U
406 #define UNREACH_HOLD_TIME       600     /* 10 minutes */
407
408 #define CHECK(op) \
409         do { result = (op); \
410                 if (result != ISC_R_SUCCESS) goto failure; \
411         } while (0)
412
413 struct dns_unreachable {
414         isc_sockaddr_t  remote;
415         isc_sockaddr_t  local;
416         isc_uint32_t    expire;
417         isc_uint32_t    last;
418 };
419
420 struct dns_zonemgr {
421         unsigned int            magic;
422         isc_mem_t *             mctx;
423         int                     refs;           /* Locked by rwlock */
424         isc_taskmgr_t *         taskmgr;
425         isc_timermgr_t *        timermgr;
426         isc_socketmgr_t *       socketmgr;
427         isc_taskpool_t *        zonetasks;
428         isc_task_t *            task;
429         isc_ratelimiter_t *     rl;
430         isc_rwlock_t            rwlock;
431         isc_mutex_t             iolock;
432         isc_rwlock_t            urlock;
433
434         /* Locked by rwlock. */
435         dns_zonelist_t          zones;
436         dns_zonelist_t          waiting_for_xfrin;
437         dns_zonelist_t          xfrin_in_progress;
438
439         /* Configuration data. */
440         isc_uint32_t            transfersin;
441         isc_uint32_t            transfersperns;
442         unsigned int            serialqueryrate;
443
444         /* Locked by iolock */
445         isc_uint32_t            iolimit;
446         isc_uint32_t            ioactive;
447         dns_iolist_t            high;
448         dns_iolist_t            low;
449
450         /* Locked by urlock. */
451         /* LRU cache */
452         struct dns_unreachable  unreachable[UNREACH_CHACHE_SIZE];
453 };
454
455 /*%
456  * Hold notify state.
457  */
458 struct dns_notify {
459         unsigned int            magic;
460         unsigned int            flags;
461         isc_mem_t               *mctx;
462         dns_zone_t              *zone;
463         dns_adbfind_t           *find;
464         dns_request_t           *request;
465         dns_name_t              ns;
466         isc_sockaddr_t          dst;
467         ISC_LINK(dns_notify_t)  link;
468 };
469
470 #define DNS_NOTIFY_NOSOA        0x0001U
471
472 /*%
473  *      dns_stub holds state while performing a 'stub' transfer.
474  *      'db' is the zone's 'db' or a new one if this is the initial
475  *      transfer.
476  */
477
478 struct dns_stub {
479         unsigned int            magic;
480         isc_mem_t               *mctx;
481         dns_zone_t              *zone;
482         dns_db_t                *db;
483         dns_dbversion_t         *version;
484 };
485
486 /*%
487  *      Hold load state.
488  */
489 struct dns_load {
490         unsigned int            magic;
491         isc_mem_t               *mctx;
492         dns_zone_t              *zone;
493         dns_db_t                *db;
494         isc_time_t              loadtime;
495         dns_rdatacallbacks_t    callbacks;
496 };
497
498 /*%
499  *      Hold forward state.
500  */
501 struct dns_forward {
502         unsigned int            magic;
503         isc_mem_t               *mctx;
504         dns_zone_t              *zone;
505         isc_buffer_t            *msgbuf;
506         dns_request_t           *request;
507         isc_uint32_t            which;
508         isc_sockaddr_t          addr;
509         dns_updatecallback_t    callback;
510         void                    *callback_arg;
511         ISC_LINK(dns_forward_t) link;
512 };
513
514 /*%
515  *      Hold IO request state.
516  */
517 struct dns_io {
518         unsigned int    magic;
519         dns_zonemgr_t   *zmgr;
520         isc_boolean_t   high;
521         isc_task_t      *task;
522         ISC_LINK(dns_io_t) link;
523         isc_event_t     *event;
524 };
525
526 /*%
527  *      Hold state for when we are signing a zone with a new
528  *      DNSKEY as result of an update.
529  */
530 struct dns_signing {
531         unsigned int            magic;
532         dns_db_t                *db;
533         dns_dbiterator_t        *dbiterator;
534         dns_secalg_t            algorithm;
535         isc_uint16_t            keyid;
536         isc_boolean_t           delete;
537         isc_boolean_t           done;
538         ISC_LINK(dns_signing_t) link;
539 };
540
541 struct dns_nsec3chain {
542         unsigned int                    magic;
543         dns_db_t                        *db;
544         dns_dbiterator_t                *dbiterator;
545         dns_rdata_nsec3param_t          nsec3param;
546         unsigned char                   salt[255];
547         isc_boolean_t                   done;
548         isc_boolean_t                   seen_nsec;
549         isc_boolean_t                   delete_nsec;
550         isc_boolean_t                   save_delete_nsec;
551         ISC_LINK(dns_nsec3chain_t)      link;
552 };
553 /*%<
554  * 'dbiterator' contains a iterator for the database.  If we are creating
555  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
556  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
557  * iterated.
558  *
559  * 'nsec3param' contains the parameters of the NSEC3 chain being created
560  * or removed.
561  *
562  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
563  *
564  * 'seen_nsec' will be set to true if, while iterating the zone to create a
565  * NSEC3 chain, a NSEC record is seen.
566  *
567  * 'delete_nsec' will be set to true if, at the completion of the creation
568  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
569  * are in the process of deleting the NSEC chain.
570  *
571  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
572  * so it can be recovered in the event of a error.
573  */
574
575 struct dns_keyfetch {
576         dns_fixedname_t name;
577         dns_rdataset_t keydataset;
578         dns_rdataset_t dnskeyset;
579         dns_rdataset_t dnskeysigset;
580         dns_zone_t *zone;
581         dns_db_t *db;
582         dns_fetch_t *fetch;
583 };
584
585 #define HOUR 3600
586 #define DAY (24*HOUR)
587 #define MONTH (30*DAY)
588
589 #define SEND_BUFFER_SIZE 2048
590
591 static void zone_settimer(dns_zone_t *, isc_time_t *);
592 static void cancel_refresh(dns_zone_t *);
593 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
594                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
595 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
596      ISC_FORMAT_PRINTF(3, 4);
597 static void queue_xfrin(dns_zone_t *zone);
598 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
599                                   dns_diff_t *diff, dns_diffop_t op,
600                                   dns_name_t *name, dns_ttl_t ttl,
601                                   dns_rdata_t *rdata);
602 static void zone_unload(dns_zone_t *zone);
603 static void zone_expire(dns_zone_t *zone);
604 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
605 static void zone_idetach(dns_zone_t **zonep);
606 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
607                                    isc_boolean_t dump);
608 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
609 static inline void zone_detachdb(dns_zone_t *zone);
610 static isc_result_t default_journal(dns_zone_t *zone);
611 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
612 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
613                                   isc_time_t loadtime, isc_result_t result);
614 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
615 static void zone_shutdown(isc_task_t *, isc_event_t *);
616 static void zone_loaddone(void *arg, isc_result_t result);
617 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
618                                    isc_time_t loadtime);
619 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
620 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
621 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
622 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
623
624 #if 0
625 /* ondestroy example */
626 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
627 #endif
628
629 static void refresh_callback(isc_task_t *, isc_event_t *);
630 static void stub_callback(isc_task_t *, isc_event_t *);
631 static void queue_soa_query(dns_zone_t *zone);
632 static void soa_query(isc_task_t *, isc_event_t *);
633 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
634                      dns_stub_t *stub);
635 static int message_count(dns_message_t *msg, dns_section_t section,
636                          dns_rdatatype_t type);
637 static void notify_cancel(dns_zone_t *zone);
638 static void notify_find_address(dns_notify_t *notify);
639 static void notify_send(dns_notify_t *notify);
640 static isc_result_t notify_createmessage(dns_zone_t *zone,
641                                          unsigned int flags,
642                                          dns_message_t **messagep);
643 static void notify_done(isc_task_t *task, isc_event_t *event);
644 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
645 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
646 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
647 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
648                                              dns_zone_t *zone);
649 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
650 static void zonemgr_free(dns_zonemgr_t *zmgr);
651 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
652                                   isc_task_t *task, isc_taskaction_t action,
653                                   void *arg, dns_io_t **iop);
654 static void zonemgr_putio(dns_io_t **iop);
655 static void zonemgr_cancelio(dns_io_t *io);
656
657 static isc_result_t
658 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
659                  unsigned int *soacount, isc_uint32_t *serial,
660                  isc_uint32_t *refresh, isc_uint32_t *retry,
661                  isc_uint32_t *expire, isc_uint32_t *minimum,
662                  unsigned int *errors);
663
664 static void zone_freedbargs(dns_zone_t *zone);
665 static void forward_callback(isc_task_t *task, isc_event_t *event);
666 static void zone_saveunique(dns_zone_t *zone, const char *path,
667                             const char *templat);
668 static void zone_maintenance(dns_zone_t *zone);
669 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
670 static void dump_done(void *arg, isc_result_t result);
671 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
672                                      isc_uint16_t keyid, isc_boolean_t delete);
673 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
674                                 dns_dbnode_t *node, dns_name_t *name,
675                                 dns_diff_t *diff);
676 static void zone_rekey(dns_zone_t *zone);
677 static isc_boolean_t delsig_ok(dns_rdata_rrsig_t *rrsig_ptr,
678                                dst_key_t **keys, unsigned int nkeys);
679
680 #define ENTER zone_debuglog(zone, me, 1, "enter")
681
682 static const unsigned int dbargc_default = 1;
683 static const char *dbargv_default[] = { "rbt" };
684
685 #define DNS_ZONE_JITTER_ADD(a, b, c) \
686         do { \
687                 isc_interval_t _i; \
688                 isc_uint32_t _j; \
689                 _j = isc_random_jitter((b), (b)/4); \
690                 isc_interval_set(&_i, _j, 0); \
691                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
692                         dns_zone_log(zone, ISC_LOG_WARNING, \
693                                      "epoch approaching: upgrade required: " \
694                                      "now + %s failed", #b); \
695                         isc_interval_set(&_i, _j/2, 0); \
696                         (void)isc_time_add((a), &_i, (c)); \
697                 } \
698         } while (0)
699
700 #define DNS_ZONE_TIME_ADD(a, b, c) \
701         do { \
702                 isc_interval_t _i; \
703                 isc_interval_set(&_i, (b), 0); \
704                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
705                         dns_zone_log(zone, ISC_LOG_WARNING, \
706                                      "epoch approaching: upgrade required: " \
707                                      "now + %s failed", #b); \
708                         isc_interval_set(&_i, (b)/2, 0); \
709                         (void)isc_time_add((a), &_i, (c)); \
710                 } \
711         } while (0)
712
713 /*%
714  * Increment resolver-related statistics counters.  Zone must be locked.
715  */
716 static inline void
717 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
718         if (zone->stats != NULL)
719                 isc_stats_increment(zone->stats, counter);
720 }
721
722 /***
723  ***    Public functions.
724  ***/
725
726 isc_result_t
727 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
728         isc_result_t result;
729         dns_zone_t *zone;
730         isc_time_t now;
731
732         REQUIRE(zonep != NULL && *zonep == NULL);
733         REQUIRE(mctx != NULL);
734
735         TIME_NOW(&now);
736         zone = isc_mem_get(mctx, sizeof(*zone));
737         if (zone == NULL)
738                 return (ISC_R_NOMEMORY);
739
740         zone->mctx = NULL;
741         isc_mem_attach(mctx, &zone->mctx);
742
743         result = isc_mutex_init(&zone->lock);
744         if (result != ISC_R_SUCCESS)
745                 goto free_zone;
746
747         result = ZONEDB_INITLOCK(&zone->dblock);
748         if (result != ISC_R_SUCCESS)
749                 goto free_mutex;
750
751         /* XXX MPA check that all elements are initialised */
752 #ifdef DNS_ZONE_CHECKLOCK
753         zone->locked = ISC_FALSE;
754 #endif
755         zone->db = NULL;
756         zone->zmgr = NULL;
757         ISC_LINK_INIT(zone, link);
758         result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
759         if (result != ISC_R_SUCCESS)
760                 goto free_dblock;
761         zone->irefs = 0;
762         dns_name_init(&zone->origin, NULL);
763         zone->strnamerd = NULL;
764         zone->strname = NULL;
765         zone->strrdclass = NULL;
766         zone->strviewname = NULL;
767         zone->masterfile = NULL;
768         zone->masterformat = dns_masterformat_none;
769         zone->keydirectory = NULL;
770         zone->journalsize = -1;
771         zone->journal = NULL;
772         zone->rdclass = dns_rdataclass_none;
773         zone->type = dns_zone_none;
774         zone->flags = 0;
775         zone->options = 0;
776         zone->keyopts = 0;
777         zone->db_argc = 0;
778         zone->db_argv = NULL;
779         isc_time_settoepoch(&zone->expiretime);
780         isc_time_settoepoch(&zone->refreshtime);
781         isc_time_settoepoch(&zone->dumptime);
782         isc_time_settoepoch(&zone->loadtime);
783         zone->notifytime = now;
784         isc_time_settoepoch(&zone->resigntime);
785         isc_time_settoepoch(&zone->keywarntime);
786         isc_time_settoepoch(&zone->signingtime);
787         isc_time_settoepoch(&zone->nsec3chaintime);
788         isc_time_settoepoch(&zone->refreshkeytime);
789         zone->refreshkeycount = 0;
790         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
791         zone->retry = DNS_ZONE_DEFAULTRETRY;
792         zone->expire = 0;
793         zone->minimum = 0;
794         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
795         zone->minrefresh = DNS_ZONE_MINREFRESH;
796         zone->maxretry = DNS_ZONE_MAXRETRY;
797         zone->minretry = DNS_ZONE_MINRETRY;
798         zone->masters = NULL;
799         zone->masterkeynames = NULL;
800         zone->mastersok = NULL;
801         zone->masterscnt = 0;
802         zone->curmaster = 0;
803         zone->notify = NULL;
804         zone->notifytype = dns_notifytype_yes;
805         zone->notifycnt = 0;
806         zone->task = NULL;
807         zone->update_acl = NULL;
808         zone->forward_acl = NULL;
809         zone->notify_acl = NULL;
810         zone->query_acl = NULL;
811         zone->queryon_acl = NULL;
812         zone->xfr_acl = NULL;
813         zone->update_disabled = ISC_FALSE;
814         zone->zero_no_soa_ttl = ISC_TRUE;
815         zone->check_names = dns_severity_ignore;
816         zone->request = NULL;
817         zone->lctx = NULL;
818         zone->readio = NULL;
819         zone->dctx = NULL;
820         zone->writeio = NULL;
821         zone->timer = NULL;
822         zone->idlein = DNS_DEFAULT_IDLEIN;
823         zone->idleout = DNS_DEFAULT_IDLEOUT;
824         zone->log_key_expired_timer = 0;
825         ISC_LIST_INIT(zone->notifies);
826         isc_sockaddr_any(&zone->notifysrc4);
827         isc_sockaddr_any6(&zone->notifysrc6);
828         isc_sockaddr_any(&zone->xfrsource4);
829         isc_sockaddr_any6(&zone->xfrsource6);
830         isc_sockaddr_any(&zone->altxfrsource4);
831         isc_sockaddr_any6(&zone->altxfrsource6);
832         zone->xfr = NULL;
833         zone->tsigkey = NULL;
834         zone->maxxfrin = MAX_XFER_TIME;
835         zone->maxxfrout = MAX_XFER_TIME;
836         zone->ssutable = NULL;
837         zone->sigvalidityinterval = 30 * 24 * 3600;
838         zone->sigresigninginterval = 7 * 24 * 3600;
839         zone->view = NULL;
840         zone->acache = NULL;
841         zone->checkmx = NULL;
842         zone->checksrv = NULL;
843         zone->checkns = NULL;
844         ISC_LINK_INIT(zone, statelink);
845         zone->statelist = NULL;
846         zone->stats = NULL;
847         zone->requeststats_on = ISC_FALSE;
848         zone->requeststats = NULL;
849         zone->notifydelay = 5;
850         zone->isself = NULL;
851         zone->isselfarg = NULL;
852         ISC_LIST_INIT(zone->signing);
853         ISC_LIST_INIT(zone->nsec3chain);
854         zone->signatures = 10;
855         zone->nodes = 100;
856         zone->privatetype = (dns_rdatatype_t)0xffffU;
857         zone->added = ISC_FALSE;
858         zone->rpz_zone = ISC_FALSE;
859         ISC_LIST_INIT(zone->forwards);
860
861         zone->magic = ZONE_MAGIC;
862
863         /* Must be after magic is set. */
864         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
865         if (result != ISC_R_SUCCESS)
866                 goto free_erefs;
867
868         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
869                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
870                        NULL, NULL);
871         *zonep = zone;
872         return (ISC_R_SUCCESS);
873
874  free_erefs:
875         isc_refcount_decrement(&zone->erefs, NULL);
876         isc_refcount_destroy(&zone->erefs);
877
878  free_dblock:
879         ZONEDB_DESTROYLOCK(&zone->dblock);
880
881  free_mutex:
882         DESTROYLOCK(&zone->lock);
883
884  free_zone:
885         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
886         return (result);
887 }
888
889 /*
890  * Free a zone.  Because we require that there be no more
891  * outstanding events or references, no locking is necessary.
892  */
893 static void
894 zone_free(dns_zone_t *zone) {
895         isc_mem_t *mctx = NULL;
896         dns_signing_t *signing;
897         dns_nsec3chain_t *nsec3chain;
898
899         REQUIRE(DNS_ZONE_VALID(zone));
900         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
901         REQUIRE(zone->irefs == 0);
902         REQUIRE(!LOCKED_ZONE(zone));
903         REQUIRE(zone->timer == NULL);
904
905         /*
906          * Managed objects.  Order is important.
907          */
908         if (zone->request != NULL)
909                 dns_request_destroy(&zone->request); /* XXXMPA */
910         INSIST(zone->readio == NULL);
911         INSIST(zone->statelist == NULL);
912         INSIST(zone->writeio == NULL);
913
914         if (zone->task != NULL)
915                 isc_task_detach(&zone->task);
916         if (zone->zmgr != NULL)
917                 dns_zonemgr_releasezone(zone->zmgr, zone);
918
919         /* Unmanaged objects */
920         for (signing = ISC_LIST_HEAD(zone->signing);
921              signing != NULL;
922              signing = ISC_LIST_HEAD(zone->signing)) {
923                 ISC_LIST_UNLINK(zone->signing, signing, link);
924                 dns_db_detach(&signing->db);
925                 dns_dbiterator_destroy(&signing->dbiterator);
926                 isc_mem_put(zone->mctx, signing, sizeof *signing);
927         }
928         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
929              nsec3chain != NULL;
930              nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
931                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
932                 dns_db_detach(&nsec3chain->db);
933                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
934                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
935         }
936         if (zone->masterfile != NULL)
937                 isc_mem_free(zone->mctx, zone->masterfile);
938         zone->masterfile = NULL;
939         if (zone->keydirectory != NULL)
940                 isc_mem_free(zone->mctx, zone->keydirectory);
941         zone->keydirectory = NULL;
942         zone->journalsize = -1;
943         if (zone->journal != NULL)
944                 isc_mem_free(zone->mctx, zone->journal);
945         zone->journal = NULL;
946         if (zone->stats != NULL)
947                 isc_stats_detach(&zone->stats);
948         if (zone->requeststats != NULL)
949                 isc_stats_detach(&zone->requeststats);
950         if (zone->db != NULL)
951                 zone_detachdb(zone);
952         if (zone->acache != NULL)
953                 dns_acache_detach(&zone->acache);
954         zone_freedbargs(zone);
955         RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
956                       == ISC_R_SUCCESS);
957         RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
958                       == ISC_R_SUCCESS);
959         zone->check_names = dns_severity_ignore;
960         if (zone->update_acl != NULL)
961                 dns_acl_detach(&zone->update_acl);
962         if (zone->forward_acl != NULL)
963                 dns_acl_detach(&zone->forward_acl);
964         if (zone->notify_acl != NULL)
965                 dns_acl_detach(&zone->notify_acl);
966         if (zone->query_acl != NULL)
967                 dns_acl_detach(&zone->query_acl);
968         if (zone->queryon_acl != NULL)
969                 dns_acl_detach(&zone->queryon_acl);
970         if (zone->xfr_acl != NULL)
971                 dns_acl_detach(&zone->xfr_acl);
972         if (dns_name_dynamic(&zone->origin))
973                 dns_name_free(&zone->origin, zone->mctx);
974         if (zone->strnamerd != NULL)
975                 isc_mem_free(zone->mctx, zone->strnamerd);
976         if (zone->strname != NULL)
977                 isc_mem_free(zone->mctx, zone->strname);
978         if (zone->strrdclass != NULL)
979                 isc_mem_free(zone->mctx, zone->strrdclass);
980         if (zone->strviewname != NULL)
981                 isc_mem_free(zone->mctx, zone->strviewname);
982         if (zone->ssutable != NULL)
983                 dns_ssutable_detach(&zone->ssutable);
984
985         /* last stuff */
986         ZONEDB_DESTROYLOCK(&zone->dblock);
987         DESTROYLOCK(&zone->lock);
988         isc_refcount_destroy(&zone->erefs);
989         zone->magic = 0;
990         mctx = zone->mctx;
991         isc_mem_put(mctx, zone, sizeof(*zone));
992         isc_mem_detach(&mctx);
993 }
994
995 /*
996  *      Single shot.
997  */
998 void
999 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1000         char namebuf[1024];
1001
1002         REQUIRE(DNS_ZONE_VALID(zone));
1003         REQUIRE(rdclass != dns_rdataclass_none);
1004
1005         /*
1006          * Test and set.
1007          */
1008         LOCK_ZONE(zone);
1009         REQUIRE(zone->rdclass == dns_rdataclass_none ||
1010                 zone->rdclass == rdclass);
1011         zone->rdclass = rdclass;
1012
1013         if (zone->strnamerd != NULL)
1014                 isc_mem_free(zone->mctx, zone->strnamerd);
1015         if (zone->strrdclass != NULL)
1016                 isc_mem_free(zone->mctx, zone->strrdclass);
1017
1018         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1019         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1020         zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1021         zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1022
1023         UNLOCK_ZONE(zone);
1024 }
1025
1026 dns_rdataclass_t
1027 dns_zone_getclass(dns_zone_t *zone) {
1028         REQUIRE(DNS_ZONE_VALID(zone));
1029
1030         return (zone->rdclass);
1031 }
1032
1033 void
1034 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1035         REQUIRE(DNS_ZONE_VALID(zone));
1036
1037         LOCK_ZONE(zone);
1038         zone->notifytype = notifytype;
1039         UNLOCK_ZONE(zone);
1040 }
1041
1042 isc_result_t
1043 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1044         isc_result_t result;
1045
1046         REQUIRE(DNS_ZONE_VALID(zone));
1047         REQUIRE(serialp != NULL);
1048
1049         LOCK_ZONE(zone);
1050         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1051         if (zone->db != NULL) {
1052                 result = zone_get_from_db(zone, zone->db, NULL, NULL, serialp,
1053                                           NULL, NULL, NULL, NULL, NULL);
1054         } else
1055                 result = DNS_R_NOTLOADED;
1056         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1057         UNLOCK_ZONE(zone);
1058
1059         return (result);
1060 }
1061
1062 isc_uint32_t
1063 dns_zone_getserial(dns_zone_t *zone) {
1064         isc_result_t result;
1065         isc_uint32_t serial;
1066
1067         result = dns_zone_getserial2(zone, &serial);
1068         if (result != ISC_R_SUCCESS)
1069                 serial = 0; /* XXX: not really correct, but no other choice */
1070
1071         return (serial);
1072 }
1073
1074 /*
1075  *      Single shot.
1076  */
1077 void
1078 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1079
1080         REQUIRE(DNS_ZONE_VALID(zone));
1081         REQUIRE(type != dns_zone_none);
1082
1083         /*
1084          * Test and set.
1085          */
1086         LOCK_ZONE(zone);
1087         REQUIRE(zone->type == dns_zone_none || zone->type == type);
1088         zone->type = type;
1089         UNLOCK_ZONE(zone);
1090 }
1091
1092 static void
1093 zone_freedbargs(dns_zone_t *zone) {
1094         unsigned int i;
1095
1096         /* Free the old database argument list. */
1097         if (zone->db_argv != NULL) {
1098                 for (i = 0; i < zone->db_argc; i++)
1099                         isc_mem_free(zone->mctx, zone->db_argv[i]);
1100                 isc_mem_put(zone->mctx, zone->db_argv,
1101                             zone->db_argc * sizeof(*zone->db_argv));
1102         }
1103         zone->db_argc = 0;
1104         zone->db_argv = NULL;
1105 }
1106
1107 isc_result_t
1108 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1109         size_t size = 0;
1110         unsigned int i;
1111         isc_result_t result = ISC_R_SUCCESS;
1112         void *mem;
1113         char **tmp, *tmp2;
1114
1115         REQUIRE(DNS_ZONE_VALID(zone));
1116         REQUIRE(argv != NULL && *argv == NULL);
1117
1118         LOCK_ZONE(zone);
1119         size = (zone->db_argc + 1) * sizeof(char *);
1120         for (i = 0; i < zone->db_argc; i++)
1121                 size += strlen(zone->db_argv[i]) + 1;
1122         mem = isc_mem_allocate(mctx, size);
1123         if (mem != NULL) {
1124                 tmp = mem;
1125                 tmp2 = mem;
1126                 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1127                 for (i = 0; i < zone->db_argc; i++) {
1128                         *tmp++ = tmp2;
1129                         strcpy(tmp2, zone->db_argv[i]);
1130                         tmp2 += strlen(tmp2) + 1;
1131                 }
1132                 *tmp = NULL;
1133         } else
1134                 result = ISC_R_NOMEMORY;
1135         UNLOCK_ZONE(zone);
1136         *argv = mem;
1137         return (result);
1138 }
1139
1140 isc_result_t
1141 dns_zone_setdbtype(dns_zone_t *zone,
1142                    unsigned int dbargc, const char * const *dbargv) {
1143         isc_result_t result = ISC_R_SUCCESS;
1144         char **new = NULL;
1145         unsigned int i;
1146
1147         REQUIRE(DNS_ZONE_VALID(zone));
1148         REQUIRE(dbargc >= 1);
1149         REQUIRE(dbargv != NULL);
1150
1151         LOCK_ZONE(zone);
1152
1153         /* Set up a new database argument list. */
1154         new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1155         if (new == NULL)
1156                 goto nomem;
1157         for (i = 0; i < dbargc; i++)
1158                 new[i] = NULL;
1159         for (i = 0; i < dbargc; i++) {
1160                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1161                 if (new[i] == NULL)
1162                         goto nomem;
1163         }
1164
1165         /* Free the old list. */
1166         zone_freedbargs(zone);
1167
1168         zone->db_argc = dbargc;
1169         zone->db_argv = new;
1170         result = ISC_R_SUCCESS;
1171         goto unlock;
1172
1173  nomem:
1174         if (new != NULL) {
1175                 for (i = 0; i < dbargc; i++)
1176                         if (new[i] != NULL)
1177                                 isc_mem_free(zone->mctx, new[i]);
1178                 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1179         }
1180         result = ISC_R_NOMEMORY;
1181
1182  unlock:
1183         UNLOCK_ZONE(zone);
1184         return (result);
1185 }
1186
1187 void
1188 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1189         char namebuf[1024];
1190         REQUIRE(DNS_ZONE_VALID(zone));
1191
1192         LOCK_ZONE(zone);
1193         if (zone->view != NULL)
1194                 dns_view_weakdetach(&zone->view);
1195         dns_view_weakattach(view, &zone->view);
1196
1197         if (zone->strviewname != NULL)
1198                 isc_mem_free(zone->mctx, zone->strviewname);
1199         if (zone->strnamerd != NULL)
1200                 isc_mem_free(zone->mctx, zone->strnamerd);
1201
1202         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1203         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1204         zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1205         zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1206
1207         UNLOCK_ZONE(zone);
1208 }
1209
1210
1211 dns_view_t *
1212 dns_zone_getview(dns_zone_t *zone) {
1213         REQUIRE(DNS_ZONE_VALID(zone));
1214
1215         return (zone->view);
1216 }
1217
1218
1219 isc_result_t
1220 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1221         isc_result_t result;
1222         char namebuf[1024];
1223
1224         REQUIRE(DNS_ZONE_VALID(zone));
1225         REQUIRE(origin != NULL);
1226
1227         LOCK_ZONE(zone);
1228         if (dns_name_dynamic(&zone->origin)) {
1229                 dns_name_free(&zone->origin, zone->mctx);
1230                 dns_name_init(&zone->origin, NULL);
1231         }
1232         result = dns_name_dup(origin, zone->mctx, &zone->origin);
1233
1234         if (zone->strnamerd != NULL)
1235                 isc_mem_free(zone->mctx, zone->strnamerd);
1236         if (zone->strname != NULL)
1237                 isc_mem_free(zone->mctx, zone->strname);
1238
1239         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1240         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1241         zone_name_tostr(zone, namebuf, sizeof namebuf);
1242         zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1243
1244         UNLOCK_ZONE(zone);
1245         return (result);
1246 }
1247
1248 void
1249 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1250         REQUIRE(DNS_ZONE_VALID(zone));
1251         REQUIRE(acache != NULL);
1252
1253         LOCK_ZONE(zone);
1254         if (zone->acache != NULL)
1255                 dns_acache_detach(&zone->acache);
1256         dns_acache_attach(acache, &zone->acache);
1257         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1258         if (zone->db != NULL) {
1259                 isc_result_t result;
1260
1261                 /*
1262                  * If the zone reuses an existing DB, the DB needs to be
1263                  * set in the acache explicitly.  We can safely ignore the
1264                  * case where the DB is already set.  If other error happens,
1265                  * the acache will not work effectively.
1266                  */
1267                 result = dns_acache_setdb(acache, zone->db);
1268                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1269                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1270                                          "dns_acache_setdb() failed: %s",
1271                                          isc_result_totext(result));
1272                 }
1273         }
1274         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1275         UNLOCK_ZONE(zone);
1276 }
1277
1278 static isc_result_t
1279 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1280         char *copy;
1281
1282         if (value != NULL) {
1283                 copy = isc_mem_strdup(zone->mctx, value);
1284                 if (copy == NULL)
1285                         return (ISC_R_NOMEMORY);
1286         } else {
1287                 copy = NULL;
1288         }
1289
1290         if (*field != NULL)
1291                 isc_mem_free(zone->mctx, *field);
1292
1293         *field = copy;
1294         return (ISC_R_SUCCESS);
1295 }
1296
1297 isc_result_t
1298 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1299         return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1300 }
1301
1302 isc_result_t
1303 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1304                   dns_masterformat_t format) {
1305         isc_result_t result = ISC_R_SUCCESS;
1306
1307         REQUIRE(DNS_ZONE_VALID(zone));
1308
1309         LOCK_ZONE(zone);
1310         result = dns_zone_setstring(zone, &zone->masterfile, file);
1311         if (result == ISC_R_SUCCESS) {
1312                 zone->masterformat = format;
1313                 result = default_journal(zone);
1314         }
1315         UNLOCK_ZONE(zone);
1316
1317         return (result);
1318 }
1319
1320 const char *
1321 dns_zone_getfile(dns_zone_t *zone) {
1322         REQUIRE(DNS_ZONE_VALID(zone));
1323
1324         return (zone->masterfile);
1325 }
1326
1327 static isc_result_t
1328 default_journal(dns_zone_t *zone) {
1329         isc_result_t result;
1330         char *journal;
1331
1332         REQUIRE(DNS_ZONE_VALID(zone));
1333         REQUIRE(LOCKED_ZONE(zone));
1334
1335         if (zone->masterfile != NULL) {
1336                 /* Calculate string length including '\0'. */
1337                 int len = strlen(zone->masterfile) + sizeof(".jnl");
1338                 journal = isc_mem_allocate(zone->mctx, len);
1339                 if (journal == NULL)
1340                         return (ISC_R_NOMEMORY);
1341                 strcpy(journal, zone->masterfile);
1342                 strcat(journal, ".jnl");
1343         } else {
1344                 journal = NULL;
1345         }
1346         result = dns_zone_setstring(zone, &zone->journal, journal);
1347         if (journal != NULL)
1348                 isc_mem_free(zone->mctx, journal);
1349         return (result);
1350 }
1351
1352 isc_result_t
1353 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1354         isc_result_t result = ISC_R_SUCCESS;
1355
1356         REQUIRE(DNS_ZONE_VALID(zone));
1357
1358         LOCK_ZONE(zone);
1359         result = dns_zone_setstring(zone, &zone->journal, journal);
1360         UNLOCK_ZONE(zone);
1361
1362         return (result);
1363 }
1364
1365 char *
1366 dns_zone_getjournal(dns_zone_t *zone) {
1367         REQUIRE(DNS_ZONE_VALID(zone));
1368
1369         return (zone->journal);
1370 }
1371
1372 /*
1373  * Return true iff the zone is "dynamic", in the sense that the zone's
1374  * master file (if any) is written by the server, rather than being
1375  * updated manually and read by the server.
1376  *
1377  * This is true for slave zones, stub zones, key zones, and zones that
1378  * allow dynamic updates either by having an update policy ("ssutable")
1379  * or an "allow-update" ACL with a value other than exactly "{ none; }".
1380  */
1381 static isc_boolean_t
1382 zone_isdynamic(dns_zone_t *zone) {
1383         REQUIRE(DNS_ZONE_VALID(zone));
1384
1385         return (ISC_TF(zone->type == dns_zone_slave ||
1386                        zone->type == dns_zone_stub ||
1387                        zone->type == dns_zone_key ||
1388                        (!zone->update_disabled && zone->ssutable != NULL) ||
1389                        (!zone->update_disabled && zone->update_acl != NULL &&
1390                         !dns_acl_isnone(zone->update_acl))));
1391 }
1392
1393
1394 static isc_result_t
1395 zone_load(dns_zone_t *zone, unsigned int flags) {
1396         isc_result_t result;
1397         isc_time_t now;
1398         isc_time_t loadtime, filetime;
1399         dns_db_t *db = NULL;
1400         isc_boolean_t rbt;
1401
1402         REQUIRE(DNS_ZONE_VALID(zone));
1403
1404         LOCK_ZONE(zone);
1405         TIME_NOW(&now);
1406
1407         INSIST(zone->type != dns_zone_none);
1408
1409         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1410                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1411                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1412                 result = DNS_R_CONTINUE;
1413                 goto cleanup;
1414         }
1415
1416
1417         INSIST(zone->db_argc >= 1);
1418
1419         rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1420               strcmp(zone->db_argv[0], "rbt64") == 0;
1421
1422         if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1423                 /*
1424                  * The zone has no master file configured.
1425                  */
1426                 result = ISC_R_SUCCESS;
1427                 goto cleanup;
1428         }
1429
1430         if (zone->db != NULL && zone_isdynamic(zone)) {
1431                 /*
1432                  * This is a slave, stub, or dynamically updated
1433                  * zone being reloaded.  Do nothing - the database
1434                  * we already have is guaranteed to be up-to-date.
1435                  */
1436                 if (zone->type == dns_zone_master)
1437                         result = DNS_R_DYNAMIC;
1438                 else
1439                         result = ISC_R_SUCCESS;
1440                 goto cleanup;
1441         }
1442
1443         /*
1444          * Store the current time before the zone is loaded, so that if the
1445          * file changes between the time of the load and the time that
1446          * zone->loadtime is set, then the file will still be reloaded
1447          * the next time dns_zone_load is called.
1448          */
1449         TIME_NOW(&loadtime);
1450
1451         /*
1452          * Don't do the load if the file that stores the zone is older
1453          * than the last time the zone was loaded.  If the zone has not
1454          * been loaded yet, zone->loadtime will be the epoch.
1455          */
1456         if (zone->masterfile != NULL) {
1457                 /*
1458                  * The file is already loaded.  If we are just doing a
1459                  * "rndc reconfig", we are done.
1460                  */
1461                 if (!isc_time_isepoch(&zone->loadtime) &&
1462                     (flags & DNS_ZONELOADFLAG_NOSTAT) != 0 &&
1463                     zone->rpz_zone == dns_rpz_needed()) {
1464                         result = ISC_R_SUCCESS;
1465                         goto cleanup;
1466                 }
1467
1468                 result = isc_file_getmodtime(zone->masterfile, &filetime);
1469                 if (result == ISC_R_SUCCESS) {
1470                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1471                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1472                             isc_time_compare(&filetime, &zone->loadtime) <= 0 &&
1473                             zone->rpz_zone == dns_rpz_needed()) {
1474                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1475                                              "skipping load: master file "
1476                                              "older than last load");
1477                                 result = DNS_R_UPTODATE;
1478                                 goto cleanup;
1479                         }
1480                         loadtime = filetime;
1481                         zone->rpz_zone = dns_rpz_needed();
1482                 }
1483         }
1484
1485         /*
1486          * Built in zones (with the exception of empty zones) don't need
1487          * to be reloaded.
1488          */
1489         if (zone->type == dns_zone_master &&
1490             strcmp(zone->db_argv[0], "_builtin") == 0 &&
1491             (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1492             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1493                 result = ISC_R_SUCCESS;
1494                 goto cleanup;
1495         }
1496
1497         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
1498             rbt) {
1499                 if (zone->masterfile == NULL ||
1500                     !isc_file_exists(zone->masterfile)) {
1501                         if (zone->masterfile != NULL) {
1502                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1503                                              "no master file");
1504                         }
1505                         zone->refreshtime = now;
1506                         if (zone->task != NULL)
1507                                 zone_settimer(zone, &now);
1508                         result = ISC_R_SUCCESS;
1509                         goto cleanup;
1510                 }
1511         }
1512
1513         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1514
1515         result = dns_db_create(zone->mctx, zone->db_argv[0],
1516                                &zone->origin, (zone->type == dns_zone_stub) ?
1517                                dns_dbtype_stub : dns_dbtype_zone,
1518                                zone->rdclass,
1519                                zone->db_argc - 1, zone->db_argv + 1,
1520                                &db);
1521
1522         if (result != ISC_R_SUCCESS) {
1523                 dns_zone_log(zone, ISC_LOG_ERROR,
1524                              "loading zone: creating database: %s",
1525                              isc_result_totext(result));
1526                 goto cleanup;
1527         }
1528         dns_db_settask(db, zone->task);
1529
1530         if (! dns_db_ispersistent(db)) {
1531                 if (zone->masterfile != NULL) {
1532                         result = zone_startload(db, zone, loadtime);
1533                 } else {
1534                         result = DNS_R_NOMASTERFILE;
1535                         if (zone->type == dns_zone_master) {
1536                                 dns_zone_log(zone, ISC_LOG_ERROR,
1537                                              "loading zone: "
1538                                              "no master file configured");
1539                                 goto cleanup;
1540                         }
1541                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1542                                      "no master file configured: continuing");
1543                 }
1544         }
1545
1546         if (result == DNS_R_CONTINUE) {
1547                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1548                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1549                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1550                 goto cleanup;
1551         }
1552
1553         result = zone_postload(zone, db, loadtime, result);
1554
1555  cleanup:
1556         UNLOCK_ZONE(zone);
1557         if (db != NULL)
1558                 dns_db_detach(&db);
1559         return (result);
1560 }
1561
1562 isc_result_t
1563 dns_zone_load(dns_zone_t *zone) {
1564         return (zone_load(zone, 0));
1565 }
1566
1567 isc_result_t
1568 dns_zone_loadnew(dns_zone_t *zone) {
1569         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1570 }
1571
1572 isc_result_t
1573 dns_zone_loadandthaw(dns_zone_t *zone) {
1574         isc_result_t result;
1575
1576         result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1577         switch (result) {
1578         case DNS_R_CONTINUE:
1579                 /* Deferred thaw. */
1580                 break;
1581         case ISC_R_SUCCESS:
1582         case DNS_R_UPTODATE:
1583         case DNS_R_SEENINCLUDE:
1584                 zone->update_disabled = ISC_FALSE;
1585                 break;
1586         case DNS_R_NOMASTERFILE:
1587                 zone->update_disabled = ISC_FALSE;
1588                 break;
1589         default:
1590                 /* Error, remain in disabled state. */
1591                 break;
1592         }
1593         return (result);
1594 }
1595
1596 static unsigned int
1597 get_master_options(dns_zone_t *zone) {
1598         unsigned int options;
1599
1600         options = DNS_MASTER_ZONE;
1601         if (zone->type == dns_zone_slave)
1602                 options |= DNS_MASTER_SLAVE;
1603         if (zone->type == dns_zone_key)
1604                 options |= DNS_MASTER_KEY;
1605         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1606                 options |= DNS_MASTER_CHECKNS;
1607         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1608                 options |= DNS_MASTER_FATALNS;
1609         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1610                 options |= DNS_MASTER_CHECKNAMES;
1611         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1612                 options |= DNS_MASTER_CHECKNAMESFAIL;
1613         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1614                 options |= DNS_MASTER_CHECKMX;
1615         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1616                 options |= DNS_MASTER_CHECKMXFAIL;
1617         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1618                 options |= DNS_MASTER_CHECKWILDCARD;
1619         if (zone->type == dns_zone_master &&
1620             ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1621               zone->ssutable != NULL))
1622                 options |= DNS_MASTER_RESIGN;
1623         return (options);
1624 }
1625
1626 static void
1627 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1628         dns_load_t *load = event->ev_arg;
1629         isc_result_t result = ISC_R_SUCCESS;
1630         unsigned int options;
1631
1632         REQUIRE(DNS_LOAD_VALID(load));
1633
1634         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1635                 result = ISC_R_CANCELED;
1636         isc_event_free(&event);
1637         if (result == ISC_R_CANCELED)
1638                 goto fail;
1639
1640         options = get_master_options(load->zone);
1641
1642         result = dns_master_loadfileinc3(load->zone->masterfile,
1643                                          dns_db_origin(load->db),
1644                                          dns_db_origin(load->db),
1645                                          load->zone->rdclass,
1646                                          options,
1647                                          load->zone->sigresigninginterval,
1648                                          &load->callbacks, task,
1649                                          zone_loaddone, load,
1650                                          &load->zone->lctx, load->zone->mctx,
1651                                          load->zone->masterformat);
1652         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1653             result != DNS_R_SEENINCLUDE)
1654                 goto fail;
1655         return;
1656
1657  fail:
1658         zone_loaddone(load, result);
1659 }
1660
1661 static void
1662 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1663         const char me[] = "zone_gotwritehandle";
1664         dns_zone_t *zone = event->ev_arg;
1665         isc_result_t result = ISC_R_SUCCESS;
1666         dns_dbversion_t *version = NULL;
1667
1668         REQUIRE(DNS_ZONE_VALID(zone));
1669         INSIST(task == zone->task);
1670         ENTER;
1671
1672         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1673                 result = ISC_R_CANCELED;
1674         isc_event_free(&event);
1675         if (result == ISC_R_CANCELED)
1676                 goto fail;
1677
1678         LOCK_ZONE(zone);
1679         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1680         if (zone->db != NULL) {
1681                 dns_db_currentversion(zone->db, &version);
1682                 result = dns_master_dumpinc2(zone->mctx, zone->db, version,
1683                                              &dns_master_style_default,
1684                                              zone->masterfile, zone->task,
1685                                              dump_done, zone, &zone->dctx,
1686                                              zone->masterformat);
1687                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
1688         } else
1689                 result = ISC_R_CANCELED;
1690         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1691         UNLOCK_ZONE(zone);
1692         if (result != DNS_R_CONTINUE)
1693                 goto fail;
1694         return;
1695
1696  fail:
1697         dump_done(zone, result);
1698 }
1699
1700 static isc_result_t
1701 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1702         dns_load_t *load;
1703         isc_result_t result;
1704         isc_result_t tresult;
1705         unsigned int options;
1706
1707         options = get_master_options(zone);
1708
1709         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1710                 options |= DNS_MASTER_MANYERRORS;
1711
1712         if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1713                 load = isc_mem_get(zone->mctx, sizeof(*load));
1714                 if (load == NULL)
1715                         return (ISC_R_NOMEMORY);
1716
1717                 load->mctx = NULL;
1718                 load->zone = NULL;
1719                 load->db = NULL;
1720                 load->loadtime = loadtime;
1721                 load->magic = LOAD_MAGIC;
1722
1723                 isc_mem_attach(zone->mctx, &load->mctx);
1724                 zone_iattach(zone, &load->zone);
1725                 dns_db_attach(db, &load->db);
1726                 dns_rdatacallbacks_init(&load->callbacks);
1727                 result = dns_db_beginload(db, &load->callbacks.add,
1728                                           &load->callbacks.add_private);
1729                 if (result != ISC_R_SUCCESS)
1730                         goto cleanup;
1731                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1732                                        zone_gotreadhandle, load,
1733                                        &zone->readio);
1734                 if (result != ISC_R_SUCCESS) {
1735                         /*
1736                          * We can't report multiple errors so ignore
1737                          * the result of dns_db_endload().
1738                          */
1739                         (void)dns_db_endload(load->db,
1740                                              &load->callbacks.add_private);
1741                         goto cleanup;
1742                 } else
1743                         result = DNS_R_CONTINUE;
1744         } else {
1745                 dns_rdatacallbacks_t callbacks;
1746
1747                 dns_rdatacallbacks_init(&callbacks);
1748                 result = dns_db_beginload(db, &callbacks.add,
1749                                           &callbacks.add_private);
1750                 if (result != ISC_R_SUCCESS)
1751                         return (result);
1752                 result = dns_master_loadfile3(zone->masterfile, &zone->origin,
1753                                               &zone->origin, zone->rdclass,
1754                                               options, zone->sigresigninginterval,
1755                                               &callbacks, zone->mctx,
1756                                               zone->masterformat);
1757                 tresult = dns_db_endload(db, &callbacks.add_private);
1758                 if (result == ISC_R_SUCCESS)
1759                         result = tresult;
1760         }
1761
1762         return (result);
1763
1764  cleanup:
1765         load->magic = 0;
1766         dns_db_detach(&load->db);
1767         zone_idetach(&load->zone);
1768         isc_mem_detach(&load->mctx);
1769         isc_mem_put(zone->mctx, load, sizeof(*load));
1770         return (result);
1771 }
1772
1773 static isc_boolean_t
1774 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1775               dns_name_t *owner)
1776 {
1777         isc_result_t result;
1778         char ownerbuf[DNS_NAME_FORMATSIZE];
1779         char namebuf[DNS_NAME_FORMATSIZE];
1780         char altbuf[DNS_NAME_FORMATSIZE];
1781         dns_fixedname_t fixed;
1782         dns_name_t *foundname;
1783         int level;
1784
1785         /*
1786          * "." means the services does not exist.
1787          */
1788         if (dns_name_equal(name, dns_rootname))
1789                 return (ISC_TRUE);
1790
1791         /*
1792          * Outside of zone.
1793          */
1794         if (!dns_name_issubdomain(name, &zone->origin)) {
1795                 if (zone->checkmx != NULL)
1796                         return ((zone->checkmx)(zone, name, owner));
1797                 return (ISC_TRUE);
1798         }
1799
1800         if (zone->type == dns_zone_master)
1801                 level = ISC_LOG_ERROR;
1802         else
1803                 level = ISC_LOG_WARNING;
1804
1805         dns_fixedname_init(&fixed);
1806         foundname = dns_fixedname_name(&fixed);
1807
1808         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1809                              0, 0, NULL, foundname, NULL, NULL);
1810         if (result == ISC_R_SUCCESS)
1811                 return (ISC_TRUE);
1812
1813         if (result == DNS_R_NXRRSET) {
1814                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1815                                      0, 0, NULL, foundname, NULL, NULL);
1816                 if (result == ISC_R_SUCCESS)
1817                         return (ISC_TRUE);
1818         }
1819
1820         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1821         dns_name_format(name, namebuf, sizeof namebuf);
1822         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1823             result == DNS_R_EMPTYNAME) {
1824                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1825                         level = ISC_LOG_WARNING;
1826                 dns_zone_log(zone, level,
1827                              "%s/MX '%s' has no address records (A or AAAA)",
1828                              ownerbuf, namebuf);
1829                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1830         }
1831
1832         if (result == DNS_R_CNAME) {
1833                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1834                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1835                         level = ISC_LOG_WARNING;
1836                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1837                         dns_zone_log(zone, level,
1838                                      "%s/MX '%s' is a CNAME (illegal)",
1839                                      ownerbuf, namebuf);
1840                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1841         }
1842
1843         if (result == DNS_R_DNAME) {
1844                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1845                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1846                         level = ISC_LOG_WARNING;
1847                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
1848                         dns_name_format(foundname, altbuf, sizeof altbuf);
1849                         dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
1850                                      " '%s' (illegal)", ownerbuf, namebuf,
1851                                      altbuf);
1852                 }
1853                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1854         }
1855
1856         if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
1857                 return ((zone->checkmx)(zone, name, owner));
1858
1859         return (ISC_TRUE);
1860 }
1861
1862 static isc_boolean_t
1863 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1864                dns_name_t *owner)
1865 {
1866         isc_result_t result;
1867         char ownerbuf[DNS_NAME_FORMATSIZE];
1868         char namebuf[DNS_NAME_FORMATSIZE];
1869         char altbuf[DNS_NAME_FORMATSIZE];
1870         dns_fixedname_t fixed;
1871         dns_name_t *foundname;
1872         int level;
1873
1874         /*
1875          * "." means the services does not exist.
1876          */
1877         if (dns_name_equal(name, dns_rootname))
1878                 return (ISC_TRUE);
1879
1880         /*
1881          * Outside of zone.
1882          */
1883         if (!dns_name_issubdomain(name, &zone->origin)) {
1884                 if (zone->checksrv != NULL)
1885                         return ((zone->checksrv)(zone, name, owner));
1886                 return (ISC_TRUE);
1887         }
1888
1889         if (zone->type == dns_zone_master)
1890                 level = ISC_LOG_ERROR;
1891         else
1892                 level = ISC_LOG_WARNING;
1893
1894         dns_fixedname_init(&fixed);
1895         foundname = dns_fixedname_name(&fixed);
1896
1897         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1898                              0, 0, NULL, foundname, NULL, NULL);
1899         if (result == ISC_R_SUCCESS)
1900                 return (ISC_TRUE);
1901
1902         if (result == DNS_R_NXRRSET) {
1903                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1904                                      0, 0, NULL, foundname, NULL, NULL);
1905                 if (result == ISC_R_SUCCESS)
1906                         return (ISC_TRUE);
1907         }
1908
1909         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1910         dns_name_format(name, namebuf, sizeof namebuf);
1911         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1912             result == DNS_R_EMPTYNAME) {
1913                 dns_zone_log(zone, level,
1914                              "%s/SRV '%s' has no address records (A or AAAA)",
1915                              ownerbuf, namebuf);
1916                 /* XXX950 make fatal for 9.5.0. */
1917                 return (ISC_TRUE);
1918         }
1919
1920         if (result == DNS_R_CNAME) {
1921                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1922                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1923                         level = ISC_LOG_WARNING;
1924                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1925                         dns_zone_log(zone, level,
1926                                      "%s/SRV '%s' is a CNAME (illegal)",
1927                                      ownerbuf, namebuf);
1928                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1929         }
1930
1931         if (result == DNS_R_DNAME) {
1932                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1933                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1934                         level = ISC_LOG_WARNING;
1935                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
1936                         dns_name_format(foundname, altbuf, sizeof altbuf);
1937                         dns_zone_log(zone, level, "%s/SRV '%s' is below a "
1938                                      "DNAME '%s' (illegal)", ownerbuf, namebuf,
1939                                      altbuf);
1940                 }
1941                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1942         }
1943
1944         if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
1945                 return ((zone->checksrv)(zone, name, owner));
1946
1947         return (ISC_TRUE);
1948 }
1949
1950 static isc_boolean_t
1951 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1952                 dns_name_t *owner)
1953 {
1954         isc_boolean_t answer = ISC_TRUE;
1955         isc_result_t result, tresult;
1956         char ownerbuf[DNS_NAME_FORMATSIZE];
1957         char namebuf[DNS_NAME_FORMATSIZE];
1958         char altbuf[DNS_NAME_FORMATSIZE];
1959         dns_fixedname_t fixed;
1960         dns_name_t *foundname;
1961         dns_rdataset_t a;
1962         dns_rdataset_t aaaa;
1963         int level;
1964
1965         /*
1966          * Outside of zone.
1967          */
1968         if (!dns_name_issubdomain(name, &zone->origin)) {
1969                 if (zone->checkns != NULL)
1970                         return ((zone->checkns)(zone, name, owner, NULL, NULL));
1971                 return (ISC_TRUE);
1972         }
1973
1974         if (zone->type == dns_zone_master)
1975                 level = ISC_LOG_ERROR;
1976         else
1977                 level = ISC_LOG_WARNING;
1978
1979         dns_fixedname_init(&fixed);
1980         foundname = dns_fixedname_name(&fixed);
1981         dns_rdataset_init(&a);
1982         dns_rdataset_init(&aaaa);
1983
1984         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1985                              DNS_DBFIND_GLUEOK, 0, NULL,
1986                              foundname, &a, NULL);
1987
1988         if (result == ISC_R_SUCCESS) {
1989                 dns_rdataset_disassociate(&a);
1990                 return (ISC_TRUE);
1991         } else if (result == DNS_R_DELEGATION)
1992                 dns_rdataset_disassociate(&a);
1993
1994         if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
1995             result == DNS_R_GLUE) {
1996                 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1997                                      DNS_DBFIND_GLUEOK, 0, NULL,
1998                                      foundname, &aaaa, NULL);
1999                 if (tresult == ISC_R_SUCCESS) {
2000                         dns_rdataset_disassociate(&aaaa);
2001                         return (ISC_TRUE);
2002                 }
2003                 if (tresult == DNS_R_DELEGATION)
2004                         dns_rdataset_disassociate(&aaaa);
2005                 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2006                         /*
2007                          * Check glue against child zone.
2008                          */
2009                         if (zone->checkns != NULL)
2010                                 answer = (zone->checkns)(zone, name, owner,
2011                                                          &a, &aaaa);
2012                         if (dns_rdataset_isassociated(&a))
2013                                 dns_rdataset_disassociate(&a);
2014                         if (dns_rdataset_isassociated(&aaaa))
2015                                 dns_rdataset_disassociate(&aaaa);
2016                         return (answer);
2017                 }
2018         }
2019
2020         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2021         dns_name_format(name, namebuf, sizeof namebuf);
2022         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2023             result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2024                 const char *what;
2025                 isc_boolean_t required = ISC_FALSE;
2026                 if (dns_name_issubdomain(name, owner)) {
2027                         what = "REQUIRED GLUE ";
2028                         required = ISC_TRUE;
2029                  } else if (result == DNS_R_DELEGATION)
2030                         what = "SIBLING GLUE ";
2031                 else
2032                         what = "";
2033
2034                 if (result != DNS_R_DELEGATION || required ||
2035                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2036                         dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2037                                      "address records (A or AAAA)",
2038                                      ownerbuf, namebuf, what);
2039                         /*
2040                          * Log missing address record.
2041                          */
2042                         if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2043                                 (void)(zone->checkns)(zone, name, owner,
2044                                                       &a, &aaaa);
2045                         /* XXX950 make fatal for 9.5.0. */
2046                         /* answer = ISC_FALSE; */
2047                 }
2048         } else if (result == DNS_R_CNAME) {
2049                 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2050                              ownerbuf, namebuf);
2051                 /* XXX950 make fatal for 9.5.0. */
2052                 /* answer = ISC_FALSE; */
2053         } else if (result == DNS_R_DNAME) {
2054                 dns_name_format(foundname, altbuf, sizeof altbuf);
2055                 dns_zone_log(zone, level,
2056                              "%s/NS '%s' is below a DNAME '%s' (illegal)",
2057                              ownerbuf, namebuf, altbuf);
2058                 /* XXX950 make fatal for 9.5.0. */
2059                 /* answer = ISC_FALSE; */
2060         }
2061
2062         if (dns_rdataset_isassociated(&a))
2063                 dns_rdataset_disassociate(&a);
2064         if (dns_rdataset_isassociated(&aaaa))
2065                 dns_rdataset_disassociate(&aaaa);
2066         return (answer);
2067 }
2068
2069 static isc_boolean_t
2070 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2071                      dns_rdataset_t *rdataset)
2072 {
2073         dns_rdataset_t tmprdataset;
2074         isc_result_t result;
2075         isc_boolean_t answer = ISC_TRUE;
2076         isc_boolean_t format = ISC_TRUE;
2077         int level = ISC_LOG_WARNING;
2078         char ownerbuf[DNS_NAME_FORMATSIZE];
2079         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2080         unsigned int count1 = 0;
2081
2082         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2083                 level = ISC_LOG_ERROR;
2084
2085         dns_rdataset_init(&tmprdataset);
2086         for (result = dns_rdataset_first(rdataset);
2087              result == ISC_R_SUCCESS;
2088              result = dns_rdataset_next(rdataset)) {
2089                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2090                 unsigned int count2 = 0;
2091
2092                 count1++;
2093                 dns_rdataset_current(rdataset, &rdata1);
2094                 dns_rdataset_clone(rdataset, &tmprdataset);
2095                 for (result = dns_rdataset_first(&tmprdataset);
2096                      result == ISC_R_SUCCESS;
2097                      result = dns_rdataset_next(&tmprdataset)) {
2098                         dns_rdata_t rdata2 = DNS_RDATA_INIT;
2099                         count2++;
2100                         if (count1 >= count2)
2101                                 continue;
2102                         dns_rdataset_current(&tmprdataset, &rdata2);
2103                         if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2104                                 if (format) {
2105                                         dns_name_format(owner, ownerbuf,
2106                                                         sizeof ownerbuf);
2107                                         dns_rdatatype_format(rdata1.type,
2108                                                              typebuf,
2109                                                              sizeof(typebuf));
2110                                         format = ISC_FALSE;
2111                                 }
2112                                 dns_zone_log(zone, level, "%s/%s has "
2113                                              "semantically identical records",
2114                                              ownerbuf, typebuf);
2115                                 if (level == ISC_LOG_ERROR)
2116                                         answer = ISC_FALSE;
2117                                 break;
2118                         }
2119                 }
2120                 dns_rdataset_disassociate(&tmprdataset);
2121                 if (!format)
2122                         break;
2123         }
2124         return (answer);
2125 }
2126
2127 static isc_boolean_t
2128 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2129         dns_dbiterator_t *dbiterator = NULL;
2130         dns_dbnode_t *node = NULL;
2131         dns_fixedname_t fixed;
2132         dns_name_t *name;
2133         dns_rdataset_t rdataset;
2134         dns_rdatasetiter_t *rdsit = NULL;
2135         isc_boolean_t ok = ISC_TRUE;
2136         isc_result_t result;
2137
2138         dns_fixedname_init(&fixed);
2139         name = dns_fixedname_name(&fixed);
2140         dns_rdataset_init(&rdataset);
2141
2142         result = dns_db_createiterator(db, 0, &dbiterator);
2143         if (result != ISC_R_SUCCESS)
2144                 return (ISC_TRUE);
2145
2146         for (result = dns_dbiterator_first(dbiterator);
2147              result == ISC_R_SUCCESS;
2148              result = dns_dbiterator_next(dbiterator)) {
2149                 result = dns_dbiterator_current(dbiterator, &node, name);
2150                 if (result != ISC_R_SUCCESS)
2151                         continue;
2152
2153                 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2154                 if (result != ISC_R_SUCCESS)
2155                         continue;
2156
2157                 for (result = dns_rdatasetiter_first(rdsit);
2158                      result == ISC_R_SUCCESS;
2159                      result = dns_rdatasetiter_next(rdsit)) {
2160                         dns_rdatasetiter_current(rdsit, &rdataset);
2161                         if (!zone_rrset_check_dup(zone, name, &rdataset))
2162                                 ok = ISC_FALSE;
2163                         dns_rdataset_disassociate(&rdataset);
2164                 }
2165                 dns_rdatasetiter_destroy(&rdsit);
2166                 dns_db_detachnode(db, &node);
2167         }
2168
2169         if (node != NULL)
2170                 dns_db_detachnode(db, &node);
2171         dns_dbiterator_destroy(&dbiterator);
2172
2173         return (ok);
2174 }
2175
2176 static isc_boolean_t
2177 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2178         dns_dbiterator_t *dbiterator = NULL;
2179         dns_dbnode_t *node = NULL;
2180         dns_rdataset_t rdataset;
2181         dns_fixedname_t fixed;
2182         dns_fixedname_t fixedbottom;
2183         dns_rdata_mx_t mx;
2184         dns_rdata_ns_t ns;
2185         dns_rdata_in_srv_t srv;
2186         dns_rdata_t rdata;
2187         dns_name_t *name;
2188         dns_name_t *bottom;
2189         isc_result_t result;
2190         isc_boolean_t ok = ISC_TRUE;
2191
2192         dns_fixedname_init(&fixed);
2193         name = dns_fixedname_name(&fixed);
2194         dns_fixedname_init(&fixedbottom);
2195         bottom = dns_fixedname_name(&fixedbottom);
2196         dns_rdataset_init(&rdataset);
2197         dns_rdata_init(&rdata);
2198
2199         result = dns_db_createiterator(db, 0, &dbiterator);
2200         if (result != ISC_R_SUCCESS)
2201                 return (ISC_TRUE);
2202
2203         result = dns_dbiterator_first(dbiterator);
2204         while (result == ISC_R_SUCCESS) {
2205                 result = dns_dbiterator_current(dbiterator, &node, name);
2206                 if (result != ISC_R_SUCCESS)
2207                         goto cleanup;
2208
2209                 /*
2210                  * Is this name visible in the zone?
2211                  */
2212                 if (!dns_name_issubdomain(name, &zone->origin) ||
2213                     (dns_name_countlabels(bottom) > 0 &&
2214                      dns_name_issubdomain(name, bottom)))
2215                         goto next;
2216
2217                 /*
2218                  * Don't check the NS records at the origin.
2219                  */
2220                 if (dns_name_equal(name, &zone->origin))
2221                         goto checkmx;
2222
2223                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2224                                              0, 0, &rdataset, NULL);
2225                 if (result != ISC_R_SUCCESS)
2226                         goto checkmx;
2227                 /*
2228                  * Remember bottom of zone.
2229                  */
2230                 dns_name_copy(name, bottom, NULL);
2231
2232                 result = dns_rdataset_first(&rdataset);
2233                 while (result == ISC_R_SUCCESS) {
2234                         dns_rdataset_current(&rdataset, &rdata);
2235                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
2236                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2237                         if (!zone_check_glue(zone, db, &ns.name, name))
2238                                 ok = ISC_FALSE;
2239                         dns_rdata_reset(&rdata);
2240                         result = dns_rdataset_next(&rdataset);
2241                 }
2242                 dns_rdataset_disassociate(&rdataset);
2243                 goto next;
2244
2245  checkmx:
2246                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2247                                              0, 0, &rdataset, NULL);
2248                 if (result != ISC_R_SUCCESS)
2249                         goto checksrv;
2250                 result = dns_rdataset_first(&rdataset);
2251                 while (result == ISC_R_SUCCESS) {
2252                         dns_rdataset_current(&rdataset, &rdata);
2253                         result = dns_rdata_tostruct(&rdata, &mx, NULL);
2254                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2255                         if (!zone_check_mx(zone, db, &mx.mx, name))
2256                                 ok = ISC_FALSE;
2257                         dns_rdata_reset(&rdata);
2258                         result = dns_rdataset_next(&rdataset);
2259                 }
2260                 dns_rdataset_disassociate(&rdataset);
2261
2262  checksrv:
2263                 if (zone->rdclass != dns_rdataclass_in)
2264                         goto next;
2265                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2266                                              0, 0, &rdataset, NULL);
2267                 if (result != ISC_R_SUCCESS)
2268                         goto next;
2269                 result = dns_rdataset_first(&rdataset);
2270                 while (result == ISC_R_SUCCESS) {
2271                         dns_rdataset_current(&rdataset, &rdata);
2272                         result = dns_rdata_tostruct(&rdata, &srv, NULL);
2273                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2274                         if (!zone_check_srv(zone, db, &srv.target, name))
2275                                 ok = ISC_FALSE;
2276                         dns_rdata_reset(&rdata);
2277                         result = dns_rdataset_next(&rdataset);
2278                 }
2279                 dns_rdataset_disassociate(&rdataset);
2280
2281  next:
2282                 dns_db_detachnode(db, &node);
2283                 result = dns_dbiterator_next(dbiterator);
2284         }
2285
2286  cleanup:
2287         if (node != NULL)
2288                 dns_db_detachnode(db, &node);
2289         dns_dbiterator_destroy(&dbiterator);
2290
2291         return (ok);
2292 }
2293
2294 /*
2295  * OpenSSL verification of RSA keys with exponent 3 is known to be
2296  * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
2297  * if they are in use.
2298  */
2299 static void
2300 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2301         dns_dbnode_t *node = NULL;
2302         dns_dbversion_t *version = NULL;
2303         dns_rdata_dnskey_t dnskey;
2304         dns_rdata_t rdata = DNS_RDATA_INIT;
2305         dns_rdataset_t rdataset;
2306         isc_result_t result;
2307         isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2308         const char *algorithm;
2309
2310         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2311         if (result != ISC_R_SUCCESS)
2312                 goto cleanup;
2313
2314         dns_db_currentversion(db, &version);
2315         dns_rdataset_init(&rdataset);
2316         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2317                                      dns_rdatatype_none, 0, &rdataset, NULL);
2318         if (result != ISC_R_SUCCESS)
2319                 goto cleanup;
2320
2321         for (result = dns_rdataset_first(&rdataset);
2322              result == ISC_R_SUCCESS;
2323              result = dns_rdataset_next(&rdataset))
2324         {
2325                 dns_rdataset_current(&rdataset, &rdata);
2326                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2327                 INSIST(result == ISC_R_SUCCESS);
2328
2329                 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2330                      dnskey.algorithm == DST_ALG_RSAMD5) &&
2331                      dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2332                      dnskey.data[1] == 3)
2333                 {
2334                         if (dnskey.algorithm == DST_ALG_RSASHA1) {
2335                                 logit = !foundrsa;
2336                                 foundrsa = ISC_TRUE;
2337                                 algorithm = "RSASHA1";
2338                         } else {
2339                                 logit = !foundmd5;
2340                                 foundmd5 = ISC_TRUE;
2341                                 algorithm = "RSAMD5";
2342                         }
2343                         if (logit)
2344                                 dns_zone_log(zone, ISC_LOG_WARNING,
2345                                              "weak %s (%u) key found "
2346                                              "(exponent=3)", algorithm,
2347                                              dnskey.algorithm);
2348                         if (foundrsa && foundmd5)
2349                                 break;
2350                 }
2351                 dns_rdata_reset(&rdata);
2352         }
2353         dns_rdataset_disassociate(&rdataset);
2354
2355  cleanup:
2356         if (node != NULL)
2357                 dns_db_detachnode(db, &node);
2358         if (version != NULL)
2359                 dns_db_closeversion(db, &version, ISC_FALSE);
2360 }
2361
2362 static void
2363 resume_signingwithkey(dns_zone_t *zone) {
2364         dns_dbnode_t *node = NULL;
2365         dns_dbversion_t *version = NULL;
2366         dns_rdata_t rdata = DNS_RDATA_INIT;
2367         dns_rdataset_t rdataset;
2368         isc_result_t result;
2369
2370         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2371         if (result != ISC_R_SUCCESS)
2372                 goto cleanup;
2373
2374         dns_db_currentversion(zone->db, &version);
2375         dns_rdataset_init(&rdataset);
2376         result = dns_db_findrdataset(zone->db, node, version,
2377                                      zone->privatetype,
2378                                      dns_rdatatype_none, 0,
2379                                      &rdataset, NULL);
2380         if (result != ISC_R_SUCCESS) {
2381                 INSIST(!dns_rdataset_isassociated(&rdataset));
2382                 goto cleanup;
2383         }
2384
2385         for (result = dns_rdataset_first(&rdataset);
2386              result == ISC_R_SUCCESS;
2387              result = dns_rdataset_next(&rdataset))
2388         {
2389                 dns_rdataset_current(&rdataset, &rdata);
2390                 if (rdata.length != 5 ||
2391                     rdata.data[0] == 0 || rdata.data[4] != 0) {
2392                         dns_rdata_reset(&rdata);
2393                         continue;
2394                 }
2395
2396                 result = zone_signwithkey(zone, rdata.data[0],
2397                                           (rdata.data[1] << 8) | rdata.data[2],
2398                                           ISC_TF(rdata.data[3]));
2399                 if (result != ISC_R_SUCCESS) {
2400                         dns_zone_log(zone, ISC_LOG_ERROR,
2401                                      "zone_signwithkey failed: %s",
2402                                      dns_result_totext(result));
2403                 }
2404                 dns_rdata_reset(&rdata);
2405         }
2406         dns_rdataset_disassociate(&rdataset);
2407
2408  cleanup:
2409         if (node != NULL)
2410                 dns_db_detachnode(zone->db, &node);
2411         if (version != NULL)
2412                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2413 }
2414
2415 static isc_result_t
2416 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2417         dns_nsec3chain_t *nsec3chain, *current;
2418         isc_result_t result;
2419         isc_time_t now;
2420         unsigned int options = 0;
2421         char saltbuf[255*2+1];
2422         char flags[sizeof("REMOVE|CREATE|NONSEC|OPTOUT")];
2423         int i;
2424
2425         nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2426         if (nsec3chain == NULL)
2427                 return (ISC_R_NOMEMORY);
2428
2429         nsec3chain->magic = 0;
2430         nsec3chain->done = ISC_FALSE;
2431         nsec3chain->db = NULL;
2432         nsec3chain->dbiterator = NULL;
2433         nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2434         nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2435         nsec3chain->nsec3param.hash = nsec3param->hash;
2436         nsec3chain->nsec3param.iterations = nsec3param->iterations;
2437         nsec3chain->nsec3param.flags = nsec3param->flags;
2438         nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2439         memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2440         nsec3chain->nsec3param.salt = nsec3chain->salt;
2441         nsec3chain->seen_nsec = ISC_FALSE;
2442         nsec3chain->delete_nsec = ISC_FALSE;
2443         nsec3chain->save_delete_nsec = ISC_FALSE;
2444
2445         if (nsec3param->flags == 0)
2446                 strlcpy(flags, "NONE", sizeof(flags));
2447         else {
2448                 flags[0] = '\0';
2449                 if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2450                         strlcat(flags, "REMOVE", sizeof(flags));
2451                 if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2452                         if (flags[0] == '\0')
2453                                 strlcpy(flags, "CREATE", sizeof(flags));
2454                         else
2455                                 strlcat(flags, "|CREATE", sizeof(flags));
2456                 }
2457                 if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2458                         if (flags[0] == '\0')
2459                                 strlcpy(flags, "NONSEC", sizeof(flags));
2460                         else
2461                                 strlcat(flags, "|NONSEC", sizeof(flags));
2462                 }
2463                 if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2464                         if (flags[0] == '\0')
2465                                 strlcpy(flags, "OPTOUT", sizeof(flags));
2466                         else
2467                                 strlcat(flags, "|OPTOUT", sizeof(flags));
2468                 }
2469         }
2470         if (nsec3param->salt_length == 0)
2471                 strlcpy(saltbuf, "-", sizeof(saltbuf));
2472         else
2473                 for (i = 0; i < nsec3param->salt_length; i++)
2474                         sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2475         dns_zone_log(zone, ISC_LOG_INFO,
2476                      "zone_addnsec3chain(%u,%s,%u,%s)",
2477                       nsec3param->hash, flags, nsec3param->iterations,
2478                       saltbuf);
2479         for (current = ISC_LIST_HEAD(zone->nsec3chain);
2480              current != NULL;
2481              current = ISC_LIST_NEXT(current, link)) {
2482                 if (current->db == zone->db &&
2483                     current->nsec3param.hash == nsec3param->hash &&
2484                     current->nsec3param.iterations == nsec3param->iterations &&
2485                     current->nsec3param.salt_length == nsec3param->salt_length
2486                     && !memcmp(current->nsec3param.salt, nsec3param->salt,
2487                                nsec3param->salt_length))
2488                         current->done = ISC_TRUE;
2489         }
2490
2491         if (zone->db != NULL) {
2492                 dns_db_attach(zone->db, &nsec3chain->db);
2493                 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2494                         options = DNS_DB_NONSEC3;
2495                 result = dns_db_createiterator(nsec3chain->db, options,
2496                                                &nsec3chain->dbiterator);
2497                 if (result == ISC_R_SUCCESS)
2498                         dns_dbiterator_first(nsec3chain->dbiterator);
2499                 if (result == ISC_R_SUCCESS) {
2500                         dns_dbiterator_pause(nsec3chain->dbiterator);
2501                         ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2502                                                nsec3chain, link);
2503                         nsec3chain = NULL;
2504                         if (isc_time_isepoch(&zone->nsec3chaintime)) {
2505                                 TIME_NOW(&now);
2506                                 zone->nsec3chaintime = now;
2507                                 if (zone->task != NULL)
2508                                         zone_settimer(zone, &now);
2509                         }
2510                 }
2511         } else
2512                 result = ISC_R_NOTFOUND;
2513
2514         if (nsec3chain != NULL) {
2515                 if (nsec3chain->db != NULL)
2516                         dns_db_detach(&nsec3chain->db);
2517                 if (nsec3chain->dbiterator != NULL)
2518                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
2519                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2520         }
2521         return (result);
2522 }
2523
2524 static void
2525 resume_addnsec3chain(dns_zone_t *zone) {
2526         dns_dbnode_t *node = NULL;
2527         dns_dbversion_t *version = NULL;
2528         dns_rdataset_t rdataset;
2529         isc_result_t result;
2530         dns_rdata_nsec3param_t nsec3param;
2531
2532         if (zone->privatetype == 0)
2533                 return;
2534
2535         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2536         if (result != ISC_R_SUCCESS)
2537                 goto cleanup;
2538
2539         dns_db_currentversion(zone->db, &version);
2540         dns_rdataset_init(&rdataset);
2541         result = dns_db_findrdataset(zone->db, node, version,
2542                                      zone->privatetype, dns_rdatatype_none,
2543                                      0, &rdataset, NULL);
2544         if (result != ISC_R_SUCCESS) {
2545                 INSIST(!dns_rdataset_isassociated(&rdataset));
2546                 goto cleanup;
2547         }
2548
2549         for (result = dns_rdataset_first(&rdataset);
2550              result == ISC_R_SUCCESS;
2551              result = dns_rdataset_next(&rdataset))
2552         {
2553                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
2554                 dns_rdata_t rdata = DNS_RDATA_INIT;
2555                 dns_rdata_t private = DNS_RDATA_INIT;
2556
2557                 dns_rdataset_current(&rdataset, &private);
2558                 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
2559                                                 sizeof(buf)))
2560                         continue;
2561                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2562                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2563                 if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 ||
2564                     (nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
2565                         result = zone_addnsec3chain(zone, &nsec3param);
2566                         if (result != ISC_R_SUCCESS) {
2567                                 dns_zone_log(zone, ISC_LOG_ERROR,
2568                                              "zone_addnsec3chain failed: %s",
2569                                              dns_result_totext(result));
2570                         }
2571                 }
2572         }
2573         dns_rdataset_disassociate(&rdataset);
2574  cleanup:
2575         if (node != NULL)
2576                 dns_db_detachnode(zone->db, &node);
2577         if (version != NULL)
2578                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2579 }
2580
2581 static void
2582 set_resigntime(dns_zone_t *zone) {
2583         dns_rdataset_t rdataset;
2584         dns_fixedname_t fixed;
2585         unsigned int resign;
2586         isc_result_t result;
2587         isc_uint32_t nanosecs;
2588
2589         dns_rdataset_init(&rdataset);
2590         dns_fixedname_init(&fixed);
2591         result = dns_db_getsigningtime(zone->db, &rdataset,
2592                                        dns_fixedname_name(&fixed));
2593         if (result != ISC_R_SUCCESS) {
2594                 isc_time_settoepoch(&zone->resigntime);
2595                 return;
2596         }
2597         resign = rdataset.resign;
2598         dns_rdataset_disassociate(&rdataset);
2599         isc_random_get(&nanosecs);
2600         nanosecs %= 1000000000;
2601         isc_time_set(&zone->resigntime, resign, nanosecs);
2602 }
2603
2604 static isc_result_t
2605 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
2606         dns_dbnode_t *node = NULL;
2607         dns_rdataset_t rdataset;
2608         dns_dbversion_t *version = NULL;
2609         dns_rdata_nsec3param_t nsec3param;
2610         isc_boolean_t ok = ISC_FALSE;
2611         isc_result_t result;
2612         dns_rdata_t rdata = DNS_RDATA_INIT;
2613         isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
2614                                 zone_isdynamic(zone) : ISC_FALSE;
2615
2616         dns_rdataset_init(&rdataset);
2617         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2618         if (result != ISC_R_SUCCESS) {
2619                 dns_zone_log(zone, ISC_LOG_ERROR,
2620                              "nsec3param lookup failure: %s",
2621                              dns_result_totext(result));
2622                 return (result);
2623         }
2624         dns_db_currentversion(db, &version);
2625
2626         result = dns_db_findrdataset(db, node, version,
2627                                      dns_rdatatype_nsec3param,
2628                                      dns_rdatatype_none, 0, &rdataset, NULL);
2629         if (result == ISC_R_NOTFOUND) {
2630                 INSIST(!dns_rdataset_isassociated(&rdataset));
2631                 result = ISC_R_SUCCESS;
2632                 goto cleanup;
2633         }
2634         if (result != ISC_R_SUCCESS) {
2635                 INSIST(!dns_rdataset_isassociated(&rdataset));
2636                 dns_zone_log(zone, ISC_LOG_ERROR,
2637                              "nsec3param lookup failure: %s",
2638                              dns_result_totext(result));
2639                 goto cleanup;
2640         }
2641
2642         /*
2643          * For dynamic zones we must support every algorithm so we can
2644          * regenerate all the NSEC3 chains.
2645          * For non-dynamic zones we only need to find a supported algorithm.
2646          */
2647         for (result = dns_rdataset_first(&rdataset);
2648              result == ISC_R_SUCCESS;
2649              result = dns_rdataset_next(&rdataset))
2650         {
2651                 dns_rdataset_current(&rdataset, &rdata);
2652                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2653                 dns_rdata_reset(&rdata);
2654                 INSIST(result == ISC_R_SUCCESS);
2655                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
2656                     nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
2657                 {
2658                         dns_zone_log(zone, ISC_LOG_WARNING,
2659                              "nsec3 test \"unknown\" hash algorithm found: %u",
2660                                      nsec3param.hash);
2661                         ok = ISC_TRUE;
2662                 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
2663                         if (dynamic) {
2664                                 dns_zone_log(zone, ISC_LOG_ERROR,
2665                                              "unsupported nsec3 hash algorithm"
2666                                              " in dynamic zone: %u",
2667                                              nsec3param.hash);
2668                                 result = DNS_R_BADZONE;
2669                                 /* Stop second error message. */
2670                                 ok = ISC_TRUE;
2671                                 break;
2672                         } else
2673                                 dns_zone_log(zone, ISC_LOG_WARNING,
2674                                      "unsupported nsec3 hash algorithm: %u",
2675                                              nsec3param.hash);
2676                 } else
2677                         ok = ISC_TRUE;
2678         }
2679         if (result == ISC_R_NOMORE)
2680                 result = ISC_R_SUCCESS;
2681
2682         if (!ok) {
2683                 result = DNS_R_BADZONE;
2684                 dns_zone_log(zone, ISC_LOG_ERROR,
2685                              "no supported nsec3 hash algorithm");
2686         }
2687
2688  cleanup:
2689         if (dns_rdataset_isassociated(&rdataset))
2690                 dns_rdataset_disassociate(&rdataset);
2691         dns_db_closeversion(db, &version, ISC_FALSE);
2692         dns_db_detachnode(db, &node);
2693         return (result);
2694 }
2695
2696 /*
2697  * Set the timer for refreshing the key zone to the soonest future time
2698  * of the set (current timer, keydata->refresh, keydata->addhd,
2699  * keydata->removehd).
2700  */
2701 static void
2702 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
2703                     isc_stdtime_t now)
2704 {
2705         const char me[] = "set_refreshkeytimer";
2706         isc_stdtime_t then;
2707         isc_time_t timenow, timethen;
2708         char timebuf[80];
2709
2710         ENTER;
2711         then = key->refresh;
2712         if (key->addhd > now && key->addhd < then)
2713                 then = key->addhd;
2714         if (key->removehd > now && key->removehd < then)
2715                 then = key->removehd;
2716
2717         TIME_NOW(&timenow);
2718         if (then > now)
2719                 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
2720         else
2721                 timethen = timenow;
2722         if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
2723             isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
2724                 zone->refreshkeytime = timethen;
2725
2726         isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
2727         dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
2728         zone_settimer(zone, &timenow);
2729 }
2730
2731 /*
2732  * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
2733  * If the key zone is changed, set '*changed' to ISC_TRUE.
2734  */
2735 static isc_result_t
2736 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
2737                dns_diff_t *diff, dns_keytable_t *keytable,
2738                dns_keynode_t **keynodep, isc_boolean_t *changed)
2739 {
2740         const char me[] = "create_keydata";
2741         isc_result_t result = ISC_R_SUCCESS;
2742         isc_buffer_t keyb, dstb;
2743         unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
2744         dns_rdata_keydata_t keydata;
2745         dns_rdata_dnskey_t dnskey;
2746         dns_rdata_t rdata = DNS_RDATA_INIT;
2747         dns_keynode_t *keynode;
2748         isc_stdtime_t now;
2749         isc_region_t r;
2750         dst_key_t *key;
2751
2752         REQUIRE(keynodep != NULL);
2753         keynode = *keynodep;
2754
2755         ENTER;
2756         isc_stdtime_get(&now);
2757
2758         /* Loop in case there's more than one key. */
2759         while (result == ISC_R_SUCCESS) {
2760                 dns_keynode_t *nextnode = NULL;
2761
2762                 key = dns_keynode_key(keynode);
2763                 if (key == NULL)
2764                         goto skip;
2765
2766                 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
2767                 CHECK(dst_key_todns(key, &dstb));
2768
2769                 /* Convert DST key to DNSKEY. */
2770                 dns_rdata_reset(&rdata);
2771                 isc_buffer_usedregion(&dstb, &r);
2772                 dns_rdata_fromregion(&rdata, dst_key_class(key),
2773                                      dns_rdatatype_dnskey, &r);
2774
2775                 /* DSTKEY to KEYDATA. */
2776                 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
2777                 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
2778                                              NULL));
2779
2780                 /* KEYDATA to rdata. */
2781                 dns_rdata_reset(&rdata);
2782                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
2783                 CHECK(dns_rdata_fromstruct(&rdata,
2784                                            zone->rdclass, dns_rdatatype_keydata,
2785                                            &keydata, &keyb));
2786
2787                 /* Add rdata to zone. */
2788                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
2789                                     dst_key_name(key), 0, &rdata));
2790                 *changed = ISC_TRUE;
2791
2792  skip:
2793                 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
2794                 if (result != ISC_R_NOTFOUND) {
2795                         dns_keytable_detachkeynode(keytable, &keynode);
2796                         keynode = nextnode;
2797                 }
2798         }
2799
2800         /* Refresh new keys from the zone apex as soon as possible. */
2801         if (*changed)
2802                 set_refreshkeytimer(zone, &keydata, now);
2803
2804         if (keynode != NULL)
2805                 dns_keytable_detachkeynode(keytable, &keynode);
2806         *keynodep = NULL;
2807
2808         return (ISC_R_SUCCESS);
2809
2810   failure:
2811         return (result);
2812 }
2813
2814 /*
2815  * Remove from the key zone all the KEYDATA records found in rdataset.
2816  */
2817 static isc_result_t
2818 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
2819                dns_name_t *name, dns_rdataset_t *rdataset)
2820 {
2821         dns_rdata_t rdata = DNS_RDATA_INIT;
2822         isc_result_t result, uresult;
2823
2824         for (result = dns_rdataset_first(rdataset);
2825              result == ISC_R_SUCCESS;
2826              result = dns_rdataset_next(rdataset)) {
2827                 dns_rdata_reset(&rdata);
2828                 dns_rdataset_current(rdataset, &rdata);
2829                 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
2830                                         name, 0, &rdata);
2831                 if (uresult != ISC_R_SUCCESS)
2832                         return (uresult);
2833         }
2834         if (result == ISC_R_NOMORE)
2835                 result = ISC_R_SUCCESS;
2836         return (result);
2837 }
2838
2839 /*
2840  * Compute the DNSSEC key ID for a DNSKEY record.
2841  */
2842 static isc_result_t
2843 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
2844             dns_keytag_t *tag)
2845 {
2846         isc_result_t result;
2847         dns_rdata_t rdata = DNS_RDATA_INIT;
2848         unsigned char data[4096];
2849         isc_buffer_t buffer;
2850         dst_key_t *dstkey = NULL;
2851
2852         isc_buffer_init(&buffer, data, sizeof(data));
2853         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
2854                              dns_rdatatype_dnskey, dnskey, &buffer);
2855
2856         result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
2857         if (result == ISC_R_SUCCESS)
2858                 *tag = dst_key_id(dstkey);
2859         dst_key_free(&dstkey);
2860
2861         return (result);
2862 }
2863
2864 /*
2865  * Add key to the security roots.
2866  */
2867 static void
2868 trust_key(dns_zone_t *zone, dns_name_t *keyname,
2869           dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
2870         isc_result_t result;
2871         dns_rdata_t rdata = DNS_RDATA_INIT;
2872         unsigned char data[4096];
2873         isc_buffer_t buffer;
2874         dns_keytable_t *sr = NULL;
2875         dst_key_t *dstkey = NULL;
2876
2877         /* Convert dnskey to DST key. */
2878         isc_buffer_init(&buffer, data, sizeof(data));
2879         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
2880                              dns_rdatatype_dnskey, dnskey, &buffer);
2881
2882         result = dns_view_getsecroots(zone->view, &sr);
2883         if (result != ISC_R_SUCCESS)
2884                 goto failure;
2885
2886         CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
2887         CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
2888         dns_keytable_detach(&sr);
2889
2890   failure:
2891         if (dstkey != NULL)
2892                 dst_key_free(&dstkey);
2893         if (sr != NULL)
2894                 dns_keytable_detach(&sr);
2895         return;
2896 }
2897
2898 /*
2899  * Add a null key to the security roots for so that all queries
2900  * to the zone will fail.
2901  */
2902 static void
2903 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
2904         isc_result_t result;
2905         dns_keytable_t *sr = NULL;
2906
2907         result = dns_view_getsecroots(zone->view, &sr);
2908         if (result == ISC_R_SUCCESS) {
2909                 dns_keytable_marksecure(sr, keyname);
2910                 dns_keytable_detach(&sr);
2911         }
2912 }
2913
2914 /*
2915  * Scan a set of KEYDATA records from the key zone.  The ones that are
2916  * valid (i.e., the add holddown timer has expired) become trusted keys.
2917  */
2918 static void
2919 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
2920         isc_result_t result;
2921         dns_rdata_t rdata = DNS_RDATA_INIT;
2922         dns_rdata_keydata_t keydata;
2923         dns_rdata_dnskey_t dnskey;
2924         isc_mem_t *mctx = zone->mctx;
2925         int trusted = 0, revoked = 0, pending = 0;
2926         isc_stdtime_t now;
2927         dns_keytable_t *sr = NULL;
2928
2929         isc_stdtime_get(&now);
2930
2931         result = dns_view_getsecroots(zone->view, &sr);
2932         if (result == ISC_R_SUCCESS) {
2933                 dns_keytable_delete(sr, name);
2934                 dns_keytable_detach(&sr);
2935         }
2936
2937         /* Now insert all the accepted trust anchors from this keydata set. */
2938         for (result = dns_rdataset_first(rdataset);
2939              result == ISC_R_SUCCESS;
2940              result = dns_rdataset_next(rdataset)) {
2941                 dns_rdata_reset(&rdata);
2942                 dns_rdataset_current(rdataset, &rdata);
2943
2944                 /* Convert rdata to keydata. */
2945                 dns_rdata_tostruct(&rdata, &keydata, NULL);
2946
2947                 /* Set the key refresh timer. */
2948                 set_refreshkeytimer(zone, &keydata, now);
2949
2950                 /* If the removal timer is nonzero, this key was revoked. */
2951                 if (keydata.removehd != 0) {
2952                         revoked++;
2953                         continue;
2954                 }
2955
2956                 /*
2957                  * If the add timer is still pending, this key is not
2958                  * trusted yet.
2959                  */
2960                 if (now < keydata.addhd) {
2961                         pending++;
2962                         continue;
2963                 }
2964
2965                 /* Convert keydata to dnskey. */
2966                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
2967
2968                 /* Add to keytables. */
2969                 trusted++;
2970                 trust_key(zone, name, &dnskey, mctx);
2971         }
2972
2973         if (trusted == 0 && pending != 0) {
2974                 char namebuf[DNS_NAME_FORMATSIZE];
2975                 dns_name_format(name, namebuf, sizeof namebuf);
2976                 dns_zone_log(zone, ISC_LOG_ERROR,
2977                              "No valid trust anchors for '%s'!", namebuf);
2978                 dns_zone_log(zone, ISC_LOG_ERROR,
2979                              "%d key(s) revoked, %d still pending",
2980                              revoked, pending);
2981                 dns_zone_log(zone, ISC_LOG_ERROR,
2982                              "All queries to '%s' will fail", namebuf);
2983                 fail_secure(zone, name);
2984         }
2985 }
2986
2987 static isc_result_t
2988 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
2989              dns_diff_t *diff)
2990 {
2991         dns_diff_t temp_diff;
2992         isc_result_t result;
2993
2994         /*
2995          * Create a singleton diff.
2996          */
2997         dns_diff_init(diff->mctx, &temp_diff);
2998         temp_diff.resign = diff->resign;
2999         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3000
3001         /*
3002          * Apply it to the database.
3003          */
3004         result = dns_diff_apply(&temp_diff, db, ver);
3005         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3006         if (result != ISC_R_SUCCESS) {
3007                 dns_difftuple_free(tuple);
3008                 return (result);
3009         }
3010
3011         /*
3012          * Merge it into the current pending journal entry.
3013          */
3014         dns_diff_appendminimal(diff, tuple);
3015
3016         /*
3017          * Do not clear temp_diff.
3018          */
3019         return (ISC_R_SUCCESS);
3020 }
3021
3022 static isc_result_t
3023 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3024               dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3025               dns_rdata_t *rdata)
3026 {
3027         dns_difftuple_t *tuple = NULL;
3028         isc_result_t result;
3029         result = dns_difftuple_create(diff->mctx, op,
3030                                       name, ttl, rdata, &tuple);
3031         if (result != ISC_R_SUCCESS)
3032                 return (result);
3033         return (do_one_tuple(&tuple, db, ver, diff));
3034 }
3035
3036 static isc_result_t
3037 increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver,
3038                      dns_diff_t *diff, isc_mem_t *mctx) {
3039         dns_difftuple_t *deltuple = NULL;
3040         dns_difftuple_t *addtuple = NULL;
3041         isc_uint32_t serial;
3042         isc_result_t result;
3043
3044         CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3045         CHECK(dns_difftuple_copy(deltuple, &addtuple));
3046         addtuple->op = DNS_DIFFOP_ADD;
3047
3048         serial = dns_soa_getserial(&addtuple->rdata);
3049
3050         /* RFC1982 */
3051         serial = (serial + 1) & 0xFFFFFFFF;
3052         if (serial == 0)
3053                 serial = 1;
3054
3055         dns_soa_setserial(serial, &addtuple->rdata);
3056         CHECK(do_one_tuple(&deltuple, db, ver, diff));
3057         CHECK(do_one_tuple(&addtuple, db, ver, diff));
3058         result = ISC_R_SUCCESS;
3059
3060         failure:
3061         if (addtuple != NULL)
3062                 dns_difftuple_free(&addtuple);
3063         if (deltuple != NULL)
3064                 dns_difftuple_free(&deltuple);
3065         return (result);
3066 }
3067
3068 /*
3069  * Write all transactions in 'diff' to the zone journal file.
3070  */
3071 static isc_result_t
3072 zone_journal(dns_zone_t *zone, dns_diff_t *diff, const char *caller) {
3073         const char me[] = "zone_journal";
3074         const char *journalfile;
3075         isc_result_t result = ISC_R_SUCCESS;
3076         dns_journal_t *journal = NULL;
3077
3078         ENTER;
3079         journalfile = dns_zone_getjournal(zone);
3080         if (journalfile != NULL) {
3081                 result = dns_journal_open(zone->mctx, journalfile,
3082                                           ISC_TRUE, &journal);
3083                 if (result != ISC_R_SUCCESS) {
3084                         dns_zone_log(zone, ISC_LOG_ERROR,
3085                                      "%s:dns_journal_open -> %s",
3086                                      caller, dns_result_totext(result));
3087                         return (result);
3088                 }
3089
3090                 result = dns_journal_write_transaction(journal, diff);
3091                 dns_journal_destroy(&journal);
3092                 if (result != ISC_R_SUCCESS) {
3093                         dns_zone_log(zone, ISC_LOG_ERROR,
3094                                      "%s:dns_journal_write_transaction -> %s",
3095                                      caller, dns_result_totext(result));
3096                         return (result);
3097                 }
3098         }
3099         return (result);
3100 }
3101
3102 /*
3103  * Create an SOA record for a newly-created zone
3104  */
3105 static isc_result_t
3106 add_soa(dns_zone_t *zone, dns_db_t *db) {
3107         isc_result_t result;
3108         dns_rdata_t rdata = DNS_RDATA_INIT;
3109         unsigned char buf[DNS_SOA_BUFFERSIZE];
3110         dns_dbversion_t *ver = NULL;
3111         dns_diff_t diff;
3112
3113         dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3114
3115         dns_diff_init(zone->mctx, &diff);
3116         result = dns_db_newversion(db, &ver);
3117         if (result != ISC_R_SUCCESS) {
3118                 dns_zone_log(zone, ISC_LOG_ERROR,
3119                              "add_soa:dns_db_newversion -> %s",
3120                              dns_result_totext(result));
3121                 goto failure;
3122         }
3123
3124         /* Build SOA record */
3125         result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3126                                     0, 0, 0, 0, 0, buf, &rdata);
3127         if (result != ISC_R_SUCCESS) {
3128                 dns_zone_log(zone, ISC_LOG_ERROR,
3129                              "add_soa:dns_soa_buildrdata -> %s",
3130                              dns_result_totext(result));
3131                 goto failure;
3132         }
3133
3134         result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3135                                &zone->origin, 0, &rdata);
3136
3137 failure:
3138         dns_diff_clear(&diff);
3139         if (ver != NULL)
3140                 dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3141
3142         return (result);
3143 }
3144
3145 /*
3146  * Synchronize the set of initializing keys found in managed-keys {}
3147  * statements with the set of trust anchors found in the managed-keys.bind
3148  * zone.  If a domain is no longer named in managed-keys, delete all keys
3149  * from that domain from the key zone.  If a domain is mentioned in in
3150  * managed-keys but there are no references to it in the key zone, load
3151  * the key zone with the initializing key(s) for that domain.
3152  */
3153 static isc_result_t
3154 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3155         isc_result_t result = ISC_R_SUCCESS;
3156         isc_boolean_t changed = ISC_FALSE;
3157         isc_boolean_t commit = ISC_FALSE;
3158         dns_rbtnodechain_t chain;
3159         dns_fixedname_t fn;
3160         dns_name_t foundname, *origin;
3161         dns_keynode_t *keynode = NULL;
3162         dns_view_t *view = zone->view;
3163         dns_keytable_t *sr = NULL;
3164         dns_dbversion_t *ver = NULL;
3165         dns_diff_t diff;
3166         dns_rriterator_t rrit;
3167
3168         dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3169
3170         dns_name_init(&foundname, NULL);
3171         dns_fixedname_init(&fn);
3172         origin = dns_fixedname_name(&fn);
3173
3174         dns_diff_init(zone->mctx, &diff);
3175
3176         CHECK(dns_view_getsecroots(view, &sr));
3177
3178         result = dns_db_newversion(db, &ver);
3179         if (result != ISC_R_SUCCESS) {
3180                 dns_zone_log(zone, ISC_LOG_ERROR,
3181                              "sync_keyzone:dns_db_newversion -> %s",
3182                              dns_result_totext(result));
3183                 goto failure;
3184         }
3185
3186         /*
3187          * Walk the zone DB.  If we find any keys whose names are no longer
3188          * in managed-keys (or *are* in trusted-keys, meaning they are
3189          * permanent and not RFC5011-maintained), delete them from the
3190          * zone.  Otherwise call load_secroots(), which loads keys into
3191          * secroots as appropriate.
3192          */
3193         dns_rriterator_init(&rrit, db, ver, 0);
3194         for (result = dns_rriterator_first(&rrit);
3195              result == ISC_R_SUCCESS;
3196              result = dns_rriterator_nextrrset(&rrit)) {
3197                 dns_rdataset_t *rdataset = NULL;
3198                 dns_name_t *rrname = NULL;
3199                 isc_uint32_t ttl;
3200
3201                 dns_rriterator_current(&rrit, &rrname, &ttl,
3202                                        &rdataset, NULL);
3203                 if (!dns_rdataset_isassociated(rdataset)) {
3204                         dns_rriterator_destroy(&rrit);
3205                         goto failure;
3206                 }
3207
3208                 if (rdataset->type != dns_rdatatype_keydata)
3209                         continue;
3210
3211                 result = dns_keytable_find(sr, rrname, &keynode);
3212                 if ((result != ISC_R_SUCCESS &&
3213                      result != DNS_R_PARTIALMATCH) ||
3214                     dns_keynode_managed(keynode) == ISC_FALSE) {
3215                         CHECK(delete_keydata(db, ver, &diff,
3216                                              rrname, rdataset));
3217                         changed = ISC_TRUE;
3218                 } else {
3219                         load_secroots(zone, rrname, rdataset);
3220                 }
3221
3222                 if (keynode != NULL)
3223                         dns_keytable_detachkeynode(sr, &keynode);
3224         }
3225         dns_rriterator_destroy(&rrit);
3226
3227         /*
3228          * Now walk secroots to find any managed keys that aren't
3229          * in the zone.  If we find any, we add them to the zone.
3230          */
3231         RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3232         dns_rbtnodechain_init(&chain, zone->mctx);
3233         result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3234         if (result == ISC_R_NOTFOUND)
3235                 result = ISC_R_NOMORE;
3236         while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3237                 dns_rbtnode_t *rbtnode = NULL;
3238
3239                 dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3240                 if (rbtnode->data == NULL)
3241                         goto skip;
3242
3243                 dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3244                 if (dns_keynode_managed(keynode)) {
3245                         dns_fixedname_t fname;
3246                         dns_name_t *keyname;
3247                         dst_key_t *key;
3248
3249                         key = dns_keynode_key(keynode);
3250                         dns_fixedname_init(&fname);
3251
3252                         if (key == NULL)   /* fail_secure() was called. */
3253                                 goto skip;
3254
3255                         keyname = dst_key_name(key);
3256                         result = dns_db_find(db, keyname, ver,
3257                                              dns_rdatatype_keydata,
3258                                              DNS_DBFIND_NOWILD, 0, NULL,
3259                                              dns_fixedname_name(&fname),
3260                                              NULL, NULL);
3261                         if (result != ISC_R_SUCCESS)
3262                                 result = create_keydata(zone, db, ver, &diff,
3263                                                         sr, &keynode, &changed);
3264                         if (result != ISC_R_SUCCESS)
3265                                 break;
3266                 }
3267   skip:
3268                 result = dns_rbtnodechain_next(&chain, &foundname, origin);
3269                 if (keynode != NULL)
3270                         dns_keytable_detachkeynode(sr, &keynode);
3271         }
3272         RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3273
3274         if (result == ISC_R_NOMORE)
3275                 result = ISC_R_SUCCESS;
3276
3277         if (changed) {
3278                 /* Write changes to journal file. */
3279                 CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
3280                 CHECK(zone_journal(zone, &diff, "sync_keyzone"));
3281
3282                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3283                 zone_needdump(zone, 30);
3284                 commit = ISC_TRUE;
3285         }
3286
3287  failure:
3288         if (keynode != NULL)
3289                 dns_keytable_detachkeynode(sr, &keynode);
3290         if (sr != NULL)
3291                 dns_keytable_detach(&sr);
3292         if (ver != NULL)
3293                 dns_db_closeversion(db, &ver, commit);
3294         dns_diff_clear(&diff);
3295
3296         return (result);
3297 }
3298
3299 static isc_result_t
3300 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3301               isc_result_t result)
3302 {
3303         unsigned int soacount = 0;
3304         unsigned int nscount = 0;
3305         unsigned int errors = 0;
3306         isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3307         isc_time_t now;
3308         isc_boolean_t needdump = ISC_FALSE;
3309         isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3310         isc_boolean_t nomaster = ISC_FALSE;
3311         unsigned int options;
3312
3313         TIME_NOW(&now);
3314
3315         /*
3316          * Initiate zone transfer?  We may need a error code that
3317          * indicates that the "permanent" form does not exist.
3318          * XXX better error feedback to log.
3319          */
3320         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3321                 if (zone->type == dns_zone_slave ||
3322                     zone->type == dns_zone_stub) {
3323                         if (result == ISC_R_FILENOTFOUND)
3324                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3325                                              "no master file");
3326                         else if (result != DNS_R_NOMASTERFILE)
3327                                 dns_zone_log(zone, ISC_LOG_ERROR,
3328                                              "loading from master file %s "
3329                                              "failed: %s",
3330                                              zone->masterfile,
3331                                              dns_result_totext(result));
3332                 } else {
3333                         int level = ISC_LOG_ERROR;
3334                         if (zone->type == dns_zone_key &&
3335                             result == ISC_R_FILENOTFOUND)
3336                                 level = ISC_LOG_DEBUG(1);
3337                         dns_zone_log(zone, level,
3338                                      "loading from master file %s failed: %s",
3339                                      zone->masterfile,
3340                                      dns_result_totext(result));
3341                         nomaster = ISC_TRUE;
3342                 }
3343
3344                 if (zone->type != dns_zone_key)
3345                         goto cleanup;
3346         }
3347
3348         dns_zone_log(zone, ISC_LOG_DEBUG(2),
3349                      "number of nodes in database: %u",
3350                      dns_db_nodecount(db));
3351
3352         if (result == DNS_R_SEENINCLUDE)
3353                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3354         else
3355                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3356
3357         /*
3358          * If there's no master file for a key zone, then the zone is new:
3359          * create an SOA record.  (We do this now, instead of later, so that
3360          * if there happens to be a journal file, we can roll forward from
3361          * a sane starting point.)
3362          */
3363         if (nomaster && zone->type == dns_zone_key) {
3364                 result = add_soa(zone, db);
3365                 if (result != ISC_R_SUCCESS)
3366                         goto cleanup;
3367         }
3368
3369         /*
3370          * Apply update log, if any, on initial load.
3371          */
3372         if (zone->journal != NULL &&
3373             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
3374             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3375         {
3376                 if (zone->type == dns_zone_master &&
3377                     (zone->update_acl != NULL || zone->ssutable != NULL))
3378                         options = DNS_JOURNALOPT_RESIGN;
3379                 else
3380                         options = 0;
3381                 result = dns_journal_rollforward2(zone->mctx, db, options,
3382                                                   zone->sigresigninginterval,
3383                                                   zone->journal);
3384                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
3385                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
3386                     result != ISC_R_RANGE) {
3387                         dns_zone_log(zone, ISC_LOG_ERROR,
3388                                      "journal rollforward failed: %s",
3389                                      dns_result_totext(result));
3390                         goto cleanup;
3391                 }
3392                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
3393                         dns_zone_log(zone, ISC_LOG_ERROR,
3394                                      "journal rollforward failed: "
3395                                      "journal out of sync with zone");
3396                         goto cleanup;
3397                 }
3398                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3399                              "journal rollforward completed "
3400                              "successfully: %s",
3401                              dns_result_totext(result));
3402                 if (result == ISC_R_SUCCESS)
3403                         needdump = ISC_TRUE;
3404         }
3405
3406         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
3407         /*
3408          * Obtain ns, soa and cname counts for top of zone.
3409          */
3410         INSIST(db != NULL);
3411         result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
3412                                   &refresh, &retry, &expire, &minimum,
3413                                   &errors);
3414         if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
3415                 dns_zone_log(zone, ISC_LOG_ERROR,
3416                              "could not find NS and/or SOA records");
3417         }
3418
3419         /*
3420          * Master / Slave / Stub zones require both NS and SOA records at
3421          * the top of the zone.
3422          */
3423
3424         switch (zone->type) {
3425         case dns_zone_dlz:
3426         case dns_zone_master:
3427         case dns_zone_slave:
3428         case dns_zone_stub:
3429                 if (soacount != 1) {
3430                         dns_zone_log(zone, ISC_LOG_ERROR,
3431                                      "has %d SOA records", soacount);
3432                         result = DNS_R_BADZONE;
3433                 }
3434                 if (nscount == 0) {
3435                         dns_zone_log(zone, ISC_LOG_ERROR,
3436                                      "has no NS records");
3437                         result = DNS_R_BADZONE;
3438                 }
3439                 if (result != ISC_R_SUCCESS)
3440                         goto cleanup;
3441                 if (zone->type == dns_zone_master && errors != 0) {
3442                         result = DNS_R_BADZONE;
3443                         goto cleanup;
3444                 }
3445                 if (zone->type != dns_zone_stub) {
3446                         result = check_nsec3param(zone, db);
3447                         if (result != ISC_R_SUCCESS)
3448                                 goto cleanup;
3449                 }
3450                 if (zone->type == dns_zone_master &&
3451                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
3452                     !integrity_checks(zone, db)) {
3453                         result = DNS_R_BADZONE;
3454                         goto cleanup;
3455                 }
3456
3457                 if (zone->type == dns_zone_master &&
3458                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
3459                     !zone_check_dup(zone, db)) {
3460                         result = DNS_R_BADZONE;
3461                         goto cleanup;
3462                 }
3463
3464                 if (zone->db != NULL) {
3465                         /*
3466                          * This is checked in zone_replacedb() for slave zones
3467                          * as they don't reload from disk.
3468                          */
3469                         result = zone_get_from_db(zone, zone->db, NULL, NULL,
3470                                                   &oldserial, NULL, NULL, NULL,
3471                                                   NULL, NULL);
3472                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3473                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
3474                             !isc_serial_gt(serial, oldserial)) {
3475                                 isc_uint32_t serialmin, serialmax;
3476
3477                                 INSIST(zone->type == dns_zone_master);
3478
3479                                 serialmin = (oldserial + 1) & 0xffffffffU;
3480                                 serialmax = (oldserial + 0x7fffffffU) &
3481                                              0xffffffffU;
3482                                 dns_zone_log(zone, ISC_LOG_ERROR,
3483                                              "ixfr-from-differences: "
3484                                              "new serial (%u) out of range "
3485                                              "[%u - %u]", serial, serialmin,
3486                                              serialmax);
3487                                 result = DNS_R_BADZONE;
3488                                 goto cleanup;
3489                         } else if (!isc_serial_ge(serial, oldserial))
3490                                 dns_zone_log(zone, ISC_LOG_ERROR,
3491                                              "zone serial (%u/%u) has gone "
3492                                              "backwards", serial, oldserial);
3493                         else if (serial == oldserial && !hasinclude &&
3494                                  strcmp(zone->db_argv[0], "_builtin") != 0)
3495                                 dns_zone_log(zone, ISC_LOG_ERROR,
3496                                              "zone serial (%u) unchanged. "
3497                                              "zone may fail to transfer "
3498                                              "to slaves.", serial);
3499                 }
3500
3501                 if (zone->type == dns_zone_master &&
3502                     (zone->update_acl != NULL || zone->ssutable != NULL) &&
3503                     zone->sigresigninginterval < (3 * refresh) &&
3504                     dns_db_issecure(db))
3505                 {
3506                         dns_zone_log(zone, ISC_LOG_WARNING,
3507                                      "sig-re-signing-interval less than "
3508                                      "3 * refresh.");
3509                 }
3510
3511                 zone->refresh = RANGE(refresh,
3512                                       zone->minrefresh, zone->maxrefresh);
3513                 zone->retry = RANGE(retry,
3514                                     zone->minretry, zone->maxretry);
3515                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
3516                                      DNS_MAX_EXPIRE);
3517                 zone->minimum = minimum;
3518                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
3519
3520                 if (zone->type == dns_zone_slave ||
3521                     zone->type == dns_zone_stub) {
3522                         isc_time_t t;
3523                         isc_uint32_t delay;
3524
3525                         result = isc_file_getmodtime(zone->journal, &t);
3526                         if (result != ISC_R_SUCCESS)
3527                                 result = isc_file_getmodtime(zone->masterfile,
3528                                                              &t);
3529                         if (result == ISC_R_SUCCESS)
3530                                 DNS_ZONE_TIME_ADD(&t, zone->expire,
3531                                                   &zone->expiretime);
3532                         else
3533                                 DNS_ZONE_TIME_ADD(&now, zone->retry,
3534                                                   &zone->expiretime);
3535
3536                         delay = isc_random_jitter(zone->retry,
3537                                                   (zone->retry * 3) / 4);
3538                         DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
3539                         if (isc_time_compare(&zone->refreshtime,
3540                                              &zone->expiretime) >= 0)
3541                                 zone->refreshtime = now;
3542                 }
3543                 break;
3544
3545         case dns_zone_key:
3546                 result = sync_keyzone(zone, db);
3547                 if (result != ISC_R_SUCCESS)
3548                         goto cleanup;
3549                 break;
3550
3551         default:
3552                 UNEXPECTED_ERROR(__FILE__, __LINE__,
3553                                  "unexpected zone type %d", zone->type);
3554                 result = ISC_R_UNEXPECTED;
3555                 goto cleanup;
3556         }
3557
3558         /*
3559          * Check for weak DNSKEY's.
3560          */
3561         if (zone->type == dns_zone_master)
3562                 zone_check_dnskeys(zone, db);
3563
3564         /*
3565          * Schedule DNSSEC key refresh.
3566          */
3567         if (zone->type == dns_zone_master &&
3568             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
3569                 zone->refreshkeytime = now;
3570
3571 #if 0
3572         /* destroy notification example. */
3573         {
3574                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
3575                                                     DNS_EVENT_DBDESTROYED,
3576                                                     dns_zonemgr_dbdestroyed,
3577                                                     zone,
3578                                                     sizeof(isc_event_t));
3579                 dns_db_ondestroy(db, zone->task, &e);
3580         }
3581 #endif
3582
3583         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
3584         if (zone->db != NULL) {
3585                 result = zone_replacedb(zone, db, ISC_FALSE);
3586                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3587                 if (result != ISC_R_SUCCESS)
3588                         goto cleanup;
3589         } else {
3590                 zone_attachdb(zone, db);
3591                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3592                 DNS_ZONE_SETFLAG(zone,
3593                                  DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
3594         }
3595
3596         result = ISC_R_SUCCESS;
3597
3598         if (needdump) {
3599                 if (zone->type == dns_zone_key)
3600                         zone_needdump(zone, 30);
3601                 else
3602                         zone_needdump(zone, DNS_DUMP_DELAY);
3603         }
3604
3605         if (zone->task != NULL) {
3606                 if (zone->type == dns_zone_master) {
3607                         set_resigntime(zone);
3608                         resume_signingwithkey(zone);
3609                         resume_addnsec3chain(zone);
3610                 }
3611
3612                 if (zone->type == dns_zone_master &&
3613                     zone_isdynamic(zone) &&
3614                     dns_db_issecure(db)) {
3615                         dns_name_t *name;
3616                         dns_fixedname_t fixed;
3617                         dns_rdataset_t next;
3618
3619                         dns_rdataset_init(&next);
3620                         dns_fixedname_init(&fixed);
3621                         name = dns_fixedname_name(&fixed);
3622
3623                         result = dns_db_getsigningtime(db, &next, name);
3624                         if (result == ISC_R_SUCCESS) {
3625                                 isc_stdtime_t timenow;
3626                                 char namebuf[DNS_NAME_FORMATSIZE];
3627                                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3628
3629                                 isc_stdtime_get(&timenow);
3630                                 dns_name_format(name, namebuf, sizeof(namebuf));
3631                                 dns_rdatatype_format(next.covers,
3632                                                      typebuf, sizeof(typebuf));
3633                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
3634                                              "next resign: %s/%s in %d seconds",
3635                                              namebuf, typebuf,
3636                                              next.resign - timenow);
3637                                 dns_rdataset_disassociate(&next);
3638                         } else
3639                                 dns_zone_log(zone, ISC_LOG_WARNING,
3640                                              "signed dynamic zone has no "
3641                                              "resign event scheduled");
3642                 }
3643
3644                 zone_settimer(zone, &now);
3645         }
3646
3647         if (! dns_db_ispersistent(db))
3648                 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
3649                              dns_db_issecure(db) ? " (DNSSEC signed)" : "");
3650
3651         zone->loadtime = loadtime;
3652         return (result);
3653
3654  cleanup:
3655         if (zone->type == dns_zone_slave ||
3656             zone->type == dns_zone_stub ||
3657             zone->type == dns_zone_key) {
3658                 if (zone->journal != NULL)
3659                         zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
3660                 if (zone->masterfile != NULL)
3661                         zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
3662
3663                 /* Mark the zone for immediate refresh. */
3664                 zone->refreshtime = now;
3665                 if (zone->task != NULL)
3666                         zone_settimer(zone, &now);
3667                 result = ISC_R_SUCCESS;
3668         } else if (zone->type == dns_zone_master)
3669                 dns_zone_log(zone, ISC_LOG_ERROR, "not loaded due to errors.");
3670         return (result);
3671 }
3672
3673 static isc_boolean_t
3674 exit_check(dns_zone_t *zone) {
3675
3676         REQUIRE(LOCKED_ZONE(zone));
3677
3678         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
3679             zone->irefs == 0)
3680         {
3681                 /*
3682                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
3683                  */
3684                 INSIST(isc_refcount_current(&zone->erefs) == 0);
3685                 return (ISC_TRUE);
3686         }
3687         return (ISC_FALSE);
3688 }
3689
3690 static isc_boolean_t
3691 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
3692               dns_name_t *name, isc_boolean_t logit)
3693 {
3694         isc_result_t result;
3695         char namebuf[DNS_NAME_FORMATSIZE];
3696         char altbuf[DNS_NAME_FORMATSIZE];
3697         dns_fixedname_t fixed;
3698         dns_name_t *foundname;
3699         int level;
3700
3701         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
3702                 return (ISC_TRUE);
3703
3704         if (zone->type == dns_zone_master)
3705                 level = ISC_LOG_ERROR;
3706         else
3707                 level = ISC_LOG_WARNING;
3708
3709         dns_fixedname_init(&fixed);
3710         foundname = dns_fixedname_name(&fixed);
3711
3712         result = dns_db_find(db, name, version, dns_rdatatype_a,
3713                              0, 0, NULL, foundname, NULL, NULL);
3714         if (result == ISC_R_SUCCESS)
3715                 return (ISC_TRUE);
3716
3717         if (result == DNS_R_NXRRSET) {
3718                 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
3719                                      0, 0, NULL, foundname, NULL, NULL);
3720                 if (result == ISC_R_SUCCESS)
3721                         return (ISC_TRUE);
3722         }
3723
3724         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3725             result == DNS_R_EMPTYNAME) {
3726                 if (logit) {
3727                         dns_name_format(name, namebuf, sizeof namebuf);
3728                         dns_zone_log(zone, level, "NS '%s' has no address "
3729                                      "records (A or AAAA)", namebuf);
3730                 }
3731                 return (ISC_FALSE);
3732         }
3733
3734         if (result == DNS_R_CNAME) {
3735                 if (logit) {
3736                         dns_name_format(name, namebuf, sizeof namebuf);
3737                         dns_zone_log(zone, level, "NS '%s' is a CNAME "
3738                                      "(illegal)", namebuf);
3739                 }
3740                 return (ISC_FALSE);
3741         }
3742
3743         if (result == DNS_R_DNAME) {
3744                 if (logit) {
3745                         dns_name_format(name, namebuf, sizeof namebuf);
3746                         dns_name_format(foundname, altbuf, sizeof altbuf);
3747                         dns_zone_log(zone, level, "NS '%s' is below a DNAME "
3748                                      "'%s' (illegal)", namebuf, altbuf);
3749                 }
3750                 return (ISC_FALSE);
3751         }
3752
3753         return (ISC_TRUE);
3754 }
3755
3756 static isc_result_t
3757 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
3758                  dns_dbversion_t *version, unsigned int *nscount,
3759                  unsigned int *errors, isc_boolean_t logit)
3760 {
3761         isc_result_t result;
3762         unsigned int count = 0;
3763         unsigned int ecount = 0;
3764         dns_rdataset_t rdataset;
3765         dns_rdata_t rdata;
3766         dns_rdata_ns_t ns;
3767
3768         dns_rdataset_init(&rdataset);
3769         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
3770                                      dns_rdatatype_none, 0, &rdataset, NULL);
3771         if (result == ISC_R_NOTFOUND) {
3772                 INSIST(!dns_rdataset_isassociated(&rdataset));
3773                 goto success;
3774         }
3775         if (result != ISC_R_SUCCESS) {
3776                 INSIST(!dns_rdataset_isassociated(&rdataset));
3777                 goto invalidate_rdataset;
3778         }
3779
3780         result = dns_rdataset_first(&rdataset);
3781         while (result == ISC_R_SUCCESS) {
3782                 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
3783                     (zone->type == dns_zone_master ||
3784                      zone->type == dns_zone_slave)) {
3785                         dns_rdata_init(&rdata);
3786                         dns_rdataset_current(&rdataset, &rdata);
3787                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
3788                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3789                         if (dns_name_issubdomain(&ns.name, &zone->origin) &&
3790                             !zone_check_ns(zone, db, version, &ns.name, logit))
3791                                 ecount++;
3792                 }
3793                 count++;
3794                 result = dns_rdataset_next(&rdataset);
3795         }
3796         dns_rdataset_disassociate(&rdataset);
3797
3798  success:
3799         if (nscount != NULL)
3800                 *nscount = count;
3801         if (errors != NULL)
3802                 *errors = ecount;
3803
3804         result = ISC_R_SUCCESS;
3805
3806  invalidate_rdataset:
3807         dns_rdataset_invalidate(&rdataset);
3808
3809         return (result);
3810 }
3811
3812 static isc_result_t
3813 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
3814                  unsigned int *soacount,
3815                  isc_uint32_t *serial, isc_uint32_t *refresh,
3816                  isc_uint32_t *retry, isc_uint32_t *expire,
3817                  isc_uint32_t *minimum)
3818 {
3819         isc_result_t result;
3820         unsigned int count;
3821         dns_rdataset_t rdataset;
3822         dns_rdata_t rdata = DNS_RDATA_INIT;
3823         dns_rdata_soa_t soa;
3824
3825         dns_rdataset_init(&rdataset);
3826         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
3827                                      dns_rdatatype_none, 0, &rdataset, NULL);
3828         if (result == ISC_R_NOTFOUND) {
3829                 INSIST(!dns_rdataset_isassociated(&rdataset));
3830                 if (soacount != NULL)
3831                         *soacount = 0;
3832                 if (serial != NULL)
3833                         *serial = 0;
3834                 if (refresh != NULL)
3835                         *refresh = 0;
3836                 if (retry != NULL)
3837                         *retry = 0;
3838                 if (expire != NULL)
3839                         *expire = 0;
3840                 if (minimum != NULL)
3841                         *minimum = 0;
3842                 result = ISC_R_SUCCESS;
3843                 goto invalidate_rdataset;
3844         }
3845         if (result != ISC_R_SUCCESS) {
3846                 INSIST(!dns_rdataset_isassociated(&rdataset));
3847                 goto invalidate_rdataset;
3848         }
3849
3850         count = 0;
3851         result = dns_rdataset_first(&rdataset);
3852         while (result == ISC_R_SUCCESS) {
3853                 dns_rdata_init(&rdata);
3854                 dns_rdataset_current(&rdataset, &rdata);
3855                 count++;
3856                 if (count == 1) {
3857                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
3858                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3859                 }
3860
3861                 result = dns_rdataset_next(&rdataset);
3862                 dns_rdata_reset(&rdata);
3863         }
3864         dns_rdataset_disassociate(&rdataset);
3865
3866         if (soacount != NULL)
3867                 *soacount = count;
3868
3869         if (count > 0) {
3870                 if (serial != NULL)
3871                         *serial = soa.serial;
3872                 if (refresh != NULL)
3873                         *refresh = soa.refresh;
3874                 if (retry != NULL)
3875                         *retry = soa.retry;
3876                 if (expire != NULL)
3877                         *expire = soa.expire;
3878                 if (minimum != NULL)
3879                         *minimum = soa.minimum;
3880         }
3881
3882         result = ISC_R_SUCCESS;
3883
3884  invalidate_rdataset:
3885         dns_rdataset_invalidate(&rdataset);
3886
3887         return (result);
3888 }
3889
3890 /*
3891  * zone must be locked.
3892  */
3893 static isc_result_t
3894 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
3895                  unsigned int *soacount, isc_uint32_t *serial,
3896                  isc_uint32_t *refresh, isc_uint32_t *retry,
3897                  isc_uint32_t *expire, isc_uint32_t *minimum,
3898                  unsigned int *errors)
3899 {
3900         isc_result_t result;
3901         isc_result_t answer = ISC_R_SUCCESS;
3902         dns_dbversion_t *version = NULL;
3903         dns_dbnode_t *node;
3904
3905         REQUIRE(db != NULL);
3906         REQUIRE(zone != NULL);
3907
3908         dns_db_currentversion(db, &version);
3909
3910         node = NULL;
3911         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3912         if (result != ISC_R_SUCCESS) {
3913                 answer = result;
3914                 goto closeversion;
3915         }
3916
3917         if (nscount != NULL || errors != NULL) {
3918                 result = zone_count_ns_rr(zone, db, node, version,
3919                                           nscount, errors, ISC_TRUE);
3920                 if (result != ISC_R_SUCCESS)
3921                         answer = result;
3922         }
3923
3924         if (soacount != NULL || serial != NULL || refresh != NULL
3925             || retry != NULL || expire != NULL || minimum != NULL) {
3926                 result = zone_load_soa_rr(db, node, version, soacount,
3927                                           serial, refresh, retry, expire,
3928                                           minimum);
3929                 if (result != ISC_R_SUCCESS)
3930                         answer = result;
3931         }
3932
3933         dns_db_detachnode(db, &node);
3934  closeversion:
3935         dns_db_closeversion(db, &version, ISC_FALSE);
3936
3937         return (answer);
3938 }
3939
3940 void
3941 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
3942         REQUIRE(DNS_ZONE_VALID(source));
3943         REQUIRE(target != NULL && *target == NULL);
3944         isc_refcount_increment(&source->erefs, NULL);
3945         *target = source;
3946 }
3947
3948 void
3949 dns_zone_detach(dns_zone_t **zonep) {
3950         dns_zone_t *zone;
3951         unsigned int refs;
3952         isc_boolean_t free_now = ISC_FALSE;
3953
3954         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
3955
3956         zone = *zonep;
3957
3958         isc_refcount_decrement(&zone->erefs, &refs);
3959
3960         if (refs == 0) {
3961                 LOCK_ZONE(zone);
3962                 /*
3963                  * We just detached the last external reference.
3964                  */
3965                 if (zone->task != NULL) {
3966                         /*
3967                          * This zone is being managed.  Post
3968                          * its control event and let it clean
3969                          * up synchronously in the context of
3970                          * its task.
3971                          */
3972                         isc_event_t *ev = &zone->ctlevent;
3973                         isc_task_send(zone->task, &ev);
3974                 } else {
3975                         /*
3976                          * This zone is not being managed; it has
3977                          * no task and can have no outstanding
3978                          * events.  Free it immediately.
3979                          */
3980                         /*
3981                          * Unmanaged zones should not have non-null views;
3982                          * we have no way of detaching from the view here
3983                          * without causing deadlock because this code is called
3984                          * with the view already locked.
3985                          */
3986                         INSIST(zone->view == NULL);
3987                         free_now = ISC_TRUE;
3988                 }
3989                 UNLOCK_ZONE(zone);
3990         }
3991         *zonep = NULL;
3992         if (free_now)
3993                 zone_free(zone);
3994 }
3995
3996 void
3997 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
3998         REQUIRE(DNS_ZONE_VALID(source));
3999         REQUIRE(target != NULL && *target == NULL);
4000         LOCK_ZONE(source);
4001         zone_iattach(source, target);
4002         UNLOCK_ZONE(source);
4003 }
4004
4005 isc_result_t
4006 dns_zone_synckeyzone(dns_zone_t *zone) {
4007         isc_result_t result;
4008         dns_db_t *db = NULL;
4009
4010         if (zone->type != dns_zone_key)
4011                 return (DNS_R_BADZONE);
4012
4013         CHECK(dns_zone_getdb(zone, &db));
4014
4015         LOCK_ZONE(zone);
4016         result = sync_keyzone(zone, db);
4017         UNLOCK_ZONE(zone);
4018
4019  failure:
4020         if (db != NULL)
4021                 dns_db_detach(&db);
4022         return (result);
4023 }
4024
4025 static void
4026 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4027
4028         /*
4029          * 'source' locked by caller.
4030          */
4031         REQUIRE(LOCKED_ZONE(source));
4032         REQUIRE(DNS_ZONE_VALID(source));
4033         REQUIRE(target != NULL && *target == NULL);
4034         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
4035         source->irefs++;
4036         INSIST(source->irefs != 0);
4037         *target = source;
4038 }
4039
4040 static void
4041 zone_idetach(dns_zone_t **zonep) {
4042         dns_zone_t *zone;
4043
4044         /*
4045          * 'zone' locked by caller.
4046          */
4047         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4048         zone = *zonep;
4049         REQUIRE(LOCKED_ZONE(*zonep));
4050         *zonep = NULL;
4051
4052         INSIST(zone->irefs > 0);
4053         zone->irefs--;
4054         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4055 }
4056
4057 void
4058 dns_zone_idetach(dns_zone_t **zonep) {
4059         dns_zone_t *zone;
4060         isc_boolean_t free_needed;
4061
4062         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4063         zone = *zonep;
4064         *zonep = NULL;
4065
4066         LOCK_ZONE(zone);
4067         INSIST(zone->irefs > 0);
4068         zone->irefs--;
4069         free_needed = exit_check(zone);
4070         UNLOCK_ZONE(zone);
4071         if (free_needed)
4072                 zone_free(zone);
4073 }
4074
4075 isc_mem_t *
4076 dns_zone_getmctx(dns_zone_t *zone) {
4077         REQUIRE(DNS_ZONE_VALID(zone));
4078
4079         return (zone->mctx);
4080 }
4081
4082 dns_zonemgr_t *
4083 dns_zone_getmgr(dns_zone_t *zone) {
4084         REQUIRE(DNS_ZONE_VALID(zone));
4085
4086         return (zone->zmgr);
4087 }
4088
4089 void
4090 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4091         REQUIRE(DNS_ZONE_VALID(zone));
4092
4093         LOCK_ZONE(zone);
4094         if (value)
4095                 DNS_ZONE_SETFLAG(zone, flags);
4096         else
4097                 DNS_ZONE_CLRFLAG(zone, flags);
4098         UNLOCK_ZONE(zone);
4099 }
4100
4101 void
4102 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4103 {
4104         REQUIRE(DNS_ZONE_VALID(zone));
4105
4106         LOCK_ZONE(zone);
4107         if (value)
4108                 zone->options |= option;
4109         else
4110                 zone->options &= ~option;
4111         UNLOCK_ZONE(zone);
4112 }
4113
4114 unsigned int
4115 dns_zone_getoptions(dns_zone_t *zone) {
4116
4117         REQUIRE(DNS_ZONE_VALID(zone));
4118
4119         return (zone->options);
4120 }
4121
4122 void
4123 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4124 {
4125         REQUIRE(DNS_ZONE_VALID(zone));
4126
4127         LOCK_ZONE(zone);
4128         if (value)
4129                 zone->keyopts |= keyopt;
4130         else
4131                 zone->keyopts &= ~keyopt;
4132         UNLOCK_ZONE(zone);
4133 }
4134
4135 unsigned int
4136 dns_zone_getkeyopts(dns_zone_t *zone) {
4137
4138         REQUIRE(DNS_ZONE_VALID(zone));
4139
4140         return (zone->keyopts);
4141 }
4142
4143 isc_result_t
4144 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4145         REQUIRE(DNS_ZONE_VALID(zone));
4146
4147         LOCK_ZONE(zone);
4148         zone->xfrsource4 = *xfrsource;
4149         UNLOCK_ZONE(zone);
4150
4151         return (ISC_R_SUCCESS);
4152 }
4153
4154 isc_sockaddr_t *
4155 dns_zone_getxfrsource4(dns_zone_t *zone) {
4156         REQUIRE(DNS_ZONE_VALID(zone));
4157         return (&zone->xfrsource4);
4158 }
4159
4160 isc_result_t
4161 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4162         REQUIRE(DNS_ZONE_VALID(zone));
4163
4164         LOCK_ZONE(zone);
4165         zone->xfrsource6 = *xfrsource;
4166         UNLOCK_ZONE(zone);
4167
4168         return (ISC_R_SUCCESS);
4169 }
4170
4171 isc_sockaddr_t *
4172 dns_zone_getxfrsource6(dns_zone_t *zone) {
4173         REQUIRE(DNS_ZONE_VALID(zone));
4174         return (&zone->xfrsource6);
4175 }
4176
4177 isc_result_t
4178 dns_zone_setaltxfrsource4(dns_zone_t *zone,
4179                           const isc_sockaddr_t *altxfrsource)
4180 {
4181         REQUIRE(DNS_ZONE_VALID(zone));
4182
4183         LOCK_ZONE(zone);
4184         zone->altxfrsource4 = *altxfrsource;
4185         UNLOCK_ZONE(zone);
4186
4187         return (ISC_R_SUCCESS);
4188 }
4189
4190 isc_sockaddr_t *
4191 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4192         REQUIRE(DNS_ZONE_VALID(zone));
4193         return (&zone->altxfrsource4);
4194 }
4195
4196 isc_result_t
4197 dns_zone_setaltxfrsource6(dns_zone_t *zone,
4198                           const isc_sockaddr_t *altxfrsource)
4199 {
4200         REQUIRE(DNS_ZONE_VALID(zone));
4201
4202         LOCK_ZONE(zone);
4203         zone->altxfrsource6 = *altxfrsource;
4204         UNLOCK_ZONE(zone);
4205
4206         return (ISC_R_SUCCESS);
4207 }
4208
4209 isc_sockaddr_t *
4210 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4211         REQUIRE(DNS_ZONE_VALID(zone));
4212         return (&zone->altxfrsource6);
4213 }
4214
4215 isc_result_t
4216 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4217         REQUIRE(DNS_ZONE_VALID(zone));
4218
4219         LOCK_ZONE(zone);
4220         zone->notifysrc4 = *notifysrc;
4221         UNLOCK_ZONE(zone);
4222
4223         return (ISC_R_SUCCESS);
4224 }
4225
4226 isc_sockaddr_t *
4227 dns_zone_getnotifysrc4(dns_zone_t *zone) {
4228         REQUIRE(DNS_ZONE_VALID(zone));
4229         return (&zone->notifysrc4);
4230 }
4231
4232 isc_result_t
4233 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4234         REQUIRE(DNS_ZONE_VALID(zone));
4235
4236         LOCK_ZONE(zone);
4237         zone->notifysrc6 = *notifysrc;
4238         UNLOCK_ZONE(zone);
4239
4240         return (ISC_R_SUCCESS);
4241 }
4242
4243 isc_sockaddr_t *
4244 dns_zone_getnotifysrc6(dns_zone_t *zone) {
4245         REQUIRE(DNS_ZONE_VALID(zone));
4246         return (&zone->notifysrc6);
4247 }
4248
4249 isc_result_t
4250 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
4251                        isc_uint32_t count)
4252 {
4253         isc_sockaddr_t *new;
4254
4255         REQUIRE(DNS_ZONE_VALID(zone));
4256         REQUIRE(count == 0 || notify != NULL);
4257
4258         LOCK_ZONE(zone);
4259         if (zone->notify != NULL) {
4260                 isc_mem_put(zone->mctx, zone->notify,
4261                             zone->notifycnt * sizeof(*new));
4262                 zone->notify = NULL;
4263                 zone->notifycnt = 0;
4264         }
4265         if (count != 0) {
4266                 new = isc_mem_get(zone->mctx, count * sizeof(*new));
4267                 if (new == NULL) {
4268                         UNLOCK_ZONE(zone);
4269                         return (ISC_R_NOMEMORY);
4270                 }
4271                 memcpy(new, notify, count * sizeof(*new));
4272                 zone->notify = new;
4273                 zone->notifycnt = count;
4274         }
4275         UNLOCK_ZONE(zone);
4276         return (ISC_R_SUCCESS);
4277 }
4278
4279 isc_result_t
4280 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
4281                     isc_uint32_t count)
4282 {
4283         isc_result_t result;
4284
4285         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
4286         return (result);
4287 }
4288
4289 static isc_boolean_t
4290 same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4291              isc_uint32_t count)
4292 {
4293         unsigned int i;
4294
4295         for (i = 0; i < count; i++)
4296                 if (!isc_sockaddr_equal(&old[i], &new[i]))
4297                         return (ISC_FALSE);
4298         return (ISC_TRUE);
4299 }
4300
4301 static isc_boolean_t
4302 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
4303         unsigned int i;
4304
4305         if (old == NULL && new == NULL)
4306                 return (ISC_TRUE);
4307         if (old == NULL || new == NULL)
4308                 return (ISC_FALSE);
4309
4310         for (i = 0; i < count; i++) {
4311                 if (old[i] == NULL && new[i] == NULL)
4312                         continue;
4313                 if (old[i] == NULL || new[i] == NULL ||
4314                      !dns_name_equal(old[i], new[i]))
4315                         return (ISC_FALSE);
4316         }
4317         return (ISC_TRUE);
4318 }
4319
4320 isc_result_t
4321 dns_zone_setmasterswithkeys(dns_zone_t *zone,
4322                             const isc_sockaddr_t *masters,
4323                             dns_name_t **keynames,
4324                             isc_uint32_t count)
4325 {
4326         isc_sockaddr_t *new;
4327         isc_result_t result = ISC_R_SUCCESS;
4328         dns_name_t **newname;
4329         isc_boolean_t *newok;
4330         unsigned int i;
4331
4332         REQUIRE(DNS_ZONE_VALID(zone));
4333         REQUIRE(count == 0 || masters != NULL);
4334         if (keynames != NULL) {
4335                 REQUIRE(count != 0);
4336         }
4337
4338         LOCK_ZONE(zone);
4339         /*
4340          * The refresh code assumes that 'masters' wouldn't change under it.
4341          * If it will change then kill off any current refresh in progress
4342          * and update the masters info.  If it won't change then we can just
4343          * unlock and exit.
4344          */
4345         if (count != zone->masterscnt ||
4346             !same_masters(zone->masters, masters, count) ||
4347             !same_keynames(zone->masterkeynames, keynames, count)) {
4348                 if (zone->request != NULL)
4349                         dns_request_cancel(zone->request);
4350         } else
4351                 goto unlock;
4352         if (zone->masters != NULL) {
4353                 isc_mem_put(zone->mctx, zone->masters,
4354                             zone->masterscnt * sizeof(*new));
4355                 zone->masters = NULL;
4356         }
4357         if (zone->masterkeynames != NULL) {
4358                 for (i = 0; i < zone->masterscnt; i++) {
4359                         if (zone->masterkeynames[i] != NULL) {
4360                                 dns_name_free(zone->masterkeynames[i],
4361                                               zone->mctx);
4362                                 isc_mem_put(zone->mctx,
4363                                             zone->masterkeynames[i],
4364                                             sizeof(dns_name_t));
4365                                 zone->masterkeynames[i] = NULL;
4366                         }
4367                 }
4368                 isc_mem_put(zone->mctx, zone->masterkeynames,
4369                             zone->masterscnt * sizeof(dns_name_t *));
4370                 zone->masterkeynames = NULL;
4371         }
4372         if (zone->mastersok != NULL) {
4373                 isc_mem_put(zone->mctx, zone->mastersok,
4374                             zone->masterscnt * sizeof(isc_boolean_t));
4375                 zone->mastersok = NULL;
4376         }
4377         zone->masterscnt = 0;
4378         /*
4379          * If count == 0, don't allocate any space for masters, mastersok or
4380          * keynames so internally, those pointers are NULL if count == 0
4381          */
4382         if (count == 0)
4383                 goto unlock;
4384
4385         /*
4386          * masters must contain count elements!
4387          */
4388         new = isc_mem_get(zone->mctx, count * sizeof(*new));
4389         if (new == NULL) {
4390                 result = ISC_R_NOMEMORY;
4391                 goto unlock;
4392         }
4393         memcpy(new, masters, count * sizeof(*new));
4394
4395         /*
4396          * Similarly for mastersok.
4397          */
4398         newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
4399         if (newok == NULL) {
4400                 result = ISC_R_NOMEMORY;
4401                 isc_mem_put(zone->mctx, new, count * sizeof(*new));
4402                 goto unlock;
4403         };
4404         for (i = 0; i < count; i++)
4405                 newok[i] = ISC_FALSE;
4406
4407         /*
4408          * if keynames is non-NULL, it must contain count elements!
4409          */
4410         newname = NULL;
4411         if (keynames != NULL) {
4412                 newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
4413                 if (newname == NULL) {
4414                         result = ISC_R_NOMEMORY;
4415                         isc_mem_put(zone->mctx, new, count * sizeof(*new));
4416                         isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
4417                         goto unlock;
4418                 }
4419                 for (i = 0; i < count; i++)
4420                         newname[i] = NULL;
4421                 for (i = 0; i < count; i++) {
4422                         if (keynames[i] != NULL) {
4423                                 newname[i] = isc_mem_get(zone->mctx,
4424                                                          sizeof(dns_name_t));
4425                                 if (newname[i] == NULL)
4426                                         goto allocfail;
4427                                 dns_name_init(newname[i], NULL);
4428                                 result = dns_name_dup(keynames[i], zone->mctx,
4429                                                       newname[i]);
4430                                 if (result != ISC_R_SUCCESS) {
4431                                 allocfail:
4432                                         for (i = 0; i < count; i++)
4433                                                 if (newname[i] != NULL)
4434                                                         dns_name_free(
4435                                                                newname[i],
4436                                                                zone->mctx);
4437                                         isc_mem_put(zone->mctx, new,
4438                                                     count * sizeof(*new));
4439                                         isc_mem_put(zone->mctx, newok,
4440                                                     count * sizeof(*newok));
4441                                         isc_mem_put(zone->mctx, newname,
4442                                                     count * sizeof(*newname));
4443                                         goto unlock;
4444                                 }
4445                         }
4446                 }
4447         }
4448
4449         /*
4450          * Everything is ok so attach to the zone.
4451          */
4452         zone->curmaster = 0;
4453         zone->masters = new;
4454         zone->mastersok = newok;
4455         zone->masterkeynames = newname;
4456         zone->masterscnt = count;
4457         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
4458
4459  unlock:
4460         UNLOCK_ZONE(zone);
4461         return (result);
4462 }
4463
4464 isc_result_t
4465 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
4466         isc_result_t result = ISC_R_SUCCESS;
4467
4468         REQUIRE(DNS_ZONE_VALID(zone));
4469
4470         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4471         if (zone->db == NULL)
4472                 result = DNS_R_NOTLOADED;
4473         else
4474                 dns_db_attach(zone->db, dpb);
4475         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4476
4477         return (result);
4478 }
4479
4480 void
4481 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
4482         REQUIRE(DNS_ZONE_VALID(zone));
4483         REQUIRE(zone->type == dns_zone_staticstub);
4484
4485         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4486         REQUIRE(zone->db == NULL);
4487         dns_db_attach(db, &zone->db);
4488         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4489 }
4490
4491 /*
4492  * Co-ordinates the starting of routine jobs.
4493  */
4494
4495 void
4496 dns_zone_maintenance(dns_zone_t *zone) {
4497         const char me[] = "dns_zone_maintenance";
4498         isc_time_t now;
4499
4500         REQUIRE(DNS_ZONE_VALID(zone));
4501         ENTER;
4502
4503         LOCK_ZONE(zone);
4504         TIME_NOW(&now);
4505         zone_settimer(zone, &now);
4506         UNLOCK_ZONE(zone);
4507 }
4508
4509 static inline isc_boolean_t
4510 was_dumping(dns_zone_t *zone) {
4511         isc_boolean_t dumping;
4512
4513         REQUIRE(LOCKED_ZONE(zone));
4514
4515         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
4516         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
4517         if (!dumping) {
4518                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
4519                 isc_time_settoepoch(&zone->dumptime);
4520         }
4521         return (dumping);
4522 }
4523
4524 static isc_result_t
4525 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4526                isc_mem_t *mctx, unsigned int maxkeys,
4527                dst_key_t **keys, unsigned int *nkeys)
4528 {
4529         isc_result_t result;
4530         dns_dbnode_t *node = NULL;
4531         const char *directory = dns_zone_getkeydirectory(zone);
4532
4533         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
4534         result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
4535                                           directory, mctx, maxkeys, keys,
4536                                           nkeys);
4537         if (result == ISC_R_NOTFOUND)
4538                 result = ISC_R_SUCCESS;
4539  failure:
4540         if (node != NULL)
4541                 dns_db_detachnode(db, &node);
4542         return (result);
4543 }
4544
4545 static isc_result_t
4546 offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name,
4547         dns_ttl_t ttl, dns_rdata_t *rdata)
4548 {
4549         isc_result_t result;
4550
4551         if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
4552                 return (ISC_R_SUCCESS);
4553         result = update_one_rr(db, ver, diff, DNS_DIFFOP_DELRESIGN,
4554                                name, ttl, rdata);
4555         if (result != ISC_R_SUCCESS)
4556                 return (result);
4557         rdata->flags |= DNS_RDATA_OFFLINE;
4558         result = update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
4559                                name, ttl, rdata);
4560         return (result);
4561 }
4562
4563 static void
4564 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
4565 {
4566         unsigned int delta;
4567         char timebuf[80];
4568
4569         zone->key_expiry = when;
4570         if (when <= now) {
4571                 dns_zone_log(zone, ISC_LOG_ERROR,
4572                              "DNSKEY RRSIG(s) have expired");
4573                 isc_time_settoepoch(&zone->keywarntime);
4574         } else if (when < now + 7 * 24 * 3600) {
4575                 isc_time_t t;
4576                 isc_time_set(&t, when, 0);
4577                 isc_time_formattimestamp(&t, timebuf, 80);
4578                 dns_zone_log(zone, ISC_LOG_WARNING,
4579                              "DNSKEY RRSIG(s) will expire within 7 days: %s",
4580                              timebuf);
4581                 delta = when - now;
4582                 delta--;                /* loop prevention */
4583                 delta /= 24 * 3600;     /* to whole days */
4584                 delta *= 24 * 3600;     /* to seconds */
4585                 isc_time_set(&zone->keywarntime, when - delta, 0);
4586         }  else {
4587                 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
4588                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4589                 dns_zone_log(zone, ISC_LOG_NOTICE,
4590                              "setting keywarntime to %s", timebuf);
4591         }
4592 }
4593
4594 /*
4595  * Helper function to del_sigs(). We don't want to delete RRSIGs that
4596  * have no new key.
4597  */
4598 static isc_boolean_t
4599 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys) {
4600         unsigned int i = 0;
4601
4602         /*
4603          * It's okay to delete a signature if there is an active ZSK
4604          * with the same algorithm
4605          */
4606         for (i = 0; i < nkeys; i++) {
4607                 if (rrsig_ptr->algorithm == dst_key_alg(keys[i]) &&
4608                     (dst_key_isprivate(keys[i])) && !KSK(keys[i]))
4609                         return (ISC_TRUE);
4610         }
4611
4612         /*
4613          * Failing that, it is *not* okay to delete a signature
4614          * if the associated public key is still in the DNSKEY RRset
4615          */
4616         for (i = 0; i < nkeys; i++) {
4617                 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
4618                     (rrsig_ptr->keyid == dst_key_id(keys[i])))
4619                         return (ISC_FALSE);
4620         }
4621
4622         /*
4623          * But if the key is gone, then go ahead.
4624          */
4625         return (ISC_TRUE);
4626 }
4627
4628 /*
4629  * Delete expired RRsigs and any RRsigs we are about to re-sign.
4630  * See also update.c:del_keysigs().
4631  */
4632 static isc_result_t
4633 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
4634          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
4635          unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
4636 {
4637         isc_result_t result;
4638         dns_dbnode_t *node = NULL;
4639         dns_rdataset_t rdataset;
4640         unsigned int i;
4641         dns_rdata_rrsig_t rrsig;
4642         isc_boolean_t found, changed;
4643         isc_int64_t warn = 0, maybe = 0;
4644
4645         dns_rdataset_init(&rdataset);
4646
4647         if (type == dns_rdatatype_nsec3)
4648                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
4649         else
4650                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
4651         if (result == ISC_R_NOTFOUND)
4652                 return (ISC_R_SUCCESS);
4653         if (result != ISC_R_SUCCESS)
4654                 goto failure;
4655         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
4656                                      (isc_stdtime_t) 0, &rdataset, NULL);
4657         dns_db_detachnode(db, &node);
4658
4659         if (result == ISC_R_NOTFOUND) {
4660                 INSIST(!dns_rdataset_isassociated(&rdataset));
4661                 return (ISC_R_SUCCESS);
4662         }
4663         if (result != ISC_R_SUCCESS) {
4664                 INSIST(!dns_rdataset_isassociated(&rdataset));
4665                 goto failure;
4666         }
4667
4668         changed = ISC_FALSE;
4669         for (result = dns_rdataset_first(&rdataset);
4670              result == ISC_R_SUCCESS;
4671              result = dns_rdataset_next(&rdataset)) {
4672                 dns_rdata_t rdata = DNS_RDATA_INIT;
4673
4674                 dns_rdataset_current(&rdataset, &rdata);
4675                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
4676                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4677
4678                 if (type != dns_rdatatype_dnskey) {
4679                         if (delsig_ok(&rrsig, keys, nkeys)) {
4680                                 result = update_one_rr(db, ver, diff,
4681                                                DNS_DIFFOP_DELRESIGN, name,
4682                                                rdataset.ttl, &rdata);
4683                                 if (incremental)
4684                                         changed = ISC_TRUE;
4685                                 if (result != ISC_R_SUCCESS)
4686                                         break;
4687                         } else {
4688                                 /*
4689                                  * At this point, we've got an RRSIG,
4690                                  * which is signed by an inactive key.
4691                                  * An administrator needs to provide a new
4692                                  * key/alg, but until that time, we want to
4693                                  * keep the old RRSIG.  Marking the key as
4694                                  * offline will prevent us spinning waiting
4695                                  * for the private part.
4696                                  */
4697                                 if (incremental) {
4698                                         result = offline(db, ver, diff, name,
4699                                                          rdataset.ttl, &rdata);
4700                                         changed = ISC_TRUE;
4701                                         if (result != ISC_R_SUCCESS)
4702                                                 break;
4703                                 }
4704
4705                                 /*
4706                                  * Log the key id and algorithm of
4707                                  * the inactive key with no replacement
4708                                  */
4709                                 if (zone->log_key_expired_timer <= now) {
4710                                         char origin[DNS_NAME_FORMATSIZE];
4711                                         char algbuf[DNS_NAME_FORMATSIZE];
4712                                         dns_name_format(&zone->origin, origin,
4713                                                         sizeof(origin));
4714                                         dns_secalg_format(rrsig.algorithm,
4715                                                           algbuf,
4716                                                           sizeof(algbuf));
4717                                         dns_zone_log(zone, ISC_LOG_WARNING,
4718                                                      "Key %s/%s/%d "
4719                                                      "missing or inactive "
4720                                                      "and has no replacement: "
4721                                                      "retaining signatures.",
4722                                                      origin, algbuf,
4723                                                      rrsig.keyid);
4724                                         zone->log_key_expired_timer = now +
4725                                                                         3600;
4726                                 }
4727                         }
4728                         continue;
4729                 }
4730
4731                 /*
4732                  * RRSIG(DNSKEY) requires special processing.
4733                  */
4734                 found = ISC_FALSE;
4735                 for (i = 0; i < nkeys; i++) {
4736                         if (rrsig.algorithm == dst_key_alg(keys[i]) &&
4737                             rrsig.keyid == dst_key_id(keys[i])) {
4738                                 found = ISC_TRUE;
4739                                 /*
4740                                  * Mark offline RRSIG(DNSKEY).
4741                                  * We want the earliest offline expire time
4742                                  * iff there is a new offline signature.
4743                                  */
4744                                 if (!dst_key_isprivate(keys[i])) {
4745                                         isc_int64_t timeexpire =
4746                                            dns_time64_from32(rrsig.timeexpire);
4747                                         if (warn != 0 && warn > timeexpire)
4748                                                 warn = timeexpire;
4749                                         if (rdata.flags & DNS_RDATA_OFFLINE) {
4750                                                 if (maybe == 0 ||
4751                                                     maybe > timeexpire)
4752                                                         maybe = timeexpire;
4753                                                 break;
4754                                         }
4755                                         if (warn == 0)
4756                                                 warn = maybe;
4757                                         if (warn == 0 || warn > timeexpire)
4758                                                 warn = timeexpire;
4759                                         result = offline(db, ver, diff, name,
4760                                                          rdataset.ttl, &rdata);
4761                                         break;
4762                                 }
4763                                 result = update_one_rr(db, ver, diff,
4764                                                        DNS_DIFFOP_DELRESIGN,
4765                                                        name, rdataset.ttl,
4766                                                        &rdata);
4767                                 break;
4768                         }
4769                 }
4770
4771                 /*
4772                  * If there is not a matching DNSKEY then
4773                  * delete the RRSIG.
4774                  */
4775                 if (!found)
4776                         result = update_one_rr(db, ver, diff,
4777                                                DNS_DIFFOP_DELRESIGN, name,
4778                                                rdataset.ttl, &rdata);
4779                 if (result != ISC_R_SUCCESS)
4780                         break;
4781         }
4782
4783         if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0)
4784                 dns_db_resigned(db, &rdataset, ver);
4785
4786         dns_rdataset_disassociate(&rdataset);
4787         if (result == ISC_R_NOMORE)
4788                 result = ISC_R_SUCCESS;
4789         if (warn > 0) {
4790 #if defined(STDTIME_ON_32BITS)
4791                 isc_stdtime_t stdwarn = (isc_stdtime_t)warn;
4792                 if (warn == stdwarn)
4793 #endif
4794                         set_key_expiry_warning(zone, (isc_stdtime_t)warn, now);
4795 #if defined(STDTIME_ON_32BITS)
4796                 else
4797                         dns_zone_log(zone, ISC_LOG_ERROR,
4798                                      "key expiry warning time out of range");
4799 #endif
4800         }
4801  failure:
4802         if (node != NULL)
4803                 dns_db_detachnode(db, &node);
4804         return (result);
4805 }
4806
4807 static isc_result_t
4808 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
4809          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
4810          unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
4811          isc_stdtime_t expire, isc_boolean_t check_ksk,
4812          isc_boolean_t keyset_kskonly)
4813 {
4814         isc_result_t result;
4815         dns_dbnode_t *node = NULL;
4816         dns_rdataset_t rdataset;
4817         dns_rdata_t sig_rdata = DNS_RDATA_INIT;
4818         unsigned char data[1024]; /* XXX */
4819         isc_buffer_t buffer;
4820         unsigned int i, j;
4821
4822         dns_rdataset_init(&rdataset);
4823         isc_buffer_init(&buffer, data, sizeof(data));
4824
4825         if (type == dns_rdatatype_nsec3)
4826                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
4827         else
4828                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
4829         if (result == ISC_R_NOTFOUND)
4830                 return (ISC_R_SUCCESS);
4831         if (result != ISC_R_SUCCESS)
4832                 goto failure;
4833         result = dns_db_findrdataset(db, node, ver, type, 0,
4834                                      (isc_stdtime_t) 0, &rdataset, NULL);
4835         dns_db_detachnode(db, &node);
4836         if (result == ISC_R_NOTFOUND) {
4837                 INSIST(!dns_rdataset_isassociated(&rdataset));
4838                 return (ISC_R_SUCCESS);
4839         }
4840         if (result != ISC_R_SUCCESS) {
4841                 INSIST(!dns_rdataset_isassociated(&rdataset));
4842                 goto failure;
4843         }
4844
4845         for (i = 0; i < nkeys; i++) {
4846                 isc_boolean_t both = ISC_FALSE;
4847
4848                 if (!dst_key_isprivate(keys[i]))
4849                         continue;
4850
4851                 if (check_ksk && !REVOKE(keys[i])) {
4852                         isc_boolean_t have_ksk, have_nonksk;
4853                         if (KSK(keys[i])) {
4854                                 have_ksk = ISC_TRUE;
4855                                 have_nonksk = ISC_FALSE;
4856                         } else {
4857                                 have_ksk = ISC_FALSE;
4858                                 have_nonksk = ISC_TRUE;
4859                         }
4860                         for (j = 0; j < nkeys; j++) {
4861                                 if (j == i || ALG(keys[i]) != ALG(keys[j]))
4862                                         continue;
4863                                 if (REVOKE(keys[j]))
4864                                         continue;
4865                                 if (KSK(keys[j]))
4866                                         have_ksk = ISC_TRUE;
4867                                 else
4868                                         have_nonksk = ISC_TRUE;
4869                                 both = have_ksk && have_nonksk;
4870                                 if (both)
4871                                         break;
4872                         }
4873                 }
4874                 if (both) {
4875                         if (type == dns_rdatatype_dnskey) {
4876                                 if (!KSK(keys[i]) && keyset_kskonly)
4877                                         continue;
4878                         } else if (KSK(keys[i]))
4879                                 continue;
4880                 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
4881                                 continue;
4882
4883                 /* Calculate the signature, creating a RRSIG RDATA. */
4884                 isc_buffer_clear(&buffer);
4885                 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
4886                                       &inception, &expire,
4887                                       mctx, &buffer, &sig_rdata));
4888                 /* Update the database and journal with the RRSIG. */
4889                 /* XXX inefficient - will cause dataset merging */
4890                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
4891                                     name, rdataset.ttl, &sig_rdata));
4892                 dns_rdata_reset(&sig_rdata);
4893                 isc_buffer_init(&buffer, data, sizeof(data));
4894         }
4895
4896  failure:
4897         if (dns_rdataset_isassociated(&rdataset))
4898                 dns_rdataset_disassociate(&rdataset);
4899         if (node != NULL)
4900                 dns_db_detachnode(db, &node);
4901         return (result);
4902 }
4903
4904 static void
4905 zone_resigninc(dns_zone_t *zone) {
4906         dns_db_t *db = NULL;
4907         dns_dbversion_t *version = NULL;
4908         dns_diff_t sig_diff;
4909         dns_fixedname_t fixed;
4910         dns_name_t *name;
4911         dns_rdataset_t rdataset;
4912         dns_rdatatype_t covers;
4913         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
4914         isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
4915         isc_result_t result;
4916         isc_stdtime_t now, inception, soaexpire, expire, stop;
4917         isc_uint32_t jitter;
4918         unsigned int i;
4919         unsigned int nkeys = 0;
4920         unsigned int resign;
4921
4922         dns_rdataset_init(&rdataset);
4923         dns_fixedname_init(&fixed);
4924         dns_diff_init(zone->mctx, &sig_diff);
4925         sig_diff.resign = zone->sigresigninginterval;
4926
4927         /*
4928          * Updates are disabled.  Pause for 5 minutes.
4929          */
4930         if (zone->update_disabled) {
4931                 result = ISC_R_FAILURE;
4932                 goto failure;
4933         }
4934
4935         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4936         dns_db_attach(zone->db, &db);
4937         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4938
4939         result = dns_db_newversion(db, &version);
4940         if (result != ISC_R_SUCCESS) {
4941                 dns_zone_log(zone, ISC_LOG_ERROR,
4942                              "zone_resigninc:dns_db_newversion -> %s",
4943                              dns_result_totext(result));
4944                 goto failure;
4945         }
4946
4947         result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
4948                                 zone_keys, &nkeys);
4949         if (result != ISC_R_SUCCESS) {
4950                 dns_zone_log(zone, ISC_LOG_ERROR,
4951                              "zone_resigninc:find_zone_keys -> %s",
4952                              dns_result_totext(result));
4953                 goto failure;
4954         }
4955
4956         isc_stdtime_get(&now);
4957         inception = now - 3600; /* Allow for clock skew. */
4958         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
4959         /*
4960          * Spread out signatures over time if they happen to be
4961          * clumped.  We don't do this for each add_sigs() call as
4962          * we still want some clustering to occur.
4963          */
4964         isc_random_get(&jitter);
4965         expire = soaexpire - jitter % 3600;
4966         stop = now + 5;
4967
4968         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
4969         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
4970
4971         name = dns_fixedname_name(&fixed);
4972         result = dns_db_getsigningtime(db, &rdataset, name);
4973         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
4974                 dns_zone_log(zone, ISC_LOG_ERROR,
4975                              "zone_resigninc:dns_db_getsigningtime -> %s",
4976                              dns_result_totext(result));
4977         }
4978
4979         i = 0;
4980         while (result == ISC_R_SUCCESS) {
4981                 resign = rdataset.resign;
4982                 covers = rdataset.covers;
4983                 dns_rdataset_disassociate(&rdataset);
4984
4985                 /*
4986                  * Stop if we hit the SOA as that means we have walked the
4987                  * entire zone.  The SOA record should always be the most
4988                  * recent signature.
4989                  */
4990                 /* XXXMPA increase number of RRsets signed pre call */
4991                 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
4992                     resign > stop)
4993                         break;
4994
4995                 result = del_sigs(zone, db, version, name, covers, &sig_diff,
4996                                   zone_keys, nkeys, now, ISC_TRUE);
4997                 if (result != ISC_R_SUCCESS) {
4998                         dns_zone_log(zone, ISC_LOG_ERROR,
4999                                      "zone_resigninc:del_sigs -> %s",
5000                                      dns_result_totext(result));
5001                         break;
5002                 }
5003
5004                 result = add_sigs(db, version, name, covers, &sig_diff,
5005                                   zone_keys, nkeys, zone->mctx, inception,
5006                                   expire, check_ksk, keyset_kskonly);
5007                 if (result != ISC_R_SUCCESS) {
5008                         dns_zone_log(zone, ISC_LOG_ERROR,
5009                                      "zone_resigninc:add_sigs -> %s",
5010                                      dns_result_totext(result));
5011                         break;
5012                 }
5013                 result  = dns_db_getsigningtime(db, &rdataset,
5014                                                 dns_fixedname_name(&fixed));
5015                 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
5016                         result = ISC_R_SUCCESS;
5017                         break;
5018                 }
5019                 if (result != ISC_R_SUCCESS)
5020                         dns_zone_log(zone, ISC_LOG_ERROR,
5021                              "zone_resigninc:dns_db_getsigningtime -> %s",
5022                                      dns_result_totext(result));
5023         }
5024
5025         if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
5026                 goto failure;
5027
5028         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5029                           &sig_diff, zone_keys, nkeys, now, ISC_TRUE);
5030         if (result != ISC_R_SUCCESS) {
5031                 dns_zone_log(zone, ISC_LOG_ERROR,
5032                              "zone_resigninc:del_sigs -> %s",
5033                              dns_result_totext(result));
5034                 goto failure;
5035         }
5036
5037         /*
5038          * Did we change anything in the zone?
5039          */
5040         if (ISC_LIST_EMPTY(sig_diff.tuples))
5041                 goto failure;
5042
5043         /* Increment SOA serial if we have made changes */
5044         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
5045         if (result != ISC_R_SUCCESS) {
5046                 dns_zone_log(zone, ISC_LOG_ERROR,
5047                              "zone_resigninc:increment_soa_serial -> %s",
5048                              dns_result_totext(result));
5049                 goto failure;
5050         }
5051
5052         /*
5053          * Generate maximum life time signatures so that the above loop
5054          * termination is sensible.
5055          */
5056         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5057                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
5058                           soaexpire, check_ksk, keyset_kskonly);
5059         if (result != ISC_R_SUCCESS) {
5060                 dns_zone_log(zone, ISC_LOG_ERROR,
5061                              "zone_resigninc:add_sigs -> %s",
5062                              dns_result_totext(result));
5063                 goto failure;
5064         }
5065
5066         /* Write changes to journal file. */
5067         CHECK(zone_journal(zone, &sig_diff, "zone_resigninc"));
5068
5069         /* Everything has succeeded. Commit the changes. */
5070         dns_db_closeversion(db, &version, ISC_TRUE);
5071
5072  failure:
5073         dns_diff_clear(&sig_diff);
5074         for (i = 0; i < nkeys; i++)
5075                 dst_key_free(&zone_keys[i]);
5076         if (version != NULL) {
5077                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
5078                 dns_db_detach(&db);
5079         } else if (db != NULL)
5080                 dns_db_detach(&db);
5081         if (result == ISC_R_SUCCESS) {
5082                 set_resigntime(zone);
5083                 LOCK_ZONE(zone);
5084                 zone_needdump(zone, DNS_DUMP_DELAY);
5085                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5086                 UNLOCK_ZONE(zone);
5087         } else {
5088                 /*
5089                  * Something failed.  Retry in 5 minutes.
5090                  */
5091                 isc_interval_t ival;
5092                 isc_interval_set(&ival, 300, 0);
5093                 isc_time_nowplusinterval(&zone->resigntime, &ival);
5094         }
5095 }
5096
5097 static isc_result_t
5098 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
5099             dns_name_t *newname, isc_boolean_t bottom)
5100 {
5101         isc_result_t result;
5102         dns_dbiterator_t *dbit = NULL;
5103         dns_rdatasetiter_t *rdsit = NULL;
5104         dns_dbnode_t *node = NULL;
5105
5106         CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
5107         CHECK(dns_dbiterator_seek(dbit, oldname));
5108         do {
5109                 result = dns_dbiterator_next(dbit);
5110                 if (result == ISC_R_NOMORE)
5111                         CHECK(dns_dbiterator_first(dbit));
5112                 CHECK(dns_dbiterator_current(dbit, &node, newname));
5113                 if (bottom && dns_name_issubdomain(newname, oldname) &&
5114                     !dns_name_equal(newname, oldname)) {
5115                         dns_db_detachnode(db, &node);
5116                         continue;
5117                 }
5118                 /*
5119                  * Is this node empty?
5120                  */
5121                 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
5122                 result = dns_rdatasetiter_first(rdsit);
5123                 dns_db_detachnode(db, &node);
5124                 dns_rdatasetiter_destroy(&rdsit);
5125                 if (result != ISC_R_NOMORE)
5126                         break;
5127         } while (1);
5128  failure:
5129         if (node != NULL)
5130                 dns_db_detachnode(db, &node);
5131         if (dbit != NULL)
5132                 dns_dbiterator_destroy(&dbit);
5133         return (result);
5134 }
5135
5136 static isc_boolean_t
5137 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5138                 dns_rdatatype_t type, dst_key_t *key)
5139 {
5140         isc_result_t result;
5141         dns_rdataset_t rdataset;
5142         dns_rdata_t rdata = DNS_RDATA_INIT;
5143         dns_rdata_rrsig_t rrsig;
5144
5145         dns_rdataset_init(&rdataset);
5146         result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
5147                                      type, 0, &rdataset, NULL);
5148         if (result != ISC_R_SUCCESS) {
5149                 INSIST(!dns_rdataset_isassociated(&rdataset));
5150                 return (ISC_FALSE);
5151         }
5152         for (result = dns_rdataset_first(&rdataset);
5153              result == ISC_R_SUCCESS;
5154              result = dns_rdataset_next(&rdataset)) {
5155                 dns_rdataset_current(&rdataset, &rdata);
5156                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5157                 INSIST(result == ISC_R_SUCCESS);
5158                 if (rrsig.algorithm == dst_key_alg(key) &&
5159                     rrsig.keyid == dst_key_id(key)) {
5160                         dns_rdataset_disassociate(&rdataset);
5161                         return (ISC_TRUE);
5162                 }
5163                 dns_rdata_reset(&rdata);
5164         }
5165         dns_rdataset_disassociate(&rdataset);
5166         return (ISC_FALSE);
5167 }
5168
5169 static isc_result_t
5170 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5171          dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
5172          dns_diff_t *diff)
5173 {
5174         dns_fixedname_t fixed;
5175         dns_name_t *next;
5176         dns_rdata_t rdata = DNS_RDATA_INIT;
5177         isc_result_t result;
5178         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
5179
5180         dns_fixedname_init(&fixed);
5181         next = dns_fixedname_name(&fixed);
5182
5183         CHECK(next_active(db, version, name, next, bottom));
5184         CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
5185                                   &rdata));
5186         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
5187                             &rdata));
5188  failure:
5189         return (result);
5190 }
5191
5192 static isc_result_t
5193 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
5194             dns_dbversion_t *version, isc_boolean_t build_nsec3,
5195             isc_boolean_t build_nsec, dst_key_t *key,
5196             isc_stdtime_t inception, isc_stdtime_t expire,
5197             unsigned int minimum, isc_boolean_t is_ksk,
5198             isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
5199             dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
5200 {
5201         isc_result_t result;
5202         dns_rdatasetiter_t *iterator = NULL;
5203         dns_rdataset_t rdataset;
5204         dns_rdata_t rdata = DNS_RDATA_INIT;
5205         isc_buffer_t buffer;
5206         unsigned char data[1024];
5207         isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
5208                       seen_nsec3, seen_ds;
5209         isc_boolean_t bottom;
5210
5211         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5212         if (result != ISC_R_SUCCESS) {
5213                 if (result == ISC_R_NOTFOUND)
5214                         result = ISC_R_SUCCESS;
5215                 return (result);
5216         }
5217
5218         dns_rdataset_init(&rdataset);
5219         isc_buffer_init(&buffer, data, sizeof(data));
5220         seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
5221         seen_nsec3 = seen_ds = ISC_FALSE;
5222         for (result = dns_rdatasetiter_first(iterator);
5223              result == ISC_R_SUCCESS;
5224              result = dns_rdatasetiter_next(iterator)) {
5225                 dns_rdatasetiter_current(iterator, &rdataset);
5226                 if (rdataset.type == dns_rdatatype_soa)
5227                         seen_soa = ISC_TRUE;
5228                 else if (rdataset.type == dns_rdatatype_ns)
5229                         seen_ns = ISC_TRUE;
5230                 else if (rdataset.type == dns_rdatatype_ds)
5231                         seen_ds = ISC_TRUE;
5232                 else if (rdataset.type == dns_rdatatype_dname)
5233                         seen_dname = ISC_TRUE;
5234                 else if (rdataset.type == dns_rdatatype_nsec)
5235                         seen_nsec = ISC_TRUE;
5236                 else if (rdataset.type == dns_rdatatype_nsec3)
5237                         seen_nsec3 = ISC_TRUE;
5238                 if (rdataset.type != dns_rdatatype_rrsig)
5239                         seen_rr = ISC_TRUE;
5240                 dns_rdataset_disassociate(&rdataset);
5241         }
5242         if (result != ISC_R_NOMORE)
5243                 goto failure;
5244         if (seen_ns && !seen_soa)
5245                 *delegation = ISC_TRUE;
5246         /*
5247          * Going from insecure to NSEC3.
5248          * Don't generate NSEC3 records for NSEC3 records.
5249          */
5250         if (build_nsec3 && !seen_nsec3 && seen_rr) {
5251                 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
5252                 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
5253                                           unsecure, diff));
5254                 (*signatures)--;
5255         }
5256         /*
5257          * Going from insecure to NSEC.
5258          * Don't generate NSEC records for NSEC3 records.
5259          */
5260         if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
5261                 /* Build and add NSEC. */
5262                 bottom = (seen_ns && !seen_soa) || seen_dname;
5263                 /*
5264                  * Build a NSEC record except at the origin.
5265                  */
5266                 if (!dns_name_equal(name, dns_db_origin(db))) {
5267                         CHECK(add_nsec(db, version, name, node, minimum,
5268                                        bottom, diff));
5269                         /* Count a NSEC generation as a signature generation. */
5270                         (*signatures)--;
5271                 }
5272         }
5273         result = dns_rdatasetiter_first(iterator);
5274         while (result == ISC_R_SUCCESS) {
5275                 dns_rdatasetiter_current(iterator, &rdataset);
5276                 if (rdataset.type == dns_rdatatype_soa ||
5277                     rdataset.type == dns_rdatatype_rrsig)
5278                         goto next_rdataset;
5279                 if (rdataset.type == dns_rdatatype_dnskey) {
5280                         if (!is_ksk && keyset_kskonly)
5281                                 goto next_rdataset;
5282                 } else if (is_ksk)
5283                         goto next_rdataset;
5284                 if (*delegation &&
5285                     rdataset.type != dns_rdatatype_ds &&
5286                     rdataset.type != dns_rdatatype_nsec)
5287                         goto next_rdataset;
5288                 if (signed_with_key(db, node, version, rdataset.type, key))
5289                         goto next_rdataset;
5290                 /* Calculate the signature, creating a RRSIG RDATA. */
5291                 isc_buffer_clear(&buffer);
5292                 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
5293                                       &expire, mctx, &buffer, &rdata));
5294                 /* Update the database and journal with the RRSIG. */
5295                 /* XXX inefficient - will cause dataset merging */
5296                 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
5297                                     name, rdataset.ttl, &rdata));
5298                 dns_rdata_reset(&rdata);
5299                 (*signatures)--;
5300  next_rdataset:
5301                 dns_rdataset_disassociate(&rdataset);
5302                 result = dns_rdatasetiter_next(iterator);
5303         }
5304         if (result == ISC_R_NOMORE)
5305                 result = ISC_R_SUCCESS;
5306         if (seen_dname)
5307                 *delegation = ISC_TRUE;
5308  failure:
5309         if (dns_rdataset_isassociated(&rdataset))
5310                 dns_rdataset_disassociate(&rdataset);
5311         if (iterator != NULL)
5312                 dns_rdatasetiter_destroy(&iterator);
5313         return (result);
5314 }
5315
5316 /*
5317  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
5318  */
5319 static isc_result_t
5320 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5321              dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
5322 {
5323         isc_result_t result;
5324         dns_rdataset_t rdataset;
5325         dns_dbnode_t *node = NULL;
5326
5327         CHECK(dns_db_getoriginnode(db, &node));
5328         if (update_only) {
5329                 dns_rdataset_init(&rdataset);
5330                 result = dns_db_findrdataset(db, node, version,
5331                                              dns_rdatatype_nsec,
5332                                              dns_rdatatype_none,
5333                                              0, &rdataset, NULL);
5334                 if (dns_rdataset_isassociated(&rdataset))
5335                         dns_rdataset_disassociate(&rdataset);
5336                 if (result == ISC_R_NOTFOUND)
5337                         goto success;
5338                 if (result != ISC_R_SUCCESS)
5339                         goto failure;
5340         }
5341         CHECK(delete_nsec(db, version, node, name, diff));
5342         CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
5343  success:
5344         result = ISC_R_SUCCESS;
5345  failure:
5346         if (node != NULL)
5347                 dns_db_detachnode(db, &node);
5348         return (result);
5349 }
5350
5351 static isc_result_t
5352 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
5353                   dns_dbversion_t *version, isc_boolean_t build_nsec3,
5354                   dns_ttl_t minimum, dns_diff_t *diff)
5355 {
5356         isc_result_t result;
5357         dns_dbnode_t *node = NULL;
5358         dns_rdataset_t rdataset;
5359         dns_rdata_t rdata = DNS_RDATA_INIT;
5360         unsigned char data[5];
5361         isc_boolean_t seen_done = ISC_FALSE;
5362         isc_boolean_t have_rr = ISC_FALSE;
5363
5364         dns_rdataset_init(&rdataset);
5365         result = dns_db_getoriginnode(signing->db, &node);
5366         if (result != ISC_R_SUCCESS)
5367                 goto failure;
5368
5369         result = dns_db_findrdataset(signing->db, node, version,
5370                                      zone->privatetype, dns_rdatatype_none,
5371                                      0, &rdataset, NULL);
5372         if (result == ISC_R_NOTFOUND) {
5373                 INSIST(!dns_rdataset_isassociated(&rdataset));
5374                 result = ISC_R_SUCCESS;
5375                 goto failure;
5376         }
5377         if (result != ISC_R_SUCCESS) {
5378                 INSIST(!dns_rdataset_isassociated(&rdataset));
5379                 goto failure;
5380         }
5381         for (result = dns_rdataset_first(&rdataset);
5382              result == ISC_R_SUCCESS;
5383              result = dns_rdataset_next(&rdataset)) {
5384                 dns_rdataset_current(&rdataset, &rdata);
5385                 /*
5386                  * If we don't match the algorithm or keyid skip the record.
5387                  */
5388                 if (rdata.length != 5 ||
5389                     rdata.data[0] != signing->algorithm ||
5390                     rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
5391                     rdata.data[2] != (signing->keyid & 0xff)) {
5392                         have_rr = ISC_TRUE;
5393                         dns_rdata_reset(&rdata);
5394                         continue;
5395                 }
5396                 /*
5397                  * We have a match.  If we were signing (!signing->delete)
5398                  * and we already have a record indicating that we have
5399                  * finished signing (rdata.data[4] != 0) then keep it.
5400                  * Otherwise it needs to be deleted as we have removed all
5401                  * the signatures (signing->delete), so any record indicating
5402                  * completion is now out of date, or we have finished signing
5403                  * with the new record so we no longer need to remember that
5404                  * we need to sign the zone with the matching key across a
5405                  * nameserver re-start.
5406                  */
5407                 if (!signing->delete && rdata.data[4] != 0) {
5408                         seen_done = ISC_TRUE;
5409                         have_rr = ISC_TRUE;
5410                 } else
5411                         CHECK(update_one_rr(signing->db, version, diff,
5412                                             DNS_DIFFOP_DEL, &zone->origin,
5413                                             rdataset.ttl, &rdata));
5414                 dns_rdata_reset(&rdata);
5415         }
5416         if (result == ISC_R_NOMORE)
5417                 result = ISC_R_SUCCESS;
5418         if (!signing->delete && !seen_done) {
5419                 /*
5420                  * If we were signing then we need to indicate that we have
5421                  * finished signing the zone with this key.  If it is already
5422                  * there we don't need to add it a second time.
5423                  */
5424                 data[0] = signing->algorithm;
5425                 data[1] = (signing->keyid >> 8) & 0xff;
5426                 data[2] = signing->keyid & 0xff;
5427                 data[3] = 0;
5428                 data[4] = 1;
5429                 rdata.length = sizeof(data);
5430                 rdata.data = data;
5431                 rdata.type = zone->privatetype;
5432                 rdata.rdclass = dns_db_class(signing->db);
5433                 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
5434                                     &zone->origin, rdataset.ttl, &rdata));
5435         } else if (!have_rr) {
5436                 dns_name_t *origin = dns_db_origin(signing->db);
5437                 /*
5438                  * Rebuild the NSEC/NSEC3 record for the origin as we no
5439                  * longer have any private records.
5440                  */
5441                 if (build_nsec3)
5442                         CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
5443                                                   minimum, ISC_FALSE, diff));
5444                 CHECK(updatesecure(signing->db, version, origin, minimum,
5445                                    ISC_TRUE, diff));
5446         }
5447
5448  failure:
5449         if (dns_rdataset_isassociated(&rdataset))
5450                 dns_rdataset_disassociate(&rdataset);
5451         if (node != NULL)
5452                 dns_db_detachnode(signing->db, &node);
5453         return (result);
5454 }
5455
5456 /*
5457  * If 'active' is set then we are not done with the chain yet so only
5458  * delete the nsec3param record which indicates a full chain exists
5459  * (flags == 0).
5460  */
5461 static isc_result_t
5462 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
5463                  isc_boolean_t active, dns_rdatatype_t privatetype,
5464                  dns_diff_t *diff)
5465 {
5466         dns_dbnode_t *node = NULL;
5467         dns_name_t *name = dns_db_origin(db);
5468         dns_rdata_t rdata = DNS_RDATA_INIT;
5469         dns_rdataset_t rdataset;
5470         dns_rdata_nsec3param_t nsec3param;
5471         isc_result_t result;
5472         isc_buffer_t buffer;
5473         unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
5474         dns_ttl_t ttl = 0;
5475
5476         dns_rdataset_init(&rdataset);
5477
5478         result = dns_db_getoriginnode(db, &node);
5479         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5480         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5481                                      0, 0, &rdataset, NULL);
5482         if (result == ISC_R_NOTFOUND)
5483                 goto try_private;
5484         if (result != ISC_R_SUCCESS)
5485                 goto failure;
5486
5487         /*
5488          * Preserve the existing ttl.
5489          */
5490         ttl = rdataset.ttl;
5491
5492         /*
5493          * Delete all NSEC3PARAM records which match that in nsec3chain.
5494          */
5495         for (result = dns_rdataset_first(&rdataset);
5496              result == ISC_R_SUCCESS;
5497              result = dns_rdataset_next(&rdataset)) {
5498
5499                 dns_rdataset_current(&rdataset, &rdata);
5500                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5501
5502                 if (nsec3param.hash != chain->nsec3param.hash ||
5503                     (active && nsec3param.flags != 0) ||
5504                     nsec3param.iterations != chain->nsec3param.iterations ||
5505                     nsec3param.salt_length != chain->nsec3param.salt_length ||
5506                     memcmp(nsec3param.salt, chain->nsec3param.salt,
5507                            nsec3param.salt_length)) {
5508                         dns_rdata_reset(&rdata);
5509                         continue;
5510                 }
5511
5512                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5513                                     name, rdataset.ttl, &rdata));
5514                 dns_rdata_reset(&rdata);
5515         }
5516         if (result != ISC_R_NOMORE)
5517                 goto failure;
5518
5519         dns_rdataset_disassociate(&rdataset);
5520
5521  try_private:
5522
5523         if (active)
5524                 goto add;
5525         /*
5526          * Delete all private records which match that in nsec3chain.
5527          */
5528         result = dns_db_findrdataset(db, node, ver, privatetype,
5529                                      0, 0, &rdataset, NULL);
5530         if (result == ISC_R_NOTFOUND)
5531                 goto add;
5532         if (result != ISC_R_SUCCESS)
5533                 goto failure;
5534
5535         for (result = dns_rdataset_first(&rdataset);
5536              result == ISC_R_SUCCESS;
5537              result = dns_rdataset_next(&rdataset)) {
5538                 dns_rdata_t private = DNS_RDATA_INIT;
5539                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
5540
5541                 dns_rdataset_current(&rdataset, &private);
5542                 if (!dns_nsec3param_fromprivate(&private, &rdata,
5543                                                 buf, sizeof(buf)))
5544                         continue;
5545                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5546
5547                 if (nsec3param.hash != chain->nsec3param.hash ||
5548                     nsec3param.iterations != chain->nsec3param.iterations ||
5549                     nsec3param.salt_length != chain->nsec3param.salt_length ||
5550                     memcmp(nsec3param.salt, chain->nsec3param.salt,
5551                            nsec3param.salt_length)) {
5552                         dns_rdata_reset(&rdata);
5553                         continue;
5554                 }
5555
5556                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5557                                     name, rdataset.ttl, &private));
5558                 dns_rdata_reset(&rdata);
5559         }
5560         if (result != ISC_R_NOMORE)
5561                 goto failure;
5562
5563   add:
5564         if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
5565                 result = ISC_R_SUCCESS;
5566                 goto failure;
5567         }
5568
5569         /*
5570          * Add a NSEC3PARAM record which matches that in nsec3chain but
5571          * with all flags bits cleared.
5572          *
5573          * Note: we do not clear chain->nsec3param.flags as this change
5574          * may be reversed.
5575          */
5576         isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
5577         CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
5578                                    dns_rdatatype_nsec3param,
5579                                    &chain->nsec3param, &buffer));
5580         rdata.data[1] = 0;      /* Clear flag bits. */
5581         CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
5582
5583   failure:
5584         dns_db_detachnode(db, &node);
5585         if (dns_rdataset_isassociated(&rdataset))
5586                 dns_rdataset_disassociate(&rdataset);
5587         return (result);
5588 }
5589
5590 static isc_result_t
5591 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
5592             dns_name_t *name, dns_diff_t *diff)
5593 {
5594         dns_rdataset_t rdataset;
5595         isc_result_t result;
5596
5597         dns_rdataset_init(&rdataset);
5598
5599         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
5600                                      0, 0, &rdataset, NULL);
5601         if (result == ISC_R_NOTFOUND)
5602                 return (ISC_R_SUCCESS);
5603         if (result != ISC_R_SUCCESS)
5604                 return (result);
5605         for (result = dns_rdataset_first(&rdataset);
5606              result == ISC_R_SUCCESS;
5607              result = dns_rdataset_next(&rdataset)) {
5608                 dns_rdata_t rdata = DNS_RDATA_INIT;
5609
5610                 dns_rdataset_current(&rdataset, &rdata);
5611                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
5612                                     rdataset.ttl, &rdata));
5613         }
5614         if (result == ISC_R_NOMORE)
5615                 result = ISC_R_SUCCESS;
5616  failure:
5617         dns_rdataset_disassociate(&rdataset);
5618         return (result);
5619 }
5620
5621 static isc_result_t
5622 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
5623                     dns_name_t *name, const dns_rdata_nsec3param_t *param,
5624                     dns_diff_t *diff)
5625 {
5626         dns_rdataset_t rdataset;
5627         dns_rdata_nsec3_t nsec3;
5628         isc_result_t result;
5629
5630         dns_rdataset_init(&rdataset);
5631         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
5632                                      0, 0, &rdataset, NULL);
5633         if (result == ISC_R_NOTFOUND)
5634                 return (ISC_R_SUCCESS);
5635         if (result != ISC_R_SUCCESS)
5636                 return (result);
5637
5638         for (result = dns_rdataset_first(&rdataset);
5639              result == ISC_R_SUCCESS;
5640              result = dns_rdataset_next(&rdataset)) {
5641                 dns_rdata_t rdata = DNS_RDATA_INIT;
5642
5643                 dns_rdataset_current(&rdataset, &rdata);
5644                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
5645                 if (nsec3.hash != param->hash ||
5646                     nsec3.iterations != param->iterations ||
5647                     nsec3.salt_length != param->salt_length ||
5648                     memcmp(nsec3.salt, param->salt, nsec3.salt_length))
5649                         continue;
5650                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
5651                                     rdataset.ttl, &rdata));
5652         }
5653         if (result == ISC_R_NOMORE)
5654                 result = ISC_R_SUCCESS;
5655  failure:
5656         dns_rdataset_disassociate(&rdataset);
5657         return (result);
5658 }
5659
5660 static isc_result_t
5661 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
5662                 const dns_rdata_nsec3param_t *param,
5663                 isc_boolean_t *answer)
5664 {
5665         dns_dbnode_t *node = NULL;
5666         dns_rdata_t rdata = DNS_RDATA_INIT;
5667         dns_rdata_nsec3param_t myparam;
5668         dns_rdataset_t rdataset;
5669         isc_result_t result;
5670
5671         *answer = ISC_FALSE;
5672
5673         result = dns_db_getoriginnode(db, &node);
5674         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5675
5676         dns_rdataset_init(&rdataset);
5677
5678         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
5679                                      0, 0, &rdataset, NULL);
5680         if (result == ISC_R_SUCCESS) {
5681                 dns_rdataset_disassociate(&rdataset);
5682                 dns_db_detachnode(db, &node);
5683                 return (result);
5684         }
5685         if (result != ISC_R_NOTFOUND) {
5686                 dns_db_detachnode(db, &node);
5687                 return (result);
5688         }
5689
5690         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5691                                      0, 0, &rdataset, NULL);
5692         if (result == ISC_R_NOTFOUND) {
5693                 *answer = ISC_TRUE;
5694                 dns_db_detachnode(db, &node);
5695                 return (ISC_R_SUCCESS);
5696         }
5697         if (result != ISC_R_SUCCESS) {
5698                 dns_db_detachnode(db, &node);
5699                 return (result);
5700         }
5701
5702         for (result = dns_rdataset_first(&rdataset);
5703              result == ISC_R_SUCCESS;
5704              result = dns_rdataset_next(&rdataset)) {
5705                 dns_rdataset_current(&rdataset, &rdata);
5706                 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
5707                 dns_rdata_reset(&rdata);
5708                 /*
5709                  * Ignore any NSEC3PARAM removals.
5710                  */
5711                 if (NSEC3REMOVE(myparam.flags))
5712                         continue;
5713                 /*
5714                  * Ignore the chain that we are in the process of deleting.
5715                  */
5716                 if (myparam.hash == param->hash &&
5717                     myparam.iterations == param->iterations &&
5718                     myparam.salt_length == param->salt_length &&
5719                     !memcmp(myparam.salt, param->salt, myparam.salt_length))
5720                         continue;
5721                 /*
5722                  * Found an active NSEC3 chain.
5723                  */
5724                 break;
5725         }
5726         if (result == ISC_R_NOMORE) {
5727                 *answer = ISC_TRUE;
5728                 result = ISC_R_SUCCESS;
5729         }
5730
5731  failure:
5732         if (dns_rdataset_isassociated(&rdataset))
5733                 dns_rdataset_disassociate(&rdataset);
5734         dns_db_detachnode(db, &node);
5735         return (result);
5736 }
5737
5738 static isc_result_t
5739 update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
5740             dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
5741             isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
5742             isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
5743             dns_diff_t *sig_diff)
5744 {
5745         dns_difftuple_t *tuple;
5746         isc_result_t result;
5747
5748         for (tuple = ISC_LIST_HEAD(diff->tuples);
5749              tuple != NULL;
5750              tuple = ISC_LIST_HEAD(diff->tuples)) {
5751                 result = del_sigs(zone, db, version, &tuple->name,
5752                                   tuple->rdata.type, sig_diff,
5753                                   zone_keys, nkeys, now, ISC_FALSE);
5754                 if (result != ISC_R_SUCCESS) {
5755                         dns_zone_log(zone, ISC_LOG_ERROR,
5756                                      "update_sigs:del_sigs -> %s",
5757                                      dns_result_totext(result));
5758                         return (result);
5759                 }
5760                 result = add_sigs(db, version, &tuple->name,
5761                                   tuple->rdata.type, sig_diff,
5762                                   zone_keys, nkeys, zone->mctx, inception,
5763                                   expire, check_ksk, keyset_kskonly);
5764                 if (result != ISC_R_SUCCESS) {
5765                         dns_zone_log(zone, ISC_LOG_ERROR,
5766                                      "update_sigs:add_sigs -> %s",
5767                                      dns_result_totext(result));
5768                         return (result);
5769                 }
5770
5771                 do {
5772                         dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
5773                         while (next != NULL &&
5774                                (tuple->rdata.type != next->rdata.type ||
5775                                 !dns_name_equal(&tuple->name, &next->name)))
5776                                 next = ISC_LIST_NEXT(next, link);
5777                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
5778                         dns_diff_appendminimal(sig_diff, &tuple);
5779                         INSIST(tuple == NULL);
5780                         tuple = next;
5781                 } while (tuple != NULL);
5782         }
5783         return (ISC_R_SUCCESS);
5784 }
5785
5786 /*
5787  * Incrementally build and sign a new NSEC3 chain using the parameters
5788  * requested.
5789  */
5790 static void
5791 zone_nsec3chain(dns_zone_t *zone) {
5792         dns_db_t *db = NULL;
5793         dns_dbnode_t *node = NULL;
5794         dns_dbversion_t *version = NULL;
5795         dns_diff_t sig_diff;
5796         dns_diff_t nsec_diff;
5797         dns_diff_t nsec3_diff;
5798         dns_diff_t param_diff;
5799         dns_fixedname_t fixed;
5800         dns_fixedname_t nextfixed;
5801         dns_name_t *name, *nextname;
5802         dns_rdataset_t rdataset;
5803         dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
5804         dns_nsec3chainlist_t cleanup;
5805         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
5806         isc_int32_t signatures;
5807         isc_boolean_t check_ksk, keyset_kskonly;
5808         isc_boolean_t delegation;
5809         isc_boolean_t first;
5810         isc_result_t result;
5811         isc_stdtime_t now, inception, soaexpire, expire;
5812         isc_uint32_t jitter;
5813         unsigned int i;
5814         unsigned int nkeys = 0;
5815         isc_uint32_t nodes;
5816         isc_boolean_t unsecure = ISC_FALSE;
5817         isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
5818         isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
5819         dns_rdatasetiter_t *iterator = NULL;
5820         isc_boolean_t buildnsecchain;
5821         isc_boolean_t updatensec = ISC_FALSE;
5822         dns_rdatatype_t privatetype = zone->privatetype;
5823
5824         dns_rdataset_init(&rdataset);
5825         dns_fixedname_init(&fixed);
5826         name = dns_fixedname_name(&fixed);
5827         dns_fixedname_init(&nextfixed);
5828         nextname = dns_fixedname_name(&nextfixed);
5829         dns_diff_init(zone->mctx, &param_diff);
5830         dns_diff_init(zone->mctx, &nsec3_diff);
5831         dns_diff_init(zone->mctx, &nsec_diff);
5832         dns_diff_init(zone->mctx, &sig_diff);
5833         sig_diff.resign = zone->sigresigninginterval;
5834         ISC_LIST_INIT(cleanup);
5835
5836         /*
5837          * Updates are disabled.  Pause for 5 minutes.
5838          */
5839         if (zone->update_disabled) {
5840                 result = ISC_R_FAILURE;
5841                 goto failure;
5842         }
5843
5844         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5845         dns_db_attach(zone->db, &db);
5846         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5847
5848         result = dns_db_newversion(db, &version);
5849         if (result != ISC_R_SUCCESS) {
5850                 dns_zone_log(zone, ISC_LOG_ERROR,
5851                              "zone_nsec3chain:dns_db_newversion -> %s",
5852                              dns_result_totext(result));
5853                 goto failure;
5854         }
5855
5856         result = find_zone_keys(zone, db, version, zone->mctx,
5857                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
5858         if (result != ISC_R_SUCCESS) {
5859                 dns_zone_log(zone, ISC_LOG_ERROR,
5860                              "zone_nsec3chain:find_zone_keys -> %s",
5861                              dns_result_totext(result));
5862                 goto failure;
5863         }
5864
5865         isc_stdtime_get(&now);
5866         inception = now - 3600; /* Allow for clock skew. */
5867         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5868
5869         /*
5870          * Spread out signatures over time if they happen to be
5871          * clumped.  We don't do this for each add_sigs() call as
5872          * we still want some clustering to occur.
5873          */
5874         isc_random_get(&jitter);
5875         expire = soaexpire - jitter % 3600;
5876
5877         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5878         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5879
5880         /*
5881          * We keep pulling nodes off each iterator in turn until
5882          * we have no more nodes to pull off or we reach the limits
5883          * for this quantum.
5884          */
5885         nodes = zone->nodes;
5886         signatures = zone->signatures;
5887         LOCK_ZONE(zone);
5888         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
5889         UNLOCK_ZONE(zone);
5890         first = ISC_TRUE;
5891
5892         if (nsec3chain != NULL)
5893                 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
5894         /*
5895          * Generate new NSEC3 chains first.
5896          */
5897         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
5898                 LOCK_ZONE(zone);
5899                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
5900
5901                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5902                 if (nsec3chain->done || nsec3chain->db != zone->db) {
5903                         ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
5904                         ISC_LIST_APPEND(cleanup, nsec3chain, link);
5905                 }
5906                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5907                 UNLOCK_ZONE(zone);
5908                 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
5909                         goto next_addchain;
5910
5911                 /*
5912                  * Possible future db.
5913                  */
5914                 if (nsec3chain->db != db) {
5915                         goto next_addchain;
5916                 }
5917
5918                 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
5919                         goto next_addchain;
5920
5921                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
5922
5923                 if (nsec3chain->delete_nsec) {
5924                         delegation = ISC_FALSE;
5925                         dns_dbiterator_pause(nsec3chain->dbiterator);
5926                         CHECK(delete_nsec(db, version, node, name, &nsec_diff));
5927                         goto next_addnode;
5928                 }
5929                 /*
5930                  * On the first pass we need to check if the current node
5931                  * has not been obscured.
5932                  */
5933                 delegation = ISC_FALSE;
5934                 unsecure = ISC_FALSE;
5935                 if (first) {
5936                         dns_fixedname_t ffound;
5937                         dns_name_t *found;
5938                         dns_fixedname_init(&ffound);
5939                         found = dns_fixedname_name(&ffound);
5940                         result = dns_db_find(db, name, version,
5941                                              dns_rdatatype_soa,
5942                                              DNS_DBFIND_NOWILD, 0, NULL, found,
5943                                              NULL, NULL);
5944                         if ((result == DNS_R_DELEGATION ||
5945                             result == DNS_R_DNAME) &&
5946                             !dns_name_equal(name, found)) {
5947                                 /*
5948                                  * Remember the obscuring name so that
5949                                  * we skip all obscured names.
5950                                  */
5951                                 dns_name_copy(found, name, NULL);
5952                                 delegation = ISC_TRUE;
5953                                 goto next_addnode;
5954                         }
5955                 }
5956
5957                 /*
5958                  * Check to see if this is a bottom of zone node.
5959                  */
5960                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5961                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
5962                         goto next_addnode;
5963                 if (result != ISC_R_SUCCESS)
5964                         goto failure;
5965
5966                 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
5967                         ISC_FALSE;
5968                 for (result = dns_rdatasetiter_first(iterator);
5969                      result == ISC_R_SUCCESS;
5970                      result = dns_rdatasetiter_next(iterator)) {
5971                         dns_rdatasetiter_current(iterator, &rdataset);
5972                         INSIST(rdataset.type != dns_rdatatype_nsec3);
5973                         if (rdataset.type == dns_rdatatype_soa)
5974                                 seen_soa = ISC_TRUE;
5975                         else if (rdataset.type == dns_rdatatype_ns)
5976                                 seen_ns = ISC_TRUE;
5977                         else if (rdataset.type == dns_rdatatype_dname)
5978                                 seen_dname = ISC_TRUE;
5979                         else if (rdataset.type == dns_rdatatype_ds)
5980                                 seen_ds = ISC_TRUE;
5981                         else if (rdataset.type == dns_rdatatype_nsec)
5982                                 seen_nsec = ISC_TRUE;
5983                         dns_rdataset_disassociate(&rdataset);
5984                 }
5985                 dns_rdatasetiter_destroy(&iterator);
5986                 /*
5987                  * Is there a NSEC chain than needs to be cleaned up?
5988                  */
5989                 if (seen_nsec)
5990                         nsec3chain->seen_nsec = ISC_TRUE;
5991                 if (seen_ns && !seen_soa && !seen_ds)
5992                         unsecure = ISC_TRUE;
5993                 if ((seen_ns && !seen_soa) || seen_dname)
5994                         delegation = ISC_TRUE;
5995
5996                 /*
5997                  * Process one node.
5998                  */
5999                 dns_dbiterator_pause(nsec3chain->dbiterator);
6000                 result = dns_nsec3_addnsec3(db, version, name,
6001                                             &nsec3chain->nsec3param,
6002                                             zone->minimum, unsecure,
6003                                             &nsec3_diff);
6004                 if (result != ISC_R_SUCCESS) {
6005                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6006                                      "dns_nsec3_addnsec3 -> %s",
6007                                      dns_result_totext(result));
6008                         goto failure;
6009                 }
6010
6011                 /*
6012                  * Treat each call to dns_nsec3_addnsec3() as if it's cost is
6013                  * two signatures.  Additionally there will, in general, be
6014                  * two signature generated below.
6015                  *
6016                  * If we are only changing the optout flag the cost is half
6017                  * that of the cost of generating a completely new chain.
6018                  */
6019                 signatures -= 4;
6020
6021                 /*
6022                  * Go onto next node.
6023                  */
6024  next_addnode:
6025                 first = ISC_FALSE;
6026                 dns_db_detachnode(db, &node);
6027                 do {
6028                         result = dns_dbiterator_next(nsec3chain->dbiterator);
6029
6030                         if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
6031                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6032                                                        ISC_FALSE, privatetype,
6033                                                        &param_diff));
6034                                 LOCK_ZONE(zone);
6035                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6036                                                 link);
6037                                 UNLOCK_ZONE(zone);
6038                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6039                                 goto next_addchain;
6040                         }
6041                         if (result == ISC_R_NOMORE) {
6042                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6043                                 if (nsec3chain->seen_nsec) {
6044                                         CHECK(fixup_nsec3param(db, version,
6045                                                                nsec3chain,
6046                                                                ISC_TRUE,
6047                                                                privatetype,
6048                                                                &param_diff));
6049                                         nsec3chain->delete_nsec = ISC_TRUE;
6050                                         goto same_addchain;
6051                                 }
6052                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6053                                                        ISC_FALSE, privatetype,
6054                                                        &param_diff));
6055                                 LOCK_ZONE(zone);
6056                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6057                                                 link);
6058                                 UNLOCK_ZONE(zone);
6059                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6060                                 goto next_addchain;
6061                         } else if (result != ISC_R_SUCCESS) {
6062                                 dns_zone_log(zone, ISC_LOG_ERROR,
6063                                              "zone_nsec3chain:"
6064                                              "dns_dbiterator_next -> %s",
6065                                              dns_result_totext(result));
6066                                 goto failure;
6067                         } else if (delegation) {
6068                                 dns_dbiterator_current(nsec3chain->dbiterator,
6069                                                        &node, nextname);
6070                                 dns_db_detachnode(db, &node);
6071                                 if (!dns_name_issubdomain(nextname, name))
6072                                         break;
6073                         } else
6074                                 break;
6075                 } while (1);
6076                 continue;
6077
6078  same_addchain:
6079                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6080                 first = ISC_TRUE;
6081                 continue;
6082
6083  next_addchain:
6084                 dns_dbiterator_pause(nsec3chain->dbiterator);
6085                 nsec3chain = nextnsec3chain;
6086                 first = ISC_TRUE;
6087                 if (nsec3chain != NULL)
6088                         nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6089         }
6090
6091         /*
6092          * Process removals.
6093          */
6094         LOCK_ZONE(zone);
6095         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6096         UNLOCK_ZONE(zone);
6097         first = ISC_TRUE;
6098         buildnsecchain = ISC_FALSE;
6099         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6100                 LOCK_ZONE(zone);
6101                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6102                 UNLOCK_ZONE(zone);
6103
6104                 if (nsec3chain->db != db)
6105                         goto next_removechain;
6106
6107                 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
6108                         goto next_removechain;
6109
6110                 /*
6111                  * Work out if we need to build a NSEC chain as a consequence
6112                  * of removing this NSEC3 chain.
6113                  */
6114                 if (first && !updatensec &&
6115                     (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0) {
6116                         result = need_nsec_chain(db, version,
6117                                                  &nsec3chain->nsec3param,
6118                                                  &buildnsecchain);
6119                         if (result != ISC_R_SUCCESS) {
6120                                 dns_zone_log(zone, ISC_LOG_ERROR,
6121                                              "zone_nsec3chain:"
6122                                              "need_nsec_chain -> %s",
6123                                              dns_result_totext(result));
6124                                 goto failure;
6125                         }
6126                 }
6127
6128                 if (first)
6129                         dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
6130                                      "buildnsecchain = %u\n", buildnsecchain);
6131
6132                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6133                 delegation = ISC_FALSE;
6134
6135                 if (!buildnsecchain) {
6136                         /*
6137                          * Delete the NSECPARAM record that matches this chain.
6138                          */
6139                         if (first) {
6140                                 result = fixup_nsec3param(db, version,
6141                                                           nsec3chain,
6142                                                           ISC_TRUE, privatetype,
6143                                                           &param_diff);
6144                                 if (result != ISC_R_SUCCESS) {
6145                                         dns_zone_log(zone, ISC_LOG_ERROR,
6146                                                      "zone_nsec3chain:"
6147                                                      "fixup_nsec3param -> %s",
6148                                                      dns_result_totext(result));
6149                                         goto failure;
6150                                 }
6151                         }
6152
6153                         /*
6154                          *  Delete the NSEC3 records.
6155                          */
6156                         result = deletematchingnsec3(db, version, node, name,
6157                                                      &nsec3chain->nsec3param,
6158                                                      &nsec3_diff);
6159                         if (result != ISC_R_SUCCESS) {
6160                                 dns_zone_log(zone, ISC_LOG_ERROR,
6161                                              "zone_nsec3chain:"
6162                                              "deletematchingnsec3 -> %s",
6163                                              dns_result_totext(result));
6164                                 goto failure;
6165                         }
6166                         goto next_removenode;
6167                 }
6168
6169                 if (first) {
6170                         dns_fixedname_t ffound;
6171                         dns_name_t *found;
6172                         dns_fixedname_init(&ffound);
6173                         found = dns_fixedname_name(&ffound);
6174                         result = dns_db_find(db, name, version,
6175                                              dns_rdatatype_soa,
6176                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6177                                              NULL, NULL);
6178                         if ((result == DNS_R_DELEGATION ||
6179                              result == DNS_R_DNAME) &&
6180                             !dns_name_equal(name, found)) {
6181                                 /*
6182                                  * Remember the obscuring name so that
6183                                  * we skip all obscured names.
6184                                  */
6185                                 dns_name_copy(found, name, NULL);
6186                                 delegation = ISC_TRUE;
6187                                 goto next_removenode;
6188                         }
6189                 }
6190
6191                 /*
6192                  * Check to see if this is a bottom of zone node.
6193                  */
6194                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6195                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
6196                         goto next_removenode;
6197                 if (result != ISC_R_SUCCESS)
6198                         goto failure;
6199
6200                 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
6201                         seen_rr = ISC_FALSE;
6202                 for (result = dns_rdatasetiter_first(iterator);
6203                      result == ISC_R_SUCCESS;
6204                      result = dns_rdatasetiter_next(iterator)) {
6205                         dns_rdatasetiter_current(iterator, &rdataset);
6206                         if (rdataset.type == dns_rdatatype_soa)
6207                                 seen_soa = ISC_TRUE;
6208                         else if (rdataset.type == dns_rdatatype_ns)
6209                                 seen_ns = ISC_TRUE;
6210                         else if (rdataset.type == dns_rdatatype_dname)
6211                                 seen_dname = ISC_TRUE;
6212                         else if (rdataset.type == dns_rdatatype_nsec)
6213                                 seen_nsec = ISC_TRUE;
6214                         else if (rdataset.type == dns_rdatatype_nsec3)
6215                                 seen_nsec3 = ISC_TRUE;
6216                         if (rdataset.type != dns_rdatatype_rrsig)
6217                                 seen_rr = ISC_TRUE;
6218                         dns_rdataset_disassociate(&rdataset);
6219                 }
6220                 dns_rdatasetiter_destroy(&iterator);
6221
6222                 if (!seen_rr || seen_nsec3 || seen_nsec)
6223                         goto next_removenode;
6224                 if ((seen_ns && !seen_soa) || seen_dname)
6225                         delegation = ISC_TRUE;
6226
6227                 /*
6228                  * Add a NSEC record except at the origin.
6229                  */
6230                 if (!dns_name_equal(name, dns_db_origin(db))) {
6231                         dns_dbiterator_pause(nsec3chain->dbiterator);
6232                         CHECK(add_nsec(db, version, name, node, zone->minimum,
6233                                        delegation, &nsec_diff));
6234                 }
6235
6236  next_removenode:
6237                 first = ISC_FALSE;
6238                 dns_db_detachnode(db, &node);
6239                 do {
6240                         result = dns_dbiterator_next(nsec3chain->dbiterator);
6241                         if (result == ISC_R_NOMORE && buildnsecchain) {
6242                                 /*
6243                                  * The NSEC chain should now be built.
6244                                  * We can now remove the NSEC3 chain.
6245                                  */
6246                                 updatensec = ISC_TRUE;
6247                                 goto same_removechain;
6248                         }
6249                         if (result == ISC_R_NOMORE) {
6250                                 LOCK_ZONE(zone);
6251                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6252                                                 link);
6253                                 UNLOCK_ZONE(zone);
6254                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6255                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6256                                 result = fixup_nsec3param(db, version,
6257                                                           nsec3chain, ISC_FALSE,
6258                                                           privatetype,
6259                                                           &param_diff);
6260                                 if (result != ISC_R_SUCCESS) {
6261                                         dns_zone_log(zone, ISC_LOG_ERROR,
6262                                                      "zone_nsec3chain:"
6263                                                      "fixup_nsec3param -> %s",
6264                                                      dns_result_totext(result));
6265                                         goto failure;
6266                                 }
6267                                 goto next_removechain;
6268                         } else if (result != ISC_R_SUCCESS) {
6269                                 dns_zone_log(zone, ISC_LOG_ERROR,
6270                                              "zone_nsec3chain:"
6271                                              "dns_dbiterator_next -> %s",
6272                                              dns_result_totext(result));
6273                                 goto failure;
6274                         } else if (delegation) {
6275                                 dns_dbiterator_current(nsec3chain->dbiterator,
6276                                                        &node, nextname);
6277                                 dns_db_detachnode(db, &node);
6278                                 if (!dns_name_issubdomain(nextname, name))
6279                                         break;
6280                         } else
6281                                 break;
6282                 } while (1);
6283                 continue;
6284
6285  same_removechain:
6286                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6287                 buildnsecchain = ISC_FALSE;
6288                 first = ISC_TRUE;
6289                 continue;
6290
6291  next_removechain:
6292                 dns_dbiterator_pause(nsec3chain->dbiterator);
6293                 nsec3chain = nextnsec3chain;
6294                 first = ISC_TRUE;
6295         }
6296
6297         /*
6298          * We may need to update the NSEC/NSEC3 records for the zone apex.
6299          */
6300         if (!ISC_LIST_EMPTY(param_diff.tuples)) {
6301                 isc_boolean_t rebuild_nsec = ISC_FALSE,
6302                               rebuild_nsec3 = ISC_FALSE;
6303                 result = dns_db_getoriginnode(db, &node);
6304                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6305                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6306                 if (result != ISC_R_SUCCESS) {
6307                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6308                                      "dns_db_allrdatasets -> %s",
6309                                      dns_result_totext(result));
6310                         goto failure;
6311                 }
6312                 for (result = dns_rdatasetiter_first(iterator);
6313                      result == ISC_R_SUCCESS;
6314                      result = dns_rdatasetiter_next(iterator)) {
6315                         dns_rdatasetiter_current(iterator, &rdataset);
6316                         if (rdataset.type == dns_rdatatype_nsec)
6317                                 rebuild_nsec = ISC_TRUE;
6318                         if (rdataset.type == dns_rdatatype_nsec3param)
6319                                 rebuild_nsec3 = ISC_TRUE;
6320                         dns_rdataset_disassociate(&rdataset);
6321                 }
6322                 dns_rdatasetiter_destroy(&iterator);
6323                 dns_db_detachnode(db, &node);
6324
6325                 if (rebuild_nsec) {
6326                         if (nsec3chain != NULL)
6327                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6328                         result = updatesecure(db, version, &zone->origin,
6329                                               zone->minimum, ISC_TRUE,
6330                                               &nsec_diff);
6331                         if (result != ISC_R_SUCCESS) {
6332                                 dns_zone_log(zone, ISC_LOG_ERROR,
6333                                              "zone_nsec3chain:"
6334                                              "updatesecure -> %s",
6335                                              dns_result_totext(result));
6336                                 goto failure;
6337                         }
6338                 }
6339                 if (rebuild_nsec3) {
6340                         result = dns_nsec3_addnsec3s(db, version,
6341                                                      dns_db_origin(db),
6342                                                      zone->minimum, ISC_FALSE,
6343                                                      &nsec3_diff);
6344                         if (result != ISC_R_SUCCESS) {
6345                                 dns_zone_log(zone, ISC_LOG_ERROR,
6346                                              "zone_nsec3chain:"
6347                                              "dns_nsec3_addnsec3s -> %s",
6348                                              dns_result_totext(result));
6349                                 goto failure;
6350                         }
6351                 }
6352         }
6353
6354         /*
6355          * Add / update signatures for the NSEC3 records.
6356          */
6357         result = update_sigs(&nsec3_diff, db, version, zone_keys,
6358                              nkeys, zone, inception, expire, now,
6359                              check_ksk, keyset_kskonly, &sig_diff);
6360         if (result != ISC_R_SUCCESS) {
6361                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6362                              "update_sigs -> %s", dns_result_totext(result));
6363                 goto failure;
6364         }
6365
6366         /*
6367          * We have changed the NSEC3PARAM or private RRsets
6368          * above so we need to update the signatures.
6369          */
6370         result = update_sigs(&param_diff, db, version, zone_keys,
6371                              nkeys, zone, inception, expire, now,
6372                              check_ksk, keyset_kskonly, &sig_diff);
6373         if (result != ISC_R_SUCCESS) {
6374                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6375                              "update_sigs -> %s", dns_result_totext(result));
6376                 goto failure;
6377         }
6378
6379         if (updatensec) {
6380                 if (nsec3chain != NULL)
6381                         dns_dbiterator_pause(nsec3chain->dbiterator);
6382                 result = updatesecure(db, version, &zone->origin,
6383                                       zone->minimum, ISC_FALSE, &nsec_diff);
6384                 if (result != ISC_R_SUCCESS) {
6385                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6386                                      "updatesecure -> %s",
6387                                      dns_result_totext(result));
6388                         goto failure;
6389                 }
6390         }
6391
6392         result = update_sigs(&nsec_diff, db, version, zone_keys,
6393                              nkeys, zone, inception, expire, now,
6394                              check_ksk, keyset_kskonly, &sig_diff);
6395         if (result != ISC_R_SUCCESS) {
6396                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6397                              "update_sigs -> %s", dns_result_totext(result));
6398                 goto failure;
6399         }
6400
6401         /*
6402          * If we made no effective changes to the zone then we can just
6403          * cleanup otherwise we need to increment the serial.
6404          */
6405         if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
6406                 goto done;
6407
6408         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6409                           &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
6410         if (result != ISC_R_SUCCESS) {
6411                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6412                              "del_sigs -> %s", dns_result_totext(result));
6413                 goto failure;
6414         }
6415
6416         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
6417         if (result != ISC_R_SUCCESS) {
6418                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6419                              "increment_soa_serial -> %s",
6420                              dns_result_totext(result));
6421                 goto failure;
6422         }
6423
6424         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6425                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
6426                           soaexpire, check_ksk, keyset_kskonly);
6427         if (result != ISC_R_SUCCESS) {
6428                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6429                              "add_sigs -> %s", dns_result_totext(result));
6430                 goto failure;
6431         }
6432
6433         /* Write changes to journal file. */
6434         CHECK(zone_journal(zone, &sig_diff, "zone_nsec3chain"));
6435
6436         LOCK_ZONE(zone);
6437         zone_needdump(zone, DNS_DUMP_DELAY);
6438         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6439         UNLOCK_ZONE(zone);
6440
6441  done:
6442         /*
6443          * Pause all iterators so that dns_db_closeversion() can succeed.
6444          */
6445         LOCK_ZONE(zone);
6446         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6447              nsec3chain != NULL;
6448              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6449                 dns_dbiterator_pause(nsec3chain->dbiterator);
6450         UNLOCK_ZONE(zone);
6451
6452         /*
6453          * Everything has succeeded. Commit the changes.
6454          */
6455         dns_db_closeversion(db, &version, ISC_TRUE);
6456
6457         /*
6458          * Everything succeeded so we can clean these up now.
6459          */
6460         nsec3chain = ISC_LIST_HEAD(cleanup);
6461         while (nsec3chain != NULL) {
6462                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6463                 dns_db_detach(&nsec3chain->db);
6464                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
6465                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6466                 nsec3chain = ISC_LIST_HEAD(cleanup);
6467         }
6468
6469         set_resigntime(zone);
6470
6471  failure:
6472         if (result != ISC_R_SUCCESS)
6473                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
6474                              dns_result_totext(result));
6475         /*
6476          * On error roll back the current nsec3chain.
6477          */
6478         if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
6479                 if (nsec3chain->done) {
6480                         dns_db_detach(&nsec3chain->db);
6481                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
6482                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6483                 } else {
6484                         result = dns_dbiterator_first(nsec3chain->dbiterator);
6485                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6486                         dns_dbiterator_pause(nsec3chain->dbiterator);
6487                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6488                 }
6489         }
6490
6491         /*
6492          * Rollback the cleanup list.
6493          */
6494         nsec3chain = ISC_LIST_TAIL(cleanup);
6495         while (nsec3chain != NULL) {
6496                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6497                 if (nsec3chain->done) {
6498                         dns_db_detach(&nsec3chain->db);
6499                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
6500                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6501                 } else {
6502                         LOCK_ZONE(zone);
6503                         ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
6504                         UNLOCK_ZONE(zone);
6505                         result = dns_dbiterator_first(nsec3chain->dbiterator);
6506                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6507                         dns_dbiterator_pause(nsec3chain->dbiterator);
6508                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6509                 }
6510                 nsec3chain = ISC_LIST_TAIL(cleanup);
6511         }
6512
6513         LOCK_ZONE(zone);
6514         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6515              nsec3chain != NULL;
6516              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6517                 dns_dbiterator_pause(nsec3chain->dbiterator);
6518         UNLOCK_ZONE(zone);
6519
6520         dns_diff_clear(&param_diff);
6521         dns_diff_clear(&nsec3_diff);
6522         dns_diff_clear(&nsec_diff);
6523         dns_diff_clear(&sig_diff);
6524
6525         if (iterator != NULL)
6526                 dns_rdatasetiter_destroy(&iterator);
6527
6528         for (i = 0; i < nkeys; i++)
6529                 dst_key_free(&zone_keys[i]);
6530
6531         if (node != NULL)
6532                 dns_db_detachnode(db, &node);
6533         if (version != NULL) {
6534                 dns_db_closeversion(db, &version, ISC_FALSE);
6535                 dns_db_detach(&db);
6536         } else if (db != NULL)
6537                 dns_db_detach(&db);
6538
6539         LOCK_ZONE(zone);
6540         if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
6541                 isc_interval_t i;
6542                 if (zone->update_disabled || result != ISC_R_SUCCESS)
6543                         isc_interval_set(&i, 60, 0);            /* 1 minute */
6544                 else
6545                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
6546                 isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
6547         } else
6548                 isc_time_settoepoch(&zone->nsec3chaintime);
6549         UNLOCK_ZONE(zone);
6550 }
6551
6552 static isc_result_t
6553 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6554         dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
6555         isc_uint16_t keyid, dns_diff_t *diff)
6556 {
6557         dns_rdata_rrsig_t rrsig;
6558         dns_rdataset_t rdataset;
6559         dns_rdatasetiter_t *iterator = NULL;
6560         isc_result_t result;
6561
6562         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6563         if (result != ISC_R_SUCCESS) {
6564                 if (result == ISC_R_NOTFOUND)
6565                         result = ISC_R_SUCCESS;
6566                 return (result);
6567         }
6568
6569         dns_rdataset_init(&rdataset);
6570         for (result = dns_rdatasetiter_first(iterator);
6571              result == ISC_R_SUCCESS;
6572              result = dns_rdatasetiter_next(iterator)) {
6573                 dns_rdatasetiter_current(iterator, &rdataset);
6574                 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
6575                         for (result = dns_rdataset_first(&rdataset);
6576                              result == ISC_R_SUCCESS;
6577                              result = dns_rdataset_next(&rdataset)) {
6578                                 dns_rdata_t rdata = DNS_RDATA_INIT;
6579                                 dns_rdataset_current(&rdataset, &rdata);
6580                                 CHECK(update_one_rr(db, version, diff,
6581                                                     DNS_DIFFOP_DEL, name,
6582                                                     rdataset.ttl, &rdata));
6583                         }
6584                         if (result != ISC_R_NOMORE)
6585                                 goto failure;
6586                         dns_rdataset_disassociate(&rdataset);
6587                         continue;
6588                 }
6589                 if (rdataset.type != dns_rdatatype_rrsig) {
6590                         dns_rdataset_disassociate(&rdataset);
6591                         continue;
6592                 }
6593                 for (result = dns_rdataset_first(&rdataset);
6594                      result == ISC_R_SUCCESS;
6595                      result = dns_rdataset_next(&rdataset)) {
6596                         dns_rdata_t rdata = DNS_RDATA_INIT;
6597                         dns_rdataset_current(&rdataset, &rdata);
6598                         CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
6599                         if (rrsig.algorithm != algorithm ||
6600                             rrsig.keyid != keyid)
6601                                 continue;
6602                         CHECK(update_one_rr(db, version, diff,
6603                                             DNS_DIFFOP_DELRESIGN, name,
6604                                             rdataset.ttl, &rdata));
6605                 }
6606                 dns_rdataset_disassociate(&rdataset);
6607                 if (result != ISC_R_NOMORE)
6608                         break;
6609         }
6610         if (result == ISC_R_NOMORE)
6611                 result = ISC_R_SUCCESS;
6612  failure:
6613         if (dns_rdataset_isassociated(&rdataset))
6614                 dns_rdataset_disassociate(&rdataset);
6615         dns_rdatasetiter_destroy(&iterator);
6616         return (result);
6617 }
6618
6619 /*
6620  * Incrementally sign the zone using the keys requested.
6621  * Builds the NSEC chain if required.
6622  */
6623 static void
6624 zone_sign(dns_zone_t *zone) {
6625         dns_db_t *db = NULL;
6626         dns_dbnode_t *node = NULL;
6627         dns_dbversion_t *version = NULL;
6628         dns_diff_t sig_diff;
6629         dns_diff_t post_diff;
6630         dns_fixedname_t fixed;
6631         dns_fixedname_t nextfixed;
6632         dns_name_t *name, *nextname;
6633         dns_rdataset_t rdataset;
6634         dns_signing_t *signing, *nextsigning;
6635         dns_signinglist_t cleanup;
6636         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6637         isc_int32_t signatures;
6638         isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
6639         isc_boolean_t commit = ISC_FALSE;
6640         isc_boolean_t delegation;
6641         isc_boolean_t build_nsec = ISC_FALSE;
6642         isc_boolean_t build_nsec3 = ISC_FALSE;
6643         isc_boolean_t first;
6644         isc_result_t result;
6645         isc_stdtime_t now, inception, soaexpire, expire;
6646         isc_uint32_t jitter;
6647         unsigned int i, j;
6648         unsigned int nkeys = 0;
6649         isc_uint32_t nodes;
6650
6651         dns_rdataset_init(&rdataset);
6652         dns_fixedname_init(&fixed);
6653         name = dns_fixedname_name(&fixed);
6654         dns_fixedname_init(&nextfixed);
6655         nextname = dns_fixedname_name(&nextfixed);
6656         dns_diff_init(zone->mctx, &sig_diff);
6657         sig_diff.resign = zone->sigresigninginterval;
6658         dns_diff_init(zone->mctx, &post_diff);
6659         ISC_LIST_INIT(cleanup);
6660
6661         /*
6662          * Updates are disabled.  Pause for 5 minutes.
6663          */
6664         if (zone->update_disabled) {
6665                 result = ISC_R_FAILURE;
6666                 goto failure;
6667         }
6668
6669         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6670         dns_db_attach(zone->db, &db);
6671         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6672
6673         result = dns_db_newversion(db, &version);
6674         if (result != ISC_R_SUCCESS) {
6675                 dns_zone_log(zone, ISC_LOG_ERROR,
6676                              "zone_sign:dns_db_newversion -> %s",
6677                              dns_result_totext(result));
6678                 goto failure;
6679         }
6680
6681         result = find_zone_keys(zone, db, version, zone->mctx,
6682                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
6683         if (result != ISC_R_SUCCESS) {
6684                 dns_zone_log(zone, ISC_LOG_ERROR,
6685                              "zone_sign:find_zone_keys -> %s",
6686                              dns_result_totext(result));
6687                 goto failure;
6688         }
6689
6690         isc_stdtime_get(&now);
6691         inception = now - 3600; /* Allow for clock skew. */
6692         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6693
6694         /*
6695          * Spread out signatures over time if they happen to be
6696          * clumped.  We don't do this for each add_sigs() call as
6697          * we still want some clustering to occur.
6698          */
6699         isc_random_get(&jitter);
6700         expire = soaexpire - jitter % 3600;
6701
6702         /*
6703          * We keep pulling nodes off each iterator in turn until
6704          * we have no more nodes to pull off or we reach the limits
6705          * for this quantum.
6706          */
6707         nodes = zone->nodes;
6708         signatures = zone->signatures;
6709         signing = ISC_LIST_HEAD(zone->signing);
6710         first = ISC_TRUE;
6711
6712         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6713         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6714
6715         /* Determine which type of chain to build */
6716         CHECK(dns_private_chains(db, version, zone->privatetype,
6717                                  &build_nsec, &build_nsec3));
6718
6719         /* If neither chain is found, default to NSEC */
6720         if (!build_nsec && !build_nsec3)
6721                 build_nsec = ISC_TRUE;
6722
6723         while (signing != NULL && nodes-- > 0 && signatures > 0) {
6724                 nextsigning = ISC_LIST_NEXT(signing, link);
6725
6726                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6727                 if (signing->done || signing->db != zone->db) {
6728                         /*
6729                          * The zone has been reloaded.  We will have
6730                          * created new signings as part of the reload
6731                          * process so we can destroy this one.
6732                          */
6733                         ISC_LIST_UNLINK(zone->signing, signing, link);
6734                         ISC_LIST_APPEND(cleanup, signing, link);
6735                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6736                         goto next_signing;
6737                 }
6738                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6739
6740                 if (signing->db != db)
6741                         goto next_signing;
6742
6743                 delegation = ISC_FALSE;
6744
6745                 if (first && signing->delete) {
6746                         /*
6747                          * Remove the key we are deleting from consideration.
6748                          */
6749                         for (i = 0, j = 0; i < nkeys; i++) {
6750                                 /*
6751                                  * Find the key we want to remove.
6752                                  */
6753                                 if (ALG(zone_keys[i]) == signing->algorithm &&
6754                                     dst_key_id(zone_keys[i]) == signing->keyid)
6755                                 {
6756                                         if (KSK(zone_keys[i]))
6757                                                 dst_key_free(&zone_keys[i]);
6758                                         continue;
6759                                 }
6760                                 zone_keys[j] = zone_keys[i];
6761                                 j++;
6762                         }
6763                         nkeys = j;
6764                 }
6765
6766                 dns_dbiterator_current(signing->dbiterator, &node, name);
6767
6768                 if (signing->delete) {
6769                         dns_dbiterator_pause(signing->dbiterator);
6770                         CHECK(del_sig(db, version, name, node, nkeys,
6771                                       signing->algorithm, signing->keyid,
6772                                       &sig_diff));
6773                 }
6774
6775                 /*
6776                  * On the first pass we need to check if the current node
6777                  * has not been obscured.
6778                  */
6779                 if (first) {
6780                         dns_fixedname_t ffound;
6781                         dns_name_t *found;
6782                         dns_fixedname_init(&ffound);
6783                         found = dns_fixedname_name(&ffound);
6784                         result = dns_db_find(db, name, version,
6785                                              dns_rdatatype_soa,
6786                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6787                                              NULL, NULL);
6788                         if ((result == DNS_R_DELEGATION ||
6789                             result == DNS_R_DNAME) &&
6790                             !dns_name_equal(name, found)) {
6791                                 /*
6792                                  * Remember the obscuring name so that
6793                                  * we skip all obscured names.
6794                                  */
6795                                 dns_name_copy(found, name, NULL);
6796                                 delegation = ISC_TRUE;
6797                                 goto next_node;
6798                         }
6799                 }
6800
6801                 /*
6802                  * Process one node.
6803                  */
6804                 dns_dbiterator_pause(signing->dbiterator);
6805                 for (i = 0; i < nkeys; i++) {
6806                         isc_boolean_t both = ISC_FALSE;
6807
6808                         /*
6809                          * Find the keys we want to sign with.
6810                          */
6811                         if (!dst_key_isprivate(zone_keys[i]))
6812                                 continue;
6813
6814                         /*
6815                          * When adding look for the specific key.
6816                          */
6817                         if (!signing->delete &&
6818                             (dst_key_alg(zone_keys[i]) != signing->algorithm ||
6819                              dst_key_id(zone_keys[i]) != signing->keyid))
6820                                 continue;
6821
6822                         /*
6823                          * When deleting make sure we are properly signed
6824                          * with the algorithm that was being removed.
6825                          */
6826                         if (signing->delete &&
6827                             ALG(zone_keys[i]) != signing->algorithm)
6828                                 continue;
6829
6830                         /*
6831                          * Do we do KSK processing?
6832                          */
6833                         if (check_ksk && !REVOKE(zone_keys[i])) {
6834                                 isc_boolean_t have_ksk, have_nonksk;
6835                                 if (KSK(zone_keys[i])) {
6836                                         have_ksk = ISC_TRUE;
6837                                         have_nonksk = ISC_FALSE;
6838                                 } else {
6839                                         have_ksk = ISC_FALSE;
6840                                         have_nonksk = ISC_TRUE;
6841                                 }
6842                                 for (j = 0; j < nkeys; j++) {
6843                                         if (j == i ||
6844                                             ALG(zone_keys[i]) !=
6845                                             ALG(zone_keys[j]))
6846                                                 continue;
6847                                         if (REVOKE(zone_keys[j]))
6848                                                 continue;
6849                                         if (KSK(zone_keys[j]))
6850                                                 have_ksk = ISC_TRUE;
6851                                         else
6852                                                 have_nonksk = ISC_TRUE;
6853                                         both = have_ksk && have_nonksk;
6854                                         if (both)
6855                                                 break;
6856                                 }
6857                         }
6858                         if (both || REVOKE(zone_keys[i]))
6859                                 is_ksk = KSK(zone_keys[i]);
6860                         else
6861                                 is_ksk = ISC_FALSE;
6862
6863                         CHECK(sign_a_node(db, name, node, version, build_nsec3,
6864                                           build_nsec, zone_keys[i], inception,
6865                                           expire, zone->minimum, is_ksk,
6866                                           ISC_TF(both && keyset_kskonly),
6867                                           &delegation, &sig_diff,
6868                                           &signatures, zone->mctx));
6869                         /*
6870                          * If we are adding we are done.  Look for other keys
6871                          * of the same algorithm if deleting.
6872                          */
6873                         if (!signing->delete)
6874                                 break;
6875                 }
6876
6877                 /*
6878                  * Go onto next node.
6879                  */
6880  next_node:
6881                 first = ISC_FALSE;
6882                 dns_db_detachnode(db, &node);
6883                 do {
6884                         result = dns_dbiterator_next(signing->dbiterator);
6885                         if (result == ISC_R_NOMORE) {
6886                                 ISC_LIST_UNLINK(zone->signing, signing, link);
6887                                 ISC_LIST_APPEND(cleanup, signing, link);
6888                                 dns_dbiterator_pause(signing->dbiterator);
6889                                 if (nkeys != 0 && build_nsec) {
6890                                         /*
6891                                          * We have finished regenerating the
6892                                          * zone with a zone signing key.
6893                                          * The NSEC chain is now complete and
6894                                          * there is a full set of signatures
6895                                          * for the zone.  We can now clear the
6896                                          * OPT bit from the NSEC record.
6897                                          */
6898                                         result = updatesecure(db, version,
6899                                                               &zone->origin,
6900                                                               zone->minimum,
6901                                                               ISC_FALSE,
6902                                                               &post_diff);
6903                                         if (result != ISC_R_SUCCESS) {
6904                                                 dns_zone_log(zone,
6905                                                              ISC_LOG_ERROR,
6906                                                     "updatesecure -> %s",
6907                                                     dns_result_totext(result));
6908                                                 goto failure;
6909                                         }
6910                                 }
6911                                 result = updatesignwithkey(zone, signing,
6912                                                            version,
6913                                                            build_nsec3,
6914                                                            zone->minimum,
6915                                                            &post_diff);
6916                                 if (result != ISC_R_SUCCESS) {
6917                                         dns_zone_log(zone, ISC_LOG_ERROR,
6918                                                      "updatesignwithkey -> %s",
6919                                                      dns_result_totext(result));
6920                                         goto failure;
6921                                 }
6922                                 build_nsec = ISC_FALSE;
6923                                 goto next_signing;
6924                         } else if (result != ISC_R_SUCCESS) {
6925                                 dns_zone_log(zone, ISC_LOG_ERROR,
6926                                         "zone_sign:dns_dbiterator_next -> %s",
6927                                              dns_result_totext(result));
6928                                 goto failure;
6929                         } else if (delegation) {
6930                                 dns_dbiterator_current(signing->dbiterator,
6931                                                        &node, nextname);
6932                                 dns_db_detachnode(db, &node);
6933                                 if (!dns_name_issubdomain(nextname, name))
6934                                         break;
6935                         } else
6936                                 break;
6937                 } while (1);
6938                 continue;
6939
6940  next_signing:
6941                 dns_dbiterator_pause(signing->dbiterator);
6942                 signing = nextsigning;
6943                 first = ISC_TRUE;
6944         }
6945
6946         if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
6947                 result = update_sigs(&post_diff, db, version, zone_keys,
6948                                      nkeys, zone, inception, expire, now,
6949                                      check_ksk, keyset_kskonly, &sig_diff);
6950                 if (result != ISC_R_SUCCESS) {
6951                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
6952                                      "update_sigs -> %s",
6953                                      dns_result_totext(result));
6954                         goto failure;
6955                 }
6956         }
6957
6958         /*
6959          * Have we changed anything?
6960          */
6961         if (ISC_LIST_HEAD(sig_diff.tuples) == NULL) {
6962                 result = ISC_R_SUCCESS;
6963                 goto pauseall;
6964         }
6965
6966         commit = ISC_TRUE;
6967
6968         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6969                           &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
6970         if (result != ISC_R_SUCCESS) {
6971                 dns_zone_log(zone, ISC_LOG_ERROR,
6972                              "zone_sign:del_sigs -> %s",
6973                              dns_result_totext(result));
6974                 goto failure;
6975         }
6976
6977         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
6978         if (result != ISC_R_SUCCESS) {
6979                 dns_zone_log(zone, ISC_LOG_ERROR,
6980                              "zone_sign:increment_soa_serial -> %s",
6981                              dns_result_totext(result));
6982                 goto failure;
6983         }
6984
6985         /*
6986          * Generate maximum life time signatures so that the above loop
6987          * termination is sensible.
6988          */
6989         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6990                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
6991                           soaexpire, check_ksk, keyset_kskonly);
6992         if (result != ISC_R_SUCCESS) {
6993                 dns_zone_log(zone, ISC_LOG_ERROR,
6994                              "zone_sign:add_sigs -> %s",
6995                              dns_result_totext(result));
6996                 goto failure;
6997         }
6998
6999         /*
7000          * Write changes to journal file.
7001          */
7002         CHECK(zone_journal(zone, &sig_diff, "zone_sign"));
7003
7004  pauseall:
7005         /*
7006          * Pause all iterators so that dns_db_closeversion() can succeed.
7007          */
7008         for (signing = ISC_LIST_HEAD(zone->signing);
7009              signing != NULL;
7010              signing = ISC_LIST_NEXT(signing, link))
7011                 dns_dbiterator_pause(signing->dbiterator);
7012
7013         for (signing = ISC_LIST_HEAD(cleanup);
7014              signing != NULL;
7015              signing = ISC_LIST_NEXT(signing, link))
7016                 dns_dbiterator_pause(signing->dbiterator);
7017
7018         /*
7019          * Everything has succeeded. Commit the changes.
7020          */
7021         dns_db_closeversion(db, &version, commit);
7022
7023         /*
7024          * Everything succeeded so we can clean these up now.
7025          */
7026         signing = ISC_LIST_HEAD(cleanup);
7027         while (signing != NULL) {
7028                 ISC_LIST_UNLINK(cleanup, signing, link);
7029                 dns_db_detach(&signing->db);
7030                 dns_dbiterator_destroy(&signing->dbiterator);
7031                 isc_mem_put(zone->mctx, signing, sizeof *signing);
7032                 signing = ISC_LIST_HEAD(cleanup);
7033         }
7034
7035         set_resigntime(zone);
7036
7037         if (commit) {
7038                 LOCK_ZONE(zone);
7039                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7040                 zone_needdump(zone, DNS_DUMP_DELAY);
7041                 UNLOCK_ZONE(zone);
7042         }
7043
7044  failure:
7045         /*
7046          * Rollback the cleanup list.
7047          */
7048         signing = ISC_LIST_HEAD(cleanup);
7049         while (signing != NULL) {
7050                 ISC_LIST_UNLINK(cleanup, signing, link);
7051                 ISC_LIST_PREPEND(zone->signing, signing, link);
7052                 dns_dbiterator_first(signing->dbiterator);
7053                 dns_dbiterator_pause(signing->dbiterator);
7054                 signing = ISC_LIST_HEAD(cleanup);
7055         }
7056
7057         for (signing = ISC_LIST_HEAD(zone->signing);
7058              signing != NULL;
7059              signing = ISC_LIST_NEXT(signing, link))
7060                 dns_dbiterator_pause(signing->dbiterator);
7061
7062         dns_diff_clear(&sig_diff);
7063
7064         for (i = 0; i < nkeys; i++)
7065                 dst_key_free(&zone_keys[i]);
7066
7067         if (node != NULL)
7068                 dns_db_detachnode(db, &node);
7069
7070         if (version != NULL) {
7071                 dns_db_closeversion(db, &version, ISC_FALSE);
7072                 dns_db_detach(&db);
7073         } else if (db != NULL)
7074                 dns_db_detach(&db);
7075
7076         if (ISC_LIST_HEAD(zone->signing) != NULL) {
7077                 isc_interval_t i;
7078                 if (zone->update_disabled || result != ISC_R_SUCCESS)
7079                         isc_interval_set(&i, 60, 0);            /* 1 minute */
7080                 else
7081                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
7082                 isc_time_nowplusinterval(&zone->signingtime, &i);
7083         } else
7084                 isc_time_settoepoch(&zone->signingtime);
7085 }
7086
7087 static void
7088 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
7089               unsigned char *data, int size) {
7090         dns_rdata_dnskey_t dnskey;
7091         dns_rdata_keydata_t keydata;
7092         isc_buffer_t buf;
7093
7094         dns_rdata_reset(target);
7095         isc_buffer_init(&buf, data, size);
7096
7097         switch (rr->type) {
7098             case dns_rdatatype_dnskey:
7099                 dns_rdata_tostruct(rr, &dnskey, NULL);
7100                 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
7101                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7102                                      &dnskey, &buf);
7103                 break;
7104             case dns_rdatatype_keydata:
7105                 dns_rdata_tostruct(rr, &keydata, NULL);
7106                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
7107                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7108                                      &dnskey, &buf);
7109                 break;
7110             default:
7111                 INSIST(0);
7112         }
7113 }
7114
7115 /*
7116  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
7117  * a KEYDATA rdataset from the key zone.
7118  *
7119  * 'rr' contains either a DNSKEY record, or a KEYDATA record
7120  *
7121  * After normalizing keys to the same format (DNSKEY, with revoke bit
7122  * cleared), return ISC_TRUE if a key that matches 'rr' is found in
7123  * 'rdset', or ISC_FALSE if not.
7124  */
7125
7126 static isc_boolean_t
7127 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
7128         unsigned char data1[4096], data2[4096];
7129         dns_rdata_t rdata, rdata1, rdata2;
7130         isc_result_t result;
7131
7132         dns_rdata_init(&rdata);
7133         dns_rdata_init(&rdata1);
7134         dns_rdata_init(&rdata2);
7135
7136         normalize_key(rr, &rdata1, data1, sizeof(data1));
7137
7138         for (result = dns_rdataset_first(rdset);
7139              result == ISC_R_SUCCESS;
7140              result = dns_rdataset_next(rdset)) {
7141                 dns_rdata_reset(&rdata);
7142                 dns_rdataset_current(rdset, &rdata);
7143                 normalize_key(&rdata, &rdata2, data2, sizeof(data2));
7144                 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
7145                         return (ISC_TRUE);
7146         }
7147
7148         return (ISC_FALSE);
7149 }
7150
7151 /*
7152  * Calculate the refresh interval for a keydata zone, per
7153  * RFC5011: MAX(1 hr,
7154  *              MIN(15 days,
7155  *                  1/2 * OrigTTL,
7156  *                  1/2 * RRSigExpirationInterval))
7157  * or for retries: MAX(1 hr,
7158  *                     MIN(1 day,
7159  *                         1/10 * OrigTTL,
7160  *                         1/10 * RRSigExpirationInterval))
7161  */
7162 static inline isc_stdtime_t
7163 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
7164         isc_result_t result;
7165         isc_uint32_t t;
7166         dns_rdataset_t *rdset;
7167         dns_rdata_t sigrr = DNS_RDATA_INIT;
7168         dns_rdata_sig_t sig;
7169         isc_stdtime_t now;
7170
7171         isc_stdtime_get(&now);
7172
7173         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7174                 rdset = &kfetch->dnskeysigset;
7175         else
7176                 return (now + HOUR);
7177
7178         result = dns_rdataset_first(rdset);
7179         if (result != ISC_R_SUCCESS)
7180                 return (now + HOUR);
7181
7182         dns_rdataset_current(rdset, &sigrr);
7183         result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7184         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7185
7186         if (!retry) {
7187                 t = sig.originalttl / 2;
7188
7189                 if (isc_serial_gt(sig.timeexpire, now)) {
7190                         isc_uint32_t exp = (sig.timeexpire - now) / 2;
7191                         if (t > exp)
7192                                 t = exp;
7193                 }
7194
7195                 if (t > (15*DAY))
7196                         t = (15*DAY);
7197
7198                 if (t < HOUR)
7199                         t = HOUR;
7200         } else {
7201                 t = sig.originalttl / 10;
7202
7203                 if (isc_serial_gt(sig.timeexpire, now)) {
7204                         isc_uint32_t exp = (sig.timeexpire - now) / 10;
7205                         if (t > exp)
7206                                 t = exp;
7207                 }
7208
7209                 if (t > DAY)
7210                         t = DAY;
7211
7212                 if (t < HOUR)
7213                         t = HOUR;
7214         }
7215
7216         return (now + t);
7217 }
7218
7219 /*
7220  * This routine is called when no changes are needed in a KEYDATA
7221  * record except to simply update the refresh timer.  Caller should
7222  * hold zone lock.
7223  */
7224 static isc_result_t
7225 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
7226 {
7227         isc_result_t result;
7228         isc_buffer_t keyb;
7229         unsigned char key_buf[4096];
7230         dns_rdata_t rdata = DNS_RDATA_INIT;
7231         dns_rdata_keydata_t keydata;
7232         dns_name_t *name;
7233         dns_zone_t *zone = kfetch->zone;
7234         isc_stdtime_t now;
7235
7236         name = dns_fixedname_name(&kfetch->name);
7237         isc_stdtime_get(&now);
7238
7239         for (result = dns_rdataset_first(&kfetch->keydataset);
7240              result == ISC_R_SUCCESS;
7241              result = dns_rdataset_next(&kfetch->keydataset)) {
7242                 dns_rdata_reset(&rdata);
7243                 dns_rdataset_current(&kfetch->keydataset, &rdata);
7244
7245                 /* Delete old version */
7246                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
7247                                     name, 0, &rdata));
7248
7249                 /* Update refresh timer */
7250                 CHECK(dns_rdata_tostruct(&rdata, &keydata, NULL));
7251                 keydata.refresh = refresh_time(kfetch, ISC_TRUE);
7252                 set_refreshkeytimer(zone, &keydata, now);
7253
7254                 dns_rdata_reset(&rdata);
7255                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7256                 CHECK(dns_rdata_fromstruct(&rdata,
7257                                            zone->rdclass, dns_rdatatype_keydata,
7258                                            &keydata, &keyb));
7259
7260                 /* Insert updated version */
7261                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
7262                                     name, 0, &rdata));
7263         }
7264         result = ISC_R_SUCCESS;
7265   failure:
7266         return (result);
7267 }
7268
7269 /*
7270  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
7271  */
7272 static isc_boolean_t
7273 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
7274         isc_result_t result;
7275         dns_name_t *keyname;
7276         isc_mem_t *mctx;
7277         dns_rdata_t sigrr = DNS_RDATA_INIT;
7278         dns_rdata_t rr = DNS_RDATA_INIT;
7279         dns_rdata_rrsig_t sig;
7280         dns_rdata_dnskey_t dnskey;
7281         dst_key_t *dstkey = NULL;
7282         unsigned char key_buf[4096];
7283         isc_buffer_t keyb;
7284         isc_boolean_t answer = ISC_FALSE;
7285
7286         REQUIRE(kfetch != NULL && keydata != NULL);
7287         REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
7288
7289         keyname = dns_fixedname_name(&kfetch->name);
7290         mctx = kfetch->zone->view->mctx;
7291
7292         /* Generate a key from keydata */
7293         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7294         dns_keydata_todnskey(keydata, &dnskey, NULL);
7295         dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
7296                                      &dnskey, &keyb);
7297         result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
7298         if (result != ISC_R_SUCCESS)
7299                 return (ISC_FALSE);
7300
7301         /* See if that key generated any of the signatures */
7302         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7303              result == ISC_R_SUCCESS;
7304              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7305                 dns_fixedname_t fixed;
7306                 dns_fixedname_init(&fixed);
7307
7308                 dns_rdata_reset(&sigrr);
7309                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7310                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7311                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7312
7313                 if (dst_key_alg(dstkey) == sig.algorithm &&
7314                     (dst_key_id(dstkey) == sig.keyid ||
7315                      dst_key_rid(dstkey) == sig.keyid)) {
7316                         result = dns_dnssec_verify2(keyname,
7317                                             &kfetch->dnskeyset,
7318                                             dstkey, ISC_FALSE, mctx, &sigrr,
7319                                             dns_fixedname_name(&fixed));
7320
7321                         dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
7322                                      "Confirm revoked DNSKEY is self-signed: "
7323                                      "%s", dns_result_totext(result));
7324
7325                         if (result == ISC_R_SUCCESS) {
7326                                 answer = ISC_TRUE;
7327                                 break;
7328                         }
7329                 }
7330         }
7331
7332         dst_key_free(&dstkey);
7333         return (answer);
7334 }
7335
7336 /*
7337  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
7338  * anchors are being managed; scan the keyset, and update the key zone and the
7339  * local trust anchors according to RFC5011.
7340  */
7341 static void
7342 keyfetch_done(isc_task_t *task, isc_event_t *event) {
7343         isc_result_t result, eresult;
7344         dns_fetchevent_t *devent;
7345         dns_keyfetch_t *kfetch;
7346         dns_zone_t *zone;
7347         isc_mem_t *mctx = NULL;
7348         dns_keytable_t *secroots = NULL;
7349         dns_dbversion_t *ver = NULL;
7350         dns_diff_t diff;
7351         isc_boolean_t alldone = ISC_FALSE;
7352         isc_boolean_t commit = ISC_FALSE;
7353         dns_name_t *keyname;
7354         dns_rdata_t sigrr = DNS_RDATA_INIT;
7355         dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
7356         dns_rdata_t keydatarr = DNS_RDATA_INIT;
7357         dns_rdata_rrsig_t sig;
7358         dns_rdata_dnskey_t dnskey;
7359         dns_rdata_keydata_t keydata;
7360         isc_boolean_t initializing;
7361         char namebuf[DNS_NAME_FORMATSIZE];
7362         unsigned char key_buf[4096];
7363         isc_buffer_t keyb;
7364         dst_key_t *dstkey;
7365         isc_stdtime_t now;
7366         int pending = 0;
7367         isc_boolean_t secure;
7368         isc_boolean_t free_needed;
7369
7370         UNUSED(task);
7371         INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
7372         INSIST(event->ev_arg != NULL);
7373
7374         kfetch = event->ev_arg;
7375         zone = kfetch->zone;
7376         isc_mem_attach(zone->mctx, &mctx);
7377         keyname = dns_fixedname_name(&kfetch->name);
7378
7379         devent = (dns_fetchevent_t *) event;
7380         eresult = devent->result;
7381
7382         /* Free resources which are not of interest */
7383         if (devent->node != NULL)
7384                 dns_db_detachnode(devent->db, &devent->node);
7385         if (devent->db != NULL)
7386                 dns_db_detach(&devent->db);
7387         isc_event_free(&event);
7388         dns_resolver_destroyfetch(&kfetch->fetch);
7389
7390         LOCK_ZONE(zone);
7391         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
7392                 goto cleanup;
7393
7394         isc_stdtime_get(&now);
7395         dns_name_format(keyname, namebuf, sizeof(namebuf));
7396
7397         result = dns_view_getsecroots(zone->view, &secroots);
7398         INSIST(result == ISC_R_SUCCESS);
7399
7400         dns_diff_init(mctx, &diff);
7401         diff.resign = zone->sigresigninginterval;
7402
7403         CHECK(dns_db_newversion(kfetch->db, &ver));
7404
7405         zone->refreshkeycount--;
7406         alldone = ISC_TF(zone->refreshkeycount == 0);
7407
7408         if (alldone)
7409                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
7410
7411         /* Fetch failed */
7412         if (eresult != ISC_R_SUCCESS ||
7413             !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
7414                 dns_zone_log(zone, ISC_LOG_WARNING,
7415                              "Unable to fetch DNSKEY set "
7416                              "'%s': %s", namebuf, dns_result_totext(eresult));
7417                 CHECK(minimal_update(kfetch, ver, &diff));
7418                 goto done;
7419         }
7420
7421         /* No RRSIGs found */
7422         if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
7423                 dns_zone_log(zone, ISC_LOG_WARNING,
7424                              "No DNSKEY RRSIGs found for "
7425                              "'%s': %s", namebuf, dns_result_totext(eresult));
7426                 CHECK(minimal_update(kfetch, ver, &diff));
7427                 goto done;
7428         }
7429
7430         /*
7431          * Validate the dnskeyset against the current trusted keys.
7432          */
7433         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7434              result == ISC_R_SUCCESS;
7435              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7436                 dns_keynode_t *keynode = NULL;
7437
7438                 dns_rdata_reset(&sigrr);
7439                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7440                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7441                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7442
7443                 result = dns_keytable_find(secroots, keyname, &keynode);
7444                 while (result == ISC_R_SUCCESS) {
7445                         dns_keynode_t *nextnode = NULL;
7446                         dns_fixedname_t fixed;
7447                         dns_fixedname_init(&fixed);
7448
7449                         dstkey = dns_keynode_key(keynode);
7450                         if (dstkey == NULL) /* fail_secure() was called */
7451                                 break;
7452
7453                         if (dst_key_alg(dstkey) == sig.algorithm &&
7454                             dst_key_id(dstkey) == sig.keyid) {
7455                                 result = dns_dnssec_verify2(keyname,
7456                                                     &kfetch->dnskeyset,
7457                                                     dstkey, ISC_FALSE,
7458                                                     zone->view->mctx, &sigrr,
7459                                                     dns_fixedname_name(&fixed));
7460
7461                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
7462                                              "Verifying DNSKEY set for zone "
7463                                              "'%s': %s", namebuf,
7464                                              dns_result_totext(result));
7465
7466                                 if (result == ISC_R_SUCCESS) {
7467                                         kfetch->dnskeyset.trust =
7468                                                 dns_trust_secure;
7469                                         kfetch->dnskeysigset.trust =
7470                                                 dns_trust_secure;
7471                                         dns_keytable_detachkeynode(secroots,
7472                                                                    &keynode);
7473                                         break;
7474                                 }
7475                         }
7476
7477                         result = dns_keytable_nextkeynode(secroots,
7478                                                           keynode, &nextnode);
7479                         dns_keytable_detachkeynode(secroots, &keynode);
7480                         keynode = nextnode;
7481                 }
7482
7483                 if (kfetch->dnskeyset.trust == dns_trust_secure)
7484                         break;
7485         }
7486
7487         /*
7488          * If we were not able to verify the answer using the current
7489          * trusted keys then all we can do is look at any revoked keys.
7490          */
7491         secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
7492
7493         /*
7494          * First scan keydataset to find keys that are not in dnskeyset
7495          *   - Missing keys which are not scheduled for removal,
7496          *     log a warning
7497          *   - Missing keys which are scheduled for removal and
7498          *     the remove hold-down timer has completed should
7499          *     be removed from the key zone
7500          *   - Missing keys whose acceptance timers have not yet
7501          *     completed, log a warning and reset the acceptance
7502          *     timer to 30 days in the future
7503          *   - All keys not being removed have their refresh timers
7504          *     updated
7505          */
7506         initializing = ISC_TRUE;
7507         for (result = dns_rdataset_first(&kfetch->keydataset);
7508              result == ISC_R_SUCCESS;
7509              result = dns_rdataset_next(&kfetch->keydataset)) {
7510                 dns_rdata_reset(&keydatarr);
7511                 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7512                 dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7513
7514                 /*
7515                  * If any keydata record has a nonzero add holddown, then
7516                  * there was a pre-existing trust anchor for this domain;
7517                  * that means we are *not* initializing it and shouldn't
7518                  * automatically trust all the keys we find at the zone apex.
7519                  */
7520                 initializing = initializing && ISC_TF(keydata.addhd == 0);
7521
7522                 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
7523                         isc_boolean_t deletekey = ISC_FALSE;
7524
7525                         if (!secure) {
7526                                 if (now > keydata.removehd)
7527                                         deletekey = ISC_TRUE;
7528                         } else if (now < keydata.addhd) {
7529                                 dns_zone_log(zone, ISC_LOG_WARNING,
7530                                              "Pending key unexpectedly missing "
7531                                              "from %s; restarting acceptance "
7532                                              "timer", namebuf);
7533                                 keydata.addhd = now + MONTH;
7534                                 keydata.refresh = refresh_time(kfetch,
7535                                                                ISC_FALSE);
7536                         } else if (keydata.addhd == 0) {
7537                                 keydata.addhd = now;
7538                         } else if (keydata.removehd == 0) {
7539                                 dns_zone_log(zone, ISC_LOG_WARNING,
7540                                              "Active key unexpectedly missing "
7541                                              "from %s", namebuf);
7542                                 keydata.refresh = now + HOUR;
7543                         } else if (now > keydata.removehd) {
7544                                 deletekey = ISC_TRUE;
7545                         } else {
7546                                 keydata.refresh = refresh_time(kfetch,
7547                                                                ISC_FALSE);
7548                         }
7549
7550                         if  (secure || deletekey) {
7551                                 /* Delete old version */
7552                                 CHECK(update_one_rr(kfetch->db, ver, &diff,
7553                                                     DNS_DIFFOP_DEL, keyname, 0,
7554                                                     &keydatarr));
7555                         }
7556
7557                         if (!secure || deletekey)
7558                                 continue;
7559
7560                         dns_rdata_reset(&keydatarr);
7561                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7562                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7563                                              dns_rdatatype_keydata,
7564                                              &keydata, &keyb);
7565
7566                         /* Insert updated version */
7567                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7568                                             DNS_DIFFOP_ADD, keyname, 0,
7569                                             &keydatarr));
7570
7571                         set_refreshkeytimer(zone, &keydata, now);
7572                 }
7573         }
7574
7575         /*
7576          * Next scan dnskeyset:
7577          *   - If new keys are found (i.e., lacking a match in keydataset)
7578          *     add them to the key zone and set the acceptance timer
7579          *     to 30 days in the future (or to immediately if we've
7580          *     determined that we're initializing the zone for the
7581          *     first time)
7582          *   - Previously-known keys that have been revoked
7583          *     must be scheduled for removal from the key zone (or,
7584          *     if they hadn't been accepted as trust anchors yet
7585          *     anyway, removed at once)
7586          *   - Previously-known unrevoked keys whose acceptance timers
7587          *     have completed are promoted to trust anchors
7588          *   - All keys not being removed have their refresh
7589          *     timers updated
7590          */
7591         for (result = dns_rdataset_first(&kfetch->dnskeyset);
7592              result == ISC_R_SUCCESS;
7593              result = dns_rdataset_next(&kfetch->dnskeyset)) {
7594                 isc_boolean_t revoked = ISC_FALSE;
7595                 isc_boolean_t newkey = ISC_FALSE;
7596                 isc_boolean_t updatekey = ISC_FALSE;
7597                 isc_boolean_t deletekey = ISC_FALSE;
7598                 isc_boolean_t trustkey = ISC_FALSE;
7599
7600                 dns_rdata_reset(&dnskeyrr);
7601                 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
7602                 dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7603
7604                 /* Skip ZSK's */
7605                 if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
7606                         continue;
7607
7608                 revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
7609
7610                 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
7611                         dns_rdata_reset(&keydatarr);
7612                         dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7613                         dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7614
7615                         if (revoked && revocable(kfetch, &keydata)) {
7616                                 if (keydata.addhd > now) {
7617                                         /*
7618                                          * Key wasn't trusted yet, and now
7619                                          * it's been revoked?  Just remove it
7620                                          */
7621                                         deletekey = ISC_TRUE;
7622                                 } else if (keydata.removehd == 0) {
7623                                         /* Remove from secroots */
7624                                         dns_view_untrust(zone->view, keyname,
7625                                                          &dnskey, mctx);
7626
7627                                         /* If initializing, delete now */
7628                                         if (keydata.addhd == 0)
7629                                                 deletekey = ISC_TRUE;
7630                                         else
7631                                                 keydata.removehd = now + MONTH;
7632                                 } else if (keydata.removehd < now) {
7633                                         /* Scheduled for removal */
7634                                         deletekey = ISC_TRUE;
7635                                 }
7636                         } else if (revoked) {
7637                                 if (secure && keydata.removehd == 0) {
7638                                         dns_zone_log(zone, ISC_LOG_WARNING,
7639                                                      "Active key for zone "
7640                                                      "'%s' is revoked but "
7641                                                      "did not self-sign; "
7642                                                          "ignoring.", namebuf);
7643                                                 continue;
7644                                 }
7645                         } else if (secure) {
7646                                 if (keydata.removehd != 0) {
7647                                         /*
7648                                          * Key isn't revoked--but it
7649                                          * seems it used to be.
7650                                          * Remove it now and add it
7651                                          * back as if it were a fresh key.
7652                                          */
7653                                         deletekey = ISC_TRUE;
7654                                         newkey = ISC_TRUE;
7655                                 } else if (keydata.addhd > now)
7656                                         pending++;
7657                                 else if (keydata.addhd == 0)
7658                                         keydata.addhd = now;
7659
7660                                 if (keydata.addhd <= now)
7661                                         trustkey = ISC_TRUE;
7662                         }
7663
7664                         if (!deletekey && !newkey)
7665                                 updatekey = ISC_TRUE;
7666                 } else if (secure) {
7667                         /*
7668                          * Key wasn't in the key zone but it's
7669                          * revoked now anyway, so just skip it
7670                          */
7671                         if (revoked)
7672                                 continue;
7673
7674                         /* Key wasn't in the key zone: add it */
7675                         newkey = ISC_TRUE;
7676
7677                         if (initializing) {
7678                                 dns_keytag_t tag = 0;
7679                                 CHECK(compute_tag(keyname, &dnskey,
7680                                                   mctx, &tag));
7681                                 dns_zone_log(zone, ISC_LOG_WARNING,
7682                                              "Initializing automatic trust "
7683                                              "anchor management for zone '%s'; "
7684                                              "DNSKEY ID %d is now trusted, "
7685                                              "waiving the normal 30-day "
7686                                              "waiting period.",
7687                                              namebuf, tag);
7688                                 trustkey = ISC_TRUE;
7689                         }
7690                 }
7691
7692                 /* Delete old version */
7693                 if (deletekey || !newkey)
7694                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7695                                             DNS_DIFFOP_DEL, keyname, 0,
7696                                             &keydatarr));
7697
7698                 if (updatekey) {
7699                         /* Set refresh timer */
7700                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
7701                         dns_rdata_reset(&keydatarr);
7702                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7703                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7704                                              dns_rdatatype_keydata,
7705                                              &keydata, &keyb);
7706
7707                         /* Insert updated version */
7708                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7709                                             DNS_DIFFOP_ADD, keyname, 0,
7710                                             &keydatarr));
7711                 } else if (newkey) {
7712                         /* Convert DNSKEY to KEYDATA */
7713                         dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7714                         dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
7715                                                NULL);
7716                         keydata.addhd = initializing ? now : now + MONTH;
7717                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
7718                         dns_rdata_reset(&keydatarr);
7719                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7720                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7721                                              dns_rdatatype_keydata,
7722                                              &keydata, &keyb);
7723
7724                         /* Insert into key zone */
7725                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7726                                             DNS_DIFFOP_ADD, keyname, 0,
7727                                             &keydatarr));
7728                 }
7729
7730                 if (trustkey) {
7731                         /* Trust this key. */
7732                         dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7733                         trust_key(zone, keyname, &dnskey, mctx);
7734                 }
7735
7736                 if (!deletekey)
7737                         set_refreshkeytimer(zone, &keydata, now);
7738         }
7739
7740         /*
7741          * RFC5011 says, "A trust point that has all of its trust anchors
7742          * revoked is considered deleted and is treated as if the trust
7743          * point was never configured."  But if someone revoked their
7744          * active key before the standby was trusted, that would mean the
7745          * zone would suddenly be nonsecured.  We avoid this by checking to
7746          * see if there's pending keydata.  If so, we put a null key in
7747          * the security roots; then all queries to the zone will fail.
7748          */
7749         if (pending != 0)
7750                 fail_secure(zone, keyname);
7751
7752  done:
7753
7754         if (!ISC_LIST_EMPTY(diff.tuples)) {
7755                 /* Write changes to journal file. */
7756                 CHECK(increment_soa_serial(kfetch->db, ver, &diff, mctx));
7757                 CHECK(zone_journal(zone, &diff, "keyfetch_done"));
7758                 commit = ISC_TRUE;
7759
7760                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
7761                 zone_needdump(zone, 30);
7762         }
7763
7764   failure:
7765
7766         dns_diff_clear(&diff);
7767         if (ver != NULL)
7768                 dns_db_closeversion(kfetch->db, &ver, commit);
7769
7770  cleanup:
7771         dns_db_detach(&kfetch->db);
7772
7773         INSIST(zone->irefs > 0);
7774         zone->irefs--;
7775         kfetch->zone = NULL;
7776
7777         if (dns_rdataset_isassociated(&kfetch->keydataset))
7778                 dns_rdataset_disassociate(&kfetch->keydataset);
7779         if (dns_rdataset_isassociated(&kfetch->dnskeyset))
7780                 dns_rdataset_disassociate(&kfetch->dnskeyset);
7781         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7782                 dns_rdataset_disassociate(&kfetch->dnskeysigset);
7783
7784         dns_name_free(keyname, mctx);
7785         isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
7786         isc_mem_detach(&mctx);
7787
7788         if (secroots != NULL)
7789                 dns_keytable_detach(&secroots);
7790
7791         free_needed = exit_check(zone);
7792         UNLOCK_ZONE(zone);
7793         if (free_needed)
7794                 zone_free(zone);
7795 }
7796
7797 /*
7798  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
7799  * records from the zone apex.
7800  */
7801 static void
7802 zone_refreshkeys(dns_zone_t *zone) {
7803         const char me[] = "zone_refreshkeys";
7804         isc_result_t result;
7805         dns_rriterator_t rrit;
7806         dns_db_t *db = NULL;
7807         dns_dbversion_t *ver = NULL;
7808         dns_diff_t diff;
7809         dns_rdata_t rdata = DNS_RDATA_INIT;
7810         dns_rdata_keydata_t kd;
7811         isc_stdtime_t now;
7812         isc_boolean_t commit = ISC_FALSE;
7813         isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
7814
7815         ENTER;
7816         REQUIRE(zone->db != NULL);
7817
7818         isc_stdtime_get(&now);
7819
7820         LOCK_ZONE(zone);
7821         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
7822                 isc_time_settoepoch(&zone->refreshkeytime);
7823                 UNLOCK_ZONE(zone);
7824                 return;
7825         }
7826
7827         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7828         dns_db_attach(zone->db, &db);
7829         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7830
7831         dns_diff_init(zone->mctx, &diff);
7832
7833         CHECK(dns_db_newversion(db, &ver));
7834
7835         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
7836
7837         dns_rriterator_init(&rrit, db, ver, 0);
7838         for (result = dns_rriterator_first(&rrit);
7839              result == ISC_R_SUCCESS;
7840              result = dns_rriterator_nextrrset(&rrit)) {
7841                 isc_stdtime_t timer = 0xffffffff;
7842                 dns_name_t *name = NULL, *kname = NULL;
7843                 dns_rdataset_t *kdset = NULL;
7844                 dns_keyfetch_t *kfetch;
7845                 isc_uint32_t ttl;
7846
7847                 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
7848                 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
7849                     !dns_rdataset_isassociated(kdset))
7850                         continue;
7851
7852                 /*
7853                  * Scan the stored keys looking for ones that need
7854                  * removal or refreshing
7855                  */
7856                 for (result = dns_rdataset_first(kdset);
7857                      result == ISC_R_SUCCESS;
7858                      result = dns_rdataset_next(kdset)) {
7859                         dns_rdata_reset(&rdata);
7860                         dns_rdataset_current(kdset, &rdata);
7861                         result = dns_rdata_tostruct(&rdata, &kd, NULL);
7862                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7863
7864                         /* Removal timer expired? */
7865                         if (kd.removehd != 0 && kd.removehd < now) {
7866                                 CHECK(update_one_rr(db, ver, &diff,
7867                                                     DNS_DIFFOP_DEL, name, ttl,
7868                                                     &rdata));
7869                                 continue;
7870                         }
7871
7872                         /* Acceptance timer expired? */
7873                         if (kd.addhd != 0 && kd.addhd < now)
7874                                 timer = kd.addhd;
7875
7876                         /* Or do we just need to refresh the keyset? */
7877                         if (timer > kd.refresh)
7878                                 timer = kd.refresh;
7879                 }
7880
7881                 if (timer > now)
7882                         continue;
7883
7884                 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
7885                 if (kfetch == NULL) {
7886                         fetch_err = ISC_TRUE;
7887                         goto failure;
7888                 }
7889
7890                 zone->refreshkeycount++;
7891                 kfetch->zone = zone;
7892                 zone->irefs++;
7893                 INSIST(zone->irefs != 0);
7894                 dns_fixedname_init(&kfetch->name);
7895                 kname = dns_fixedname_name(&kfetch->name);
7896                 dns_name_dup(name, zone->mctx, kname);
7897                 dns_rdataset_init(&kfetch->dnskeyset);
7898                 dns_rdataset_init(&kfetch->dnskeysigset);
7899                 dns_rdataset_init(&kfetch->keydataset);
7900                 dns_rdataset_clone(kdset, &kfetch->keydataset);
7901                 kfetch->db = NULL;
7902                 dns_db_attach(db, &kfetch->db);
7903                 kfetch->fetch = NULL;
7904
7905                 result = dns_resolver_createfetch(zone->view->resolver,
7906                                                   kname, dns_rdatatype_dnskey,
7907                                                   NULL, NULL, NULL,
7908                                                   DNS_FETCHOPT_NOVALIDATE,
7909                                                   zone->task,
7910                                                   keyfetch_done, kfetch,
7911                                                   &kfetch->dnskeyset,
7912                                                   &kfetch->dnskeysigset,
7913                                                   &kfetch->fetch);
7914                 if (result == ISC_R_SUCCESS)
7915                         fetching = ISC_TRUE;
7916                 else {
7917                         zone->refreshkeycount--;
7918                         zone->irefs--;
7919                         dns_db_detach(&kfetch->db);
7920                         dns_rdataset_disassociate(&kfetch->keydataset);
7921                         dns_name_free(kname, zone->mctx);
7922                         isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
7923                         dns_zone_log(zone, ISC_LOG_WARNING,
7924                                      "Failed to create fetch for "
7925                                      "DNSKEY update");
7926                         fetch_err = ISC_TRUE;
7927                 }
7928         }
7929         if (!ISC_LIST_EMPTY(diff.tuples)) {
7930                 CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
7931                 CHECK(zone_journal(zone, &diff, "zone_refreshkeys"));
7932                 commit = ISC_TRUE;
7933                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
7934                 zone_needdump(zone, 30);
7935         }
7936
7937   failure:
7938         if (fetch_err) {
7939                 /*
7940                  * Error during a key fetch; retry in an hour.
7941                  */
7942                 isc_time_t timenow, timethen;
7943                 char timebuf[80];
7944
7945                 TIME_NOW(&timenow);
7946                 DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
7947                 zone->refreshkeytime = timethen;
7948                 zone_settimer(zone, &timenow);
7949
7950                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
7951                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
7952                              timebuf);
7953
7954                 if (!fetching)
7955                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
7956         }
7957
7958         UNLOCK_ZONE(zone);
7959
7960         dns_diff_clear(&diff);
7961         if (ver != NULL) {
7962                 dns_rriterator_destroy(&rrit);
7963                 dns_db_closeversion(db, &ver, commit);
7964         }
7965         dns_db_detach(&db);
7966 }
7967
7968 static void
7969 zone_maintenance(dns_zone_t *zone) {
7970         const char me[] = "zone_maintenance";
7971         isc_time_t now;
7972         isc_result_t result;
7973         isc_boolean_t dumping;
7974
7975         REQUIRE(DNS_ZONE_VALID(zone));
7976         ENTER;
7977
7978         /*
7979          * Configuring the view of this zone may have
7980          * failed, for example because the config file
7981          * had a syntax error.  In that case, the view
7982          * db or resolver will be NULL, and we had better not try
7983          * to do maintenance on it.
7984          */
7985         if (zone->view == NULL || zone->view->adb == NULL)
7986                 return;
7987
7988         TIME_NOW(&now);
7989
7990         /*
7991          * Expire check.
7992          */
7993         switch (zone->type) {
7994         case dns_zone_slave:
7995         case dns_zone_stub:
7996                 LOCK_ZONE(zone);
7997                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
7998                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
7999                         zone_expire(zone);
8000                         zone->refreshtime = now;
8001                 }
8002                 UNLOCK_ZONE(zone);
8003                 break;
8004         default:
8005                 break;
8006         }
8007
8008         /*
8009          * Up to date check.
8010          */
8011         switch (zone->type) {
8012         case dns_zone_slave:
8013         case dns_zone_stub:
8014                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8015                     isc_time_compare(&now, &zone->refreshtime) >= 0)
8016                         dns_zone_refresh(zone);
8017                 break;
8018         default:
8019                 break;
8020         }
8021
8022         /*
8023          * Do we need to consolidate the backing store?
8024          */
8025         switch (zone->type) {
8026         case dns_zone_master:
8027         case dns_zone_slave:
8028         case dns_zone_key:
8029         case dns_zone_stub:
8030                 LOCK_ZONE(zone);
8031                 if (zone->masterfile != NULL &&
8032                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
8033                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8034                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
8035                         dumping = was_dumping(zone);
8036                 } else
8037                         dumping = ISC_TRUE;
8038                 UNLOCK_ZONE(zone);
8039                 if (!dumping) {
8040                         result = zone_dump(zone, ISC_TRUE); /* task locked */
8041                         if (result != ISC_R_SUCCESS)
8042                                 dns_zone_log(zone, ISC_LOG_WARNING,
8043                                              "dump failed: %s",
8044                                              dns_result_totext(result));
8045                 }
8046                 break;
8047         default:
8048                 break;
8049         }
8050
8051         /*
8052          * Do we need to refresh keys?
8053          */
8054         switch (zone->type) {
8055         case dns_zone_key:
8056                 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
8057                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8058                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
8059                         zone_refreshkeys(zone);
8060                 break;
8061         case dns_zone_master:
8062                 if (!isc_time_isepoch(&zone->refreshkeytime) &&
8063                     isc_time_compare(&now, &zone->refreshkeytime) >= 0)
8064                         zone_rekey(zone);
8065         default:
8066                 break;
8067         }
8068
8069         switch (zone->type) {
8070         case dns_zone_master:
8071         case dns_zone_slave:
8072                 /*
8073                  * Do we need to send out notify messages?
8074                  */
8075                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8076                     isc_time_compare(&now, &zone->notifytime) >= 0)
8077                         zone_notify(zone, &now);
8078                 /*
8079                  * Do we need to sign/resign some RRsets?
8080                  */
8081                 if (!isc_time_isepoch(&zone->signingtime) &&
8082                     isc_time_compare(&now, &zone->signingtime) >= 0)
8083                         zone_sign(zone);
8084                 else if (!isc_time_isepoch(&zone->resigntime) &&
8085                     isc_time_compare(&now, &zone->resigntime) >= 0)
8086                         zone_resigninc(zone);
8087                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
8088                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
8089                         zone_nsec3chain(zone);
8090                 /*
8091                  * Do we need to issue a key expiry warning.
8092                  */
8093                 if (!isc_time_isepoch(&zone->keywarntime) &&
8094                     isc_time_compare(&now, &zone->keywarntime) >= 0)
8095                         set_key_expiry_warning(zone, zone->key_expiry,
8096                                                isc_time_seconds(&now));
8097                 break;
8098         default:
8099                 break;
8100         }
8101         zone_settimer(zone, &now);
8102 }
8103
8104 void
8105 dns_zone_markdirty(dns_zone_t *zone) {
8106
8107         LOCK_ZONE(zone);
8108         if (zone->type == dns_zone_master)
8109                 set_resigntime(zone);   /* XXXMPA make separate call back */
8110         zone_needdump(zone, DNS_DUMP_DELAY);
8111         UNLOCK_ZONE(zone);
8112 }
8113
8114 void
8115 dns_zone_expire(dns_zone_t *zone) {
8116         REQUIRE(DNS_ZONE_VALID(zone));
8117
8118         LOCK_ZONE(zone);
8119         zone_expire(zone);
8120         UNLOCK_ZONE(zone);
8121 }
8122
8123 static void
8124 zone_expire(dns_zone_t *zone) {
8125         /*
8126          * 'zone' locked by caller.
8127          */
8128
8129         REQUIRE(LOCKED_ZONE(zone));
8130
8131         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
8132
8133         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
8134         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
8135         zone->retry = DNS_ZONE_DEFAULTRETRY;
8136         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
8137         zone_unload(zone);
8138 }
8139
8140 void
8141 dns_zone_refresh(dns_zone_t *zone) {
8142         isc_interval_t i;
8143         isc_uint32_t oldflags;
8144         unsigned int j;
8145         isc_result_t result;
8146
8147         REQUIRE(DNS_ZONE_VALID(zone));
8148
8149         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
8150                 return;
8151
8152         /*
8153          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
8154          * in progress at a time.
8155          */
8156
8157         LOCK_ZONE(zone);
8158         oldflags = zone->flags;
8159         if (zone->masterscnt == 0) {
8160                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
8161                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
8162                         dns_zone_log(zone, ISC_LOG_ERROR,
8163                                      "cannot refresh: no masters");
8164                 goto unlock;
8165         }
8166         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
8167         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
8168         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
8169         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
8170                 goto unlock;
8171
8172         /*
8173          * Set the next refresh time as if refresh check has failed.
8174          * Setting this to the retry time will do that.  XXXMLG
8175          * If we are successful it will be reset using zone->refresh.
8176          */
8177         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
8178                          0);
8179         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
8180         if (result != ISC_R_SUCCESS)
8181                 dns_zone_log(zone, ISC_LOG_WARNING,
8182                              "isc_time_nowplusinterval() failed: %s",
8183                              dns_result_totext(result));
8184
8185         /*
8186          * When lacking user-specified timer values from the SOA,
8187          * do exponential backoff of the retry time up to a
8188          * maximum of six hours.
8189          */
8190         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
8191                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
8192
8193         zone->curmaster = 0;
8194         for (j = 0; j < zone->masterscnt; j++)
8195                 zone->mastersok[j] = ISC_FALSE;
8196         /* initiate soa query */
8197         queue_soa_query(zone);
8198  unlock:
8199         UNLOCK_ZONE(zone);
8200 }
8201
8202 isc_result_t
8203 dns_zone_flush(dns_zone_t *zone) {
8204         isc_result_t result = ISC_R_SUCCESS;
8205         isc_boolean_t dumping;
8206
8207         REQUIRE(DNS_ZONE_VALID(zone));
8208
8209         LOCK_ZONE(zone);
8210         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
8211         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8212             zone->masterfile != NULL) {
8213                 result = ISC_R_ALREADYRUNNING;
8214                 dumping = was_dumping(zone);
8215         } else
8216                 dumping = ISC_TRUE;
8217         UNLOCK_ZONE(zone);
8218         if (!dumping)
8219                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
8220         return (result);
8221 }
8222
8223 isc_result_t
8224 dns_zone_dump(dns_zone_t *zone) {
8225         isc_result_t result = ISC_R_ALREADYRUNNING;
8226         isc_boolean_t dumping;
8227
8228         REQUIRE(DNS_ZONE_VALID(zone));
8229
8230         LOCK_ZONE(zone);
8231         dumping = was_dumping(zone);
8232         UNLOCK_ZONE(zone);
8233         if (!dumping)
8234                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
8235         return (result);
8236 }
8237
8238 static void
8239 zone_needdump(dns_zone_t *zone, unsigned int delay) {
8240         isc_time_t dumptime;
8241         isc_time_t now;
8242
8243         /*
8244          * 'zone' locked by caller
8245          */
8246
8247         REQUIRE(DNS_ZONE_VALID(zone));
8248         REQUIRE(LOCKED_ZONE(zone));
8249
8250         /*
8251          * Do we have a place to dump to and are we loaded?
8252          */
8253         if (zone->masterfile == NULL ||
8254             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
8255                 return;
8256
8257         TIME_NOW(&now);
8258         /* add some noise */
8259         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
8260
8261         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8262         if (isc_time_isepoch(&zone->dumptime) ||
8263             isc_time_compare(&zone->dumptime, &dumptime) > 0)
8264                 zone->dumptime = dumptime;
8265         if (zone->task != NULL)
8266                 zone_settimer(zone, &now);
8267 }
8268
8269 static void
8270 dump_done(void *arg, isc_result_t result) {
8271         const char me[] = "dump_done";
8272         dns_zone_t *zone = arg;
8273         dns_db_t *db;
8274         dns_dbversion_t *version;
8275         isc_boolean_t again = ISC_FALSE;
8276         isc_boolean_t compact = ISC_FALSE;
8277         isc_uint32_t serial;
8278         isc_result_t tresult;
8279
8280         REQUIRE(DNS_ZONE_VALID(zone));
8281
8282         ENTER;
8283
8284         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
8285             zone->journalsize != -1) {
8286
8287                 /*
8288                  * We don't own these, zone->dctx must stay valid.
8289                  */
8290                 db = dns_dumpctx_db(zone->dctx);
8291                 version = dns_dumpctx_version(zone->dctx);
8292
8293                 tresult = dns_db_getsoaserial(db, version, &serial);
8294                 /*
8295                  * Note: we are task locked here so we can test
8296                  * zone->xfr safely.
8297                  */
8298                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
8299                         tresult = dns_journal_compact(zone->mctx,
8300                                                       zone->journal,
8301                                                       serial,
8302                                                       zone->journalsize);
8303                         switch (tresult) {
8304                         case ISC_R_SUCCESS:
8305                         case ISC_R_NOSPACE:
8306                         case ISC_R_NOTFOUND:
8307                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
8308                                              "dns_journal_compact: %s",
8309                                              dns_result_totext(tresult));
8310                                 break;
8311                         default:
8312                                 dns_zone_log(zone, ISC_LOG_ERROR,
8313                                              "dns_journal_compact failed: %s",
8314                                              dns_result_totext(tresult));
8315                                 break;
8316                         }
8317                 } else if (tresult == ISC_R_SUCCESS) {
8318                         compact = ISC_TRUE;
8319                         zone->compact_serial = serial;
8320                 }
8321         }
8322
8323         LOCK_ZONE(zone);
8324         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8325         if (compact)
8326                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
8327         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
8328                 /*
8329                  * Try again in a short while.
8330                  */
8331                 zone_needdump(zone, DNS_DUMP_DELAY);
8332         } else if (result == ISC_R_SUCCESS &&
8333                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8334                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8335                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8336                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8337                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8338                 isc_time_settoepoch(&zone->dumptime);
8339                 again = ISC_TRUE;
8340         } else if (result == ISC_R_SUCCESS)
8341                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8342
8343         if (zone->dctx != NULL)
8344                 dns_dumpctx_detach(&zone->dctx);
8345         zonemgr_putio(&zone->writeio);
8346         UNLOCK_ZONE(zone);
8347         if (again)
8348                 (void)zone_dump(zone, ISC_FALSE);
8349         dns_zone_idetach(&zone);
8350 }
8351
8352 static isc_result_t
8353 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
8354         const char me[] = "zone_dump";
8355         isc_result_t result;
8356         dns_dbversion_t *version = NULL;
8357         isc_boolean_t again;
8358         dns_db_t *db = NULL;
8359         char *masterfile = NULL;
8360         dns_masterformat_t masterformat = dns_masterformat_none;
8361
8362 /*
8363  * 'compact' MUST only be set if we are task locked.
8364  */
8365
8366         REQUIRE(DNS_ZONE_VALID(zone));
8367         ENTER;
8368
8369  redo:
8370         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8371         if (zone->db != NULL)
8372                 dns_db_attach(zone->db, &db);
8373         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8374         LOCK_ZONE(zone);
8375         if (zone->masterfile != NULL) {
8376                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
8377                 masterformat = zone->masterformat;
8378         }
8379         UNLOCK_ZONE(zone);
8380         if (db == NULL) {
8381                 result = DNS_R_NOTLOADED;
8382                 goto fail;
8383         }
8384         if (masterfile == NULL) {
8385                 result = DNS_R_NOMASTERFILE;
8386                 goto fail;
8387         }
8388
8389         if (compact && zone->type != dns_zone_stub) {
8390                 dns_zone_t *dummy = NULL;
8391                 LOCK_ZONE(zone);
8392                 zone_iattach(zone, &dummy);
8393                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
8394                                        zone_gotwritehandle, zone,
8395                                        &zone->writeio);
8396                 if (result != ISC_R_SUCCESS)
8397                         zone_idetach(&dummy);
8398                 else
8399                         result = DNS_R_CONTINUE;
8400                 UNLOCK_ZONE(zone);
8401         } else {
8402                 dns_db_currentversion(db, &version);
8403                 result = dns_master_dump2(zone->mctx, db, version,
8404                                           &dns_master_style_default,
8405                                           masterfile, masterformat);
8406                 dns_db_closeversion(db, &version, ISC_FALSE);
8407         }
8408  fail:
8409         if (db != NULL)
8410                 dns_db_detach(&db);
8411         if (masterfile != NULL)
8412                 isc_mem_free(zone->mctx, masterfile);
8413         masterfile = NULL;
8414
8415         if (result == DNS_R_CONTINUE)
8416                 return (ISC_R_SUCCESS); /* XXXMPA */
8417
8418         again = ISC_FALSE;
8419         LOCK_ZONE(zone);
8420         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8421         if (result != ISC_R_SUCCESS) {
8422                 /*
8423                  * Try again in a short while.
8424                  */
8425                 zone_needdump(zone, DNS_DUMP_DELAY);
8426         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8427                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8428                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8429                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8430                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8431                 isc_time_settoepoch(&zone->dumptime);
8432                 again = ISC_TRUE;
8433         } else
8434                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8435         UNLOCK_ZONE(zone);
8436         if (again)
8437                 goto redo;
8438
8439         return (result);
8440 }
8441
8442 static isc_result_t
8443 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
8444              dns_masterformat_t format)
8445 {
8446         isc_result_t result;
8447         dns_dbversion_t *version = NULL;
8448         dns_db_t *db = NULL;
8449
8450         REQUIRE(DNS_ZONE_VALID(zone));
8451
8452         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8453         if (zone->db != NULL)
8454                 dns_db_attach(zone->db, &db);
8455         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8456         if (db == NULL)
8457                 return (DNS_R_NOTLOADED);
8458
8459         dns_db_currentversion(db, &version);
8460         result = dns_master_dumptostream2(zone->mctx, db, version, style,
8461                                           format, fd);
8462         dns_db_closeversion(db, &version, ISC_FALSE);
8463         dns_db_detach(&db);
8464         return (result);
8465 }
8466
8467 isc_result_t
8468 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
8469                        const dns_master_style_t *style) {
8470         return dumptostream(zone, fd, style, format);
8471 }
8472
8473 isc_result_t
8474 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
8475         return dumptostream(zone, fd, &dns_master_style_default,
8476                             dns_masterformat_text);
8477 }
8478
8479 isc_result_t
8480 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
8481         return dumptostream(zone, fd, &dns_master_style_full,
8482                             dns_masterformat_text);
8483 }
8484
8485 void
8486 dns_zone_unload(dns_zone_t *zone) {
8487         REQUIRE(DNS_ZONE_VALID(zone));
8488
8489         LOCK_ZONE(zone);
8490         zone_unload(zone);
8491         UNLOCK_ZONE(zone);
8492 }
8493
8494 static void
8495 notify_cancel(dns_zone_t *zone) {
8496         dns_notify_t *notify;
8497
8498         /*
8499          * 'zone' locked by caller.
8500          */
8501
8502         REQUIRE(LOCKED_ZONE(zone));
8503
8504         for (notify = ISC_LIST_HEAD(zone->notifies);
8505              notify != NULL;
8506              notify = ISC_LIST_NEXT(notify, link)) {
8507                 if (notify->find != NULL)
8508                         dns_adb_cancelfind(notify->find);
8509                 if (notify->request != NULL)
8510                         dns_request_cancel(notify->request);
8511         }
8512 }
8513
8514 static void
8515 forward_cancel(dns_zone_t *zone) {
8516         dns_forward_t *forward;
8517
8518         /*
8519          * 'zone' locked by caller.
8520          */
8521
8522         REQUIRE(LOCKED_ZONE(zone));
8523
8524         for (forward = ISC_LIST_HEAD(zone->forwards);
8525              forward != NULL;
8526              forward = ISC_LIST_NEXT(forward, link)) {
8527                 if (forward->request != NULL)
8528                         dns_request_cancel(forward->request);
8529         }
8530 }
8531
8532 static void
8533 zone_unload(dns_zone_t *zone) {
8534
8535         /*
8536          * 'zone' locked by caller.
8537          */
8538
8539         REQUIRE(LOCKED_ZONE(zone));
8540
8541         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
8542             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
8543                 if (zone->writeio != NULL)
8544                         zonemgr_cancelio(zone->writeio);
8545
8546                 if (zone->dctx != NULL)
8547                         dns_dumpctx_cancel(zone->dctx);
8548         }
8549         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
8550         zone_detachdb(zone);
8551         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
8552         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
8553         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8554 }
8555
8556 void
8557 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8558         REQUIRE(DNS_ZONE_VALID(zone));
8559         REQUIRE(val > 0);
8560
8561         zone->minrefresh = val;
8562 }
8563
8564 void
8565 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8566         REQUIRE(DNS_ZONE_VALID(zone));
8567         REQUIRE(val > 0);
8568
8569         zone->maxrefresh = val;
8570 }
8571
8572 void
8573 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
8574         REQUIRE(DNS_ZONE_VALID(zone));
8575         REQUIRE(val > 0);
8576
8577         zone->minretry = val;
8578 }
8579
8580 void
8581 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
8582         REQUIRE(DNS_ZONE_VALID(zone));
8583         REQUIRE(val > 0);
8584
8585         zone->maxretry = val;
8586 }
8587
8588 static isc_boolean_t
8589 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
8590         dns_notify_t *notify;
8591
8592         for (notify = ISC_LIST_HEAD(zone->notifies);
8593              notify != NULL;
8594              notify = ISC_LIST_NEXT(notify, link)) {
8595                 if (notify->request != NULL)
8596                         continue;
8597                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
8598                     dns_name_equal(name, &notify->ns))
8599                         return (ISC_TRUE);
8600                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
8601                         return (ISC_TRUE);
8602         }
8603         return (ISC_FALSE);
8604 }
8605
8606 static isc_boolean_t
8607 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
8608         dns_tsigkey_t *key = NULL;
8609         isc_sockaddr_t src;
8610         isc_sockaddr_t any;
8611         isc_boolean_t isself;
8612         isc_netaddr_t dstaddr;
8613         isc_result_t result;
8614
8615         if (zone->view == NULL || zone->isself == NULL)
8616                 return (ISC_FALSE);
8617
8618         switch (isc_sockaddr_pf(dst)) {
8619         case PF_INET:
8620                 src = zone->notifysrc4;
8621                 isc_sockaddr_any(&any);
8622                 break;
8623         case PF_INET6:
8624                 src = zone->notifysrc6;
8625                 isc_sockaddr_any6(&any);
8626                 break;
8627         default:
8628                 return (ISC_FALSE);
8629         }
8630
8631         /*
8632          * When sending from any the kernel will assign a source address
8633          * that matches the destination address.
8634          */
8635         if (isc_sockaddr_eqaddr(&any, &src))
8636                 src = *dst;
8637
8638         isc_netaddr_fromsockaddr(&dstaddr, dst);
8639         result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
8640         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
8641                 return (ISC_FALSE);
8642         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
8643                                 zone->isselfarg);
8644         if (key != NULL)
8645                 dns_tsigkey_detach(&key);
8646         return (isself);
8647 }
8648
8649 static void
8650 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
8651         isc_mem_t *mctx;
8652
8653         /*
8654          * Caller holds zone lock.
8655          */
8656         REQUIRE(DNS_NOTIFY_VALID(notify));
8657
8658         if (notify->zone != NULL) {
8659                 if (!locked)
8660                         LOCK_ZONE(notify->zone);
8661                 REQUIRE(LOCKED_ZONE(notify->zone));
8662                 if (ISC_LINK_LINKED(notify, link))
8663                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
8664                 if (!locked)
8665                         UNLOCK_ZONE(notify->zone);
8666                 if (locked)
8667                         zone_idetach(&notify->zone);
8668                 else
8669                         dns_zone_idetach(&notify->zone);
8670         }
8671         if (notify->find != NULL)
8672                 dns_adb_destroyfind(&notify->find);
8673         if (notify->request != NULL)
8674                 dns_request_destroy(&notify->request);
8675         if (dns_name_dynamic(&notify->ns))
8676                 dns_name_free(&notify->ns, notify->mctx);
8677         mctx = notify->mctx;
8678         isc_mem_put(notify->mctx, notify, sizeof(*notify));
8679         isc_mem_detach(&mctx);
8680 }
8681
8682 static isc_result_t
8683 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
8684         dns_notify_t *notify;
8685
8686         REQUIRE(notifyp != NULL && *notifyp == NULL);
8687
8688         notify = isc_mem_get(mctx, sizeof(*notify));
8689         if (notify == NULL)
8690                 return (ISC_R_NOMEMORY);
8691
8692         notify->mctx = NULL;
8693         isc_mem_attach(mctx, &notify->mctx);
8694         notify->flags = flags;
8695         notify->zone = NULL;
8696         notify->find = NULL;
8697         notify->request = NULL;
8698         isc_sockaddr_any(&notify->dst);
8699         dns_name_init(&notify->ns, NULL);
8700         ISC_LINK_INIT(notify, link);
8701         notify->magic = NOTIFY_MAGIC;
8702         *notifyp = notify;
8703         return (ISC_R_SUCCESS);
8704 }
8705
8706 /*
8707  * XXXAG should check for DNS_ZONEFLG_EXITING
8708  */
8709 static void
8710 process_adb_event(isc_task_t *task, isc_event_t *ev) {
8711         dns_notify_t *notify;
8712         isc_eventtype_t result;
8713
8714         UNUSED(task);
8715
8716         notify = ev->ev_arg;
8717         REQUIRE(DNS_NOTIFY_VALID(notify));
8718         INSIST(task == notify->zone->task);
8719         result = ev->ev_type;
8720         isc_event_free(&ev);
8721         if (result == DNS_EVENT_ADBMOREADDRESSES) {
8722                 dns_adb_destroyfind(&notify->find);
8723                 notify_find_address(notify);
8724                 return;
8725         }
8726         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
8727                 LOCK_ZONE(notify->zone);
8728                 notify_send(notify);
8729                 UNLOCK_ZONE(notify->zone);
8730         }
8731         notify_destroy(notify, ISC_FALSE);
8732 }
8733
8734 static void
8735 notify_find_address(dns_notify_t *notify) {
8736         isc_result_t result;
8737         unsigned int options;
8738
8739         REQUIRE(DNS_NOTIFY_VALID(notify));
8740         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
8741                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
8742
8743         if (notify->zone->view->adb == NULL)
8744                 goto destroy;
8745
8746         result = dns_adb_createfind(notify->zone->view->adb,
8747                                     notify->zone->task,
8748                                     process_adb_event, notify,
8749                                     &notify->ns, dns_rootname, 0,
8750                                     options, 0, NULL,
8751                                     notify->zone->view->dstport,
8752                                     &notify->find);
8753
8754         /* Something failed? */
8755         if (result != ISC_R_SUCCESS)
8756                 goto destroy;
8757
8758         /* More addresses pending? */
8759         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
8760                 return;
8761
8762         /* We have as many addresses as we can get. */
8763         LOCK_ZONE(notify->zone);
8764         notify_send(notify);
8765         UNLOCK_ZONE(notify->zone);
8766
8767  destroy:
8768         notify_destroy(notify, ISC_FALSE);
8769 }
8770
8771
8772 static isc_result_t
8773 notify_send_queue(dns_notify_t *notify) {
8774         isc_event_t *e;
8775         isc_result_t result;
8776
8777         e = isc_event_allocate(notify->mctx, NULL,
8778                                DNS_EVENT_NOTIFYSENDTOADDR,
8779                                notify_send_toaddr,
8780                                notify, sizeof(isc_event_t));
8781         if (e == NULL)
8782                 return (ISC_R_NOMEMORY);
8783         e->ev_arg = notify;
8784         e->ev_sender = NULL;
8785         result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
8786                                          notify->zone->task, &e);
8787         if (result != ISC_R_SUCCESS)
8788                 isc_event_free(&e);
8789         return (result);
8790 }
8791
8792 static void
8793 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
8794         dns_notify_t *notify;
8795         isc_result_t result;
8796         dns_message_t *message = NULL;
8797         isc_netaddr_t dstip;
8798         dns_tsigkey_t *key = NULL;
8799         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
8800         isc_sockaddr_t src;
8801         int timeout;
8802         isc_boolean_t have_notifysource = ISC_FALSE;
8803
8804         notify = event->ev_arg;
8805         REQUIRE(DNS_NOTIFY_VALID(notify));
8806
8807         UNUSED(task);
8808
8809         LOCK_ZONE(notify->zone);
8810
8811         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
8812                 result = ISC_R_CANCELED;
8813                 goto cleanup;
8814         }
8815
8816         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
8817             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
8818             notify->zone->view->requestmgr == NULL ||
8819             notify->zone->db == NULL) {
8820                 result = ISC_R_CANCELED;
8821                 goto cleanup;
8822         }
8823
8824         /*
8825          * The raw IPv4 address should also exist.  Don't send to the
8826          * mapped form.
8827          */
8828         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
8829             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
8830                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
8831                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
8832                            "notify: ignoring IPv6 mapped IPV4 address: %s",
8833                            addrbuf);
8834                 result = ISC_R_CANCELED;
8835                 goto cleanup;
8836         }
8837
8838         result = notify_createmessage(notify->zone, notify->flags, &message);
8839         if (result != ISC_R_SUCCESS)
8840                 goto cleanup;
8841
8842         isc_netaddr_fromsockaddr(&dstip, &notify->dst);
8843         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
8844         result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
8845         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
8846                 notify_log(notify->zone, ISC_LOG_ERROR, "NOTIFY to %s not "
8847                            "sent. Peer TSIG key lookup failure.", addrbuf);
8848                 goto cleanup_message;
8849         }
8850
8851         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
8852                    addrbuf);
8853         if (notify->zone->view->peers != NULL) {
8854                 dns_peer_t *peer = NULL;
8855                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
8856                                                  &dstip, &peer);
8857                 if (result == ISC_R_SUCCESS) {
8858                         result = dns_peer_getnotifysource(peer, &src);
8859                         if (result == ISC_R_SUCCESS)
8860                                 have_notifysource = ISC_TRUE;
8861                 }
8862         }
8863         switch (isc_sockaddr_pf(&notify->dst)) {
8864         case PF_INET:
8865                 if (!have_notifysource)
8866                         src = notify->zone->notifysrc4;
8867                 break;
8868         case PF_INET6:
8869                 if (!have_notifysource)
8870                         src = notify->zone->notifysrc6;
8871                 break;
8872         default:
8873                 result = ISC_R_NOTIMPLEMENTED;
8874                 goto cleanup_key;
8875         }
8876         timeout = 15;
8877         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
8878                 timeout = 30;
8879         result = dns_request_createvia2(notify->zone->view->requestmgr,
8880                                         message, &src, &notify->dst, 0, key,
8881                                         timeout * 3, timeout,
8882                                         notify->zone->task, notify_done,
8883                                         notify, &notify->request);
8884         if (result == ISC_R_SUCCESS) {
8885                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
8886                         inc_stats(notify->zone,
8887                                   dns_zonestatscounter_notifyoutv4);
8888                 } else {
8889                         inc_stats(notify->zone,
8890                                   dns_zonestatscounter_notifyoutv6);
8891                 }
8892         }
8893
8894  cleanup_key:
8895         if (key != NULL)
8896                 dns_tsigkey_detach(&key);
8897  cleanup_message:
8898         dns_message_destroy(&message);
8899  cleanup:
8900         UNLOCK_ZONE(notify->zone);
8901         if (result != ISC_R_SUCCESS)
8902                 notify_destroy(notify, ISC_FALSE);
8903         isc_event_free(&event);
8904 }
8905
8906 static void
8907 notify_send(dns_notify_t *notify) {
8908         dns_adbaddrinfo_t *ai;
8909         isc_sockaddr_t dst;
8910         isc_result_t result;
8911         dns_notify_t *new = NULL;
8912
8913         /*
8914          * Zone lock held by caller.
8915          */
8916         REQUIRE(DNS_NOTIFY_VALID(notify));
8917         REQUIRE(LOCKED_ZONE(notify->zone));
8918
8919         for (ai = ISC_LIST_HEAD(notify->find->list);
8920              ai != NULL;
8921              ai = ISC_LIST_NEXT(ai, publink)) {
8922                 dst = ai->sockaddr;
8923                 if (notify_isqueued(notify->zone, NULL, &dst))
8924                         continue;
8925                 if (notify_isself(notify->zone, &dst))
8926                         continue;
8927                 new = NULL;
8928                 result = notify_create(notify->mctx,
8929                                        (notify->flags & DNS_NOTIFY_NOSOA),
8930                                        &new);
8931                 if (result != ISC_R_SUCCESS)
8932                         goto cleanup;
8933                 zone_iattach(notify->zone, &new->zone);
8934                 ISC_LIST_APPEND(new->zone->notifies, new, link);
8935                 new->dst = dst;
8936                 result = notify_send_queue(new);
8937                 if (result != ISC_R_SUCCESS)
8938                         goto cleanup;
8939                 new = NULL;
8940         }
8941
8942  cleanup:
8943         if (new != NULL)
8944                 notify_destroy(new, ISC_TRUE);
8945 }
8946
8947 void
8948 dns_zone_notify(dns_zone_t *zone) {
8949         isc_time_t now;
8950
8951         REQUIRE(DNS_ZONE_VALID(zone));
8952
8953         LOCK_ZONE(zone);
8954         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8955
8956         TIME_NOW(&now);
8957         zone_settimer(zone, &now);
8958         UNLOCK_ZONE(zone);
8959 }
8960
8961 static void
8962 zone_notify(dns_zone_t *zone, isc_time_t *now) {
8963         dns_dbnode_t *node = NULL;
8964         dns_db_t *zonedb = NULL;
8965         dns_dbversion_t *version = NULL;
8966         dns_name_t *origin = NULL;
8967         dns_name_t master;
8968         dns_rdata_ns_t ns;
8969         dns_rdata_soa_t soa;
8970         isc_uint32_t serial;
8971         dns_rdata_t rdata = DNS_RDATA_INIT;
8972         dns_rdataset_t nsrdset;
8973         dns_rdataset_t soardset;
8974         isc_result_t result;
8975         dns_notify_t *notify = NULL;
8976         unsigned int i;
8977         isc_sockaddr_t dst;
8978         isc_boolean_t isqueued;
8979         dns_notifytype_t notifytype;
8980         unsigned int flags = 0;
8981         isc_boolean_t loggednotify = ISC_FALSE;
8982
8983         REQUIRE(DNS_ZONE_VALID(zone));
8984
8985         LOCK_ZONE(zone);
8986         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8987         notifytype = zone->notifytype;
8988         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
8989         UNLOCK_ZONE(zone);
8990
8991         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
8992                 return;
8993
8994         if (notifytype == dns_notifytype_no)
8995                 return;
8996
8997         if (notifytype == dns_notifytype_masteronly &&
8998             zone->type != dns_zone_master)
8999                 return;
9000
9001         origin = &zone->origin;
9002
9003         /*
9004          * If the zone is dialup we are done as we don't want to send
9005          * the current soa so as to force a refresh query.
9006          */
9007         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
9008                 flags |= DNS_NOTIFY_NOSOA;
9009
9010         /*
9011          * Get SOA RRset.
9012          */
9013         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9014         if (zone->db != NULL)
9015                 dns_db_attach(zone->db, &zonedb);
9016         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9017         if (zonedb == NULL)
9018                 return;
9019         dns_db_currentversion(zonedb, &version);
9020         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
9021         if (result != ISC_R_SUCCESS)
9022                 goto cleanup1;
9023
9024         dns_rdataset_init(&soardset);
9025         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
9026                                      dns_rdatatype_none, 0, &soardset, NULL);
9027         if (result != ISC_R_SUCCESS)
9028                 goto cleanup2;
9029
9030         /*
9031          * Find serial and master server's name.
9032          */
9033         dns_name_init(&master, NULL);
9034         result = dns_rdataset_first(&soardset);
9035         if (result != ISC_R_SUCCESS)
9036                 goto cleanup3;
9037         dns_rdataset_current(&soardset, &rdata);
9038         result = dns_rdata_tostruct(&rdata, &soa, NULL);
9039         RUNTIME_CHECK(result == ISC_R_SUCCESS);
9040         dns_rdata_reset(&rdata);
9041         result = dns_name_dup(&soa.origin, zone->mctx, &master);
9042         serial = soa.serial;
9043         dns_rdataset_disassociate(&soardset);
9044         if (result != ISC_R_SUCCESS)
9045                 goto cleanup3;
9046
9047         /*
9048          * Enqueue notify requests for 'also-notify' servers.
9049          */
9050         LOCK_ZONE(zone);
9051         for (i = 0; i < zone->notifycnt; i++) {
9052                 dst = zone->notify[i];
9053                 if (notify_isqueued(zone, NULL, &dst))
9054                         continue;
9055                 result = notify_create(zone->mctx, flags, &notify);
9056                 if (result != ISC_R_SUCCESS)
9057                         continue;
9058                 zone_iattach(zone, &notify->zone);
9059                 notify->dst = dst;
9060                 ISC_LIST_APPEND(zone->notifies, notify, link);
9061                 result = notify_send_queue(notify);
9062                 if (result != ISC_R_SUCCESS)
9063                         notify_destroy(notify, ISC_TRUE);
9064                 if (!loggednotify) {
9065                         notify_log(zone, ISC_LOG_INFO,
9066                                    "sending notifies (serial %u)",
9067                                    serial);
9068                         loggednotify = ISC_TRUE;
9069                 }
9070                 notify = NULL;
9071         }
9072         UNLOCK_ZONE(zone);
9073
9074         if (notifytype == dns_notifytype_explicit)
9075                 goto cleanup3;
9076
9077         /*
9078          * Process NS RRset to generate notifies.
9079          */
9080
9081         dns_rdataset_init(&nsrdset);
9082         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
9083                                      dns_rdatatype_none, 0, &nsrdset, NULL);
9084         if (result != ISC_R_SUCCESS)
9085                 goto cleanup3;
9086
9087         result = dns_rdataset_first(&nsrdset);
9088         while (result == ISC_R_SUCCESS) {
9089                 dns_rdataset_current(&nsrdset, &rdata);
9090                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
9091                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9092                 dns_rdata_reset(&rdata);
9093                 /*
9094                  * Don't notify the master server unless explicitly
9095                  * configured to do so.
9096                  */
9097                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
9098                     dns_name_compare(&master, &ns.name) == 0) {
9099                         result = dns_rdataset_next(&nsrdset);
9100                         continue;
9101                 }
9102
9103                 if (!loggednotify) {
9104                         notify_log(zone, ISC_LOG_INFO,
9105                                    "sending notifies (serial %u)",
9106                                    serial);
9107                         loggednotify = ISC_TRUE;
9108                 }
9109
9110                 LOCK_ZONE(zone);
9111                 isqueued = notify_isqueued(zone, &ns.name, NULL);
9112                 UNLOCK_ZONE(zone);
9113                 if (isqueued) {
9114                         result = dns_rdataset_next(&nsrdset);
9115                         continue;
9116                 }
9117                 result = notify_create(zone->mctx, flags, &notify);
9118                 if (result != ISC_R_SUCCESS)
9119                         continue;
9120                 dns_zone_iattach(zone, &notify->zone);
9121                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
9122                 if (result != ISC_R_SUCCESS) {
9123                         LOCK_ZONE(zone);
9124                         notify_destroy(notify, ISC_TRUE);
9125                         UNLOCK_ZONE(zone);
9126                         continue;
9127                 }
9128                 LOCK_ZONE(zone);
9129                 ISC_LIST_APPEND(zone->notifies, notify, link);
9130                 UNLOCK_ZONE(zone);
9131                 notify_find_address(notify);
9132                 notify = NULL;
9133                 result = dns_rdataset_next(&nsrdset);
9134         }
9135         dns_rdataset_disassociate(&nsrdset);
9136
9137  cleanup3:
9138         if (dns_name_dynamic(&master))
9139                 dns_name_free(&master, zone->mctx);
9140  cleanup2:
9141         dns_db_detachnode(zonedb, &node);
9142  cleanup1:
9143         dns_db_closeversion(zonedb, &version, ISC_FALSE);
9144         dns_db_detach(&zonedb);
9145 }
9146
9147 /***
9148  *** Private
9149  ***/
9150
9151 static inline isc_result_t
9152 save_nsrrset(dns_message_t *message, dns_name_t *name,
9153              dns_db_t *db, dns_dbversion_t *version)
9154 {
9155         dns_rdataset_t *nsrdataset = NULL;
9156         dns_rdataset_t *rdataset = NULL;
9157         dns_dbnode_t *node = NULL;
9158         dns_rdata_ns_t ns;
9159         isc_result_t result;
9160         dns_rdata_t rdata = DNS_RDATA_INIT;
9161
9162         /*
9163          * Extract NS RRset from message.
9164          */
9165         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
9166                                       dns_rdatatype_ns, dns_rdatatype_none,
9167                                       NULL, &nsrdataset);
9168         if (result != ISC_R_SUCCESS)
9169                 goto fail;
9170
9171         /*
9172          * Add NS rdataset.
9173          */
9174         result = dns_db_findnode(db, name, ISC_TRUE, &node);
9175         if (result != ISC_R_SUCCESS)
9176                 goto fail;
9177         result = dns_db_addrdataset(db, node, version, 0,
9178                                     nsrdataset, 0, NULL);
9179         dns_db_detachnode(db, &node);
9180         if (result != ISC_R_SUCCESS)
9181                 goto fail;
9182         /*
9183          * Add glue rdatasets.
9184          */
9185         for (result = dns_rdataset_first(nsrdataset);
9186              result == ISC_R_SUCCESS;
9187              result = dns_rdataset_next(nsrdataset)) {
9188                 dns_rdataset_current(nsrdataset, &rdata);
9189                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
9190                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9191                 dns_rdata_reset(&rdata);
9192                 if (!dns_name_issubdomain(&ns.name, name))
9193                         continue;
9194                 rdataset = NULL;
9195                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9196                                               &ns.name, dns_rdatatype_aaaa,
9197                                               dns_rdatatype_none, NULL,
9198                                               &rdataset);
9199                 if (result == ISC_R_SUCCESS) {
9200                         result = dns_db_findnode(db, &ns.name,
9201                                                  ISC_TRUE, &node);
9202                         if (result != ISC_R_SUCCESS)
9203                                 goto fail;
9204                         result = dns_db_addrdataset(db, node, version, 0,
9205                                                     rdataset, 0, NULL);
9206                         dns_db_detachnode(db, &node);
9207                         if (result != ISC_R_SUCCESS)
9208                                 goto fail;
9209                 }
9210                 rdataset = NULL;
9211                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9212                                               &ns.name, dns_rdatatype_a,
9213                                               dns_rdatatype_none, NULL,
9214                                               &rdataset);
9215                 if (result == ISC_R_SUCCESS) {
9216                         result = dns_db_findnode(db, &ns.name,
9217                                                  ISC_TRUE, &node);
9218                         if (result != ISC_R_SUCCESS)
9219                                 goto fail;
9220                         result = dns_db_addrdataset(db, node, version, 0,
9221                                                     rdataset, 0, NULL);
9222                         dns_db_detachnode(db, &node);
9223                         if (result != ISC_R_SUCCESS)
9224                                 goto fail;
9225                 }
9226         }
9227         if (result != ISC_R_NOMORE)
9228                 goto fail;
9229
9230         return (ISC_R_SUCCESS);
9231
9232 fail:
9233         return (result);
9234 }
9235
9236 static void
9237 stub_callback(isc_task_t *task, isc_event_t *event) {
9238         const char me[] = "stub_callback";
9239         dns_requestevent_t *revent = (dns_requestevent_t *)event;
9240         dns_stub_t *stub = NULL;
9241         dns_message_t *msg = NULL;
9242         dns_zone_t *zone = NULL;
9243         char master[ISC_SOCKADDR_FORMATSIZE];
9244         char source[ISC_SOCKADDR_FORMATSIZE];
9245         isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
9246         isc_result_t result;
9247         isc_time_t now;
9248         isc_boolean_t exiting = ISC_FALSE;
9249         isc_interval_t i;
9250         unsigned int j;
9251
9252         stub = revent->ev_arg;
9253         INSIST(DNS_STUB_VALID(stub));
9254
9255         UNUSED(task);
9256
9257         zone = stub->zone;
9258
9259         ENTER;
9260
9261         TIME_NOW(&now);
9262
9263         LOCK_ZONE(zone);
9264
9265         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9266                 zone_debuglog(zone, me, 1, "exiting");
9267                 exiting = ISC_TRUE;
9268                 goto next_master;
9269         }
9270
9271         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9272         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9273
9274         if (revent->result != ISC_R_SUCCESS) {
9275                 if (revent->result == ISC_R_TIMEDOUT &&
9276                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9277                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9278                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9279                                      "refreshing stub: timeout retrying "
9280                                      " without EDNS master %s (source %s)",
9281                                      master, source);
9282                         goto same_master;
9283                 }
9284                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
9285                                            &zone->sourceaddr, &now);
9286                 dns_zone_log(zone, ISC_LOG_INFO,
9287                              "could not refresh stub from master %s"
9288                              " (source %s): %s", master, source,
9289                              dns_result_totext(revent->result));
9290                 goto next_master;
9291         }
9292
9293         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9294         if (result != ISC_R_SUCCESS)
9295                 goto next_master;
9296
9297         result = dns_request_getresponse(revent->request, msg, 0);
9298         if (result != ISC_R_SUCCESS)
9299                 goto next_master;
9300
9301         /*
9302          * Unexpected rcode.
9303          */
9304         if (msg->rcode != dns_rcode_noerror) {
9305                 char rcode[128];
9306                 isc_buffer_t rb;
9307
9308                 isc_buffer_init(&rb, rcode, sizeof(rcode));
9309                 (void)dns_rcode_totext(msg->rcode, &rb);
9310
9311                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9312                     (msg->rcode == dns_rcode_servfail ||
9313                      msg->rcode == dns_rcode_notimp ||
9314                      msg->rcode == dns_rcode_formerr)) {
9315                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9316                                      "refreshing stub: rcode (%.*s) retrying "
9317                                      "without EDNS master %s (source %s)",
9318                                      (int)rb.used, rcode, master, source);
9319                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9320                         goto same_master;
9321                 }
9322
9323                 dns_zone_log(zone, ISC_LOG_INFO,
9324                              "refreshing stub: "
9325                              "unexpected rcode (%.*s) from %s (source %s)",
9326                              (int)rb.used, rcode, master, source);
9327                 goto next_master;
9328         }
9329
9330         /*
9331          * We need complete messages.
9332          */
9333         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9334                 if (dns_request_usedtcp(revent->request)) {
9335                         dns_zone_log(zone, ISC_LOG_INFO,
9336                                      "refreshing stub: truncated TCP "
9337                                      "response from master %s (source %s)",
9338                                      master, source);
9339                         goto next_master;
9340                 }
9341                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9342                 goto same_master;
9343         }
9344
9345         /*
9346          * If non-auth log and next master.
9347          */
9348         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9349                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
9350                              "non-authoritative answer from "
9351                              "master %s (source %s)", master, source);
9352                 goto next_master;
9353         }
9354
9355         /*
9356          * Sanity checks.
9357          */
9358         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9359         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
9360
9361         if (cnamecnt != 0) {
9362                 dns_zone_log(zone, ISC_LOG_INFO,
9363                              "refreshing stub: unexpected CNAME response "
9364                              "from master %s (source %s)", master, source);
9365                 goto next_master;
9366         }
9367
9368         if (nscnt == 0) {
9369                 dns_zone_log(zone, ISC_LOG_INFO,
9370                              "refreshing stub: no NS records in response "
9371                              "from master %s (source %s)", master, source);
9372                 goto next_master;
9373         }
9374
9375         /*
9376          * Save answer.
9377          */
9378         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
9379         if (result != ISC_R_SUCCESS) {
9380                 dns_zone_log(zone, ISC_LOG_INFO,
9381                              "refreshing stub: unable to save NS records "
9382                              "from master %s (source %s)", master, source);
9383                 goto next_master;
9384         }
9385
9386         /*
9387          * Tidy up.
9388          */
9389         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
9390         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9391         if (zone->db == NULL)
9392                 zone_attachdb(zone, stub->db);
9393         result = zone_get_from_db(zone, zone->db, NULL, NULL, NULL, &refresh,
9394                                   &retry, &expire, NULL, NULL);
9395         if (result == ISC_R_SUCCESS) {
9396                 zone->refresh = RANGE(refresh, zone->minrefresh,
9397                                       zone->maxrefresh);
9398                 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
9399                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
9400                                      DNS_MAX_EXPIRE);
9401                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9402         }
9403         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9404         dns_db_detach(&stub->db);
9405
9406         dns_message_destroy(&msg);
9407         isc_event_free(&event);
9408         dns_request_destroy(&zone->request);
9409
9410         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9411         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
9412         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9413         isc_interval_set(&i, zone->expire, 0);
9414         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9415
9416         if (zone->masterfile != NULL)
9417                 zone_needdump(zone, 0);
9418
9419         zone_settimer(zone, &now);
9420         goto free_stub;
9421
9422  next_master:
9423         if (stub->version != NULL)
9424                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
9425         if (stub->db != NULL)
9426                 dns_db_detach(&stub->db);
9427         if (msg != NULL)
9428                 dns_message_destroy(&msg);
9429         isc_event_free(&event);
9430         dns_request_destroy(&zone->request);
9431         /*
9432          * Skip to next failed / untried master.
9433          */
9434         do {
9435                 zone->curmaster++;
9436         } while (zone->curmaster < zone->masterscnt &&
9437                  zone->mastersok[zone->curmaster]);
9438         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9439         if (exiting || zone->curmaster >= zone->masterscnt) {
9440                 isc_boolean_t done = ISC_TRUE;
9441                 if (!exiting &&
9442                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9443                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9444                         /*
9445                          * Did we get a good answer from all the masters?
9446                          */
9447                         for (j = 0; j < zone->masterscnt; j++)
9448                                 if (zone->mastersok[j] == ISC_FALSE) {
9449                                         done = ISC_FALSE;
9450                                         break;
9451                                 }
9452                 } else
9453                         done = ISC_TRUE;
9454                 if (!done) {
9455                         zone->curmaster = 0;
9456                         /*
9457                          * Find the next failed master.
9458                          */
9459                         while (zone->curmaster < zone->masterscnt &&
9460                                zone->mastersok[zone->curmaster])
9461                                 zone->curmaster++;
9462                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9463                 } else {
9464                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9465
9466                         zone_settimer(zone, &now);
9467                         goto free_stub;
9468                 }
9469         }
9470         queue_soa_query(zone);
9471         goto free_stub;
9472
9473  same_master:
9474         if (msg != NULL)
9475                 dns_message_destroy(&msg);
9476         isc_event_free(&event);
9477         dns_request_destroy(&zone->request);
9478         ns_query(zone, NULL, stub);
9479         UNLOCK_ZONE(zone);
9480         goto done;
9481
9482  free_stub:
9483         UNLOCK_ZONE(zone);
9484         stub->magic = 0;
9485         dns_zone_idetach(&stub->zone);
9486         INSIST(stub->db == NULL);
9487         INSIST(stub->version == NULL);
9488         isc_mem_put(stub->mctx, stub, sizeof(*stub));
9489
9490  done:
9491         INSIST(event == NULL);
9492         return;
9493 }
9494
9495 /*
9496  * An SOA query has finished (successfully or not).
9497  */
9498 static void
9499 refresh_callback(isc_task_t *task, isc_event_t *event) {
9500         const char me[] = "refresh_callback";
9501         dns_requestevent_t *revent = (dns_requestevent_t *)event;
9502         dns_zone_t *zone;
9503         dns_message_t *msg = NULL;
9504         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
9505         isc_time_t now;
9506         char master[ISC_SOCKADDR_FORMATSIZE];
9507         char source[ISC_SOCKADDR_FORMATSIZE];
9508         dns_rdataset_t *rdataset = NULL;
9509         dns_rdata_t rdata = DNS_RDATA_INIT;
9510         dns_rdata_soa_t soa;
9511         isc_result_t result;
9512         isc_uint32_t serial, oldserial = 0;
9513         unsigned int j;
9514         isc_boolean_t do_queue_xfrin = ISC_FALSE;
9515
9516         zone = revent->ev_arg;
9517         INSIST(DNS_ZONE_VALID(zone));
9518
9519         UNUSED(task);
9520
9521         ENTER;
9522
9523         TIME_NOW(&now);
9524
9525         LOCK_ZONE(zone);
9526
9527         /*
9528          * if timeout log and next master;
9529          */
9530
9531         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9532         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9533
9534         if (revent->result != ISC_R_SUCCESS) {
9535                 if (revent->result == ISC_R_TIMEDOUT &&
9536                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9537                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9538                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9539                                      "refresh: timeout retrying without EDNS "
9540                                      "master %s (source %s)", master, source);
9541                         goto same_master;
9542                 }
9543                 if (revent->result == ISC_R_TIMEDOUT &&
9544                     !dns_request_usedtcp(revent->request)) {
9545                         dns_zone_log(zone, ISC_LOG_INFO,
9546                                      "refresh: retry limit for "
9547                                      "master %s exceeded (source %s)",
9548                                      master, source);
9549                         /* Try with slave with TCP. */
9550                         if (zone->type == dns_zone_slave &&
9551                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
9552                                 if (!dns_zonemgr_unreachable(zone->zmgr,
9553                                                              &zone->masteraddr,
9554                                                              &zone->sourceaddr,
9555                                                              &now))
9556                                 {
9557                                         DNS_ZONE_SETFLAG(zone,
9558                                                      DNS_ZONEFLG_SOABEFOREAXFR);
9559                                         goto tcp_transfer;
9560                                 }
9561                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
9562                                              "refresh: skipped tcp fallback "
9563                                              "as master %s (source %s) is "
9564                                              "unreachable (cached)",
9565                                               master, source);
9566                         }
9567                 } else
9568                         dns_zone_log(zone, ISC_LOG_INFO,
9569                                      "refresh: failure trying master "
9570                                      "%s (source %s): %s", master, source,
9571                                      dns_result_totext(revent->result));
9572                 goto next_master;
9573         }
9574
9575         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9576         if (result != ISC_R_SUCCESS)
9577                 goto next_master;
9578         result = dns_request_getresponse(revent->request, msg, 0);
9579         if (result != ISC_R_SUCCESS) {
9580                 dns_zone_log(zone, ISC_LOG_INFO,
9581                              "refresh: failure trying master "
9582                              "%s (source %s): %s", master, source,
9583                              dns_result_totext(result));
9584                 goto next_master;
9585         }
9586
9587         /*
9588          * Unexpected rcode.
9589          */
9590         if (msg->rcode != dns_rcode_noerror) {
9591                 char rcode[128];
9592                 isc_buffer_t rb;
9593
9594                 isc_buffer_init(&rb, rcode, sizeof(rcode));
9595                 (void)dns_rcode_totext(msg->rcode, &rb);
9596
9597                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9598                     (msg->rcode == dns_rcode_servfail ||
9599                      msg->rcode == dns_rcode_notimp ||
9600                      msg->rcode == dns_rcode_formerr)) {
9601                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9602                                      "refresh: rcode (%.*s) retrying without "
9603                                      "EDNS master %s (source %s)",
9604                                      (int)rb.used, rcode, master, source);
9605                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9606                         goto same_master;
9607                 }
9608                 dns_zone_log(zone, ISC_LOG_INFO,
9609                              "refresh: unexpected rcode (%.*s) from "
9610                              "master %s (source %s)", (int)rb.used, rcode,
9611                              master, source);
9612                 /*
9613                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
9614                  */
9615                 if (msg->rcode == dns_rcode_refused &&
9616                     zone->type == dns_zone_slave)
9617                         goto tcp_transfer;
9618                 goto next_master;
9619         }
9620
9621         /*
9622          * If truncated punt to zone transfer which will query again.
9623          */
9624         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9625                 if (zone->type == dns_zone_slave) {
9626                         dns_zone_log(zone, ISC_LOG_INFO,
9627                                      "refresh: truncated UDP answer, "
9628                                      "initiating TCP zone xfer "
9629                                      "for master %s (source %s)",
9630                                      master, source);
9631                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
9632                         goto tcp_transfer;
9633                 } else {
9634                         INSIST(zone->type == dns_zone_stub);
9635                         if (dns_request_usedtcp(revent->request)) {
9636                                 dns_zone_log(zone, ISC_LOG_INFO,
9637                                              "refresh: truncated TCP response "
9638                                              "from master %s (source %s)",
9639                                              master, source);
9640                                 goto next_master;
9641                         }
9642                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9643                         goto same_master;
9644                 }
9645         }
9646
9647         /*
9648          * if non-auth log and next master;
9649          */
9650         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9651                 dns_zone_log(zone, ISC_LOG_INFO,
9652                              "refresh: non-authoritative answer from "
9653                              "master %s (source %s)", master, source);
9654                 goto next_master;
9655         }
9656
9657         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9658         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
9659         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
9660         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
9661                                  dns_rdatatype_soa);
9662
9663         /*
9664          * There should not be a CNAME record at top of zone.
9665          */
9666         if (cnamecnt != 0) {
9667                 dns_zone_log(zone, ISC_LOG_INFO,
9668                              "refresh: CNAME at top of zone "
9669                              "in master %s (source %s)", master, source);
9670                 goto next_master;
9671         }
9672
9673         /*
9674          * if referral log and next master;
9675          */
9676         if (soacnt == 0 && soacount == 0 && nscount != 0) {
9677                 dns_zone_log(zone, ISC_LOG_INFO,
9678                              "refresh: referral response "
9679                              "from master %s (source %s)", master, source);
9680                 goto next_master;
9681         }
9682
9683         /*
9684          * if nodata log and next master;
9685          */
9686         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
9687                 dns_zone_log(zone, ISC_LOG_INFO,
9688                              "refresh: NODATA response "
9689                              "from master %s (source %s)", master, source);
9690                 goto next_master;
9691         }
9692
9693         /*
9694          * Only one soa at top of zone.
9695          */
9696         if (soacnt != 1) {
9697                 dns_zone_log(zone, ISC_LOG_INFO,
9698                              "refresh: answer SOA count (%d) != 1 "
9699                              "from master %s (source %s)",
9700                              soacnt, master, source);
9701                 goto next_master;
9702         }
9703
9704         /*
9705          * Extract serial
9706          */
9707         rdataset = NULL;
9708         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
9709                                       dns_rdatatype_soa, dns_rdatatype_none,
9710                                       NULL, &rdataset);
9711         if (result != ISC_R_SUCCESS) {
9712                 dns_zone_log(zone, ISC_LOG_INFO,
9713                              "refresh: unable to get SOA record "
9714                              "from master %s (source %s)", master, source);
9715                 goto next_master;
9716         }
9717
9718         result = dns_rdataset_first(rdataset);
9719         if (result != ISC_R_SUCCESS) {
9720                 dns_zone_log(zone, ISC_LOG_INFO,
9721                              "refresh: dns_rdataset_first() failed");
9722                 goto next_master;
9723         }
9724
9725         dns_rdataset_current(rdataset, &rdata);
9726         result = dns_rdata_tostruct(&rdata, &soa, NULL);
9727         RUNTIME_CHECK(result == ISC_R_SUCCESS);
9728
9729         serial = soa.serial;
9730         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9731                 result = zone_get_from_db(zone, zone->db, NULL, NULL,
9732                                           &oldserial, NULL, NULL, NULL, NULL,
9733                                           NULL);
9734                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9735                 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
9736                               serial, oldserial);
9737         } else
9738                 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
9739                               serial);
9740
9741         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
9742             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
9743             isc_serial_gt(serial, oldserial)) {
9744                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
9745                                             &zone->sourceaddr, &now))
9746                 {
9747                         dns_zone_log(zone, ISC_LOG_INFO,
9748                                      "refresh: skipping %s as master %s "
9749                                      "(source %s) is unreachable (cached)",
9750                                      zone->type == dns_zone_slave ?
9751                                      "zone transfer" : "NS query",
9752                                      master, source);
9753                         goto next_master;
9754                 }
9755  tcp_transfer:
9756                 isc_event_free(&event);
9757                 dns_request_destroy(&zone->request);
9758                 if (zone->type == dns_zone_slave) {
9759                         do_queue_xfrin = ISC_TRUE;
9760                 } else {
9761                         INSIST(zone->type == dns_zone_stub);
9762                         ns_query(zone, rdataset, NULL);
9763                 }
9764                 if (msg != NULL)
9765                         dns_message_destroy(&msg);
9766         } else if (isc_serial_eq(soa.serial, oldserial)) {
9767                 if (zone->masterfile != NULL) {
9768                         result = ISC_R_FAILURE;
9769                         if (zone->journal != NULL)
9770                                 result = isc_file_settime(zone->journal, &now);
9771                         if (result == ISC_R_SUCCESS &&
9772                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9773                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9774                                 result = isc_file_settime(zone->masterfile,
9775                                                           &now);
9776                         } else if (result != ISC_R_SUCCESS)
9777                                 result = isc_file_settime(zone->masterfile,
9778                                                           &now);
9779                         /* Someone removed the file from underneath us! */
9780                         if (result == ISC_R_FILENOTFOUND) {
9781                                 zone_needdump(zone, DNS_DUMP_DELAY);
9782                         } else if (result != ISC_R_SUCCESS)
9783                                 dns_zone_log(zone, ISC_LOG_ERROR,
9784                                              "refresh: could not set file "
9785                                              "modification time of '%s': %s",
9786                                              zone->masterfile,
9787                                              dns_result_totext(result));
9788                 }
9789                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9790                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9791                 zone->mastersok[zone->curmaster] = ISC_TRUE;
9792                 goto next_master;
9793         } else {
9794                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
9795                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
9796                                      "received from master %s < ours (%u)",
9797                                      soa.serial, master, oldserial);
9798                 else
9799                         zone_debuglog(zone, me, 1, "ahead");
9800                 zone->mastersok[zone->curmaster] = ISC_TRUE;
9801                 goto next_master;
9802         }
9803         if (msg != NULL)
9804                 dns_message_destroy(&msg);
9805         goto detach;
9806
9807  next_master:
9808         if (msg != NULL)
9809                 dns_message_destroy(&msg);
9810         isc_event_free(&event);
9811         dns_request_destroy(&zone->request);
9812         /*
9813          * Skip to next failed / untried master.
9814          */
9815         do {
9816                 zone->curmaster++;
9817         } while (zone->curmaster < zone->masterscnt &&
9818                  zone->mastersok[zone->curmaster]);
9819         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9820         if (zone->curmaster >= zone->masterscnt) {
9821                 isc_boolean_t done = ISC_TRUE;
9822                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9823                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9824                         /*
9825                          * Did we get a good answer from all the masters?
9826                          */
9827                         for (j = 0; j < zone->masterscnt; j++)
9828                                 if (zone->mastersok[j] == ISC_FALSE) {
9829                                         done = ISC_FALSE;
9830                                         break;
9831                                 }
9832                 } else
9833                         done = ISC_TRUE;
9834                 if (!done) {
9835                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9836                         zone->curmaster = 0;
9837                         /*
9838                          * Find the next failed master.
9839                          */
9840                         while (zone->curmaster < zone->masterscnt &&
9841                                zone->mastersok[zone->curmaster])
9842                                 zone->curmaster++;
9843                         goto requeue;
9844                 }
9845                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9846                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
9847                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
9848                         zone->refreshtime = now;
9849                 }
9850                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9851                 zone_settimer(zone, &now);
9852                 goto detach;
9853         }
9854
9855  requeue:
9856         queue_soa_query(zone);
9857         goto detach;
9858
9859  same_master:
9860         if (msg != NULL)
9861                 dns_message_destroy(&msg);
9862         isc_event_free(&event);
9863         dns_request_destroy(&zone->request);
9864         queue_soa_query(zone);
9865
9866  detach:
9867         UNLOCK_ZONE(zone);
9868         if (do_queue_xfrin)
9869                 queue_xfrin(zone);
9870         dns_zone_idetach(&zone);
9871         return;
9872 }
9873
9874 static void
9875 queue_soa_query(dns_zone_t *zone) {
9876         const char me[] = "queue_soa_query";
9877         isc_event_t *e;
9878         dns_zone_t *dummy = NULL;
9879         isc_result_t result;
9880
9881         ENTER;
9882         /*
9883          * Locked by caller
9884          */
9885         REQUIRE(LOCKED_ZONE(zone));
9886
9887         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9888                 cancel_refresh(zone);
9889                 return;
9890         }
9891
9892         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
9893                                soa_query, zone, sizeof(isc_event_t));
9894         if (e == NULL) {
9895                 cancel_refresh(zone);
9896                 return;
9897         }
9898
9899         /*
9900          * Attach so that we won't clean up
9901          * until the event is delivered.
9902          */
9903         zone_iattach(zone, &dummy);
9904
9905         e->ev_arg = zone;
9906         e->ev_sender = NULL;
9907         result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
9908         if (result != ISC_R_SUCCESS) {
9909                 zone_idetach(&dummy);
9910                 isc_event_free(&e);
9911                 cancel_refresh(zone);
9912         }
9913 }
9914
9915 static inline isc_result_t
9916 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
9917              dns_message_t **messagep)
9918 {
9919         dns_message_t *message = NULL;
9920         dns_name_t *qname = NULL;
9921         dns_rdataset_t *qrdataset = NULL;
9922         isc_result_t result;
9923
9924         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
9925                                     &message);
9926         if (result != ISC_R_SUCCESS)
9927                 goto cleanup;
9928
9929         message->opcode = dns_opcode_query;
9930         message->rdclass = zone->rdclass;
9931
9932         result = dns_message_gettempname(message, &qname);
9933         if (result != ISC_R_SUCCESS)
9934                 goto cleanup;
9935
9936         result = dns_message_gettemprdataset(message, &qrdataset);
9937         if (result != ISC_R_SUCCESS)
9938                 goto cleanup;
9939
9940         /*
9941          * Make question.
9942          */
9943         dns_name_init(qname, NULL);
9944         dns_name_clone(&zone->origin, qname);
9945         dns_rdataset_init(qrdataset);
9946         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
9947         ISC_LIST_APPEND(qname->list, qrdataset, link);
9948         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
9949
9950         *messagep = message;
9951         return (ISC_R_SUCCESS);
9952
9953  cleanup:
9954         if (qname != NULL)
9955                 dns_message_puttempname(message, &qname);
9956         if (qrdataset != NULL)
9957                 dns_message_puttemprdataset(message, &qrdataset);
9958         if (message != NULL)
9959                 dns_message_destroy(&message);
9960         return (result);
9961 }
9962
9963 static isc_result_t
9964 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
9965         dns_rdataset_t *rdataset = NULL;
9966         dns_rdatalist_t *rdatalist = NULL;
9967         dns_rdata_t *rdata = NULL;
9968         isc_result_t result;
9969
9970         result = dns_message_gettemprdatalist(message, &rdatalist);
9971         if (result != ISC_R_SUCCESS)
9972                 goto cleanup;
9973         result = dns_message_gettemprdata(message, &rdata);
9974         if (result != ISC_R_SUCCESS)
9975                 goto cleanup;
9976         result = dns_message_gettemprdataset(message, &rdataset);
9977         if (result != ISC_R_SUCCESS)
9978                 goto cleanup;
9979         dns_rdataset_init(rdataset);
9980
9981         rdatalist->type = dns_rdatatype_opt;
9982         rdatalist->covers = 0;
9983
9984         /*
9985          * Set Maximum UDP buffer size.
9986          */
9987         rdatalist->rdclass = udpsize;
9988
9989         /*
9990          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
9991          */
9992         rdatalist->ttl = 0;
9993
9994         /* Set EDNS options if applicable */
9995         if (reqnsid) {
9996                 unsigned char data[4];
9997                 isc_buffer_t buf;
9998
9999                 isc_buffer_init(&buf, data, sizeof(data));
10000                 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
10001                 isc_buffer_putuint16(&buf, 0);
10002                 rdata->data = data;
10003                 rdata->length = sizeof(data);
10004         } else {
10005                 rdata->data = NULL;
10006                 rdata->length = 0;
10007         }
10008
10009         rdata->rdclass = rdatalist->rdclass;
10010         rdata->type = rdatalist->type;
10011         rdata->flags = 0;
10012
10013         ISC_LIST_INIT(rdatalist->rdata);
10014         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
10015         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
10016                       == ISC_R_SUCCESS);
10017
10018         return (dns_message_setopt(message, rdataset));
10019
10020  cleanup:
10021         if (rdatalist != NULL)
10022                 dns_message_puttemprdatalist(message, &rdatalist);
10023         if (rdataset != NULL)
10024                 dns_message_puttemprdataset(message, &rdataset);
10025         if (rdata != NULL)
10026                 dns_message_puttemprdata(message, &rdata);
10027
10028         return (result);
10029 }
10030
10031 static void
10032 soa_query(isc_task_t *task, isc_event_t *event) {
10033         const char me[] = "soa_query";
10034         isc_result_t result = ISC_R_FAILURE;
10035         dns_message_t *message = NULL;
10036         dns_zone_t *zone = event->ev_arg;
10037         dns_zone_t *dummy = NULL;
10038         isc_netaddr_t masterip;
10039         dns_tsigkey_t *key = NULL;
10040         isc_uint32_t options;
10041         isc_boolean_t cancel = ISC_TRUE;
10042         int timeout;
10043         isc_boolean_t have_xfrsource, reqnsid;
10044         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10045
10046         REQUIRE(DNS_ZONE_VALID(zone));
10047
10048         UNUSED(task);
10049
10050         ENTER;
10051
10052         LOCK_ZONE(zone);
10053         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
10054             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
10055             zone->view->requestmgr == NULL) {
10056                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10057                         cancel = ISC_FALSE;
10058                 goto cleanup;
10059         }
10060
10061         /*
10062          * XXX Optimisation: Create message when zone is setup and reuse.
10063          */
10064         result = create_query(zone, dns_rdatatype_soa, &message);
10065         if (result != ISC_R_SUCCESS)
10066                 goto cleanup;
10067
10068  again:
10069         INSIST(zone->masterscnt > 0);
10070         INSIST(zone->curmaster < zone->masterscnt);
10071
10072         zone->masteraddr = zone->masters[zone->curmaster];
10073
10074         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10075         /*
10076          * First, look for a tsig key in the master statement, then
10077          * try for a server key.
10078          */
10079         if ((zone->masterkeynames != NULL) &&
10080             (zone->masterkeynames[zone->curmaster] != NULL)) {
10081                 dns_view_t *view = dns_zone_getview(zone);
10082                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10083                 result = dns_view_gettsig(view, keyname, &key);
10084                 if (result != ISC_R_SUCCESS) {
10085                         char namebuf[DNS_NAME_FORMATSIZE];
10086                         dns_name_format(keyname, namebuf, sizeof(namebuf));
10087                         dns_zone_log(zone, ISC_LOG_ERROR,
10088                                      "unable to find key: %s", namebuf);
10089                         goto skip_master;
10090                 }
10091         }
10092         if (key == NULL) {
10093                 result = dns_view_getpeertsig(zone->view, &masterip, &key);
10094                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
10095                         char addrbuf[ISC_NETADDR_FORMATSIZE];
10096                         isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
10097                         dns_zone_log(zone, ISC_LOG_ERROR,
10098                                      "unable to find TSIG key for %s", addrbuf);
10099                         goto skip_master;
10100                 }
10101         }
10102
10103         have_xfrsource = ISC_FALSE;
10104         reqnsid = zone->view->requestnsid;
10105         if (zone->view->peers != NULL) {
10106                 dns_peer_t *peer = NULL;
10107                 isc_boolean_t edns;
10108                 result = dns_peerlist_peerbyaddr(zone->view->peers,
10109                                                  &masterip, &peer);
10110                 if (result == ISC_R_SUCCESS) {
10111                         result = dns_peer_getsupportedns(peer, &edns);
10112                         if (result == ISC_R_SUCCESS && !edns)
10113                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10114                         result = dns_peer_gettransfersource(peer,
10115                                                             &zone->sourceaddr);
10116                         if (result == ISC_R_SUCCESS)
10117                                 have_xfrsource = ISC_TRUE;
10118                         if (zone->view->resolver != NULL)
10119                                 udpsize =
10120                                   dns_resolver_getudpsize(zone->view->resolver);
10121                         (void)dns_peer_getudpsize(peer, &udpsize);
10122                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
10123                 }
10124         }
10125
10126         switch (isc_sockaddr_pf(&zone->masteraddr)) {
10127         case PF_INET:
10128                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10129                         if (isc_sockaddr_equal(&zone->altxfrsource4,
10130                                                &zone->xfrsource4))
10131                                 goto skip_master;
10132                         zone->sourceaddr = zone->altxfrsource4;
10133                 } else if (!have_xfrsource)
10134                         zone->sourceaddr = zone->xfrsource4;
10135                 break;
10136         case PF_INET6:
10137                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10138                         if (isc_sockaddr_equal(&zone->altxfrsource6,
10139                                                &zone->xfrsource6))
10140                                 goto skip_master;
10141                         zone->sourceaddr = zone->altxfrsource6;
10142                 } else if (!have_xfrsource)
10143                         zone->sourceaddr = zone->xfrsource6;
10144                 break;
10145         default:
10146                 result = ISC_R_NOTIMPLEMENTED;
10147                 goto cleanup;
10148         }
10149
10150         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
10151                   DNS_REQUESTOPT_TCP : 0;
10152
10153         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10154                 result = add_opt(message, udpsize, reqnsid);
10155                 if (result != ISC_R_SUCCESS)
10156                         zone_debuglog(zone, me, 1,
10157                                       "unable to add opt record: %s",
10158                                       dns_result_totext(result));
10159         }
10160
10161         zone_iattach(zone, &dummy);
10162         timeout = 15;
10163         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10164                 timeout = 30;
10165         result = dns_request_createvia2(zone->view->requestmgr, message,
10166                                         &zone->sourceaddr, &zone->masteraddr,
10167                                         options, key, timeout * 3, timeout,
10168                                         zone->task, refresh_callback, zone,
10169                                         &zone->request);
10170         if (result != ISC_R_SUCCESS) {
10171                 zone_idetach(&dummy);
10172                 zone_debuglog(zone, me, 1,
10173                               "dns_request_createvia2() failed: %s",
10174                               dns_result_totext(result));
10175                 goto cleanup;
10176         } else {
10177                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
10178                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
10179                 else
10180                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
10181         }
10182         cancel = ISC_FALSE;
10183
10184  cleanup:
10185         if (key != NULL)
10186                 dns_tsigkey_detach(&key);
10187         if (result != ISC_R_SUCCESS)
10188                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10189         if (message != NULL)
10190                 dns_message_destroy(&message);
10191         if (cancel)
10192                 cancel_refresh(zone);
10193         isc_event_free(&event);
10194         UNLOCK_ZONE(zone);
10195         dns_zone_idetach(&zone);
10196         return;
10197
10198  skip_master:
10199         if (key != NULL)
10200                 dns_tsigkey_detach(&key);
10201         /*
10202          * Skip to next failed / untried master.
10203          */
10204         do {
10205                 zone->curmaster++;
10206         } while (zone->curmaster < zone->masterscnt &&
10207                  zone->mastersok[zone->curmaster]);
10208         if (zone->curmaster < zone->masterscnt)
10209                 goto again;
10210         zone->curmaster = 0;
10211         goto cleanup;
10212 }
10213
10214 static void
10215 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
10216         const char me[] = "ns_query";
10217         isc_result_t result;
10218         dns_message_t *message = NULL;
10219         isc_netaddr_t masterip;
10220         dns_tsigkey_t *key = NULL;
10221         dns_dbnode_t *node = NULL;
10222         int timeout;
10223         isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
10224         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10225
10226         REQUIRE(DNS_ZONE_VALID(zone));
10227         REQUIRE(LOCKED_ZONE(zone));
10228         REQUIRE((soardataset != NULL && stub == NULL) ||
10229                 (soardataset == NULL && stub != NULL));
10230         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
10231
10232         ENTER;
10233
10234         if (stub == NULL) {
10235                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
10236                 if (stub == NULL)
10237                         goto cleanup;
10238                 stub->magic = STUB_MAGIC;
10239                 stub->mctx = zone->mctx;
10240                 stub->zone = NULL;
10241                 stub->db = NULL;
10242                 stub->version = NULL;
10243
10244                 /*
10245                  * Attach so that the zone won't disappear from under us.
10246                  */
10247                 zone_iattach(zone, &stub->zone);
10248
10249                 /*
10250                  * If a db exists we will update it, otherwise we create a
10251                  * new one and attach it to the zone once we have the NS
10252                  * RRset and glue.
10253                  */
10254                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10255                 if (zone->db != NULL) {
10256                         dns_db_attach(zone->db, &stub->db);
10257                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10258                 } else {
10259                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10260
10261                         INSIST(zone->db_argc >= 1);
10262                         result = dns_db_create(zone->mctx, zone->db_argv[0],
10263                                                &zone->origin, dns_dbtype_stub,
10264                                                zone->rdclass,
10265                                                zone->db_argc - 1,
10266                                                zone->db_argv + 1,
10267                                                &stub->db);
10268                         if (result != ISC_R_SUCCESS) {
10269                                 dns_zone_log(zone, ISC_LOG_ERROR,
10270                                              "refreshing stub: "
10271                                              "could not create "
10272                                              "database: %s",
10273                                              dns_result_totext(result));
10274                                 goto cleanup;
10275                         }
10276                         dns_db_settask(stub->db, zone->task);
10277                 }
10278
10279                 result = dns_db_newversion(stub->db, &stub->version);
10280                 if (result != ISC_R_SUCCESS) {
10281                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10282                                      "dns_db_newversion() failed: %s",
10283                                      dns_result_totext(result));
10284                         goto cleanup;
10285                 }
10286
10287                 /*
10288                  * Update SOA record.
10289                  */
10290                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
10291                                          &node);
10292                 if (result != ISC_R_SUCCESS) {
10293                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10294                                      "dns_db_findnode() failed: %s",
10295                                      dns_result_totext(result));
10296                         goto cleanup;
10297                 }
10298
10299                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
10300                                             soardataset, 0, NULL);
10301                 dns_db_detachnode(stub->db, &node);
10302                 if (result != ISC_R_SUCCESS) {
10303                         dns_zone_log(zone, ISC_LOG_INFO,
10304                                      "refreshing stub: "
10305                                      "dns_db_addrdataset() failed: %s",
10306                                      dns_result_totext(result));
10307                         goto cleanup;
10308                 }
10309         }
10310
10311         /*
10312          * XXX Optimisation: Create message when zone is setup and reuse.
10313          */
10314         result = create_query(zone, dns_rdatatype_ns, &message);
10315         INSIST(result == ISC_R_SUCCESS);
10316
10317         INSIST(zone->masterscnt > 0);
10318         INSIST(zone->curmaster < zone->masterscnt);
10319         zone->masteraddr = zone->masters[zone->curmaster];
10320
10321         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10322         /*
10323          * First, look for a tsig key in the master statement, then
10324          * try for a server key.
10325          */
10326         if ((zone->masterkeynames != NULL) &&
10327             (zone->masterkeynames[zone->curmaster] != NULL)) {
10328                 dns_view_t *view = dns_zone_getview(zone);
10329                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10330                 result = dns_view_gettsig(view, keyname, &key);
10331                 if (result != ISC_R_SUCCESS) {
10332                         char namebuf[DNS_NAME_FORMATSIZE];
10333                         dns_name_format(keyname, namebuf, sizeof(namebuf));
10334                         dns_zone_log(zone, ISC_LOG_ERROR,
10335                                      "unable to find key: %s", namebuf);
10336                 }
10337         }
10338         if (key == NULL)
10339                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
10340
10341         reqnsid = zone->view->requestnsid;
10342         if (zone->view->peers != NULL) {
10343                 dns_peer_t *peer = NULL;
10344                 isc_boolean_t edns;
10345                 result = dns_peerlist_peerbyaddr(zone->view->peers,
10346                                                  &masterip, &peer);
10347                 if (result == ISC_R_SUCCESS) {
10348                         result = dns_peer_getsupportedns(peer, &edns);
10349                         if (result == ISC_R_SUCCESS && !edns)
10350                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10351                         result = dns_peer_gettransfersource(peer,
10352                                                             &zone->sourceaddr);
10353                         if (result == ISC_R_SUCCESS)
10354                                 have_xfrsource = ISC_TRUE;
10355                         if (zone->view->resolver != NULL)
10356                                 udpsize =
10357                                   dns_resolver_getudpsize(zone->view->resolver);
10358                         (void)dns_peer_getudpsize(peer, &udpsize);
10359                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
10360                 }
10361
10362         }
10363         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10364                 result = add_opt(message, udpsize, reqnsid);
10365                 if (result != ISC_R_SUCCESS)
10366                         zone_debuglog(zone, me, 1,
10367                                       "unable to add opt record: %s",
10368                                       dns_result_totext(result));
10369         }
10370
10371         /*
10372          * Always use TCP so that we shouldn't truncate in additional section.
10373          */
10374         switch (isc_sockaddr_pf(&zone->masteraddr)) {
10375         case PF_INET:
10376                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10377                         zone->sourceaddr = zone->altxfrsource4;
10378                 else if (!have_xfrsource)
10379                         zone->sourceaddr = zone->xfrsource4;
10380                 break;
10381         case PF_INET6:
10382                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10383                         zone->sourceaddr = zone->altxfrsource6;
10384                 else if (!have_xfrsource)
10385                         zone->sourceaddr = zone->xfrsource6;
10386                 break;
10387         default:
10388                 result = ISC_R_NOTIMPLEMENTED;
10389                 POST(result);
10390                 goto cleanup;
10391         }
10392         timeout = 15;
10393         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10394                 timeout = 30;
10395         result = dns_request_createvia2(zone->view->requestmgr, message,
10396                                         &zone->sourceaddr, &zone->masteraddr,
10397                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
10398                                         timeout, zone->task, stub_callback,
10399                                         stub, &zone->request);
10400         if (result != ISC_R_SUCCESS) {
10401                 zone_debuglog(zone, me, 1,
10402                               "dns_request_createvia() failed: %s",
10403                               dns_result_totext(result));
10404                 goto cleanup;
10405         }
10406         dns_message_destroy(&message);
10407         goto unlock;
10408
10409  cleanup:
10410         cancel_refresh(zone);
10411         if (stub != NULL) {
10412                 stub->magic = 0;
10413                 if (stub->version != NULL)
10414                         dns_db_closeversion(stub->db, &stub->version,
10415                                             ISC_FALSE);
10416                 if (stub->db != NULL)
10417                         dns_db_detach(&stub->db);
10418                 if (stub->zone != NULL)
10419                         zone_idetach(&stub->zone);
10420                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
10421         }
10422         if (message != NULL)
10423                 dns_message_destroy(&message);
10424  unlock:
10425         if (key != NULL)
10426                 dns_tsigkey_detach(&key);
10427         return;
10428 }
10429
10430 /*
10431  * Handle the control event.  Note that although this event causes the zone
10432  * to shut down, it is not a shutdown event in the sense of the task library.
10433  */
10434 static void
10435 zone_shutdown(isc_task_t *task, isc_event_t *event) {
10436         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
10437         isc_boolean_t free_needed, linked = ISC_FALSE;
10438
10439         UNUSED(task);
10440         REQUIRE(DNS_ZONE_VALID(zone));
10441         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
10442         INSIST(isc_refcount_current(&zone->erefs) == 0);
10443
10444         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
10445
10446         /*
10447          * Stop things being restarted after we cancel them below.
10448          */
10449         LOCK_ZONE(zone);
10450         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
10451         UNLOCK_ZONE(zone);
10452
10453         /*
10454          * If we were waiting for xfrin quota, step out of
10455          * the queue.
10456          * If there's no zone manager, we can't be waiting for the
10457          * xfrin quota
10458          */
10459         if (zone->zmgr != NULL) {
10460                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10461                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
10462                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
10463                                         statelink);
10464                         linked = ISC_TRUE;
10465                         zone->statelist = NULL;
10466                 }
10467                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10468         }
10469
10470         /*
10471          * In task context, no locking required.  See zone_xfrdone().
10472          */
10473         if (zone->xfr != NULL)
10474                 dns_xfrin_shutdown(zone->xfr);
10475
10476         LOCK_ZONE(zone);
10477         if (linked) {
10478                 INSIST(zone->irefs > 0);
10479                 zone->irefs--;
10480         }
10481         if (zone->request != NULL) {
10482                 dns_request_cancel(zone->request);
10483         }
10484
10485         if (zone->readio != NULL)
10486                 zonemgr_cancelio(zone->readio);
10487
10488         if (zone->lctx != NULL)
10489                 dns_loadctx_cancel(zone->lctx);
10490
10491         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
10492             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10493                 if (zone->writeio != NULL)
10494                         zonemgr_cancelio(zone->writeio);
10495
10496                 if (zone->dctx != NULL)
10497                         dns_dumpctx_cancel(zone->dctx);
10498         }
10499
10500         notify_cancel(zone);
10501
10502         forward_cancel(zone);
10503
10504         if (zone->timer != NULL) {
10505                 isc_timer_detach(&zone->timer);
10506                 INSIST(zone->irefs > 0);
10507                 zone->irefs--;
10508         }
10509
10510         if (zone->view != NULL)
10511                 dns_view_weakdetach(&zone->view);
10512
10513         /*
10514          * We have now canceled everything set the flag to allow exit_check()
10515          * to succeed.  We must not unlock between setting this flag and
10516          * calling exit_check().
10517          */
10518         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
10519         free_needed = exit_check(zone);
10520         UNLOCK_ZONE(zone);
10521         if (free_needed)
10522                 zone_free(zone);
10523 }
10524
10525 static void
10526 zone_timer(isc_task_t *task, isc_event_t *event) {
10527         const char me[] = "zone_timer";
10528         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
10529
10530         UNUSED(task);
10531         REQUIRE(DNS_ZONE_VALID(zone));
10532
10533         ENTER;
10534
10535         zone_maintenance(zone);
10536
10537         isc_event_free(&event);
10538 }
10539
10540 static void
10541 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
10542         const char me[] = "zone_settimer";
10543         isc_time_t next;
10544         isc_result_t result;
10545
10546         ENTER;
10547         REQUIRE(DNS_ZONE_VALID(zone));
10548         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10549                 return;
10550
10551         isc_time_settoepoch(&next);
10552
10553         switch (zone->type) {
10554         case dns_zone_master:
10555                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10556                         next = zone->notifytime;
10557                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10558                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10559                         INSIST(!isc_time_isepoch(&zone->dumptime));
10560                         if (isc_time_isepoch(&next) ||
10561                             isc_time_compare(&zone->dumptime, &next) < 0)
10562                                 next = zone->dumptime;
10563                 }
10564                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
10565                     !isc_time_isepoch(&zone->refreshkeytime)) {
10566                         if (isc_time_isepoch(&next) ||
10567                             isc_time_compare(&zone->refreshkeytime, &next) < 0)
10568                                 next = zone->refreshkeytime;
10569                 }
10570                 if (!isc_time_isepoch(&zone->resigntime)) {
10571                         if (isc_time_isepoch(&next) ||
10572                             isc_time_compare(&zone->resigntime, &next) < 0)
10573                                 next = zone->resigntime;
10574                 }
10575                 if (!isc_time_isepoch(&zone->keywarntime)) {
10576                         if (isc_time_isepoch(&next) ||
10577                             isc_time_compare(&zone->keywarntime, &next) < 0)
10578                                 next = zone->keywarntime;
10579                 }
10580                 if (!isc_time_isepoch(&zone->signingtime)) {
10581                         if (isc_time_isepoch(&next) ||
10582                             isc_time_compare(&zone->signingtime, &next) < 0)
10583                                 next = zone->signingtime;
10584                 }
10585                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
10586                         if (isc_time_isepoch(&next) ||
10587                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
10588                                 next = zone->nsec3chaintime;
10589                 }
10590                 break;
10591
10592         case dns_zone_slave:
10593                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10594                         next = zone->notifytime;
10595                 /*FALLTHROUGH*/
10596
10597         case dns_zone_stub:
10598                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
10599                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
10600                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
10601                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
10602                         INSIST(!isc_time_isepoch(&zone->refreshtime));
10603                         if (isc_time_isepoch(&next) ||
10604                             isc_time_compare(&zone->refreshtime, &next) < 0)
10605                                 next = zone->refreshtime;
10606                 }
10607                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10608                         INSIST(!isc_time_isepoch(&zone->expiretime));
10609                         if (isc_time_isepoch(&next) ||
10610                             isc_time_compare(&zone->expiretime, &next) < 0)
10611                                 next = zone->expiretime;
10612                 }
10613                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10614                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10615                         INSIST(!isc_time_isepoch(&zone->dumptime));
10616                         if (isc_time_isepoch(&next) ||
10617                             isc_time_compare(&zone->dumptime, &next) < 0)
10618                                 next = zone->dumptime;
10619                 }
10620                 break;
10621
10622         case dns_zone_key:
10623                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10624                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10625                         INSIST(!isc_time_isepoch(&zone->dumptime));
10626                         if (isc_time_isepoch(&next) ||
10627                             isc_time_compare(&zone->dumptime, &next) < 0)
10628                                 next = zone->dumptime;
10629                 }
10630                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10631                         if (isc_time_isepoch(&next) ||
10632                             (!isc_time_isepoch(&zone->refreshkeytime) &&
10633                             isc_time_compare(&zone->refreshkeytime, &next) < 0))
10634                                 next = zone->refreshkeytime;
10635                 }
10636                 break;
10637
10638         default:
10639                 break;
10640         }
10641
10642         if (isc_time_isepoch(&next)) {
10643                 zone_debuglog(zone, me, 10, "settimer inactive");
10644                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
10645                                           NULL, NULL, ISC_TRUE);
10646                 if (result != ISC_R_SUCCESS)
10647                         dns_zone_log(zone, ISC_LOG_ERROR,
10648                                      "could not deactivate zone timer: %s",
10649                                      isc_result_totext(result));
10650         } else {
10651                 if (isc_time_compare(&next, now) <= 0)
10652                         next = *now;
10653                 result = isc_timer_reset(zone->timer, isc_timertype_once,
10654                                          &next, NULL, ISC_TRUE);
10655                 if (result != ISC_R_SUCCESS)
10656                         dns_zone_log(zone, ISC_LOG_ERROR,
10657                                      "could not reset zone timer: %s",
10658                                      isc_result_totext(result));
10659         }
10660 }
10661
10662 static void
10663 cancel_refresh(dns_zone_t *zone) {
10664         const char me[] = "cancel_refresh";
10665         isc_time_t now;
10666
10667         /*
10668          * 'zone' locked by caller.
10669          */
10670
10671         REQUIRE(DNS_ZONE_VALID(zone));
10672         REQUIRE(LOCKED_ZONE(zone));
10673
10674         ENTER;
10675
10676         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10677         TIME_NOW(&now);
10678         zone_settimer(zone, &now);
10679 }
10680
10681 static isc_result_t
10682 notify_createmessage(dns_zone_t *zone, unsigned int flags,
10683                      dns_message_t **messagep)
10684 {
10685         dns_db_t *zonedb = NULL;
10686         dns_dbnode_t *node = NULL;
10687         dns_dbversion_t *version = NULL;
10688         dns_message_t *message = NULL;
10689         dns_rdataset_t rdataset;
10690         dns_rdata_t rdata = DNS_RDATA_INIT;
10691
10692         dns_name_t *tempname = NULL;
10693         dns_rdata_t *temprdata = NULL;
10694         dns_rdatalist_t *temprdatalist = NULL;
10695         dns_rdataset_t *temprdataset = NULL;
10696
10697         isc_result_t result;
10698         isc_region_t r;
10699         isc_buffer_t *b = NULL;
10700
10701         REQUIRE(DNS_ZONE_VALID(zone));
10702         REQUIRE(messagep != NULL && *messagep == NULL);
10703
10704         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10705                                     &message);
10706         if (result != ISC_R_SUCCESS)
10707                 return (result);
10708
10709         message->opcode = dns_opcode_notify;
10710         message->flags |= DNS_MESSAGEFLAG_AA;
10711         message->rdclass = zone->rdclass;
10712
10713         result = dns_message_gettempname(message, &tempname);
10714         if (result != ISC_R_SUCCESS)
10715                 goto cleanup;
10716
10717         result = dns_message_gettemprdataset(message, &temprdataset);
10718         if (result != ISC_R_SUCCESS)
10719                 goto cleanup;
10720
10721         /*
10722          * Make question.
10723          */
10724         dns_name_init(tempname, NULL);
10725         dns_name_clone(&zone->origin, tempname);
10726         dns_rdataset_init(temprdataset);
10727         dns_rdataset_makequestion(temprdataset, zone->rdclass,
10728                                   dns_rdatatype_soa);
10729         ISC_LIST_APPEND(tempname->list, temprdataset, link);
10730         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
10731         tempname = NULL;
10732         temprdataset = NULL;
10733
10734         if ((flags & DNS_NOTIFY_NOSOA) != 0)
10735                 goto done;
10736
10737         result = dns_message_gettempname(message, &tempname);
10738         if (result != ISC_R_SUCCESS)
10739                 goto soa_cleanup;
10740         result = dns_message_gettemprdata(message, &temprdata);
10741         if (result != ISC_R_SUCCESS)
10742                 goto soa_cleanup;
10743         result = dns_message_gettemprdataset(message, &temprdataset);
10744         if (result != ISC_R_SUCCESS)
10745                 goto soa_cleanup;
10746         result = dns_message_gettemprdatalist(message, &temprdatalist);
10747         if (result != ISC_R_SUCCESS)
10748                 goto soa_cleanup;
10749
10750         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10751         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
10752         dns_db_attach(zone->db, &zonedb);
10753         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10754
10755         dns_name_init(tempname, NULL);
10756         dns_name_clone(&zone->origin, tempname);
10757         dns_db_currentversion(zonedb, &version);
10758         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
10759         if (result != ISC_R_SUCCESS)
10760                 goto soa_cleanup;
10761
10762         dns_rdataset_init(&rdataset);
10763         result = dns_db_findrdataset(zonedb, node, version,
10764                                      dns_rdatatype_soa,
10765                                      dns_rdatatype_none, 0, &rdataset,
10766                                      NULL);
10767         if (result != ISC_R_SUCCESS)
10768                 goto soa_cleanup;
10769         result = dns_rdataset_first(&rdataset);
10770         if (result != ISC_R_SUCCESS)
10771                 goto soa_cleanup;
10772         dns_rdataset_current(&rdataset, &rdata);
10773         dns_rdata_toregion(&rdata, &r);
10774         result = isc_buffer_allocate(zone->mctx, &b, r.length);
10775         if (result != ISC_R_SUCCESS)
10776                 goto soa_cleanup;
10777         isc_buffer_putmem(b, r.base, r.length);
10778         isc_buffer_usedregion(b, &r);
10779         dns_rdata_init(temprdata);
10780         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
10781         dns_message_takebuffer(message, &b);
10782         result = dns_rdataset_next(&rdataset);
10783         dns_rdataset_disassociate(&rdataset);
10784         if (result != ISC_R_NOMORE)
10785                 goto soa_cleanup;
10786         temprdatalist->rdclass = rdata.rdclass;
10787         temprdatalist->type = rdata.type;
10788         temprdatalist->covers = 0;
10789         temprdatalist->ttl = rdataset.ttl;
10790         ISC_LIST_INIT(temprdatalist->rdata);
10791         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
10792
10793         dns_rdataset_init(temprdataset);
10794         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
10795         if (result != ISC_R_SUCCESS)
10796                 goto soa_cleanup;
10797
10798         ISC_LIST_APPEND(tempname->list, temprdataset, link);
10799         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
10800         temprdatalist = NULL;
10801         temprdataset = NULL;
10802         temprdata = NULL;
10803         tempname = NULL;
10804
10805  soa_cleanup:
10806         if (node != NULL)
10807                 dns_db_detachnode(zonedb, &node);
10808         if (version != NULL)
10809                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
10810         if (zonedb != NULL)
10811                 dns_db_detach(&zonedb);
10812         if (tempname != NULL)
10813                 dns_message_puttempname(message, &tempname);
10814         if (temprdata != NULL)
10815                 dns_message_puttemprdata(message, &temprdata);
10816         if (temprdataset != NULL)
10817                 dns_message_puttemprdataset(message, &temprdataset);
10818         if (temprdatalist != NULL)
10819                 dns_message_puttemprdatalist(message, &temprdatalist);
10820
10821  done:
10822         *messagep = message;
10823         return (ISC_R_SUCCESS);
10824
10825  cleanup:
10826         if (tempname != NULL)
10827                 dns_message_puttempname(message, &tempname);
10828         if (temprdataset != NULL)
10829                 dns_message_puttemprdataset(message, &temprdataset);
10830         dns_message_destroy(&message);
10831         return (result);
10832 }
10833
10834 isc_result_t
10835 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
10836                        dns_message_t *msg)
10837 {
10838         unsigned int i;
10839         dns_rdata_soa_t soa;
10840         dns_rdataset_t *rdataset = NULL;
10841         dns_rdata_t rdata = DNS_RDATA_INIT;
10842         isc_result_t result;
10843         char fromtext[ISC_SOCKADDR_FORMATSIZE];
10844         int match = 0;
10845         isc_netaddr_t netaddr;
10846         isc_sockaddr_t local, remote;
10847
10848         REQUIRE(DNS_ZONE_VALID(zone));
10849
10850         /*
10851          * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
10852          * ROLLOVER.
10853          *
10854          * SOA: RFC1996
10855          * Check that 'from' is a valid notify source, (zone->masters).
10856          *      Return DNS_R_REFUSED if not.
10857          *
10858          * If the notify message contains a serial number check it
10859          * against the zones serial and return if <= current serial
10860          *
10861          * If a refresh check is progress, if so just record the
10862          * fact we received a NOTIFY and from where and return.
10863          * We will perform a new refresh check when the current one
10864          * completes. Return ISC_R_SUCCESS.
10865          *
10866          * Otherwise initiate a refresh check using 'from' as the
10867          * first address to check.  Return ISC_R_SUCCESS.
10868          */
10869
10870         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
10871
10872         /*
10873          *  We only handle NOTIFY (SOA) at the present.
10874          */
10875         LOCK_ZONE(zone);
10876         if (isc_sockaddr_pf(from) == PF_INET)
10877                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
10878         else
10879                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
10880         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
10881             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
10882                                  dns_rdatatype_soa, dns_rdatatype_none,
10883                                  NULL, NULL) != ISC_R_SUCCESS) {
10884                 UNLOCK_ZONE(zone);
10885                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
10886                         dns_zone_log(zone, ISC_LOG_NOTICE,
10887                                      "NOTIFY with no "
10888                                      "question section from: %s", fromtext);
10889                         return (DNS_R_FORMERR);
10890                 }
10891                 dns_zone_log(zone, ISC_LOG_NOTICE,
10892                              "NOTIFY zone does not match");
10893                 return (DNS_R_NOTIMP);
10894         }
10895
10896         /*
10897          * If we are a master zone just succeed.
10898          */
10899         if (zone->type == dns_zone_master) {
10900                 UNLOCK_ZONE(zone);
10901                 return (ISC_R_SUCCESS);
10902         }
10903
10904         isc_netaddr_fromsockaddr(&netaddr, from);
10905         for (i = 0; i < zone->masterscnt; i++) {
10906                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
10907                         break;
10908                 if (zone->view->aclenv.match_mapped &&
10909                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
10910                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
10911                         isc_netaddr_t na1, na2;
10912                         isc_netaddr_fromv4mapped(&na1, &netaddr);
10913                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
10914                         if (isc_netaddr_equal(&na1, &na2))
10915                                 break;
10916                 }
10917         }
10918
10919         /*
10920          * Accept notify requests from non masters if they are on
10921          * 'zone->notify_acl'.
10922          */
10923         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
10924             dns_acl_match(&netaddr, NULL, zone->notify_acl,
10925                           &zone->view->aclenv,
10926                           &match, NULL) == ISC_R_SUCCESS &&
10927             match > 0)
10928         {
10929                 /* Accept notify. */
10930         } else if (i >= zone->masterscnt) {
10931                 UNLOCK_ZONE(zone);
10932                 dns_zone_log(zone, ISC_LOG_INFO,
10933                              "refused notify from non-master: %s", fromtext);
10934                 inc_stats(zone, dns_zonestatscounter_notifyrej);
10935                 return (DNS_R_REFUSED);
10936         }
10937
10938         /*
10939          * If the zone is loaded and there are answers check the serial
10940          * to see if we need to do a refresh.  Do not worry about this
10941          * check if we are a dialup zone as we use the notify request
10942          * to trigger a refresh check.
10943          */
10944         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
10945             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10946             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
10947                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
10948                                               &zone->origin,
10949                                               dns_rdatatype_soa,
10950                                               dns_rdatatype_none, NULL,
10951                                               &rdataset);
10952                 if (result == ISC_R_SUCCESS)
10953                         result = dns_rdataset_first(rdataset);
10954                 if (result == ISC_R_SUCCESS) {
10955                         isc_uint32_t serial = 0, oldserial;
10956
10957                         dns_rdataset_current(rdataset, &rdata);
10958                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
10959                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10960                         serial = soa.serial;
10961                         /*
10962                          * The following should safely be performed without DB
10963                          * lock and succeed in this context.
10964                          */
10965                         result = zone_get_from_db(zone, zone->db, NULL, NULL,
10966                                                   &oldserial, NULL, NULL, NULL,
10967                                                   NULL, NULL);
10968                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10969                         if (isc_serial_le(serial, oldserial)) {
10970                                 dns_zone_log(zone,
10971                                              ISC_LOG_INFO,
10972                                              "notify from %s: "
10973                                              "zone is up to date",
10974                                              fromtext);
10975                                 UNLOCK_ZONE(zone);
10976                                 return (ISC_R_SUCCESS);
10977                         }
10978                 }
10979         }
10980
10981         /*
10982          * If we got this far and there was a refresh in progress just
10983          * let it complete.  Record where we got the notify from so we
10984          * can perform a refresh check when the current one completes
10985          */
10986         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
10987                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10988                 zone->notifyfrom = *from;
10989                 UNLOCK_ZONE(zone);
10990                 dns_zone_log(zone, ISC_LOG_INFO,
10991                              "notify from %s: refresh in progress, "
10992                              "refresh check queued",
10993                              fromtext);
10994                 return (ISC_R_SUCCESS);
10995         }
10996         zone->notifyfrom = *from;
10997         local = zone->masteraddr;
10998         remote = zone->sourceaddr;
10999         UNLOCK_ZONE(zone);
11000         dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
11001         dns_zone_refresh(zone);
11002         return (ISC_R_SUCCESS);
11003 }
11004
11005 void
11006 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
11007
11008         REQUIRE(DNS_ZONE_VALID(zone));
11009
11010         LOCK_ZONE(zone);
11011         if (zone->notify_acl != NULL)
11012                 dns_acl_detach(&zone->notify_acl);
11013         dns_acl_attach(acl, &zone->notify_acl);
11014         UNLOCK_ZONE(zone);
11015 }
11016
11017 void
11018 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
11019
11020         REQUIRE(DNS_ZONE_VALID(zone));
11021
11022         LOCK_ZONE(zone);
11023         if (zone->query_acl != NULL)
11024                 dns_acl_detach(&zone->query_acl);
11025         dns_acl_attach(acl, &zone->query_acl);
11026         UNLOCK_ZONE(zone);
11027 }
11028
11029 void
11030 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
11031
11032         REQUIRE(DNS_ZONE_VALID(zone));
11033
11034         LOCK_ZONE(zone);
11035         if (zone->queryon_acl != NULL)
11036                 dns_acl_detach(&zone->queryon_acl);
11037         dns_acl_attach(acl, &zone->queryon_acl);
11038         UNLOCK_ZONE(zone);
11039 }
11040
11041 void
11042 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
11043
11044         REQUIRE(DNS_ZONE_VALID(zone));
11045
11046         LOCK_ZONE(zone);
11047         if (zone->update_acl != NULL)
11048                 dns_acl_detach(&zone->update_acl);
11049         dns_acl_attach(acl, &zone->update_acl);
11050         UNLOCK_ZONE(zone);
11051 }
11052
11053 void
11054 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
11055
11056         REQUIRE(DNS_ZONE_VALID(zone));
11057
11058         LOCK_ZONE(zone);
11059         if (zone->forward_acl != NULL)
11060                 dns_acl_detach(&zone->forward_acl);
11061         dns_acl_attach(acl, &zone->forward_acl);
11062         UNLOCK_ZONE(zone);
11063 }
11064
11065 void
11066 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
11067
11068         REQUIRE(DNS_ZONE_VALID(zone));
11069
11070         LOCK_ZONE(zone);
11071         if (zone->xfr_acl != NULL)
11072                 dns_acl_detach(&zone->xfr_acl);
11073         dns_acl_attach(acl, &zone->xfr_acl);
11074         UNLOCK_ZONE(zone);
11075 }
11076
11077 dns_acl_t *
11078 dns_zone_getnotifyacl(dns_zone_t *zone) {
11079
11080         REQUIRE(DNS_ZONE_VALID(zone));
11081
11082         return (zone->notify_acl);
11083 }
11084
11085 dns_acl_t *
11086 dns_zone_getqueryacl(dns_zone_t *zone) {
11087
11088         REQUIRE(DNS_ZONE_VALID(zone));
11089
11090         return (zone->query_acl);
11091 }
11092
11093 dns_acl_t *
11094 dns_zone_getqueryonacl(dns_zone_t *zone) {
11095
11096         REQUIRE(DNS_ZONE_VALID(zone));
11097
11098         return (zone->queryon_acl);
11099 }
11100
11101 dns_acl_t *
11102 dns_zone_getupdateacl(dns_zone_t *zone) {
11103
11104         REQUIRE(DNS_ZONE_VALID(zone));
11105
11106         return (zone->update_acl);
11107 }
11108
11109 dns_acl_t *
11110 dns_zone_getforwardacl(dns_zone_t *zone) {
11111
11112         REQUIRE(DNS_ZONE_VALID(zone));
11113
11114         return (zone->forward_acl);
11115 }
11116
11117 dns_acl_t *
11118 dns_zone_getxfracl(dns_zone_t *zone) {
11119
11120         REQUIRE(DNS_ZONE_VALID(zone));
11121
11122         return (zone->xfr_acl);
11123 }
11124
11125 void
11126 dns_zone_clearupdateacl(dns_zone_t *zone) {
11127
11128         REQUIRE(DNS_ZONE_VALID(zone));
11129
11130         LOCK_ZONE(zone);
11131         if (zone->update_acl != NULL)
11132                 dns_acl_detach(&zone->update_acl);
11133         UNLOCK_ZONE(zone);
11134 }
11135
11136 void
11137 dns_zone_clearforwardacl(dns_zone_t *zone) {
11138
11139         REQUIRE(DNS_ZONE_VALID(zone));
11140
11141         LOCK_ZONE(zone);
11142         if (zone->forward_acl != NULL)
11143                 dns_acl_detach(&zone->forward_acl);
11144         UNLOCK_ZONE(zone);
11145 }
11146
11147 void
11148 dns_zone_clearnotifyacl(dns_zone_t *zone) {
11149
11150         REQUIRE(DNS_ZONE_VALID(zone));
11151
11152         LOCK_ZONE(zone);
11153         if (zone->notify_acl != NULL)
11154                 dns_acl_detach(&zone->notify_acl);
11155         UNLOCK_ZONE(zone);
11156 }
11157
11158 void
11159 dns_zone_clearqueryacl(dns_zone_t *zone) {
11160
11161         REQUIRE(DNS_ZONE_VALID(zone));
11162
11163         LOCK_ZONE(zone);
11164         if (zone->query_acl != NULL)
11165                 dns_acl_detach(&zone->query_acl);
11166         UNLOCK_ZONE(zone);
11167 }
11168
11169 void
11170 dns_zone_clearqueryonacl(dns_zone_t *zone) {
11171
11172         REQUIRE(DNS_ZONE_VALID(zone));
11173
11174         LOCK_ZONE(zone);
11175         if (zone->queryon_acl != NULL)
11176                 dns_acl_detach(&zone->queryon_acl);
11177         UNLOCK_ZONE(zone);
11178 }
11179
11180 void
11181 dns_zone_clearxfracl(dns_zone_t *zone) {
11182
11183         REQUIRE(DNS_ZONE_VALID(zone));
11184
11185         LOCK_ZONE(zone);
11186         if (zone->xfr_acl != NULL)
11187                 dns_acl_detach(&zone->xfr_acl);
11188         UNLOCK_ZONE(zone);
11189 }
11190
11191 isc_boolean_t
11192 dns_zone_getupdatedisabled(dns_zone_t *zone) {
11193         REQUIRE(DNS_ZONE_VALID(zone));
11194         return (zone->update_disabled);
11195
11196 }
11197
11198 void
11199 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
11200         REQUIRE(DNS_ZONE_VALID(zone));
11201         zone->update_disabled = state;
11202 }
11203
11204 isc_boolean_t
11205 dns_zone_getzeronosoattl(dns_zone_t *zone) {
11206         REQUIRE(DNS_ZONE_VALID(zone));
11207         return (zone->zero_no_soa_ttl);
11208
11209 }
11210
11211 void
11212 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
11213         REQUIRE(DNS_ZONE_VALID(zone));
11214         zone->zero_no_soa_ttl = state;
11215 }
11216
11217 void
11218 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
11219
11220         REQUIRE(DNS_ZONE_VALID(zone));
11221
11222         zone->check_names = severity;
11223 }
11224
11225 dns_severity_t
11226 dns_zone_getchecknames(dns_zone_t *zone) {
11227
11228         REQUIRE(DNS_ZONE_VALID(zone));
11229
11230         return (zone->check_names);
11231 }
11232
11233 void
11234 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
11235
11236         REQUIRE(DNS_ZONE_VALID(zone));
11237
11238         zone->journalsize = size;
11239 }
11240
11241 isc_int32_t
11242 dns_zone_getjournalsize(dns_zone_t *zone) {
11243
11244         REQUIRE(DNS_ZONE_VALID(zone));
11245
11246         return (zone->journalsize);
11247 }
11248
11249 static void
11250 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
11251         isc_result_t result = ISC_R_FAILURE;
11252         isc_buffer_t buffer;
11253
11254         REQUIRE(buf != NULL);
11255         REQUIRE(length > 1U);
11256
11257         /*
11258          * Leave space for terminating '\0'.
11259          */
11260         isc_buffer_init(&buffer, buf, length - 1);
11261         if (dns_name_dynamic(&zone->origin))
11262                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11263         if (result != ISC_R_SUCCESS &&
11264             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11265                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
11266
11267         if (isc_buffer_availablelength(&buffer) > 0)
11268                 isc_buffer_putstr(&buffer, "/");
11269         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
11270
11271         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
11272             strcmp(zone->view->name, "_default") != 0 &&
11273             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
11274                 isc_buffer_putstr(&buffer, "/");
11275                 isc_buffer_putstr(&buffer, zone->view->name);
11276         }
11277
11278         buf[isc_buffer_usedlength(&buffer)] = '\0';
11279 }
11280
11281 static void
11282 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
11283         isc_result_t result = ISC_R_FAILURE;
11284         isc_buffer_t buffer;
11285
11286         REQUIRE(buf != NULL);
11287         REQUIRE(length > 1U);
11288
11289         /*
11290          * Leave space for terminating '\0'.
11291          */
11292         isc_buffer_init(&buffer, buf, length - 1);
11293         if (dns_name_dynamic(&zone->origin))
11294                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11295         if (result != ISC_R_SUCCESS &&
11296             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11297                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
11298
11299         buf[isc_buffer_usedlength(&buffer)] = '\0';
11300 }
11301
11302 static void
11303 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
11304         isc_buffer_t buffer;
11305
11306         REQUIRE(buf != NULL);
11307         REQUIRE(length > 1U);
11308
11309         /*
11310          * Leave space for terminating '\0'.
11311          */
11312         isc_buffer_init(&buffer, buf, length - 1);
11313         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
11314
11315         buf[isc_buffer_usedlength(&buffer)] = '\0';
11316 }
11317
11318 static void
11319 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
11320         isc_buffer_t buffer;
11321
11322         REQUIRE(buf != NULL);
11323         REQUIRE(length > 1U);
11324
11325
11326         /*
11327          * Leave space for terminating '\0'.
11328          */
11329         isc_buffer_init(&buffer, buf, length - 1);
11330
11331         if (zone->view == NULL) {
11332                 isc_buffer_putstr(&buffer, "_none");
11333         } else if (strlen(zone->view->name)
11334                    < isc_buffer_availablelength(&buffer)) {
11335                 isc_buffer_putstr(&buffer, zone->view->name);
11336         } else {
11337                 isc_buffer_putstr(&buffer, "_toolong");
11338         }
11339
11340         buf[isc_buffer_usedlength(&buffer)] = '\0';
11341 }
11342
11343 void
11344 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
11345         REQUIRE(DNS_ZONE_VALID(zone));
11346         REQUIRE(buf != NULL);
11347         zone_namerd_tostr(zone, buf, length);
11348 }
11349
11350 static void
11351 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11352         va_list ap;
11353         char message[4096];
11354
11355         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11356                 return;
11357
11358         va_start(ap, fmt);
11359         vsnprintf(message, sizeof(message), fmt, ap);
11360         va_end(ap);
11361         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
11362                       level, "zone %s: %s", zone->strnamerd, message);
11363 }
11364
11365 void
11366 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
11367               int level, const char *fmt, ...) {
11368         va_list ap;
11369         char message[4096];
11370
11371         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11372                 return;
11373
11374         va_start(ap, fmt);
11375         vsnprintf(message, sizeof(message), fmt, ap);
11376         va_end(ap);
11377         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
11378                       level, "%s %s: %s", (zone->type == dns_zone_key) ?
11379                       "managed-keys-zone" : "zone", zone->strnamerd, message);
11380 }
11381
11382 void
11383 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11384         va_list ap;
11385         char message[4096];
11386
11387         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11388                 return;
11389
11390         va_start(ap, fmt);
11391         vsnprintf(message, sizeof(message), fmt, ap);
11392         va_end(ap);
11393         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11394                       level, "%s %s: %s", (zone->type == dns_zone_key) ?
11395                       "managed-keys-zone" : "zone", zone->strnamerd, message);
11396 }
11397
11398 static void
11399 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
11400               const char *fmt, ...)
11401 {
11402         va_list ap;
11403         char message[4096];
11404         int level = ISC_LOG_DEBUG(debuglevel);
11405
11406         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11407                 return;
11408
11409         va_start(ap, fmt);
11410         vsnprintf(message, sizeof(message), fmt, ap);
11411         va_end(ap);
11412         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11413                       level, "%s: %s %s: %s", me, zone->type != dns_zone_key ?
11414                       "zone" : "managed-keys-zone", zone->strnamerd, message);
11415 }
11416
11417 static int
11418 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
11419 {
11420         isc_result_t result;
11421         dns_name_t *name;
11422         dns_rdataset_t *curr;
11423         int count = 0;
11424
11425         result = dns_message_firstname(msg, section);
11426         while (result == ISC_R_SUCCESS) {
11427                 name = NULL;
11428                 dns_message_currentname(msg, section, &name);
11429
11430                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
11431                      curr = ISC_LIST_PREV(curr, link)) {
11432                         if (curr->type == type)
11433                                 count++;
11434                 }
11435                 result = dns_message_nextname(msg, section);
11436         }
11437
11438         return (count);
11439 }
11440
11441 void
11442 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
11443         REQUIRE(DNS_ZONE_VALID(zone));
11444
11445         zone->maxxfrin = maxxfrin;
11446 }
11447
11448 isc_uint32_t
11449 dns_zone_getmaxxfrin(dns_zone_t *zone) {
11450         REQUIRE(DNS_ZONE_VALID(zone));
11451
11452         return (zone->maxxfrin);
11453 }
11454
11455 void
11456 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
11457         REQUIRE(DNS_ZONE_VALID(zone));
11458         zone->maxxfrout = maxxfrout;
11459 }
11460
11461 isc_uint32_t
11462 dns_zone_getmaxxfrout(dns_zone_t *zone) {
11463         REQUIRE(DNS_ZONE_VALID(zone));
11464
11465         return (zone->maxxfrout);
11466 }
11467
11468 dns_zonetype_t
11469 dns_zone_gettype(dns_zone_t *zone) {
11470         REQUIRE(DNS_ZONE_VALID(zone));
11471
11472         return (zone->type);
11473 }
11474
11475 dns_name_t *
11476 dns_zone_getorigin(dns_zone_t *zone) {
11477         REQUIRE(DNS_ZONE_VALID(zone));
11478
11479         return (&zone->origin);
11480 }
11481
11482 void
11483 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
11484         REQUIRE(DNS_ZONE_VALID(zone));
11485
11486         LOCK_ZONE(zone);
11487         if (zone->task != NULL)
11488                 isc_task_detach(&zone->task);
11489         isc_task_attach(task, &zone->task);
11490         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11491         if (zone->db != NULL)
11492                 dns_db_settask(zone->db, zone->task);
11493         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11494         UNLOCK_ZONE(zone);
11495 }
11496
11497 void
11498 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
11499         REQUIRE(DNS_ZONE_VALID(zone));
11500         isc_task_attach(zone->task, target);
11501 }
11502
11503 void
11504 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
11505         REQUIRE(DNS_ZONE_VALID(zone));
11506
11507         if (idlein == 0)
11508                 idlein = DNS_DEFAULT_IDLEIN;
11509         zone->idlein = idlein;
11510 }
11511
11512 isc_uint32_t
11513 dns_zone_getidlein(dns_zone_t *zone) {
11514         REQUIRE(DNS_ZONE_VALID(zone));
11515
11516         return (zone->idlein);
11517 }
11518
11519 void
11520 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
11521         REQUIRE(DNS_ZONE_VALID(zone));
11522
11523         zone->idleout = idleout;
11524 }
11525
11526 isc_uint32_t
11527 dns_zone_getidleout(dns_zone_t *zone) {
11528         REQUIRE(DNS_ZONE_VALID(zone));
11529
11530         return (zone->idleout);
11531 }
11532
11533 static void
11534 notify_done(isc_task_t *task, isc_event_t *event) {
11535         dns_requestevent_t *revent = (dns_requestevent_t *)event;
11536         dns_notify_t *notify;
11537         isc_result_t result;
11538         dns_message_t *message = NULL;
11539         isc_buffer_t buf;
11540         char rcode[128];
11541         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
11542
11543         UNUSED(task);
11544
11545         notify = event->ev_arg;
11546         REQUIRE(DNS_NOTIFY_VALID(notify));
11547         INSIST(task == notify->zone->task);
11548
11549         isc_buffer_init(&buf, rcode, sizeof(rcode));
11550         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
11551
11552         result = revent->result;
11553         if (result == ISC_R_SUCCESS)
11554                 result = dns_message_create(notify->zone->mctx,
11555                                             DNS_MESSAGE_INTENTPARSE, &message);
11556         if (result == ISC_R_SUCCESS)
11557                 result = dns_request_getresponse(revent->request, message,
11558                                         DNS_MESSAGEPARSE_PRESERVEORDER);
11559         if (result == ISC_R_SUCCESS)
11560                 result = dns_rcode_totext(message->rcode, &buf);
11561         if (result == ISC_R_SUCCESS)
11562                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
11563                            "notify response from %s: %.*s",
11564                            addrbuf, (int)buf.used, rcode);
11565         else
11566                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
11567                            "notify to %s failed: %s", addrbuf,
11568                            dns_result_totext(result));
11569
11570         /*
11571          * Old bind's return formerr if they see a soa record.  Retry w/o
11572          * the soa if we see a formerr and had sent a SOA.
11573          */
11574         isc_event_free(&event);
11575         if (message != NULL && message->rcode == dns_rcode_formerr &&
11576             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
11577                 notify->flags |= DNS_NOTIFY_NOSOA;
11578                 dns_request_destroy(&notify->request);
11579                 result = notify_send_queue(notify);
11580                 if (result != ISC_R_SUCCESS)
11581                         notify_destroy(notify, ISC_FALSE);
11582         } else {
11583                 if (result == ISC_R_TIMEDOUT)
11584                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
11585                                    "notify to %s: retries exceeded", addrbuf);
11586                 notify_destroy(notify, ISC_FALSE);
11587         }
11588         if (message != NULL)
11589                 dns_message_destroy(&message);
11590 }
11591
11592 isc_result_t
11593 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11594         isc_result_t result;
11595
11596         REQUIRE(DNS_ZONE_VALID(zone));
11597         LOCK_ZONE(zone);
11598         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11599         result = zone_replacedb(zone, db, dump);
11600         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11601         UNLOCK_ZONE(zone);
11602         return (result);
11603 }
11604
11605 static isc_result_t
11606 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11607         dns_dbversion_t *ver;
11608         isc_result_t result;
11609         unsigned int soacount = 0;
11610         unsigned int nscount = 0;
11611
11612         /*
11613          * 'zone' and 'zonedb' locked by caller.
11614          */
11615         REQUIRE(DNS_ZONE_VALID(zone));
11616         REQUIRE(LOCKED_ZONE(zone));
11617
11618         result = zone_get_from_db(zone, db, &nscount, &soacount,
11619                                   NULL, NULL, NULL, NULL, NULL, NULL);
11620         if (result == ISC_R_SUCCESS) {
11621                 if (soacount != 1) {
11622                         dns_zone_log(zone, ISC_LOG_ERROR,
11623                                      "has %d SOA records", soacount);
11624                         result = DNS_R_BADZONE;
11625                 }
11626                 if (nscount == 0 && zone->type != dns_zone_key) {
11627                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
11628                         result = DNS_R_BADZONE;
11629                 }
11630                 if (result != ISC_R_SUCCESS)
11631                         return (result);
11632         } else {
11633                 dns_zone_log(zone, ISC_LOG_ERROR,
11634                             "retrieving SOA and NS records failed: %s",
11635                             dns_result_totext(result));
11636                 return (result);
11637         }
11638
11639         result = check_nsec3param(zone, db);
11640         if (result != ISC_R_SUCCESS)
11641                 return (result);
11642
11643         ver = NULL;
11644         dns_db_currentversion(db, &ver);
11645
11646         /*
11647          * The initial version of a slave zone is always dumped;
11648          * subsequent versions may be journaled instead if this
11649          * is enabled in the configuration.
11650          */
11651         if (zone->db != NULL && zone->journal != NULL &&
11652             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
11653             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
11654                 isc_uint32_t serial, oldserial;
11655
11656                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
11657
11658                 result = dns_db_getsoaserial(db, ver, &serial);
11659                 if (result != ISC_R_SUCCESS) {
11660                         dns_zone_log(zone, ISC_LOG_ERROR,
11661                                      "ixfr-from-differences: unable to get "
11662                                      "new serial");
11663                         goto fail;
11664                 }
11665
11666                 /*
11667                  * This is checked in zone_postload() for master zones.
11668                  */
11669                 result = zone_get_from_db(zone, zone->db, NULL, NULL,
11670                                           &oldserial, NULL, NULL, NULL, NULL,
11671                                           NULL);
11672                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11673                 if (zone->type == dns_zone_slave &&
11674                     !isc_serial_gt(serial, oldserial)) {
11675                         isc_uint32_t serialmin, serialmax;
11676                         serialmin = (oldserial + 1) & 0xffffffffU;
11677                         serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
11678                         dns_zone_log(zone, ISC_LOG_ERROR,
11679                                      "ixfr-from-differences: failed: "
11680                                      "new serial (%u) out of range [%u - %u]",
11681                                      serial, serialmin, serialmax);
11682                         result = ISC_R_RANGE;
11683                         goto fail;
11684                 }
11685
11686                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
11687                                      zone->journal);
11688                 if (result != ISC_R_SUCCESS)
11689                         goto fail;
11690                 if (dump)
11691                         zone_needdump(zone, DNS_DUMP_DELAY);
11692                 else if (zone->journalsize != -1) {
11693                         result = dns_journal_compact(zone->mctx, zone->journal,
11694                                                      serial, zone->journalsize);
11695                         switch (result) {
11696                         case ISC_R_SUCCESS:
11697                         case ISC_R_NOSPACE:
11698                         case ISC_R_NOTFOUND:
11699                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
11700                                              "dns_journal_compact: %s",
11701                                              dns_result_totext(result));
11702                                 break;
11703                         default:
11704                                 dns_zone_log(zone, ISC_LOG_ERROR,
11705                                              "dns_journal_compact failed: %s",
11706                                              dns_result_totext(result));
11707                                 break;
11708                         }
11709                 }
11710         } else {
11711                 if (dump && zone->masterfile != NULL) {
11712                         /*
11713                          * If DNS_ZONEFLG_FORCEXFER was set we don't want
11714                          * to keep the old masterfile.
11715                          */
11716                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
11717                             remove(zone->masterfile) < 0 && errno != ENOENT) {
11718                                 char strbuf[ISC_STRERRORSIZE];
11719                                 isc__strerror(errno, strbuf, sizeof(strbuf));
11720                                 isc_log_write(dns_lctx,
11721                                               DNS_LOGCATEGORY_GENERAL,
11722                                               DNS_LOGMODULE_ZONE,
11723                                               ISC_LOG_WARNING,
11724                                               "unable to remove masterfile "
11725                                               "'%s': '%s'",
11726                                               zone->masterfile, strbuf);
11727                         }
11728                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
11729                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
11730                         else
11731                                 zone_needdump(zone, 0);
11732                 }
11733                 if (dump && zone->journal != NULL) {
11734                         /*
11735                          * The in-memory database just changed, and
11736                          * because 'dump' is set, it didn't change by
11737                          * being loaded from disk.  Also, we have not
11738                          * journaled diffs for this change.
11739                          * Therefore, the on-disk journal is missing
11740                          * the deltas for this change.  Since it can
11741                          * no longer be used to bring the zone
11742                          * up-to-date, it is useless and should be
11743                          * removed.
11744                          */
11745                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11746                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
11747                                       "removing journal file");
11748                         if (remove(zone->journal) < 0 && errno != ENOENT) {
11749                                 char strbuf[ISC_STRERRORSIZE];
11750                                 isc__strerror(errno, strbuf, sizeof(strbuf));
11751                                 isc_log_write(dns_lctx,
11752                                               DNS_LOGCATEGORY_GENERAL,
11753                                               DNS_LOGMODULE_ZONE,
11754                                               ISC_LOG_WARNING,
11755                                               "unable to remove journal "
11756                                               "'%s': '%s'",
11757                                               zone->journal, strbuf);
11758                         }
11759                 }
11760         }
11761
11762         dns_db_closeversion(db, &ver, ISC_FALSE);
11763
11764         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11765                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
11766                       "replacing zone database");
11767
11768         if (zone->db != NULL)
11769                 zone_detachdb(zone);
11770         zone_attachdb(zone, db);
11771         dns_db_settask(zone->db, zone->task);
11772         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
11773         return (ISC_R_SUCCESS);
11774
11775  fail:
11776         dns_db_closeversion(db, &ver, ISC_FALSE);
11777         return (result);
11778 }
11779
11780 /* The caller must hold the dblock as a writer. */
11781 static inline void
11782 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
11783         REQUIRE(zone->db == NULL && db != NULL);
11784
11785         dns_db_attach(db, &zone->db);
11786         if (zone->acache != NULL) {
11787                 isc_result_t result;
11788                 result = dns_acache_setdb(zone->acache, db);
11789                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
11790                         UNEXPECTED_ERROR(__FILE__, __LINE__,
11791                                          "dns_acache_setdb() failed: %s",
11792                                          isc_result_totext(result));
11793                 }
11794         }
11795 }
11796
11797 /* The caller must hold the dblock as a writer. */
11798 static inline void
11799 zone_detachdb(dns_zone_t *zone) {
11800         REQUIRE(zone->db != NULL);
11801
11802         if (zone->acache != NULL)
11803                 (void)dns_acache_putdb(zone->acache, zone->db);
11804         dns_db_detach(&zone->db);
11805 }
11806
11807 static void
11808 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
11809         isc_time_t now;
11810         isc_boolean_t again = ISC_FALSE;
11811         unsigned int soacount;
11812         unsigned int nscount;
11813         isc_uint32_t serial, refresh, retry, expire, minimum;
11814         isc_result_t xfrresult = result;
11815         isc_boolean_t free_needed;
11816
11817         REQUIRE(DNS_ZONE_VALID(zone));
11818
11819         dns_zone_log(zone, ISC_LOG_DEBUG(1),
11820                      "zone transfer finished: %s", dns_result_totext(result));
11821
11822         LOCK_ZONE(zone);
11823         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
11824         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11825         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
11826
11827         TIME_NOW(&now);
11828         switch (result) {
11829         case ISC_R_SUCCESS:
11830                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11831                 /*FALLTHROUGH*/
11832         case DNS_R_UPTODATE:
11833                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
11834                 /*
11835                  * Has the zone expired underneath us?
11836                  */
11837                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11838                 if (zone->db == NULL) {
11839                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11840                         goto same_master;
11841                 }
11842
11843                 /*
11844                  * Update the zone structure's data from the actual
11845                  * SOA received.
11846                  */
11847                 nscount = 0;
11848                 soacount = 0;
11849                 INSIST(zone->db != NULL);
11850                 result = zone_get_from_db(zone, zone->db, &nscount,
11851                                           &soacount, &serial, &refresh,
11852                                           &retry, &expire, &minimum, NULL);
11853                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11854                 if (result == ISC_R_SUCCESS) {
11855                         if (soacount != 1)
11856                                 dns_zone_log(zone, ISC_LOG_ERROR,
11857                                              "transferred zone "
11858                                              "has %d SOA record%s", soacount,
11859                                              (soacount != 0) ? "s" : "");
11860                         if (nscount == 0) {
11861                                 dns_zone_log(zone, ISC_LOG_ERROR,
11862                                              "transferred zone "
11863                                              "has no NS records");
11864                                 if (DNS_ZONE_FLAG(zone,
11865                                                   DNS_ZONEFLG_HAVETIMERS)) {
11866                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11867                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
11868                                 }
11869                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11870                                 zone_unload(zone);
11871                                 goto next_master;
11872                         }
11873                         zone->refresh = RANGE(refresh, zone->minrefresh,
11874                                               zone->maxrefresh);
11875                         zone->retry = RANGE(retry, zone->minretry,
11876                                             zone->maxretry);
11877                         zone->expire = RANGE(expire,
11878                                              zone->refresh + zone->retry,
11879                                              DNS_MAX_EXPIRE);
11880                         zone->minimum = minimum;
11881                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11882                 }
11883
11884                 /*
11885                  * Set our next update/expire times.
11886                  */
11887                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
11888                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11889                         zone->refreshtime = now;
11890                         DNS_ZONE_TIME_ADD(&now, zone->expire,
11891                                           &zone->expiretime);
11892                 } else {
11893                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
11894                                             &zone->refreshtime);
11895                         DNS_ZONE_TIME_ADD(&now, zone->expire,
11896                                           &zone->expiretime);
11897                 }
11898                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
11899                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
11900                         if (zone->tsigkey != NULL) {
11901                                 char namebuf[DNS_NAME_FORMATSIZE];
11902                                 dns_name_format(&zone->tsigkey->name, namebuf,
11903                                                 sizeof(namebuf));
11904                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
11905                                          namebuf);
11906                         } else
11907                                 buf[0] = '\0';
11908                         dns_zone_log(zone, ISC_LOG_INFO,
11909                                      "transferred serial %u%s",
11910                                      serial, buf);
11911                 }
11912
11913                 /*
11914                  * This is not necessary if we just performed a AXFR
11915                  * however it is necessary for an IXFR / UPTODATE and
11916                  * won't hurt with an AXFR.
11917                  */
11918                 if (zone->masterfile != NULL || zone->journal != NULL) {
11919                         result = ISC_R_FAILURE;
11920                         if (zone->journal != NULL)
11921                                 result = isc_file_settime(zone->journal, &now);
11922                         if (result != ISC_R_SUCCESS &&
11923                             zone->masterfile != NULL)
11924                                 result = isc_file_settime(zone->masterfile,
11925                                                           &now);
11926                         /* Someone removed the file from underneath us! */
11927                         if (result == ISC_R_FILENOTFOUND &&
11928                             zone->masterfile != NULL) {
11929                                 unsigned int delay = DNS_DUMP_DELAY;
11930                                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY))
11931                                         delay = 0;
11932                                 zone_needdump(zone, delay);
11933                         } else if (result != ISC_R_SUCCESS)
11934                                 dns_zone_log(zone, ISC_LOG_ERROR,
11935                                              "transfer: could not set file "
11936                                              "modification time of '%s': %s",
11937                                              zone->masterfile,
11938                                              dns_result_totext(result));
11939                 }
11940                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
11941                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
11942                 break;
11943
11944         case DNS_R_BADIXFR:
11945                 /* Force retry with AXFR. */
11946                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
11947                 goto same_master;
11948
11949         default:
11950         next_master:
11951                 /*
11952                  * Skip to next failed / untried master.
11953                  */
11954                 do {
11955                         zone->curmaster++;
11956                 } while (zone->curmaster < zone->masterscnt &&
11957                          zone->mastersok[zone->curmaster]);
11958                 /* FALLTHROUGH */
11959         same_master:
11960                 if (zone->curmaster >= zone->masterscnt) {
11961                         zone->curmaster = 0;
11962                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
11963                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11964                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11965                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11966                                 while (zone->curmaster < zone->masterscnt &&
11967                                        zone->mastersok[zone->curmaster])
11968                                         zone->curmaster++;
11969                                 again = ISC_TRUE;
11970                         } else
11971                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11972                 } else {
11973                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11974                         again = ISC_TRUE;
11975                 }
11976                 inc_stats(zone, dns_zonestatscounter_xfrfail);
11977                 break;
11978         }
11979         zone_settimer(zone, &now);
11980
11981         /*
11982          * If creating the transfer object failed, zone->xfr is NULL.
11983          * Otherwise, we are called as the done callback of a zone
11984          * transfer object that just entered its shutting-down
11985          * state.  Since we are no longer responsible for shutting
11986          * it down, we can detach our reference.
11987          */
11988         if (zone->xfr != NULL)
11989                 dns_xfrin_detach(&zone->xfr);
11990
11991         if (zone->tsigkey != NULL)
11992                 dns_tsigkey_detach(&zone->tsigkey);
11993
11994         /*
11995          * Handle any deferred journal compaction.
11996          */
11997         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
11998                 result = dns_journal_compact(zone->mctx, zone->journal,
11999                                              zone->compact_serial,
12000                                              zone->journalsize);
12001                 switch (result) {
12002                 case ISC_R_SUCCESS:
12003                 case ISC_R_NOSPACE:
12004                 case ISC_R_NOTFOUND:
12005                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
12006                                      "dns_journal_compact: %s",
12007                                      dns_result_totext(result));
12008                         break;
12009                 default:
12010                         dns_zone_log(zone, ISC_LOG_ERROR,
12011                                      "dns_journal_compact failed: %s",
12012                                      dns_result_totext(result));
12013                         break;
12014                 }
12015                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
12016         }
12017
12018         /*
12019          * This transfer finishing freed up a transfer quota slot.
12020          * Let any other zones waiting for quota have it.
12021          */
12022         UNLOCK_ZONE(zone);
12023         RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12024         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
12025         zone->statelist = NULL;
12026         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
12027         RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12028         LOCK_ZONE(zone);
12029
12030         /*
12031          * Retry with a different server if necessary.
12032          */
12033         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12034                 queue_soa_query(zone);
12035
12036         INSIST(zone->irefs > 0);
12037         zone->irefs--;
12038         free_needed = exit_check(zone);
12039         UNLOCK_ZONE(zone);
12040         if (free_needed)
12041                 zone_free(zone);
12042 }
12043
12044 static void
12045 zone_loaddone(void *arg, isc_result_t result) {
12046         static char me[] = "zone_loaddone";
12047         dns_load_t *load = arg;
12048         dns_zone_t *zone;
12049         isc_result_t tresult;
12050
12051         REQUIRE(DNS_LOAD_VALID(load));
12052         zone = load->zone;
12053
12054         ENTER;
12055
12056         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
12057         if (tresult != ISC_R_SUCCESS &&
12058             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
12059                 result = tresult;
12060
12061         LOCK_ZONE(load->zone);
12062         (void)zone_postload(load->zone, load->db, load->loadtime, result);
12063         zonemgr_putio(&load->zone->readio);
12064         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
12065         /*
12066          * Leave the zone frozen if the reload fails.
12067          */
12068         if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
12069              DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW))
12070                 zone->update_disabled = ISC_FALSE;
12071         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW);
12072         UNLOCK_ZONE(load->zone);
12073
12074         load->magic = 0;
12075         dns_db_detach(&load->db);
12076         if (load->zone->lctx != NULL)
12077                 dns_loadctx_detach(&load->zone->lctx);
12078         dns_zone_idetach(&load->zone);
12079         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
12080 }
12081
12082 void
12083 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
12084         REQUIRE(DNS_ZONE_VALID(zone));
12085         REQUIRE(table != NULL);
12086         REQUIRE(*table == NULL);
12087
12088         LOCK_ZONE(zone);
12089         if (zone->ssutable != NULL)
12090                 dns_ssutable_attach(zone->ssutable, table);
12091         UNLOCK_ZONE(zone);
12092 }
12093
12094 void
12095 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
12096         REQUIRE(DNS_ZONE_VALID(zone));
12097
12098         LOCK_ZONE(zone);
12099         if (zone->ssutable != NULL)
12100                 dns_ssutable_detach(&zone->ssutable);
12101         if (table != NULL)
12102                 dns_ssutable_attach(table, &zone->ssutable);
12103         UNLOCK_ZONE(zone);
12104 }
12105
12106 void
12107 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
12108         REQUIRE(DNS_ZONE_VALID(zone));
12109
12110         zone->sigvalidityinterval = interval;
12111 }
12112
12113 isc_uint32_t
12114 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
12115         REQUIRE(DNS_ZONE_VALID(zone));
12116
12117         return (zone->sigvalidityinterval);
12118 }
12119
12120 void
12121 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
12122         REQUIRE(DNS_ZONE_VALID(zone));
12123
12124         zone->sigresigninginterval = interval;
12125 }
12126
12127 isc_uint32_t
12128 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
12129         REQUIRE(DNS_ZONE_VALID(zone));
12130
12131         return (zone->sigresigninginterval);
12132 }
12133
12134 static void
12135 queue_xfrin(dns_zone_t *zone) {
12136         const char me[] = "queue_xfrin";
12137         isc_result_t result;
12138         dns_zonemgr_t *zmgr = zone->zmgr;
12139
12140         ENTER;
12141
12142         INSIST(zone->statelist == NULL);
12143
12144         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12145         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
12146         LOCK_ZONE(zone);
12147         zone->irefs++;
12148         UNLOCK_ZONE(zone);
12149         zone->statelist = &zmgr->waiting_for_xfrin;
12150         result = zmgr_start_xfrin_ifquota(zmgr, zone);
12151         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12152
12153         if (result == ISC_R_QUOTA) {
12154                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
12155                               "zone transfer deferred due to quota");
12156         } else if (result != ISC_R_SUCCESS) {
12157                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
12158                               "starting zone transfer: %s",
12159                               isc_result_totext(result));
12160         }
12161 }
12162
12163 /*
12164  * This event callback is called when a zone has received
12165  * any necessary zone transfer quota.  This is the time
12166  * to go ahead and start the transfer.
12167  */
12168 static void
12169 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
12170         isc_result_t result;
12171         dns_peer_t *peer = NULL;
12172         char master[ISC_SOCKADDR_FORMATSIZE];
12173         char source[ISC_SOCKADDR_FORMATSIZE];
12174         dns_rdatatype_t xfrtype;
12175         dns_zone_t *zone = event->ev_arg;
12176         isc_netaddr_t masterip;
12177         isc_sockaddr_t sourceaddr;
12178         isc_sockaddr_t masteraddr;
12179         isc_time_t now;
12180         const char *soa_before = "";
12181
12182         UNUSED(task);
12183
12184         INSIST(task == zone->task);
12185
12186         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12187                 result = ISC_R_CANCELED;
12188                 goto cleanup;
12189         }
12190
12191         TIME_NOW(&now);
12192
12193         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12194         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
12195                                     &zone->sourceaddr, &now))
12196         {
12197                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12198                 dns_zone_log(zone, ISC_LOG_INFO,
12199                              "got_transfer_quota: skipping zone transfer as "
12200                              "master %s (source %s) is unreachable (cached)",
12201                              master, source);
12202                 result = ISC_R_CANCELED;
12203                 goto cleanup;
12204         }
12205
12206         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12207         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
12208
12209         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12210                 soa_before = "SOA before ";
12211         /*
12212          * Decide whether we should request IXFR or AXFR.
12213          */
12214         if (zone->db == NULL) {
12215                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12216                              "no database exists yet, requesting AXFR of "
12217                              "initial version from %s", master);
12218                 xfrtype = dns_rdatatype_axfr;
12219         } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
12220                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
12221                              "set, requesting %sAXFR from %s", soa_before,
12222                              master);
12223                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12224                         xfrtype = dns_rdatatype_soa;
12225                 else
12226                         xfrtype = dns_rdatatype_axfr;
12227         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
12228                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12229                              "forced reload, requesting AXFR of "
12230                              "initial version from %s", master);
12231                 xfrtype = dns_rdatatype_axfr;
12232         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
12233                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12234                              "retrying with AXFR from %s due to "
12235                              "previous IXFR failure", master);
12236                 xfrtype = dns_rdatatype_axfr;
12237                 LOCK_ZONE(zone);
12238                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
12239                 UNLOCK_ZONE(zone);
12240         } else {
12241                 isc_boolean_t use_ixfr = ISC_TRUE;
12242                 if (peer != NULL &&
12243                     dns_peer_getrequestixfr(peer, &use_ixfr) ==
12244                     ISC_R_SUCCESS) {
12245                         ; /* Using peer setting */
12246                 } else {
12247                         use_ixfr = zone->view->requestixfr;
12248                 }
12249                 if (use_ixfr == ISC_FALSE) {
12250                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12251                                      "IXFR disabled, requesting %sAXFR from %s",
12252                                      soa_before, master);
12253                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12254                                 xfrtype = dns_rdatatype_soa;
12255                         else
12256                                 xfrtype = dns_rdatatype_axfr;
12257                 } else {
12258                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12259                                      "requesting IXFR from %s", master);
12260                         xfrtype = dns_rdatatype_ixfr;
12261                 }
12262         }
12263
12264         /*
12265          * Determine if we should attempt to sign the request with TSIG.
12266          */
12267         result = ISC_R_NOTFOUND;
12268         /*
12269          * First, look for a tsig key in the master statement, then
12270          * try for a server key.
12271          */
12272         if ((zone->masterkeynames != NULL) &&
12273             (zone->masterkeynames[zone->curmaster] != NULL)) {
12274                 dns_view_t *view = dns_zone_getview(zone);
12275                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12276                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
12277         }
12278         if (zone->tsigkey == NULL)
12279                 result = dns_view_getpeertsig(zone->view, &masterip,
12280                                               &zone->tsigkey);
12281
12282         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12283                 dns_zone_log(zone, ISC_LOG_ERROR,
12284                              "could not get TSIG key for zone transfer: %s",
12285                              isc_result_totext(result));
12286         }
12287
12288         LOCK_ZONE(zone);
12289         masteraddr = zone->masteraddr;
12290         sourceaddr = zone->sourceaddr;
12291         UNLOCK_ZONE(zone);
12292         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
12293         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
12294                                    zone->tsigkey, zone->mctx,
12295                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
12296                                    zone->task, zone_xfrdone, &zone->xfr);
12297         if (result == ISC_R_SUCCESS) {
12298                 LOCK_ZONE(zone);
12299                 if (xfrtype == dns_rdatatype_axfr) {
12300                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12301                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
12302                         else
12303                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
12304                 } else if (xfrtype == dns_rdatatype_ixfr) {
12305                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12306                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
12307                         else
12308                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
12309                 }
12310                 UNLOCK_ZONE(zone);
12311         }
12312  cleanup:
12313         /*
12314          * Any failure in this function is handled like a failed
12315          * zone transfer.  This ensures that we get removed from
12316          * zmgr->xfrin_in_progress.
12317          */
12318         if (result != ISC_R_SUCCESS)
12319                 zone_xfrdone(zone, result);
12320
12321         isc_event_free(&event);
12322 }
12323
12324 /*
12325  * Update forwarding support.
12326  */
12327
12328 static void
12329 forward_destroy(dns_forward_t *forward) {
12330
12331         forward->magic = 0;
12332         if (forward->request != NULL)
12333                 dns_request_destroy(&forward->request);
12334         if (forward->msgbuf != NULL)
12335                 isc_buffer_free(&forward->msgbuf);
12336         if (forward->zone != NULL) {
12337                 LOCK(&forward->zone->lock);
12338                 if (ISC_LINK_LINKED(forward, link))
12339                         ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
12340                 UNLOCK(&forward->zone->lock);
12341                 dns_zone_idetach(&forward->zone);
12342         }
12343         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
12344 }
12345
12346 static isc_result_t
12347 sendtomaster(dns_forward_t *forward) {
12348         isc_result_t result;
12349         isc_sockaddr_t src;
12350
12351         LOCK_ZONE(forward->zone);
12352
12353         if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
12354                 UNLOCK_ZONE(forward->zone);
12355                 return (ISC_R_CANCELED);
12356         }
12357
12358         if (forward->which >= forward->zone->masterscnt) {
12359                 UNLOCK_ZONE(forward->zone);
12360                 return (ISC_R_NOMORE);
12361         }
12362
12363         forward->addr = forward->zone->masters[forward->which];
12364         /*
12365          * Always use TCP regardless of whether the original update
12366          * used TCP.
12367          * XXX The timeout may but a bit small if we are far down a
12368          * transfer graph and the master has to try several masters.
12369          */
12370         switch (isc_sockaddr_pf(&forward->addr)) {
12371         case PF_INET:
12372                 src = forward->zone->xfrsource4;
12373                 break;
12374         case PF_INET6:
12375                 src = forward->zone->xfrsource6;
12376                 break;
12377         default:
12378                 result = ISC_R_NOTIMPLEMENTED;
12379                 goto unlock;
12380         }
12381         result = dns_request_createraw(forward->zone->view->requestmgr,
12382                                        forward->msgbuf,
12383                                        &src, &forward->addr,
12384                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
12385                                        forward->zone->task,
12386                                        forward_callback, forward,
12387                                        &forward->request);
12388         if (result == ISC_R_SUCCESS) {
12389                 if (!ISC_LINK_LINKED(forward, link))
12390                         ISC_LIST_APPEND(forward->zone->forwards, forward, link);
12391         }
12392
12393  unlock:
12394         UNLOCK_ZONE(forward->zone);
12395         return (result);
12396 }
12397
12398 static void
12399 forward_callback(isc_task_t *task, isc_event_t *event) {
12400         const char me[] = "forward_callback";
12401         dns_requestevent_t *revent = (dns_requestevent_t *)event;
12402         dns_message_t *msg = NULL;
12403         char master[ISC_SOCKADDR_FORMATSIZE];
12404         isc_result_t result;
12405         dns_forward_t *forward;
12406         dns_zone_t *zone;
12407
12408         UNUSED(task);
12409
12410         forward = revent->ev_arg;
12411         INSIST(DNS_FORWARD_VALID(forward));
12412         zone = forward->zone;
12413         INSIST(DNS_ZONE_VALID(zone));
12414
12415         ENTER;
12416
12417         isc_sockaddr_format(&forward->addr, master, sizeof(master));
12418
12419         if (revent->result != ISC_R_SUCCESS) {
12420                 dns_zone_log(zone, ISC_LOG_INFO,
12421                              "could not forward dynamic update to %s: %s",
12422                              master, dns_result_totext(revent->result));
12423                 goto next_master;
12424         }
12425
12426         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12427         if (result != ISC_R_SUCCESS)
12428                 goto next_master;
12429
12430         result = dns_request_getresponse(revent->request, msg,
12431                                          DNS_MESSAGEPARSE_PRESERVEORDER |
12432                                          DNS_MESSAGEPARSE_CLONEBUFFER);
12433         if (result != ISC_R_SUCCESS)
12434                 goto next_master;
12435
12436         switch (msg->rcode) {
12437         /*
12438          * Pass these rcodes back to client.
12439          */
12440         case dns_rcode_noerror:
12441         case dns_rcode_yxdomain:
12442         case dns_rcode_yxrrset:
12443         case dns_rcode_nxrrset:
12444         case dns_rcode_refused:
12445         case dns_rcode_nxdomain:
12446                 break;
12447
12448         /* These should not occur if the masters/zone are valid. */
12449         case dns_rcode_notzone:
12450         case dns_rcode_notauth: {
12451                 char rcode[128];
12452                 isc_buffer_t rb;
12453
12454                 isc_buffer_init(&rb, rcode, sizeof(rcode));
12455                 (void)dns_rcode_totext(msg->rcode, &rb);
12456                 dns_zone_log(zone, ISC_LOG_WARNING,
12457                              "forwarding dynamic update: "
12458                              "unexpected response: master %s returned: %.*s",
12459                              master, (int)rb.used, rcode);
12460                 goto next_master;
12461         }
12462
12463         /* Try another server for these rcodes. */
12464         case dns_rcode_formerr:
12465         case dns_rcode_servfail:
12466         case dns_rcode_notimp:
12467         case dns_rcode_badvers:
12468         default:
12469                 goto next_master;
12470         }
12471
12472         /* call callback */
12473         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
12474         msg = NULL;
12475         dns_request_destroy(&forward->request);
12476         forward_destroy(forward);
12477         isc_event_free(&event);
12478         return;
12479
12480  next_master:
12481         if (msg != NULL)
12482                 dns_message_destroy(&msg);
12483         isc_event_free(&event);
12484         forward->which++;
12485         dns_request_destroy(&forward->request);
12486         result = sendtomaster(forward);
12487         if (result != ISC_R_SUCCESS) {
12488                 /* call callback */
12489                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
12490                              "exhausted dynamic update forwarder list");
12491                 (forward->callback)(forward->callback_arg, result, NULL);
12492                 forward_destroy(forward);
12493         }
12494 }
12495
12496 isc_result_t
12497 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
12498                        dns_updatecallback_t callback, void *callback_arg)
12499 {
12500         dns_forward_t *forward;
12501         isc_result_t result;
12502         isc_region_t *mr;
12503
12504         REQUIRE(DNS_ZONE_VALID(zone));
12505         REQUIRE(msg != NULL);
12506         REQUIRE(callback != NULL);
12507
12508         forward = isc_mem_get(zone->mctx, sizeof(*forward));
12509         if (forward == NULL)
12510                 return (ISC_R_NOMEMORY);
12511
12512         forward->request = NULL;
12513         forward->zone = NULL;
12514         forward->msgbuf = NULL;
12515         forward->which = 0;
12516         forward->mctx = 0;
12517         forward->callback = callback;
12518         forward->callback_arg = callback_arg;
12519         ISC_LINK_INIT(forward, link);
12520         forward->magic = FORWARD_MAGIC;
12521
12522         mr = dns_message_getrawmessage(msg);
12523         if (mr == NULL) {
12524                 result = ISC_R_UNEXPECTEDEND;
12525                 goto cleanup;
12526         }
12527
12528         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
12529         if (result != ISC_R_SUCCESS)
12530                 goto cleanup;
12531         result = isc_buffer_copyregion(forward->msgbuf, mr);
12532         if (result != ISC_R_SUCCESS)
12533                 goto cleanup;
12534
12535         isc_mem_attach(zone->mctx, &forward->mctx);
12536         dns_zone_iattach(zone, &forward->zone);
12537         result = sendtomaster(forward);
12538
12539  cleanup:
12540         if (result != ISC_R_SUCCESS) {
12541                 forward_destroy(forward);
12542         }
12543         return (result);
12544 }
12545
12546 isc_result_t
12547 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
12548         REQUIRE(DNS_ZONE_VALID(zone));
12549         REQUIRE(next != NULL && *next == NULL);
12550
12551         *next = ISC_LIST_NEXT(zone, link);
12552         if (*next == NULL)
12553                 return (ISC_R_NOMORE);
12554         else
12555                 return (ISC_R_SUCCESS);
12556 }
12557
12558 isc_result_t
12559 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
12560         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12561         REQUIRE(first != NULL && *first == NULL);
12562
12563         *first = ISC_LIST_HEAD(zmgr->zones);
12564         if (*first == NULL)
12565                 return (ISC_R_NOMORE);
12566         else
12567                 return (ISC_R_SUCCESS);
12568 }
12569
12570 /***
12571  ***    Zone manager.
12572  ***/
12573
12574 isc_result_t
12575 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
12576                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
12577                    dns_zonemgr_t **zmgrp)
12578 {
12579         dns_zonemgr_t *zmgr;
12580         isc_result_t result;
12581         isc_interval_t interval;
12582
12583         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
12584         if (zmgr == NULL)
12585                 return (ISC_R_NOMEMORY);
12586         zmgr->mctx = NULL;
12587         zmgr->refs = 1;
12588         isc_mem_attach(mctx, &zmgr->mctx);
12589         zmgr->taskmgr = taskmgr;
12590         zmgr->timermgr = timermgr;
12591         zmgr->socketmgr = socketmgr;
12592         zmgr->zonetasks = NULL;
12593         zmgr->task = NULL;
12594         zmgr->rl = NULL;
12595         ISC_LIST_INIT(zmgr->zones);
12596         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
12597         ISC_LIST_INIT(zmgr->xfrin_in_progress);
12598         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
12599         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
12600         if (result != ISC_R_SUCCESS)
12601                 goto free_mem;
12602
12603         zmgr->transfersin = 10;
12604         zmgr->transfersperns = 2;
12605
12606         /* Unreachable lock. */
12607         result = isc_rwlock_init(&zmgr->urlock, 0, 0);
12608         if (result != ISC_R_SUCCESS)
12609                 goto free_rwlock;
12610
12611         /* Create a single task for queueing of SOA queries. */
12612         result = isc_task_create(taskmgr, 1, &zmgr->task);
12613         if (result != ISC_R_SUCCESS)
12614                 goto free_urlock;
12615
12616         isc_task_setname(zmgr->task, "zmgr", zmgr);
12617         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
12618                                         &zmgr->rl);
12619         if (result != ISC_R_SUCCESS)
12620                 goto free_task;
12621
12622         /* default to 20 refresh queries / notifies per second. */
12623         isc_interval_set(&interval, 0, 1000000000/2);
12624         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
12625         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12626         isc_ratelimiter_setpertic(zmgr->rl, 10);
12627
12628         zmgr->iolimit = 1;
12629         zmgr->ioactive = 0;
12630         ISC_LIST_INIT(zmgr->high);
12631         ISC_LIST_INIT(zmgr->low);
12632
12633         result = isc_mutex_init(&zmgr->iolock);
12634         if (result != ISC_R_SUCCESS)
12635                 goto free_rl;
12636
12637         zmgr->magic = ZONEMGR_MAGIC;
12638
12639         *zmgrp = zmgr;
12640         return (ISC_R_SUCCESS);
12641
12642 #if 0
12643  free_iolock:
12644         DESTROYLOCK(&zmgr->iolock);
12645 #endif
12646  free_rl:
12647         isc_ratelimiter_detach(&zmgr->rl);
12648  free_task:
12649         isc_task_detach(&zmgr->task);
12650  free_urlock:
12651         isc_rwlock_destroy(&zmgr->urlock);
12652  free_rwlock:
12653         isc_rwlock_destroy(&zmgr->rwlock);
12654  free_mem:
12655         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
12656         isc_mem_detach(&mctx);
12657         return (result);
12658 }
12659
12660 isc_result_t
12661 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12662         isc_result_t result;
12663
12664         REQUIRE(DNS_ZONE_VALID(zone));
12665         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12666
12667         if (zmgr->zonetasks == NULL)
12668                 return (ISC_R_FAILURE);
12669
12670         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12671         LOCK_ZONE(zone);
12672         REQUIRE(zone->task == NULL);
12673         REQUIRE(zone->timer == NULL);
12674         REQUIRE(zone->zmgr == NULL);
12675
12676         isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
12677
12678         /*
12679          * Set the task name.  The tag will arbitrarily point to one
12680          * of the zones sharing the task (in practice, the one
12681          * to be managed last).
12682          */
12683         isc_task_setname(zone->task, "zone", zone);
12684
12685         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
12686                                   NULL, NULL,
12687                                   zone->task, zone_timer, zone,
12688                                   &zone->timer);
12689
12690         if (result != ISC_R_SUCCESS)
12691                 goto cleanup_task;
12692
12693         /*
12694          * The timer "holds" a iref.
12695          */
12696         zone->irefs++;
12697         INSIST(zone->irefs != 0);
12698
12699         ISC_LIST_APPEND(zmgr->zones, zone, link);
12700         zone->zmgr = zmgr;
12701         zmgr->refs++;
12702
12703         goto unlock;
12704
12705  cleanup_task:
12706         isc_task_detach(&zone->task);
12707
12708  unlock:
12709         UNLOCK_ZONE(zone);
12710         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12711         return (result);
12712 }
12713
12714 void
12715 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12716         isc_boolean_t free_now = ISC_FALSE;
12717
12718         REQUIRE(DNS_ZONE_VALID(zone));
12719         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12720         REQUIRE(zone->zmgr == zmgr);
12721
12722         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12723         LOCK_ZONE(zone);
12724
12725         ISC_LIST_UNLINK(zmgr->zones, zone, link);
12726         zone->zmgr = NULL;
12727         zmgr->refs--;
12728         if (zmgr->refs == 0)
12729                 free_now = ISC_TRUE;
12730
12731         UNLOCK_ZONE(zone);
12732         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12733
12734         if (free_now)
12735                 zonemgr_free(zmgr);
12736         ENSURE(zone->zmgr == NULL);
12737 }
12738
12739 void
12740 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
12741         REQUIRE(DNS_ZONEMGR_VALID(source));
12742         REQUIRE(target != NULL && *target == NULL);
12743
12744         RWLOCK(&source->rwlock, isc_rwlocktype_write);
12745         REQUIRE(source->refs > 0);
12746         source->refs++;
12747         INSIST(source->refs > 0);
12748         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
12749         *target = source;
12750 }
12751
12752 void
12753 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
12754         dns_zonemgr_t *zmgr;
12755         isc_boolean_t free_now = ISC_FALSE;
12756
12757         REQUIRE(zmgrp != NULL);
12758         zmgr = *zmgrp;
12759         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12760
12761         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12762         zmgr->refs--;
12763         if (zmgr->refs == 0)
12764                 free_now = ISC_TRUE;
12765         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12766
12767         if (free_now)
12768                 zonemgr_free(zmgr);
12769         *zmgrp = NULL;
12770 }
12771
12772 isc_result_t
12773 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
12774         dns_zone_t *p;
12775
12776         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12777
12778         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12779         for (p = ISC_LIST_HEAD(zmgr->zones);
12780              p != NULL;
12781              p = ISC_LIST_NEXT(p, link))
12782         {
12783                 dns_zone_maintenance(p);
12784         }
12785         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12786
12787         /*
12788          * Recent configuration changes may have increased the
12789          * amount of available transfers quota.  Make sure any
12790          * transfers currently blocked on quota get started if
12791          * possible.
12792          */
12793         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12794         zmgr_resume_xfrs(zmgr, ISC_TRUE);
12795         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12796         return (ISC_R_SUCCESS);
12797 }
12798
12799 void
12800 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
12801
12802         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12803
12804         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12805         zmgr_resume_xfrs(zmgr, ISC_TRUE);
12806         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12807 }
12808
12809 void
12810 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
12811         dns_zone_t *zone;
12812
12813         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12814
12815         isc_ratelimiter_shutdown(zmgr->rl);
12816
12817         if (zmgr->task != NULL)
12818                 isc_task_destroy(&zmgr->task);
12819         if (zmgr->zonetasks != NULL)
12820                 isc_taskpool_destroy(&zmgr->zonetasks);
12821
12822         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12823         for (zone = ISC_LIST_HEAD(zmgr->zones);
12824              zone != NULL;
12825              zone = ISC_LIST_NEXT(zone, link))
12826         {
12827                 LOCK_ZONE(zone);
12828                 forward_cancel(zone);
12829                 UNLOCK_ZONE(zone);
12830         }
12831         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12832 }
12833
12834 isc_result_t
12835 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
12836         isc_result_t result;
12837         int ntasks = num_zones / 100;
12838         isc_taskpool_t *pool = NULL;
12839
12840         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12841
12842         /*
12843          * For anything fewer than 1000 zones we use 10 tasks in
12844          * the task pool.  More than that, and we'll scale at one
12845          * task per 100 zones.
12846          */
12847         if (ntasks < 10)
12848                 ntasks = 10;
12849
12850         /* Create or resize the zone task pool. */
12851         if (zmgr->zonetasks == NULL)
12852                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
12853                                              ntasks, 2, &pool);
12854         else
12855                 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
12856
12857         if (result == ISC_R_SUCCESS)
12858                 zmgr->zonetasks = pool;
12859
12860         return (result);
12861 }
12862
12863 static void
12864 zonemgr_free(dns_zonemgr_t *zmgr) {
12865         isc_mem_t *mctx;
12866
12867         INSIST(zmgr->refs == 0);
12868         INSIST(ISC_LIST_EMPTY(zmgr->zones));
12869
12870         zmgr->magic = 0;
12871
12872         DESTROYLOCK(&zmgr->iolock);
12873         isc_ratelimiter_detach(&zmgr->rl);
12874
12875         isc_rwlock_destroy(&zmgr->urlock);
12876         isc_rwlock_destroy(&zmgr->rwlock);
12877         mctx = zmgr->mctx;
12878         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
12879         isc_mem_detach(&mctx);
12880 }
12881
12882 void
12883 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
12884         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12885
12886         zmgr->transfersin = value;
12887 }
12888
12889 isc_uint32_t
12890 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
12891         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12892
12893         return (zmgr->transfersin);
12894 }
12895
12896 void
12897 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
12898         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12899
12900         zmgr->transfersperns = value;
12901 }
12902
12903 isc_uint32_t
12904 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
12905         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12906
12907         return (zmgr->transfersperns);
12908 }
12909
12910 /*
12911  * Try to start a new incoming zone transfer to fill a quota
12912  * slot that was just vacated.
12913  *
12914  * Requires:
12915  *      The zone manager is locked by the caller.
12916  */
12917 static void
12918 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
12919         dns_zone_t *zone;
12920         dns_zone_t *next;
12921
12922         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
12923              zone != NULL;
12924              zone = next)
12925         {
12926                 isc_result_t result;
12927                 next = ISC_LIST_NEXT(zone, statelink);
12928                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
12929                 if (result == ISC_R_SUCCESS) {
12930                         if (multi)
12931                                 continue;
12932                         /*
12933                          * We successfully filled the slot.  We're done.
12934                          */
12935                         break;
12936                 } else if (result == ISC_R_QUOTA) {
12937                         /*
12938                          * Not enough quota.  This is probably the per-server
12939                          * quota, because we usually get called when a unit of
12940                          * global quota has just been freed.  Try the next
12941                          * zone, it may succeed if it uses another master.
12942                          */
12943                         continue;
12944                 } else {
12945                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12946                                      "starting zone transfer: %s",
12947                                      isc_result_totext(result));
12948                         break;
12949                 }
12950         }
12951 }
12952
12953 /*
12954  * Try to start an incoming zone transfer for 'zone', quota permitting.
12955  *
12956  * Requires:
12957  *      The zone manager is locked by the caller.
12958  *
12959  * Returns:
12960  *      ISC_R_SUCCESS   There was enough quota and we attempted to
12961  *                      start a transfer.  zone_xfrdone() has been or will
12962  *                      be called.
12963  *      ISC_R_QUOTA     Not enough quota.
12964  *      Others          Failure.
12965  */
12966 static isc_result_t
12967 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12968         dns_peer_t *peer = NULL;
12969         isc_netaddr_t masterip;
12970         isc_uint32_t nxfrsin, nxfrsperns;
12971         dns_zone_t *x;
12972         isc_uint32_t maxtransfersin, maxtransfersperns;
12973         isc_event_t *e;
12974
12975         /*
12976          * If we are exiting just pretend we got quota so the zone will
12977          * be cleaned up in the zone's task context.
12978          */
12979         LOCK_ZONE(zone);
12980         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12981                 UNLOCK_ZONE(zone);
12982                 goto gotquota;
12983         }
12984
12985         /*
12986          * Find any configured information about the server we'd
12987          * like to transfer this zone from.
12988          */
12989         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12990         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
12991         UNLOCK_ZONE(zone);
12992
12993         /*
12994          * Determine the total maximum number of simultaneous
12995          * transfers allowed, and the maximum for this specific
12996          * master.
12997          */
12998         maxtransfersin = zmgr->transfersin;
12999         maxtransfersperns = zmgr->transfersperns;
13000         if (peer != NULL)
13001                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
13002
13003         /*
13004          * Count the total number of transfers that are in progress,
13005          * and the number of transfers in progress from this master.
13006          * We linearly scan a list of all transfers; if this turns
13007          * out to be too slow, we could hash on the master address.
13008          */
13009         nxfrsin = nxfrsperns = 0;
13010         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
13011              x != NULL;
13012              x = ISC_LIST_NEXT(x, statelink))
13013         {
13014                 isc_netaddr_t xip;
13015
13016                 LOCK_ZONE(x);
13017                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
13018                 UNLOCK_ZONE(x);
13019
13020                 nxfrsin++;
13021                 if (isc_netaddr_equal(&xip, &masterip))
13022                         nxfrsperns++;
13023         }
13024
13025         /* Enforce quota. */
13026         if (nxfrsin >= maxtransfersin)
13027                 return (ISC_R_QUOTA);
13028
13029         if (nxfrsperns >= maxtransfersperns)
13030                 return (ISC_R_QUOTA);
13031
13032  gotquota:
13033         /*
13034          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
13035          * list and send it an event to let it start the actual transfer in the
13036          * context of its own task.
13037          */
13038         e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
13039                                got_transfer_quota, zone, sizeof(isc_event_t));
13040         if (e == NULL)
13041                 return (ISC_R_NOMEMORY);
13042
13043         LOCK_ZONE(zone);
13044         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
13045         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
13046         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
13047         zone->statelist = &zmgr->xfrin_in_progress;
13048         isc_task_send(zone->task, &e);
13049         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
13050         UNLOCK_ZONE(zone);
13051
13052         return (ISC_R_SUCCESS);
13053 }
13054
13055 void
13056 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
13057
13058         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13059         REQUIRE(iolimit > 0);
13060
13061         zmgr->iolimit = iolimit;
13062 }
13063
13064 isc_uint32_t
13065 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
13066
13067         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13068
13069         return (zmgr->iolimit);
13070 }
13071
13072 /*
13073  * Get permission to request a file handle from the OS.
13074  * An event will be sent to action when one is available.
13075  * There are two queues available (high and low), the high
13076  * queue will be serviced before the low one.
13077  *
13078  * zonemgr_putio() must be called after the event is delivered to
13079  * 'action'.
13080  */
13081
13082 static isc_result_t
13083 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
13084               isc_task_t *task, isc_taskaction_t action, void *arg,
13085               dns_io_t **iop)
13086 {
13087         dns_io_t *io;
13088         isc_boolean_t queue;
13089
13090         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13091         REQUIRE(iop != NULL && *iop == NULL);
13092
13093         io = isc_mem_get(zmgr->mctx, sizeof(*io));
13094         if (io == NULL)
13095                 return (ISC_R_NOMEMORY);
13096         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
13097                                        action, arg, sizeof(*io->event));
13098         if (io->event == NULL) {
13099                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
13100                 return (ISC_R_NOMEMORY);
13101         }
13102         io->zmgr = zmgr;
13103         io->high = high;
13104         io->task = NULL;
13105         isc_task_attach(task, &io->task);
13106         ISC_LINK_INIT(io, link);
13107         io->magic = IO_MAGIC;
13108
13109         LOCK(&zmgr->iolock);
13110         zmgr->ioactive++;
13111         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
13112         if (queue) {
13113                 if (io->high)
13114                         ISC_LIST_APPEND(zmgr->high, io, link);
13115                 else
13116                         ISC_LIST_APPEND(zmgr->low, io, link);
13117         }
13118         UNLOCK(&zmgr->iolock);
13119         *iop = io;
13120
13121         if (!queue) {
13122                 isc_task_send(io->task, &io->event);
13123         }
13124         return (ISC_R_SUCCESS);
13125 }
13126
13127 static void
13128 zonemgr_putio(dns_io_t **iop) {
13129         dns_io_t *io;
13130         dns_io_t *next;
13131         dns_zonemgr_t *zmgr;
13132
13133         REQUIRE(iop != NULL);
13134         io = *iop;
13135         REQUIRE(DNS_IO_VALID(io));
13136
13137         *iop = NULL;
13138
13139         INSIST(!ISC_LINK_LINKED(io, link));
13140         INSIST(io->event == NULL);
13141
13142         zmgr = io->zmgr;
13143         isc_task_detach(&io->task);
13144         io->magic = 0;
13145         isc_mem_put(zmgr->mctx, io, sizeof(*io));
13146
13147         LOCK(&zmgr->iolock);
13148         INSIST(zmgr->ioactive > 0);
13149         zmgr->ioactive--;
13150         next = HEAD(zmgr->high);
13151         if (next == NULL)
13152                 next = HEAD(zmgr->low);
13153         if (next != NULL) {
13154                 if (next->high)
13155                         ISC_LIST_UNLINK(zmgr->high, next, link);
13156                 else
13157                         ISC_LIST_UNLINK(zmgr->low, next, link);
13158                 INSIST(next->event != NULL);
13159         }
13160         UNLOCK(&zmgr->iolock);
13161         if (next != NULL)
13162                 isc_task_send(next->task, &next->event);
13163 }
13164
13165 static void
13166 zonemgr_cancelio(dns_io_t *io) {
13167         isc_boolean_t send_event = ISC_FALSE;
13168
13169         REQUIRE(DNS_IO_VALID(io));
13170
13171         /*
13172          * If we are queued to be run then dequeue.
13173          */
13174         LOCK(&io->zmgr->iolock);
13175         if (ISC_LINK_LINKED(io, link)) {
13176                 if (io->high)
13177                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
13178                 else
13179                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
13180
13181                 send_event = ISC_TRUE;
13182                 INSIST(io->event != NULL);
13183         }
13184         UNLOCK(&io->zmgr->iolock);
13185         if (send_event) {
13186                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
13187                 isc_task_send(io->task, &io->event);
13188         }
13189 }
13190
13191 static void
13192 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
13193         char *buf;
13194         int buflen;
13195         isc_result_t result;
13196
13197         buflen = strlen(path) + strlen(templat) + 2;
13198
13199         buf = isc_mem_get(zone->mctx, buflen);
13200         if (buf == NULL)
13201                 return;
13202
13203         result = isc_file_template(path, templat, buf, buflen);
13204         if (result != ISC_R_SUCCESS)
13205                 goto cleanup;
13206
13207         result = isc_file_renameunique(path, buf);
13208         if (result != ISC_R_SUCCESS)
13209                 goto cleanup;
13210
13211         dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
13212                      "renaming file to '%s' for failure analysis and "
13213                      "retransferring.", path, buf);
13214
13215  cleanup:
13216         isc_mem_put(zone->mctx, buf, buflen);
13217 }
13218
13219 #if 0
13220 /* Hook for ondestroy notification from a database. */
13221
13222 static void
13223 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
13224         dns_db_t *db = event->sender;
13225         UNUSED(task);
13226
13227         isc_event_free(&event);
13228
13229         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13230                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13231                       "database (%p) destroyed", (void*) db);
13232 }
13233 #endif
13234
13235 void
13236 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
13237         isc_interval_t interval;
13238         isc_uint32_t s, ns;
13239         isc_uint32_t pertic;
13240         isc_result_t result;
13241
13242         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13243
13244         if (value == 0)
13245                 value = 1;
13246
13247         if (value == 1) {
13248                 s = 1;
13249                 ns = 0;
13250                 pertic = 1;
13251         } else if (value <= 10) {
13252                 s = 0;
13253                 ns = 1000000000 / value;
13254                 pertic = 1;
13255         } else {
13256                 s = 0;
13257                 ns = (1000000000 / value) * 10;
13258                 pertic = 10;
13259         }
13260
13261         isc_interval_set(&interval, s, ns);
13262         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
13263         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13264         isc_ratelimiter_setpertic(zmgr->rl, pertic);
13265
13266         zmgr->serialqueryrate = value;
13267 }
13268
13269 unsigned int
13270 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
13271         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13272
13273         return (zmgr->serialqueryrate);
13274 }
13275
13276 isc_boolean_t
13277 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13278                         isc_sockaddr_t *local, isc_time_t *now)
13279 {
13280         unsigned int i;
13281         isc_rwlocktype_t locktype;
13282         isc_result_t result;
13283         isc_uint32_t seconds = isc_time_seconds(now);
13284
13285         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13286
13287         locktype = isc_rwlocktype_read;
13288         RWLOCK(&zmgr->urlock, locktype);
13289         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13290                 if (zmgr->unreachable[i].expire >= seconds &&
13291                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13292                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
13293                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
13294                         if (result == ISC_R_SUCCESS) {
13295                                 locktype = isc_rwlocktype_write;
13296                                 zmgr->unreachable[i].last = seconds;
13297                         }
13298                         break;
13299                 }
13300         }
13301         RWUNLOCK(&zmgr->urlock, locktype);
13302         return (ISC_TF(i < UNREACH_CHACHE_SIZE));
13303 }
13304
13305 void
13306 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13307                            isc_sockaddr_t *local)
13308 {
13309         unsigned int i;
13310         isc_rwlocktype_t locktype;
13311         isc_result_t result;
13312
13313         char master[ISC_SOCKADDR_FORMATSIZE];
13314         char source[ISC_SOCKADDR_FORMATSIZE];
13315
13316         isc_sockaddr_format(remote, master, sizeof(master));
13317         isc_sockaddr_format(local, source, sizeof(source));
13318
13319         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13320
13321         locktype = isc_rwlocktype_read;
13322         RWLOCK(&zmgr->urlock, locktype);
13323         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13324                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13325                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
13326                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
13327                         if (result == ISC_R_SUCCESS) {
13328                                 locktype = isc_rwlocktype_write;
13329                                 zmgr->unreachable[i].expire = 0;
13330                                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13331                                               DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
13332                                               "master %s (source %s) deleted "
13333                                               "from unreachable cache",
13334                                               master, source);
13335                         }
13336                         break;
13337                 }
13338         }
13339         RWUNLOCK(&zmgr->urlock, locktype);
13340 }
13341
13342 void
13343 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13344                            isc_sockaddr_t *local, isc_time_t *now)
13345 {
13346         isc_uint32_t seconds = isc_time_seconds(now);
13347         isc_uint32_t last = seconds;
13348         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
13349
13350         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13351
13352         RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
13353         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13354                 /* Existing entry? */
13355                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13356                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
13357                         break;
13358                 /* Empty slot? */
13359                 if (zmgr->unreachable[i].expire < seconds)
13360                         slot = i;
13361                 /* Least recently used slot? */
13362                 if (zmgr->unreachable[i].last < last) {
13363                         last = zmgr->unreachable[i].last;
13364                         oldest = i;
13365                 }
13366         }
13367         if (i < UNREACH_CHACHE_SIZE) {
13368                 /*
13369                  * Found a existing entry.  Update the expire timer and
13370                  * last usage timestamps.
13371                  */
13372                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
13373                 zmgr->unreachable[i].last = seconds;
13374         } else if (slot != UNREACH_CHACHE_SIZE) {
13375                 /*
13376                  * Found a empty slot. Add a new entry to the cache.
13377                  */
13378                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
13379                 zmgr->unreachable[slot].last = seconds;
13380                 zmgr->unreachable[slot].remote = *remote;
13381                 zmgr->unreachable[slot].local = *local;
13382         } else {
13383                 /*
13384                  * Replace the least recently used entry in the cache.
13385                  */
13386                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
13387                 zmgr->unreachable[oldest].last = seconds;
13388                 zmgr->unreachable[oldest].remote = *remote;
13389                 zmgr->unreachable[oldest].local = *local;
13390         }
13391         RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
13392 }
13393
13394 void
13395 dns_zone_forcereload(dns_zone_t *zone) {
13396         REQUIRE(DNS_ZONE_VALID(zone));
13397
13398         if (zone->type == dns_zone_master)
13399                 return;
13400
13401         LOCK_ZONE(zone);
13402         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13403         UNLOCK_ZONE(zone);
13404         dns_zone_refresh(zone);
13405 }
13406
13407 isc_boolean_t
13408 dns_zone_isforced(dns_zone_t *zone) {
13409         REQUIRE(DNS_ZONE_VALID(zone));
13410
13411         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
13412 }
13413
13414 isc_result_t
13415 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
13416         /*
13417          * This function is obsoleted.
13418          */
13419         UNUSED(zone);
13420         UNUSED(on);
13421         return (ISC_R_NOTIMPLEMENTED);
13422 }
13423
13424 isc_uint64_t *
13425 dns_zone_getstatscounters(dns_zone_t *zone) {
13426         /*
13427          * This function is obsoleted.
13428          */
13429         UNUSED(zone);
13430         return (NULL);
13431 }
13432
13433 void
13434 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
13435         REQUIRE(DNS_ZONE_VALID(zone));
13436         REQUIRE(zone->stats == NULL);
13437
13438         LOCK_ZONE(zone);
13439         zone->stats = NULL;
13440         isc_stats_attach(stats, &zone->stats);
13441         UNLOCK_ZONE(zone);
13442 }
13443
13444 void
13445 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
13446         REQUIRE(DNS_ZONE_VALID(zone));
13447
13448         LOCK_ZONE(zone);
13449         if (zone->requeststats_on && stats == NULL)
13450                 zone->requeststats_on = ISC_FALSE;
13451         else if (!zone->requeststats_on && stats != NULL) {
13452                 if (zone->requeststats == NULL) {
13453                         isc_stats_attach(stats, &zone->requeststats);
13454                         zone->requeststats_on = ISC_TRUE;
13455                 }
13456         }
13457         UNLOCK_ZONE(zone);
13458
13459         return;
13460 }
13461
13462 isc_stats_t *
13463 dns_zone_getrequeststats(dns_zone_t *zone) {
13464         /*
13465          * We don't lock zone for efficiency reason.  This is not catastrophic
13466          * because requeststats must always be valid when requeststats_on is
13467          * true.
13468          * Some counters may be incremented while requeststats_on is becoming
13469          * false, or some cannot be incremented just after the statistics are
13470          * installed, but it shouldn't matter much in practice.
13471          */
13472         if (zone->requeststats_on)
13473                 return (zone->requeststats);
13474         else
13475                 return (NULL);
13476 }
13477
13478 void
13479 dns_zone_dialup(dns_zone_t *zone) {
13480
13481         REQUIRE(DNS_ZONE_VALID(zone));
13482
13483         zone_debuglog(zone, "dns_zone_dialup", 3,
13484                       "notify = %d, refresh = %d",
13485                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
13486                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
13487
13488         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
13489                 dns_zone_notify(zone);
13490         if (zone->type != dns_zone_master &&
13491             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
13492                 dns_zone_refresh(zone);
13493 }
13494
13495 void
13496 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
13497         REQUIRE(DNS_ZONE_VALID(zone));
13498
13499         LOCK_ZONE(zone);
13500         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
13501                          DNS_ZONEFLG_DIALREFRESH |
13502                          DNS_ZONEFLG_NOREFRESH);
13503         switch (dialup) {
13504         case dns_dialuptype_no:
13505                 break;
13506         case dns_dialuptype_yes:
13507                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
13508                                  DNS_ZONEFLG_DIALREFRESH |
13509                                  DNS_ZONEFLG_NOREFRESH));
13510                 break;
13511         case dns_dialuptype_notify:
13512                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13513                 break;
13514         case dns_dialuptype_notifypassive:
13515                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13516                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13517                 break;
13518         case dns_dialuptype_refresh:
13519                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
13520                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13521                 break;
13522         case dns_dialuptype_passive:
13523                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13524                 break;
13525         default:
13526                 INSIST(0);
13527         }
13528         UNLOCK_ZONE(zone);
13529 }
13530
13531 isc_result_t
13532 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
13533         isc_result_t result = ISC_R_SUCCESS;
13534
13535         REQUIRE(DNS_ZONE_VALID(zone));
13536
13537         LOCK_ZONE(zone);
13538         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
13539         UNLOCK_ZONE(zone);
13540
13541         return (result);
13542 }
13543
13544 const char *
13545 dns_zone_getkeydirectory(dns_zone_t *zone) {
13546         REQUIRE(DNS_ZONE_VALID(zone));
13547
13548         return (zone->keydirectory);
13549 }
13550
13551 unsigned int
13552 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
13553         dns_zone_t *zone;
13554         unsigned int count = 0;
13555
13556         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13557
13558         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13559         switch (state) {
13560         case DNS_ZONESTATE_XFERRUNNING:
13561                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
13562                      zone != NULL;
13563                      zone = ISC_LIST_NEXT(zone, statelink))
13564                         count++;
13565                 break;
13566         case DNS_ZONESTATE_XFERDEFERRED:
13567                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
13568                      zone != NULL;
13569                      zone = ISC_LIST_NEXT(zone, statelink))
13570                         count++;
13571                 break;
13572         case DNS_ZONESTATE_SOAQUERY:
13573                 for (zone = ISC_LIST_HEAD(zmgr->zones);
13574                      zone != NULL;
13575                      zone = ISC_LIST_NEXT(zone, link))
13576                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
13577                                 count++;
13578                 break;
13579         case DNS_ZONESTATE_ANY:
13580                 for (zone = ISC_LIST_HEAD(zmgr->zones);
13581                      zone != NULL;
13582                      zone = ISC_LIST_NEXT(zone, link)) {
13583                         dns_view_t *view = zone->view;
13584                         if (view != NULL && strcmp(view->name, "_bind") == 0)
13585                                 continue;
13586                         count++;
13587                 }
13588                 break;
13589         default:
13590                 INSIST(0);
13591         }
13592
13593         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13594
13595         return (count);
13596 }
13597
13598 isc_result_t
13599 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
13600         isc_boolean_t ok = ISC_TRUE;
13601         isc_boolean_t fail = ISC_FALSE;
13602         char namebuf[DNS_NAME_FORMATSIZE];
13603         char namebuf2[DNS_NAME_FORMATSIZE];
13604         char typebuf[DNS_RDATATYPE_FORMATSIZE];
13605         int level = ISC_LOG_WARNING;
13606         dns_name_t bad;
13607
13608         REQUIRE(DNS_ZONE_VALID(zone));
13609
13610         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
13611                 return (ISC_R_SUCCESS);
13612
13613         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
13614                 level = ISC_LOG_ERROR;
13615                 fail = ISC_TRUE;
13616         }
13617
13618         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
13619         if (!ok) {
13620                 dns_name_format(name, namebuf, sizeof(namebuf));
13621                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13622                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
13623                              dns_result_totext(DNS_R_BADOWNERNAME));
13624                 if (fail)
13625                         return (DNS_R_BADOWNERNAME);
13626         }
13627
13628         dns_name_init(&bad, NULL);
13629         ok = dns_rdata_checknames(rdata, name, &bad);
13630         if (!ok) {
13631                 dns_name_format(name, namebuf, sizeof(namebuf));
13632                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
13633                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13634                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
13635                              namebuf2, dns_result_totext(DNS_R_BADNAME));
13636                 if (fail)
13637                         return (DNS_R_BADNAME);
13638         }
13639
13640         return (ISC_R_SUCCESS);
13641 }
13642
13643 void
13644 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
13645         REQUIRE(DNS_ZONE_VALID(zone));
13646         zone->checkmx = checkmx;
13647 }
13648
13649 void
13650 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
13651         REQUIRE(DNS_ZONE_VALID(zone));
13652         zone->checksrv = checksrv;
13653 }
13654
13655 void
13656 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
13657         REQUIRE(DNS_ZONE_VALID(zone));
13658         zone->checkns = checkns;
13659 }
13660
13661 void
13662 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
13663         REQUIRE(DNS_ZONE_VALID(zone));
13664
13665         LOCK_ZONE(zone);
13666         zone->isself = isself;
13667         zone->isselfarg = arg;
13668         UNLOCK_ZONE(zone);
13669 }
13670
13671 void
13672 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
13673         REQUIRE(DNS_ZONE_VALID(zone));
13674
13675         LOCK_ZONE(zone);
13676         zone->notifydelay = delay;
13677         UNLOCK_ZONE(zone);
13678 }
13679
13680 isc_uint32_t
13681 dns_zone_getnotifydelay(dns_zone_t *zone) {
13682         REQUIRE(DNS_ZONE_VALID(zone));
13683
13684         return (zone->notifydelay);
13685 }
13686
13687 isc_result_t
13688 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
13689                      isc_uint16_t keyid, isc_boolean_t delete)
13690 {
13691         isc_result_t result;
13692         REQUIRE(DNS_ZONE_VALID(zone));
13693
13694         dns_zone_log(zone, ISC_LOG_NOTICE,
13695                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
13696                      algorithm, keyid);
13697         LOCK_ZONE(zone);
13698         result = zone_signwithkey(zone, algorithm, keyid, delete);
13699         UNLOCK_ZONE(zone);
13700
13701         return (result);
13702 }
13703
13704 static const char *hex = "0123456789ABCDEF";
13705
13706 isc_result_t
13707 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
13708         isc_result_t result;
13709         char salt[255*2+1];
13710         unsigned int i, j;
13711
13712         REQUIRE(DNS_ZONE_VALID(zone));
13713
13714         if (nsec3param->salt_length != 0) {
13715                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
13716                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
13717                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
13718                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
13719                 }
13720                 salt[j] = '\0';
13721         } else
13722                 strcpy(salt, "-");
13723         dns_zone_log(zone, ISC_LOG_NOTICE,
13724                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
13725                      nsec3param->hash, nsec3param->iterations,
13726                      salt);
13727         LOCK_ZONE(zone);
13728         result = zone_addnsec3chain(zone, nsec3param);
13729         UNLOCK_ZONE(zone);
13730
13731         return (result);
13732 }
13733
13734 void
13735 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
13736         REQUIRE(DNS_ZONE_VALID(zone));
13737
13738         if (nodes == 0)
13739                 nodes = 1;
13740         zone->nodes = nodes;
13741 }
13742
13743 void
13744 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
13745         REQUIRE(DNS_ZONE_VALID(zone));
13746
13747         /*
13748          * We treat signatures as a signed value so explicitly
13749          * limit its range here.
13750          */
13751         if (signatures > ISC_INT32_MAX)
13752                 signatures = ISC_INT32_MAX;
13753         else if (signatures == 0)
13754                 signatures = 1;
13755         zone->signatures = signatures;
13756 }
13757
13758 void
13759 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
13760         REQUIRE(DNS_ZONE_VALID(zone));
13761         zone->privatetype = type;
13762 }
13763
13764 dns_rdatatype_t
13765 dns_zone_getprivatetype(dns_zone_t *zone) {
13766         REQUIRE(DNS_ZONE_VALID(zone));
13767         return (zone->privatetype);
13768 }
13769
13770 static isc_result_t
13771 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
13772                  isc_boolean_t delete)
13773 {
13774         dns_signing_t *signing;
13775         dns_signing_t *current;
13776         isc_result_t result = ISC_R_SUCCESS;
13777         isc_time_t now;
13778
13779         signing = isc_mem_get(zone->mctx, sizeof *signing);
13780         if (signing == NULL)
13781                 return (ISC_R_NOMEMORY);
13782
13783         signing->magic = 0;
13784         signing->db  = NULL;
13785         signing->dbiterator = NULL;
13786         signing->algorithm = algorithm;
13787         signing->keyid = keyid;
13788         signing->delete = delete;
13789         signing->done = ISC_FALSE;
13790
13791         TIME_NOW(&now);
13792
13793         for (current = ISC_LIST_HEAD(zone->signing);
13794              current != NULL;
13795              current = ISC_LIST_NEXT(current, link)) {
13796                 if (current->db == zone->db &&
13797                     current->algorithm == signing->algorithm &&
13798                     current->keyid == signing->keyid) {
13799                         if (current->delete != signing->delete)
13800                                 current->done = ISC_TRUE;
13801                         else
13802                                 goto cleanup;
13803                 }
13804         }
13805
13806         if (zone->db != NULL) {
13807                 dns_db_attach(zone->db, &signing->db);
13808                 result = dns_db_createiterator(signing->db, 0,
13809                                                &signing->dbiterator);
13810
13811                 if (result == ISC_R_SUCCESS)
13812                         result = dns_dbiterator_first(signing->dbiterator);
13813                 if (result == ISC_R_SUCCESS) {
13814                         dns_dbiterator_pause(signing->dbiterator);
13815                         ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
13816                         signing = NULL;
13817                         if (isc_time_isepoch(&zone->signingtime)) {
13818                                 zone->signingtime = now;
13819                                 if (zone->task != NULL)
13820                                         zone_settimer(zone, &now);
13821                         }
13822                 }
13823         } else
13824                 result = ISC_R_NOTFOUND;
13825
13826  cleanup:
13827         if (signing != NULL) {
13828                 if (signing->db != NULL)
13829                         dns_db_detach(&signing->db);
13830                 if (signing->dbiterator != NULL)
13831                         dns_dbiterator_destroy(&signing->dbiterator);
13832                 isc_mem_put(zone->mctx, signing, sizeof *signing);
13833         }
13834         return (result);
13835 }
13836
13837 static void
13838 logmsg(const char *format, ...) {
13839         va_list args;
13840         va_start(args, format);
13841         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
13842                        ISC_LOG_DEBUG(1), format, args);
13843         va_end(args);
13844 }
13845
13846 static void
13847 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
13848         dns_dnsseckey_t *key;
13849         while (!ISC_LIST_EMPTY(*list)) {
13850                 key = ISC_LIST_HEAD(*list);
13851                 ISC_LIST_UNLINK(*list, key, link);
13852                 dns_dnsseckey_destroy(mctx, &key);
13853         }
13854 }
13855
13856 /* Called once; *timep should be set to the current time. */
13857 static isc_result_t
13858 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
13859         isc_result_t result;
13860         isc_stdtime_t now, then = 0, event;
13861         int i;
13862
13863         now = *timep;
13864
13865         for (i = 0; i <= DST_MAX_TIMES; i++) {
13866                 result = dst_key_gettime(key, i, &event);
13867                 if (result == ISC_R_SUCCESS && event > now &&
13868                     (then == 0 || event < then))
13869                         then = event;
13870         }
13871
13872         if (then != 0) {
13873                 *timep = then;
13874                 return (ISC_R_SUCCESS);
13875         }
13876
13877         return (ISC_R_NOTFOUND);
13878 }
13879
13880 static isc_result_t
13881 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
13882           const dns_rdata_t *rdata, isc_boolean_t *flag)
13883 {
13884         dns_rdataset_t rdataset;
13885         dns_dbnode_t *node = NULL;
13886         isc_result_t result;
13887
13888         dns_rdataset_init(&rdataset);
13889         if (rdata->type == dns_rdatatype_nsec3)
13890                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
13891         else
13892                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
13893         result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
13894                                      (isc_stdtime_t) 0, &rdataset, NULL);
13895         if (result == ISC_R_NOTFOUND) {
13896                 *flag = ISC_FALSE;
13897                 result = ISC_R_SUCCESS;
13898                 goto failure;
13899         }
13900
13901         for (result = dns_rdataset_first(&rdataset);
13902              result == ISC_R_SUCCESS;
13903              result = dns_rdataset_next(&rdataset)) {
13904                 dns_rdata_t myrdata = DNS_RDATA_INIT;
13905                 dns_rdataset_current(&rdataset, &myrdata);
13906                 if (!dns_rdata_compare(&myrdata, rdata))
13907                         break;
13908         }
13909         dns_rdataset_disassociate(&rdataset);
13910         if (result == ISC_R_SUCCESS) {
13911                 *flag = ISC_TRUE;
13912         } else if (result == ISC_R_NOMORE) {
13913                 *flag = ISC_FALSE;
13914                 result = ISC_R_SUCCESS;
13915         }
13916
13917  failure:
13918         if (node != NULL)
13919                 dns_db_detachnode(db, &node);
13920         return (result);
13921 }
13922
13923 /*
13924  * Add records to signal the state of signing or of key removal.
13925  */
13926 static isc_result_t
13927 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
13928                     dns_dbversion_t *ver, dns_diff_t *diff,
13929                     isc_boolean_t sign_all)
13930 {
13931         dns_difftuple_t *tuple, *newtuple = NULL;
13932         dns_rdata_dnskey_t dnskey;
13933         dns_rdata_t rdata = DNS_RDATA_INIT;
13934         isc_boolean_t flag;
13935         isc_region_t r;
13936         isc_result_t result = ISC_R_SUCCESS;
13937         isc_uint16_t keyid;
13938         unsigned char buf[5];
13939         dns_name_t *name = dns_db_origin(db);
13940
13941         for (tuple = ISC_LIST_HEAD(diff->tuples);
13942              tuple != NULL;
13943              tuple = ISC_LIST_NEXT(tuple, link)) {
13944                 if (tuple->rdata.type != dns_rdatatype_dnskey)
13945                         continue;
13946
13947                 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
13948                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13949                 if ((dnskey.flags &
13950                      (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
13951                          != DNS_KEYOWNER_ZONE)
13952                         continue;
13953
13954                 dns_rdata_toregion(&tuple->rdata, &r);
13955
13956                 keyid = dst_region_computeid(&r, dnskey.algorithm);
13957
13958                 buf[0] = dnskey.algorithm;
13959                 buf[1] = (keyid & 0xff00) >> 8;
13960                 buf[2] = (keyid & 0xff);
13961                 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
13962                 buf[4] = 0;
13963                 rdata.data = buf;
13964                 rdata.length = sizeof(buf);
13965                 rdata.type = privatetype;
13966                 rdata.rdclass = tuple->rdata.rdclass;
13967
13968                 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
13969                         CHECK(rr_exists(db, ver, name, &rdata, &flag));
13970                         if (flag)
13971                                 continue;
13972                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
13973                                                    name, 0, &rdata, &newtuple));
13974                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
13975                         INSIST(newtuple == NULL);
13976                 }
13977
13978                 /*
13979                  * Remove any record which says this operation has already
13980                  * completed.
13981                  */
13982                 buf[4] = 1;
13983                 CHECK(rr_exists(db, ver, name, &rdata, &flag));
13984                 if (flag) {
13985                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
13986                                                    name, 0, &rdata, &newtuple));
13987                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
13988                         INSIST(newtuple == NULL);
13989                 }
13990         }
13991  failure:
13992         return (result);
13993 }
13994
13995 static isc_result_t
13996 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
13997           dns_diff_t *diff, dns_diff_t *sig_diff)
13998 {
13999         isc_result_t result;
14000         isc_stdtime_t now, inception, soaexpire;
14001         isc_boolean_t check_ksk, keyset_kskonly;
14002         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
14003         unsigned int nkeys = 0, i;
14004         dns_difftuple_t *tuple;
14005
14006         result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
14007                                 zone_keys, &nkeys);
14008         if (result != ISC_R_SUCCESS) {
14009                 dns_zone_log(zone, ISC_LOG_ERROR,
14010                              "sign_apex:find_zone_keys -> %s",
14011                              dns_result_totext(result));
14012                 return (result);
14013         }
14014
14015         isc_stdtime_get(&now);
14016         inception = now - 3600; /* Allow for clock skew. */
14017         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
14018
14019         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
14020         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
14021
14022         /*
14023          * See if update_sigs will update DNSKEY signature and if not
14024          * cause them to sign so that so that newly activated keys
14025          * are used.
14026          */
14027         for (tuple = ISC_LIST_HEAD(diff->tuples);
14028              tuple != NULL;
14029              tuple = ISC_LIST_NEXT(tuple, link)) {
14030                 if (tuple->rdata.type == dns_rdatatype_dnskey &&
14031                     dns_name_equal(&tuple->name, &zone->origin))
14032                         break;
14033         }
14034
14035         if (tuple == NULL) {
14036                 result = del_sigs(zone, db, ver, &zone->origin,
14037                                   dns_rdatatype_dnskey, sig_diff,
14038                                   zone_keys, nkeys, now, ISC_FALSE);
14039                 if (result != ISC_R_SUCCESS) {
14040                         dns_zone_log(zone, ISC_LOG_ERROR,
14041                                      "sign_apex:del_sigs -> %s",
14042                                      dns_result_totext(result));
14043                         goto failure;
14044                 }
14045                 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
14046                                   sig_diff, zone_keys, nkeys, zone->mctx,
14047                                   inception, soaexpire, check_ksk,
14048                                   keyset_kskonly);
14049                 if (result != ISC_R_SUCCESS) {
14050                         dns_zone_log(zone, ISC_LOG_ERROR,
14051                                      "sign_apex:add_sigs -> %s",
14052                                      dns_result_totext(result));
14053                         goto failure;
14054                 }
14055         }
14056
14057         result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
14058                              inception, soaexpire, now, check_ksk,
14059                              keyset_kskonly, sig_diff);
14060
14061         if (result != ISC_R_SUCCESS) {
14062                 dns_zone_log(zone, ISC_LOG_ERROR,
14063                              "sign_apex:update_sigs -> %s",
14064                              dns_result_totext(result));
14065                 goto failure;
14066         }
14067
14068  failure:
14069         for (i = 0; i < nkeys; i++)
14070                 dst_key_free(&zone_keys[i]);
14071         return (result);
14072 }
14073
14074 /*
14075  * Prevent the zone entering a inconsistent state where
14076  * NSEC only DNSKEYs are present with NSEC3 chains.
14077  * See update.c:check_dnssec()
14078  */
14079 static isc_boolean_t
14080 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14081             dns_diff_t *diff)
14082 {
14083         isc_result_t result;
14084         dns_difftuple_t *tuple;
14085         isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
14086         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
14087
14088         /* Scan the tuples for an NSEC-only DNSKEY */
14089         for (tuple = ISC_LIST_HEAD(diff->tuples);
14090              tuple != NULL;
14091              tuple = ISC_LIST_NEXT(tuple, link)) {
14092                 isc_uint8_t alg;
14093                 if (tuple->rdata.type != dns_rdatatype_dnskey ||
14094                     tuple->op != DNS_DIFFOP_ADD)
14095                         continue;
14096
14097                 alg = tuple->rdata.data[3];
14098                 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
14099                     alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
14100                         nseconly = ISC_TRUE;
14101                         break;
14102                 }
14103         }
14104
14105         /* Check existing DB for NSEC-only DNSKEY */
14106         if (!nseconly)
14107                 CHECK(dns_nsec_nseconly(db, ver, &nseconly));
14108
14109         /* Check existing DB for NSEC3 */
14110         if (!nsec3)
14111                 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
14112                                         privatetype, &nsec3));
14113
14114         /* Refuse to allow NSEC3 with NSEC-only keys */
14115         if (nseconly && nsec3) {
14116                 dns_zone_log(zone, ISC_LOG_ERROR,
14117                            "NSEC only DNSKEYs and NSEC3 chains not allowed");
14118                 goto failure;
14119         }
14120
14121         return (ISC_TRUE);
14122
14123  failure:
14124         return (ISC_FALSE);
14125 }
14126
14127 static isc_result_t
14128 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14129                  dns_diff_t *diff)
14130 {
14131         isc_result_t result;
14132         dns_dbnode_t *node = NULL;
14133         dns_rdataset_t rdataset;
14134
14135         dns_rdataset_init(&rdataset);
14136         CHECK(dns_db_getoriginnode(db, &node));
14137
14138         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
14139                                      dns_rdatatype_none, 0, &rdataset, NULL);
14140         if (dns_rdataset_isassociated(&rdataset))
14141                 dns_rdataset_disassociate(&rdataset);
14142         if (result != ISC_R_NOTFOUND)
14143                 goto failure;
14144
14145         result = dns_nsec3param_deletechains(db, ver, zone, diff);
14146
14147  failure:
14148         if (node != NULL)
14149                 dns_db_detachnode(db, &node);
14150         return (result);
14151 }
14152
14153 /*
14154  * Given an RRSIG rdataset and an algorithm, determine whether there
14155  * are any signatures using that algorithm.
14156  */
14157 static isc_boolean_t
14158 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
14159         dns_rdata_t rdata = DNS_RDATA_INIT;
14160         dns_rdata_rrsig_t rrsig;
14161         isc_result_t result;
14162
14163         REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
14164         if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
14165                 return (ISC_FALSE);
14166         }
14167
14168         for (result = dns_rdataset_first(rdataset);
14169              result == ISC_R_SUCCESS;
14170              result = dns_rdataset_next(rdataset))
14171         {
14172                 dns_rdataset_current(rdataset, &rdata);
14173                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
14174                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14175                 dns_rdata_reset(&rdata);
14176                 if (rrsig.algorithm == alg)
14177                         return (ISC_TRUE);
14178         }
14179
14180         return (ISC_FALSE);
14181 }
14182
14183 static isc_result_t
14184 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
14185            dns_diff_t *diff)
14186 {
14187         dns_name_t *origin;
14188         isc_boolean_t build_nsec3;
14189         isc_result_t result;
14190
14191         origin = dns_db_origin(db);
14192         CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
14193                                  &build_nsec3));
14194         if (build_nsec3)
14195                 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
14196                                            ISC_FALSE, zone->privatetype, diff));
14197         CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
14198
14199  failure:
14200         return (result);
14201 }
14202
14203 static void
14204 zone_rekey(dns_zone_t *zone) {
14205         isc_result_t result;
14206         dns_db_t *db = NULL;
14207         dns_dbnode_t *node = NULL;
14208         dns_dbversion_t *ver = NULL;
14209         dns_rdataset_t soaset, soasigs, keyset, keysigs;
14210         dns_dnsseckeylist_t dnskeys, keys, rmkeys;
14211         dns_dnsseckey_t *key;
14212         dns_diff_t diff, sig_diff;
14213         isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
14214         isc_boolean_t newalg = ISC_FALSE;
14215         isc_boolean_t fullsign;
14216         dns_ttl_t ttl = 3600;
14217         const char *dir;
14218         isc_mem_t *mctx;
14219         isc_stdtime_t now;
14220         isc_time_t timenow;
14221         isc_interval_t ival;
14222         char timebuf[80];
14223
14224         REQUIRE(DNS_ZONE_VALID(zone));
14225
14226         ISC_LIST_INIT(dnskeys);
14227         ISC_LIST_INIT(keys);
14228         ISC_LIST_INIT(rmkeys);
14229         dns_rdataset_init(&soaset);
14230         dns_rdataset_init(&soasigs);
14231         dns_rdataset_init(&keyset);
14232         dns_rdataset_init(&keysigs);
14233         dir = dns_zone_getkeydirectory(zone);
14234         mctx = zone->mctx;
14235         dns_diff_init(mctx, &diff);
14236         dns_diff_init(mctx, &sig_diff);
14237         sig_diff.resign = zone->sigresigninginterval;
14238
14239         CHECK(dns_zone_getdb(zone, &db));
14240         CHECK(dns_db_newversion(db, &ver));
14241         CHECK(dns_db_getoriginnode(db, &node));
14242
14243         TIME_NOW(&timenow);
14244         now = isc_time_seconds(&timenow);
14245
14246         dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
14247
14248         /* Get the SOA record's TTL */
14249         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
14250                                   dns_rdatatype_none, 0, &soaset, &soasigs));
14251         ttl = soaset.ttl;
14252         dns_rdataset_disassociate(&soaset);
14253
14254         /* Get the DNSKEY rdataset */
14255         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
14256                                      dns_rdatatype_none, 0, &keyset, &keysigs);
14257         if (result == ISC_R_SUCCESS) {
14258                 ttl = keyset.ttl;
14259                 result = dns_dnssec_keylistfromrdataset(&zone->origin, dir,
14260                                                         mctx, &keyset,
14261                                                         &keysigs, &soasigs,
14262                                                         ISC_FALSE, ISC_FALSE,
14263                                                         &dnskeys);
14264                 /* Can't get keys for some reason; try again later. */
14265                 if (result != ISC_R_SUCCESS)
14266                         goto trylater;
14267         } else if (result != ISC_R_NOTFOUND)
14268                 goto failure;
14269
14270         /*
14271          * True when called from "rndc sign".  Indicates the zone should be
14272          * fully signed now.
14273          */
14274         fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
14275
14276         result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
14277         if (result == ISC_R_SUCCESS) {
14278                 isc_boolean_t check_ksk;
14279                 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
14280
14281                 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
14282                                                &zone->origin, ttl, &diff,
14283                                                ISC_TF(!check_ksk),
14284                                                mctx, logmsg);
14285
14286                 /* Keys couldn't be updated for some reason;
14287                  * try again later. */
14288                 if (result != ISC_R_SUCCESS) {
14289                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
14290                                      "couldn't update zone keys: %s",
14291                                      isc_result_totext(result));
14292                         goto trylater;
14293                 }
14294
14295                 /*
14296                  * See if any pre-existing keys have newly become active;
14297                  * also, see if any new key is for a new algorithm, as in that
14298                  * event, we need to sign the zone fully.  (If there's a new
14299                  * key, but it's for an already-existing algorithm, then
14300                  * the zone signing can be handled incrementally.)
14301                  */
14302                 for (key = ISC_LIST_HEAD(dnskeys);
14303                      key != NULL;
14304                      key = ISC_LIST_NEXT(key, link)) {
14305                         if (!key->first_sign)
14306                                 continue;
14307
14308                         newactive = ISC_TRUE;
14309
14310                         if (!dns_rdataset_isassociated(&keysigs)) {
14311                                 newalg = ISC_TRUE;
14312                                 break;
14313                         }
14314
14315                         if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
14316                                 /*
14317                                  * This isn't a new algorithm; clear
14318                                  * first_sign so we won't sign the
14319                                  * whole zone with this key later
14320                                  */
14321                                 key->first_sign = ISC_FALSE;
14322                         } else {
14323                                 newalg = ISC_TRUE;
14324                                 break;
14325                         }
14326                 }
14327
14328                 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
14329                     dnskey_sane(zone, db, ver, &diff)) {
14330                         CHECK(dns_diff_apply(&diff, db, ver));
14331                         CHECK(clean_nsec3param(zone, db, ver, &diff));
14332                         CHECK(add_signing_records(db, zone->privatetype,
14333                                                   ver, &diff,
14334                                                   ISC_TF(newalg || fullsign)));
14335                         CHECK(increment_soa_serial(db, ver, &diff, mctx));
14336                         CHECK(add_chains(zone, db, ver, &diff));
14337                         CHECK(sign_apex(zone, db, ver, &diff, &sig_diff));
14338                         CHECK(zone_journal(zone, &sig_diff, "zone_rekey"));
14339                         commit = ISC_TRUE;
14340                 }
14341         }
14342
14343         dns_db_closeversion(db, &ver, commit);
14344
14345         if (commit) {
14346                 dns_difftuple_t *tuple;
14347
14348                 LOCK_ZONE(zone);
14349                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14350
14351                 zone_needdump(zone, DNS_DUMP_DELAY);
14352
14353                 zone_settimer(zone, &timenow);
14354
14355                 /* Remove any signatures from removed keys.  */
14356                 if (!ISC_LIST_EMPTY(rmkeys)) {
14357                         for (key = ISC_LIST_HEAD(rmkeys);
14358                              key != NULL;
14359                              key = ISC_LIST_NEXT(key, link)) {
14360                                 result = zone_signwithkey(zone,
14361                                                           dst_key_alg(key->key),
14362                                                           dst_key_id(key->key),
14363                                                           ISC_TRUE);
14364                                 if (result != ISC_R_SUCCESS) {
14365                                         dns_zone_log(zone, ISC_LOG_ERROR,
14366                                              "zone_signwithkey failed: %s",
14367                                              dns_result_totext(result));
14368                                 }
14369                         }
14370                 }
14371
14372                 if (fullsign) {
14373                         /*
14374                          * "rndc sign" was called, so we now sign the zone
14375                          * with all active keys, whether they're new or not.
14376                          */
14377                         for (key = ISC_LIST_HEAD(dnskeys);
14378                              key != NULL;
14379                              key = ISC_LIST_NEXT(key, link)) {
14380                                 if (!key->force_sign && !key->hint_sign)
14381                                         continue;
14382
14383                                 result = zone_signwithkey(zone,
14384                                                           dst_key_alg(key->key),
14385                                                           dst_key_id(key->key),
14386                                                           ISC_FALSE);
14387                                 if (result != ISC_R_SUCCESS) {
14388                                         dns_zone_log(zone, ISC_LOG_ERROR,
14389                                              "zone_signwithkey failed: %s",
14390                                              dns_result_totext(result));
14391                                 }
14392                         }
14393                 } else if (newalg) {
14394                         /*
14395                          * We haven't been told to sign fully, but a new
14396                          * algorithm was added to the DNSKEY.  We sign
14397                          * the full zone, but only with newly active
14398                          * keys.
14399                          */
14400                         for (key = ISC_LIST_HEAD(dnskeys);
14401                              key != NULL;
14402                              key = ISC_LIST_NEXT(key, link)) {
14403                                 if (!key->first_sign)
14404                                         continue;
14405
14406                                 result = zone_signwithkey(zone,
14407                                                           dst_key_alg(key->key),
14408                                                           dst_key_id(key->key),
14409                                                           ISC_FALSE);
14410                                 if (result != ISC_R_SUCCESS) {
14411                                         dns_zone_log(zone, ISC_LOG_ERROR,
14412                                              "zone_signwithkey failed: %s",
14413                                              dns_result_totext(result));
14414                                 }
14415                         }
14416                 }
14417
14418                 /*
14419                  * Clear fullsign flag, if it was set, so we don't do
14420                  * another full signing next time
14421                  */
14422                 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
14423
14424                 /*
14425                  * Cause the zone to add/delete NSEC3 chains for the
14426                  * deferred NSEC3PARAM changes.
14427                  */
14428                 for (tuple = ISC_LIST_HEAD(sig_diff.tuples);
14429                      tuple != NULL;
14430                      tuple = ISC_LIST_NEXT(tuple, link)) {
14431                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
14432                         dns_rdata_t rdata = DNS_RDATA_INIT;
14433                         dns_rdata_nsec3param_t nsec3param;
14434
14435                         if (tuple->rdata.type != zone->privatetype ||
14436                             tuple->op != DNS_DIFFOP_ADD)
14437                                 continue;
14438
14439                         if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
14440                                                         buf, sizeof(buf)))
14441                                 continue;
14442                         result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
14443                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
14444                         if (nsec3param.flags == 0)
14445                                 continue;
14446
14447                         result = zone_addnsec3chain(zone, &nsec3param);
14448                         if (result != ISC_R_SUCCESS) {
14449                                 dns_zone_log(zone, ISC_LOG_ERROR,
14450                                              "zone_addnsec3chain failed: %s",
14451                                              dns_result_totext(result));
14452                         }
14453                 }
14454
14455                 /*
14456                  * Schedule the next resigning event
14457                  */
14458                 set_resigntime(zone);
14459                 UNLOCK_ZONE(zone);
14460         }
14461
14462         isc_time_settoepoch(&zone->refreshkeytime);
14463
14464         /*
14465          * If we're doing key maintenance, set the key refresh timer to
14466          * the next scheduled key event or to one hour in the future,
14467          * whichever is sooner.
14468          */
14469         if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
14470                 isc_time_t timethen;
14471                 isc_stdtime_t then;
14472
14473                 LOCK_ZONE(zone);
14474                 DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
14475                 zone->refreshkeytime = timethen;
14476                 UNLOCK_ZONE(zone);
14477
14478                 for (key = ISC_LIST_HEAD(dnskeys);
14479                      key != NULL;
14480                      key = ISC_LIST_NEXT(key, link)) {
14481                         then = now;
14482                         result = next_keyevent(key->key, &then);
14483                         if (result != ISC_R_SUCCESS)
14484                                 continue;
14485
14486                         DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
14487                         LOCK_ZONE(zone);
14488                         if (isc_time_compare(&timethen,
14489                                              &zone->refreshkeytime) < 0) {
14490                                 zone->refreshkeytime = timethen;
14491                         }
14492                         UNLOCK_ZONE(zone);
14493                 }
14494
14495                 zone_settimer(zone, &timenow);
14496
14497                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
14498                 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
14499         }
14500
14501  failure:
14502         dns_diff_clear(&diff);
14503         dns_diff_clear(&sig_diff);
14504
14505         clear_keylist(&dnskeys, mctx);
14506         clear_keylist(&keys, mctx);
14507         clear_keylist(&rmkeys, mctx);
14508
14509         if (ver != NULL)
14510                 dns_db_closeversion(db, &ver, ISC_FALSE);
14511         if (dns_rdataset_isassociated(&keyset))
14512                 dns_rdataset_disassociate(&keyset);
14513         if (dns_rdataset_isassociated(&keysigs))
14514                 dns_rdataset_disassociate(&keysigs);
14515         if (dns_rdataset_isassociated(&soasigs))
14516                 dns_rdataset_disassociate(&soasigs);
14517         if (node != NULL)
14518                 dns_db_detachnode(db, &node);
14519         if (db != NULL)
14520                 dns_db_detach(&db);
14521         return;
14522
14523  trylater:
14524         isc_interval_set(&ival, HOUR, 0);
14525         isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
14526         goto failure;
14527 }
14528
14529 void
14530 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
14531         isc_time_t now;
14532
14533         if (zone->type == dns_zone_master && zone->task != NULL) {
14534                 LOCK_ZONE(zone);
14535
14536                 if (fullsign)
14537                         zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
14538
14539                 TIME_NOW(&now);
14540                 zone->refreshkeytime = now;
14541                 zone_settimer(zone, &now);
14542
14543                 UNLOCK_ZONE(zone);
14544         }
14545 }
14546
14547 isc_result_t
14548 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
14549                  unsigned int *errors)
14550 {
14551         isc_result_t result;
14552         dns_dbnode_t *node = NULL;
14553
14554         REQUIRE(DNS_ZONE_VALID(zone));
14555         REQUIRE(errors != NULL);
14556
14557         result = dns_db_getoriginnode(db, &node);
14558         if (result != ISC_R_SUCCESS)
14559                 return (result);
14560         result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
14561                                   ISC_FALSE);
14562         dns_db_detachnode(db, &node);
14563         return (result);
14564 }
14565
14566 void
14567 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
14568         REQUIRE(DNS_ZONE_VALID(zone));
14569         LOCK_ZONE(zone);
14570         zone->added = added;
14571         UNLOCK_ZONE(zone);
14572 }
14573
14574 isc_boolean_t
14575 dns_zone_getadded(dns_zone_t *zone) {
14576         REQUIRE(DNS_ZONE_VALID(zone));
14577         return (zone->added);
14578 }
14579
14580 isc_result_t
14581 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
14582 {
14583         isc_time_t loadtime;
14584         isc_result_t result;
14585         TIME_NOW(&loadtime);
14586
14587         LOCK_ZONE(zone);
14588         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
14589         UNLOCK_ZONE(zone);
14590         return result;
14591 }