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