]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/bind9/lib/dns/zone.c
Copy stable/9 to releng/9.3 as part of the 9.3-RELEASE cycle.
[FreeBSD/releng/9.3.git] / contrib / bind9 / lib / dns / zone.c
1 /*
2  * Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id$ */
19
20 /*! \file */
21
22 #include <config.h>
23 #include <errno.h>
24
25 #include <isc/file.h>
26 #include <isc/hex.h>
27 #include <isc/mutex.h>
28 #include <isc/pool.h>
29 #include <isc/print.h>
30 #include <isc/random.h>
31 #include <isc/ratelimiter.h>
32 #include <isc/refcount.h>
33 #include <isc/rwlock.h>
34 #include <isc/serial.h>
35 #include <isc/stats.h>
36 #include <isc/stdtime.h>
37 #include <isc/strerror.h>
38 #include <isc/string.h>
39 #include <isc/taskpool.h>
40 #include <isc/thread.h>
41 #include <isc/timer.h>
42 #include <isc/util.h>
43
44 #include <dns/acache.h>
45 #include <dns/acl.h>
46 #include <dns/adb.h>
47 #include <dns/callbacks.h>
48 #include <dns/db.h>
49 #include <dns/dbiterator.h>
50 #include <dns/dnssec.h>
51 #include <dns/events.h>
52 #include <dns/journal.h>
53 #include <dns/keydata.h>
54 #include <dns/keytable.h>
55 #include <dns/keyvalues.h>
56 #include <dns/log.h>
57 #include <dns/master.h>
58 #include <dns/masterdump.h>
59 #include <dns/message.h>
60 #include <dns/name.h>
61 #include <dns/nsec.h>
62 #include <dns/nsec3.h>
63 #include <dns/peer.h>
64 #include <dns/private.h>
65 #include <dns/rbt.h>
66 #include <dns/rcode.h>
67 #include <dns/rdata.h>
68 #include <dns/rdataclass.h>
69 #include <dns/rdatalist.h>
70 #include <dns/rdataset.h>
71 #include <dns/rdatasetiter.h>
72 #include <dns/rdatastruct.h>
73 #include <dns/rdatatype.h>
74 #include <dns/request.h>
75 #include <dns/resolver.h>
76 #include <dns/result.h>
77 #include <dns/rriterator.h>
78 #include <dns/soa.h>
79 #include <dns/ssu.h>
80 #include <dns/stats.h>
81 #include <dns/time.h>
82 #include <dns/tsig.h>
83 #include <dns/update.h>
84 #include <dns/xfrin.h>
85 #include <dns/zone.h>
86 #include <dns/zt.h>
87
88 #include <dst/dst.h>
89
90 #define ZONE_MAGIC                      ISC_MAGIC('Z', 'O', 'N', 'E')
91 #define DNS_ZONE_VALID(zone)            ISC_MAGIC_VALID(zone, ZONE_MAGIC)
92
93 #define NOTIFY_MAGIC                    ISC_MAGIC('N', 't', 'f', 'y')
94 #define DNS_NOTIFY_VALID(notify)        ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
95
96 #define STUB_MAGIC                      ISC_MAGIC('S', 't', 'u', 'b')
97 #define DNS_STUB_VALID(stub)            ISC_MAGIC_VALID(stub, STUB_MAGIC)
98
99 #define ZONEMGR_MAGIC                   ISC_MAGIC('Z', 'm', 'g', 'r')
100 #define DNS_ZONEMGR_VALID(stub)         ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
101
102 #define LOAD_MAGIC                      ISC_MAGIC('L', 'o', 'a', 'd')
103 #define DNS_LOAD_VALID(load)            ISC_MAGIC_VALID(load, LOAD_MAGIC)
104
105 #define FORWARD_MAGIC                   ISC_MAGIC('F', 'o', 'r', 'w')
106 #define DNS_FORWARD_VALID(load)         ISC_MAGIC_VALID(load, FORWARD_MAGIC)
107
108 #define IO_MAGIC                        ISC_MAGIC('Z', 'm', 'I', 'O')
109 #define DNS_IO_VALID(load)              ISC_MAGIC_VALID(load, IO_MAGIC)
110
111 /*%
112  * Ensure 'a' is at least 'min' but not more than 'max'.
113  */
114 #define RANGE(a, min, max) \
115                 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
116
117 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
118
119 /*%
120  * Key flags
121  */
122 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
123 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
124 #define ALG(x) dst_key_alg(x)
125
126 /*
127  * Default values.
128  */
129 #define DNS_DEFAULT_IDLEIN 3600         /*%< 1 hour */
130 #define DNS_DEFAULT_IDLEOUT 3600        /*%< 1 hour */
131 #define MAX_XFER_TIME (2*3600)          /*%< Documented default is 2 hours */
132 #define RESIGN_DELAY 3600               /*%< 1 hour */
133
134 #ifndef DNS_MAX_EXPIRE
135 #define DNS_MAX_EXPIRE  14515200        /*%< 24 weeks */
136 #endif
137
138 #ifndef DNS_DUMP_DELAY
139 #define DNS_DUMP_DELAY 900              /*%< 15 minutes */
140 #endif
141
142 typedef struct dns_notify dns_notify_t;
143 typedef struct dns_stub dns_stub_t;
144 typedef struct dns_load dns_load_t;
145 typedef struct dns_forward dns_forward_t;
146 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
147 typedef struct dns_io dns_io_t;
148 typedef ISC_LIST(dns_io_t) dns_iolist_t;
149 typedef struct dns_signing dns_signing_t;
150 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
151 typedef struct dns_nsec3chain dns_nsec3chain_t;
152 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
153 typedef struct dns_keyfetch dns_keyfetch_t;
154 typedef struct dns_asyncload dns_asyncload_t;
155
156 #define DNS_ZONE_CHECKLOCK
157 #ifdef DNS_ZONE_CHECKLOCK
158 #define LOCK_ZONE(z) \
159          do { LOCK(&(z)->lock); \
160               INSIST((z)->locked == ISC_FALSE); \
161              (z)->locked = ISC_TRUE; \
162                 } while (0)
163 #define UNLOCK_ZONE(z) \
164         do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
165 #define LOCKED_ZONE(z) ((z)->locked)
166 #define TRYLOCK_ZONE(result, z) \
167         do { \
168               result = isc_mutex_trylock(&(z)->lock); \
169               if (result == ISC_R_SUCCESS) {  \
170                      INSIST((z)->locked == ISC_FALSE); \
171                      (z)->locked = ISC_TRUE; \
172               } \
173         } while (0)
174 #else
175 #define LOCK_ZONE(z) LOCK(&(z)->lock)
176 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
177 #define LOCKED_ZONE(z) ISC_TRUE
178 #define TRYLOCK_ZONE(result, z) \
179         do { result = isc_mutex_trylock(&(z)->lock); } while (0)
180 #endif
181
182 #ifdef ISC_RWLOCK_USEATOMIC
183 #define ZONEDB_INITLOCK(l)      isc_rwlock_init((l), 0, 0)
184 #define ZONEDB_DESTROYLOCK(l)   isc_rwlock_destroy(l)
185 #define ZONEDB_LOCK(l, t)       RWLOCK((l), (t))
186 #define ZONEDB_UNLOCK(l, t)     RWUNLOCK((l), (t))
187 #else
188 #define ZONEDB_INITLOCK(l)      isc_mutex_init(l)
189 #define ZONEDB_DESTROYLOCK(l)   DESTROYLOCK(l)
190 #define ZONEDB_LOCK(l, t)       LOCK(l)
191 #define ZONEDB_UNLOCK(l, t)     UNLOCK(l)
192 #endif
193
194 struct dns_zone {
195         /* Unlocked */
196         unsigned int            magic;
197         isc_mutex_t             lock;
198 #ifdef DNS_ZONE_CHECKLOCK
199         isc_boolean_t           locked;
200 #endif
201         isc_mem_t               *mctx;
202         isc_refcount_t          erefs;
203
204 #ifdef ISC_RWLOCK_USEATOMIC
205         isc_rwlock_t            dblock;
206 #else
207         isc_mutex_t             dblock;
208 #endif
209         dns_db_t                *db;            /* Locked by dblock */
210
211         /* Locked */
212         dns_zonemgr_t           *zmgr;
213         ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
214         isc_timer_t             *timer;
215         unsigned int            irefs;
216         dns_name_t              origin;
217         char                    *masterfile;
218         dns_masterformat_t      masterformat;
219         char                    *journal;
220         isc_int32_t             journalsize;
221         dns_rdataclass_t        rdclass;
222         dns_zonetype_t          type;
223         unsigned int            flags;
224         unsigned int            options;
225         unsigned int            db_argc;
226         char                    **db_argv;
227         isc_time_t              expiretime;
228         isc_time_t              refreshtime;
229         isc_time_t              dumptime;
230         isc_time_t              loadtime;
231         isc_time_t              notifytime;
232         isc_time_t              resigntime;
233         isc_time_t              keywarntime;
234         isc_time_t              signingtime;
235         isc_time_t              nsec3chaintime;
236         isc_time_t              refreshkeytime;
237         isc_uint32_t            refreshkeyinterval;
238         isc_uint32_t            refreshkeycount;
239         isc_uint32_t            refresh;
240         isc_uint32_t            retry;
241         isc_uint32_t            expire;
242         isc_uint32_t            minimum;
243         isc_stdtime_t           key_expiry;
244         isc_stdtime_t           log_key_expired_timer;
245         char                    *keydirectory;
246
247         isc_uint32_t            maxrefresh;
248         isc_uint32_t            minrefresh;
249         isc_uint32_t            maxretry;
250         isc_uint32_t            minretry;
251
252         isc_sockaddr_t          *masters;
253         dns_name_t              **masterkeynames;
254         isc_boolean_t           *mastersok;
255         unsigned int            masterscnt;
256         unsigned int            curmaster;
257         isc_sockaddr_t          masteraddr;
258         dns_notifytype_t        notifytype;
259         isc_sockaddr_t          *notify;
260         dns_name_t              **notifykeynames;
261         unsigned int            notifycnt;
262         isc_sockaddr_t          notifyfrom;
263         isc_task_t              *task;
264         isc_task_t              *loadtask;
265         isc_sockaddr_t          notifysrc4;
266         isc_sockaddr_t          notifysrc6;
267         isc_sockaddr_t          xfrsource4;
268         isc_sockaddr_t          xfrsource6;
269         isc_sockaddr_t          altxfrsource4;
270         isc_sockaddr_t          altxfrsource6;
271         isc_sockaddr_t          sourceaddr;
272         dns_xfrin_ctx_t         *xfr;           /* task locked */
273         dns_tsigkey_t           *tsigkey;       /* key used for xfr */
274         /* Access Control Lists */
275         dns_acl_t               *update_acl;
276         dns_acl_t               *forward_acl;
277         dns_acl_t               *notify_acl;
278         dns_acl_t               *query_acl;
279         dns_acl_t               *queryon_acl;
280         dns_acl_t               *xfr_acl;
281         isc_boolean_t           update_disabled;
282         isc_boolean_t           zero_no_soa_ttl;
283         dns_severity_t          check_names;
284         ISC_LIST(dns_notify_t)  notifies;
285         dns_request_t           *request;
286         dns_loadctx_t           *lctx;
287         dns_io_t                *readio;
288         dns_dumpctx_t           *dctx;
289         dns_io_t                *writeio;
290         isc_uint32_t            maxxfrin;
291         isc_uint32_t            maxxfrout;
292         isc_uint32_t            idlein;
293         isc_uint32_t            idleout;
294         isc_event_t             ctlevent;
295         dns_ssutable_t          *ssutable;
296         isc_uint32_t            sigvalidityinterval;
297         isc_uint32_t            sigresigninginterval;
298         dns_view_t              *view;
299         dns_acache_t            *acache;
300         dns_checkmxfunc_t       checkmx;
301         dns_checksrvfunc_t      checksrv;
302         dns_checknsfunc_t       checkns;
303         /*%
304          * Zones in certain states such as "waiting for zone transfer"
305          * or "zone transfer in progress" are kept on per-state linked lists
306          * in the zone manager using the 'statelink' field.  The 'statelist'
307          * field points at the list the zone is currently on.  It the zone
308          * is not on any such list, statelist is NULL.
309          */
310         ISC_LINK(dns_zone_t)    statelink;
311         dns_zonelist_t          *statelist;
312         /*%
313          * Statistics counters about zone management.
314          */
315         isc_stats_t             *stats;
316         /*%
317          * Optional per-zone statistics counters.  Counted outside of this
318          * module.
319          */
320         dns_zonestat_level_t    statlevel;
321         isc_boolean_t           requeststats_on;
322         isc_stats_t             *requeststats;
323         dns_stats_t             *rcvquerystats;
324         isc_uint32_t            notifydelay;
325         dns_isselffunc_t        isself;
326         void                    *isselfarg;
327
328         char *                  strnamerd;
329         char *                  strname;
330         char *                  strrdclass;
331         char *                  strviewname;
332
333         /*%
334          * Serial number for deferred journal compaction.
335          */
336         isc_uint32_t            compact_serial;
337         /*%
338          * Keys that are signing the zone for the first time.
339          */
340         dns_signinglist_t       signing;
341         dns_nsec3chainlist_t    nsec3chain;
342         /*%
343          * Signing / re-signing quantum stopping parameters.
344          */
345         isc_uint32_t            signatures;
346         isc_uint32_t            nodes;
347         dns_rdatatype_t         privatetype;
348
349         /*%
350          * Autosigning/key-maintenance options
351          */
352         isc_uint32_t            keyopts;
353
354         /*%
355          * True if added by "rndc addzone"
356          */
357         isc_boolean_t           added;
358
359         /*%
360          * whether this is a response policy zone
361          */
362         isc_boolean_t           is_rpz;
363
364         /*%
365          * Serial number update method.
366          */
367         dns_updatemethod_t      updatemethod;
368
369         /*%
370          * whether ixfr is requested
371          */
372         isc_boolean_t           requestixfr;
373
374         /*%
375          * Outstanding forwarded UPDATE requests.
376          */
377         dns_forwardlist_t       forwards;
378
379         dns_zone_t              *raw;
380         dns_zone_t              *secure;
381
382         isc_boolean_t           sourceserialset;
383         isc_uint32_t            sourceserial;
384 };
385
386 typedef struct {
387         dns_diff_t      *diff;
388         isc_boolean_t   offline;
389 } zonediff_t;
390
391 #define zonediff_init(z, d) \
392         do { \
393                 zonediff_t *_z = (z); \
394                 (_z)->diff = (d); \
395                 (_z)->offline = ISC_FALSE; \
396         } while (0)
397
398 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
399 #define DNS_ZONE_SETFLAG(z,f) do { \
400                 INSIST(LOCKED_ZONE(z)); \
401                 (z)->flags |= (f); \
402                 } while (0)
403 #define DNS_ZONE_CLRFLAG(z,f) do { \
404                 INSIST(LOCKED_ZONE(z)); \
405                 (z)->flags &= ~(f); \
406                 } while (0)
407         /* XXX MPA these may need to go back into zone.h */
408 #define DNS_ZONEFLG_REFRESH     0x00000001U     /*%< refresh check in progress */
409 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /*%< zone need consolidation */
410 #define DNS_ZONEFLG_USEVC       0x00000004U     /*%< use tcp for refresh query */
411 #define DNS_ZONEFLG_DUMPING     0x00000008U     /*%< a dump is in progress */
412 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /*%< $INCLUDE in zone file */
413 #define DNS_ZONEFLG_LOADED      0x00000020U     /*%< database has loaded */
414 #define DNS_ZONEFLG_EXITING     0x00000040U     /*%< zone is being destroyed */
415 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /*%< zone has expired */
416 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /*%< refresh check needed */
417 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /*%< zone contents are
418                                                  * uptodate */
419 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /*%< need to send out notify
420                                                  * messages */
421 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /*%< generate a journal diff on
422                                                  * reload */
423 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /*%< an attempt to refresh a
424                                                  * zone with no masters
425                                                  * occurred */
426 #define DNS_ZONEFLG_LOADING     0x00002000U     /*%< load from disk in progress*/
427 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /*%< timer values have been set
428                                                  * from SOA (if not set, we
429                                                  * are still using
430                                                  * default timer values) */
431 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
432 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
433 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
434 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
435 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
436 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /*%< IXFR failed, force AXFR */
437 #define DNS_ZONEFLG_FLUSH       0x00200000U
438 #define DNS_ZONEFLG_NOEDNS      0x00400000U
439 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
440 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
441 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
442 #define DNS_ZONEFLG_REFRESHING  0x04000000U     /*%< Refreshing keydata */
443 #define DNS_ZONEFLG_THAW        0x08000000U
444 #define DNS_ZONEFLG_LOADPENDING 0x10000000U     /*%< Loading scheduled */
445 #define DNS_ZONEFLG_NODELAY     0x20000000U
446 #define DNS_ZONEFLG_SENDSECURE  0x40000000U
447
448 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
449 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
450
451 /* Flags for zone_load() */
452 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
453 #define DNS_ZONELOADFLAG_THAW   0x00000002U     /* Thaw the zone on successful
454                                                    load. */
455
456 #define UNREACH_CHACHE_SIZE     10U
457 #define UNREACH_HOLD_TIME       600     /* 10 minutes */
458
459 #define CHECK(op) \
460         do { result = (op); \
461                 if (result != ISC_R_SUCCESS) goto failure; \
462         } while (0)
463
464 struct dns_unreachable {
465         isc_sockaddr_t  remote;
466         isc_sockaddr_t  local;
467         isc_uint32_t    expire;
468         isc_uint32_t    last;
469         isc_uint32_t    count;
470 };
471
472 struct dns_zonemgr {
473         unsigned int            magic;
474         isc_mem_t *             mctx;
475         int                     refs;           /* Locked by rwlock */
476         isc_taskmgr_t *         taskmgr;
477         isc_timermgr_t *        timermgr;
478         isc_socketmgr_t *       socketmgr;
479         isc_taskpool_t *        zonetasks;
480         isc_taskpool_t *        loadtasks;
481         isc_task_t *            task;
482         isc_pool_t *            mctxpool;
483         isc_ratelimiter_t *     notifyrl;
484         isc_ratelimiter_t *     refreshrl;
485         isc_rwlock_t            rwlock;
486         isc_mutex_t             iolock;
487         isc_rwlock_t            urlock;
488
489         /* Locked by rwlock. */
490         dns_zonelist_t          zones;
491         dns_zonelist_t          waiting_for_xfrin;
492         dns_zonelist_t          xfrin_in_progress;
493
494         /* Configuration data. */
495         isc_uint32_t            transfersin;
496         isc_uint32_t            transfersperns;
497         unsigned int            serialqueryrate;
498
499         /* Locked by iolock */
500         isc_uint32_t            iolimit;
501         isc_uint32_t            ioactive;
502         dns_iolist_t            high;
503         dns_iolist_t            low;
504
505         /* Locked by urlock. */
506         /* LRU cache */
507         struct dns_unreachable  unreachable[UNREACH_CHACHE_SIZE];
508 };
509
510 /*%
511  * Hold notify state.
512  */
513 struct dns_notify {
514         unsigned int            magic;
515         unsigned int            flags;
516         isc_mem_t               *mctx;
517         dns_zone_t              *zone;
518         dns_adbfind_t           *find;
519         dns_request_t           *request;
520         dns_name_t              ns;
521         isc_sockaddr_t          dst;
522         dns_tsigkey_t           *key;
523         ISC_LINK(dns_notify_t)  link;
524 };
525
526 #define DNS_NOTIFY_NOSOA        0x0001U
527
528 /*%
529  *      dns_stub holds state while performing a 'stub' transfer.
530  *      'db' is the zone's 'db' or a new one if this is the initial
531  *      transfer.
532  */
533
534 struct dns_stub {
535         unsigned int            magic;
536         isc_mem_t               *mctx;
537         dns_zone_t              *zone;
538         dns_db_t                *db;
539         dns_dbversion_t         *version;
540 };
541
542 /*%
543  *      Hold load state.
544  */
545 struct dns_load {
546         unsigned int            magic;
547         isc_mem_t               *mctx;
548         dns_zone_t              *zone;
549         dns_db_t                *db;
550         isc_time_t              loadtime;
551         dns_rdatacallbacks_t    callbacks;
552 };
553
554 /*%
555  *      Hold forward state.
556  */
557 struct dns_forward {
558         unsigned int            magic;
559         isc_mem_t               *mctx;
560         dns_zone_t              *zone;
561         isc_buffer_t            *msgbuf;
562         dns_request_t           *request;
563         isc_uint32_t            which;
564         isc_sockaddr_t          addr;
565         dns_updatecallback_t    callback;
566         void                    *callback_arg;
567         ISC_LINK(dns_forward_t) link;
568 };
569
570 /*%
571  *      Hold IO request state.
572  */
573 struct dns_io {
574         unsigned int    magic;
575         dns_zonemgr_t   *zmgr;
576         isc_boolean_t   high;
577         isc_task_t      *task;
578         ISC_LINK(dns_io_t) link;
579         isc_event_t     *event;
580 };
581
582 /*%
583  *      Hold state for when we are signing a zone with a new
584  *      DNSKEY as result of an update.
585  */
586 struct dns_signing {
587         unsigned int            magic;
588         dns_db_t                *db;
589         dns_dbiterator_t        *dbiterator;
590         dns_secalg_t            algorithm;
591         isc_uint16_t            keyid;
592         isc_boolean_t           delete;
593         isc_boolean_t           done;
594         ISC_LINK(dns_signing_t) link;
595 };
596
597 struct dns_nsec3chain {
598         unsigned int                    magic;
599         dns_db_t                        *db;
600         dns_dbiterator_t                *dbiterator;
601         dns_rdata_nsec3param_t          nsec3param;
602         unsigned char                   salt[255];
603         isc_boolean_t                   done;
604         isc_boolean_t                   seen_nsec;
605         isc_boolean_t                   delete_nsec;
606         isc_boolean_t                   save_delete_nsec;
607         ISC_LINK(dns_nsec3chain_t)      link;
608 };
609 /*%<
610  * 'dbiterator' contains a iterator for the database.  If we are creating
611  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
612  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
613  * iterated.
614  *
615  * 'nsec3param' contains the parameters of the NSEC3 chain being created
616  * or removed.
617  *
618  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
619  *
620  * 'seen_nsec' will be set to true if, while iterating the zone to create a
621  * NSEC3 chain, a NSEC record is seen.
622  *
623  * 'delete_nsec' will be set to true if, at the completion of the creation
624  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
625  * are in the process of deleting the NSEC chain.
626  *
627  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
628  * so it can be recovered in the event of a error.
629  */
630
631 struct dns_keyfetch {
632         dns_fixedname_t name;
633         dns_rdataset_t keydataset;
634         dns_rdataset_t dnskeyset;
635         dns_rdataset_t dnskeysigset;
636         dns_zone_t *zone;
637         dns_db_t *db;
638         dns_fetch_t *fetch;
639 };
640
641 /*%
642  * Hold state for an asynchronous load
643  */
644 struct dns_asyncload {
645         dns_zone_t *zone;
646         dns_zt_zoneloaded_t loaded;
647         void *loaded_arg;
648 };
649
650 #define HOUR 3600
651 #define DAY (24*HOUR)
652 #define MONTH (30*DAY)
653
654 #define SEND_BUFFER_SIZE 2048
655
656 static void zone_settimer(dns_zone_t *, isc_time_t *);
657 static void cancel_refresh(dns_zone_t *);
658 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
659                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
660 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
661      ISC_FORMAT_PRINTF(3, 4);
662 static void queue_xfrin(dns_zone_t *zone);
663 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
664                                   dns_diff_t *diff, dns_diffop_t op,
665                                   dns_name_t *name, dns_ttl_t ttl,
666                                   dns_rdata_t *rdata);
667 static void zone_unload(dns_zone_t *zone);
668 static void zone_expire(dns_zone_t *zone);
669 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
670 static void zone_idetach(dns_zone_t **zonep);
671 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
672                                    isc_boolean_t dump);
673 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
674 static inline void zone_detachdb(dns_zone_t *zone);
675 static isc_result_t default_journal(dns_zone_t *zone);
676 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
677 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
678                                   isc_time_t loadtime, isc_result_t result);
679 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
680 static void zone_shutdown(isc_task_t *, isc_event_t *);
681 static void zone_loaddone(void *arg, isc_result_t result);
682 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
683                                    isc_time_t loadtime);
684 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
685 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
686 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
687 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
688 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
689                                            isc_uint32_t serial);
690
691 #if 0
692 /* ondestroy example */
693 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
694 #endif
695
696 static void refresh_callback(isc_task_t *, isc_event_t *);
697 static void stub_callback(isc_task_t *, isc_event_t *);
698 static void queue_soa_query(dns_zone_t *zone);
699 static void soa_query(isc_task_t *, isc_event_t *);
700 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
701                      dns_stub_t *stub);
702 static int message_count(dns_message_t *msg, dns_section_t section,
703                          dns_rdatatype_t type);
704 static void notify_cancel(dns_zone_t *zone);
705 static void notify_find_address(dns_notify_t *notify);
706 static void notify_send(dns_notify_t *notify);
707 static isc_result_t notify_createmessage(dns_zone_t *zone,
708                                          unsigned int flags,
709                                          dns_message_t **messagep);
710 static void notify_done(isc_task_t *task, isc_event_t *event);
711 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
712 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
713 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
714 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
715                                              dns_zone_t *zone);
716 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
717 static void zonemgr_free(dns_zonemgr_t *zmgr);
718 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
719                                   isc_task_t *task, isc_taskaction_t action,
720                                   void *arg, dns_io_t **iop);
721 static void zonemgr_putio(dns_io_t **iop);
722 static void zonemgr_cancelio(dns_io_t *io);
723
724 static isc_result_t
725 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
726                  unsigned int *soacount, isc_uint32_t *serial,
727                  isc_uint32_t *refresh, isc_uint32_t *retry,
728                  isc_uint32_t *expire, isc_uint32_t *minimum,
729                  unsigned int *errors);
730
731 static void zone_freedbargs(dns_zone_t *zone);
732 static void forward_callback(isc_task_t *task, isc_event_t *event);
733 static void zone_saveunique(dns_zone_t *zone, const char *path,
734                             const char *templat);
735 static void zone_maintenance(dns_zone_t *zone);
736 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
737 static void dump_done(void *arg, isc_result_t result);
738 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
739                                      isc_uint16_t keyid, isc_boolean_t delete);
740 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
741                                 dns_dbnode_t *node, dns_name_t *name,
742                                 dns_diff_t *diff);
743 static void zone_rekey(dns_zone_t *zone);
744 static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
745
746 #define ENTER zone_debuglog(zone, me, 1, "enter")
747
748 static const unsigned int dbargc_default = 1;
749 static const char *dbargv_default[] = { "rbt" };
750
751 #define DNS_ZONE_JITTER_ADD(a, b, c) \
752         do { \
753                 isc_interval_t _i; \
754                 isc_uint32_t _j; \
755                 _j = isc_random_jitter((b), (b)/4); \
756                 isc_interval_set(&_i, _j, 0); \
757                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
758                         dns_zone_log(zone, ISC_LOG_WARNING, \
759                                      "epoch approaching: upgrade required: " \
760                                      "now + %s failed", #b); \
761                         isc_interval_set(&_i, _j/2, 0); \
762                         (void)isc_time_add((a), &_i, (c)); \
763                 } \
764         } while (0)
765
766 #define DNS_ZONE_TIME_ADD(a, b, c) \
767         do { \
768                 isc_interval_t _i; \
769                 isc_interval_set(&_i, (b), 0); \
770                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
771                         dns_zone_log(zone, ISC_LOG_WARNING, \
772                                      "epoch approaching: upgrade required: " \
773                                      "now + %s failed", #b); \
774                         isc_interval_set(&_i, (b)/2, 0); \
775                         (void)isc_time_add((a), &_i, (c)); \
776                 } \
777         } while (0)
778
779 typedef struct nsec3param nsec3param_t;
780 struct nsec3param {
781         unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
782         unsigned int length;
783         isc_boolean_t nsec;
784         isc_boolean_t replace;
785         ISC_LINK(nsec3param_t)  link;
786 };
787 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
788 struct np3event {
789         isc_event_t event;
790         nsec3param_t params;
791 };
792
793 /*%
794  * Increment resolver-related statistics counters.  Zone must be locked.
795  */
796 static inline void
797 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
798         if (zone->stats != NULL)
799                 isc_stats_increment(zone->stats, counter);
800 }
801
802 /***
803  ***    Public functions.
804  ***/
805
806 isc_result_t
807 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
808         isc_result_t result;
809         dns_zone_t *zone;
810         isc_time_t now;
811
812         REQUIRE(zonep != NULL && *zonep == NULL);
813         REQUIRE(mctx != NULL);
814
815         TIME_NOW(&now);
816         zone = isc_mem_get(mctx, sizeof(*zone));
817         if (zone == NULL)
818                 return (ISC_R_NOMEMORY);
819
820         zone->mctx = NULL;
821         isc_mem_attach(mctx, &zone->mctx);
822
823         result = isc_mutex_init(&zone->lock);
824         if (result != ISC_R_SUCCESS)
825                 goto free_zone;
826
827         result = ZONEDB_INITLOCK(&zone->dblock);
828         if (result != ISC_R_SUCCESS)
829                 goto free_mutex;
830
831         /* XXX MPA check that all elements are initialised */
832 #ifdef DNS_ZONE_CHECKLOCK
833         zone->locked = ISC_FALSE;
834 #endif
835         zone->db = NULL;
836         zone->zmgr = NULL;
837         ISC_LINK_INIT(zone, link);
838         result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
839         if (result != ISC_R_SUCCESS)
840                 goto free_dblock;
841         zone->irefs = 0;
842         dns_name_init(&zone->origin, NULL);
843         zone->strnamerd = NULL;
844         zone->strname = NULL;
845         zone->strrdclass = NULL;
846         zone->strviewname = NULL;
847         zone->masterfile = NULL;
848         zone->masterformat = dns_masterformat_none;
849         zone->keydirectory = NULL;
850         zone->journalsize = -1;
851         zone->journal = NULL;
852         zone->rdclass = dns_rdataclass_none;
853         zone->type = dns_zone_none;
854         zone->flags = 0;
855         zone->options = 0;
856         zone->keyopts = 0;
857         zone->db_argc = 0;
858         zone->db_argv = NULL;
859         isc_time_settoepoch(&zone->expiretime);
860         isc_time_settoepoch(&zone->refreshtime);
861         isc_time_settoepoch(&zone->dumptime);
862         isc_time_settoepoch(&zone->loadtime);
863         zone->notifytime = now;
864         isc_time_settoepoch(&zone->resigntime);
865         isc_time_settoepoch(&zone->keywarntime);
866         isc_time_settoepoch(&zone->signingtime);
867         isc_time_settoepoch(&zone->nsec3chaintime);
868         isc_time_settoepoch(&zone->refreshkeytime);
869         zone->refreshkeyinterval = 0;
870         zone->refreshkeycount = 0;
871         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
872         zone->retry = DNS_ZONE_DEFAULTRETRY;
873         zone->expire = 0;
874         zone->minimum = 0;
875         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
876         zone->minrefresh = DNS_ZONE_MINREFRESH;
877         zone->maxretry = DNS_ZONE_MAXRETRY;
878         zone->minretry = DNS_ZONE_MINRETRY;
879         zone->masters = NULL;
880         zone->masterkeynames = NULL;
881         zone->mastersok = NULL;
882         zone->masterscnt = 0;
883         zone->curmaster = 0;
884         zone->notify = NULL;
885         zone->notifykeynames = NULL;
886         zone->notifytype = dns_notifytype_yes;
887         zone->notifycnt = 0;
888         zone->task = NULL;
889         zone->loadtask = NULL;
890         zone->update_acl = NULL;
891         zone->forward_acl = NULL;
892         zone->notify_acl = NULL;
893         zone->query_acl = NULL;
894         zone->queryon_acl = NULL;
895         zone->xfr_acl = NULL;
896         zone->update_disabled = ISC_FALSE;
897         zone->zero_no_soa_ttl = ISC_TRUE;
898         zone->check_names = dns_severity_ignore;
899         zone->request = NULL;
900         zone->lctx = NULL;
901         zone->readio = NULL;
902         zone->dctx = NULL;
903         zone->writeio = NULL;
904         zone->timer = NULL;
905         zone->idlein = DNS_DEFAULT_IDLEIN;
906         zone->idleout = DNS_DEFAULT_IDLEOUT;
907         zone->log_key_expired_timer = 0;
908         ISC_LIST_INIT(zone->notifies);
909         isc_sockaddr_any(&zone->notifysrc4);
910         isc_sockaddr_any6(&zone->notifysrc6);
911         isc_sockaddr_any(&zone->xfrsource4);
912         isc_sockaddr_any6(&zone->xfrsource6);
913         isc_sockaddr_any(&zone->altxfrsource4);
914         isc_sockaddr_any6(&zone->altxfrsource6);
915         zone->xfr = NULL;
916         zone->tsigkey = NULL;
917         zone->maxxfrin = MAX_XFER_TIME;
918         zone->maxxfrout = MAX_XFER_TIME;
919         zone->ssutable = NULL;
920         zone->sigvalidityinterval = 30 * 24 * 3600;
921         zone->sigresigninginterval = 7 * 24 * 3600;
922         zone->view = NULL;
923         zone->acache = NULL;
924         zone->checkmx = NULL;
925         zone->checksrv = NULL;
926         zone->checkns = NULL;
927         ISC_LINK_INIT(zone, statelink);
928         zone->statelist = NULL;
929         zone->stats = NULL;
930         zone->requeststats_on = ISC_FALSE;
931         zone->statlevel = dns_zonestat_none;
932         zone->requeststats = NULL;
933         zone->rcvquerystats = NULL;
934         zone->notifydelay = 5;
935         zone->isself = NULL;
936         zone->isselfarg = NULL;
937         ISC_LIST_INIT(zone->signing);
938         ISC_LIST_INIT(zone->nsec3chain);
939         zone->signatures = 10;
940         zone->nodes = 100;
941         zone->privatetype = (dns_rdatatype_t)0xffffU;
942         zone->added = ISC_FALSE;
943         zone->is_rpz = ISC_FALSE;
944         ISC_LIST_INIT(zone->forwards);
945         zone->raw = NULL;
946         zone->secure = NULL;
947         zone->sourceserial = 0;
948         zone->sourceserialset = ISC_FALSE;
949
950         zone->magic = ZONE_MAGIC;
951
952         /* Must be after magic is set. */
953         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
954         if (result != ISC_R_SUCCESS)
955                 goto free_erefs;
956
957         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
958                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
959                        NULL, NULL);
960         *zonep = zone;
961         return (ISC_R_SUCCESS);
962
963  free_erefs:
964         isc_refcount_decrement(&zone->erefs, NULL);
965         isc_refcount_destroy(&zone->erefs);
966
967  free_dblock:
968         ZONEDB_DESTROYLOCK(&zone->dblock);
969
970  free_mutex:
971         DESTROYLOCK(&zone->lock);
972
973  free_zone:
974         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
975         return (result);
976 }
977
978 /*
979  * Free a zone.  Because we require that there be no more
980  * outstanding events or references, no locking is necessary.
981  */
982 static void
983 zone_free(dns_zone_t *zone) {
984         isc_mem_t *mctx = NULL;
985         dns_signing_t *signing;
986         dns_nsec3chain_t *nsec3chain;
987
988         REQUIRE(DNS_ZONE_VALID(zone));
989         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
990         REQUIRE(zone->irefs == 0);
991         REQUIRE(!LOCKED_ZONE(zone));
992         REQUIRE(zone->timer == NULL);
993         REQUIRE(zone->zmgr == NULL);
994
995         /*
996          * Managed objects.  Order is important.
997          */
998         if (zone->request != NULL)
999                 dns_request_destroy(&zone->request); /* XXXMPA */
1000         INSIST(zone->readio == NULL);
1001         INSIST(zone->statelist == NULL);
1002         INSIST(zone->writeio == NULL);
1003
1004         if (zone->task != NULL)
1005                 isc_task_detach(&zone->task);
1006         if (zone->loadtask != NULL)
1007                 isc_task_detach(&zone->loadtask);
1008
1009         /* Unmanaged objects */
1010         for (signing = ISC_LIST_HEAD(zone->signing);
1011              signing != NULL;
1012              signing = ISC_LIST_HEAD(zone->signing)) {
1013                 ISC_LIST_UNLINK(zone->signing, signing, link);
1014                 dns_db_detach(&signing->db);
1015                 dns_dbiterator_destroy(&signing->dbiterator);
1016                 isc_mem_put(zone->mctx, signing, sizeof *signing);
1017         }
1018         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
1019              nsec3chain != NULL;
1020              nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
1021                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1022                 dns_db_detach(&nsec3chain->db);
1023                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1024                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1025         }
1026         if (zone->masterfile != NULL)
1027                 isc_mem_free(zone->mctx, zone->masterfile);
1028         zone->masterfile = NULL;
1029         if (zone->keydirectory != NULL)
1030                 isc_mem_free(zone->mctx, zone->keydirectory);
1031         zone->keydirectory = NULL;
1032         zone->journalsize = -1;
1033         if (zone->journal != NULL)
1034                 isc_mem_free(zone->mctx, zone->journal);
1035         zone->journal = NULL;
1036         if (zone->stats != NULL)
1037                 isc_stats_detach(&zone->stats);
1038         if (zone->requeststats != NULL)
1039                 isc_stats_detach(&zone->requeststats);
1040         if(zone->rcvquerystats != NULL )
1041                 dns_stats_detach(&zone->rcvquerystats);
1042         if (zone->db != NULL)
1043                 zone_detachdb(zone);
1044         if (zone->acache != NULL)
1045                 dns_acache_detach(&zone->acache);
1046         zone_freedbargs(zone);
1047         RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
1048                       == ISC_R_SUCCESS);
1049         RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
1050                       == ISC_R_SUCCESS);
1051         zone->check_names = dns_severity_ignore;
1052         if (zone->update_acl != NULL)
1053                 dns_acl_detach(&zone->update_acl);
1054         if (zone->forward_acl != NULL)
1055                 dns_acl_detach(&zone->forward_acl);
1056         if (zone->notify_acl != NULL)
1057                 dns_acl_detach(&zone->notify_acl);
1058         if (zone->query_acl != NULL)
1059                 dns_acl_detach(&zone->query_acl);
1060         if (zone->queryon_acl != NULL)
1061                 dns_acl_detach(&zone->queryon_acl);
1062         if (zone->xfr_acl != NULL)
1063                 dns_acl_detach(&zone->xfr_acl);
1064         if (dns_name_dynamic(&zone->origin))
1065                 dns_name_free(&zone->origin, zone->mctx);
1066         if (zone->strnamerd != NULL)
1067                 isc_mem_free(zone->mctx, zone->strnamerd);
1068         if (zone->strname != NULL)
1069                 isc_mem_free(zone->mctx, zone->strname);
1070         if (zone->strrdclass != NULL)
1071                 isc_mem_free(zone->mctx, zone->strrdclass);
1072         if (zone->strviewname != NULL)
1073                 isc_mem_free(zone->mctx, zone->strviewname);
1074         if (zone->ssutable != NULL)
1075                 dns_ssutable_detach(&zone->ssutable);
1076
1077         /* last stuff */
1078         ZONEDB_DESTROYLOCK(&zone->dblock);
1079         DESTROYLOCK(&zone->lock);
1080         isc_refcount_destroy(&zone->erefs);
1081         zone->magic = 0;
1082         mctx = zone->mctx;
1083         isc_mem_put(mctx, zone, sizeof(*zone));
1084         isc_mem_detach(&mctx);
1085 }
1086
1087 /*
1088  * Returns ISC_TRUE iff this the signed side of an inline-signing zone.
1089  * Caller should hold zone lock.
1090  */
1091 static inline isc_boolean_t
1092 inline_secure(dns_zone_t *zone) {
1093         REQUIRE(DNS_ZONE_VALID(zone));
1094         if (zone->raw != NULL)
1095                 return (ISC_TRUE);
1096         return (ISC_FALSE);
1097 }
1098
1099 /*
1100  * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone
1101  * Caller should hold zone lock.
1102  */
1103 static inline isc_boolean_t
1104 inline_raw(dns_zone_t *zone) {
1105         REQUIRE(DNS_ZONE_VALID(zone));
1106         if (zone->secure != NULL)
1107                 return (ISC_TRUE);
1108         return (ISC_FALSE);
1109 }
1110
1111 /*
1112  *      Single shot.
1113  */
1114 void
1115 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1116         char namebuf[1024];
1117
1118         REQUIRE(DNS_ZONE_VALID(zone));
1119         REQUIRE(rdclass != dns_rdataclass_none);
1120
1121         /*
1122          * Test and set.
1123          */
1124         LOCK_ZONE(zone);
1125         REQUIRE(zone->rdclass == dns_rdataclass_none ||
1126                 zone->rdclass == rdclass);
1127         zone->rdclass = rdclass;
1128
1129         if (zone->strnamerd != NULL)
1130                 isc_mem_free(zone->mctx, zone->strnamerd);
1131         if (zone->strrdclass != NULL)
1132                 isc_mem_free(zone->mctx, zone->strrdclass);
1133
1134         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1135         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1136         zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1137         zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1138
1139         if (inline_secure(zone))
1140                 dns_zone_setclass(zone->raw, rdclass);
1141         UNLOCK_ZONE(zone);
1142 }
1143
1144 dns_rdataclass_t
1145 dns_zone_getclass(dns_zone_t *zone) {
1146         REQUIRE(DNS_ZONE_VALID(zone));
1147
1148         return (zone->rdclass);
1149 }
1150
1151 void
1152 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1153         REQUIRE(DNS_ZONE_VALID(zone));
1154
1155         LOCK_ZONE(zone);
1156         zone->notifytype = notifytype;
1157         UNLOCK_ZONE(zone);
1158 }
1159
1160 isc_result_t
1161 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1162         isc_result_t result;
1163         unsigned int soacount;
1164
1165         REQUIRE(DNS_ZONE_VALID(zone));
1166         REQUIRE(serialp != NULL);
1167
1168         LOCK_ZONE(zone);
1169         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1170         if (zone->db != NULL) {
1171                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1172                                           serialp, NULL, NULL, NULL, NULL,
1173                                           NULL);
1174                 if (result == ISC_R_SUCCESS && soacount == 0)
1175                         result = ISC_R_FAILURE;
1176         } else
1177                 result = DNS_R_NOTLOADED;
1178         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1179         UNLOCK_ZONE(zone);
1180
1181         return (result);
1182 }
1183
1184 isc_uint32_t
1185 dns_zone_getserial(dns_zone_t *zone) {
1186         isc_result_t result;
1187         isc_uint32_t serial;
1188
1189         result = dns_zone_getserial2(zone, &serial);
1190         if (result != ISC_R_SUCCESS)
1191                 serial = 0; /* XXX: not really correct, but no other choice */
1192
1193         return (serial);
1194 }
1195
1196 /*
1197  *      Single shot.
1198  */
1199 void
1200 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1201         char namebuf[1024];
1202
1203         REQUIRE(DNS_ZONE_VALID(zone));
1204         REQUIRE(type != dns_zone_none);
1205
1206         /*
1207          * Test and set.
1208          */
1209         LOCK_ZONE(zone);
1210         REQUIRE(zone->type == dns_zone_none || zone->type == type);
1211         zone->type = type;
1212
1213         if (zone->strnamerd != NULL)
1214                 isc_mem_free(zone->mctx, zone->strnamerd);
1215
1216         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1217         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1218         UNLOCK_ZONE(zone);
1219 }
1220
1221 static void
1222 zone_freedbargs(dns_zone_t *zone) {
1223         unsigned int i;
1224
1225         /* Free the old database argument list. */
1226         if (zone->db_argv != NULL) {
1227                 for (i = 0; i < zone->db_argc; i++)
1228                         isc_mem_free(zone->mctx, zone->db_argv[i]);
1229                 isc_mem_put(zone->mctx, zone->db_argv,
1230                             zone->db_argc * sizeof(*zone->db_argv));
1231         }
1232         zone->db_argc = 0;
1233         zone->db_argv = NULL;
1234 }
1235
1236 isc_result_t
1237 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1238         size_t size = 0;
1239         unsigned int i;
1240         isc_result_t result = ISC_R_SUCCESS;
1241         void *mem;
1242         char **tmp, *tmp2;
1243
1244         REQUIRE(DNS_ZONE_VALID(zone));
1245         REQUIRE(argv != NULL && *argv == NULL);
1246
1247         LOCK_ZONE(zone);
1248         size = (zone->db_argc + 1) * sizeof(char *);
1249         for (i = 0; i < zone->db_argc; i++)
1250                 size += strlen(zone->db_argv[i]) + 1;
1251         mem = isc_mem_allocate(mctx, size);
1252         if (mem != NULL) {
1253                 tmp = mem;
1254                 tmp2 = mem;
1255                 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1256                 for (i = 0; i < zone->db_argc; i++) {
1257                         *tmp++ = tmp2;
1258                         strcpy(tmp2, zone->db_argv[i]);
1259                         tmp2 += strlen(tmp2) + 1;
1260                 }
1261                 *tmp = NULL;
1262         } else
1263                 result = ISC_R_NOMEMORY;
1264         UNLOCK_ZONE(zone);
1265         *argv = mem;
1266         return (result);
1267 }
1268
1269 isc_result_t
1270 dns_zone_setdbtype(dns_zone_t *zone,
1271                    unsigned int dbargc, const char * const *dbargv) {
1272         isc_result_t result = ISC_R_SUCCESS;
1273         char **new = NULL;
1274         unsigned int i;
1275
1276         REQUIRE(DNS_ZONE_VALID(zone));
1277         REQUIRE(dbargc >= 1);
1278         REQUIRE(dbargv != NULL);
1279
1280         LOCK_ZONE(zone);
1281
1282         /* Set up a new database argument list. */
1283         new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1284         if (new == NULL)
1285                 goto nomem;
1286         for (i = 0; i < dbargc; i++)
1287                 new[i] = NULL;
1288         for (i = 0; i < dbargc; i++) {
1289                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1290                 if (new[i] == NULL)
1291                         goto nomem;
1292         }
1293
1294         /* Free the old list. */
1295         zone_freedbargs(zone);
1296
1297         zone->db_argc = dbargc;
1298         zone->db_argv = new;
1299         result = ISC_R_SUCCESS;
1300         goto unlock;
1301
1302  nomem:
1303         if (new != NULL) {
1304                 for (i = 0; i < dbargc; i++)
1305                         if (new[i] != NULL)
1306                                 isc_mem_free(zone->mctx, new[i]);
1307                 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1308         }
1309         result = ISC_R_NOMEMORY;
1310
1311  unlock:
1312         UNLOCK_ZONE(zone);
1313         return (result);
1314 }
1315
1316 void
1317 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1318         char namebuf[1024];
1319         REQUIRE(DNS_ZONE_VALID(zone));
1320
1321         LOCK_ZONE(zone);
1322         if (zone->view != NULL)
1323                 dns_view_weakdetach(&zone->view);
1324         dns_view_weakattach(view, &zone->view);
1325
1326         if (zone->strviewname != NULL)
1327                 isc_mem_free(zone->mctx, zone->strviewname);
1328         if (zone->strnamerd != NULL)
1329                 isc_mem_free(zone->mctx, zone->strnamerd);
1330
1331         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1332         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1333         zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1334         zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1335
1336         if (inline_secure(zone))
1337                 dns_zone_setview(zone->raw, view);
1338
1339         UNLOCK_ZONE(zone);
1340 }
1341
1342 dns_view_t *
1343 dns_zone_getview(dns_zone_t *zone) {
1344         REQUIRE(DNS_ZONE_VALID(zone));
1345
1346         return (zone->view);
1347 }
1348
1349
1350 isc_result_t
1351 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1352         isc_result_t result;
1353         char namebuf[1024];
1354
1355         REQUIRE(DNS_ZONE_VALID(zone));
1356         REQUIRE(origin != NULL);
1357
1358         LOCK_ZONE(zone);
1359         if (dns_name_dynamic(&zone->origin)) {
1360                 dns_name_free(&zone->origin, zone->mctx);
1361                 dns_name_init(&zone->origin, NULL);
1362         }
1363         result = dns_name_dup(origin, zone->mctx, &zone->origin);
1364
1365         if (zone->strnamerd != NULL)
1366                 isc_mem_free(zone->mctx, zone->strnamerd);
1367         if (zone->strname != NULL)
1368                 isc_mem_free(zone->mctx, zone->strname);
1369
1370         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1371         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1372         zone_name_tostr(zone, namebuf, sizeof namebuf);
1373         zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1374
1375         if (result == ISC_R_SUCCESS && inline_secure(zone))
1376                 result = dns_zone_setorigin(zone->raw, origin);
1377         UNLOCK_ZONE(zone);
1378         return (result);
1379 }
1380
1381 void
1382 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1383         REQUIRE(DNS_ZONE_VALID(zone));
1384         REQUIRE(acache != NULL);
1385
1386         LOCK_ZONE(zone);
1387         if (zone->acache != NULL)
1388                 dns_acache_detach(&zone->acache);
1389         dns_acache_attach(acache, &zone->acache);
1390         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1391         if (zone->db != NULL) {
1392                 isc_result_t result;
1393
1394                 /*
1395                  * If the zone reuses an existing DB, the DB needs to be
1396                  * set in the acache explicitly.  We can safely ignore the
1397                  * case where the DB is already set.  If other error happens,
1398                  * the acache will not work effectively.
1399                  */
1400                 result = dns_acache_setdb(acache, zone->db);
1401                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1402                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1403                                          "dns_acache_setdb() failed: %s",
1404                                          isc_result_totext(result));
1405                 }
1406         }
1407         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1408         UNLOCK_ZONE(zone);
1409 }
1410
1411 static isc_result_t
1412 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1413         char *copy;
1414
1415         if (value != NULL) {
1416                 copy = isc_mem_strdup(zone->mctx, value);
1417                 if (copy == NULL)
1418                         return (ISC_R_NOMEMORY);
1419         } else {
1420                 copy = NULL;
1421         }
1422
1423         if (*field != NULL)
1424                 isc_mem_free(zone->mctx, *field);
1425
1426         *field = copy;
1427         return (ISC_R_SUCCESS);
1428 }
1429
1430 isc_result_t
1431 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1432         return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1433 }
1434
1435 isc_result_t
1436 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1437                   dns_masterformat_t format) {
1438         isc_result_t result = ISC_R_SUCCESS;
1439
1440         REQUIRE(DNS_ZONE_VALID(zone));
1441
1442         LOCK_ZONE(zone);
1443         result = dns_zone_setstring(zone, &zone->masterfile, file);
1444         if (result == ISC_R_SUCCESS) {
1445                 zone->masterformat = format;
1446                 result = default_journal(zone);
1447         }
1448         UNLOCK_ZONE(zone);
1449
1450         return (result);
1451 }
1452
1453 const char *
1454 dns_zone_getfile(dns_zone_t *zone) {
1455         REQUIRE(DNS_ZONE_VALID(zone));
1456
1457         return (zone->masterfile);
1458 }
1459
1460 static isc_result_t
1461 default_journal(dns_zone_t *zone) {
1462         isc_result_t result;
1463         char *journal;
1464
1465         REQUIRE(DNS_ZONE_VALID(zone));
1466         REQUIRE(LOCKED_ZONE(zone));
1467
1468         if (zone->masterfile != NULL) {
1469                 /* Calculate string length including '\0'. */
1470                 int len = strlen(zone->masterfile) + sizeof(".jnl");
1471                 journal = isc_mem_allocate(zone->mctx, len);
1472                 if (journal == NULL)
1473                         return (ISC_R_NOMEMORY);
1474                 strcpy(journal, zone->masterfile);
1475                 strcat(journal, ".jnl");
1476         } else {
1477                 journal = NULL;
1478         }
1479         result = dns_zone_setstring(zone, &zone->journal, journal);
1480         if (journal != NULL)
1481                 isc_mem_free(zone->mctx, journal);
1482         return (result);
1483 }
1484
1485 isc_result_t
1486 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1487         isc_result_t result = ISC_R_SUCCESS;
1488
1489         REQUIRE(DNS_ZONE_VALID(zone));
1490
1491         LOCK_ZONE(zone);
1492         result = dns_zone_setstring(zone, &zone->journal, journal);
1493         UNLOCK_ZONE(zone);
1494
1495         return (result);
1496 }
1497
1498 char *
1499 dns_zone_getjournal(dns_zone_t *zone) {
1500         REQUIRE(DNS_ZONE_VALID(zone));
1501
1502         return (zone->journal);
1503 }
1504
1505 /*
1506  * Return true iff the zone is "dynamic", in the sense that the zone's
1507  * master file (if any) is written by the server, rather than being
1508  * updated manually and read by the server.
1509  *
1510  * This is true for slave zones, stub zones, key zones, and zones that
1511  * allow dynamic updates either by having an update policy ("ssutable")
1512  * or an "allow-update" ACL with a value other than exactly "{ none; }".
1513  */
1514 isc_boolean_t
1515 dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) {
1516         REQUIRE(DNS_ZONE_VALID(zone));
1517
1518         if (zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1519             zone->type == dns_zone_key ||
1520             (zone->type == dns_zone_redirect && zone->masters != NULL))
1521                 return (ISC_TRUE);
1522
1523         /* If !ignore_freeze, we need check whether updates are disabled.  */
1524         if (zone->type == dns_zone_master &&
1525             (!zone->update_disabled || ignore_freeze) &&
1526             ((zone->ssutable != NULL) ||
1527              (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1528                 return (ISC_TRUE);
1529
1530         return (ISC_FALSE);
1531
1532 }
1533
1534 /*
1535  * Set the response policy index and information for a zone.
1536  */
1537 isc_result_t
1538 dns_zone_rpz_enable(dns_zone_t *zone) {
1539         /*
1540          * Only RBTDB zones can be used for response policy zones,
1541          * because only they have the code to load the create the summary data.
1542          * Only zones that are loaded instead of mmap()ed create the
1543          * summary data and so can be policy zones.
1544          */
1545         if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1546             strcmp(zone->db_argv[0], "rbt64") != 0)
1547                 return (ISC_R_NOTIMPLEMENTED);
1548
1549         zone->is_rpz = ISC_TRUE;
1550
1551         return (ISC_R_SUCCESS);
1552 }
1553
1554 isc_boolean_t
1555 dns_zone_get_rpz(dns_zone_t *zone) {
1556         return (zone->is_rpz);
1557 }
1558
1559 /*
1560  * If a zone is a response policy zone, mark its new database.
1561  */
1562 isc_result_t
1563 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1564 #ifdef BIND9
1565         if (zone->is_rpz)
1566                 return (dns_db_rpz_enabled(db, NULL));
1567 #endif
1568         return (ISC_R_SUCCESS);
1569 }
1570
1571 static isc_result_t
1572 zone_load(dns_zone_t *zone, unsigned int flags) {
1573         isc_result_t result;
1574         isc_time_t now;
1575         isc_time_t loadtime, filetime;
1576         dns_db_t *db = NULL;
1577         isc_boolean_t rbt, hasraw;
1578
1579         REQUIRE(DNS_ZONE_VALID(zone));
1580
1581         LOCK_ZONE(zone);
1582         hasraw = inline_secure(zone);
1583         if (hasraw) {
1584                 result = zone_load(zone->raw, flags);
1585                 if (result != ISC_R_SUCCESS) {
1586                         UNLOCK_ZONE(zone);
1587                         return(result);
1588                 }
1589                 LOCK_ZONE(zone->raw);
1590         }
1591
1592         TIME_NOW(&now);
1593
1594         INSIST(zone->type != dns_zone_none);
1595
1596         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1597                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1598                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1599                 result = DNS_R_CONTINUE;
1600                 goto cleanup;
1601         }
1602
1603         INSIST(zone->db_argc >= 1);
1604
1605         rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1606               strcmp(zone->db_argv[0], "rbt64") == 0;
1607
1608         if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1609                 /*
1610                  * The zone has no master file configured.
1611                  */
1612                 result = ISC_R_SUCCESS;
1613                 goto cleanup;
1614         }
1615
1616         if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) {
1617                 /*
1618                  * This is a slave, stub, or dynamically updated
1619                  * zone being reloaded.  Do nothing - the database
1620                  * we already have is guaranteed to be up-to-date.
1621                  */
1622                 if (zone->type == dns_zone_master)
1623                         result = DNS_R_DYNAMIC;
1624                 else
1625                         result = ISC_R_SUCCESS;
1626                 goto cleanup;
1627         }
1628
1629         /*
1630          * Store the current time before the zone is loaded, so that if the
1631          * file changes between the time of the load and the time that
1632          * zone->loadtime is set, then the file will still be reloaded
1633          * the next time dns_zone_load is called.
1634          */
1635         TIME_NOW(&loadtime);
1636
1637         /*
1638          * Don't do the load if the file that stores the zone is older
1639          * than the last time the zone was loaded.  If the zone has not
1640          * been loaded yet, zone->loadtime will be the epoch.
1641          */
1642         if (zone->masterfile != NULL) {
1643                 /*
1644                  * The file is already loaded.  If we are just doing a
1645                  * "rndc reconfig", we are done.
1646                  */
1647                 if (!isc_time_isepoch(&zone->loadtime) &&
1648                     (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1649                         result = ISC_R_SUCCESS;
1650                         goto cleanup;
1651                 }
1652
1653                 result = isc_file_getmodtime(zone->masterfile, &filetime);
1654                 if (result == ISC_R_SUCCESS) {
1655                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1656                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1657                             isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1658                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1659                                              "skipping load: master file "
1660                                              "older than last load");
1661                                 result = DNS_R_UPTODATE;
1662                                 goto cleanup;
1663                         }
1664                         loadtime = filetime;
1665                 }
1666         }
1667
1668         /*
1669          * Built in zones (with the exception of empty zones) don't need
1670          * to be reloaded.
1671          */
1672         if (zone->type == dns_zone_master &&
1673             strcmp(zone->db_argv[0], "_builtin") == 0 &&
1674             (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1675             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1676                 result = ISC_R_SUCCESS;
1677                 goto cleanup;
1678         }
1679
1680         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1681              (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
1682             rbt) {
1683                 if (zone->masterfile == NULL ||
1684                     !isc_file_exists(zone->masterfile)) {
1685                         if (zone->masterfile != NULL) {
1686                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1687                                              "no master file");
1688                         }
1689                         zone->refreshtime = now;
1690                         if (zone->task != NULL)
1691                                 zone_settimer(zone, &now);
1692                         result = ISC_R_SUCCESS;
1693                         goto cleanup;
1694                 }
1695         }
1696
1697         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1698
1699         result = dns_db_create(zone->mctx, zone->db_argv[0],
1700                                &zone->origin, (zone->type == dns_zone_stub) ?
1701                                dns_dbtype_stub : dns_dbtype_zone,
1702                                zone->rdclass,
1703                                zone->db_argc - 1, zone->db_argv + 1,
1704                                &db);
1705
1706         if (result != ISC_R_SUCCESS) {
1707                 dns_zone_log(zone, ISC_LOG_ERROR,
1708                              "loading zone: creating database: %s",
1709                              isc_result_totext(result));
1710                 goto cleanup;
1711         }
1712         dns_db_settask(db, zone->task);
1713
1714         if (! dns_db_ispersistent(db)) {
1715                 if (zone->masterfile != NULL) {
1716                         result = zone_startload(db, zone, loadtime);
1717                 } else {
1718                         result = DNS_R_NOMASTERFILE;
1719                         if (zone->type == dns_zone_master ||
1720                             (zone->type == dns_zone_redirect &&
1721                              zone->masters == NULL)) {
1722                                 dns_zone_log(zone, ISC_LOG_ERROR,
1723                                              "loading zone: "
1724                                              "no master file configured");
1725                                 goto cleanup;
1726                         }
1727                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1728                                      "no master file configured: continuing");
1729                 }
1730         }
1731
1732         if (result == DNS_R_CONTINUE) {
1733                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1734                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1735                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1736                 goto cleanup;
1737         }
1738
1739         result = zone_postload(zone, db, loadtime, result);
1740
1741  cleanup:
1742         if (hasraw)
1743                 UNLOCK_ZONE(zone->raw);
1744         UNLOCK_ZONE(zone);
1745         if (db != NULL)
1746                 dns_db_detach(&db);
1747         return (result);
1748 }
1749
1750 isc_result_t
1751 dns_zone_load(dns_zone_t *zone) {
1752         return (zone_load(zone, 0));
1753 }
1754
1755 isc_result_t
1756 dns_zone_loadnew(dns_zone_t *zone) {
1757         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1758 }
1759
1760 static void
1761 zone_asyncload(isc_task_t *task, isc_event_t *event) {
1762         dns_asyncload_t *asl = event->ev_arg;
1763         dns_zone_t *zone = asl->zone;
1764         isc_result_t result = ISC_R_SUCCESS;
1765
1766         UNUSED(task);
1767
1768         REQUIRE(DNS_ZONE_VALID(zone));
1769
1770         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1771                 result = ISC_R_CANCELED;
1772         isc_event_free(&event);
1773         if (result == ISC_R_CANCELED ||
1774             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
1775                 goto cleanup;
1776
1777         zone_load(zone, 0);
1778
1779         LOCK_ZONE(zone);
1780         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1781         UNLOCK_ZONE(zone);
1782
1783         /* Inform the zone table we've finished loading */
1784         if (asl->loaded != NULL)
1785                 (asl->loaded)(asl->loaded_arg, zone, task);
1786
1787  cleanup:
1788         isc_mem_put(zone->mctx, asl, sizeof (*asl));
1789         dns_zone_idetach(&zone);
1790 }
1791
1792 isc_result_t
1793 dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
1794         isc_event_t *e;
1795         dns_asyncload_t *asl = NULL;
1796         isc_result_t result = ISC_R_SUCCESS;
1797
1798         REQUIRE(DNS_ZONE_VALID(zone));
1799
1800         if (zone->zmgr == NULL)
1801                 return (ISC_R_FAILURE);
1802
1803         asl = isc_mem_get(zone->mctx, sizeof (*asl));
1804         if (asl == NULL)
1805                 CHECK(ISC_R_NOMEMORY);
1806
1807         asl->zone = NULL;
1808         asl->loaded = done;
1809         asl->loaded_arg = arg;
1810
1811         e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
1812                                DNS_EVENT_ZONELOAD,
1813                                zone_asyncload, asl,
1814                                sizeof(isc_event_t));
1815         if (e == NULL)
1816                 CHECK(ISC_R_NOMEMORY);
1817
1818         LOCK_ZONE(zone);
1819         zone_iattach(zone, &asl->zone);
1820         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1821         isc_task_send(zone->loadtask, &e);
1822         UNLOCK_ZONE(zone);
1823
1824         return (ISC_R_SUCCESS);
1825
1826   failure:
1827         if (asl != NULL)
1828                 isc_mem_put(zone->mctx, asl, sizeof (*asl));
1829         return (result);
1830 }
1831
1832 isc_boolean_t
1833 dns__zone_loadpending(dns_zone_t *zone) {
1834         REQUIRE(DNS_ZONE_VALID(zone));
1835
1836         return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)));
1837 }
1838
1839 isc_result_t
1840 dns_zone_loadandthaw(dns_zone_t *zone) {
1841         isc_result_t result;
1842
1843         if (inline_raw(zone))
1844                 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW);
1845         else
1846                 result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1847
1848         switch (result) {
1849         case DNS_R_CONTINUE:
1850                 /* Deferred thaw. */
1851                 break;
1852         case DNS_R_UPTODATE:
1853         case ISC_R_SUCCESS:
1854         case DNS_R_SEENINCLUDE:
1855                 zone->update_disabled = ISC_FALSE;
1856                 break;
1857         case DNS_R_NOMASTERFILE:
1858                 zone->update_disabled = ISC_FALSE;
1859                 break;
1860         default:
1861                 /* Error, remain in disabled state. */
1862                 break;
1863         }
1864         return (result);
1865 }
1866
1867 static unsigned int
1868 get_master_options(dns_zone_t *zone) {
1869         unsigned int options;
1870
1871         options = DNS_MASTER_ZONE;
1872         if (zone->type == dns_zone_slave ||
1873             (zone->type == dns_zone_redirect && zone->masters == NULL))
1874                 options |= DNS_MASTER_SLAVE;
1875         if (zone->type == dns_zone_key)
1876                 options |= DNS_MASTER_KEY;
1877         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1878                 options |= DNS_MASTER_CHECKNS;
1879         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1880                 options |= DNS_MASTER_FATALNS;
1881         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1882                 options |= DNS_MASTER_CHECKNAMES;
1883         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1884                 options |= DNS_MASTER_CHECKNAMESFAIL;
1885         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1886                 options |= DNS_MASTER_CHECKMX;
1887         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1888                 options |= DNS_MASTER_CHECKMXFAIL;
1889         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1890                 options |= DNS_MASTER_CHECKWILDCARD;
1891         if (inline_secure(zone) || (zone->type == dns_zone_master &&
1892             ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1893               zone->ssutable != NULL)))
1894                 options |= DNS_MASTER_RESIGN;
1895         return (options);
1896 }
1897
1898 static void
1899 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1900         dns_load_t *load = event->ev_arg;
1901         isc_result_t result = ISC_R_SUCCESS;
1902         unsigned int options;
1903
1904         REQUIRE(DNS_LOAD_VALID(load));
1905
1906         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1907                 result = ISC_R_CANCELED;
1908         isc_event_free(&event);
1909         if (result == ISC_R_CANCELED)
1910                 goto fail;
1911
1912         options = get_master_options(load->zone);
1913
1914         result = dns_master_loadfileinc3(load->zone->masterfile,
1915                                          dns_db_origin(load->db),
1916                                          dns_db_origin(load->db),
1917                                          load->zone->rdclass, options, 0,
1918                                          &load->callbacks, task,
1919                                          zone_loaddone, load,
1920                                          &load->zone->lctx, load->zone->mctx,
1921                                          load->zone->masterformat);
1922         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1923             result != DNS_R_SEENINCLUDE)
1924                 goto fail;
1925         return;
1926
1927  fail:
1928         zone_loaddone(load, result);
1929 }
1930
1931 static void
1932 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
1933         isc_result_t result;
1934         unsigned int soacount;
1935
1936         LOCK(&raw->lock);
1937         if (raw->db != NULL) {
1938                 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
1939                                           &rawdata->sourceserial,
1940                                           NULL, NULL, NULL, NULL,
1941                                           NULL);
1942                 if (result == ISC_R_SUCCESS && soacount > 0U)
1943                         rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
1944         }
1945         UNLOCK(&raw->lock);
1946 }
1947
1948 static void
1949 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1950         const char me[] = "zone_gotwritehandle";
1951         dns_zone_t *zone = event->ev_arg;
1952         isc_result_t result = ISC_R_SUCCESS;
1953         dns_dbversion_t *version = NULL;
1954         dns_masterrawheader_t rawdata;
1955
1956         REQUIRE(DNS_ZONE_VALID(zone));
1957         INSIST(task == zone->task);
1958         ENTER;
1959
1960         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1961                 result = ISC_R_CANCELED;
1962         isc_event_free(&event);
1963         if (result == ISC_R_CANCELED)
1964                 goto fail;
1965
1966         LOCK_ZONE(zone);
1967         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1968         if (zone->db != NULL) {
1969                 const dns_master_style_t *output_style;
1970
1971                 dns_db_currentversion(zone->db, &version);
1972                 dns_master_initrawheader(&rawdata);
1973                 if (inline_secure(zone))
1974                         get_raw_serial(zone->raw, &rawdata);
1975                 if (zone->type == dns_zone_key)
1976                         output_style = &dns_master_style_keyzone;
1977                 else
1978                         output_style = &dns_master_style_default;
1979                 result = dns_master_dumpinc3(zone->mctx, zone->db, version,
1980                                              output_style, zone->masterfile,
1981                                              zone->task, dump_done, zone,                                                    &zone->dctx, zone->masterformat,
1982                                              &rawdata);
1983                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
1984         } else
1985                 result = ISC_R_CANCELED;
1986         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1987         UNLOCK_ZONE(zone);
1988         if (result != DNS_R_CONTINUE)
1989                 goto fail;
1990         return;
1991
1992  fail:
1993         dump_done(zone, result);
1994 }
1995
1996 /*
1997  * Save the raw serial number for inline-signing zones.
1998  * (XXX: Other information from the header will be used
1999  * for other purposes in the future, but for now this is
2000  * all we're interested in.)
2001  */
2002 static void
2003 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2004         if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
2005                 return;
2006
2007         zone->sourceserial = header->sourceserial;
2008         zone->sourceserialset = ISC_TRUE;
2009 }
2010
2011 void
2012 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2013         if (zone == NULL)
2014                 return;
2015
2016         LOCK_ZONE(zone);
2017         zone_setrawdata(zone, header);
2018         UNLOCK_ZONE(zone);
2019 }
2020
2021 static isc_result_t
2022 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2023         dns_load_t *load;
2024         isc_result_t result;
2025         isc_result_t tresult;
2026         unsigned int options;
2027
2028         result = dns_zone_rpz_enable_db(zone, db);
2029         if (result != ISC_R_SUCCESS)
2030                 return (result);
2031         options = get_master_options(zone);
2032         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
2033                 options |= DNS_MASTER_MANYERRORS;
2034
2035         if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2036                 load = isc_mem_get(zone->mctx, sizeof(*load));
2037                 if (load == NULL)
2038                         return (ISC_R_NOMEMORY);
2039
2040                 load->mctx = NULL;
2041                 load->zone = NULL;
2042                 load->db = NULL;
2043                 load->loadtime = loadtime;
2044                 load->magic = LOAD_MAGIC;
2045
2046                 isc_mem_attach(zone->mctx, &load->mctx);
2047                 zone_iattach(zone, &load->zone);
2048                 dns_db_attach(db, &load->db);
2049                 dns_rdatacallbacks_init(&load->callbacks);
2050                 load->callbacks.rawdata = zone_setrawdata;
2051                 zone_iattach(zone, &load->callbacks.zone);
2052                 result = dns_db_beginload(db, &load->callbacks.add,
2053                                           &load->callbacks.add_private);
2054                 if (result != ISC_R_SUCCESS)
2055                         goto cleanup;
2056                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask,
2057                                        zone_gotreadhandle, load,
2058                                        &zone->readio);
2059                 if (result != ISC_R_SUCCESS) {
2060                         /*
2061                          * We can't report multiple errors so ignore
2062                          * the result of dns_db_endload().
2063                          */
2064                         (void)dns_db_endload(load->db,
2065                                              &load->callbacks.add_private);
2066                         goto cleanup;
2067                 } else
2068                         result = DNS_R_CONTINUE;
2069         } else {
2070                 dns_rdatacallbacks_t callbacks;
2071
2072                 dns_rdatacallbacks_init(&callbacks);
2073                 callbacks.rawdata = zone_setrawdata;
2074                 zone_iattach(zone, &callbacks.zone);
2075                 result = dns_db_beginload(db, &callbacks.add,
2076                                           &callbacks.add_private);
2077                 if (result != ISC_R_SUCCESS) {
2078                         zone_idetach(&callbacks.zone);
2079                         return (result);
2080                 }
2081                 result = dns_master_loadfile3(zone->masterfile,
2082                                               &zone->origin, &zone->origin,
2083                                               zone->rdclass, options, 0,
2084                                               &callbacks, zone->mctx,
2085                                               zone->masterformat);
2086                 tresult = dns_db_endload(db, &callbacks.add_private);
2087                 if (result == ISC_R_SUCCESS)
2088                         result = tresult;
2089                 zone_idetach(&callbacks.zone);
2090         }
2091
2092         return (result);
2093
2094  cleanup:
2095         load->magic = 0;
2096         dns_db_detach(&load->db);
2097         zone_idetach(&load->zone);
2098         zone_idetach(&load->callbacks.zone);
2099         isc_mem_detach(&load->mctx);
2100         isc_mem_put(zone->mctx, load, sizeof(*load));
2101         return (result);
2102 }
2103
2104 static isc_boolean_t
2105 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2106               dns_name_t *owner)
2107 {
2108         isc_result_t result;
2109         char ownerbuf[DNS_NAME_FORMATSIZE];
2110         char namebuf[DNS_NAME_FORMATSIZE];
2111         char altbuf[DNS_NAME_FORMATSIZE];
2112         dns_fixedname_t fixed;
2113         dns_name_t *foundname;
2114         int level;
2115
2116         /*
2117          * "." means the services does not exist.
2118          */
2119         if (dns_name_equal(name, dns_rootname))
2120                 return (ISC_TRUE);
2121
2122         /*
2123          * Outside of zone.
2124          */
2125         if (!dns_name_issubdomain(name, &zone->origin)) {
2126                 if (zone->checkmx != NULL)
2127                         return ((zone->checkmx)(zone, name, owner));
2128                 return (ISC_TRUE);
2129         }
2130
2131         if (zone->type == dns_zone_master)
2132                 level = ISC_LOG_ERROR;
2133         else
2134                 level = ISC_LOG_WARNING;
2135
2136         dns_fixedname_init(&fixed);
2137         foundname = dns_fixedname_name(&fixed);
2138
2139         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2140                              0, 0, NULL, foundname, NULL, NULL);
2141         if (result == ISC_R_SUCCESS)
2142                 return (ISC_TRUE);
2143
2144         if (result == DNS_R_NXRRSET) {
2145                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2146                                      0, 0, NULL, foundname, NULL, NULL);
2147                 if (result == ISC_R_SUCCESS)
2148                         return (ISC_TRUE);
2149         }
2150
2151         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2152         dns_name_format(name, namebuf, sizeof namebuf);
2153         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2154             result == DNS_R_EMPTYNAME) {
2155                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2156                         level = ISC_LOG_WARNING;
2157                 dns_zone_log(zone, level,
2158                              "%s/MX '%s' has no address records (A or AAAA)",
2159                              ownerbuf, namebuf);
2160                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2161         }
2162
2163         if (result == DNS_R_CNAME) {
2164                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2165                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2166                         level = ISC_LOG_WARNING;
2167                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2168                         dns_zone_log(zone, level,
2169                                      "%s/MX '%s' is a CNAME (illegal)",
2170                                      ownerbuf, namebuf);
2171                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2172         }
2173
2174         if (result == DNS_R_DNAME) {
2175                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2176                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2177                         level = ISC_LOG_WARNING;
2178                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2179                         dns_name_format(foundname, altbuf, sizeof altbuf);
2180                         dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2181                                      " '%s' (illegal)", ownerbuf, namebuf,
2182                                      altbuf);
2183                 }
2184                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2185         }
2186
2187         if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2188                 return ((zone->checkmx)(zone, name, owner));
2189
2190         return (ISC_TRUE);
2191 }
2192
2193 static isc_boolean_t
2194 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2195                dns_name_t *owner)
2196 {
2197         isc_result_t result;
2198         char ownerbuf[DNS_NAME_FORMATSIZE];
2199         char namebuf[DNS_NAME_FORMATSIZE];
2200         char altbuf[DNS_NAME_FORMATSIZE];
2201         dns_fixedname_t fixed;
2202         dns_name_t *foundname;
2203         int level;
2204
2205         /*
2206          * "." means the services does not exist.
2207          */
2208         if (dns_name_equal(name, dns_rootname))
2209                 return (ISC_TRUE);
2210
2211         /*
2212          * Outside of zone.
2213          */
2214         if (!dns_name_issubdomain(name, &zone->origin)) {
2215                 if (zone->checksrv != NULL)
2216                         return ((zone->checksrv)(zone, name, owner));
2217                 return (ISC_TRUE);
2218         }
2219
2220         if (zone->type == dns_zone_master)
2221                 level = ISC_LOG_ERROR;
2222         else
2223                 level = ISC_LOG_WARNING;
2224
2225         dns_fixedname_init(&fixed);
2226         foundname = dns_fixedname_name(&fixed);
2227
2228         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2229                              0, 0, NULL, foundname, NULL, NULL);
2230         if (result == ISC_R_SUCCESS)
2231                 return (ISC_TRUE);
2232
2233         if (result == DNS_R_NXRRSET) {
2234                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2235                                      0, 0, NULL, foundname, NULL, NULL);
2236                 if (result == ISC_R_SUCCESS)
2237                         return (ISC_TRUE);
2238         }
2239
2240         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2241         dns_name_format(name, namebuf, sizeof namebuf);
2242         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2243             result == DNS_R_EMPTYNAME) {
2244                 dns_zone_log(zone, level,
2245                              "%s/SRV '%s' has no address records (A or AAAA)",
2246                              ownerbuf, namebuf);
2247                 /* XXX950 make fatal for 9.5.0. */
2248                 return (ISC_TRUE);
2249         }
2250
2251         if (result == DNS_R_CNAME) {
2252                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2253                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2254                         level = ISC_LOG_WARNING;
2255                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2256                         dns_zone_log(zone, level,
2257                                      "%s/SRV '%s' is a CNAME (illegal)",
2258                                      ownerbuf, namebuf);
2259                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2260         }
2261
2262         if (result == DNS_R_DNAME) {
2263                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2264                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2265                         level = ISC_LOG_WARNING;
2266                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2267                         dns_name_format(foundname, altbuf, sizeof altbuf);
2268                         dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2269                                      "DNAME '%s' (illegal)", ownerbuf, namebuf,
2270                                      altbuf);
2271                 }
2272                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2273         }
2274
2275         if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2276                 return ((zone->checksrv)(zone, name, owner));
2277
2278         return (ISC_TRUE);
2279 }
2280
2281 static isc_boolean_t
2282 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2283                 dns_name_t *owner)
2284 {
2285         isc_boolean_t answer = ISC_TRUE;
2286         isc_result_t result, tresult;
2287         char ownerbuf[DNS_NAME_FORMATSIZE];
2288         char namebuf[DNS_NAME_FORMATSIZE];
2289         char altbuf[DNS_NAME_FORMATSIZE];
2290         dns_fixedname_t fixed;
2291         dns_name_t *foundname;
2292         dns_rdataset_t a;
2293         dns_rdataset_t aaaa;
2294         int level;
2295
2296         /*
2297          * Outside of zone.
2298          */
2299         if (!dns_name_issubdomain(name, &zone->origin)) {
2300                 if (zone->checkns != NULL)
2301                         return ((zone->checkns)(zone, name, owner, NULL, NULL));
2302                 return (ISC_TRUE);
2303         }
2304
2305         if (zone->type == dns_zone_master)
2306                 level = ISC_LOG_ERROR;
2307         else
2308                 level = ISC_LOG_WARNING;
2309
2310         dns_fixedname_init(&fixed);
2311         foundname = dns_fixedname_name(&fixed);
2312         dns_rdataset_init(&a);
2313         dns_rdataset_init(&aaaa);
2314
2315         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2316                              DNS_DBFIND_GLUEOK, 0, NULL,
2317                              foundname, &a, NULL);
2318
2319         if (result == ISC_R_SUCCESS) {
2320                 dns_rdataset_disassociate(&a);
2321                 return (ISC_TRUE);
2322         } else if (result == DNS_R_DELEGATION)
2323                 dns_rdataset_disassociate(&a);
2324
2325         if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2326             result == DNS_R_GLUE) {
2327                 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2328                                      DNS_DBFIND_GLUEOK, 0, NULL,
2329                                      foundname, &aaaa, NULL);
2330                 if (tresult == ISC_R_SUCCESS) {
2331                         dns_rdataset_disassociate(&aaaa);
2332                         return (ISC_TRUE);
2333                 }
2334                 if (tresult == DNS_R_DELEGATION)
2335                         dns_rdataset_disassociate(&aaaa);
2336                 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2337                         /*
2338                          * Check glue against child zone.
2339                          */
2340                         if (zone->checkns != NULL)
2341                                 answer = (zone->checkns)(zone, name, owner,
2342                                                          &a, &aaaa);
2343                         if (dns_rdataset_isassociated(&a))
2344                                 dns_rdataset_disassociate(&a);
2345                         if (dns_rdataset_isassociated(&aaaa))
2346                                 dns_rdataset_disassociate(&aaaa);
2347                         return (answer);
2348                 }
2349         }
2350
2351         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2352         dns_name_format(name, namebuf, sizeof namebuf);
2353         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2354             result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2355                 const char *what;
2356                 isc_boolean_t required = ISC_FALSE;
2357                 if (dns_name_issubdomain(name, owner)) {
2358                         what = "REQUIRED GLUE ";
2359                         required = ISC_TRUE;
2360                  } else if (result == DNS_R_DELEGATION)
2361                         what = "SIBLING GLUE ";
2362                 else
2363                         what = "";
2364
2365                 if (result != DNS_R_DELEGATION || required ||
2366                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2367                         dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2368                                      "address records (A or AAAA)",
2369                                      ownerbuf, namebuf, what);
2370                         /*
2371                          * Log missing address record.
2372                          */
2373                         if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2374                                 (void)(zone->checkns)(zone, name, owner,
2375                                                       &a, &aaaa);
2376                         /* XXX950 make fatal for 9.5.0. */
2377                         /* answer = ISC_FALSE; */
2378                 }
2379         } else if (result == DNS_R_CNAME) {
2380                 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2381                              ownerbuf, namebuf);
2382                 /* XXX950 make fatal for 9.5.0. */
2383                 /* answer = ISC_FALSE; */
2384         } else if (result == DNS_R_DNAME) {
2385                 dns_name_format(foundname, altbuf, sizeof altbuf);
2386                 dns_zone_log(zone, level,
2387                              "%s/NS '%s' is below a DNAME '%s' (illegal)",
2388                              ownerbuf, namebuf, altbuf);
2389                 /* XXX950 make fatal for 9.5.0. */
2390                 /* answer = ISC_FALSE; */
2391         }
2392
2393         if (dns_rdataset_isassociated(&a))
2394                 dns_rdataset_disassociate(&a);
2395         if (dns_rdataset_isassociated(&aaaa))
2396                 dns_rdataset_disassociate(&aaaa);
2397         return (answer);
2398 }
2399
2400 static isc_boolean_t
2401 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2402                      dns_rdataset_t *rdataset)
2403 {
2404         dns_rdataset_t tmprdataset;
2405         isc_result_t result;
2406         isc_boolean_t answer = ISC_TRUE;
2407         isc_boolean_t format = ISC_TRUE;
2408         int level = ISC_LOG_WARNING;
2409         char ownerbuf[DNS_NAME_FORMATSIZE];
2410         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2411         unsigned int count1 = 0;
2412
2413         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2414                 level = ISC_LOG_ERROR;
2415
2416         dns_rdataset_init(&tmprdataset);
2417         for (result = dns_rdataset_first(rdataset);
2418              result == ISC_R_SUCCESS;
2419              result = dns_rdataset_next(rdataset)) {
2420                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2421                 unsigned int count2 = 0;
2422
2423                 count1++;
2424                 dns_rdataset_current(rdataset, &rdata1);
2425                 dns_rdataset_clone(rdataset, &tmprdataset);
2426                 for (result = dns_rdataset_first(&tmprdataset);
2427                      result == ISC_R_SUCCESS;
2428                      result = dns_rdataset_next(&tmprdataset)) {
2429                         dns_rdata_t rdata2 = DNS_RDATA_INIT;
2430                         count2++;
2431                         if (count1 >= count2)
2432                                 continue;
2433                         dns_rdataset_current(&tmprdataset, &rdata2);
2434                         if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2435                                 if (format) {
2436                                         dns_name_format(owner, ownerbuf,
2437                                                         sizeof ownerbuf);
2438                                         dns_rdatatype_format(rdata1.type,
2439                                                              typebuf,
2440                                                              sizeof(typebuf));
2441                                         format = ISC_FALSE;
2442                                 }
2443                                 dns_zone_log(zone, level, "%s/%s has "
2444                                              "semantically identical records",
2445                                              ownerbuf, typebuf);
2446                                 if (level == ISC_LOG_ERROR)
2447                                         answer = ISC_FALSE;
2448                                 break;
2449                         }
2450                 }
2451                 dns_rdataset_disassociate(&tmprdataset);
2452                 if (!format)
2453                         break;
2454         }
2455         return (answer);
2456 }
2457
2458 static isc_boolean_t
2459 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2460         dns_dbiterator_t *dbiterator = NULL;
2461         dns_dbnode_t *node = NULL;
2462         dns_fixedname_t fixed;
2463         dns_name_t *name;
2464         dns_rdataset_t rdataset;
2465         dns_rdatasetiter_t *rdsit = NULL;
2466         isc_boolean_t ok = ISC_TRUE;
2467         isc_result_t result;
2468
2469         dns_fixedname_init(&fixed);
2470         name = dns_fixedname_name(&fixed);
2471         dns_rdataset_init(&rdataset);
2472
2473         result = dns_db_createiterator(db, 0, &dbiterator);
2474         if (result != ISC_R_SUCCESS)
2475                 return (ISC_TRUE);
2476
2477         for (result = dns_dbiterator_first(dbiterator);
2478              result == ISC_R_SUCCESS;
2479              result = dns_dbiterator_next(dbiterator)) {
2480                 result = dns_dbiterator_current(dbiterator, &node, name);
2481                 if (result != ISC_R_SUCCESS)
2482                         continue;
2483
2484                 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2485                 if (result != ISC_R_SUCCESS)
2486                         continue;
2487
2488                 for (result = dns_rdatasetiter_first(rdsit);
2489                      result == ISC_R_SUCCESS;
2490                      result = dns_rdatasetiter_next(rdsit)) {
2491                         dns_rdatasetiter_current(rdsit, &rdataset);
2492                         if (!zone_rrset_check_dup(zone, name, &rdataset))
2493                                 ok = ISC_FALSE;
2494                         dns_rdataset_disassociate(&rdataset);
2495                 }
2496                 dns_rdatasetiter_destroy(&rdsit);
2497                 dns_db_detachnode(db, &node);
2498         }
2499
2500         if (node != NULL)
2501                 dns_db_detachnode(db, &node);
2502         dns_dbiterator_destroy(&dbiterator);
2503
2504         return (ok);
2505 }
2506
2507 static isc_boolean_t
2508 isspf(const dns_rdata_t *rdata) {
2509         char buf[1024];
2510         const unsigned char *data = rdata->data;
2511         unsigned int rdl = rdata->length, i = 0, tl, len;
2512
2513         while (rdl > 0U) {
2514                 len = tl = *data;
2515                 ++data;
2516                 --rdl;
2517                 INSIST(tl <= rdl);
2518                 if (len > sizeof(buf) - i - 1)
2519                         len = sizeof(buf) - i - 1;
2520                 memmove(buf + i, data, len);
2521                 i += len;
2522                 data += tl;
2523                 rdl -= tl;
2524         }
2525
2526         if (i < 6U)
2527                 return(ISC_FALSE);
2528
2529         buf[i] = 0;
2530         if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
2531                 return (ISC_TRUE);
2532         return (ISC_FALSE);
2533 }
2534
2535 static isc_boolean_t
2536 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2537         dns_dbiterator_t *dbiterator = NULL;
2538         dns_dbnode_t *node = NULL;
2539         dns_rdataset_t rdataset;
2540         dns_fixedname_t fixed;
2541         dns_fixedname_t fixedbottom;
2542         dns_rdata_mx_t mx;
2543         dns_rdata_ns_t ns;
2544         dns_rdata_in_srv_t srv;
2545         dns_rdata_t rdata;
2546         dns_name_t *name;
2547         dns_name_t *bottom;
2548         isc_result_t result;
2549         isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
2550
2551         dns_fixedname_init(&fixed);
2552         name = dns_fixedname_name(&fixed);
2553         dns_fixedname_init(&fixedbottom);
2554         bottom = dns_fixedname_name(&fixedbottom);
2555         dns_rdataset_init(&rdataset);
2556         dns_rdata_init(&rdata);
2557
2558         result = dns_db_createiterator(db, 0, &dbiterator);
2559         if (result != ISC_R_SUCCESS)
2560                 return (ISC_TRUE);
2561
2562         result = dns_dbiterator_first(dbiterator);
2563         while (result == ISC_R_SUCCESS) {
2564                 result = dns_dbiterator_current(dbiterator, &node, name);
2565                 if (result != ISC_R_SUCCESS)
2566                         goto cleanup;
2567
2568                 /*
2569                  * Is this name visible in the zone?
2570                  */
2571                 if (!dns_name_issubdomain(name, &zone->origin) ||
2572                     (dns_name_countlabels(bottom) > 0 &&
2573                      dns_name_issubdomain(name, bottom)))
2574                         goto next;
2575
2576                 /*
2577                  * Don't check the NS records at the origin.
2578                  */
2579                 if (dns_name_equal(name, &zone->origin))
2580                         goto checkmx;
2581
2582                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2583                                              0, 0, &rdataset, NULL);
2584                 if (result != ISC_R_SUCCESS)
2585                         goto checkmx;
2586                 /*
2587                  * Remember bottom of zone.
2588                  */
2589                 dns_name_copy(name, bottom, NULL);
2590
2591                 result = dns_rdataset_first(&rdataset);
2592                 while (result == ISC_R_SUCCESS) {
2593                         dns_rdataset_current(&rdataset, &rdata);
2594                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
2595                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2596                         if (!zone_check_glue(zone, db, &ns.name, name))
2597                                 ok = ISC_FALSE;
2598                         dns_rdata_reset(&rdata);
2599                         result = dns_rdataset_next(&rdataset);
2600                 }
2601                 dns_rdataset_disassociate(&rdataset);
2602                 goto next;
2603
2604  checkmx:
2605                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2606                                              0, 0, &rdataset, NULL);
2607                 if (result != ISC_R_SUCCESS)
2608                         goto checksrv;
2609                 result = dns_rdataset_first(&rdataset);
2610                 while (result == ISC_R_SUCCESS) {
2611                         dns_rdataset_current(&rdataset, &rdata);
2612                         result = dns_rdata_tostruct(&rdata, &mx, NULL);
2613                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2614                         if (!zone_check_mx(zone, db, &mx.mx, name))
2615                                 ok = ISC_FALSE;
2616                         dns_rdata_reset(&rdata);
2617                         result = dns_rdataset_next(&rdataset);
2618                 }
2619                 dns_rdataset_disassociate(&rdataset);
2620
2621  checksrv:
2622                 if (zone->rdclass != dns_rdataclass_in)
2623                         goto next;
2624                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2625                                              0, 0, &rdataset, NULL);
2626                 if (result != ISC_R_SUCCESS)
2627                         goto checkspf;
2628                 result = dns_rdataset_first(&rdataset);
2629                 while (result == ISC_R_SUCCESS) {
2630                         dns_rdataset_current(&rdataset, &rdata);
2631                         result = dns_rdata_tostruct(&rdata, &srv, NULL);
2632                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2633                         if (!zone_check_srv(zone, db, &srv.target, name))
2634                                 ok = ISC_FALSE;
2635                         dns_rdata_reset(&rdata);
2636                         result = dns_rdataset_next(&rdataset);
2637                 }
2638                 dns_rdataset_disassociate(&rdataset);
2639
2640  checkspf:
2641                 /*
2642                  * Check if there is a type TXT spf record without a type SPF
2643                  * RRset being present.
2644                  */
2645                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
2646                         goto next;
2647                 if (zone->rdclass != dns_rdataclass_in)
2648                         goto next;
2649                 have_spf = have_txt = ISC_FALSE;
2650                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
2651                                              0, 0, &rdataset, NULL);
2652                 if (result == ISC_R_SUCCESS) {
2653                         dns_rdataset_disassociate(&rdataset);
2654                         have_spf = ISC_TRUE;
2655                 }
2656                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
2657                                              0, 0, &rdataset, NULL);
2658                 if (result != ISC_R_SUCCESS)
2659                         goto notxt;
2660                 result = dns_rdataset_first(&rdataset);
2661                 while (result == ISC_R_SUCCESS) {
2662                         dns_rdataset_current(&rdataset, &rdata);
2663                         have_txt = isspf(&rdata);
2664                         dns_rdata_reset(&rdata);
2665                         if (have_txt)
2666                                 break;
2667                         result = dns_rdataset_next(&rdataset);
2668                 }
2669                 dns_rdataset_disassociate(&rdataset);
2670
2671  notxt:
2672                 if (have_spf != have_txt) {
2673                         char namebuf[DNS_NAME_FORMATSIZE];
2674                         const char *found = have_txt ? "TXT" : "SPF";
2675                         const char *need = have_txt ? "SPF" : "TXT";
2676
2677                         dns_name_format(name, namebuf, sizeof(namebuf));
2678                         dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found SPF/%s "
2679                                      "record but no SPF/%s record found, add "
2680                                      "matching type %s record", namebuf, found,
2681                                      need, need);
2682                 }
2683
2684  next:
2685                 dns_db_detachnode(db, &node);
2686                 result = dns_dbiterator_next(dbiterator);
2687         }
2688
2689  cleanup:
2690         if (node != NULL)
2691                 dns_db_detachnode(db, &node);
2692         dns_dbiterator_destroy(&dbiterator);
2693
2694         return (ok);
2695 }
2696
2697 /*
2698  * OpenSSL verification of RSA keys with exponent 3 is known to be
2699  * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
2700  * if they are in use.
2701  */
2702 static void
2703 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2704         dns_dbnode_t *node = NULL;
2705         dns_dbversion_t *version = NULL;
2706         dns_rdata_dnskey_t dnskey;
2707         dns_rdata_t rdata = DNS_RDATA_INIT;
2708         dns_rdataset_t rdataset;
2709         isc_result_t result;
2710         isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2711         const char *algorithm;
2712
2713         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2714         if (result != ISC_R_SUCCESS)
2715                 goto cleanup;
2716
2717         dns_db_currentversion(db, &version);
2718         dns_rdataset_init(&rdataset);
2719         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2720                                      dns_rdatatype_none, 0, &rdataset, NULL);
2721         if (result != ISC_R_SUCCESS)
2722                 goto cleanup;
2723
2724         for (result = dns_rdataset_first(&rdataset);
2725              result == ISC_R_SUCCESS;
2726              result = dns_rdataset_next(&rdataset))
2727         {
2728                 dns_rdataset_current(&rdataset, &rdata);
2729                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2730                 INSIST(result == ISC_R_SUCCESS);
2731
2732                 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2733                      dnskey.algorithm == DST_ALG_RSAMD5) &&
2734                      dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2735                      dnskey.data[1] == 3)
2736                 {
2737                         if (dnskey.algorithm == DST_ALG_RSASHA1) {
2738                                 logit = !foundrsa;
2739                                 foundrsa = ISC_TRUE;
2740                                 algorithm = "RSASHA1";
2741                         } else {
2742                                 logit = !foundmd5;
2743                                 foundmd5 = ISC_TRUE;
2744                                 algorithm = "RSAMD5";
2745                         }
2746                         if (logit)
2747                                 dns_zone_log(zone, ISC_LOG_WARNING,
2748                                              "weak %s (%u) key found "
2749                                              "(exponent=3)", algorithm,
2750                                              dnskey.algorithm);
2751                         if (foundrsa && foundmd5)
2752                                 break;
2753                 }
2754                 dns_rdata_reset(&rdata);
2755         }
2756         dns_rdataset_disassociate(&rdataset);
2757
2758  cleanup:
2759         if (node != NULL)
2760                 dns_db_detachnode(db, &node);
2761         if (version != NULL)
2762                 dns_db_closeversion(db, &version, ISC_FALSE);
2763 }
2764
2765 static void
2766 resume_signingwithkey(dns_zone_t *zone) {
2767         dns_dbnode_t *node = NULL;
2768         dns_dbversion_t *version = NULL;
2769         dns_rdata_t rdata = DNS_RDATA_INIT;
2770         dns_rdataset_t rdataset;
2771         isc_result_t result;
2772         dns_db_t *db = NULL;
2773
2774         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2775         if (zone->db != NULL)
2776                 dns_db_attach(zone->db, &db);
2777         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2778         if (db == NULL)
2779                 goto cleanup;
2780
2781         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2782         if (result != ISC_R_SUCCESS)
2783                 goto cleanup;
2784
2785         dns_db_currentversion(db, &version);
2786         dns_rdataset_init(&rdataset);
2787         result = dns_db_findrdataset(db, node, version,
2788                                      zone->privatetype,
2789                                      dns_rdatatype_none, 0,
2790                                      &rdataset, NULL);
2791         if (result != ISC_R_SUCCESS) {
2792                 INSIST(!dns_rdataset_isassociated(&rdataset));
2793                 goto cleanup;
2794         }
2795
2796         for (result = dns_rdataset_first(&rdataset);
2797              result == ISC_R_SUCCESS;
2798              result = dns_rdataset_next(&rdataset))
2799         {
2800                 dns_rdataset_current(&rdataset, &rdata);
2801                 if (rdata.length != 5 ||
2802                     rdata.data[0] == 0 || rdata.data[4] != 0) {
2803                         dns_rdata_reset(&rdata);
2804                         continue;
2805                 }
2806
2807                 result = zone_signwithkey(zone, rdata.data[0],
2808                                           (rdata.data[1] << 8) | rdata.data[2],
2809                                           ISC_TF(rdata.data[3]));
2810                 if (result != ISC_R_SUCCESS) {
2811                         dns_zone_log(zone, ISC_LOG_ERROR,
2812                                      "zone_signwithkey failed: %s",
2813                                      dns_result_totext(result));
2814                 }
2815                 dns_rdata_reset(&rdata);
2816         }
2817         dns_rdataset_disassociate(&rdataset);
2818
2819  cleanup:
2820         if (db != NULL) {
2821                 if (node != NULL)
2822                         dns_db_detachnode(db, &node);
2823                 if (version != NULL)
2824                         dns_db_closeversion(db, &version, ISC_FALSE);
2825                 dns_db_detach(&db);
2826         }
2827 }
2828
2829 static isc_result_t
2830 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2831         dns_nsec3chain_t *nsec3chain, *current;
2832         dns_dbversion_t *version = NULL;
2833         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
2834         isc_result_t result;
2835         isc_time_t now;
2836         unsigned int options = 0;
2837         char saltbuf[255*2+1];
2838         char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
2839         dns_db_t *db = NULL;
2840         int i;
2841
2842         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2843         if (zone->db != NULL)
2844                 dns_db_attach(zone->db, &db);
2845         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2846
2847         if (db == NULL) {
2848                 result = ISC_R_SUCCESS;
2849                 goto cleanup;
2850         }
2851
2852         dns_db_currentversion(db, &version);
2853         result = dns_nsec_nseconly(db, version, &nseconly);
2854         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
2855         dns_db_closeversion(db, &version, ISC_FALSE);
2856         if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
2857                 result = ISC_R_SUCCESS;
2858                 goto cleanup;
2859         }
2860
2861         nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2862         if (nsec3chain == NULL) {
2863                 result = ISC_R_NOMEMORY;
2864                 goto cleanup;
2865         }
2866
2867         nsec3chain->magic = 0;
2868         nsec3chain->done = ISC_FALSE;
2869         nsec3chain->db = NULL;
2870         nsec3chain->dbiterator = NULL;
2871         nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2872         nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2873         nsec3chain->nsec3param.hash = nsec3param->hash;
2874         nsec3chain->nsec3param.iterations = nsec3param->iterations;
2875         nsec3chain->nsec3param.flags = nsec3param->flags;
2876         nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2877         memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2878         nsec3chain->nsec3param.salt = nsec3chain->salt;
2879         nsec3chain->seen_nsec = ISC_FALSE;
2880         nsec3chain->delete_nsec = ISC_FALSE;
2881         nsec3chain->save_delete_nsec = ISC_FALSE;
2882
2883         if (nsec3param->flags == 0)
2884                 strlcpy(flags, "NONE", sizeof(flags));
2885         else {
2886                 flags[0] = '\0';
2887                 if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2888                         strlcat(flags, "REMOVE", sizeof(flags));
2889                 if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) {
2890                         if (flags[0] == '\0')
2891                                 strlcpy(flags, "INITIAL", sizeof(flags));
2892                         else
2893                                 strlcat(flags, "|INITIAL", sizeof(flags));
2894                 }
2895                 if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2896                         if (flags[0] == '\0')
2897                                 strlcpy(flags, "CREATE", sizeof(flags));
2898                         else
2899                                 strlcat(flags, "|CREATE", sizeof(flags));
2900                 }
2901                 if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2902                         if (flags[0] == '\0')
2903                                 strlcpy(flags, "NONSEC", sizeof(flags));
2904                         else
2905                                 strlcat(flags, "|NONSEC", sizeof(flags));
2906                 }
2907                 if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2908                         if (flags[0] == '\0')
2909                                 strlcpy(flags, "OPTOUT", sizeof(flags));
2910                         else
2911                                 strlcat(flags, "|OPTOUT", sizeof(flags));
2912                 }
2913         }
2914         if (nsec3param->salt_length == 0)
2915                 strlcpy(saltbuf, "-", sizeof(saltbuf));
2916         else
2917                 for (i = 0; i < nsec3param->salt_length; i++)
2918                         sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2919         dns_zone_log(zone, ISC_LOG_INFO,
2920                      "zone_addnsec3chain(%u,%s,%u,%s)",
2921                       nsec3param->hash, flags, nsec3param->iterations,
2922                       saltbuf);
2923
2924         for (current = ISC_LIST_HEAD(zone->nsec3chain);
2925              current != NULL;
2926              current = ISC_LIST_NEXT(current, link)) {
2927                 if (current->db == db &&
2928                     current->nsec3param.hash == nsec3param->hash &&
2929                     current->nsec3param.iterations == nsec3param->iterations &&
2930                     current->nsec3param.salt_length == nsec3param->salt_length
2931                     && !memcmp(current->nsec3param.salt, nsec3param->salt,
2932                                nsec3param->salt_length))
2933                         current->done = ISC_TRUE;
2934         }
2935
2936         dns_db_attach(db, &nsec3chain->db);
2937         if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2938                 options = DNS_DB_NONSEC3;
2939         result = dns_db_createiterator(nsec3chain->db, options,
2940                                        &nsec3chain->dbiterator);
2941         if (result == ISC_R_SUCCESS)
2942                 dns_dbiterator_first(nsec3chain->dbiterator);
2943         if (result == ISC_R_SUCCESS) {
2944                 dns_dbiterator_pause(nsec3chain->dbiterator);
2945                 ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2946                                        nsec3chain, link);
2947                 nsec3chain = NULL;
2948                 if (isc_time_isepoch(&zone->nsec3chaintime)) {
2949                         TIME_NOW(&now);
2950                         zone->nsec3chaintime = now;
2951                         if (zone->task != NULL)
2952                                 zone_settimer(zone, &now);
2953                 }
2954         }
2955
2956         if (nsec3chain != NULL) {
2957                 if (nsec3chain->db != NULL)
2958                         dns_db_detach(&nsec3chain->db);
2959                 if (nsec3chain->dbiterator != NULL)
2960                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
2961                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2962         }
2963
2964  cleanup:
2965         if (db != NULL)
2966                 dns_db_detach(&db);
2967         return (result);
2968 }
2969
2970 static void
2971 resume_addnsec3chain(dns_zone_t *zone) {
2972         dns_dbnode_t *node = NULL;
2973         dns_dbversion_t *version = NULL;
2974         dns_rdataset_t rdataset;
2975         isc_result_t result;
2976         dns_rdata_nsec3param_t nsec3param;
2977         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
2978         dns_db_t *db = NULL;
2979
2980         if (zone->privatetype == 0)
2981                 return;
2982
2983         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2984         if (zone->db != NULL)
2985                 dns_db_attach(zone->db, &db);
2986         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2987         if (db == NULL)
2988                 goto cleanup;
2989
2990         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2991         if (result != ISC_R_SUCCESS)
2992                 goto cleanup;
2993
2994         dns_db_currentversion(db, &version);
2995
2996         result = dns_nsec_nseconly(db, version, &nseconly);
2997         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
2998
2999         dns_rdataset_init(&rdataset);
3000         result = dns_db_findrdataset(db, node, version,
3001                                      zone->privatetype, dns_rdatatype_none,
3002                                      0, &rdataset, NULL);
3003         if (result != ISC_R_SUCCESS) {
3004                 INSIST(!dns_rdataset_isassociated(&rdataset));
3005                 goto cleanup;
3006         }
3007
3008         for (result = dns_rdataset_first(&rdataset);
3009              result == ISC_R_SUCCESS;
3010              result = dns_rdataset_next(&rdataset))
3011         {
3012                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3013                 dns_rdata_t rdata = DNS_RDATA_INIT;
3014                 dns_rdata_t private = DNS_RDATA_INIT;
3015
3016                 dns_rdataset_current(&rdataset, &private);
3017                 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3018                                                 sizeof(buf)))
3019                         continue;
3020                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3021                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3022                 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3023                     ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3024                 {
3025                         result = zone_addnsec3chain(zone, &nsec3param);
3026                         if (result != ISC_R_SUCCESS) {
3027                                 dns_zone_log(zone, ISC_LOG_ERROR,
3028                                              "zone_addnsec3chain failed: %s",
3029                                              dns_result_totext(result));
3030                         }
3031                 }
3032         }
3033         dns_rdataset_disassociate(&rdataset);
3034  cleanup:
3035         if (db != NULL) {
3036                 if (node != NULL)
3037                         dns_db_detachnode(db, &node);
3038                 if (version != NULL)
3039                         dns_db_closeversion(db, &version, ISC_FALSE);
3040                 dns_db_detach(&db);
3041         }
3042 }
3043
3044 static void
3045 set_resigntime(dns_zone_t *zone) {
3046         dns_rdataset_t rdataset;
3047         dns_fixedname_t fixed;
3048         unsigned int resign;
3049         isc_result_t result;
3050         isc_uint32_t nanosecs;
3051         dns_db_t *db = NULL;
3052
3053         dns_rdataset_init(&rdataset);
3054         dns_fixedname_init(&fixed);
3055
3056         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3057         if (zone->db != NULL)
3058                 dns_db_attach(zone->db, &db);
3059         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3060         if (db == NULL) {
3061                 isc_time_settoepoch(&zone->resigntime);
3062                 return;
3063         }
3064
3065         result = dns_db_getsigningtime(db, &rdataset,
3066                                        dns_fixedname_name(&fixed));
3067         if (result != ISC_R_SUCCESS) {
3068                 isc_time_settoepoch(&zone->resigntime);
3069                 goto cleanup;
3070         }
3071
3072         resign = rdataset.resign - zone->sigresigninginterval;
3073         dns_rdataset_disassociate(&rdataset);
3074         isc_random_get(&nanosecs);
3075         nanosecs %= 1000000000;
3076         isc_time_set(&zone->resigntime, resign, nanosecs);
3077  cleanup:
3078         dns_db_detach(&db);
3079         return;
3080 }
3081
3082 static isc_result_t
3083 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3084         dns_dbnode_t *node = NULL;
3085         dns_rdataset_t rdataset;
3086         dns_dbversion_t *version = NULL;
3087         dns_rdata_nsec3param_t nsec3param;
3088         isc_boolean_t ok = ISC_FALSE;
3089         isc_result_t result;
3090         dns_rdata_t rdata = DNS_RDATA_INIT;
3091         isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
3092                                 dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE;
3093
3094         dns_rdataset_init(&rdataset);
3095         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3096         if (result != ISC_R_SUCCESS) {
3097                 dns_zone_log(zone, ISC_LOG_ERROR,
3098                              "nsec3param lookup failure: %s",
3099                              dns_result_totext(result));
3100                 return (result);
3101         }
3102         dns_db_currentversion(db, &version);
3103
3104         result = dns_db_findrdataset(db, node, version,
3105                                      dns_rdatatype_nsec3param,
3106                                      dns_rdatatype_none, 0, &rdataset, NULL);
3107         if (result == ISC_R_NOTFOUND) {
3108                 INSIST(!dns_rdataset_isassociated(&rdataset));
3109                 result = ISC_R_SUCCESS;
3110                 goto cleanup;
3111         }
3112         if (result != ISC_R_SUCCESS) {
3113                 INSIST(!dns_rdataset_isassociated(&rdataset));
3114                 dns_zone_log(zone, ISC_LOG_ERROR,
3115                              "nsec3param lookup failure: %s",
3116                              dns_result_totext(result));
3117                 goto cleanup;
3118         }
3119
3120         /*
3121          * For dynamic zones we must support every algorithm so we can
3122          * regenerate all the NSEC3 chains.
3123          * For non-dynamic zones we only need to find a supported algorithm.
3124          */
3125         for (result = dns_rdataset_first(&rdataset);
3126              result == ISC_R_SUCCESS;
3127              result = dns_rdataset_next(&rdataset))
3128         {
3129                 dns_rdataset_current(&rdataset, &rdata);
3130                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3131                 dns_rdata_reset(&rdata);
3132                 INSIST(result == ISC_R_SUCCESS);
3133                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3134                     nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3135                 {
3136                         dns_zone_log(zone, ISC_LOG_WARNING,
3137                              "nsec3 test \"unknown\" hash algorithm found: %u",
3138                                      nsec3param.hash);
3139                         ok = ISC_TRUE;
3140                 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3141                         if (dynamic) {
3142                                 dns_zone_log(zone, ISC_LOG_ERROR,
3143                                              "unsupported nsec3 hash algorithm"
3144                                              " in dynamic zone: %u",
3145                                              nsec3param.hash);
3146                                 result = DNS_R_BADZONE;
3147                                 /* Stop second error message. */
3148                                 ok = ISC_TRUE;
3149                                 break;
3150                         } else
3151                                 dns_zone_log(zone, ISC_LOG_WARNING,
3152                                      "unsupported nsec3 hash algorithm: %u",
3153                                              nsec3param.hash);
3154                 } else
3155                         ok = ISC_TRUE;
3156         }
3157         if (result == ISC_R_NOMORE)
3158                 result = ISC_R_SUCCESS;
3159
3160         if (!ok) {
3161                 result = DNS_R_BADZONE;
3162                 dns_zone_log(zone, ISC_LOG_ERROR,
3163                              "no supported nsec3 hash algorithm");
3164         }
3165
3166  cleanup:
3167         if (dns_rdataset_isassociated(&rdataset))
3168                 dns_rdataset_disassociate(&rdataset);
3169         dns_db_closeversion(db, &version, ISC_FALSE);
3170         dns_db_detachnode(db, &node);
3171         return (result);
3172 }
3173
3174 /*
3175  * Set the timer for refreshing the key zone to the soonest future time
3176  * of the set (current timer, keydata->refresh, keydata->addhd,
3177  * keydata->removehd).
3178  */
3179 static void
3180 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3181                     isc_stdtime_t now)
3182 {
3183         const char me[] = "set_refreshkeytimer";
3184         isc_stdtime_t then;
3185         isc_time_t timenow, timethen;
3186         char timebuf[80];
3187
3188         ENTER;
3189         then = key->refresh;
3190         if (key->addhd > now && key->addhd < then)
3191                 then = key->addhd;
3192         if (key->removehd > now && key->removehd < then)
3193                 then = key->removehd;
3194
3195         TIME_NOW(&timenow);
3196         if (then > now)
3197                 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
3198         else
3199                 timethen = timenow;
3200         if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
3201             isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
3202                 zone->refreshkeytime = timethen;
3203
3204         isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
3205         dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
3206         zone_settimer(zone, &timenow);
3207 }
3208
3209 /*
3210  * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3211  * If the key zone is changed, set '*changed' to ISC_TRUE.
3212  */
3213 static isc_result_t
3214 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3215                dns_diff_t *diff, dns_keytable_t *keytable,
3216                dns_keynode_t **keynodep, isc_boolean_t *changed)
3217 {
3218         const char me[] = "create_keydata";
3219         isc_result_t result = ISC_R_SUCCESS;
3220         isc_buffer_t keyb, dstb;
3221         unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3222         dns_rdata_keydata_t keydata;
3223         dns_rdata_dnskey_t dnskey;
3224         dns_rdata_t rdata = DNS_RDATA_INIT;
3225         dns_keynode_t *keynode;
3226         isc_stdtime_t now;
3227         isc_region_t r;
3228         dst_key_t *key;
3229
3230         REQUIRE(keynodep != NULL);
3231         keynode = *keynodep;
3232
3233         ENTER;
3234         isc_stdtime_get(&now);
3235
3236         /* Loop in case there's more than one key. */
3237         while (result == ISC_R_SUCCESS) {
3238                 dns_keynode_t *nextnode = NULL;
3239
3240                 key = dns_keynode_key(keynode);
3241                 if (key == NULL)
3242                         goto skip;
3243
3244                 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3245                 CHECK(dst_key_todns(key, &dstb));
3246
3247                 /* Convert DST key to DNSKEY. */
3248                 dns_rdata_reset(&rdata);
3249                 isc_buffer_usedregion(&dstb, &r);
3250                 dns_rdata_fromregion(&rdata, dst_key_class(key),
3251                                      dns_rdatatype_dnskey, &r);
3252
3253                 /* DSTKEY to KEYDATA. */
3254                 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3255                 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3256                                              NULL));
3257
3258                 /* KEYDATA to rdata. */
3259                 dns_rdata_reset(&rdata);
3260                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3261                 CHECK(dns_rdata_fromstruct(&rdata,
3262                                            zone->rdclass, dns_rdatatype_keydata,
3263                                            &keydata, &keyb));
3264
3265                 /* Add rdata to zone. */
3266                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3267                                     dst_key_name(key), 0, &rdata));
3268                 *changed = ISC_TRUE;
3269                 /* Refresh new keys from the zone apex as soon as possible. */
3270                 set_refreshkeytimer(zone, &keydata, now);
3271
3272  skip:
3273                 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3274                 if (result != ISC_R_NOTFOUND) {
3275                         dns_keytable_detachkeynode(keytable, &keynode);
3276                         keynode = nextnode;
3277                 }
3278         }
3279
3280         if (keynode != NULL)
3281                 dns_keytable_detachkeynode(keytable, &keynode);
3282         *keynodep = NULL;
3283
3284         return (ISC_R_SUCCESS);
3285
3286   failure:
3287         return (result);
3288 }
3289
3290 /*
3291  * Remove from the key zone all the KEYDATA records found in rdataset.
3292  */
3293 static isc_result_t
3294 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3295                dns_name_t *name, dns_rdataset_t *rdataset)
3296 {
3297         dns_rdata_t rdata = DNS_RDATA_INIT;
3298         isc_result_t result, uresult;
3299
3300         for (result = dns_rdataset_first(rdataset);
3301              result == ISC_R_SUCCESS;
3302              result = dns_rdataset_next(rdataset)) {
3303                 dns_rdata_reset(&rdata);
3304                 dns_rdataset_current(rdataset, &rdata);
3305                 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3306                                         name, 0, &rdata);
3307                 if (uresult != ISC_R_SUCCESS)
3308                         return (uresult);
3309         }
3310         if (result == ISC_R_NOMORE)
3311                 result = ISC_R_SUCCESS;
3312         return (result);
3313 }
3314
3315 /*
3316  * Compute the DNSSEC key ID for a DNSKEY record.
3317  */
3318 static isc_result_t
3319 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3320             dns_keytag_t *tag)
3321 {
3322         isc_result_t result;
3323         dns_rdata_t rdata = DNS_RDATA_INIT;
3324         unsigned char data[4096];
3325         isc_buffer_t buffer;
3326         dst_key_t *dstkey = NULL;
3327
3328         isc_buffer_init(&buffer, data, sizeof(data));
3329         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3330                              dns_rdatatype_dnskey, dnskey, &buffer);
3331
3332         result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3333         if (result == ISC_R_SUCCESS)
3334                 *tag = dst_key_id(dstkey);
3335         dst_key_free(&dstkey);
3336
3337         return (result);
3338 }
3339
3340 /*
3341  * Add key to the security roots.
3342  */
3343 static void
3344 trust_key(dns_zone_t *zone, dns_name_t *keyname,
3345           dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
3346         isc_result_t result;
3347         dns_rdata_t rdata = DNS_RDATA_INIT;
3348         unsigned char data[4096];
3349         isc_buffer_t buffer;
3350         dns_keytable_t *sr = NULL;
3351         dst_key_t *dstkey = NULL;
3352
3353         /* Convert dnskey to DST key. */
3354         isc_buffer_init(&buffer, data, sizeof(data));
3355         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3356                              dns_rdatatype_dnskey, dnskey, &buffer);
3357
3358         result = dns_view_getsecroots(zone->view, &sr);
3359         if (result != ISC_R_SUCCESS)
3360                 goto failure;
3361
3362         CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
3363         CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
3364         dns_keytable_detach(&sr);
3365
3366   failure:
3367         if (dstkey != NULL)
3368                 dst_key_free(&dstkey);
3369         if (sr != NULL)
3370                 dns_keytable_detach(&sr);
3371         return;
3372 }
3373
3374 /*
3375  * Add a null key to the security roots for so that all queries
3376  * to the zone will fail.
3377  */
3378 static void
3379 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
3380         isc_result_t result;
3381         dns_keytable_t *sr = NULL;
3382
3383         result = dns_view_getsecroots(zone->view, &sr);
3384         if (result == ISC_R_SUCCESS) {
3385                 dns_keytable_marksecure(sr, keyname);
3386                 dns_keytable_detach(&sr);
3387         }
3388 }
3389
3390 /*
3391  * Scan a set of KEYDATA records from the key zone.  The ones that are
3392  * valid (i.e., the add holddown timer has expired) become trusted keys.
3393  */
3394 static void
3395 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
3396         isc_result_t result;
3397         dns_rdata_t rdata = DNS_RDATA_INIT;
3398         dns_rdata_keydata_t keydata;
3399         dns_rdata_dnskey_t dnskey;
3400         isc_mem_t *mctx = zone->mctx;
3401         int trusted = 0, revoked = 0, pending = 0;
3402         isc_stdtime_t now;
3403         dns_keytable_t *sr = NULL;
3404
3405         isc_stdtime_get(&now);
3406
3407         result = dns_view_getsecroots(zone->view, &sr);
3408         if (result == ISC_R_SUCCESS) {
3409                 dns_keytable_delete(sr, name);
3410                 dns_keytable_detach(&sr);
3411         }
3412
3413         /* Now insert all the accepted trust anchors from this keydata set. */
3414         for (result = dns_rdataset_first(rdataset);
3415              result == ISC_R_SUCCESS;
3416              result = dns_rdataset_next(rdataset)) {
3417                 dns_rdata_reset(&rdata);
3418                 dns_rdataset_current(rdataset, &rdata);
3419
3420                 /* Convert rdata to keydata. */
3421                 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
3422                 if (result == ISC_R_UNEXPECTEDEND)
3423                         continue;
3424                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3425
3426                 /* Set the key refresh timer. */
3427                 set_refreshkeytimer(zone, &keydata, now);
3428
3429                 /* If the removal timer is nonzero, this key was revoked. */
3430                 if (keydata.removehd != 0) {
3431                         revoked++;
3432                         continue;
3433                 }
3434
3435                 /*
3436                  * If the add timer is still pending, this key is not
3437                  * trusted yet.
3438                  */
3439                 if (now < keydata.addhd) {
3440                         pending++;
3441                         continue;
3442                 }
3443
3444                 /* Convert keydata to dnskey. */
3445                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
3446
3447                 /* Add to keytables. */
3448                 trusted++;
3449                 trust_key(zone, name, &dnskey, mctx);
3450         }
3451
3452         if (trusted == 0 && pending != 0) {
3453                 char namebuf[DNS_NAME_FORMATSIZE];
3454                 dns_name_format(name, namebuf, sizeof namebuf);
3455                 dns_zone_log(zone, ISC_LOG_ERROR,
3456                              "No valid trust anchors for '%s'!", namebuf);
3457                 dns_zone_log(zone, ISC_LOG_ERROR,
3458                              "%d key(s) revoked, %d still pending",
3459                              revoked, pending);
3460                 dns_zone_log(zone, ISC_LOG_ERROR,
3461                              "All queries to '%s' will fail", namebuf);
3462                 fail_secure(zone, name);
3463         }
3464 }
3465
3466 static isc_result_t
3467 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3468              dns_diff_t *diff)
3469 {
3470         dns_diff_t temp_diff;
3471         isc_result_t result;
3472
3473         /*
3474          * Create a singleton diff.
3475          */
3476         dns_diff_init(diff->mctx, &temp_diff);
3477         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3478
3479         /*
3480          * Apply it to the database.
3481          */
3482         result = dns_diff_apply(&temp_diff, db, ver);
3483         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3484         if (result != ISC_R_SUCCESS) {
3485                 dns_difftuple_free(tuple);
3486                 return (result);
3487         }
3488
3489         /*
3490          * Merge it into the current pending journal entry.
3491          */
3492         dns_diff_appendminimal(diff, tuple);
3493
3494         /*
3495          * Do not clear temp_diff.
3496          */
3497         return (ISC_R_SUCCESS);
3498 }
3499
3500 static isc_result_t
3501 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3502               dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3503               dns_rdata_t *rdata)
3504 {
3505         dns_difftuple_t *tuple = NULL;
3506         isc_result_t result;
3507         result = dns_difftuple_create(diff->mctx, op,
3508                                       name, ttl, rdata, &tuple);
3509         if (result != ISC_R_SUCCESS)
3510                 return (result);
3511         return (do_one_tuple(&tuple, db, ver, diff));
3512 }
3513
3514 static isc_result_t
3515 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3516                   isc_mem_t *mctx, dns_updatemethod_t method) {
3517         dns_difftuple_t *deltuple = NULL;
3518         dns_difftuple_t *addtuple = NULL;
3519         isc_uint32_t serial;
3520         isc_result_t result;
3521
3522         CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3523         CHECK(dns_difftuple_copy(deltuple, &addtuple));
3524         addtuple->op = DNS_DIFFOP_ADD;
3525
3526         serial = dns_soa_getserial(&addtuple->rdata);
3527         serial = dns_update_soaserial(serial, method);
3528         dns_soa_setserial(serial, &addtuple->rdata);
3529         CHECK(do_one_tuple(&deltuple, db, ver, diff));
3530         CHECK(do_one_tuple(&addtuple, db, ver, diff));
3531         result = ISC_R_SUCCESS;
3532
3533         failure:
3534         if (addtuple != NULL)
3535                 dns_difftuple_free(&addtuple);
3536         if (deltuple != NULL)
3537                 dns_difftuple_free(&deltuple);
3538         return (result);
3539 }
3540
3541 /*
3542  * Write all transactions in 'diff' to the zone journal file.
3543  */
3544 static isc_result_t
3545 zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial,
3546              const char *caller)
3547 {
3548         const char me[] = "zone_journal";
3549         const char *journalfile;
3550         isc_result_t result = ISC_R_SUCCESS;
3551         dns_journal_t *journal = NULL;
3552         unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
3553
3554         ENTER;
3555         journalfile = dns_zone_getjournal(zone);
3556         if (journalfile != NULL) {
3557                 result = dns_journal_open(zone->mctx, journalfile, mode,
3558                                           &journal);
3559                 if (result != ISC_R_SUCCESS) {
3560                         dns_zone_log(zone, ISC_LOG_ERROR,
3561                                      "%s:dns_journal_open -> %s",
3562                                      caller, dns_result_totext(result));
3563                         return (result);
3564                 }
3565
3566                 if (sourceserial != NULL)
3567                         dns_journal_set_sourceserial(journal, *sourceserial);
3568
3569                 result = dns_journal_write_transaction(journal, diff);
3570                 if (result != ISC_R_SUCCESS) {
3571                         dns_zone_log(zone, ISC_LOG_ERROR,
3572                                      "%s:dns_journal_write_transaction -> %s",
3573                                      caller, dns_result_totext(result));
3574                 }
3575                 dns_journal_destroy(&journal);
3576         }
3577
3578         return (result);
3579 }
3580
3581 /*
3582  * Create an SOA record for a newly-created zone
3583  */
3584 static isc_result_t
3585 add_soa(dns_zone_t *zone, dns_db_t *db) {
3586         isc_result_t result;
3587         dns_rdata_t rdata = DNS_RDATA_INIT;
3588         unsigned char buf[DNS_SOA_BUFFERSIZE];
3589         dns_dbversion_t *ver = NULL;
3590         dns_diff_t diff;
3591
3592         dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3593
3594         dns_diff_init(zone->mctx, &diff);
3595         result = dns_db_newversion(db, &ver);
3596         if (result != ISC_R_SUCCESS) {
3597                 dns_zone_log(zone, ISC_LOG_ERROR,
3598                              "add_soa:dns_db_newversion -> %s",
3599                              dns_result_totext(result));
3600                 goto failure;
3601         }
3602
3603         /* Build SOA record */
3604         result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3605                                     0, 0, 0, 0, 0, buf, &rdata);
3606         if (result != ISC_R_SUCCESS) {
3607                 dns_zone_log(zone, ISC_LOG_ERROR,
3608                              "add_soa:dns_soa_buildrdata -> %s",
3609                              dns_result_totext(result));
3610                 goto failure;
3611         }
3612
3613         result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3614                                &zone->origin, 0, &rdata);
3615
3616 failure:
3617         dns_diff_clear(&diff);
3618         if (ver != NULL)
3619                 dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3620
3621         return (result);
3622 }
3623
3624 /*
3625  * Synchronize the set of initializing keys found in managed-keys {}
3626  * statements with the set of trust anchors found in the managed-keys.bind
3627  * zone.  If a domain is no longer named in managed-keys, delete all keys
3628  * from that domain from the key zone.  If a domain is mentioned in in
3629  * managed-keys but there are no references to it in the key zone, load
3630  * the key zone with the initializing key(s) for that domain.
3631  */
3632 static isc_result_t
3633 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3634         isc_result_t result = ISC_R_SUCCESS;
3635         isc_boolean_t changed = ISC_FALSE;
3636         isc_boolean_t commit = ISC_FALSE;
3637         dns_rbtnodechain_t chain;
3638         dns_fixedname_t fn;
3639         dns_name_t foundname, *origin;
3640         dns_keynode_t *keynode = NULL;
3641         dns_view_t *view = zone->view;
3642         dns_keytable_t *sr = NULL;
3643         dns_dbversion_t *ver = NULL;
3644         dns_diff_t diff;
3645         dns_rriterator_t rrit;
3646
3647         dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3648
3649         dns_name_init(&foundname, NULL);
3650         dns_fixedname_init(&fn);
3651         origin = dns_fixedname_name(&fn);
3652
3653         dns_diff_init(zone->mctx, &diff);
3654
3655         CHECK(dns_view_getsecroots(view, &sr));
3656
3657         result = dns_db_newversion(db, &ver);
3658         if (result != ISC_R_SUCCESS) {
3659                 dns_zone_log(zone, ISC_LOG_ERROR,
3660                              "sync_keyzone:dns_db_newversion -> %s",
3661                              dns_result_totext(result));
3662                 goto failure;
3663         }
3664
3665         /*
3666          * Walk the zone DB.  If we find any keys whose names are no longer
3667          * in managed-keys (or *are* in trusted-keys, meaning they are
3668          * permanent and not RFC5011-maintained), delete them from the
3669          * zone.  Otherwise call load_secroots(), which loads keys into
3670          * secroots as appropriate.
3671          */
3672         dns_rriterator_init(&rrit, db, ver, 0);
3673         for (result = dns_rriterator_first(&rrit);
3674              result == ISC_R_SUCCESS;
3675              result = dns_rriterator_nextrrset(&rrit)) {
3676                 dns_rdataset_t *rdataset = NULL;
3677                 dns_name_t *rrname = NULL;
3678                 isc_uint32_t ttl;
3679
3680                 dns_rriterator_current(&rrit, &rrname, &ttl,
3681                                        &rdataset, NULL);
3682                 if (!dns_rdataset_isassociated(rdataset)) {
3683                         dns_rriterator_destroy(&rrit);
3684                         goto failure;
3685                 }
3686
3687                 if (rdataset->type != dns_rdatatype_keydata)
3688                         continue;
3689
3690                 result = dns_keytable_find(sr, rrname, &keynode);
3691                 if ((result != ISC_R_SUCCESS &&
3692                      result != DNS_R_PARTIALMATCH) ||
3693                     dns_keynode_managed(keynode) == ISC_FALSE) {
3694                         CHECK(delete_keydata(db, ver, &diff,
3695                                              rrname, rdataset));
3696                         changed = ISC_TRUE;
3697                 } else {
3698                         load_secroots(zone, rrname, rdataset);
3699                 }
3700
3701                 if (keynode != NULL)
3702                         dns_keytable_detachkeynode(sr, &keynode);
3703         }
3704         dns_rriterator_destroy(&rrit);
3705
3706         /*
3707          * Now walk secroots to find any managed keys that aren't
3708          * in the zone.  If we find any, we add them to the zone.
3709          */
3710         RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3711         dns_rbtnodechain_init(&chain, zone->mctx);
3712         result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3713         if (result == ISC_R_NOTFOUND)
3714                 result = ISC_R_NOMORE;
3715         while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3716                 dns_rbtnode_t *rbtnode = NULL;
3717
3718                 dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3719                 if (rbtnode->data == NULL)
3720                         goto skip;
3721
3722                 dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3723                 if (dns_keynode_managed(keynode)) {
3724                         dns_fixedname_t fname;
3725                         dns_name_t *keyname;
3726                         dst_key_t *key;
3727
3728                         key = dns_keynode_key(keynode);
3729                         dns_fixedname_init(&fname);
3730
3731                         if (key == NULL)   /* fail_secure() was called. */
3732                                 goto skip;
3733
3734                         keyname = dst_key_name(key);
3735                         result = dns_db_find(db, keyname, ver,
3736                                              dns_rdatatype_keydata,
3737                                              DNS_DBFIND_NOWILD, 0, NULL,
3738                                              dns_fixedname_name(&fname),
3739                                              NULL, NULL);
3740                         if (result != ISC_R_SUCCESS)
3741                                 result = create_keydata(zone, db, ver, &diff,
3742                                                         sr, &keynode, &changed);
3743                         if (result != ISC_R_SUCCESS)
3744                                 break;
3745                 }
3746   skip:
3747                 result = dns_rbtnodechain_next(&chain, &foundname, origin);
3748                 if (keynode != NULL)
3749                         dns_keytable_detachkeynode(sr, &keynode);
3750         }
3751         RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3752
3753         if (result == ISC_R_NOMORE)
3754                 result = ISC_R_SUCCESS;
3755
3756         if (changed) {
3757                 /* Write changes to journal file. */
3758                 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
3759                                         zone->updatemethod));
3760                 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
3761
3762                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3763                 zone_needdump(zone, 30);
3764                 commit = ISC_TRUE;
3765         }
3766
3767  failure:
3768         if (result != ISC_R_SUCCESS &&
3769             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3770                 dns_zone_log(zone, ISC_LOG_ERROR,
3771                              "unable to synchronize managed keys: %s",
3772                              dns_result_totext(result));
3773                 isc_time_settoepoch(&zone->refreshkeytime);
3774         }
3775         if (keynode != NULL)
3776                 dns_keytable_detachkeynode(sr, &keynode);
3777         if (sr != NULL)
3778                 dns_keytable_detach(&sr);
3779         if (ver != NULL)
3780                 dns_db_closeversion(db, &ver, commit);
3781         dns_diff_clear(&diff);
3782
3783         return (result);
3784 }
3785
3786 isc_result_t
3787 dns_zone_synckeyzone(dns_zone_t *zone) {
3788         isc_result_t result;
3789         dns_db_t *db = NULL;
3790
3791         if (zone->type != dns_zone_key)
3792                 return (DNS_R_BADZONE);
3793
3794         CHECK(dns_zone_getdb(zone, &db));
3795
3796         LOCK_ZONE(zone);
3797         result = sync_keyzone(zone, db);
3798         UNLOCK_ZONE(zone);
3799
3800  failure:
3801         if (db != NULL)
3802                 dns_db_detach(&db);
3803         return (result);
3804 }
3805
3806 static void
3807 maybe_send_secure(dns_zone_t *zone) {
3808         isc_result_t result;
3809
3810         /*
3811          * We've finished loading, or else failed to load, an inline-signing
3812          * 'secure' zone.  We now need information about the status of the
3813          * 'raw' zone.  If we failed to load, then we need it to send a
3814          * copy of its database; if we succeeded, we need it to send its
3815          * serial number so that we can sync with it.  If it has not yet
3816          * loaded, we set a flag so that it will send the necessary
3817          * information when it has finished loading.
3818          */
3819         if (zone->raw->db != NULL) {
3820                 if (zone->db != NULL) {
3821                         isc_uint32_t serial;
3822                         unsigned int soacount;
3823
3824                         result = zone_get_from_db(zone->raw, zone->raw->db,
3825                                                   NULL, &soacount, &serial, NULL,
3826                                                   NULL, NULL, NULL, NULL);
3827                         if (result == ISC_R_SUCCESS && soacount > 0U)
3828                                 zone_send_secureserial(zone->raw, serial);
3829                 } else
3830                         zone_send_securedb(zone->raw, zone->raw->db);
3831
3832         } else
3833                 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
3834 }
3835
3836 static isc_boolean_t
3837 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
3838         isc_result_t result;
3839         isc_boolean_t answer = ISC_FALSE;
3840         dns_diff_t diff;
3841
3842         dns_diff_init(mctx, &diff);
3843         result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
3844         if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
3845                 answer = ISC_TRUE;
3846         dns_diff_clear(&diff);
3847         return (answer);
3848 }
3849
3850 /*
3851  * The zone is presumed to be locked.
3852  * If this is a inline_raw zone the secure version is also locked.
3853  */
3854 static isc_result_t
3855 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3856               isc_result_t result)
3857 {
3858         unsigned int soacount = 0;
3859         unsigned int nscount = 0;
3860         unsigned int errors = 0;
3861         isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3862         isc_time_t now;
3863         isc_boolean_t needdump = ISC_FALSE;
3864         isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3865         isc_boolean_t nomaster = ISC_FALSE;
3866         unsigned int options;
3867
3868         INSIST(LOCKED_ZONE(zone));
3869         if (inline_raw(zone))
3870                 INSIST(LOCKED_ZONE(zone->secure));
3871
3872         TIME_NOW(&now);
3873
3874         /*
3875          * Initiate zone transfer?  We may need a error code that
3876          * indicates that the "permanent" form does not exist.
3877          * XXX better error feedback to log.
3878          */
3879         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3880                 if (zone->type == dns_zone_slave ||
3881                     zone->type == dns_zone_stub ||
3882                     (zone->type == dns_zone_redirect &&
3883                      zone->masters == NULL)) {
3884                         if (result == ISC_R_FILENOTFOUND)
3885                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3886                                              "no master file");
3887                         else if (result != DNS_R_NOMASTERFILE)
3888                                 dns_zone_log(zone, ISC_LOG_ERROR,
3889                                              "loading from master file %s "
3890                                              "failed: %s",
3891                                              zone->masterfile,
3892                                              dns_result_totext(result));
3893                 } else if (zone->type == dns_zone_master &&
3894                            inline_secure(zone) && result == ISC_R_FILENOTFOUND)
3895                 {
3896                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
3897                                      "no master file, requesting db");
3898                         maybe_send_secure(zone);
3899                 } else {
3900                         int level = ISC_LOG_ERROR;
3901                         if (zone->type == dns_zone_key &&
3902                             result == ISC_R_FILENOTFOUND)
3903                                 level = ISC_LOG_DEBUG(1);
3904                         dns_zone_log(zone, level,
3905                                      "loading from master file %s failed: %s",
3906                                      zone->masterfile,
3907                                      dns_result_totext(result));
3908                         nomaster = ISC_TRUE;
3909                 }
3910
3911                 if (zone->type != dns_zone_key)
3912                         goto cleanup;
3913         }
3914
3915         dns_zone_log(zone, ISC_LOG_DEBUG(2),
3916                      "number of nodes in database: %u",
3917                      dns_db_nodecount(db));
3918
3919         if (result == DNS_R_SEENINCLUDE)
3920                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3921         else
3922                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3923
3924         /*
3925          * If there's no master file for a key zone, then the zone is new:
3926          * create an SOA record.  (We do this now, instead of later, so that
3927          * if there happens to be a journal file, we can roll forward from
3928          * a sane starting point.)
3929          */
3930         if (nomaster && zone->type == dns_zone_key) {
3931                 result = add_soa(zone, db);
3932                 if (result != ISC_R_SUCCESS)
3933                         goto cleanup;
3934         }
3935
3936         /*
3937          * Apply update log, if any, on initial load.
3938          */
3939         if (zone->journal != NULL &&
3940             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
3941             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3942         {
3943                 if (zone->type == dns_zone_master &&
3944                     (zone->update_acl != NULL || zone->ssutable != NULL))
3945                         options = DNS_JOURNALOPT_RESIGN;
3946                 else
3947                         options = 0;
3948                 result = dns_journal_rollforward2(zone->mctx, db, options,
3949                                                   0, zone->journal);
3950                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
3951                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
3952                     result != ISC_R_RANGE) {
3953                         dns_zone_log(zone, ISC_LOG_ERROR,
3954                                      "journal rollforward failed: %s",
3955                                      dns_result_totext(result));
3956                         goto cleanup;
3957
3958
3959                 }
3960                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
3961                         dns_zone_log(zone, ISC_LOG_ERROR,
3962                                      "journal rollforward failed: "
3963                                      "journal out of sync with zone");
3964                         goto cleanup;
3965                 }
3966                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3967                              "journal rollforward completed "
3968                              "successfully: %s",
3969                              dns_result_totext(result));
3970                 if (result == ISC_R_SUCCESS)
3971                         needdump = ISC_TRUE;
3972         }
3973
3974         /*
3975          * Obtain ns, soa and cname counts for top of zone.
3976          */
3977         INSIST(db != NULL);
3978         result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
3979                                   &refresh, &retry, &expire, &minimum,
3980                                   &errors);
3981         if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
3982                 dns_zone_log(zone, ISC_LOG_ERROR,
3983                              "could not find NS and/or SOA records");
3984         }
3985
3986         /*
3987          * Check to make sure the journal is up to date, and remove the
3988          * journal file if it isn't, as we wouldn't be able to apply
3989          * updates otherwise.
3990          */
3991         if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) &&
3992             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
3993                 isc_uint32_t jserial;
3994                 dns_journal_t *journal = NULL;
3995
3996                 result = dns_journal_open(zone->mctx, zone->journal,
3997                                           DNS_JOURNAL_READ, &journal);
3998                 if (result == ISC_R_SUCCESS) {
3999                         jserial = dns_journal_last_serial(journal);
4000                         dns_journal_destroy(&journal);
4001                 } else {
4002                         jserial = serial;
4003                         result = ISC_R_SUCCESS;
4004                 }
4005
4006                 if (jserial != serial) {
4007                         dns_zone_log(zone, ISC_LOG_INFO,
4008                                      "journal file is out of date: "
4009                                      "removing journal file");
4010                         if (remove(zone->journal) < 0 && errno != ENOENT) {
4011                                 char strbuf[ISC_STRERRORSIZE];
4012                                 isc__strerror(errno, strbuf, sizeof(strbuf));
4013                                 isc_log_write(dns_lctx,
4014                                               DNS_LOGCATEGORY_GENERAL,
4015                                               DNS_LOGMODULE_ZONE,
4016                                               ISC_LOG_WARNING,
4017                                               "unable to remove journal "
4018                                               "'%s': '%s'",
4019                                               zone->journal, strbuf);
4020                         }
4021                 }
4022         }
4023
4024         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
4025
4026         /*
4027          * Master / Slave / Stub zones require both NS and SOA records at
4028          * the top of the zone.
4029          */
4030
4031         switch (zone->type) {
4032         case dns_zone_dlz:
4033         case dns_zone_master:
4034         case dns_zone_slave:
4035         case dns_zone_stub:
4036         case dns_zone_redirect:
4037                 if (soacount != 1) {
4038                         dns_zone_log(zone, ISC_LOG_ERROR,
4039                                      "has %d SOA records", soacount);
4040                         result = DNS_R_BADZONE;
4041                 }
4042                 if (nscount == 0) {
4043                         dns_zone_log(zone, ISC_LOG_ERROR,
4044                                      "has no NS records");
4045                         result = DNS_R_BADZONE;
4046                 }
4047                 if (result != ISC_R_SUCCESS)
4048                         goto cleanup;
4049                 if (zone->type == dns_zone_master && errors != 0) {
4050                         result = DNS_R_BADZONE;
4051                         goto cleanup;
4052                 }
4053                 if (zone->type != dns_zone_stub &&
4054                     zone->type != dns_zone_redirect) {
4055                         result = check_nsec3param(zone, db);
4056                         if (result != ISC_R_SUCCESS)
4057                                 goto cleanup;
4058                 }
4059                 if (zone->type == dns_zone_master &&
4060                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4061                     !integrity_checks(zone, db)) {
4062                         result = DNS_R_BADZONE;
4063                         goto cleanup;
4064                 }
4065                 if (zone->type == dns_zone_master &&
4066                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4067                     !zone_check_dup(zone, db)) {
4068                         result = DNS_R_BADZONE;
4069                         goto cleanup;
4070                 }
4071
4072                 if (zone->db != NULL) {
4073                         unsigned int oldsoacount;
4074
4075                         /*
4076                          * This is checked in zone_replacedb() for slave zones
4077                          * as they don't reload from disk.
4078                          */
4079                         result = zone_get_from_db(zone, zone->db, NULL,
4080                                                   &oldsoacount, &oldserial,
4081                                                   NULL, NULL, NULL, NULL,
4082                                                   NULL);
4083                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4084                         RUNTIME_CHECK(soacount > 0U);
4085                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4086                             !isc_serial_gt(serial, oldserial)) {
4087                                 isc_uint32_t serialmin, serialmax;
4088
4089                                 INSIST(zone->type == dns_zone_master);
4090
4091                                 if (serial == oldserial &&
4092                                     zone_unchanged(zone->db, db, zone->mctx)) {
4093                                         dns_zone_log(zone, ISC_LOG_INFO,
4094                                                      "ixfr-from-differences: "
4095                                                      "unchanged");
4096                                         return(ISC_R_SUCCESS);
4097                                 }
4098
4099                                 serialmin = (oldserial + 1) & 0xffffffffU;
4100                                 serialmax = (oldserial + 0x7fffffffU) &
4101                                              0xffffffffU;
4102                                 dns_zone_log(zone, ISC_LOG_ERROR,
4103                                              "ixfr-from-differences: "
4104                                              "new serial (%u) out of range "
4105                                              "[%u - %u]", serial, serialmin,
4106                                              serialmax);
4107                                 result = DNS_R_BADZONE;
4108                                 goto cleanup;
4109                         } else if (!isc_serial_ge(serial, oldserial))
4110                                 dns_zone_log(zone, ISC_LOG_ERROR,
4111                                              "zone serial (%u/%u) has gone "
4112                                              "backwards", serial, oldserial);
4113                         else if (serial == oldserial && !hasinclude &&
4114                                  strcmp(zone->db_argv[0], "_builtin") != 0)
4115                                 dns_zone_log(zone, ISC_LOG_ERROR,
4116                                              "zone serial (%u) unchanged. "
4117                                              "zone may fail to transfer "
4118                                              "to slaves.", serial);
4119                 }
4120
4121                 if (zone->type == dns_zone_master &&
4122                     (zone->update_acl != NULL || zone->ssutable != NULL) &&
4123                     zone->sigresigninginterval < (3 * refresh) &&
4124                     dns_db_issecure(db))
4125                 {
4126                         dns_zone_log(zone, ISC_LOG_WARNING,
4127                                      "sig-re-signing-interval less than "
4128                                      "3 * refresh.");
4129                 }
4130
4131                 zone->refresh = RANGE(refresh,
4132                                       zone->minrefresh, zone->maxrefresh);
4133                 zone->retry = RANGE(retry,
4134                                     zone->minretry, zone->maxretry);
4135                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
4136                                      DNS_MAX_EXPIRE);
4137                 zone->minimum = minimum;
4138                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4139
4140                 if (zone->type == dns_zone_slave ||
4141                     zone->type == dns_zone_stub ||
4142                     (zone->type == dns_zone_redirect &&
4143                      zone->masters != NULL)) {
4144                         isc_time_t t;
4145                         isc_uint32_t delay;
4146
4147                         result = isc_file_getmodtime(zone->journal, &t);
4148                         if (result != ISC_R_SUCCESS)
4149                                 result = isc_file_getmodtime(zone->masterfile,
4150                                                              &t);
4151                         if (result == ISC_R_SUCCESS)
4152                                 DNS_ZONE_TIME_ADD(&t, zone->expire,
4153                                                   &zone->expiretime);
4154                         else
4155                                 DNS_ZONE_TIME_ADD(&now, zone->retry,
4156                                                   &zone->expiretime);
4157
4158                         delay = isc_random_jitter(zone->retry,
4159                                                   (zone->retry * 3) / 4);
4160                         DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
4161                         if (isc_time_compare(&zone->refreshtime,
4162                                              &zone->expiretime) >= 0)
4163                                 zone->refreshtime = now;
4164                 }
4165
4166                 break;
4167
4168         case dns_zone_key:
4169                 result = sync_keyzone(zone, db);
4170                 if (result != ISC_R_SUCCESS)
4171                         goto cleanup;
4172                 break;
4173
4174         default:
4175                 UNEXPECTED_ERROR(__FILE__, __LINE__,
4176                                  "unexpected zone type %d", zone->type);
4177                 result = ISC_R_UNEXPECTED;
4178                 goto cleanup;
4179         }
4180
4181         /*
4182          * Check for weak DNSKEY's.
4183          */
4184         if (zone->type == dns_zone_master)
4185                 zone_check_dnskeys(zone, db);
4186
4187         /*
4188          * Schedule DNSSEC key refresh.
4189          */
4190         if (zone->type == dns_zone_master &&
4191             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
4192                 zone->refreshkeytime = now;
4193
4194 #if 0
4195         /* destroy notification example. */
4196         {
4197                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
4198                                                     DNS_EVENT_DBDESTROYED,
4199                                                     dns_zonemgr_dbdestroyed,
4200                                                     zone,
4201                                                     sizeof(isc_event_t));
4202                 dns_db_ondestroy(db, zone->task, &e);
4203         }
4204 #endif
4205
4206         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4207         if (zone->db != NULL) {
4208                 result = zone_replacedb(zone, db, ISC_FALSE);
4209                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4210                 if (result != ISC_R_SUCCESS)
4211                         goto cleanup;
4212         } else {
4213                 zone_attachdb(zone, db);
4214                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4215                 DNS_ZONE_SETFLAG(zone,
4216                                  DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
4217                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
4218                     inline_raw(zone))
4219                 {
4220                         if (zone->secure->db == NULL)
4221                                 zone_send_securedb(zone, db);
4222                         else
4223                                 zone_send_secureserial(zone, serial);
4224                 }
4225         }
4226
4227         /*
4228          * Finished loading inline-signing zone; need to get status
4229          * from the raw side now.
4230          */
4231         if (zone->type == dns_zone_master && inline_secure(zone))
4232                 maybe_send_secure(zone);
4233
4234
4235         result = ISC_R_SUCCESS;
4236
4237         if (needdump) {
4238                 if (zone->type == dns_zone_key)
4239                         zone_needdump(zone, 30);
4240                 else
4241                         zone_needdump(zone, DNS_DUMP_DELAY);
4242         }
4243
4244         if (zone->task != NULL) {
4245                 if (zone->type == dns_zone_master) {
4246                         set_resigntime(zone);
4247                         resume_signingwithkey(zone);
4248                         resume_addnsec3chain(zone);
4249                 }
4250
4251                 if (zone->type == dns_zone_master &&
4252                     !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4253                     dns_zone_isdynamic(zone, ISC_FALSE) &&
4254                     dns_db_issecure(db)) {
4255                         dns_name_t *name;
4256                         dns_fixedname_t fixed;
4257                         dns_rdataset_t next;
4258
4259                         dns_rdataset_init(&next);
4260                         dns_fixedname_init(&fixed);
4261                         name = dns_fixedname_name(&fixed);
4262
4263                         result = dns_db_getsigningtime(db, &next, name);
4264                         if (result == ISC_R_SUCCESS) {
4265                                 isc_stdtime_t timenow;
4266                                 char namebuf[DNS_NAME_FORMATSIZE];
4267                                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4268
4269                                 isc_stdtime_get(&timenow);
4270                                 dns_name_format(name, namebuf, sizeof(namebuf));
4271                                 dns_rdatatype_format(next.covers,
4272                                                      typebuf, sizeof(typebuf));
4273                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
4274                                              "next resign: %s/%s in %d seconds",
4275                                              namebuf, typebuf,
4276                                              next.resign - timenow -
4277                                              zone->sigresigninginterval);
4278                                 dns_rdataset_disassociate(&next);
4279                         } else
4280                                 dns_zone_log(zone, ISC_LOG_WARNING,
4281                                              "signed dynamic zone has no "
4282                                              "resign event scheduled");
4283                 }
4284
4285                 zone_settimer(zone, &now);
4286         }
4287
4288         if (! dns_db_ispersistent(db))
4289                 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
4290                              dns_db_issecure(db) ? " (DNSSEC signed)" : "");
4291
4292         zone->loadtime = loadtime;
4293         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
4294         return (result);
4295
4296  cleanup:
4297         if (zone->type == dns_zone_slave ||
4298             zone->type == dns_zone_stub ||
4299             zone->type == dns_zone_key ||
4300             (zone->type == dns_zone_redirect && zone->masters != NULL)) {
4301                 if (zone->journal != NULL)
4302                         zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
4303                 if (zone->masterfile != NULL)
4304                         zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
4305
4306                 /* Mark the zone for immediate refresh. */
4307                 zone->refreshtime = now;
4308                 if (zone->task != NULL)
4309                         zone_settimer(zone, &now);
4310                 result = ISC_R_SUCCESS;
4311         } else if (zone->type == dns_zone_master ||
4312                    zone->type == dns_zone_redirect) {
4313                 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND))
4314                         dns_zone_log(zone, ISC_LOG_ERROR,
4315                                      "not loaded due to errors.");
4316                 else if (zone->type == dns_zone_master)
4317                         result = ISC_R_SUCCESS;
4318         }
4319
4320         return (result);
4321 }
4322
4323 static isc_boolean_t
4324 exit_check(dns_zone_t *zone) {
4325         REQUIRE(LOCKED_ZONE(zone));
4326
4327         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
4328                 /*
4329                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
4330                  */
4331                 INSIST(isc_refcount_current(&zone->erefs) == 0);
4332                 return (ISC_TRUE);
4333         }
4334         return (ISC_FALSE);
4335 }
4336
4337 static isc_boolean_t
4338 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
4339               dns_name_t *name, isc_boolean_t logit)
4340 {
4341         isc_result_t result;
4342         char namebuf[DNS_NAME_FORMATSIZE];
4343         char altbuf[DNS_NAME_FORMATSIZE];
4344         dns_fixedname_t fixed;
4345         dns_name_t *foundname;
4346         int level;
4347
4348         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
4349                 return (ISC_TRUE);
4350
4351         if (zone->type == dns_zone_master)
4352                 level = ISC_LOG_ERROR;
4353         else
4354                 level = ISC_LOG_WARNING;
4355
4356         dns_fixedname_init(&fixed);
4357         foundname = dns_fixedname_name(&fixed);
4358
4359         result = dns_db_find(db, name, version, dns_rdatatype_a,
4360                              0, 0, NULL, foundname, NULL, NULL);
4361         if (result == ISC_R_SUCCESS)
4362                 return (ISC_TRUE);
4363
4364         if (result == DNS_R_NXRRSET) {
4365                 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
4366                                      0, 0, NULL, foundname, NULL, NULL);
4367                 if (result == ISC_R_SUCCESS)
4368                         return (ISC_TRUE);
4369         }
4370
4371         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
4372             result == DNS_R_EMPTYNAME) {
4373                 if (logit) {
4374                         dns_name_format(name, namebuf, sizeof namebuf);
4375                         dns_zone_log(zone, level, "NS '%s' has no address "
4376                                      "records (A or AAAA)", namebuf);
4377                 }
4378                 return (ISC_FALSE);
4379         }
4380
4381         if (result == DNS_R_CNAME) {
4382                 if (logit) {
4383                         dns_name_format(name, namebuf, sizeof namebuf);
4384                         dns_zone_log(zone, level, "NS '%s' is a CNAME "
4385                                      "(illegal)", namebuf);
4386                 }
4387                 return (ISC_FALSE);
4388         }
4389
4390         if (result == DNS_R_DNAME) {
4391                 if (logit) {
4392                         dns_name_format(name, namebuf, sizeof namebuf);
4393                         dns_name_format(foundname, altbuf, sizeof altbuf);
4394                         dns_zone_log(zone, level, "NS '%s' is below a DNAME "
4395                                      "'%s' (illegal)", namebuf, altbuf);
4396                 }
4397                 return (ISC_FALSE);
4398         }
4399
4400         return (ISC_TRUE);
4401 }
4402
4403 static isc_result_t
4404 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
4405                  dns_dbversion_t *version, unsigned int *nscount,
4406                  unsigned int *errors, isc_boolean_t logit)
4407 {
4408         isc_result_t result;
4409         unsigned int count = 0;
4410         unsigned int ecount = 0;
4411         dns_rdataset_t rdataset;
4412         dns_rdata_t rdata;
4413         dns_rdata_ns_t ns;
4414
4415         dns_rdataset_init(&rdataset);
4416         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
4417                                      dns_rdatatype_none, 0, &rdataset, NULL);
4418         if (result == ISC_R_NOTFOUND) {
4419                 INSIST(!dns_rdataset_isassociated(&rdataset));
4420                 goto success;
4421         }
4422         if (result != ISC_R_SUCCESS) {
4423                 INSIST(!dns_rdataset_isassociated(&rdataset));
4424                 goto invalidate_rdataset;
4425         }
4426
4427         result = dns_rdataset_first(&rdataset);
4428         while (result == ISC_R_SUCCESS) {
4429                 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
4430                     (zone->type == dns_zone_master ||
4431                      zone->type == dns_zone_slave)) {
4432                         dns_rdata_init(&rdata);
4433                         dns_rdataset_current(&rdataset, &rdata);
4434                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
4435                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4436                         if (dns_name_issubdomain(&ns.name, &zone->origin) &&
4437                             !zone_check_ns(zone, db, version, &ns.name, logit))
4438                                 ecount++;
4439                 }
4440                 count++;
4441                 result = dns_rdataset_next(&rdataset);
4442         }
4443         dns_rdataset_disassociate(&rdataset);
4444
4445  success:
4446         if (nscount != NULL)
4447                 *nscount = count;
4448         if (errors != NULL)
4449                 *errors = ecount;
4450
4451         result = ISC_R_SUCCESS;
4452
4453  invalidate_rdataset:
4454         dns_rdataset_invalidate(&rdataset);
4455
4456         return (result);
4457 }
4458
4459 static isc_result_t
4460 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
4461                  unsigned int *soacount,
4462                  isc_uint32_t *serial, isc_uint32_t *refresh,
4463                  isc_uint32_t *retry, isc_uint32_t *expire,
4464                  isc_uint32_t *minimum)
4465 {
4466         isc_result_t result;
4467         unsigned int count;
4468         dns_rdataset_t rdataset;
4469         dns_rdata_t rdata = DNS_RDATA_INIT;
4470         dns_rdata_soa_t soa;
4471
4472         dns_rdataset_init(&rdataset);
4473         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
4474                                      dns_rdatatype_none, 0, &rdataset, NULL);
4475         if (result == ISC_R_NOTFOUND) {
4476                 INSIST(!dns_rdataset_isassociated(&rdataset));
4477                 if (soacount != NULL)
4478                         *soacount = 0;
4479                 if (serial != NULL)
4480                         *serial = 0;
4481                 if (refresh != NULL)
4482                         *refresh = 0;
4483                 if (retry != NULL)
4484                         *retry = 0;
4485                 if (expire != NULL)
4486                         *expire = 0;
4487                 if (minimum != NULL)
4488                         *minimum = 0;
4489                 result = ISC_R_SUCCESS;
4490                 goto invalidate_rdataset;
4491         }
4492         if (result != ISC_R_SUCCESS) {
4493                 INSIST(!dns_rdataset_isassociated(&rdataset));
4494                 goto invalidate_rdataset;
4495         }
4496
4497         count = 0;
4498         result = dns_rdataset_first(&rdataset);
4499         while (result == ISC_R_SUCCESS) {
4500                 dns_rdata_init(&rdata);
4501                 dns_rdataset_current(&rdataset, &rdata);
4502                 count++;
4503                 if (count == 1) {
4504                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
4505                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4506                 }
4507
4508                 result = dns_rdataset_next(&rdataset);
4509                 dns_rdata_reset(&rdata);
4510         }
4511         dns_rdataset_disassociate(&rdataset);
4512
4513         if (soacount != NULL)
4514                 *soacount = count;
4515
4516         if (count > 0) {
4517                 if (serial != NULL)
4518                         *serial = soa.serial;
4519                 if (refresh != NULL)
4520                         *refresh = soa.refresh;
4521                 if (retry != NULL)
4522                         *retry = soa.retry;
4523                 if (expire != NULL)
4524                         *expire = soa.expire;
4525                 if (minimum != NULL)
4526                         *minimum = soa.minimum;
4527         } else {
4528                 if (soacount != NULL)
4529                         *soacount = 0;
4530                 if (serial != NULL)
4531                         *serial = 0;
4532                 if (refresh != NULL)
4533                         *refresh = 0;
4534                 if (retry != NULL)
4535                         *retry = 0;
4536                 if (expire != NULL)
4537                         *expire = 0;
4538                 if (minimum != NULL)
4539                         *minimum = 0;
4540         }
4541
4542         result = ISC_R_SUCCESS;
4543
4544  invalidate_rdataset:
4545         dns_rdataset_invalidate(&rdataset);
4546
4547         return (result);
4548 }
4549
4550 /*
4551  * zone must be locked.
4552  */
4553 static isc_result_t
4554 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
4555                  unsigned int *soacount, isc_uint32_t *serial,
4556                  isc_uint32_t *refresh, isc_uint32_t *retry,
4557                  isc_uint32_t *expire, isc_uint32_t *minimum,
4558                  unsigned int *errors)
4559 {
4560         isc_result_t result;
4561         isc_result_t answer = ISC_R_SUCCESS;
4562         dns_dbversion_t *version = NULL;
4563         dns_dbnode_t *node;
4564
4565         REQUIRE(db != NULL);
4566         REQUIRE(zone != NULL);
4567
4568         dns_db_currentversion(db, &version);
4569
4570         node = NULL;
4571         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
4572         if (result != ISC_R_SUCCESS) {
4573                 answer = result;
4574                 goto closeversion;
4575         }
4576
4577         if (nscount != NULL || errors != NULL) {
4578                 result = zone_count_ns_rr(zone, db, node, version,
4579                                           nscount, errors, ISC_TRUE);
4580                 if (result != ISC_R_SUCCESS)
4581                         answer = result;
4582         }
4583
4584         if (soacount != NULL || serial != NULL || refresh != NULL
4585             || retry != NULL || expire != NULL || minimum != NULL) {
4586                 result = zone_load_soa_rr(db, node, version, soacount,
4587                                           serial, refresh, retry, expire,
4588                                           minimum);
4589                 if (result != ISC_R_SUCCESS)
4590                         answer = result;
4591         }
4592
4593         dns_db_detachnode(db, &node);
4594  closeversion:
4595         dns_db_closeversion(db, &version, ISC_FALSE);
4596
4597         return (answer);
4598 }
4599
4600 void
4601 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
4602         REQUIRE(DNS_ZONE_VALID(source));
4603         REQUIRE(target != NULL && *target == NULL);
4604         isc_refcount_increment(&source->erefs, NULL);
4605         *target = source;
4606 }
4607
4608 void
4609 dns_zone_detach(dns_zone_t **zonep) {
4610         dns_zone_t *zone;
4611         dns_zone_t *raw = NULL;
4612         dns_zone_t *secure = NULL;
4613         unsigned int refs;
4614         isc_boolean_t free_now = ISC_FALSE;
4615
4616         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4617
4618         zone = *zonep;
4619
4620         isc_refcount_decrement(&zone->erefs, &refs);
4621
4622         if (refs == 0) {
4623                 LOCK_ZONE(zone);
4624                 /*
4625                  * We just detached the last external reference.
4626                  */
4627                 if (zone->task != NULL) {
4628                         /*
4629                          * This zone is being managed.  Post
4630                          * its control event and let it clean
4631                          * up synchronously in the context of
4632                          * its task.
4633                          */
4634                         isc_event_t *ev = &zone->ctlevent;
4635                         isc_task_send(zone->task, &ev);
4636                 } else {
4637                         /*
4638                          * This zone is not being managed; it has
4639                          * no task and can have no outstanding
4640                          * events.  Free it immediately.
4641                          */
4642                         /*
4643                          * Unmanaged zones should not have non-null views;
4644                          * we have no way of detaching from the view here
4645                          * without causing deadlock because this code is called
4646                          * with the view already locked.
4647                          */
4648                         INSIST(zone->view == NULL);
4649                         free_now = ISC_TRUE;
4650                         raw = zone->raw;
4651                         zone->raw = NULL;
4652                         secure = zone->secure;
4653                         zone->secure = NULL;
4654                 }
4655                 UNLOCK_ZONE(zone);
4656         }
4657         *zonep = NULL;
4658         if (free_now) {
4659                 if (raw != NULL)
4660                         dns_zone_detach(&raw);
4661                 if (secure != NULL)
4662                         dns_zone_idetach(&secure);
4663                 zone_free(zone);
4664         }
4665 }
4666
4667 void
4668 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4669         REQUIRE(DNS_ZONE_VALID(source));
4670         REQUIRE(target != NULL && *target == NULL);
4671         LOCK_ZONE(source);
4672         zone_iattach(source, target);
4673         UNLOCK_ZONE(source);
4674 }
4675
4676 static void
4677 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4678
4679         /*
4680          * 'source' locked by caller.
4681          */
4682         REQUIRE(LOCKED_ZONE(source));
4683         REQUIRE(DNS_ZONE_VALID(source));
4684         REQUIRE(target != NULL && *target == NULL);
4685         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
4686         source->irefs++;
4687         INSIST(source->irefs != 0);
4688         *target = source;
4689 }
4690
4691 static void
4692 zone_idetach(dns_zone_t **zonep) {
4693         dns_zone_t *zone;
4694
4695         /*
4696          * 'zone' locked by caller.
4697          */
4698         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4699         zone = *zonep;
4700         REQUIRE(LOCKED_ZONE(*zonep));
4701         *zonep = NULL;
4702
4703         INSIST(zone->irefs > 0);
4704         zone->irefs--;
4705         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4706 }
4707
4708 void
4709 dns_zone_idetach(dns_zone_t **zonep) {
4710         dns_zone_t *zone;
4711         isc_boolean_t free_needed;
4712
4713         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4714         zone = *zonep;
4715         *zonep = NULL;
4716
4717         LOCK_ZONE(zone);
4718         INSIST(zone->irefs > 0);
4719         zone->irefs--;
4720         free_needed = exit_check(zone);
4721         UNLOCK_ZONE(zone);
4722         if (free_needed)
4723                 zone_free(zone);
4724 }
4725
4726 isc_mem_t *
4727 dns_zone_getmctx(dns_zone_t *zone) {
4728         REQUIRE(DNS_ZONE_VALID(zone));
4729
4730         return (zone->mctx);
4731 }
4732
4733 dns_zonemgr_t *
4734 dns_zone_getmgr(dns_zone_t *zone) {
4735         REQUIRE(DNS_ZONE_VALID(zone));
4736
4737         return (zone->zmgr);
4738 }
4739
4740 void
4741 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4742         REQUIRE(DNS_ZONE_VALID(zone));
4743
4744         LOCK_ZONE(zone);
4745         if (value)
4746                 DNS_ZONE_SETFLAG(zone, flags);
4747         else
4748                 DNS_ZONE_CLRFLAG(zone, flags);
4749         UNLOCK_ZONE(zone);
4750 }
4751
4752 void
4753 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4754 {
4755         REQUIRE(DNS_ZONE_VALID(zone));
4756
4757         LOCK_ZONE(zone);
4758         if (value)
4759                 zone->options |= option;
4760         else
4761                 zone->options &= ~option;
4762         UNLOCK_ZONE(zone);
4763 }
4764
4765 unsigned int
4766 dns_zone_getoptions(dns_zone_t *zone) {
4767
4768         REQUIRE(DNS_ZONE_VALID(zone));
4769
4770         return (zone->options);
4771 }
4772
4773 void
4774 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4775 {
4776         REQUIRE(DNS_ZONE_VALID(zone));
4777
4778         LOCK_ZONE(zone);
4779         if (value)
4780                 zone->keyopts |= keyopt;
4781         else
4782                 zone->keyopts &= ~keyopt;
4783         UNLOCK_ZONE(zone);
4784 }
4785
4786 unsigned int
4787 dns_zone_getkeyopts(dns_zone_t *zone) {
4788
4789         REQUIRE(DNS_ZONE_VALID(zone));
4790
4791         return (zone->keyopts);
4792 }
4793
4794 isc_result_t
4795 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4796         REQUIRE(DNS_ZONE_VALID(zone));
4797
4798         LOCK_ZONE(zone);
4799         zone->xfrsource4 = *xfrsource;
4800         UNLOCK_ZONE(zone);
4801
4802         return (ISC_R_SUCCESS);
4803 }
4804
4805 isc_sockaddr_t *
4806 dns_zone_getxfrsource4(dns_zone_t *zone) {
4807         REQUIRE(DNS_ZONE_VALID(zone));
4808         return (&zone->xfrsource4);
4809 }
4810
4811 isc_result_t
4812 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4813         REQUIRE(DNS_ZONE_VALID(zone));
4814
4815         LOCK_ZONE(zone);
4816         zone->xfrsource6 = *xfrsource;
4817         UNLOCK_ZONE(zone);
4818
4819         return (ISC_R_SUCCESS);
4820 }
4821
4822 isc_sockaddr_t *
4823 dns_zone_getxfrsource6(dns_zone_t *zone) {
4824         REQUIRE(DNS_ZONE_VALID(zone));
4825         return (&zone->xfrsource6);
4826 }
4827
4828 isc_result_t
4829 dns_zone_setaltxfrsource4(dns_zone_t *zone,
4830                           const isc_sockaddr_t *altxfrsource)
4831 {
4832         REQUIRE(DNS_ZONE_VALID(zone));
4833
4834         LOCK_ZONE(zone);
4835         zone->altxfrsource4 = *altxfrsource;
4836         UNLOCK_ZONE(zone);
4837
4838         return (ISC_R_SUCCESS);
4839 }
4840
4841 isc_sockaddr_t *
4842 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4843         REQUIRE(DNS_ZONE_VALID(zone));
4844         return (&zone->altxfrsource4);
4845 }
4846
4847 isc_result_t
4848 dns_zone_setaltxfrsource6(dns_zone_t *zone,
4849                           const isc_sockaddr_t *altxfrsource)
4850 {
4851         REQUIRE(DNS_ZONE_VALID(zone));
4852
4853         LOCK_ZONE(zone);
4854         zone->altxfrsource6 = *altxfrsource;
4855         UNLOCK_ZONE(zone);
4856
4857         return (ISC_R_SUCCESS);
4858 }
4859
4860 isc_sockaddr_t *
4861 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4862         REQUIRE(DNS_ZONE_VALID(zone));
4863         return (&zone->altxfrsource6);
4864 }
4865
4866 isc_result_t
4867 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4868         REQUIRE(DNS_ZONE_VALID(zone));
4869
4870         LOCK_ZONE(zone);
4871         zone->notifysrc4 = *notifysrc;
4872         UNLOCK_ZONE(zone);
4873
4874         return (ISC_R_SUCCESS);
4875 }
4876
4877 isc_sockaddr_t *
4878 dns_zone_getnotifysrc4(dns_zone_t *zone) {
4879         REQUIRE(DNS_ZONE_VALID(zone));
4880         return (&zone->notifysrc4);
4881 }
4882
4883 isc_result_t
4884 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4885         REQUIRE(DNS_ZONE_VALID(zone));
4886
4887         LOCK_ZONE(zone);
4888         zone->notifysrc6 = *notifysrc;
4889         UNLOCK_ZONE(zone);
4890
4891         return (ISC_R_SUCCESS);
4892 }
4893
4894 isc_sockaddr_t *
4895 dns_zone_getnotifysrc6(dns_zone_t *zone) {
4896         REQUIRE(DNS_ZONE_VALID(zone));
4897         return (&zone->notifysrc6);
4898 }
4899
4900 static isc_boolean_t
4901 same_addrs(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4902              isc_uint32_t count)
4903 {
4904         unsigned int i;
4905
4906         for (i = 0; i < count; i++)
4907                 if (!isc_sockaddr_equal(&old[i], &new[i]))
4908                         return (ISC_FALSE);
4909         return (ISC_TRUE);
4910 }
4911
4912 static isc_boolean_t
4913 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
4914         unsigned int i;
4915
4916         if (old == NULL && new == NULL)
4917                 return (ISC_TRUE);
4918         if (old == NULL || new == NULL)
4919                 return (ISC_FALSE);
4920
4921         for (i = 0; i < count; i++) {
4922                 if (old[i] == NULL && new[i] == NULL)
4923                         continue;
4924                 if (old[i] == NULL || new[i] == NULL ||
4925                      !dns_name_equal(old[i], new[i]))
4926                         return (ISC_FALSE);
4927         }
4928         return (ISC_TRUE);
4929 }
4930
4931 static void
4932 clear_addresskeylist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
4933                      unsigned int *countp, isc_mem_t *mctx)
4934 {
4935         unsigned int count;
4936         isc_sockaddr_t *addrs;
4937         dns_name_t **keynames;
4938
4939         REQUIRE(countp != NULL && addrsp != NULL && keynamesp != NULL);
4940
4941         count = *countp;
4942         *countp = 0;
4943         addrs = *addrsp;
4944         *addrsp = NULL;
4945         keynames = *keynamesp;
4946         *keynamesp = NULL;
4947
4948         if (addrs != NULL)
4949                 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
4950
4951         if (keynames != NULL) {
4952                 unsigned int i;
4953                 for (i = 0; i < count; i++) {
4954                         if (keynames[i] != NULL) {
4955                                 dns_name_free(keynames[i], mctx);
4956                                 isc_mem_put(mctx, keynames[i],
4957                                             sizeof(dns_name_t));
4958                                 keynames[i] = NULL;
4959                         }
4960                 }
4961                 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
4962         }
4963 }
4964
4965 static isc_result_t
4966 set_addrkeylist(unsigned int count,
4967                 const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
4968                 dns_name_t **names, dns_name_t ***newnamesp,
4969                 isc_mem_t *mctx)
4970 {
4971         isc_result_t result;
4972         isc_sockaddr_t *newaddrs = NULL;
4973         dns_name_t **newnames = NULL;
4974         unsigned int i;
4975
4976         REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
4977         REQUIRE(newnamesp != NULL && *newnamesp == NULL);
4978
4979         newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
4980         if (newaddrs == NULL)
4981                 return (ISC_R_NOMEMORY);
4982         memmove(newaddrs, addrs, count * sizeof(*newaddrs));
4983
4984         newnames = NULL;
4985         if (names != NULL) {
4986                 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
4987                 if (newnames == NULL) {
4988                         isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
4989                         return (ISC_R_NOMEMORY);
4990                 }
4991                 for (i = 0; i < count; i++)
4992                         newnames[i] = NULL;
4993                 for (i = 0; i < count; i++) {
4994                         if (names[i] != NULL) {
4995                                 newnames[i] = isc_mem_get(mctx,
4996                                                          sizeof(dns_name_t));
4997                                 if (newnames[i] == NULL)
4998                                         goto allocfail;
4999                                 dns_name_init(newnames[i], NULL);
5000                                 result = dns_name_dup(names[i], mctx,
5001                                                       newnames[i]);
5002                                 if (result != ISC_R_SUCCESS) {
5003                                 allocfail:
5004                                         for (i = 0; i < count; i++)
5005                                                 if (newnames[i] != NULL)
5006                                                         dns_name_free(
5007                                                                newnames[i],
5008                                                                mctx);
5009                                         isc_mem_put(mctx, newaddrs,
5010                                                     count * sizeof(*newaddrs));
5011                                         isc_mem_put(mctx, newnames,
5012                                                     count * sizeof(*newnames));
5013                                         return (ISC_R_NOMEMORY);
5014                                 }
5015                         }
5016                 }
5017         }
5018
5019         *newaddrsp = newaddrs;
5020         *newnamesp = newnames;
5021         return (ISC_R_SUCCESS);
5022 }
5023
5024 isc_result_t
5025 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
5026                        isc_uint32_t count)
5027 {
5028         return (dns_zone_setalsonotifywithkeys(zone, notify, NULL, count));
5029 }
5030
5031 isc_result_t
5032 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5033                                dns_name_t **keynames, isc_uint32_t count)
5034 {
5035         isc_result_t result;
5036         isc_sockaddr_t *newaddrs = NULL;
5037         dns_name_t **newnames = NULL;
5038
5039         REQUIRE(DNS_ZONE_VALID(zone));
5040         REQUIRE(count == 0 || notify != NULL);
5041         if (keynames != NULL)
5042                 REQUIRE(count != 0);
5043
5044         LOCK_ZONE(zone);
5045
5046         if (count == zone->notifycnt &&
5047             same_addrs(zone->notify, notify, count) &&
5048             same_keynames(zone->notifykeynames, keynames, count))
5049                 goto unlock;
5050
5051         clear_addresskeylist(&zone->notify, &zone->notifykeynames,
5052                              &zone->notifycnt, zone->mctx);
5053
5054         if (count == 0)
5055                 goto unlock;
5056
5057         /*
5058          * Set up the notify and notifykey lists
5059          */
5060         result = set_addrkeylist(count, notify, &newaddrs,
5061                                  keynames, &newnames, zone->mctx);
5062         if (result != ISC_R_SUCCESS)
5063                 goto unlock;
5064
5065         /*
5066          * Everything is ok so attach to the zone.
5067          */
5068         zone->notify = newaddrs;
5069         zone->notifykeynames = newnames;
5070         zone->notifycnt = count;
5071  unlock:
5072         UNLOCK_ZONE(zone);
5073         return (ISC_R_SUCCESS);
5074 }
5075
5076 isc_result_t
5077 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
5078                     isc_uint32_t count)
5079 {
5080         isc_result_t result;
5081
5082         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
5083         return (result);
5084 }
5085
5086 isc_result_t
5087 dns_zone_setmasterswithkeys(dns_zone_t *zone,
5088                             const isc_sockaddr_t *masters,
5089                             dns_name_t **keynames,
5090                             isc_uint32_t count)
5091 {
5092         isc_result_t result = ISC_R_SUCCESS;
5093         isc_sockaddr_t *newaddrs = NULL;
5094         dns_name_t **newnames = NULL;
5095         isc_boolean_t *newok;
5096         unsigned int i;
5097
5098         REQUIRE(DNS_ZONE_VALID(zone));
5099         REQUIRE(count == 0 || masters != NULL);
5100         if (keynames != NULL) {
5101                 REQUIRE(count != 0);
5102         }
5103
5104         LOCK_ZONE(zone);
5105         /*
5106          * The refresh code assumes that 'masters' wouldn't change under it.
5107          * If it will change then kill off any current refresh in progress
5108          * and update the masters info.  If it won't change then we can just
5109          * unlock and exit.
5110          */
5111         if (count != zone->masterscnt ||
5112             !same_addrs(zone->masters, masters, count) ||
5113             !same_keynames(zone->masterkeynames, keynames, count)) {
5114                 if (zone->request != NULL)
5115                         dns_request_cancel(zone->request);
5116         } else
5117                 goto unlock;
5118
5119         /*
5120          * This needs to happen before clear_addresskeylist() sets
5121          * zone->masterscnt to 0:
5122          */
5123         if (zone->mastersok != NULL) {
5124                 isc_mem_put(zone->mctx, zone->mastersok,
5125                             zone->masterscnt * sizeof(isc_boolean_t));
5126                 zone->mastersok = NULL;
5127         }
5128         clear_addresskeylist(&zone->masters, &zone->masterkeynames,
5129                              &zone->masterscnt, zone->mctx);
5130         /*
5131          * If count == 0, don't allocate any space for masters, mastersok or
5132          * keynames so internally, those pointers are NULL if count == 0
5133          */
5134         if (count == 0)
5135                 goto unlock;
5136
5137         /*
5138          * mastersok must contain count elements
5139          */
5140         newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
5141         if (newok == NULL) {
5142                 result = ISC_R_NOMEMORY;
5143                 isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
5144                 goto unlock;
5145         };
5146         for (i = 0; i < count; i++)
5147                 newok[i] = ISC_FALSE;
5148
5149         /*
5150          * Now set up the masters and masterkey lists
5151          */
5152         result = set_addrkeylist(count, masters, &newaddrs,
5153                                  keynames, &newnames, zone->mctx);
5154         if (result != ISC_R_SUCCESS) {
5155                 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
5156                 goto unlock;
5157         }
5158
5159         /*
5160          * Everything is ok so attach to the zone.
5161          */
5162         zone->curmaster = 0;
5163         zone->mastersok = newok;
5164         zone->masters = newaddrs;
5165         zone->masterkeynames = newnames;
5166         zone->masterscnt = count;
5167         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
5168
5169  unlock:
5170         UNLOCK_ZONE(zone);
5171         return (result);
5172 }
5173
5174 isc_result_t
5175 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
5176         isc_result_t result = ISC_R_SUCCESS;
5177
5178         REQUIRE(DNS_ZONE_VALID(zone));
5179
5180         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5181         if (zone->db == NULL)
5182                 result = DNS_R_NOTLOADED;
5183         else
5184                 dns_db_attach(zone->db, dpb);
5185         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5186
5187         return (result);
5188 }
5189
5190 void
5191 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
5192         REQUIRE(DNS_ZONE_VALID(zone));
5193         REQUIRE(zone->type == dns_zone_staticstub);
5194
5195         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5196         REQUIRE(zone->db == NULL);
5197         dns_db_attach(db, &zone->db);
5198         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5199 }
5200
5201 /*
5202  * Co-ordinates the starting of routine jobs.
5203  */
5204
5205 void
5206 dns_zone_maintenance(dns_zone_t *zone) {
5207         const char me[] = "dns_zone_maintenance";
5208         isc_time_t now;
5209
5210         REQUIRE(DNS_ZONE_VALID(zone));
5211         ENTER;
5212
5213         LOCK_ZONE(zone);
5214         TIME_NOW(&now);
5215         zone_settimer(zone, &now);
5216         UNLOCK_ZONE(zone);
5217 }
5218
5219 static inline isc_boolean_t
5220 was_dumping(dns_zone_t *zone) {
5221         isc_boolean_t dumping;
5222
5223         REQUIRE(LOCKED_ZONE(zone));
5224
5225         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
5226         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
5227         if (!dumping) {
5228                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
5229                 isc_time_settoepoch(&zone->dumptime);
5230         }
5231         return (dumping);
5232 }
5233
5234 static isc_result_t
5235 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
5236                isc_mem_t *mctx, unsigned int maxkeys,
5237                dst_key_t **keys, unsigned int *nkeys)
5238 {
5239         isc_result_t result;
5240         dns_dbnode_t *node = NULL;
5241         const char *directory = dns_zone_getkeydirectory(zone);
5242
5243         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
5244         memset(keys, 0, sizeof(*keys) * maxkeys);
5245         result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
5246                                           directory, mctx, maxkeys, keys,
5247                                           nkeys);
5248         if (result == ISC_R_NOTFOUND)
5249                 result = ISC_R_SUCCESS;
5250  failure:
5251         if (node != NULL)
5252                 dns_db_detachnode(db, &node);
5253         return (result);
5254 }
5255
5256 static isc_result_t
5257 offline(dns_db_t *db, dns_dbversion_t *ver, zonediff_t *zonediff,
5258         dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
5259 {
5260         isc_result_t result;
5261
5262         if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
5263                 return (ISC_R_SUCCESS);
5264         result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
5265                                name, ttl, rdata);
5266         if (result != ISC_R_SUCCESS)
5267                 return (result);
5268         rdata->flags |= DNS_RDATA_OFFLINE;
5269         result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
5270                                name, ttl, rdata);
5271         zonediff->offline = ISC_TRUE;
5272         return (result);
5273 }
5274
5275 static void
5276 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
5277 {
5278         unsigned int delta;
5279         char timebuf[80];
5280
5281         zone->key_expiry = when;
5282         if (when <= now) {
5283                 dns_zone_log(zone, ISC_LOG_ERROR,
5284                              "DNSKEY RRSIG(s) have expired");
5285                 isc_time_settoepoch(&zone->keywarntime);
5286         } else if (when < now + 7 * 24 * 3600) {
5287                 isc_time_t t;
5288                 isc_time_set(&t, when, 0);
5289                 isc_time_formattimestamp(&t, timebuf, 80);
5290                 dns_zone_log(zone, ISC_LOG_WARNING,
5291                              "DNSKEY RRSIG(s) will expire within 7 days: %s",
5292                              timebuf);
5293                 delta = when - now;
5294                 delta--;                /* loop prevention */
5295                 delta /= 24 * 3600;     /* to whole days */
5296                 delta *= 24 * 3600;     /* to seconds */
5297                 isc_time_set(&zone->keywarntime, when - delta, 0);
5298         }  else {
5299                 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
5300                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
5301                 dns_zone_log(zone, ISC_LOG_NOTICE,
5302                              "setting keywarntime to %s", timebuf);
5303         }
5304 }
5305
5306 /*
5307  * Helper function to del_sigs(). We don't want to delete RRSIGs that
5308  * have no new key.
5309  */
5310 static isc_boolean_t
5311 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
5312           isc_boolean_t *warn)
5313 {
5314         unsigned int i = 0;
5315         isc_boolean_t have_ksk = ISC_FALSE, have_zsk = ISC_FALSE;
5316         isc_boolean_t have_pksk = ISC_FALSE, have_pzsk = ISC_FALSE;
5317
5318         for (i = 0; i < nkeys; i++) {
5319                 if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
5320                         continue;
5321                 if (dst_key_isprivate(keys[i])) {
5322                         if (KSK(keys[i]))
5323                                 have_ksk = have_pksk = ISC_TRUE;
5324                         else
5325                                 have_zsk = have_pzsk = ISC_TRUE;
5326                 } else {
5327                         if (KSK(keys[i]))
5328                                 have_ksk = ISC_TRUE;
5329                         else
5330                                 have_zsk = ISC_TRUE;
5331                 }
5332         }
5333
5334         if (have_zsk && have_ksk && !have_pzsk)
5335                 *warn = ISC_TRUE;
5336
5337         /*
5338          * It's okay to delete a signature if there is an active key
5339          * with the same algorithm to replace it.
5340          */
5341         if (have_pksk || have_pzsk)
5342                 return (ISC_TRUE);
5343
5344         /*
5345          * Failing that, it is *not* okay to delete a signature
5346          * if the associated public key is still in the DNSKEY RRset
5347          */
5348         for (i = 0; i < nkeys; i++) {
5349                 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
5350                     (rrsig_ptr->keyid == dst_key_id(keys[i])))
5351                         return (ISC_FALSE);
5352         }
5353
5354         /*
5355          * But if the key is gone, then go ahead.
5356          */
5357         return (ISC_TRUE);
5358 }
5359
5360 /*
5361  * Delete expired RRsigs and any RRsigs we are about to re-sign.
5362  * See also update.c:del_keysigs().
5363  */
5364 static isc_result_t
5365 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5366          dns_rdatatype_t type, zonediff_t *zonediff, dst_key_t **keys,
5367          unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
5368 {
5369         isc_result_t result;
5370         dns_dbnode_t *node = NULL;
5371         dns_rdataset_t rdataset;
5372         unsigned int i;
5373         dns_rdata_rrsig_t rrsig;
5374         isc_boolean_t found, changed;
5375         isc_int64_t warn = 0, maybe = 0;
5376
5377         dns_rdataset_init(&rdataset);
5378
5379         if (type == dns_rdatatype_nsec3)
5380                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5381         else
5382                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
5383         if (result == ISC_R_NOTFOUND)
5384                 return (ISC_R_SUCCESS);
5385         if (result != ISC_R_SUCCESS)
5386                 goto failure;
5387         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
5388                                      (isc_stdtime_t) 0, &rdataset, NULL);
5389         dns_db_detachnode(db, &node);
5390
5391         if (result == ISC_R_NOTFOUND) {
5392                 INSIST(!dns_rdataset_isassociated(&rdataset));
5393                 return (ISC_R_SUCCESS);
5394         }
5395         if (result != ISC_R_SUCCESS) {
5396                 INSIST(!dns_rdataset_isassociated(&rdataset));
5397                 goto failure;
5398         }
5399
5400         changed = ISC_FALSE;
5401         for (result = dns_rdataset_first(&rdataset);
5402              result == ISC_R_SUCCESS;
5403              result = dns_rdataset_next(&rdataset)) {
5404                 dns_rdata_t rdata = DNS_RDATA_INIT;
5405
5406                 dns_rdataset_current(&rdataset, &rdata);
5407                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5408                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5409
5410                 if (type != dns_rdatatype_dnskey) {
5411                         isc_boolean_t warn = ISC_FALSE, deleted = ISC_FALSE;
5412                         if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
5413                                 result = update_one_rr(db, ver, zonediff->diff,
5414                                                DNS_DIFFOP_DELRESIGN, name,
5415                                                rdataset.ttl, &rdata);
5416                                 if (incremental)
5417                                         changed = ISC_TRUE;
5418                                 if (result != ISC_R_SUCCESS)
5419                                         break;
5420                                 deleted = ISC_TRUE;
5421                         }
5422                         if (warn) {
5423                                 /*
5424                                  * At this point, we've got an RRSIG,
5425                                  * which is signed by an inactive key.
5426                                  * An administrator needs to provide a new
5427                                  * key/alg, but until that time, we want to
5428                                  * keep the old RRSIG.  Marking the key as
5429                                  * offline will prevent us spinning waiting
5430                                  * for the private part.
5431                                  */
5432                                 if (incremental && !deleted) {
5433                                         result = offline(db, ver, zonediff,
5434                                                          name, rdataset.ttl,
5435                                                          &rdata);
5436                                         changed = ISC_TRUE;
5437                                         if (result != ISC_R_SUCCESS)
5438                                                 break;
5439                                 }
5440
5441                                 /*
5442                                  * Log the key id and algorithm of
5443                                  * the inactive key with no replacement
5444                                  */
5445                                 if (zone->log_key_expired_timer <= now) {
5446                                         char origin[DNS_NAME_FORMATSIZE];
5447                                         char algbuf[DNS_NAME_FORMATSIZE];
5448                                         dns_name_format(&zone->origin, origin,
5449                                                         sizeof(origin));
5450                                         dns_secalg_format(rrsig.algorithm,
5451                                                           algbuf,
5452                                                           sizeof(algbuf));
5453                                         dns_zone_log(zone, ISC_LOG_WARNING,
5454                                                      "Key %s/%s/%d "
5455                                                      "missing or inactive "
5456                                                      "and has no replacement: "
5457                                                      "retaining signatures.",
5458                                                      origin, algbuf,
5459                                                      rrsig.keyid);
5460                                         zone->log_key_expired_timer = now +
5461                                                                         3600;
5462                                 }
5463                         }
5464                         continue;
5465                 }
5466
5467                 /*
5468                  * RRSIG(DNSKEY) requires special processing.
5469                  */
5470                 found = ISC_FALSE;
5471                 for (i = 0; i < nkeys; i++) {
5472                         if (rrsig.algorithm == dst_key_alg(keys[i]) &&
5473                             rrsig.keyid == dst_key_id(keys[i])) {
5474                                 found = ISC_TRUE;
5475                                 /*
5476                                  * Mark offline RRSIG(DNSKEY).
5477                                  * We want the earliest offline expire time
5478                                  * iff there is a new offline signature.
5479                                  */
5480                                 if (!dst_key_inactive(keys[i]) &&
5481                                     !dst_key_isprivate(keys[i]))
5482                                 {
5483                                         isc_int64_t timeexpire =
5484                                            dns_time64_from32(rrsig.timeexpire);
5485                                         if (warn != 0 && warn > timeexpire)
5486                                                 warn = timeexpire;
5487                                         if (rdata.flags & DNS_RDATA_OFFLINE) {
5488                                                 if (maybe == 0 ||
5489                                                     maybe > timeexpire)
5490                                                         maybe = timeexpire;
5491                                                 break;
5492                                         }
5493                                         if (warn == 0)
5494                                                 warn = maybe;
5495                                         if (warn == 0 || warn > timeexpire)
5496                                                 warn = timeexpire;
5497                                         result = offline(db, ver, zonediff,
5498                                                          name, rdataset.ttl,
5499                                                          &rdata);
5500                                         changed = ISC_TRUE;
5501                                         break;
5502                                 }
5503                                 result = update_one_rr(db, ver, zonediff->diff,
5504                                                        DNS_DIFFOP_DELRESIGN,
5505                                                        name, rdataset.ttl,
5506                                                        &rdata);
5507                                 break;
5508                         }
5509                 }
5510
5511                 /*
5512                  * If there is not a matching DNSKEY then
5513                  * delete the RRSIG.
5514                  */
5515                 if (!found)
5516                         result = update_one_rr(db, ver, zonediff->diff,
5517                                                DNS_DIFFOP_DELRESIGN, name,
5518                                                rdataset.ttl, &rdata);
5519                 if (result != ISC_R_SUCCESS)
5520                         break;
5521         }
5522
5523         if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0)
5524                 dns_db_resigned(db, &rdataset, ver);
5525
5526         dns_rdataset_disassociate(&rdataset);
5527         if (result == ISC_R_NOMORE)
5528                 result = ISC_R_SUCCESS;
5529         if (warn > 0) {
5530 #if defined(STDTIME_ON_32BITS)
5531                 isc_stdtime_t stdwarn = (isc_stdtime_t)warn;
5532                 if (warn == stdwarn)
5533 #endif
5534                         set_key_expiry_warning(zone, (isc_stdtime_t)warn, now);
5535 #if defined(STDTIME_ON_32BITS)
5536                 else
5537                         dns_zone_log(zone, ISC_LOG_ERROR,
5538                                      "key expiry warning time out of range");
5539 #endif
5540         }
5541  failure:
5542         if (node != NULL)
5543                 dns_db_detachnode(db, &node);
5544         return (result);
5545 }
5546
5547 static isc_result_t
5548 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5549          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
5550          unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
5551          isc_stdtime_t expire, isc_boolean_t check_ksk,
5552          isc_boolean_t keyset_kskonly)
5553 {
5554         isc_result_t result;
5555         dns_dbnode_t *node = NULL;
5556         dns_rdataset_t rdataset;
5557         dns_rdata_t sig_rdata = DNS_RDATA_INIT;
5558         unsigned char data[1024]; /* XXX */
5559         isc_buffer_t buffer;
5560         unsigned int i, j;
5561
5562         dns_rdataset_init(&rdataset);
5563         isc_buffer_init(&buffer, data, sizeof(data));
5564
5565         if (type == dns_rdatatype_nsec3)
5566                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5567         else
5568                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
5569         if (result == ISC_R_NOTFOUND)
5570                 return (ISC_R_SUCCESS);
5571         if (result != ISC_R_SUCCESS)
5572                 goto failure;
5573         result = dns_db_findrdataset(db, node, ver, type, 0,
5574                                      (isc_stdtime_t) 0, &rdataset, NULL);
5575         dns_db_detachnode(db, &node);
5576         if (result == ISC_R_NOTFOUND) {
5577                 INSIST(!dns_rdataset_isassociated(&rdataset));
5578                 return (ISC_R_SUCCESS);
5579         }
5580         if (result != ISC_R_SUCCESS) {
5581                 INSIST(!dns_rdataset_isassociated(&rdataset));
5582                 goto failure;
5583         }
5584
5585         for (i = 0; i < nkeys; i++) {
5586                 isc_boolean_t both = ISC_FALSE;
5587
5588                 if (!dst_key_isprivate(keys[i]))
5589                         continue;
5590
5591                 if (check_ksk && !REVOKE(keys[i])) {
5592                         isc_boolean_t have_ksk, have_nonksk;
5593                         if (KSK(keys[i])) {
5594                                 have_ksk = ISC_TRUE;
5595                                 have_nonksk = ISC_FALSE;
5596                         } else {
5597                                 have_ksk = ISC_FALSE;
5598                                 have_nonksk = ISC_TRUE;
5599                         }
5600                         for (j = 0; j < nkeys; j++) {
5601                                 if (j == i || ALG(keys[i]) != ALG(keys[j]))
5602                                         continue;
5603                                 if (REVOKE(keys[j]))
5604                                         continue;
5605                                 if (KSK(keys[j]))
5606                                         have_ksk = ISC_TRUE;
5607                                 else
5608                                         have_nonksk = ISC_TRUE;
5609                                 both = have_ksk && have_nonksk;
5610                                 if (both)
5611                                         break;
5612                         }
5613                 }
5614                 if (both) {
5615                         if (type == dns_rdatatype_dnskey) {
5616                                 if (!KSK(keys[i]) && keyset_kskonly)
5617                                         continue;
5618                         } else if (KSK(keys[i]))
5619                                 continue;
5620                 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
5621                                 continue;
5622
5623                 /* Calculate the signature, creating a RRSIG RDATA. */
5624                 isc_buffer_clear(&buffer);
5625                 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
5626                                       &inception, &expire,
5627                                       mctx, &buffer, &sig_rdata));
5628                 /* Update the database and journal with the RRSIG. */
5629                 /* XXX inefficient - will cause dataset merging */
5630                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
5631                                     name, rdataset.ttl, &sig_rdata));
5632                 dns_rdata_reset(&sig_rdata);
5633                 isc_buffer_init(&buffer, data, sizeof(data));
5634         }
5635
5636  failure:
5637         if (dns_rdataset_isassociated(&rdataset))
5638                 dns_rdataset_disassociate(&rdataset);
5639         if (node != NULL)
5640                 dns_db_detachnode(db, &node);
5641         return (result);
5642 }
5643
5644 static void
5645 zone_resigninc(dns_zone_t *zone) {
5646         const char *me = "zone_resigninc";
5647         dns_db_t *db = NULL;
5648         dns_dbversion_t *version = NULL;
5649         dns_diff_t _sig_diff;
5650         zonediff_t zonediff;
5651         dns_fixedname_t fixed;
5652         dns_name_t *name;
5653         dns_rdataset_t rdataset;
5654         dns_rdatatype_t covers;
5655         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
5656         isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
5657         isc_result_t result;
5658         isc_stdtime_t now, inception, soaexpire, expire, stop;
5659         isc_uint32_t jitter;
5660         unsigned int i;
5661         unsigned int nkeys = 0;
5662         unsigned int resign;
5663
5664         ENTER;
5665
5666         dns_rdataset_init(&rdataset);
5667         dns_fixedname_init(&fixed);
5668         dns_diff_init(zone->mctx, &_sig_diff);
5669         zonediff_init(&zonediff, &_sig_diff);
5670
5671         /*
5672          * Zone is frozen or automatic resigning is disabled.
5673          * Pause for 5 minutes.
5674          */
5675         if (zone->update_disabled ||
5676             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
5677         {
5678                 result = ISC_R_FAILURE;
5679                 goto failure;
5680         }
5681
5682         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5683         dns_db_attach(zone->db, &db);
5684         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5685
5686         result = dns_db_newversion(db, &version);
5687         if (result != ISC_R_SUCCESS) {
5688                 dns_zone_log(zone, ISC_LOG_ERROR,
5689                              "zone_resigninc:dns_db_newversion -> %s",
5690                              dns_result_totext(result));
5691                 goto failure;
5692         }
5693
5694         result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
5695                                 zone_keys, &nkeys);
5696         if (result != ISC_R_SUCCESS) {
5697                 dns_zone_log(zone, ISC_LOG_ERROR,
5698                              "zone_resigninc:find_zone_keys -> %s",
5699                              dns_result_totext(result));
5700                 goto failure;
5701         }
5702
5703         isc_stdtime_get(&now);
5704         inception = now - 3600; /* Allow for clock skew. */
5705         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5706         /*
5707          * Spread out signatures over time if they happen to be
5708          * clumped.  We don't do this for each add_sigs() call as
5709          * we still want some clustering to occur.
5710          */
5711         isc_random_get(&jitter);
5712         expire = soaexpire - jitter % 3600;
5713         stop = now + 5;
5714
5715         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5716         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5717
5718         name = dns_fixedname_name(&fixed);
5719         result = dns_db_getsigningtime(db, &rdataset, name);
5720         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
5721                 dns_zone_log(zone, ISC_LOG_ERROR,
5722                              "zone_resigninc:dns_db_getsigningtime -> %s",
5723                              dns_result_totext(result));
5724         }
5725
5726         i = 0;
5727         while (result == ISC_R_SUCCESS) {
5728                 resign = rdataset.resign - zone->sigresigninginterval;
5729                 covers = rdataset.covers;
5730                 dns_rdataset_disassociate(&rdataset);
5731
5732                 /*
5733                  * Stop if we hit the SOA as that means we have walked the
5734                  * entire zone.  The SOA record should always be the most
5735                  * recent signature.
5736                  */
5737                 /* XXXMPA increase number of RRsets signed pre call */
5738                 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
5739                     resign > stop)
5740                         break;
5741
5742                 result = del_sigs(zone, db, version, name, covers, &zonediff,
5743                                   zone_keys, nkeys, now, ISC_TRUE);
5744                 if (result != ISC_R_SUCCESS) {
5745                         dns_zone_log(zone, ISC_LOG_ERROR,
5746                                      "zone_resigninc:del_sigs -> %s",
5747                                      dns_result_totext(result));
5748                         break;
5749                 }
5750
5751                 result = add_sigs(db, version, name, covers, zonediff.diff,
5752                                   zone_keys, nkeys, zone->mctx, inception,
5753                                   expire, check_ksk, keyset_kskonly);
5754                 if (result != ISC_R_SUCCESS) {
5755                         dns_zone_log(zone, ISC_LOG_ERROR,
5756                                      "zone_resigninc:add_sigs -> %s",
5757                                      dns_result_totext(result));
5758                         break;
5759                 }
5760                 result  = dns_db_getsigningtime(db, &rdataset,
5761                                                 dns_fixedname_name(&fixed));
5762                 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
5763                         result = ISC_R_SUCCESS;
5764                         break;
5765                 }
5766                 if (result != ISC_R_SUCCESS)
5767                         dns_zone_log(zone, ISC_LOG_ERROR,
5768                              "zone_resigninc:dns_db_getsigningtime -> %s",
5769                                      dns_result_totext(result));
5770         }
5771
5772         if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
5773                 goto failure;
5774
5775         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5776                           &zonediff, zone_keys, nkeys, now, ISC_TRUE);
5777         if (result != ISC_R_SUCCESS) {
5778                 dns_zone_log(zone, ISC_LOG_ERROR,
5779                              "zone_resigninc:del_sigs -> %s",
5780                              dns_result_totext(result));
5781                 goto failure;
5782         }
5783
5784         /*
5785          * Did we change anything in the zone?
5786          */
5787         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
5788                 /*
5789                  * Commit the changes if any key has been marked as offline.                     */
5790                 if (zonediff.offline)
5791                         dns_db_closeversion(db, &version, ISC_TRUE);
5792                 goto failure;
5793         }
5794
5795         /* Increment SOA serial if we have made changes */
5796         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
5797                                    zone->updatemethod);
5798         if (result != ISC_R_SUCCESS) {
5799                 dns_zone_log(zone, ISC_LOG_ERROR,
5800                              "zone_resigninc:update_soa_serial -> %s",
5801                              dns_result_totext(result));
5802                 goto failure;
5803         }
5804
5805         /*
5806          * Generate maximum life time signatures so that the above loop
5807          * termination is sensible.
5808          */
5809         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5810                           zonediff.diff, zone_keys, nkeys, zone->mctx,
5811                           inception, soaexpire, check_ksk, keyset_kskonly);
5812         if (result != ISC_R_SUCCESS) {
5813                 dns_zone_log(zone, ISC_LOG_ERROR,
5814                              "zone_resigninc:add_sigs -> %s",
5815                              dns_result_totext(result));
5816                 goto failure;
5817         }
5818
5819         /* Write changes to journal file. */
5820         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
5821
5822         /* Everything has succeeded. Commit the changes. */
5823         dns_db_closeversion(db, &version, ISC_TRUE);
5824
5825  failure:
5826         dns_diff_clear(&_sig_diff);
5827         for (i = 0; i < nkeys; i++)
5828                 dst_key_free(&zone_keys[i]);
5829         if (version != NULL) {
5830                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
5831                 dns_db_detach(&db);
5832         } else if (db != NULL)
5833                 dns_db_detach(&db);
5834         if (result == ISC_R_SUCCESS) {
5835                 set_resigntime(zone);
5836                 LOCK_ZONE(zone);
5837                 zone_needdump(zone, DNS_DUMP_DELAY);
5838                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5839                 UNLOCK_ZONE(zone);
5840         } else {
5841                 /*
5842                  * Something failed.  Retry in 5 minutes.
5843                  */
5844                 isc_interval_t ival;
5845                 isc_interval_set(&ival, 300, 0);
5846                 isc_time_nowplusinterval(&zone->resigntime, &ival);
5847         }
5848 }
5849
5850 static isc_result_t
5851 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
5852             dns_name_t *newname, isc_boolean_t bottom)
5853 {
5854         isc_result_t result;
5855         dns_dbiterator_t *dbit = NULL;
5856         dns_rdatasetiter_t *rdsit = NULL;
5857         dns_dbnode_t *node = NULL;
5858
5859         CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
5860         CHECK(dns_dbiterator_seek(dbit, oldname));
5861         do {
5862                 result = dns_dbiterator_next(dbit);
5863                 if (result == ISC_R_NOMORE)
5864                         CHECK(dns_dbiterator_first(dbit));
5865                 CHECK(dns_dbiterator_current(dbit, &node, newname));
5866                 if (bottom && dns_name_issubdomain(newname, oldname) &&
5867                     !dns_name_equal(newname, oldname)) {
5868                         dns_db_detachnode(db, &node);
5869                         continue;
5870                 }
5871                 /*
5872                  * Is this node empty?
5873                  */
5874                 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
5875                 result = dns_rdatasetiter_first(rdsit);
5876                 dns_db_detachnode(db, &node);
5877                 dns_rdatasetiter_destroy(&rdsit);
5878                 if (result != ISC_R_NOMORE)
5879                         break;
5880         } while (1);
5881  failure:
5882         if (node != NULL)
5883                 dns_db_detachnode(db, &node);
5884         if (dbit != NULL)
5885                 dns_dbiterator_destroy(&dbit);
5886         return (result);
5887 }
5888
5889 static isc_boolean_t
5890 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5891                 dns_rdatatype_t type, dst_key_t *key)
5892 {
5893         isc_result_t result;
5894         dns_rdataset_t rdataset;
5895         dns_rdata_t rdata = DNS_RDATA_INIT;
5896         dns_rdata_rrsig_t rrsig;
5897
5898         dns_rdataset_init(&rdataset);
5899         result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
5900                                      type, 0, &rdataset, NULL);
5901         if (result != ISC_R_SUCCESS) {
5902                 INSIST(!dns_rdataset_isassociated(&rdataset));
5903                 return (ISC_FALSE);
5904         }
5905         for (result = dns_rdataset_first(&rdataset);
5906              result == ISC_R_SUCCESS;
5907              result = dns_rdataset_next(&rdataset)) {
5908                 dns_rdataset_current(&rdataset, &rdata);
5909                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5910                 INSIST(result == ISC_R_SUCCESS);
5911                 if (rrsig.algorithm == dst_key_alg(key) &&
5912                     rrsig.keyid == dst_key_id(key)) {
5913                         dns_rdataset_disassociate(&rdataset);
5914                         return (ISC_TRUE);
5915                 }
5916                 dns_rdata_reset(&rdata);
5917         }
5918         dns_rdataset_disassociate(&rdataset);
5919         return (ISC_FALSE);
5920 }
5921
5922 static isc_result_t
5923 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5924          dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
5925          dns_diff_t *diff)
5926 {
5927         dns_fixedname_t fixed;
5928         dns_name_t *next;
5929         dns_rdata_t rdata = DNS_RDATA_INIT;
5930         isc_result_t result;
5931         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
5932
5933         dns_fixedname_init(&fixed);
5934         next = dns_fixedname_name(&fixed);
5935
5936         CHECK(next_active(db, version, name, next, bottom));
5937         CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
5938                                   &rdata));
5939         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
5940                             &rdata));
5941  failure:
5942         return (result);
5943 }
5944
5945 static isc_result_t
5946 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
5947             dns_dbversion_t *version, isc_boolean_t build_nsec3,
5948             isc_boolean_t build_nsec, dst_key_t *key,
5949             isc_stdtime_t inception, isc_stdtime_t expire,
5950             unsigned int minimum, isc_boolean_t is_ksk,
5951             isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
5952             dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
5953 {
5954         isc_result_t result;
5955         dns_rdatasetiter_t *iterator = NULL;
5956         dns_rdataset_t rdataset;
5957         dns_rdata_t rdata = DNS_RDATA_INIT;
5958         isc_buffer_t buffer;
5959         unsigned char data[1024];
5960         isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
5961                       seen_nsec3, seen_ds;
5962         isc_boolean_t bottom;
5963
5964         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5965         if (result != ISC_R_SUCCESS) {
5966                 if (result == ISC_R_NOTFOUND)
5967                         result = ISC_R_SUCCESS;
5968                 return (result);
5969         }
5970
5971         dns_rdataset_init(&rdataset);
5972         isc_buffer_init(&buffer, data, sizeof(data));
5973         seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
5974         seen_nsec3 = seen_ds = ISC_FALSE;
5975         for (result = dns_rdatasetiter_first(iterator);
5976              result == ISC_R_SUCCESS;
5977              result = dns_rdatasetiter_next(iterator)) {
5978                 dns_rdatasetiter_current(iterator, &rdataset);
5979                 if (rdataset.type == dns_rdatatype_soa)
5980                         seen_soa = ISC_TRUE;
5981                 else if (rdataset.type == dns_rdatatype_ns)
5982                         seen_ns = ISC_TRUE;
5983                 else if (rdataset.type == dns_rdatatype_ds)
5984                         seen_ds = ISC_TRUE;
5985                 else if (rdataset.type == dns_rdatatype_dname)
5986                         seen_dname = ISC_TRUE;
5987                 else if (rdataset.type == dns_rdatatype_nsec)
5988                         seen_nsec = ISC_TRUE;
5989                 else if (rdataset.type == dns_rdatatype_nsec3)
5990                         seen_nsec3 = ISC_TRUE;
5991                 if (rdataset.type != dns_rdatatype_rrsig)
5992                         seen_rr = ISC_TRUE;
5993                 dns_rdataset_disassociate(&rdataset);
5994         }
5995         if (result != ISC_R_NOMORE)
5996                 goto failure;
5997         if (seen_ns && !seen_soa)
5998                 *delegation = ISC_TRUE;
5999         /*
6000          * Going from insecure to NSEC3.
6001          * Don't generate NSEC3 records for NSEC3 records.
6002          */
6003         if (build_nsec3 && !seen_nsec3 && seen_rr) {
6004                 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
6005                 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
6006                                           unsecure, diff));
6007                 (*signatures)--;
6008         }
6009         /*
6010          * Going from insecure to NSEC.
6011          * Don't generate NSEC records for NSEC3 records.
6012          */
6013         if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
6014                 /* Build and add NSEC. */
6015                 bottom = (seen_ns && !seen_soa) || seen_dname;
6016                 /*
6017                  * Build a NSEC record except at the origin.
6018                  */
6019                 if (!dns_name_equal(name, dns_db_origin(db))) {
6020                         CHECK(add_nsec(db, version, name, node, minimum,
6021                                        bottom, diff));
6022                         /* Count a NSEC generation as a signature generation. */
6023                         (*signatures)--;
6024                 }
6025         }
6026         result = dns_rdatasetiter_first(iterator);
6027         while (result == ISC_R_SUCCESS) {
6028                 dns_rdatasetiter_current(iterator, &rdataset);
6029                 if (rdataset.type == dns_rdatatype_soa ||
6030                     rdataset.type == dns_rdatatype_rrsig)
6031                         goto next_rdataset;
6032                 if (rdataset.type == dns_rdatatype_dnskey) {
6033                         if (!is_ksk && keyset_kskonly)
6034                                 goto next_rdataset;
6035                 } else if (is_ksk)
6036                         goto next_rdataset;
6037                 if (*delegation &&
6038                     rdataset.type != dns_rdatatype_ds &&
6039                     rdataset.type != dns_rdatatype_nsec)
6040                         goto next_rdataset;
6041                 if (signed_with_key(db, node, version, rdataset.type, key))
6042                         goto next_rdataset;
6043                 /* Calculate the signature, creating a RRSIG RDATA. */
6044                 isc_buffer_clear(&buffer);
6045                 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
6046                                       &expire, mctx, &buffer, &rdata));
6047                 /* Update the database and journal with the RRSIG. */
6048                 /* XXX inefficient - will cause dataset merging */
6049                 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
6050                                     name, rdataset.ttl, &rdata));
6051                 dns_rdata_reset(&rdata);
6052                 (*signatures)--;
6053  next_rdataset:
6054                 dns_rdataset_disassociate(&rdataset);
6055                 result = dns_rdatasetiter_next(iterator);
6056         }
6057         if (result == ISC_R_NOMORE)
6058                 result = ISC_R_SUCCESS;
6059         if (seen_dname)
6060                 *delegation = ISC_TRUE;
6061  failure:
6062         if (dns_rdataset_isassociated(&rdataset))
6063                 dns_rdataset_disassociate(&rdataset);
6064         if (iterator != NULL)
6065                 dns_rdatasetiter_destroy(&iterator);
6066         return (result);
6067 }
6068
6069 /*
6070  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
6071  */
6072 static isc_result_t
6073 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6074              dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
6075 {
6076         isc_result_t result;
6077         dns_rdataset_t rdataset;
6078         dns_dbnode_t *node = NULL;
6079
6080         CHECK(dns_db_getoriginnode(db, &node));
6081         if (update_only) {
6082                 dns_rdataset_init(&rdataset);
6083                 result = dns_db_findrdataset(db, node, version,
6084                                              dns_rdatatype_nsec,
6085                                              dns_rdatatype_none,
6086                                              0, &rdataset, NULL);
6087                 if (dns_rdataset_isassociated(&rdataset))
6088                         dns_rdataset_disassociate(&rdataset);
6089                 if (result == ISC_R_NOTFOUND)
6090                         goto success;
6091                 if (result != ISC_R_SUCCESS)
6092                         goto failure;
6093         }
6094         CHECK(delete_nsec(db, version, node, name, diff));
6095         CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
6096  success:
6097         result = ISC_R_SUCCESS;
6098  failure:
6099         if (node != NULL)
6100                 dns_db_detachnode(db, &node);
6101         return (result);
6102 }
6103
6104 static isc_result_t
6105 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
6106                   dns_dbversion_t *version, isc_boolean_t build_nsec3,
6107                   dns_ttl_t minimum, dns_diff_t *diff)
6108 {
6109         isc_result_t result;
6110         dns_dbnode_t *node = NULL;
6111         dns_rdataset_t rdataset;
6112         dns_rdata_t rdata = DNS_RDATA_INIT;
6113         unsigned char data[5];
6114         isc_boolean_t seen_done = ISC_FALSE;
6115         isc_boolean_t have_rr = ISC_FALSE;
6116
6117         dns_rdataset_init(&rdataset);
6118         result = dns_db_getoriginnode(signing->db, &node);
6119         if (result != ISC_R_SUCCESS)
6120                 goto failure;
6121
6122         result = dns_db_findrdataset(signing->db, node, version,
6123                                      zone->privatetype, dns_rdatatype_none,
6124                                      0, &rdataset, NULL);
6125         if (result == ISC_R_NOTFOUND) {
6126                 INSIST(!dns_rdataset_isassociated(&rdataset));
6127                 result = ISC_R_SUCCESS;
6128                 goto failure;
6129         }
6130         if (result != ISC_R_SUCCESS) {
6131                 INSIST(!dns_rdataset_isassociated(&rdataset));
6132                 goto failure;
6133         }
6134         for (result = dns_rdataset_first(&rdataset);
6135              result == ISC_R_SUCCESS;
6136              result = dns_rdataset_next(&rdataset)) {
6137                 dns_rdataset_current(&rdataset, &rdata);
6138                 /*
6139                  * If we don't match the algorithm or keyid skip the record.
6140                  */
6141                 if (rdata.length != 5 ||
6142                     rdata.data[0] != signing->algorithm ||
6143                     rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
6144                     rdata.data[2] != (signing->keyid & 0xff)) {
6145                         have_rr = ISC_TRUE;
6146                         dns_rdata_reset(&rdata);
6147                         continue;
6148                 }
6149                 /*
6150                  * We have a match.  If we were signing (!signing->delete)
6151                  * and we already have a record indicating that we have
6152                  * finished signing (rdata.data[4] != 0) then keep it.
6153                  * Otherwise it needs to be deleted as we have removed all
6154                  * the signatures (signing->delete), so any record indicating
6155                  * completion is now out of date, or we have finished signing
6156                  * with the new record so we no longer need to remember that
6157                  * we need to sign the zone with the matching key across a
6158                  * nameserver re-start.
6159                  */
6160                 if (!signing->delete && rdata.data[4] != 0) {
6161                         seen_done = ISC_TRUE;
6162                         have_rr = ISC_TRUE;
6163                 } else
6164                         CHECK(update_one_rr(signing->db, version, diff,
6165                                             DNS_DIFFOP_DEL, &zone->origin,
6166                                             rdataset.ttl, &rdata));
6167                 dns_rdata_reset(&rdata);
6168         }
6169         if (result == ISC_R_NOMORE)
6170                 result = ISC_R_SUCCESS;
6171         if (!signing->delete && !seen_done) {
6172                 /*
6173                  * If we were signing then we need to indicate that we have
6174                  * finished signing the zone with this key.  If it is already
6175                  * there we don't need to add it a second time.
6176                  */
6177                 data[0] = signing->algorithm;
6178                 data[1] = (signing->keyid >> 8) & 0xff;
6179                 data[2] = signing->keyid & 0xff;
6180                 data[3] = 0;
6181                 data[4] = 1;
6182                 rdata.length = sizeof(data);
6183                 rdata.data = data;
6184                 rdata.type = zone->privatetype;
6185                 rdata.rdclass = dns_db_class(signing->db);
6186                 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
6187                                     &zone->origin, rdataset.ttl, &rdata));
6188         } else if (!have_rr) {
6189                 dns_name_t *origin = dns_db_origin(signing->db);
6190                 /*
6191                  * Rebuild the NSEC/NSEC3 record for the origin as we no
6192                  * longer have any private records.
6193                  */
6194                 if (build_nsec3)
6195                         CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
6196                                                   minimum, ISC_FALSE, diff));
6197                 CHECK(updatesecure(signing->db, version, origin, minimum,
6198                                    ISC_TRUE, diff));
6199         }
6200
6201  failure:
6202         if (dns_rdataset_isassociated(&rdataset))
6203                 dns_rdataset_disassociate(&rdataset);
6204         if (node != NULL)
6205                 dns_db_detachnode(signing->db, &node);
6206         return (result);
6207 }
6208
6209 /*
6210  * If 'active' is set then we are not done with the chain yet so only
6211  * delete the nsec3param record which indicates a full chain exists
6212  * (flags == 0).
6213  */
6214 static isc_result_t
6215 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
6216                  isc_boolean_t active, dns_rdatatype_t privatetype,
6217                  dns_diff_t *diff)
6218 {
6219         dns_dbnode_t *node = NULL;
6220         dns_name_t *name = dns_db_origin(db);
6221         dns_rdata_t rdata = DNS_RDATA_INIT;
6222         dns_rdataset_t rdataset;
6223         dns_rdata_nsec3param_t nsec3param;
6224         isc_result_t result;
6225         isc_buffer_t buffer;
6226         unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
6227         dns_ttl_t ttl = 0;
6228         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
6229
6230         dns_rdataset_init(&rdataset);
6231
6232         result = dns_db_getoriginnode(db, &node);
6233         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6234         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6235                                      0, 0, &rdataset, NULL);
6236         if (result == ISC_R_NOTFOUND)
6237                 goto try_private;
6238         if (result != ISC_R_SUCCESS)
6239                 goto failure;
6240
6241         /*
6242          * Preserve the existing ttl.
6243          */
6244         ttl = rdataset.ttl;
6245
6246         /*
6247          * Delete all NSEC3PARAM records which match that in nsec3chain.
6248          */
6249         for (result = dns_rdataset_first(&rdataset);
6250              result == ISC_R_SUCCESS;
6251              result = dns_rdataset_next(&rdataset)) {
6252
6253                 dns_rdataset_current(&rdataset, &rdata);
6254                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6255
6256                 if (nsec3param.hash != chain->nsec3param.hash ||
6257                     (active && nsec3param.flags != 0) ||
6258                     nsec3param.iterations != chain->nsec3param.iterations ||
6259                     nsec3param.salt_length != chain->nsec3param.salt_length ||
6260                     memcmp(nsec3param.salt, chain->nsec3param.salt,
6261                            nsec3param.salt_length)) {
6262                         dns_rdata_reset(&rdata);
6263                         continue;
6264                 }
6265
6266                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6267                                     name, rdataset.ttl, &rdata));
6268                 dns_rdata_reset(&rdata);
6269         }
6270         if (result != ISC_R_NOMORE)
6271                 goto failure;
6272
6273         dns_rdataset_disassociate(&rdataset);
6274
6275  try_private:
6276
6277         if (active)
6278                 goto add;
6279
6280         result = dns_nsec_nseconly(db, ver, &nseconly);
6281         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
6282
6283         /*
6284          * Delete all private records which match that in nsec3chain.
6285          */
6286         result = dns_db_findrdataset(db, node, ver, privatetype,
6287                                      0, 0, &rdataset, NULL);
6288         if (result == ISC_R_NOTFOUND)
6289                 goto add;
6290         if (result != ISC_R_SUCCESS)
6291                 goto failure;
6292
6293         for (result = dns_rdataset_first(&rdataset);
6294              result == ISC_R_SUCCESS;
6295              result = dns_rdataset_next(&rdataset)) {
6296                 dns_rdata_t private = DNS_RDATA_INIT;
6297                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
6298
6299                 dns_rdataset_current(&rdataset, &private);
6300                 if (!dns_nsec3param_fromprivate(&private, &rdata,
6301                                                 buf, sizeof(buf)))
6302                         continue;
6303                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6304
6305                 if ((!nsec3ok &&
6306                      (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
6307                     nsec3param.hash != chain->nsec3param.hash ||
6308                     nsec3param.iterations != chain->nsec3param.iterations ||
6309                     nsec3param.salt_length != chain->nsec3param.salt_length ||
6310                     memcmp(nsec3param.salt, chain->nsec3param.salt,
6311                            nsec3param.salt_length)) {
6312                         dns_rdata_reset(&rdata);
6313                         continue;
6314                 }
6315
6316                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6317                                     name, rdataset.ttl, &private));
6318                 dns_rdata_reset(&rdata);
6319         }
6320         if (result != ISC_R_NOMORE)
6321                 goto failure;
6322
6323   add:
6324         if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
6325                 result = ISC_R_SUCCESS;
6326                 goto failure;
6327         }
6328
6329         /*
6330          * Add a NSEC3PARAM record which matches that in nsec3chain but
6331          * with all flags bits cleared.
6332          *
6333          * Note: we do not clear chain->nsec3param.flags as this change
6334          * may be reversed.
6335          */
6336         isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
6337         CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
6338                                    dns_rdatatype_nsec3param,
6339                                    &chain->nsec3param, &buffer));
6340         rdata.data[1] = 0;      /* Clear flag bits. */
6341         CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
6342
6343   failure:
6344         dns_db_detachnode(db, &node);
6345         if (dns_rdataset_isassociated(&rdataset))
6346                 dns_rdataset_disassociate(&rdataset);
6347         return (result);
6348 }
6349
6350 static isc_result_t
6351 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6352             dns_name_t *name, dns_diff_t *diff)
6353 {
6354         dns_rdataset_t rdataset;
6355         isc_result_t result;
6356
6357         dns_rdataset_init(&rdataset);
6358
6359         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6360                                      0, 0, &rdataset, NULL);
6361         if (result == ISC_R_NOTFOUND)
6362                 return (ISC_R_SUCCESS);
6363         if (result != ISC_R_SUCCESS)
6364                 return (result);
6365         for (result = dns_rdataset_first(&rdataset);
6366              result == ISC_R_SUCCESS;
6367              result = dns_rdataset_next(&rdataset)) {
6368                 dns_rdata_t rdata = DNS_RDATA_INIT;
6369
6370                 dns_rdataset_current(&rdataset, &rdata);
6371                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6372                                     rdataset.ttl, &rdata));
6373         }
6374         if (result == ISC_R_NOMORE)
6375                 result = ISC_R_SUCCESS;
6376  failure:
6377         dns_rdataset_disassociate(&rdataset);
6378         return (result);
6379 }
6380
6381 static isc_result_t
6382 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6383                     dns_name_t *name, const dns_rdata_nsec3param_t *param,
6384                     dns_diff_t *diff)
6385 {
6386         dns_rdataset_t rdataset;
6387         dns_rdata_nsec3_t nsec3;
6388         isc_result_t result;
6389
6390         dns_rdataset_init(&rdataset);
6391         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
6392                                      0, 0, &rdataset, NULL);
6393         if (result == ISC_R_NOTFOUND)
6394                 return (ISC_R_SUCCESS);
6395         if (result != ISC_R_SUCCESS)
6396                 return (result);
6397
6398         for (result = dns_rdataset_first(&rdataset);
6399              result == ISC_R_SUCCESS;
6400              result = dns_rdataset_next(&rdataset)) {
6401                 dns_rdata_t rdata = DNS_RDATA_INIT;
6402
6403                 dns_rdataset_current(&rdataset, &rdata);
6404                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
6405                 if (nsec3.hash != param->hash ||
6406                     nsec3.iterations != param->iterations ||
6407                     nsec3.salt_length != param->salt_length ||
6408                     memcmp(nsec3.salt, param->salt, nsec3.salt_length))
6409                         continue;
6410                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6411                                     rdataset.ttl, &rdata));
6412         }
6413         if (result == ISC_R_NOMORE)
6414                 result = ISC_R_SUCCESS;
6415  failure:
6416         dns_rdataset_disassociate(&rdataset);
6417         return (result);
6418 }
6419
6420 static isc_result_t
6421 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
6422                 const dns_rdata_nsec3param_t *param,
6423                 isc_boolean_t *answer)
6424 {
6425         dns_dbnode_t *node = NULL;
6426         dns_rdata_t rdata = DNS_RDATA_INIT;
6427         dns_rdata_nsec3param_t myparam;
6428         dns_rdataset_t rdataset;
6429         isc_result_t result;
6430
6431         *answer = ISC_FALSE;
6432
6433         result = dns_db_getoriginnode(db, &node);
6434         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6435
6436         dns_rdataset_init(&rdataset);
6437
6438         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6439                                      0, 0, &rdataset, NULL);
6440         if (result == ISC_R_SUCCESS) {
6441                 dns_rdataset_disassociate(&rdataset);
6442                 dns_db_detachnode(db, &node);
6443                 return (result);
6444         }
6445         if (result != ISC_R_NOTFOUND) {
6446                 dns_db_detachnode(db, &node);
6447                 return (result);
6448         }
6449
6450         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6451                                      0, 0, &rdataset, NULL);
6452         if (result == ISC_R_NOTFOUND) {
6453                 *answer = ISC_TRUE;
6454                 dns_db_detachnode(db, &node);
6455                 return (ISC_R_SUCCESS);
6456         }
6457         if (result != ISC_R_SUCCESS) {
6458                 dns_db_detachnode(db, &node);
6459                 return (result);
6460         }
6461
6462         for (result = dns_rdataset_first(&rdataset);
6463              result == ISC_R_SUCCESS;
6464              result = dns_rdataset_next(&rdataset)) {
6465                 dns_rdataset_current(&rdataset, &rdata);
6466                 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
6467                 dns_rdata_reset(&rdata);
6468                 /*
6469                  * Ignore any NSEC3PARAM removals.
6470                  */
6471                 if (NSEC3REMOVE(myparam.flags))
6472                         continue;
6473                 /*
6474                  * Ignore the chain that we are in the process of deleting.
6475                  */
6476                 if (myparam.hash == param->hash &&
6477                     myparam.iterations == param->iterations &&
6478                     myparam.salt_length == param->salt_length &&
6479                     !memcmp(myparam.salt, param->salt, myparam.salt_length))
6480                         continue;
6481                 /*
6482                  * Found an active NSEC3 chain.
6483                  */
6484                 break;
6485         }
6486         if (result == ISC_R_NOMORE) {
6487                 *answer = ISC_TRUE;
6488                 result = ISC_R_SUCCESS;
6489         }
6490
6491  failure:
6492         if (dns_rdataset_isassociated(&rdataset))
6493                 dns_rdataset_disassociate(&rdataset);
6494         dns_db_detachnode(db, &node);
6495         return (result);
6496 }
6497
6498 static isc_result_t
6499 update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
6500             dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
6501             isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
6502             isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
6503             zonediff_t *zonediff)
6504 {
6505         dns_difftuple_t *tuple;
6506         isc_result_t result;
6507
6508         for (tuple = ISC_LIST_HEAD(diff->tuples);
6509              tuple != NULL;
6510              tuple = ISC_LIST_HEAD(diff->tuples)) {
6511                 result = del_sigs(zone, db, version, &tuple->name,
6512                                   tuple->rdata.type, zonediff,
6513                                   zone_keys, nkeys, now, ISC_FALSE);
6514                 if (result != ISC_R_SUCCESS) {
6515                         dns_zone_log(zone, ISC_LOG_ERROR,
6516                                      "update_sigs:del_sigs -> %s",
6517                                      dns_result_totext(result));
6518                         return (result);
6519                 }
6520                 result = add_sigs(db, version, &tuple->name,
6521                                   tuple->rdata.type, zonediff->diff,
6522                                   zone_keys, nkeys, zone->mctx, inception,
6523                                   expire, check_ksk, keyset_kskonly);
6524                 if (result != ISC_R_SUCCESS) {
6525                         dns_zone_log(zone, ISC_LOG_ERROR,
6526                                      "update_sigs:add_sigs -> %s",
6527                                      dns_result_totext(result));
6528                         return (result);
6529                 }
6530
6531                 do {
6532                         dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
6533                         while (next != NULL &&
6534                                (tuple->rdata.type != next->rdata.type ||
6535                                 !dns_name_equal(&tuple->name, &next->name)))
6536                                 next = ISC_LIST_NEXT(next, link);
6537                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
6538                         dns_diff_appendminimal(zonediff->diff, &tuple);
6539                         INSIST(tuple == NULL);
6540                         tuple = next;
6541                 } while (tuple != NULL);
6542         }
6543         return (ISC_R_SUCCESS);
6544 }
6545
6546 /*
6547  * Incrementally build and sign a new NSEC3 chain using the parameters
6548  * requested.
6549  */
6550 static void
6551 zone_nsec3chain(dns_zone_t *zone) {
6552         const char *me = "zone_nsec3chain";
6553         dns_db_t *db = NULL;
6554         dns_dbnode_t *node = NULL;
6555         dns_dbversion_t *version = NULL;
6556         dns_diff_t _sig_diff;
6557         dns_diff_t nsec_diff;
6558         dns_diff_t nsec3_diff;
6559         dns_diff_t param_diff;
6560         zonediff_t zonediff;
6561         dns_fixedname_t fixed;
6562         dns_fixedname_t nextfixed;
6563         dns_name_t *name, *nextname;
6564         dns_rdataset_t rdataset;
6565         dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
6566         dns_nsec3chainlist_t cleanup;
6567         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6568         isc_int32_t signatures;
6569         isc_boolean_t check_ksk, keyset_kskonly;
6570         isc_boolean_t delegation;
6571         isc_boolean_t first;
6572         isc_result_t result;
6573         isc_stdtime_t now, inception, soaexpire, expire;
6574         isc_uint32_t jitter;
6575         unsigned int i;
6576         unsigned int nkeys = 0;
6577         isc_uint32_t nodes;
6578         isc_boolean_t unsecure = ISC_FALSE;
6579         isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
6580         isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
6581         dns_rdatasetiter_t *iterator = NULL;
6582         isc_boolean_t buildnsecchain;
6583         isc_boolean_t updatensec = ISC_FALSE;
6584         dns_rdatatype_t privatetype = zone->privatetype;
6585
6586         ENTER;
6587
6588         dns_rdataset_init(&rdataset);
6589         dns_fixedname_init(&fixed);
6590         name = dns_fixedname_name(&fixed);
6591         dns_fixedname_init(&nextfixed);
6592         nextname = dns_fixedname_name(&nextfixed);
6593         dns_diff_init(zone->mctx, &param_diff);
6594         dns_diff_init(zone->mctx, &nsec3_diff);
6595         dns_diff_init(zone->mctx, &nsec_diff);
6596         dns_diff_init(zone->mctx, &_sig_diff);
6597         zonediff_init(&zonediff, &_sig_diff);
6598         ISC_LIST_INIT(cleanup);
6599
6600         /*
6601          * Updates are disabled.  Pause for 5 minutes.
6602          */
6603         if (zone->update_disabled) {
6604                 result = ISC_R_FAILURE;
6605                 goto failure;
6606         }
6607
6608         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6609         dns_db_attach(zone->db, &db);
6610         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6611
6612         result = dns_db_newversion(db, &version);
6613         if (result != ISC_R_SUCCESS) {
6614                 dns_zone_log(zone, ISC_LOG_ERROR,
6615                              "zone_nsec3chain:dns_db_newversion -> %s",
6616                              dns_result_totext(result));
6617                 goto failure;
6618         }
6619
6620         result = find_zone_keys(zone, db, version, zone->mctx,
6621                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
6622         if (result != ISC_R_SUCCESS) {
6623                 dns_zone_log(zone, ISC_LOG_ERROR,
6624                              "zone_nsec3chain:find_zone_keys -> %s",
6625                              dns_result_totext(result));
6626                 goto failure;
6627         }
6628
6629         isc_stdtime_get(&now);
6630         inception = now - 3600; /* Allow for clock skew. */
6631         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6632
6633         /*
6634          * Spread out signatures over time if they happen to be
6635          * clumped.  We don't do this for each add_sigs() call as
6636          * we still want some clustering to occur.
6637          */
6638         isc_random_get(&jitter);
6639         expire = soaexpire - jitter % 3600;
6640
6641         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6642         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6643
6644         /*
6645          * We keep pulling nodes off each iterator in turn until
6646          * we have no more nodes to pull off or we reach the limits
6647          * for this quantum.
6648          */
6649         nodes = zone->nodes;
6650         signatures = zone->signatures;
6651         LOCK_ZONE(zone);
6652         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6653         UNLOCK_ZONE(zone);
6654         first = ISC_TRUE;
6655
6656         if (nsec3chain != NULL)
6657                 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6658         /*
6659          * Generate new NSEC3 chains first.
6660          */
6661         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6662                 LOCK_ZONE(zone);
6663                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6664
6665                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6666                 if (nsec3chain->done || nsec3chain->db != zone->db) {
6667                         ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
6668                         ISC_LIST_APPEND(cleanup, nsec3chain, link);
6669                 }
6670                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6671                 UNLOCK_ZONE(zone);
6672                 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
6673                         goto next_addchain;
6674
6675                 /*
6676                  * Possible future db.
6677                  */
6678                 if (nsec3chain->db != db) {
6679                         goto next_addchain;
6680                 }
6681
6682                 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
6683                         goto next_addchain;
6684
6685                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6686
6687                 if (nsec3chain->delete_nsec) {
6688                         delegation = ISC_FALSE;
6689                         dns_dbiterator_pause(nsec3chain->dbiterator);
6690                         CHECK(delete_nsec(db, version, node, name, &nsec_diff));
6691                         goto next_addnode;
6692                 }
6693                 /*
6694                  * On the first pass we need to check if the current node
6695                  * has not been obscured.
6696                  */
6697                 delegation = ISC_FALSE;
6698                 unsecure = ISC_FALSE;
6699                 if (first) {
6700                         dns_fixedname_t ffound;
6701                         dns_name_t *found;
6702                         dns_fixedname_init(&ffound);
6703                         found = dns_fixedname_name(&ffound);
6704                         result = dns_db_find(db, name, version,
6705                                              dns_rdatatype_soa,
6706                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6707                                              NULL, NULL);
6708                         if ((result == DNS_R_DELEGATION ||
6709                             result == DNS_R_DNAME) &&
6710                             !dns_name_equal(name, found)) {
6711                                 /*
6712                                  * Remember the obscuring name so that
6713                                  * we skip all obscured names.
6714                                  */
6715                                 dns_name_copy(found, name, NULL);
6716                                 delegation = ISC_TRUE;
6717                                 goto next_addnode;
6718                         }
6719                 }
6720
6721                 /*
6722                  * Check to see if this is a bottom of zone node.
6723                  */
6724                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6725                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
6726                         goto next_addnode;
6727                 if (result != ISC_R_SUCCESS)
6728                         goto failure;
6729
6730                 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
6731                         ISC_FALSE;
6732                 for (result = dns_rdatasetiter_first(iterator);
6733                      result == ISC_R_SUCCESS;
6734                      result = dns_rdatasetiter_next(iterator)) {
6735                         dns_rdatasetiter_current(iterator, &rdataset);
6736                         INSIST(rdataset.type != dns_rdatatype_nsec3);
6737                         if (rdataset.type == dns_rdatatype_soa)
6738                                 seen_soa = ISC_TRUE;
6739                         else if (rdataset.type == dns_rdatatype_ns)
6740                                 seen_ns = ISC_TRUE;
6741                         else if (rdataset.type == dns_rdatatype_dname)
6742                                 seen_dname = ISC_TRUE;
6743                         else if (rdataset.type == dns_rdatatype_ds)
6744                                 seen_ds = ISC_TRUE;
6745                         else if (rdataset.type == dns_rdatatype_nsec)
6746                                 seen_nsec = ISC_TRUE;
6747                         dns_rdataset_disassociate(&rdataset);
6748                 }
6749                 dns_rdatasetiter_destroy(&iterator);
6750                 /*
6751                  * Is there a NSEC chain than needs to be cleaned up?
6752                  */
6753                 if (seen_nsec)
6754                         nsec3chain->seen_nsec = ISC_TRUE;
6755                 if (seen_ns && !seen_soa && !seen_ds)
6756                         unsecure = ISC_TRUE;
6757                 if ((seen_ns && !seen_soa) || seen_dname)
6758                         delegation = ISC_TRUE;
6759
6760                 /*
6761                  * Process one node.
6762                  */
6763                 dns_dbiterator_pause(nsec3chain->dbiterator);
6764                 result = dns_nsec3_addnsec3(db, version, name,
6765                                             &nsec3chain->nsec3param,
6766                                             zone->minimum, unsecure,
6767                                             &nsec3_diff);
6768                 if (result != ISC_R_SUCCESS) {
6769                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6770                                      "dns_nsec3_addnsec3 -> %s",
6771                                      dns_result_totext(result));
6772                         goto failure;
6773                 }
6774
6775                 /*
6776                  * Treat each call to dns_nsec3_addnsec3() as if it's cost is
6777                  * two signatures.  Additionally there will, in general, be
6778                  * two signature generated below.
6779                  *
6780                  * If we are only changing the optout flag the cost is half
6781                  * that of the cost of generating a completely new chain.
6782                  */
6783                 signatures -= 4;
6784
6785                 /*
6786                  * Go onto next node.
6787                  */
6788  next_addnode:
6789                 first = ISC_FALSE;
6790                 dns_db_detachnode(db, &node);
6791                 do {
6792                         result = dns_dbiterator_next(nsec3chain->dbiterator);
6793
6794                         if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
6795                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6796                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6797                                                        ISC_FALSE, privatetype,
6798                                                        &param_diff));
6799                                 LOCK_ZONE(zone);
6800                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6801                                                 link);
6802                                 UNLOCK_ZONE(zone);
6803                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6804                                 goto next_addchain;
6805                         }
6806                         if (result == ISC_R_NOMORE) {
6807                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6808                                 if (nsec3chain->seen_nsec) {
6809                                         CHECK(fixup_nsec3param(db, version,
6810                                                                nsec3chain,
6811                                                                ISC_TRUE,
6812                                                                privatetype,
6813                                                                &param_diff));
6814                                         nsec3chain->delete_nsec = ISC_TRUE;
6815                                         goto same_addchain;
6816                                 }
6817                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6818                                                        ISC_FALSE, privatetype,
6819                                                        &param_diff));
6820                                 LOCK_ZONE(zone);
6821                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6822                                                 link);
6823                                 UNLOCK_ZONE(zone);
6824                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6825                                 goto next_addchain;
6826                         } else if (result != ISC_R_SUCCESS) {
6827                                 dns_zone_log(zone, ISC_LOG_ERROR,
6828                                              "zone_nsec3chain:"
6829                                              "dns_dbiterator_next -> %s",
6830                                              dns_result_totext(result));
6831                                 goto failure;
6832                         } else if (delegation) {
6833                                 dns_dbiterator_current(nsec3chain->dbiterator,
6834                                                        &node, nextname);
6835                                 dns_db_detachnode(db, &node);
6836                                 if (!dns_name_issubdomain(nextname, name))
6837                                         break;
6838                         } else
6839                                 break;
6840                 } while (1);
6841                 continue;
6842
6843  same_addchain:
6844                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6845                 first = ISC_TRUE;
6846                 continue;
6847
6848  next_addchain:
6849                 dns_dbiterator_pause(nsec3chain->dbiterator);
6850                 nsec3chain = nextnsec3chain;
6851                 first = ISC_TRUE;
6852                 if (nsec3chain != NULL)
6853                         nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6854         }
6855
6856         /*
6857          * Process removals.
6858          */
6859         LOCK_ZONE(zone);
6860         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6861         UNLOCK_ZONE(zone);
6862         first = ISC_TRUE;
6863         buildnsecchain = ISC_FALSE;
6864         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6865                 LOCK_ZONE(zone);
6866                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6867                 UNLOCK_ZONE(zone);
6868
6869                 if (nsec3chain->db != db)
6870                         goto next_removechain;
6871
6872                 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
6873                         goto next_removechain;
6874
6875                 /*
6876                  * Work out if we need to build a NSEC chain as a consequence
6877                  * of removing this NSEC3 chain.
6878                  */
6879                 if (first && !updatensec &&
6880                     (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
6881                 {
6882                         result = need_nsec_chain(db, version,
6883                                                  &nsec3chain->nsec3param,
6884                                                  &buildnsecchain);
6885                         if (result != ISC_R_SUCCESS) {
6886                                 dns_zone_log(zone, ISC_LOG_ERROR,
6887                                              "zone_nsec3chain:"
6888                                              "need_nsec_chain -> %s",
6889                                              dns_result_totext(result));
6890                                 goto failure;
6891                         }
6892                 }
6893
6894                 if (first)
6895                         dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
6896                                      "buildnsecchain = %u\n", buildnsecchain);
6897
6898                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6899                 delegation = ISC_FALSE;
6900
6901                 if (!buildnsecchain) {
6902                         /*
6903                          * Delete the NSECPARAM record that matches this chain.
6904                          */
6905                         if (first) {
6906                                 result = fixup_nsec3param(db, version,
6907                                                           nsec3chain,
6908                                                           ISC_TRUE, privatetype,
6909                                                           &param_diff);
6910                                 if (result != ISC_R_SUCCESS) {
6911                                         dns_zone_log(zone, ISC_LOG_ERROR,
6912                                                      "zone_nsec3chain:"
6913                                                      "fixup_nsec3param -> %s",
6914                                                      dns_result_totext(result));
6915                                         goto failure;
6916                                 }
6917                         }
6918
6919                         /*
6920                          *  Delete the NSEC3 records.
6921                          */
6922                         result = deletematchingnsec3(db, version, node, name,
6923                                                      &nsec3chain->nsec3param,
6924                                                      &nsec3_diff);
6925                         if (result != ISC_R_SUCCESS) {
6926                                 dns_zone_log(zone, ISC_LOG_ERROR,
6927                                              "zone_nsec3chain:"
6928                                              "deletematchingnsec3 -> %s",
6929                                              dns_result_totext(result));
6930                                 goto failure;
6931                         }
6932                         goto next_removenode;
6933                 }
6934
6935                 if (first) {
6936                         dns_fixedname_t ffound;
6937                         dns_name_t *found;
6938                         dns_fixedname_init(&ffound);
6939                         found = dns_fixedname_name(&ffound);
6940                         result = dns_db_find(db, name, version,
6941                                              dns_rdatatype_soa,
6942                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6943                                              NULL, NULL);
6944                         if ((result == DNS_R_DELEGATION ||
6945                              result == DNS_R_DNAME) &&
6946                             !dns_name_equal(name, found)) {
6947                                 /*
6948                                  * Remember the obscuring name so that
6949                                  * we skip all obscured names.
6950                                  */
6951                                 dns_name_copy(found, name, NULL);
6952                                 delegation = ISC_TRUE;
6953                                 goto next_removenode;
6954                         }
6955                 }
6956
6957                 /*
6958                  * Check to see if this is a bottom of zone node.
6959                  */
6960                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6961                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
6962                         goto next_removenode;
6963                 if (result != ISC_R_SUCCESS)
6964                         goto failure;
6965
6966                 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
6967                         seen_rr = ISC_FALSE;
6968                 for (result = dns_rdatasetiter_first(iterator);
6969                      result == ISC_R_SUCCESS;
6970                      result = dns_rdatasetiter_next(iterator)) {
6971                         dns_rdatasetiter_current(iterator, &rdataset);
6972                         if (rdataset.type == dns_rdatatype_soa)
6973                                 seen_soa = ISC_TRUE;
6974                         else if (rdataset.type == dns_rdatatype_ns)
6975                                 seen_ns = ISC_TRUE;
6976                         else if (rdataset.type == dns_rdatatype_dname)
6977                                 seen_dname = ISC_TRUE;
6978                         else if (rdataset.type == dns_rdatatype_nsec)
6979                                 seen_nsec = ISC_TRUE;
6980                         else if (rdataset.type == dns_rdatatype_nsec3)
6981                                 seen_nsec3 = ISC_TRUE;
6982                         if (rdataset.type != dns_rdatatype_rrsig)
6983                                 seen_rr = ISC_TRUE;
6984                         dns_rdataset_disassociate(&rdataset);
6985                 }
6986                 dns_rdatasetiter_destroy(&iterator);
6987
6988                 if (!seen_rr || seen_nsec3 || seen_nsec)
6989                         goto next_removenode;
6990                 if ((seen_ns && !seen_soa) || seen_dname)
6991                         delegation = ISC_TRUE;
6992
6993                 /*
6994                  * Add a NSEC record except at the origin.
6995                  */
6996                 if (!dns_name_equal(name, dns_db_origin(db))) {
6997                         dns_dbiterator_pause(nsec3chain->dbiterator);
6998                         CHECK(add_nsec(db, version, name, node, zone->minimum,
6999                                        delegation, &nsec_diff));
7000                 }
7001
7002  next_removenode:
7003                 first = ISC_FALSE;
7004                 dns_db_detachnode(db, &node);
7005                 do {
7006                         result = dns_dbiterator_next(nsec3chain->dbiterator);
7007                         if (result == ISC_R_NOMORE && buildnsecchain) {
7008                                 /*
7009                                  * The NSEC chain should now be built.
7010                                  * We can now remove the NSEC3 chain.
7011                                  */
7012                                 updatensec = ISC_TRUE;
7013                                 goto same_removechain;
7014                         }
7015                         if (result == ISC_R_NOMORE) {
7016                                 LOCK_ZONE(zone);
7017                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7018                                                 link);
7019                                 UNLOCK_ZONE(zone);
7020                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7021                                 dns_dbiterator_pause(nsec3chain->dbiterator);
7022                                 result = fixup_nsec3param(db, version,
7023                                                           nsec3chain, ISC_FALSE,
7024                                                           privatetype,
7025                                                           &param_diff);
7026                                 if (result != ISC_R_SUCCESS) {
7027                                         dns_zone_log(zone, ISC_LOG_ERROR,
7028                                                      "zone_nsec3chain:"
7029                                                      "fixup_nsec3param -> %s",
7030                                                      dns_result_totext(result));
7031                                         goto failure;
7032                                 }
7033                                 goto next_removechain;
7034                         } else if (result != ISC_R_SUCCESS) {
7035                                 dns_zone_log(zone, ISC_LOG_ERROR,
7036                                              "zone_nsec3chain:"
7037                                              "dns_dbiterator_next -> %s",
7038                                              dns_result_totext(result));
7039                                 goto failure;
7040                         } else if (delegation) {
7041                                 dns_dbiterator_current(nsec3chain->dbiterator,
7042                                                        &node, nextname);
7043                                 dns_db_detachnode(db, &node);
7044                                 if (!dns_name_issubdomain(nextname, name))
7045                                         break;
7046                         } else
7047                                 break;
7048                 } while (1);
7049                 continue;
7050
7051  same_removechain:
7052                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
7053                 buildnsecchain = ISC_FALSE;
7054                 first = ISC_TRUE;
7055                 continue;
7056
7057  next_removechain:
7058                 dns_dbiterator_pause(nsec3chain->dbiterator);
7059                 nsec3chain = nextnsec3chain;
7060                 first = ISC_TRUE;
7061         }
7062
7063         /*
7064          * We may need to update the NSEC/NSEC3 records for the zone apex.
7065          */
7066         if (!ISC_LIST_EMPTY(param_diff.tuples)) {
7067                 isc_boolean_t rebuild_nsec = ISC_FALSE,
7068                               rebuild_nsec3 = ISC_FALSE;
7069                 result = dns_db_getoriginnode(db, &node);
7070                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7071                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7072                 if (result != ISC_R_SUCCESS) {
7073                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7074                                      "dns_db_allrdatasets -> %s",
7075                                      dns_result_totext(result));
7076                         goto failure;
7077                 }
7078                 for (result = dns_rdatasetiter_first(iterator);
7079                      result == ISC_R_SUCCESS;
7080                      result = dns_rdatasetiter_next(iterator)) {
7081                         dns_rdatasetiter_current(iterator, &rdataset);
7082                         if (rdataset.type == dns_rdatatype_nsec)
7083                                 rebuild_nsec = ISC_TRUE;
7084                         if (rdataset.type == dns_rdatatype_nsec3param)
7085                                 rebuild_nsec3 = ISC_TRUE;
7086                         dns_rdataset_disassociate(&rdataset);
7087                 }
7088                 dns_rdatasetiter_destroy(&iterator);
7089                 dns_db_detachnode(db, &node);
7090
7091                 if (rebuild_nsec) {
7092                         if (nsec3chain != NULL)
7093                                 dns_dbiterator_pause(nsec3chain->dbiterator);
7094
7095                         result = updatesecure(db, version, &zone->origin,
7096                                               zone->minimum, ISC_TRUE,
7097                                               &nsec_diff);
7098                         if (result != ISC_R_SUCCESS) {
7099                                 dns_zone_log(zone, ISC_LOG_ERROR,
7100                                              "zone_nsec3chain:"
7101                                              "updatesecure -> %s",
7102                                              dns_result_totext(result));
7103                                 goto failure;
7104                         }
7105                 }
7106
7107                 if (rebuild_nsec3) {
7108                         if (nsec3chain != NULL)
7109                                 dns_dbiterator_pause(nsec3chain->dbiterator);
7110
7111                         result = dns_nsec3_addnsec3s(db, version,
7112                                                      dns_db_origin(db),
7113                                                      zone->minimum, ISC_FALSE,
7114                                                      &nsec3_diff);
7115                         if (result != ISC_R_SUCCESS) {
7116                                 dns_zone_log(zone, ISC_LOG_ERROR,
7117                                              "zone_nsec3chain:"
7118                                              "dns_nsec3_addnsec3s -> %s",
7119                                              dns_result_totext(result));
7120                                 goto failure;
7121                         }
7122                 }
7123         }
7124
7125         if (nsec3chain != NULL)
7126                 dns_dbiterator_pause(nsec3chain->dbiterator);
7127
7128         /*
7129          * Add / update signatures for the NSEC3 records.
7130          */
7131         if (nsec3chain != NULL)
7132                 dns_dbiterator_pause(nsec3chain->dbiterator);
7133         result = update_sigs(&nsec3_diff, db, version, zone_keys,
7134                              nkeys, zone, inception, expire, now,
7135                              check_ksk, keyset_kskonly, &zonediff);
7136         if (result != ISC_R_SUCCESS) {
7137                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7138                              "update_sigs -> %s", dns_result_totext(result));
7139                 goto failure;
7140         }
7141
7142         /*
7143          * We have changed the NSEC3PARAM or private RRsets
7144          * above so we need to update the signatures.
7145          */
7146         result = update_sigs(&param_diff, db, version, zone_keys,
7147                              nkeys, zone, inception, expire, now,
7148                              check_ksk, keyset_kskonly, &zonediff);
7149         if (result != ISC_R_SUCCESS) {
7150                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7151                              "update_sigs -> %s", dns_result_totext(result));
7152                 goto failure;
7153         }
7154
7155         if (updatensec) {
7156                 result = updatesecure(db, version, &zone->origin,
7157                                       zone->minimum, ISC_FALSE, &nsec_diff);
7158                 if (result != ISC_R_SUCCESS) {
7159                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7160                                      "updatesecure -> %s",
7161                                      dns_result_totext(result));
7162                         goto failure;
7163                 }
7164         }
7165
7166         result = update_sigs(&nsec_diff, db, version, zone_keys,
7167                              nkeys, zone, inception, expire, now,
7168                              check_ksk, keyset_kskonly, &zonediff);
7169         if (result != ISC_R_SUCCESS) {
7170                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7171                              "update_sigs -> %s", dns_result_totext(result));
7172                 goto failure;
7173         }
7174
7175         /*
7176          * If we made no effective changes to the zone then we can just
7177          * cleanup otherwise we need to increment the serial.
7178          */
7179         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7180                 /*
7181                  * No need to call dns_db_closeversion() here as it is
7182                  * called with commit = ISC_TRUE below.
7183                  */
7184                 goto done;
7185         }
7186
7187         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7188                           &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7189         if (result != ISC_R_SUCCESS) {
7190                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7191                              "del_sigs -> %s", dns_result_totext(result));
7192                 goto failure;
7193         }
7194
7195         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7196                                    zone->updatemethod);
7197         if (result != ISC_R_SUCCESS) {
7198                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7199                              "update_soa_serial -> %s",
7200                              dns_result_totext(result));
7201                 goto failure;
7202         }
7203
7204         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7205                           zonediff.diff, zone_keys, nkeys, zone->mctx,
7206                           inception, soaexpire, check_ksk, keyset_kskonly);
7207         if (result != ISC_R_SUCCESS) {
7208                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7209                              "add_sigs -> %s", dns_result_totext(result));
7210                 goto failure;
7211         }
7212
7213         /* Write changes to journal file. */
7214         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
7215
7216         LOCK_ZONE(zone);
7217         zone_needdump(zone, DNS_DUMP_DELAY);
7218         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7219         UNLOCK_ZONE(zone);
7220
7221  done:
7222         /*
7223          * Pause all iterators so that dns_db_closeversion() can succeed.
7224          */
7225         LOCK_ZONE(zone);
7226         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7227              nsec3chain != NULL;
7228              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7229                 dns_dbiterator_pause(nsec3chain->dbiterator);
7230         UNLOCK_ZONE(zone);
7231
7232         /*
7233          * Everything has succeeded. Commit the changes.
7234          * Unconditionally commit as zonediff.offline not checked above.
7235          */
7236         dns_db_closeversion(db, &version, ISC_TRUE);
7237
7238         /*
7239          * Everything succeeded so we can clean these up now.
7240          */
7241         nsec3chain = ISC_LIST_HEAD(cleanup);
7242         while (nsec3chain != NULL) {
7243                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7244                 dns_db_detach(&nsec3chain->db);
7245                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
7246                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7247                 nsec3chain = ISC_LIST_HEAD(cleanup);
7248         }
7249
7250         set_resigntime(zone);
7251
7252  failure:
7253         if (result != ISC_R_SUCCESS)
7254                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
7255                              dns_result_totext(result));
7256         /*
7257          * On error roll back the current nsec3chain.
7258          */
7259         if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
7260                 if (nsec3chain->done) {
7261                         dns_db_detach(&nsec3chain->db);
7262                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
7263                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7264                 } else {
7265                         result = dns_dbiterator_first(nsec3chain->dbiterator);
7266                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7267                         dns_dbiterator_pause(nsec3chain->dbiterator);
7268                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7269                 }
7270         }
7271
7272         /*
7273          * Rollback the cleanup list.
7274          */
7275         nsec3chain = ISC_LIST_TAIL(cleanup);
7276         while (nsec3chain != NULL) {
7277                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7278                 if (nsec3chain->done) {
7279                         dns_db_detach(&nsec3chain->db);
7280                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
7281                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7282                 } else {
7283                         LOCK_ZONE(zone);
7284                         ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
7285                         UNLOCK_ZONE(zone);
7286                         result = dns_dbiterator_first(nsec3chain->dbiterator);
7287                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7288                         dns_dbiterator_pause(nsec3chain->dbiterator);
7289                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7290                 }
7291                 nsec3chain = ISC_LIST_TAIL(cleanup);
7292         }
7293
7294         LOCK_ZONE(zone);
7295         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7296              nsec3chain != NULL;
7297              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7298                 dns_dbiterator_pause(nsec3chain->dbiterator);
7299         UNLOCK_ZONE(zone);
7300
7301         dns_diff_clear(&param_diff);
7302         dns_diff_clear(&nsec3_diff);
7303         dns_diff_clear(&nsec_diff);
7304         dns_diff_clear(&_sig_diff);
7305
7306         if (iterator != NULL)
7307                 dns_rdatasetiter_destroy(&iterator);
7308
7309         for (i = 0; i < nkeys; i++)
7310                 dst_key_free(&zone_keys[i]);
7311
7312         if (node != NULL)
7313                 dns_db_detachnode(db, &node);
7314         if (version != NULL) {
7315                 dns_db_closeversion(db, &version, ISC_FALSE);
7316                 dns_db_detach(&db);
7317         } else if (db != NULL)
7318                 dns_db_detach(&db);
7319
7320         LOCK_ZONE(zone);
7321         if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
7322                 isc_interval_t i;
7323                 if (zone->update_disabled || result != ISC_R_SUCCESS)
7324                         isc_interval_set(&i, 60, 0);            /* 1 minute */
7325                 else
7326                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
7327                 isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
7328         } else
7329                 isc_time_settoepoch(&zone->nsec3chaintime);
7330         UNLOCK_ZONE(zone);
7331 }
7332
7333 static isc_result_t
7334 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7335         dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
7336         isc_uint16_t keyid, dns_diff_t *diff)
7337 {
7338         dns_rdata_rrsig_t rrsig;
7339         dns_rdataset_t rdataset;
7340         dns_rdatasetiter_t *iterator = NULL;
7341         isc_result_t result;
7342
7343         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7344         if (result != ISC_R_SUCCESS) {
7345                 if (result == ISC_R_NOTFOUND)
7346                         result = ISC_R_SUCCESS;
7347                 return (result);
7348         }
7349
7350         dns_rdataset_init(&rdataset);
7351         for (result = dns_rdatasetiter_first(iterator);
7352              result == ISC_R_SUCCESS;
7353              result = dns_rdatasetiter_next(iterator)) {
7354                 dns_rdatasetiter_current(iterator, &rdataset);
7355                 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
7356                         for (result = dns_rdataset_first(&rdataset);
7357                              result == ISC_R_SUCCESS;
7358                              result = dns_rdataset_next(&rdataset)) {
7359                                 dns_rdata_t rdata = DNS_RDATA_INIT;
7360                                 dns_rdataset_current(&rdataset, &rdata);
7361                                 CHECK(update_one_rr(db, version, diff,
7362                                                     DNS_DIFFOP_DEL, name,
7363                                                     rdataset.ttl, &rdata));
7364                         }
7365                         if (result != ISC_R_NOMORE)
7366                                 goto failure;
7367                         dns_rdataset_disassociate(&rdataset);
7368                         continue;
7369                 }
7370                 if (rdataset.type != dns_rdatatype_rrsig) {
7371                         dns_rdataset_disassociate(&rdataset);
7372                         continue;
7373                 }
7374                 for (result = dns_rdataset_first(&rdataset);
7375                      result == ISC_R_SUCCESS;
7376                      result = dns_rdataset_next(&rdataset)) {
7377                         dns_rdata_t rdata = DNS_RDATA_INIT;
7378                         dns_rdataset_current(&rdataset, &rdata);
7379                         CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
7380                         if (rrsig.algorithm != algorithm ||
7381                             rrsig.keyid != keyid)
7382                                 continue;
7383                         CHECK(update_one_rr(db, version, diff,
7384                                             DNS_DIFFOP_DELRESIGN, name,
7385                                             rdataset.ttl, &rdata));
7386                 }
7387                 dns_rdataset_disassociate(&rdataset);
7388                 if (result != ISC_R_NOMORE)
7389                         break;
7390         }
7391         if (result == ISC_R_NOMORE)
7392                 result = ISC_R_SUCCESS;
7393  failure:
7394         if (dns_rdataset_isassociated(&rdataset))
7395                 dns_rdataset_disassociate(&rdataset);
7396         dns_rdatasetiter_destroy(&iterator);
7397         return (result);
7398 }
7399
7400 /*
7401  * Incrementally sign the zone using the keys requested.
7402  * Builds the NSEC chain if required.
7403  */
7404 static void
7405 zone_sign(dns_zone_t *zone) {
7406         const char *me = "zone_sign";
7407         dns_db_t *db = NULL;
7408         dns_dbnode_t *node = NULL;
7409         dns_dbversion_t *version = NULL;
7410         dns_diff_t _sig_diff;
7411         dns_diff_t post_diff;
7412         zonediff_t zonediff;
7413         dns_fixedname_t fixed;
7414         dns_fixedname_t nextfixed;
7415         dns_name_t *name, *nextname;
7416         dns_rdataset_t rdataset;
7417         dns_signing_t *signing, *nextsigning;
7418         dns_signinglist_t cleanup;
7419         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7420         isc_int32_t signatures;
7421         isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
7422         isc_boolean_t commit = ISC_FALSE;
7423         isc_boolean_t delegation;
7424         isc_boolean_t build_nsec = ISC_FALSE;
7425         isc_boolean_t build_nsec3 = ISC_FALSE;
7426         isc_boolean_t first;
7427         isc_result_t result;
7428         isc_stdtime_t now, inception, soaexpire, expire;
7429         isc_uint32_t jitter;
7430         unsigned int i, j;
7431         unsigned int nkeys = 0;
7432         isc_uint32_t nodes;
7433
7434         ENTER;
7435
7436         dns_rdataset_init(&rdataset);
7437         dns_fixedname_init(&fixed);
7438         name = dns_fixedname_name(&fixed);
7439         dns_fixedname_init(&nextfixed);
7440         nextname = dns_fixedname_name(&nextfixed);
7441         dns_diff_init(zone->mctx, &_sig_diff);
7442         dns_diff_init(zone->mctx, &post_diff);
7443         zonediff_init(&zonediff, &_sig_diff);
7444         ISC_LIST_INIT(cleanup);
7445
7446         /*
7447          * Updates are disabled.  Pause for 5 minutes.
7448          */
7449         if (zone->update_disabled) {
7450                 result = ISC_R_FAILURE;
7451                 goto failure;
7452         }
7453
7454         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7455         if (zone->db != NULL)
7456                 dns_db_attach(zone->db, &db);
7457         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7458         if (db == NULL) {
7459                 result = ISC_R_FAILURE;
7460                 goto failure;
7461         }
7462
7463         result = dns_db_newversion(db, &version);
7464         if (result != ISC_R_SUCCESS) {
7465                 dns_zone_log(zone, ISC_LOG_ERROR,
7466                              "zone_sign:dns_db_newversion -> %s",
7467                              dns_result_totext(result));
7468                 goto failure;
7469         }
7470
7471         result = find_zone_keys(zone, db, version, zone->mctx,
7472                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7473         if (result != ISC_R_SUCCESS) {
7474                 dns_zone_log(zone, ISC_LOG_ERROR,
7475                              "zone_sign:find_zone_keys -> %s",
7476                              dns_result_totext(result));
7477                 goto failure;
7478         }
7479
7480         isc_stdtime_get(&now);
7481         inception = now - 3600; /* Allow for clock skew. */
7482         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
7483
7484         /*
7485          * Spread out signatures over time if they happen to be
7486          * clumped.  We don't do this for each add_sigs() call as
7487          * we still want some clustering to occur.
7488          */
7489         isc_random_get(&jitter);
7490         expire = soaexpire - jitter % 3600;
7491
7492         /*
7493          * We keep pulling nodes off each iterator in turn until
7494          * we have no more nodes to pull off or we reach the limits
7495          * for this quantum.
7496          */
7497         nodes = zone->nodes;
7498         signatures = zone->signatures;
7499         signing = ISC_LIST_HEAD(zone->signing);
7500         first = ISC_TRUE;
7501
7502         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7503         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7504
7505         /* Determine which type of chain to build */
7506         CHECK(dns_private_chains(db, version, zone->privatetype,
7507                                  &build_nsec, &build_nsec3));
7508
7509         /* If neither chain is found, default to NSEC */
7510         if (!build_nsec && !build_nsec3)
7511                 build_nsec = ISC_TRUE;
7512
7513         while (signing != NULL && nodes-- > 0 && signatures > 0) {
7514                 nextsigning = ISC_LIST_NEXT(signing, link);
7515
7516                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7517                 if (signing->done || signing->db != zone->db) {
7518                         /*
7519                          * The zone has been reloaded.  We will have
7520                          * created new signings as part of the reload
7521                          * process so we can destroy this one.
7522                          */
7523                         ISC_LIST_UNLINK(zone->signing, signing, link);
7524                         ISC_LIST_APPEND(cleanup, signing, link);
7525                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7526                         goto next_signing;
7527                 }
7528                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7529
7530                 if (signing->db != db)
7531                         goto next_signing;
7532
7533                 delegation = ISC_FALSE;
7534
7535                 if (first && signing->delete) {
7536                         /*
7537                          * Remove the key we are deleting from consideration.
7538                          */
7539                         for (i = 0, j = 0; i < nkeys; i++) {
7540                                 /*
7541                                  * Find the key we want to remove.
7542                                  */
7543                                 if (ALG(zone_keys[i]) == signing->algorithm &&
7544                                     dst_key_id(zone_keys[i]) == signing->keyid)
7545                                 {
7546                                         if (KSK(zone_keys[i]))
7547                                                 dst_key_free(&zone_keys[i]);
7548                                         continue;
7549                                 }
7550                                 zone_keys[j] = zone_keys[i];
7551                                 j++;
7552                         }
7553                         nkeys = j;
7554                 }
7555
7556                 dns_dbiterator_current(signing->dbiterator, &node, name);
7557
7558                 if (signing->delete) {
7559                         dns_dbiterator_pause(signing->dbiterator);
7560                         CHECK(del_sig(db, version, name, node, nkeys,
7561                                       signing->algorithm, signing->keyid,
7562                                       zonediff.diff));
7563                 }
7564
7565                 /*
7566                  * On the first pass we need to check if the current node
7567                  * has not been obscured.
7568                  */
7569                 if (first) {
7570                         dns_fixedname_t ffound;
7571                         dns_name_t *found;
7572                         dns_fixedname_init(&ffound);
7573                         found = dns_fixedname_name(&ffound);
7574                         result = dns_db_find(db, name, version,
7575                                              dns_rdatatype_soa,
7576                                              DNS_DBFIND_NOWILD, 0, NULL, found,
7577                                              NULL, NULL);
7578                         if ((result == DNS_R_DELEGATION ||
7579                             result == DNS_R_DNAME) &&
7580                             !dns_name_equal(name, found)) {
7581                                 /*
7582                                  * Remember the obscuring name so that
7583                                  * we skip all obscured names.
7584                                  */
7585                                 dns_name_copy(found, name, NULL);
7586                                 delegation = ISC_TRUE;
7587                                 goto next_node;
7588                         }
7589                 }
7590
7591                 /*
7592                  * Process one node.
7593                  */
7594                 dns_dbiterator_pause(signing->dbiterator);
7595                 for (i = 0; i < nkeys; i++) {
7596                         isc_boolean_t both = ISC_FALSE;
7597
7598                         /*
7599                          * Find the keys we want to sign with.
7600                          */
7601                         if (!dst_key_isprivate(zone_keys[i]))
7602                                 continue;
7603
7604                         /*
7605                          * When adding look for the specific key.
7606                          */
7607                         if (!signing->delete &&
7608                             (dst_key_alg(zone_keys[i]) != signing->algorithm ||
7609                              dst_key_id(zone_keys[i]) != signing->keyid))
7610                                 continue;
7611
7612                         /*
7613                          * When deleting make sure we are properly signed
7614                          * with the algorithm that was being removed.
7615                          */
7616                         if (signing->delete &&
7617                             ALG(zone_keys[i]) != signing->algorithm)
7618                                 continue;
7619
7620                         /*
7621                          * Do we do KSK processing?
7622                          */
7623                         if (check_ksk && !REVOKE(zone_keys[i])) {
7624                                 isc_boolean_t have_ksk, have_nonksk;
7625                                 if (KSK(zone_keys[i])) {
7626                                         have_ksk = ISC_TRUE;
7627                                         have_nonksk = ISC_FALSE;
7628                                 } else {
7629                                         have_ksk = ISC_FALSE;
7630                                         have_nonksk = ISC_TRUE;
7631                                 }
7632                                 for (j = 0; j < nkeys; j++) {
7633                                         if (j == i ||
7634                                             ALG(zone_keys[i]) !=
7635                                             ALG(zone_keys[j]))
7636                                                 continue;
7637                                         if (REVOKE(zone_keys[j]))
7638                                                 continue;
7639                                         if (KSK(zone_keys[j]))
7640                                                 have_ksk = ISC_TRUE;
7641                                         else
7642                                                 have_nonksk = ISC_TRUE;
7643                                         both = have_ksk && have_nonksk;
7644                                         if (both)
7645                                                 break;
7646                                 }
7647                         }
7648                         if (both || REVOKE(zone_keys[i]))
7649                                 is_ksk = KSK(zone_keys[i]);
7650                         else
7651                                 is_ksk = ISC_FALSE;
7652
7653                         CHECK(sign_a_node(db, name, node, version, build_nsec3,
7654                                           build_nsec, zone_keys[i], inception,
7655                                           expire, zone->minimum, is_ksk,
7656                                           ISC_TF(both && keyset_kskonly),
7657                                           &delegation, zonediff.diff,
7658                                           &signatures, zone->mctx));
7659                         /*
7660                          * If we are adding we are done.  Look for other keys
7661                          * of the same algorithm if deleting.
7662                          */
7663                         if (!signing->delete)
7664                                 break;
7665                 }
7666
7667                 /*
7668                  * Go onto next node.
7669                  */
7670  next_node:
7671                 first = ISC_FALSE;
7672                 dns_db_detachnode(db, &node);
7673                 do {
7674                         result = dns_dbiterator_next(signing->dbiterator);
7675                         if (result == ISC_R_NOMORE) {
7676                                 ISC_LIST_UNLINK(zone->signing, signing, link);
7677                                 ISC_LIST_APPEND(cleanup, signing, link);
7678                                 dns_dbiterator_pause(signing->dbiterator);
7679                                 if (nkeys != 0 && build_nsec) {
7680                                         /*
7681                                          * We have finished regenerating the
7682                                          * zone with a zone signing key.
7683                                          * The NSEC chain is now complete and
7684                                          * there is a full set of signatures
7685                                          * for the zone.  We can now clear the
7686                                          * OPT bit from the NSEC record.
7687                                          */
7688                                         result = updatesecure(db, version,
7689                                                               &zone->origin,
7690                                                               zone->minimum,
7691                                                               ISC_FALSE,
7692                                                               &post_diff);
7693                                         if (result != ISC_R_SUCCESS) {
7694                                                 dns_zone_log(zone,
7695                                                              ISC_LOG_ERROR,
7696                                                     "updatesecure -> %s",
7697                                                     dns_result_totext(result));
7698                                                 goto failure;
7699                                         }
7700                                 }
7701                                 result = updatesignwithkey(zone, signing,
7702                                                            version,
7703                                                            build_nsec3,
7704                                                            zone->minimum,
7705                                                            &post_diff);
7706                                 if (result != ISC_R_SUCCESS) {
7707                                         dns_zone_log(zone, ISC_LOG_ERROR,
7708                                                      "updatesignwithkey -> %s",
7709                                                      dns_result_totext(result));
7710                                         goto failure;
7711                                 }
7712                                 build_nsec = ISC_FALSE;
7713                                 goto next_signing;
7714                         } else if (result != ISC_R_SUCCESS) {
7715                                 dns_zone_log(zone, ISC_LOG_ERROR,
7716                                         "zone_sign:dns_dbiterator_next -> %s",
7717                                              dns_result_totext(result));
7718                                 goto failure;
7719                         } else if (delegation) {
7720                                 dns_dbiterator_current(signing->dbiterator,
7721                                                        &node, nextname);
7722                                 dns_db_detachnode(db, &node);
7723                                 if (!dns_name_issubdomain(nextname, name))
7724                                         break;
7725                         } else
7726                                 break;
7727                 } while (1);
7728                 continue;
7729
7730  next_signing:
7731                 dns_dbiterator_pause(signing->dbiterator);
7732                 signing = nextsigning;
7733                 first = ISC_TRUE;
7734         }
7735
7736         if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
7737                 result = update_sigs(&post_diff, db, version, zone_keys,
7738                                      nkeys, zone, inception, expire, now,
7739                                      check_ksk, keyset_kskonly, &zonediff);
7740                 if (result != ISC_R_SUCCESS) {
7741                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
7742                                      "update_sigs -> %s",
7743                                      dns_result_totext(result));
7744                         goto failure;
7745                 }
7746         }
7747
7748         /*
7749          * Have we changed anything?
7750          */
7751         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7752                 if (zonediff.offline)
7753                         commit = ISC_TRUE;
7754                 result = ISC_R_SUCCESS;
7755                 goto pauseall;
7756         }
7757
7758         commit = ISC_TRUE;
7759
7760         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7761                           &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7762         if (result != ISC_R_SUCCESS) {
7763                 dns_zone_log(zone, ISC_LOG_ERROR,
7764                              "zone_sign:del_sigs -> %s",
7765                              dns_result_totext(result));
7766                 goto failure;
7767         }
7768
7769         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7770                                    zone->updatemethod);
7771         if (result != ISC_R_SUCCESS) {
7772                 dns_zone_log(zone, ISC_LOG_ERROR,
7773                              "zone_sign:update_soa_serial -> %s",
7774                              dns_result_totext(result));
7775                 goto failure;
7776         }
7777
7778         /*
7779          * Generate maximum life time signatures so that the above loop
7780          * termination is sensible.
7781          */
7782         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7783                           zonediff.diff, zone_keys, nkeys, zone->mctx,
7784                           inception, soaexpire, check_ksk, keyset_kskonly);
7785         if (result != ISC_R_SUCCESS) {
7786                 dns_zone_log(zone, ISC_LOG_ERROR,
7787                              "zone_sign:add_sigs -> %s",
7788                              dns_result_totext(result));
7789                 goto failure;
7790         }
7791
7792         /*
7793          * Write changes to journal file.
7794          */
7795         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
7796
7797  pauseall:
7798         /*
7799          * Pause all iterators so that dns_db_closeversion() can succeed.
7800          */
7801         for (signing = ISC_LIST_HEAD(zone->signing);
7802              signing != NULL;
7803              signing = ISC_LIST_NEXT(signing, link))
7804                 dns_dbiterator_pause(signing->dbiterator);
7805
7806         for (signing = ISC_LIST_HEAD(cleanup);
7807              signing != NULL;
7808              signing = ISC_LIST_NEXT(signing, link))
7809                 dns_dbiterator_pause(signing->dbiterator);
7810
7811         /*
7812          * Everything has succeeded. Commit the changes.
7813          */
7814         dns_db_closeversion(db, &version, commit);
7815
7816         /*
7817          * Everything succeeded so we can clean these up now.
7818          */
7819         signing = ISC_LIST_HEAD(cleanup);
7820         while (signing != NULL) {
7821                 ISC_LIST_UNLINK(cleanup, signing, link);
7822                 dns_db_detach(&signing->db);
7823                 dns_dbiterator_destroy(&signing->dbiterator);
7824                 isc_mem_put(zone->mctx, signing, sizeof *signing);
7825                 signing = ISC_LIST_HEAD(cleanup);
7826         }
7827
7828         set_resigntime(zone);
7829
7830         if (commit) {
7831                 LOCK_ZONE(zone);
7832                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7833                 zone_needdump(zone, DNS_DUMP_DELAY);
7834                 UNLOCK_ZONE(zone);
7835         }
7836
7837  failure:
7838         /*
7839          * Rollback the cleanup list.
7840          */
7841         signing = ISC_LIST_HEAD(cleanup);
7842         while (signing != NULL) {
7843                 ISC_LIST_UNLINK(cleanup, signing, link);
7844                 ISC_LIST_PREPEND(zone->signing, signing, link);
7845                 dns_dbiterator_first(signing->dbiterator);
7846                 dns_dbiterator_pause(signing->dbiterator);
7847                 signing = ISC_LIST_HEAD(cleanup);
7848         }
7849
7850         for (signing = ISC_LIST_HEAD(zone->signing);
7851              signing != NULL;
7852              signing = ISC_LIST_NEXT(signing, link))
7853                 dns_dbiterator_pause(signing->dbiterator);
7854
7855         dns_diff_clear(&_sig_diff);
7856
7857         for (i = 0; i < nkeys; i++)
7858                 dst_key_free(&zone_keys[i]);
7859
7860         if (node != NULL)
7861                 dns_db_detachnode(db, &node);
7862
7863         if (version != NULL) {
7864                 dns_db_closeversion(db, &version, ISC_FALSE);
7865                 dns_db_detach(&db);
7866         } else if (db != NULL)
7867                 dns_db_detach(&db);
7868
7869         if (ISC_LIST_HEAD(zone->signing) != NULL) {
7870                 isc_interval_t i;
7871                 if (zone->update_disabled || result != ISC_R_SUCCESS)
7872                         isc_interval_set(&i, 60, 0);            /* 1 minute */
7873                 else
7874                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
7875                 isc_time_nowplusinterval(&zone->signingtime, &i);
7876         } else
7877                 isc_time_settoepoch(&zone->signingtime);
7878 }
7879
7880 static isc_result_t
7881 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
7882               unsigned char *data, int size) {
7883         dns_rdata_dnskey_t dnskey;
7884         dns_rdata_keydata_t keydata;
7885         isc_buffer_t buf;
7886         isc_result_t result;
7887
7888         dns_rdata_reset(target);
7889         isc_buffer_init(&buf, data, size);
7890
7891         switch (rr->type) {
7892             case dns_rdatatype_dnskey:
7893                 result = dns_rdata_tostruct(rr, &dnskey, NULL);
7894                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7895                 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
7896                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7897                                      &dnskey, &buf);
7898                 break;
7899             case dns_rdatatype_keydata:
7900                 result = dns_rdata_tostruct(rr, &keydata, NULL);
7901                 if (result == ISC_R_UNEXPECTEDEND)
7902                         return (result);
7903                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7904                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
7905                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7906                                      &dnskey, &buf);
7907                 break;
7908             default:
7909                 INSIST(0);
7910         }
7911         return (ISC_R_SUCCESS);
7912 }
7913
7914 /*
7915  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
7916  * a KEYDATA rdataset from the key zone.
7917  *
7918  * 'rr' contains either a DNSKEY record, or a KEYDATA record
7919  *
7920  * After normalizing keys to the same format (DNSKEY, with revoke bit
7921  * cleared), return ISC_TRUE if a key that matches 'rr' is found in
7922  * 'rdset', or ISC_FALSE if not.
7923  */
7924
7925 static isc_boolean_t
7926 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
7927         unsigned char data1[4096], data2[4096];
7928         dns_rdata_t rdata, rdata1, rdata2;
7929         isc_result_t result;
7930
7931         dns_rdata_init(&rdata);
7932         dns_rdata_init(&rdata1);
7933         dns_rdata_init(&rdata2);
7934
7935         result = normalize_key(rr, &rdata1, data1, sizeof(data1));
7936         if (result != ISC_R_SUCCESS)
7937                 return (ISC_FALSE);
7938
7939         for (result = dns_rdataset_first(rdset);
7940              result == ISC_R_SUCCESS;
7941              result = dns_rdataset_next(rdset)) {
7942                 dns_rdata_reset(&rdata);
7943                 dns_rdataset_current(rdset, &rdata);
7944                 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
7945                 if (result != ISC_R_SUCCESS)
7946                         continue;
7947                 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
7948                         return (ISC_TRUE);
7949         }
7950
7951         return (ISC_FALSE);
7952 }
7953
7954 /*
7955  * Calculate the refresh interval for a keydata zone, per
7956  * RFC5011: MAX(1 hr,
7957  *              MIN(15 days,
7958  *                  1/2 * OrigTTL,
7959  *                  1/2 * RRSigExpirationInterval))
7960  * or for retries: MAX(1 hr,
7961  *                     MIN(1 day,
7962  *                         1/10 * OrigTTL,
7963  *                         1/10 * RRSigExpirationInterval))
7964  */
7965 static inline isc_stdtime_t
7966 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
7967         isc_result_t result;
7968         isc_uint32_t t;
7969         dns_rdataset_t *rdset;
7970         dns_rdata_t sigrr = DNS_RDATA_INIT;
7971         dns_rdata_sig_t sig;
7972         isc_stdtime_t now;
7973
7974         isc_stdtime_get(&now);
7975
7976         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7977                 rdset = &kfetch->dnskeysigset;
7978         else
7979                 return (now + HOUR);
7980
7981         result = dns_rdataset_first(rdset);
7982         if (result != ISC_R_SUCCESS)
7983                 return (now + HOUR);
7984
7985         dns_rdataset_current(rdset, &sigrr);
7986         result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7987         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7988
7989         if (!retry) {
7990                 t = sig.originalttl / 2;
7991
7992                 if (isc_serial_gt(sig.timeexpire, now)) {
7993                         isc_uint32_t exp = (sig.timeexpire - now) / 2;
7994                         if (t > exp)
7995                                 t = exp;
7996                 }
7997
7998                 if (t > (15*DAY))
7999                         t = (15*DAY);
8000
8001                 if (t < HOUR)
8002                         t = HOUR;
8003         } else {
8004                 t = sig.originalttl / 10;
8005
8006                 if (isc_serial_gt(sig.timeexpire, now)) {
8007                         isc_uint32_t exp = (sig.timeexpire - now) / 10;
8008                         if (t > exp)
8009                                 t = exp;
8010                 }
8011
8012                 if (t > DAY)
8013                         t = DAY;
8014
8015                 if (t < HOUR)
8016                         t = HOUR;
8017         }
8018
8019         return (now + t);
8020 }
8021
8022 /*
8023  * This routine is called when no changes are needed in a KEYDATA
8024  * record except to simply update the refresh timer.  Caller should
8025  * hold zone lock.
8026  */
8027 static isc_result_t
8028 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
8029 {
8030         isc_result_t result;
8031         isc_buffer_t keyb;
8032         unsigned char key_buf[4096];
8033         dns_rdata_t rdata = DNS_RDATA_INIT;
8034         dns_rdata_keydata_t keydata;
8035         dns_name_t *name;
8036         dns_zone_t *zone = kfetch->zone;
8037         isc_stdtime_t now;
8038
8039         name = dns_fixedname_name(&kfetch->name);
8040         isc_stdtime_get(&now);
8041
8042         for (result = dns_rdataset_first(&kfetch->keydataset);
8043              result == ISC_R_SUCCESS;
8044              result = dns_rdataset_next(&kfetch->keydataset)) {
8045                 dns_rdata_reset(&rdata);
8046                 dns_rdataset_current(&kfetch->keydataset, &rdata);
8047
8048                 /* Delete old version */
8049                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
8050                                     name, 0, &rdata));
8051
8052                 /* Update refresh timer */
8053                 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
8054                 if (result == ISC_R_UNEXPECTEDEND)
8055                         continue;
8056                 if (result != ISC_R_SUCCESS)
8057                         goto failure;
8058                 keydata.refresh = refresh_time(kfetch, ISC_TRUE);
8059                 set_refreshkeytimer(zone, &keydata, now);
8060
8061                 dns_rdata_reset(&rdata);
8062                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8063                 CHECK(dns_rdata_fromstruct(&rdata,
8064                                            zone->rdclass, dns_rdatatype_keydata,
8065                                            &keydata, &keyb));
8066
8067                 /* Insert updated version */
8068                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
8069                                     name, 0, &rdata));
8070         }
8071         result = ISC_R_SUCCESS;
8072   failure:
8073         return (result);
8074 }
8075
8076 /*
8077  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
8078  */
8079 static isc_boolean_t
8080 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
8081         isc_result_t result;
8082         dns_name_t *keyname;
8083         isc_mem_t *mctx;
8084         dns_rdata_t sigrr = DNS_RDATA_INIT;
8085         dns_rdata_t rr = DNS_RDATA_INIT;
8086         dns_rdata_rrsig_t sig;
8087         dns_rdata_dnskey_t dnskey;
8088         dst_key_t *dstkey = NULL;
8089         unsigned char key_buf[4096];
8090         isc_buffer_t keyb;
8091         isc_boolean_t answer = ISC_FALSE;
8092
8093         REQUIRE(kfetch != NULL && keydata != NULL);
8094         REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
8095
8096         keyname = dns_fixedname_name(&kfetch->name);
8097         mctx = kfetch->zone->view->mctx;
8098
8099         /* Generate a key from keydata */
8100         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8101         dns_keydata_todnskey(keydata, &dnskey, NULL);
8102         dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
8103                                      &dnskey, &keyb);
8104         result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
8105         if (result != ISC_R_SUCCESS)
8106                 return (ISC_FALSE);
8107
8108         /* See if that key generated any of the signatures */
8109         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8110              result == ISC_R_SUCCESS;
8111              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
8112                 dns_fixedname_t fixed;
8113                 dns_fixedname_init(&fixed);
8114
8115                 dns_rdata_reset(&sigrr);
8116                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8117                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8118                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8119
8120                 if (dst_key_alg(dstkey) == sig.algorithm &&
8121                     (dst_key_id(dstkey) == sig.keyid ||
8122                      dst_key_rid(dstkey) == sig.keyid)) {
8123                         result = dns_dnssec_verify2(keyname,
8124                                             &kfetch->dnskeyset,
8125                                             dstkey, ISC_FALSE, mctx, &sigrr,
8126                                             dns_fixedname_name(&fixed));
8127
8128                         dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
8129                                      "Confirm revoked DNSKEY is self-signed: "
8130                                      "%s", dns_result_totext(result));
8131
8132                         if (result == ISC_R_SUCCESS) {
8133                                 answer = ISC_TRUE;
8134                                 break;
8135                         }
8136                 }
8137         }
8138
8139         dst_key_free(&dstkey);
8140         return (answer);
8141 }
8142
8143 /*
8144  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
8145  * anchors are being managed; scan the keyset, and update the key zone and the
8146  * local trust anchors according to RFC5011.
8147  */
8148 static void
8149 keyfetch_done(isc_task_t *task, isc_event_t *event) {
8150         isc_result_t result, eresult;
8151         dns_fetchevent_t *devent;
8152         dns_keyfetch_t *kfetch;
8153         dns_zone_t *zone;
8154         isc_mem_t *mctx = NULL;
8155         dns_keytable_t *secroots = NULL;
8156         dns_dbversion_t *ver = NULL;
8157         dns_diff_t diff;
8158         isc_boolean_t alldone = ISC_FALSE;
8159         isc_boolean_t commit = ISC_FALSE;
8160         dns_name_t *keyname;
8161         dns_rdata_t sigrr = DNS_RDATA_INIT;
8162         dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
8163         dns_rdata_t keydatarr = DNS_RDATA_INIT;
8164         dns_rdata_rrsig_t sig;
8165         dns_rdata_dnskey_t dnskey;
8166         dns_rdata_keydata_t keydata;
8167         isc_boolean_t initializing;
8168         char namebuf[DNS_NAME_FORMATSIZE];
8169         unsigned char key_buf[4096];
8170         isc_buffer_t keyb;
8171         dst_key_t *dstkey;
8172         isc_stdtime_t now;
8173         int pending = 0;
8174         isc_boolean_t secure;
8175         isc_boolean_t free_needed;
8176
8177         UNUSED(task);
8178         INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
8179         INSIST(event->ev_arg != NULL);
8180
8181         kfetch = event->ev_arg;
8182         zone = kfetch->zone;
8183         isc_mem_attach(zone->mctx, &mctx);
8184         keyname = dns_fixedname_name(&kfetch->name);
8185
8186         devent = (dns_fetchevent_t *) event;
8187         eresult = devent->result;
8188
8189         /* Free resources which are not of interest */
8190         if (devent->node != NULL)
8191                 dns_db_detachnode(devent->db, &devent->node);
8192         if (devent->db != NULL)
8193                 dns_db_detach(&devent->db);
8194         isc_event_free(&event);
8195         dns_resolver_destroyfetch(&kfetch->fetch);
8196
8197         LOCK_ZONE(zone);
8198         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
8199                 goto cleanup;
8200
8201         isc_stdtime_get(&now);
8202         dns_name_format(keyname, namebuf, sizeof(namebuf));
8203
8204         result = dns_view_getsecroots(zone->view, &secroots);
8205         INSIST(result == ISC_R_SUCCESS);
8206
8207         dns_diff_init(mctx, &diff);
8208
8209         CHECK(dns_db_newversion(kfetch->db, &ver));
8210
8211         zone->refreshkeycount--;
8212         alldone = ISC_TF(zone->refreshkeycount == 0);
8213
8214         if (alldone)
8215                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8216
8217         /* Fetch failed */
8218         if (eresult != ISC_R_SUCCESS ||
8219             !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
8220                 dns_zone_log(zone, ISC_LOG_WARNING,
8221                              "Unable to fetch DNSKEY set "
8222                              "'%s': %s", namebuf, dns_result_totext(eresult));
8223                 CHECK(minimal_update(kfetch, ver, &diff));
8224                 goto done;
8225         }
8226
8227         /* No RRSIGs found */
8228         if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
8229                 dns_zone_log(zone, ISC_LOG_WARNING,
8230                              "No DNSKEY RRSIGs found for "
8231                              "'%s': %s", namebuf, dns_result_totext(eresult));
8232                 CHECK(minimal_update(kfetch, ver, &diff));
8233                 goto done;
8234         }
8235
8236         /*
8237          * Validate the dnskeyset against the current trusted keys.
8238          */
8239         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8240              result == ISC_R_SUCCESS;
8241              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
8242                 dns_keynode_t *keynode = NULL;
8243
8244                 dns_rdata_reset(&sigrr);
8245                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8246                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8247                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8248
8249                 result = dns_keytable_find(secroots, keyname, &keynode);
8250                 while (result == ISC_R_SUCCESS) {
8251                         dns_keynode_t *nextnode = NULL;
8252                         dns_fixedname_t fixed;
8253                         dns_fixedname_init(&fixed);
8254
8255                         dstkey = dns_keynode_key(keynode);
8256                         if (dstkey == NULL) /* fail_secure() was called */
8257                                 break;
8258
8259                         if (dst_key_alg(dstkey) == sig.algorithm &&
8260                             dst_key_id(dstkey) == sig.keyid) {
8261                                 result = dns_dnssec_verify2(keyname,
8262                                                     &kfetch->dnskeyset,
8263                                                     dstkey, ISC_FALSE,
8264                                                     zone->view->mctx, &sigrr,
8265                                                     dns_fixedname_name(&fixed));
8266
8267                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
8268                                              "Verifying DNSKEY set for zone "
8269                                              "'%s': %s", namebuf,
8270                                              dns_result_totext(result));
8271
8272                                 if (result == ISC_R_SUCCESS) {
8273                                         kfetch->dnskeyset.trust =
8274                                                 dns_trust_secure;
8275                                         kfetch->dnskeysigset.trust =
8276                                                 dns_trust_secure;
8277                                         dns_keytable_detachkeynode(secroots,
8278                                                                    &keynode);
8279                                         break;
8280                                 }
8281                         }
8282
8283                         result = dns_keytable_nextkeynode(secroots,
8284                                                           keynode, &nextnode);
8285                         dns_keytable_detachkeynode(secroots, &keynode);
8286                         keynode = nextnode;
8287                 }
8288
8289                 if (kfetch->dnskeyset.trust == dns_trust_secure)
8290                         break;
8291         }
8292
8293         /*
8294          * If we were not able to verify the answer using the current
8295          * trusted keys then all we can do is look at any revoked keys.
8296          */
8297         secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
8298
8299         /*
8300          * First scan keydataset to find keys that are not in dnskeyset
8301          *   - Missing keys which are not scheduled for removal,
8302          *     log a warning
8303          *   - Missing keys which are scheduled for removal and
8304          *     the remove hold-down timer has completed should
8305          *     be removed from the key zone
8306          *   - Missing keys whose acceptance timers have not yet
8307          *     completed, log a warning and reset the acceptance
8308          *     timer to 30 days in the future
8309          *   - All keys not being removed have their refresh timers
8310          *     updated
8311          */
8312         initializing = ISC_TRUE;
8313         for (result = dns_rdataset_first(&kfetch->keydataset);
8314              result == ISC_R_SUCCESS;
8315              result = dns_rdataset_next(&kfetch->keydataset)) {
8316                 dns_rdata_reset(&keydatarr);
8317                 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8318                 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8319                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8320
8321                 /*
8322                  * If any keydata record has a nonzero add holddown, then
8323                  * there was a pre-existing trust anchor for this domain;
8324                  * that means we are *not* initializing it and shouldn't
8325                  * automatically trust all the keys we find at the zone apex.
8326                  */
8327                 initializing = initializing && ISC_TF(keydata.addhd == 0);
8328
8329                 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
8330                         isc_boolean_t deletekey = ISC_FALSE;
8331
8332                         if (!secure) {
8333                                 if (now > keydata.removehd)
8334                                         deletekey = ISC_TRUE;
8335                         } else if (now < keydata.addhd) {
8336                                 dns_zone_log(zone, ISC_LOG_WARNING,
8337                                              "Pending key unexpectedly missing "
8338                                              "from %s; restarting acceptance "
8339                                              "timer", namebuf);
8340                                 keydata.addhd = now + MONTH;
8341                                 keydata.refresh = refresh_time(kfetch,
8342                                                                ISC_FALSE);
8343                         } else if (keydata.addhd == 0) {
8344                                 keydata.addhd = now;
8345                         } else if (keydata.removehd == 0) {
8346                                 dns_zone_log(zone, ISC_LOG_WARNING,
8347                                              "Active key unexpectedly missing "
8348                                              "from %s", namebuf);
8349                                 keydata.refresh = now + HOUR;
8350                         } else if (now > keydata.removehd) {
8351                                 deletekey = ISC_TRUE;
8352                         } else {
8353                                 keydata.refresh = refresh_time(kfetch,
8354                                                                ISC_FALSE);
8355                         }
8356
8357                         if  (secure || deletekey) {
8358                                 /* Delete old version */
8359                                 CHECK(update_one_rr(kfetch->db, ver, &diff,
8360                                                     DNS_DIFFOP_DEL, keyname, 0,
8361                                                     &keydatarr));
8362                         }
8363
8364                         if (!secure || deletekey)
8365                                 continue;
8366
8367                         dns_rdata_reset(&keydatarr);
8368                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8369                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8370                                              dns_rdatatype_keydata,
8371                                              &keydata, &keyb);
8372
8373                         /* Insert updated version */
8374                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8375                                             DNS_DIFFOP_ADD, keyname, 0,
8376                                             &keydatarr));
8377
8378                         set_refreshkeytimer(zone, &keydata, now);
8379                 }
8380         }
8381
8382         /*
8383          * Next scan dnskeyset:
8384          *   - If new keys are found (i.e., lacking a match in keydataset)
8385          *     add them to the key zone and set the acceptance timer
8386          *     to 30 days in the future (or to immediately if we've
8387          *     determined that we're initializing the zone for the
8388          *     first time)
8389          *   - Previously-known keys that have been revoked
8390          *     must be scheduled for removal from the key zone (or,
8391          *     if they hadn't been accepted as trust anchors yet
8392          *     anyway, removed at once)
8393          *   - Previously-known unrevoked keys whose acceptance timers
8394          *     have completed are promoted to trust anchors
8395          *   - All keys not being removed have their refresh
8396          *     timers updated
8397          */
8398         for (result = dns_rdataset_first(&kfetch->dnskeyset);
8399              result == ISC_R_SUCCESS;
8400              result = dns_rdataset_next(&kfetch->dnskeyset)) {
8401                 isc_boolean_t revoked = ISC_FALSE;
8402                 isc_boolean_t newkey = ISC_FALSE;
8403                 isc_boolean_t updatekey = ISC_FALSE;
8404                 isc_boolean_t deletekey = ISC_FALSE;
8405                 isc_boolean_t trustkey = ISC_FALSE;
8406
8407                 dns_rdata_reset(&dnskeyrr);
8408                 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
8409                 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8410                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8411
8412                 /* Skip ZSK's */
8413                 if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
8414                         continue;
8415
8416                 revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
8417
8418                 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
8419                         dns_rdata_reset(&keydatarr);
8420                         dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8421                         result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8422                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8423
8424                         if (revoked && revocable(kfetch, &keydata)) {
8425                                 if (keydata.addhd > now) {
8426                                         /*
8427                                          * Key wasn't trusted yet, and now
8428                                          * it's been revoked?  Just remove it
8429                                          */
8430                                         deletekey = ISC_TRUE;
8431                                 } else if (keydata.removehd == 0) {
8432                                         /* Remove from secroots */
8433                                         dns_view_untrust(zone->view, keyname,
8434                                                          &dnskey, mctx);
8435
8436                                         /* If initializing, delete now */
8437                                         if (keydata.addhd == 0)
8438                                                 deletekey = ISC_TRUE;
8439                                         else
8440                                                 keydata.removehd = now + MONTH;
8441                                 } else if (keydata.removehd < now) {
8442                                         /* Scheduled for removal */
8443                                         deletekey = ISC_TRUE;
8444                                 }
8445                         } else if (revoked) {
8446                                 if (secure && keydata.removehd == 0) {
8447                                         dns_zone_log(zone, ISC_LOG_WARNING,
8448                                                      "Active key for zone "
8449                                                      "'%s' is revoked but "
8450                                                      "did not self-sign; "
8451                                                          "ignoring.", namebuf);
8452                                                 continue;
8453                                 }
8454                         } else if (secure) {
8455                                 if (keydata.removehd != 0) {
8456                                         /*
8457                                          * Key isn't revoked--but it
8458                                          * seems it used to be.
8459                                          * Remove it now and add it
8460                                          * back as if it were a fresh key.
8461                                          */
8462                                         deletekey = ISC_TRUE;
8463                                         newkey = ISC_TRUE;
8464                                 } else if (keydata.addhd > now)
8465                                         pending++;
8466                                 else if (keydata.addhd == 0)
8467                                         keydata.addhd = now;
8468
8469                                 if (keydata.addhd <= now)
8470                                         trustkey = ISC_TRUE;
8471                         }
8472
8473                         if (!deletekey && !newkey)
8474                                 updatekey = ISC_TRUE;
8475                 } else if (secure) {
8476                         /*
8477                          * Key wasn't in the key zone but it's
8478                          * revoked now anyway, so just skip it
8479                          */
8480                         if (revoked)
8481                                 continue;
8482
8483                         /* Key wasn't in the key zone: add it */
8484                         newkey = ISC_TRUE;
8485
8486                         if (initializing) {
8487                                 dns_keytag_t tag = 0;
8488                                 CHECK(compute_tag(keyname, &dnskey,
8489                                                   mctx, &tag));
8490                                 dns_zone_log(zone, ISC_LOG_WARNING,
8491                                              "Initializing automatic trust "
8492                                              "anchor management for zone '%s'; "
8493                                              "DNSKEY ID %d is now trusted, "
8494                                              "waiving the normal 30-day "
8495                                              "waiting period.",
8496                                              namebuf, tag);
8497                                 trustkey = ISC_TRUE;
8498                         }
8499                 }
8500
8501                 /* Delete old version */
8502                 if (deletekey || !newkey)
8503                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8504                                             DNS_DIFFOP_DEL, keyname, 0,
8505                                             &keydatarr));
8506
8507                 if (updatekey) {
8508                         /* Set refresh timer */
8509                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8510                         dns_rdata_reset(&keydatarr);
8511                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8512                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8513                                              dns_rdatatype_keydata,
8514                                              &keydata, &keyb);
8515
8516                         /* Insert updated version */
8517                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8518                                             DNS_DIFFOP_ADD, keyname, 0,
8519                                             &keydatarr));
8520                 } else if (newkey) {
8521                         /* Convert DNSKEY to KEYDATA */
8522                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8523                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8524                         dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
8525                                                NULL);
8526                         keydata.addhd = initializing ? now : now + MONTH;
8527                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8528                         dns_rdata_reset(&keydatarr);
8529                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8530                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8531                                              dns_rdatatype_keydata,
8532                                              &keydata, &keyb);
8533
8534                         /* Insert into key zone */
8535                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8536                                             DNS_DIFFOP_ADD, keyname, 0,
8537                                             &keydatarr));
8538                 }
8539
8540                 if (trustkey) {
8541                         /* Trust this key. */
8542                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8543                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8544                         trust_key(zone, keyname, &dnskey, mctx);
8545                 }
8546
8547                 if (!deletekey)
8548                         set_refreshkeytimer(zone, &keydata, now);
8549         }
8550
8551         /*
8552          * RFC5011 says, "A trust point that has all of its trust anchors
8553          * revoked is considered deleted and is treated as if the trust
8554          * point was never configured."  But if someone revoked their
8555          * active key before the standby was trusted, that would mean the
8556          * zone would suddenly be nonsecured.  We avoid this by checking to
8557          * see if there's pending keydata.  If so, we put a null key in
8558          * the security roots; then all queries to the zone will fail.
8559          */
8560         if (pending != 0)
8561                 fail_secure(zone, keyname);
8562
8563  done:
8564
8565         if (!ISC_LIST_EMPTY(diff.tuples)) {
8566                 /* Write changes to journal file. */
8567                 CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
8568                                         zone->updatemethod));
8569                 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
8570                 commit = ISC_TRUE;
8571
8572                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8573                 zone_needdump(zone, 30);
8574         }
8575
8576   failure:
8577
8578         dns_diff_clear(&diff);
8579         if (ver != NULL)
8580                 dns_db_closeversion(kfetch->db, &ver, commit);
8581
8582  cleanup:
8583         dns_db_detach(&kfetch->db);
8584
8585         INSIST(zone->irefs > 0);
8586         zone->irefs--;
8587         kfetch->zone = NULL;
8588
8589         if (dns_rdataset_isassociated(&kfetch->keydataset))
8590                 dns_rdataset_disassociate(&kfetch->keydataset);
8591         if (dns_rdataset_isassociated(&kfetch->dnskeyset))
8592                 dns_rdataset_disassociate(&kfetch->dnskeyset);
8593         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8594                 dns_rdataset_disassociate(&kfetch->dnskeysigset);
8595
8596         dns_name_free(keyname, mctx);
8597         isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
8598         isc_mem_detach(&mctx);
8599
8600         if (secroots != NULL)
8601                 dns_keytable_detach(&secroots);
8602
8603         free_needed = exit_check(zone);
8604         UNLOCK_ZONE(zone);
8605         if (free_needed)
8606                 zone_free(zone);
8607 }
8608
8609 /*
8610  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
8611  * records from the zone apex.
8612  */
8613 static void
8614 zone_refreshkeys(dns_zone_t *zone) {
8615         const char me[] = "zone_refreshkeys";
8616         isc_result_t result;
8617         dns_rriterator_t rrit;
8618         dns_db_t *db = NULL;
8619         dns_dbversion_t *ver = NULL;
8620         dns_diff_t diff;
8621         dns_rdata_t rdata = DNS_RDATA_INIT;
8622         dns_rdata_keydata_t kd;
8623         isc_stdtime_t now;
8624         isc_boolean_t commit = ISC_FALSE;
8625         isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
8626
8627         ENTER;
8628         REQUIRE(zone->db != NULL);
8629
8630         isc_stdtime_get(&now);
8631
8632         LOCK_ZONE(zone);
8633         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
8634                 isc_time_settoepoch(&zone->refreshkeytime);
8635                 UNLOCK_ZONE(zone);
8636                 return;
8637         }
8638
8639         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8640         dns_db_attach(zone->db, &db);
8641         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8642
8643         dns_diff_init(zone->mctx, &diff);
8644
8645         CHECK(dns_db_newversion(db, &ver));
8646
8647         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
8648
8649         dns_rriterator_init(&rrit, db, ver, 0);
8650         for (result = dns_rriterator_first(&rrit);
8651              result == ISC_R_SUCCESS;
8652              result = dns_rriterator_nextrrset(&rrit)) {
8653                 isc_stdtime_t timer = 0xffffffff;
8654                 dns_name_t *name = NULL, *kname = NULL;
8655                 dns_rdataset_t *kdset = NULL;
8656                 dns_keyfetch_t *kfetch;
8657                 isc_uint32_t ttl;
8658
8659                 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
8660                 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
8661                     !dns_rdataset_isassociated(kdset))
8662                         continue;
8663
8664                 /*
8665                  * Scan the stored keys looking for ones that need
8666                  * removal or refreshing
8667                  */
8668                 for (result = dns_rdataset_first(kdset);
8669                      result == ISC_R_SUCCESS;
8670                      result = dns_rdataset_next(kdset)) {
8671                         dns_rdata_reset(&rdata);
8672                         dns_rdataset_current(kdset, &rdata);
8673                         result = dns_rdata_tostruct(&rdata, &kd, NULL);
8674                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8675
8676                         /* Removal timer expired? */
8677                         if (kd.removehd != 0 && kd.removehd < now) {
8678                                 CHECK(update_one_rr(db, ver, &diff,
8679                                                     DNS_DIFFOP_DEL, name, ttl,
8680                                                     &rdata));
8681                                 continue;
8682                         }
8683
8684                         /* Acceptance timer expired? */
8685                         if (kd.addhd != 0 && kd.addhd < now)
8686                                 timer = kd.addhd;
8687
8688                         /* Or do we just need to refresh the keyset? */
8689                         if (timer > kd.refresh)
8690                                 timer = kd.refresh;
8691                 }
8692
8693                 if (timer > now)
8694                         continue;
8695
8696                 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
8697                 if (kfetch == NULL) {
8698                         fetch_err = ISC_TRUE;
8699                         goto failure;
8700                 }
8701
8702                 zone->refreshkeycount++;
8703                 kfetch->zone = zone;
8704                 zone->irefs++;
8705                 INSIST(zone->irefs != 0);
8706                 dns_fixedname_init(&kfetch->name);
8707                 kname = dns_fixedname_name(&kfetch->name);
8708                 dns_name_dup(name, zone->mctx, kname);
8709                 dns_rdataset_init(&kfetch->dnskeyset);
8710                 dns_rdataset_init(&kfetch->dnskeysigset);
8711                 dns_rdataset_init(&kfetch->keydataset);
8712                 dns_rdataset_clone(kdset, &kfetch->keydataset);
8713                 kfetch->db = NULL;
8714                 dns_db_attach(db, &kfetch->db);
8715                 kfetch->fetch = NULL;
8716
8717                 result = dns_resolver_createfetch(zone->view->resolver,
8718                                                   kname, dns_rdatatype_dnskey,
8719                                                   NULL, NULL, NULL,
8720                                                   DNS_FETCHOPT_NOVALIDATE,
8721                                                   zone->task,
8722                                                   keyfetch_done, kfetch,
8723                                                   &kfetch->dnskeyset,
8724                                                   &kfetch->dnskeysigset,
8725                                                   &kfetch->fetch);
8726                 if (result == ISC_R_SUCCESS)
8727                         fetching = ISC_TRUE;
8728                 else {
8729                         zone->refreshkeycount--;
8730                         zone->irefs--;
8731                         dns_db_detach(&kfetch->db);
8732                         dns_rdataset_disassociate(&kfetch->keydataset);
8733                         dns_name_free(kname, zone->mctx);
8734                         isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
8735                         dns_zone_log(zone, ISC_LOG_WARNING,
8736                                      "Failed to create fetch for "
8737                                      "DNSKEY update");
8738                         fetch_err = ISC_TRUE;
8739                 }
8740         }
8741         if (!ISC_LIST_EMPTY(diff.tuples)) {
8742                 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
8743                                         zone->updatemethod));
8744                 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
8745                 commit = ISC_TRUE;
8746                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8747                 zone_needdump(zone, 30);
8748         }
8749
8750   failure:
8751         if (fetch_err) {
8752                 /*
8753                  * Error during a key fetch; retry in an hour.
8754                  */
8755                 isc_time_t timenow, timethen;
8756                 char timebuf[80];
8757
8758                 TIME_NOW(&timenow);
8759                 DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
8760                 zone->refreshkeytime = timethen;
8761                 zone_settimer(zone, &timenow);
8762
8763                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
8764                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
8765                              timebuf);
8766
8767                 if (!fetching)
8768                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8769         }
8770
8771         UNLOCK_ZONE(zone);
8772
8773         dns_diff_clear(&diff);
8774         if (ver != NULL) {
8775                 dns_rriterator_destroy(&rrit);
8776                 dns_db_closeversion(db, &ver, commit);
8777         }
8778         dns_db_detach(&db);
8779 }
8780
8781 static void
8782 zone_maintenance(dns_zone_t *zone) {
8783         const char me[] = "zone_maintenance";
8784         isc_time_t now;
8785         isc_result_t result;
8786         isc_boolean_t dumping;
8787
8788         REQUIRE(DNS_ZONE_VALID(zone));
8789         ENTER;
8790
8791         /*
8792          * Are we pending load/reload?
8793          */
8794         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
8795                 return;
8796
8797         /*
8798          * Configuring the view of this zone may have
8799          * failed, for example because the config file
8800          * had a syntax error.  In that case, the view
8801          * adb or resolver will be NULL, and we had better not try
8802          * to do further maintenance on it.
8803          */
8804         if (zone->view == NULL || zone->view->adb == NULL)
8805                 return;
8806
8807         TIME_NOW(&now);
8808
8809         /*
8810          * Expire check.
8811          */
8812         switch (zone->type) {
8813         case dns_zone_redirect:
8814                 if (zone->masters == NULL)
8815                         break;
8816         case dns_zone_slave:
8817         case dns_zone_stub:
8818                 LOCK_ZONE(zone);
8819                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
8820                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8821                         zone_expire(zone);
8822                         zone->refreshtime = now;
8823                 }
8824                 UNLOCK_ZONE(zone);
8825                 break;
8826         default:
8827                 break;
8828         }
8829
8830         /*
8831          * Up to date check.
8832          */
8833         switch (zone->type) {
8834         case dns_zone_redirect:
8835                 if (zone->masters == NULL)
8836                         break;
8837         case dns_zone_slave:
8838         case dns_zone_stub:
8839                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8840                     isc_time_compare(&now, &zone->refreshtime) >= 0)
8841                         dns_zone_refresh(zone);
8842                 break;
8843         default:
8844                 break;
8845         }
8846
8847         /*
8848          * Slaves send notifies before backing up to disk, masters after.
8849          */
8850         if (zone->type == dns_zone_slave &&
8851             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8852             isc_time_compare(&now, &zone->notifytime) >= 0)
8853                 zone_notify(zone, &now);
8854
8855         /*
8856          * Do we need to consolidate the backing store?
8857          */
8858         switch (zone->type) {
8859         case dns_zone_master:
8860         case dns_zone_slave:
8861         case dns_zone_key:
8862         case dns_zone_redirect:
8863         case dns_zone_stub:
8864                 LOCK_ZONE(zone);
8865                 if (zone->masterfile != NULL &&
8866                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
8867                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8868                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
8869                         dumping = was_dumping(zone);
8870                 } else
8871                         dumping = ISC_TRUE;
8872                 UNLOCK_ZONE(zone);
8873                 if (!dumping) {
8874                         result = zone_dump(zone, ISC_TRUE); /* task locked */
8875                         if (result != ISC_R_SUCCESS)
8876                                 dns_zone_log(zone, ISC_LOG_WARNING,
8877                                              "dump failed: %s",
8878                                              dns_result_totext(result));
8879                 }
8880                 break;
8881         default:
8882                 break;
8883         }
8884
8885         /*
8886          * Master/redirect zones send notifies now, if needed
8887          */
8888         switch (zone->type) {
8889         case dns_zone_master:
8890         case dns_zone_redirect:
8891                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8892                     isc_time_compare(&now, &zone->notifytime) >= 0)
8893                         zone_notify(zone, &now);
8894         default:
8895                 break;
8896         }
8897
8898         /*
8899          * Do we need to refresh keys?
8900          */
8901         switch (zone->type) {
8902         case dns_zone_key:
8903                 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
8904                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8905                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
8906                                 zone_refreshkeys(zone);
8907                         }
8908                 }
8909                 break;
8910         case dns_zone_master:
8911                 if (!isc_time_isepoch(&zone->refreshkeytime) &&
8912                     isc_time_compare(&now, &zone->refreshkeytime) >= 0)
8913                         zone_rekey(zone);
8914         default:
8915                 break;
8916         }
8917
8918         switch (zone->type) {
8919         case dns_zone_master:
8920         case dns_zone_redirect:
8921         case dns_zone_slave:
8922                 /*
8923                  * Do we need to sign/resign some RRsets?
8924                  */
8925                 if (!isc_time_isepoch(&zone->signingtime) &&
8926                     isc_time_compare(&now, &zone->signingtime) >= 0)
8927                         zone_sign(zone);
8928                 else if (!isc_time_isepoch(&zone->resigntime) &&
8929                     isc_time_compare(&now, &zone->resigntime) >= 0)
8930                         zone_resigninc(zone);
8931                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
8932                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
8933                         zone_nsec3chain(zone);
8934                 /*
8935                  * Do we need to issue a key expiry warning?
8936                  */
8937                 if (!isc_time_isepoch(&zone->keywarntime) &&
8938                     isc_time_compare(&now, &zone->keywarntime) >= 0)
8939                         set_key_expiry_warning(zone, zone->key_expiry,
8940                                                isc_time_seconds(&now));
8941                 break;
8942
8943         default:
8944                 break;
8945         }
8946         zone_settimer(zone, &now);
8947 }
8948
8949 void
8950 dns_zone_markdirty(dns_zone_t *zone) {
8951         isc_uint32_t serial;
8952         isc_result_t result = ISC_R_SUCCESS;
8953         dns_zone_t *secure = NULL;
8954
8955         /*
8956          * Obtaining a lock on the zone->secure (see zone_send_secureserial)
8957          * could result in a deadlock due to a LOR so we will spin if we
8958          * can't obtain the both locks.
8959          */
8960  again:
8961         LOCK_ZONE(zone);
8962         if (zone->type == dns_zone_master) {
8963                 if (inline_raw(zone)) {
8964                         unsigned int soacount;
8965                         secure = zone->secure;
8966                         INSIST(secure != zone);
8967                         TRYLOCK_ZONE(result, secure);
8968                         if (result != ISC_R_SUCCESS) {
8969                                 UNLOCK_ZONE(zone);
8970                                 secure = NULL;
8971 #ifdef ISC_PLATFORM_USETHREADS
8972                                 isc_thread_yield();
8973 #endif
8974                                 goto again;
8975                         }
8976
8977                         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8978                         if (zone->db != NULL) {
8979                                 result = zone_get_from_db(zone, zone->db, NULL,
8980                                                           &soacount, &serial,
8981                                                           NULL, NULL, NULL,
8982                                                           NULL, NULL);
8983                         } else
8984                                 result = DNS_R_NOTLOADED;
8985                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8986                         if (result == ISC_R_SUCCESS && soacount > 0U)
8987                                 zone_send_secureserial(zone, serial);
8988                 }
8989
8990                 /* XXXMPA make separate call back */
8991                 if (result == ISC_R_SUCCESS)
8992                         set_resigntime(zone);
8993         }
8994         if (secure != NULL)
8995                 UNLOCK_ZONE(secure);
8996         zone_needdump(zone, DNS_DUMP_DELAY);
8997         UNLOCK_ZONE(zone);
8998 }
8999
9000 void
9001 dns_zone_expire(dns_zone_t *zone) {
9002         REQUIRE(DNS_ZONE_VALID(zone));
9003
9004         LOCK_ZONE(zone);
9005         zone_expire(zone);
9006         UNLOCK_ZONE(zone);
9007 }
9008
9009 static void
9010 zone_expire(dns_zone_t *zone) {
9011         /*
9012          * 'zone' locked by caller.
9013          */
9014
9015         REQUIRE(LOCKED_ZONE(zone));
9016
9017         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
9018
9019         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
9020         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
9021         zone->retry = DNS_ZONE_DEFAULTRETRY;
9022         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9023         zone_unload(zone);
9024 }
9025
9026 void
9027 dns_zone_refresh(dns_zone_t *zone) {
9028         isc_interval_t i;
9029         isc_uint32_t oldflags;
9030         unsigned int j;
9031         isc_result_t result;
9032
9033         REQUIRE(DNS_ZONE_VALID(zone));
9034
9035         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
9036                 return;
9037
9038         /*
9039          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
9040          * in progress at a time.
9041          */
9042
9043         LOCK_ZONE(zone);
9044         oldflags = zone->flags;
9045         if (zone->masterscnt == 0) {
9046                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
9047                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
9048                         dns_zone_log(zone, ISC_LOG_ERROR,
9049                                      "cannot refresh: no masters");
9050                 goto unlock;
9051         }
9052         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
9053         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9054         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9055         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
9056                 goto unlock;
9057
9058         /*
9059          * Set the next refresh time as if refresh check has failed.
9060          * Setting this to the retry time will do that.  XXXMLG
9061          * If we are successful it will be reset using zone->refresh.
9062          */
9063         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
9064                          0);
9065         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
9066         if (result != ISC_R_SUCCESS)
9067                 dns_zone_log(zone, ISC_LOG_WARNING,
9068                              "isc_time_nowplusinterval() failed: %s",
9069                              dns_result_totext(result));
9070
9071         /*
9072          * When lacking user-specified timer values from the SOA,
9073          * do exponential backoff of the retry time up to a
9074          * maximum of six hours.
9075          */
9076         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
9077                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
9078
9079         zone->curmaster = 0;
9080         for (j = 0; j < zone->masterscnt; j++)
9081                 zone->mastersok[j] = ISC_FALSE;
9082         /* initiate soa query */
9083         queue_soa_query(zone);
9084  unlock:
9085         UNLOCK_ZONE(zone);
9086 }
9087
9088 isc_result_t
9089 dns_zone_flush(dns_zone_t *zone) {
9090         isc_result_t result = ISC_R_SUCCESS;
9091         isc_boolean_t dumping;
9092
9093         REQUIRE(DNS_ZONE_VALID(zone));
9094
9095         LOCK_ZONE(zone);
9096         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
9097         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9098             zone->masterfile != NULL) {
9099                 result = ISC_R_ALREADYRUNNING;
9100                 dumping = was_dumping(zone);
9101         } else
9102                 dumping = ISC_TRUE;
9103         UNLOCK_ZONE(zone);
9104         if (!dumping)
9105                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
9106         return (result);
9107 }
9108
9109 isc_result_t
9110 dns_zone_dump(dns_zone_t *zone) {
9111         isc_result_t result = ISC_R_ALREADYRUNNING;
9112         isc_boolean_t dumping;
9113
9114         REQUIRE(DNS_ZONE_VALID(zone));
9115
9116         LOCK_ZONE(zone);
9117         dumping = was_dumping(zone);
9118         UNLOCK_ZONE(zone);
9119         if (!dumping)
9120                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
9121         return (result);
9122 }
9123
9124 static void
9125 zone_needdump(dns_zone_t *zone, unsigned int delay) {
9126         const char me[] = "zone_needdump";
9127         isc_time_t dumptime;
9128         isc_time_t now;
9129
9130         /*
9131          * 'zone' locked by caller
9132          */
9133
9134         REQUIRE(DNS_ZONE_VALID(zone));
9135         REQUIRE(LOCKED_ZONE(zone));
9136         ENTER;
9137
9138         /*
9139          * Do we have a place to dump to and are we loaded?
9140          */
9141         if (zone->masterfile == NULL ||
9142             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
9143                 return;
9144
9145         TIME_NOW(&now);
9146         /* add some noise */
9147         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
9148
9149         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9150         if (isc_time_isepoch(&zone->dumptime) ||
9151             isc_time_compare(&zone->dumptime, &dumptime) > 0)
9152                 zone->dumptime = dumptime;
9153         if (zone->task != NULL)
9154                 zone_settimer(zone, &now);
9155 }
9156
9157 static void
9158 dump_done(void *arg, isc_result_t result) {
9159         const char me[] = "dump_done";
9160         dns_zone_t *zone = arg;
9161         dns_db_t *db;
9162         dns_dbversion_t *version;
9163         isc_boolean_t again = ISC_FALSE;
9164         isc_boolean_t compact = ISC_FALSE;
9165         isc_uint32_t serial;
9166         isc_result_t tresult;
9167
9168         REQUIRE(DNS_ZONE_VALID(zone));
9169
9170         ENTER;
9171
9172         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
9173             zone->journalsize != -1) {
9174
9175                 /*
9176                  * We don't own these, zone->dctx must stay valid.
9177                  */
9178                 db = dns_dumpctx_db(zone->dctx);
9179                 version = dns_dumpctx_version(zone->dctx);
9180
9181                 tresult = dns_db_getsoaserial(db, version, &serial);
9182                 /*
9183                  * If there is a secure version of this zone
9184                  * use its serial if it is less than ours.
9185                  */
9186                 if (tresult == ISC_R_SUCCESS && inline_raw(zone) &&
9187                     zone->secure->db != NULL)
9188                 {
9189                         isc_uint32_t sserial;
9190                         isc_result_t mresult;
9191
9192                         mresult = dns_db_getsoaserial(zone->secure->db,
9193                                                       NULL, &sserial);
9194                         if (mresult == ISC_R_SUCCESS &&
9195                             isc_serial_lt(sserial, serial))
9196                                 serial = sserial;
9197                 }
9198                 /*
9199                  * Note: we are task locked here so we can test
9200                  * zone->xfr safely.
9201                  */
9202                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
9203                         tresult = dns_journal_compact(zone->mctx,
9204                                                       zone->journal,
9205                                                       serial,
9206                                                       zone->journalsize);
9207                         switch (tresult) {
9208                         case ISC_R_SUCCESS:
9209                         case ISC_R_NOSPACE:
9210                         case ISC_R_NOTFOUND:
9211                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9212                                              "dns_journal_compact: %s",
9213                                              dns_result_totext(tresult));
9214                                 break;
9215                         default:
9216                                 dns_zone_log(zone, ISC_LOG_ERROR,
9217                                              "dns_journal_compact failed: %s",
9218                                              dns_result_totext(tresult));
9219                                 break;
9220                         }
9221                 } else if (tresult == ISC_R_SUCCESS) {
9222                         compact = ISC_TRUE;
9223                         zone->compact_serial = serial;
9224                 }
9225         }
9226
9227         LOCK_ZONE(zone);
9228         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9229         if (compact)
9230                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
9231         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
9232                 /*
9233                  * Try again in a short while.
9234                  */
9235                 zone_needdump(zone, DNS_DUMP_DELAY);
9236         } else if (result == ISC_R_SUCCESS &&
9237                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9238                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9239                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9240                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9241                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9242                 isc_time_settoepoch(&zone->dumptime);
9243                 again = ISC_TRUE;
9244         } else if (result == ISC_R_SUCCESS)
9245                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9246
9247         if (zone->dctx != NULL)
9248                 dns_dumpctx_detach(&zone->dctx);
9249         zonemgr_putio(&zone->writeio);
9250         UNLOCK_ZONE(zone);
9251         if (again)
9252                 (void)zone_dump(zone, ISC_FALSE);
9253         dns_zone_idetach(&zone);
9254 }
9255
9256 static isc_result_t
9257 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
9258         const char me[] = "zone_dump";
9259         isc_result_t result;
9260         dns_dbversion_t *version = NULL;
9261         isc_boolean_t again;
9262         dns_db_t *db = NULL;
9263         char *masterfile = NULL;
9264         dns_masterformat_t masterformat = dns_masterformat_none;
9265
9266 /*
9267  * 'compact' MUST only be set if we are task locked.
9268  */
9269
9270         REQUIRE(DNS_ZONE_VALID(zone));
9271         ENTER;
9272
9273  redo:
9274         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9275         if (zone->db != NULL)
9276                 dns_db_attach(zone->db, &db);
9277         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9278         LOCK_ZONE(zone);
9279         if (zone->masterfile != NULL) {
9280                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
9281                 masterformat = zone->masterformat;
9282         }
9283         UNLOCK_ZONE(zone);
9284         if (db == NULL) {
9285                 result = DNS_R_NOTLOADED;
9286                 goto fail;
9287         }
9288         if (masterfile == NULL) {
9289                 result = DNS_R_NOMASTERFILE;
9290                 goto fail;
9291         }
9292
9293         if (compact && zone->type != dns_zone_stub) {
9294                 dns_zone_t *dummy = NULL;
9295                 LOCK_ZONE(zone);
9296                 zone_iattach(zone, &dummy);
9297                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
9298                                        zone_gotwritehandle, zone,
9299                                        &zone->writeio);
9300                 if (result != ISC_R_SUCCESS)
9301                         zone_idetach(&dummy);
9302                 else
9303                         result = DNS_R_CONTINUE;
9304                 UNLOCK_ZONE(zone);
9305         } else {
9306                 const dns_master_style_t *output_style;
9307
9308                 dns_masterrawheader_t rawdata;
9309                 dns_db_currentversion(db, &version);
9310                 dns_master_initrawheader(&rawdata);
9311                 if (inline_secure(zone))
9312                         get_raw_serial(zone->raw, &rawdata);
9313                 if (zone->type == dns_zone_key)
9314                         output_style = &dns_master_style_keyzone;
9315                 else
9316                         output_style = &dns_master_style_default;
9317                 result = dns_master_dump3(zone->mctx, db, version,
9318                                           output_style, masterfile,
9319                                           masterformat, &rawdata);
9320                 dns_db_closeversion(db, &version, ISC_FALSE);
9321         }
9322  fail:
9323         if (db != NULL)
9324                 dns_db_detach(&db);
9325         if (masterfile != NULL)
9326                 isc_mem_free(zone->mctx, masterfile);
9327         masterfile = NULL;
9328
9329         if (result == DNS_R_CONTINUE)
9330                 return (ISC_R_SUCCESS); /* XXXMPA */
9331
9332         again = ISC_FALSE;
9333         LOCK_ZONE(zone);
9334         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9335         if (result != ISC_R_SUCCESS) {
9336                 /*
9337                  * Try again in a short while.
9338                  */
9339                 zone_needdump(zone, DNS_DUMP_DELAY);
9340         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9341                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9342                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9343                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9344                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9345                 isc_time_settoepoch(&zone->dumptime);
9346                 again = ISC_TRUE;
9347         } else
9348                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9349         UNLOCK_ZONE(zone);
9350         if (again)
9351                 goto redo;
9352
9353         return (result);
9354 }
9355
9356 static isc_result_t
9357 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
9358              dns_masterformat_t format, const isc_uint32_t rawversion)
9359 {
9360         isc_result_t result;
9361         dns_dbversion_t *version = NULL;
9362         dns_db_t *db = NULL;
9363         dns_masterrawheader_t rawdata;
9364
9365         REQUIRE(DNS_ZONE_VALID(zone));
9366
9367         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9368         if (zone->db != NULL)
9369                 dns_db_attach(zone->db, &db);
9370         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9371         if (db == NULL)
9372                 return (DNS_R_NOTLOADED);
9373
9374         dns_db_currentversion(db, &version);
9375         dns_master_initrawheader(&rawdata);
9376         if (rawversion == 0)
9377                 rawdata.flags |= DNS_MASTERRAW_COMPAT;
9378         else if (inline_secure(zone))
9379                 get_raw_serial(zone->raw, &rawdata);
9380         else if (zone->sourceserialset) {
9381                 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
9382                 rawdata.sourceserial = zone->sourceserial;
9383         }
9384         result = dns_master_dumptostream3(zone->mctx, db, version, style,
9385                                           format, &rawdata, fd);
9386         dns_db_closeversion(db, &version, ISC_FALSE);
9387         dns_db_detach(&db);
9388         return (result);
9389 }
9390
9391 isc_result_t
9392 dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9393                        const dns_master_style_t *style,
9394                        const isc_uint32_t rawversion)
9395 {
9396         return (dumptostream(zone, fd, style, format, rawversion));
9397 }
9398
9399 isc_result_t
9400 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9401                        const dns_master_style_t *style) {
9402         return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
9403 }
9404
9405 isc_result_t
9406 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
9407         return (dumptostream(zone, fd, &dns_master_style_default,
9408                              dns_masterformat_text, 0));
9409 }
9410
9411 isc_result_t
9412 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
9413         return (dumptostream(zone, fd, &dns_master_style_full,
9414                              dns_masterformat_text, 0));
9415 }
9416
9417 void
9418 dns_zone_unload(dns_zone_t *zone) {
9419         REQUIRE(DNS_ZONE_VALID(zone));
9420
9421         LOCK_ZONE(zone);
9422         zone_unload(zone);
9423         UNLOCK_ZONE(zone);
9424 }
9425
9426 static void
9427 notify_cancel(dns_zone_t *zone) {
9428         dns_notify_t *notify;
9429
9430         /*
9431          * 'zone' locked by caller.
9432          */
9433
9434         REQUIRE(LOCKED_ZONE(zone));
9435
9436         for (notify = ISC_LIST_HEAD(zone->notifies);
9437              notify != NULL;
9438              notify = ISC_LIST_NEXT(notify, link)) {
9439                 if (notify->find != NULL)
9440                         dns_adb_cancelfind(notify->find);
9441                 if (notify->request != NULL)
9442                         dns_request_cancel(notify->request);
9443         }
9444 }
9445
9446 static void
9447 forward_cancel(dns_zone_t *zone) {
9448         dns_forward_t *forward;
9449
9450         /*
9451          * 'zone' locked by caller.
9452          */
9453
9454         REQUIRE(LOCKED_ZONE(zone));
9455
9456         for (forward = ISC_LIST_HEAD(zone->forwards);
9457              forward != NULL;
9458              forward = ISC_LIST_NEXT(forward, link)) {
9459                 if (forward->request != NULL)
9460                         dns_request_cancel(forward->request);
9461         }
9462 }
9463
9464 static void
9465 zone_unload(dns_zone_t *zone) {
9466         /*
9467          * 'zone' locked by caller.
9468          */
9469
9470         REQUIRE(LOCKED_ZONE(zone));
9471
9472         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
9473             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9474                 if (zone->writeio != NULL)
9475                         zonemgr_cancelio(zone->writeio);
9476
9477                 if (zone->dctx != NULL)
9478                         dns_dumpctx_cancel(zone->dctx);
9479         }
9480         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9481         zone_detachdb(zone);
9482         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9483         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
9484         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9485 }
9486
9487 void
9488 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9489         REQUIRE(DNS_ZONE_VALID(zone));
9490         REQUIRE(val > 0);
9491
9492         zone->minrefresh = val;
9493 }
9494
9495 void
9496 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9497         REQUIRE(DNS_ZONE_VALID(zone));
9498         REQUIRE(val > 0);
9499
9500         zone->maxrefresh = val;
9501 }
9502
9503 void
9504 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
9505         REQUIRE(DNS_ZONE_VALID(zone));
9506         REQUIRE(val > 0);
9507
9508         zone->minretry = val;
9509 }
9510
9511 void
9512 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
9513         REQUIRE(DNS_ZONE_VALID(zone));
9514         REQUIRE(val > 0);
9515
9516         zone->maxretry = val;
9517 }
9518
9519 static isc_boolean_t
9520 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
9521         dns_notify_t *notify;
9522
9523         for (notify = ISC_LIST_HEAD(zone->notifies);
9524              notify != NULL;
9525              notify = ISC_LIST_NEXT(notify, link)) {
9526                 if (notify->request != NULL)
9527                         continue;
9528                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
9529                     dns_name_equal(name, &notify->ns))
9530                         return (ISC_TRUE);
9531                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
9532                         return (ISC_TRUE);
9533         }
9534         return (ISC_FALSE);
9535 }
9536
9537 static isc_boolean_t
9538 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
9539         dns_tsigkey_t *key = NULL;
9540         isc_sockaddr_t src;
9541         isc_sockaddr_t any;
9542         isc_boolean_t isself;
9543         isc_netaddr_t dstaddr;
9544         isc_result_t result;
9545
9546         if (zone->view == NULL || zone->isself == NULL)
9547                 return (ISC_FALSE);
9548
9549         switch (isc_sockaddr_pf(dst)) {
9550         case PF_INET:
9551                 src = zone->notifysrc4;
9552                 isc_sockaddr_any(&any);
9553                 break;
9554         case PF_INET6:
9555                 src = zone->notifysrc6;
9556                 isc_sockaddr_any6(&any);
9557                 break;
9558         default:
9559                 return (ISC_FALSE);
9560         }
9561
9562         /*
9563          * When sending from any the kernel will assign a source address
9564          * that matches the destination address.
9565          */
9566         if (isc_sockaddr_eqaddr(&any, &src))
9567                 src = *dst;
9568
9569         isc_netaddr_fromsockaddr(&dstaddr, dst);
9570         result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
9571         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
9572                 return (ISC_FALSE);
9573         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
9574                                 zone->isselfarg);
9575         if (key != NULL)
9576                 dns_tsigkey_detach(&key);
9577         return (isself);
9578 }
9579
9580 static void
9581 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
9582         isc_mem_t *mctx;
9583
9584         /*
9585          * Caller holds zone lock.
9586          */
9587         REQUIRE(DNS_NOTIFY_VALID(notify));
9588
9589         if (notify->zone != NULL) {
9590                 if (!locked)
9591                         LOCK_ZONE(notify->zone);
9592                 REQUIRE(LOCKED_ZONE(notify->zone));
9593                 if (ISC_LINK_LINKED(notify, link))
9594                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
9595                 if (!locked)
9596                         UNLOCK_ZONE(notify->zone);
9597                 if (locked)
9598                         zone_idetach(&notify->zone);
9599                 else
9600                         dns_zone_idetach(&notify->zone);
9601         }
9602         if (notify->find != NULL)
9603                 dns_adb_destroyfind(&notify->find);
9604         if (notify->request != NULL)
9605                 dns_request_destroy(&notify->request);
9606         if (dns_name_dynamic(&notify->ns))
9607                 dns_name_free(&notify->ns, notify->mctx);
9608         if (notify->key != NULL)
9609                 dns_tsigkey_detach(&notify->key);
9610         mctx = notify->mctx;
9611         isc_mem_put(notify->mctx, notify, sizeof(*notify));
9612         isc_mem_detach(&mctx);
9613 }
9614
9615 static isc_result_t
9616 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
9617         dns_notify_t *notify;
9618
9619         REQUIRE(notifyp != NULL && *notifyp == NULL);
9620
9621         notify = isc_mem_get(mctx, sizeof(*notify));
9622         if (notify == NULL)
9623                 return (ISC_R_NOMEMORY);
9624
9625         notify->mctx = NULL;
9626         isc_mem_attach(mctx, &notify->mctx);
9627         notify->flags = flags;
9628         notify->zone = NULL;
9629         notify->find = NULL;
9630         notify->request = NULL;
9631         notify->key = NULL;
9632         isc_sockaddr_any(&notify->dst);
9633         dns_name_init(&notify->ns, NULL);
9634         ISC_LINK_INIT(notify, link);
9635         notify->magic = NOTIFY_MAGIC;
9636         *notifyp = notify;
9637         return (ISC_R_SUCCESS);
9638 }
9639
9640 /*
9641  * XXXAG should check for DNS_ZONEFLG_EXITING
9642  */
9643 static void
9644 process_adb_event(isc_task_t *task, isc_event_t *ev) {
9645         dns_notify_t *notify;
9646         isc_eventtype_t result;
9647
9648         UNUSED(task);
9649
9650         notify = ev->ev_arg;
9651         REQUIRE(DNS_NOTIFY_VALID(notify));
9652         INSIST(task == notify->zone->task);
9653         result = ev->ev_type;
9654         isc_event_free(&ev);
9655         if (result == DNS_EVENT_ADBMOREADDRESSES) {
9656                 dns_adb_destroyfind(&notify->find);
9657                 notify_find_address(notify);
9658                 return;
9659         }
9660         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
9661                 LOCK_ZONE(notify->zone);
9662                 notify_send(notify);
9663                 UNLOCK_ZONE(notify->zone);
9664         }
9665         notify_destroy(notify, ISC_FALSE);
9666 }
9667
9668 static void
9669 notify_find_address(dns_notify_t *notify) {
9670         isc_result_t result;
9671         unsigned int options;
9672
9673         REQUIRE(DNS_NOTIFY_VALID(notify));
9674         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
9675                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
9676
9677         if (notify->zone->view->adb == NULL)
9678                 goto destroy;
9679
9680         result = dns_adb_createfind(notify->zone->view->adb,
9681                                     notify->zone->task,
9682                                     process_adb_event, notify,
9683                                     &notify->ns, dns_rootname, 0,
9684                                     options, 0, NULL,
9685                                     notify->zone->view->dstport,
9686                                     &notify->find);
9687
9688         /* Something failed? */
9689         if (result != ISC_R_SUCCESS)
9690                 goto destroy;
9691
9692         /* More addresses pending? */
9693         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
9694                 return;
9695
9696         /* We have as many addresses as we can get. */
9697         LOCK_ZONE(notify->zone);
9698         notify_send(notify);
9699         UNLOCK_ZONE(notify->zone);
9700
9701  destroy:
9702         notify_destroy(notify, ISC_FALSE);
9703 }
9704
9705
9706 static isc_result_t
9707 notify_send_queue(dns_notify_t *notify) {
9708         isc_event_t *e;
9709         isc_result_t result;
9710
9711         e = isc_event_allocate(notify->mctx, NULL,
9712                                DNS_EVENT_NOTIFYSENDTOADDR,
9713                                notify_send_toaddr,
9714                                notify, sizeof(isc_event_t));
9715         if (e == NULL)
9716                 return (ISC_R_NOMEMORY);
9717         e->ev_arg = notify;
9718         e->ev_sender = NULL;
9719         result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
9720                                          notify->zone->task, &e);
9721         if (result != ISC_R_SUCCESS)
9722                 isc_event_free(&e);
9723         return (result);
9724 }
9725
9726 static void
9727 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
9728         dns_notify_t *notify;
9729         isc_result_t result;
9730         dns_message_t *message = NULL;
9731         isc_netaddr_t dstip;
9732         dns_tsigkey_t *key = NULL;
9733         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9734         isc_sockaddr_t src;
9735         int timeout;
9736         isc_boolean_t have_notifysource = ISC_FALSE;
9737
9738         notify = event->ev_arg;
9739         REQUIRE(DNS_NOTIFY_VALID(notify));
9740
9741         UNUSED(task);
9742
9743         LOCK_ZONE(notify->zone);
9744
9745         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
9746                 result = ISC_R_CANCELED;
9747                 goto cleanup;
9748         }
9749
9750         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
9751             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
9752             notify->zone->view->requestmgr == NULL ||
9753             notify->zone->db == NULL) {
9754                 result = ISC_R_CANCELED;
9755                 goto cleanup;
9756         }
9757
9758         /*
9759          * The raw IPv4 address should also exist.  Don't send to the
9760          * mapped form.
9761          */
9762         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
9763             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
9764                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9765                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
9766                            "notify: ignoring IPv6 mapped IPV4 address: %s",
9767                            addrbuf);
9768                 result = ISC_R_CANCELED;
9769                 goto cleanup;
9770         }
9771
9772         result = notify_createmessage(notify->zone, notify->flags, &message);
9773         if (result != ISC_R_SUCCESS)
9774                 goto cleanup;
9775
9776         if (notify->key != NULL) {
9777                 /* Transfer ownership of key */
9778                 key = notify->key;
9779                 notify->key = NULL;
9780         } else {
9781                 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
9782                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9783                 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
9784                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9785                         notify_log(notify->zone, ISC_LOG_ERROR,
9786                                    "NOTIFY to %s not sent. "
9787                                    "Peer TSIG key lookup failure.", addrbuf);
9788                         goto cleanup_message;
9789                 }
9790         }
9791
9792         /* XXX: should we log the tsig key too? */
9793         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
9794                    addrbuf);
9795         if (notify->zone->view->peers != NULL) {
9796                 dns_peer_t *peer = NULL;
9797                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
9798                                                  &dstip, &peer);
9799                 if (result == ISC_R_SUCCESS) {
9800                         result = dns_peer_getnotifysource(peer, &src);
9801                         if (result == ISC_R_SUCCESS)
9802                                 have_notifysource = ISC_TRUE;
9803                 }
9804         }
9805         switch (isc_sockaddr_pf(&notify->dst)) {
9806         case PF_INET:
9807                 if (!have_notifysource)
9808                         src = notify->zone->notifysrc4;
9809                 break;
9810         case PF_INET6:
9811                 if (!have_notifysource)
9812                         src = notify->zone->notifysrc6;
9813                 break;
9814         default:
9815                 result = ISC_R_NOTIMPLEMENTED;
9816                 goto cleanup_key;
9817         }
9818         timeout = 15;
9819         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
9820                 timeout = 30;
9821         result = dns_request_createvia2(notify->zone->view->requestmgr,
9822                                         message, &src, &notify->dst, 0, key,
9823                                         timeout * 3, timeout,
9824                                         notify->zone->task, notify_done,
9825                                         notify, &notify->request);
9826         if (result == ISC_R_SUCCESS) {
9827                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
9828                         inc_stats(notify->zone,
9829                                   dns_zonestatscounter_notifyoutv4);
9830                 } else {
9831                         inc_stats(notify->zone,
9832                                   dns_zonestatscounter_notifyoutv6);
9833                 }
9834         }
9835
9836  cleanup_key:
9837         if (key != NULL)
9838                 dns_tsigkey_detach(&key);
9839  cleanup_message:
9840         dns_message_destroy(&message);
9841  cleanup:
9842         UNLOCK_ZONE(notify->zone);
9843         isc_event_free(&event);
9844         if (result != ISC_R_SUCCESS)
9845                 notify_destroy(notify, ISC_FALSE);
9846 }
9847
9848 static void
9849 notify_send(dns_notify_t *notify) {
9850         dns_adbaddrinfo_t *ai;
9851         isc_sockaddr_t dst;
9852         isc_result_t result;
9853         dns_notify_t *new = NULL;
9854
9855         /*
9856          * Zone lock held by caller.
9857          */
9858         REQUIRE(DNS_NOTIFY_VALID(notify));
9859         REQUIRE(LOCKED_ZONE(notify->zone));
9860
9861         for (ai = ISC_LIST_HEAD(notify->find->list);
9862              ai != NULL;
9863              ai = ISC_LIST_NEXT(ai, publink)) {
9864                 dst = ai->sockaddr;
9865                 if (notify_isqueued(notify->zone, NULL, &dst))
9866                         continue;
9867                 if (notify_isself(notify->zone, &dst))
9868                         continue;
9869                 new = NULL;
9870                 result = notify_create(notify->mctx,
9871                                        (notify->flags & DNS_NOTIFY_NOSOA),
9872                                        &new);
9873                 if (result != ISC_R_SUCCESS)
9874                         goto cleanup;
9875                 zone_iattach(notify->zone, &new->zone);
9876                 ISC_LIST_APPEND(new->zone->notifies, new, link);
9877                 new->dst = dst;
9878                 result = notify_send_queue(new);
9879                 if (result != ISC_R_SUCCESS)
9880                         goto cleanup;
9881                 new = NULL;
9882         }
9883
9884  cleanup:
9885         if (new != NULL)
9886                 notify_destroy(new, ISC_TRUE);
9887 }
9888
9889 void
9890 dns_zone_notify(dns_zone_t *zone) {
9891         isc_time_t now;
9892
9893         REQUIRE(DNS_ZONE_VALID(zone));
9894
9895         LOCK_ZONE(zone);
9896         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9897
9898         TIME_NOW(&now);
9899         zone_settimer(zone, &now);
9900         UNLOCK_ZONE(zone);
9901 }
9902
9903 static void
9904 zone_notify(dns_zone_t *zone, isc_time_t *now) {
9905         dns_dbnode_t *node = NULL;
9906         dns_db_t *zonedb = NULL;
9907         dns_dbversion_t *version = NULL;
9908         dns_name_t *origin = NULL;
9909         dns_name_t master;
9910         dns_rdata_ns_t ns;
9911         dns_rdata_soa_t soa;
9912         isc_uint32_t serial;
9913         dns_rdata_t rdata = DNS_RDATA_INIT;
9914         dns_rdataset_t nsrdset;
9915         dns_rdataset_t soardset;
9916         isc_result_t result;
9917         dns_notify_t *notify = NULL;
9918         unsigned int i;
9919         isc_sockaddr_t dst;
9920         isc_boolean_t isqueued;
9921         dns_notifytype_t notifytype;
9922         unsigned int flags = 0;
9923         isc_boolean_t loggednotify = ISC_FALSE;
9924
9925         REQUIRE(DNS_ZONE_VALID(zone));
9926
9927         LOCK_ZONE(zone);
9928         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9929         notifytype = zone->notifytype;
9930         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
9931         UNLOCK_ZONE(zone);
9932
9933         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
9934                 return;
9935
9936         if (notifytype == dns_notifytype_no)
9937                 return;
9938
9939         if (notifytype == dns_notifytype_masteronly &&
9940             zone->type != dns_zone_master)
9941                 return;
9942
9943         origin = &zone->origin;
9944
9945         /*
9946          * If the zone is dialup we are done as we don't want to send
9947          * the current soa so as to force a refresh query.
9948          */
9949         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
9950                 flags |= DNS_NOTIFY_NOSOA;
9951
9952         /*
9953          * Get SOA RRset.
9954          */
9955         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9956         if (zone->db != NULL)
9957                 dns_db_attach(zone->db, &zonedb);
9958         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9959         if (zonedb == NULL)
9960                 return;
9961         dns_db_currentversion(zonedb, &version);
9962         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
9963         if (result != ISC_R_SUCCESS)
9964                 goto cleanup1;
9965
9966         dns_rdataset_init(&soardset);
9967         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
9968                                      dns_rdatatype_none, 0, &soardset, NULL);
9969         if (result != ISC_R_SUCCESS)
9970                 goto cleanup2;
9971
9972         /*
9973          * Find serial and master server's name.
9974          */
9975         dns_name_init(&master, NULL);
9976         result = dns_rdataset_first(&soardset);
9977         if (result != ISC_R_SUCCESS)
9978                 goto cleanup3;
9979         dns_rdataset_current(&soardset, &rdata);
9980         result = dns_rdata_tostruct(&rdata, &soa, NULL);
9981         RUNTIME_CHECK(result == ISC_R_SUCCESS);
9982         dns_rdata_reset(&rdata);
9983         result = dns_name_dup(&soa.origin, zone->mctx, &master);
9984         serial = soa.serial;
9985         dns_rdataset_disassociate(&soardset);
9986         if (result != ISC_R_SUCCESS)
9987                 goto cleanup3;
9988
9989         /*
9990          * Enqueue notify requests for 'also-notify' servers.
9991          */
9992         LOCK_ZONE(zone);
9993         for (i = 0; i < zone->notifycnt; i++) {
9994                 dns_tsigkey_t *key = NULL;
9995
9996                 dst = zone->notify[i];
9997                 if (notify_isqueued(zone, NULL, &dst))
9998                         continue;
9999
10000                 result = notify_create(zone->mctx, flags, &notify);
10001                 if (result != ISC_R_SUCCESS)
10002                         continue;
10003
10004                 zone_iattach(zone, &notify->zone);
10005                 notify->dst = dst;
10006
10007                 if ((zone->notifykeynames != NULL) &&
10008                     (zone->notifykeynames[i] != NULL)) {
10009                         dns_view_t *view = dns_zone_getview(zone);
10010                         dns_name_t *keyname = zone->notifykeynames[i];
10011                         result = dns_view_gettsig(view, keyname, &key);
10012                         if (result == ISC_R_SUCCESS) {
10013                                 notify->key = key;
10014                                 key = NULL;
10015                         }
10016                 }
10017
10018                 ISC_LIST_APPEND(zone->notifies, notify, link);
10019                 result = notify_send_queue(notify);
10020                 if (result != ISC_R_SUCCESS)
10021                         notify_destroy(notify, ISC_TRUE);
10022                 if (!loggednotify) {
10023                         notify_log(zone, ISC_LOG_INFO,
10024                                    "sending notifies (serial %u)",
10025                                    serial);
10026                         loggednotify = ISC_TRUE;
10027                 }
10028                 notify = NULL;
10029         }
10030         UNLOCK_ZONE(zone);
10031
10032         if (notifytype == dns_notifytype_explicit)
10033                 goto cleanup3;
10034
10035         /*
10036          * Process NS RRset to generate notifies.
10037          */
10038
10039         dns_rdataset_init(&nsrdset);
10040         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
10041                                      dns_rdatatype_none, 0, &nsrdset, NULL);
10042         if (result != ISC_R_SUCCESS)
10043                 goto cleanup3;
10044
10045         result = dns_rdataset_first(&nsrdset);
10046         while (result == ISC_R_SUCCESS) {
10047                 dns_rdataset_current(&nsrdset, &rdata);
10048                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
10049                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10050                 dns_rdata_reset(&rdata);
10051                 /*
10052                  * Don't notify the master server unless explicitly
10053                  * configured to do so.
10054                  */
10055                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
10056                     dns_name_compare(&master, &ns.name) == 0) {
10057                         result = dns_rdataset_next(&nsrdset);
10058                         continue;
10059                 }
10060
10061                 if (!loggednotify) {
10062                         notify_log(zone, ISC_LOG_INFO,
10063                                    "sending notifies (serial %u)",
10064                                    serial);
10065                         loggednotify = ISC_TRUE;
10066                 }
10067
10068                 LOCK_ZONE(zone);
10069                 isqueued = notify_isqueued(zone, &ns.name, NULL);
10070                 UNLOCK_ZONE(zone);
10071                 if (isqueued) {
10072                         result = dns_rdataset_next(&nsrdset);
10073                         continue;
10074                 }
10075                 result = notify_create(zone->mctx, flags, &notify);
10076                 if (result != ISC_R_SUCCESS)
10077                         continue;
10078                 dns_zone_iattach(zone, &notify->zone);
10079                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
10080                 if (result != ISC_R_SUCCESS) {
10081                         LOCK_ZONE(zone);
10082                         notify_destroy(notify, ISC_TRUE);
10083                         UNLOCK_ZONE(zone);
10084                         continue;
10085                 }
10086                 LOCK_ZONE(zone);
10087                 ISC_LIST_APPEND(zone->notifies, notify, link);
10088                 UNLOCK_ZONE(zone);
10089                 notify_find_address(notify);
10090                 notify = NULL;
10091                 result = dns_rdataset_next(&nsrdset);
10092         }
10093         dns_rdataset_disassociate(&nsrdset);
10094
10095  cleanup3:
10096         if (dns_name_dynamic(&master))
10097                 dns_name_free(&master, zone->mctx);
10098  cleanup2:
10099         dns_db_detachnode(zonedb, &node);
10100  cleanup1:
10101         dns_db_closeversion(zonedb, &version, ISC_FALSE);
10102         dns_db_detach(&zonedb);
10103 }
10104
10105 /***
10106  *** Private
10107  ***/
10108
10109 static inline isc_result_t
10110 save_nsrrset(dns_message_t *message, dns_name_t *name,
10111              dns_db_t *db, dns_dbversion_t *version)
10112 {
10113         dns_rdataset_t *nsrdataset = NULL;
10114         dns_rdataset_t *rdataset = NULL;
10115         dns_dbnode_t *node = NULL;
10116         dns_rdata_ns_t ns;
10117         isc_result_t result;
10118         dns_rdata_t rdata = DNS_RDATA_INIT;
10119
10120         /*
10121          * Extract NS RRset from message.
10122          */
10123         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
10124                                       dns_rdatatype_ns, dns_rdatatype_none,
10125                                       NULL, &nsrdataset);
10126         if (result != ISC_R_SUCCESS)
10127                 goto fail;
10128
10129         /*
10130          * Add NS rdataset.
10131          */
10132         result = dns_db_findnode(db, name, ISC_TRUE, &node);
10133         if (result != ISC_R_SUCCESS)
10134                 goto fail;
10135         result = dns_db_addrdataset(db, node, version, 0,
10136                                     nsrdataset, 0, NULL);
10137         dns_db_detachnode(db, &node);
10138         if (result != ISC_R_SUCCESS)
10139                 goto fail;
10140         /*
10141          * Add glue rdatasets.
10142          */
10143         for (result = dns_rdataset_first(nsrdataset);
10144              result == ISC_R_SUCCESS;
10145              result = dns_rdataset_next(nsrdataset)) {
10146                 dns_rdataset_current(nsrdataset, &rdata);
10147                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
10148                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10149                 dns_rdata_reset(&rdata);
10150                 if (!dns_name_issubdomain(&ns.name, name))
10151                         continue;
10152                 rdataset = NULL;
10153                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10154                                               &ns.name, dns_rdatatype_aaaa,
10155                                               dns_rdatatype_none, NULL,
10156                                               &rdataset);
10157                 if (result == ISC_R_SUCCESS) {
10158                         result = dns_db_findnode(db, &ns.name,
10159                                                  ISC_TRUE, &node);
10160                         if (result != ISC_R_SUCCESS)
10161                                 goto fail;
10162                         result = dns_db_addrdataset(db, node, version, 0,
10163                                                     rdataset, 0, NULL);
10164                         dns_db_detachnode(db, &node);
10165                         if (result != ISC_R_SUCCESS)
10166                                 goto fail;
10167                 }
10168                 rdataset = NULL;
10169                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10170                                               &ns.name, dns_rdatatype_a,
10171                                               dns_rdatatype_none, NULL,
10172                                               &rdataset);
10173                 if (result == ISC_R_SUCCESS) {
10174                         result = dns_db_findnode(db, &ns.name,
10175                                                  ISC_TRUE, &node);
10176                         if (result != ISC_R_SUCCESS)
10177                                 goto fail;
10178                         result = dns_db_addrdataset(db, node, version, 0,
10179                                                     rdataset, 0, NULL);
10180                         dns_db_detachnode(db, &node);
10181                         if (result != ISC_R_SUCCESS)
10182                                 goto fail;
10183                 }
10184         }
10185         if (result != ISC_R_NOMORE)
10186                 goto fail;
10187
10188         return (ISC_R_SUCCESS);
10189
10190 fail:
10191         return (result);
10192 }
10193
10194 static void
10195 stub_callback(isc_task_t *task, isc_event_t *event) {
10196         const char me[] = "stub_callback";
10197         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10198         dns_stub_t *stub = NULL;
10199         dns_message_t *msg = NULL;
10200         dns_zone_t *zone = NULL;
10201         char master[ISC_SOCKADDR_FORMATSIZE];
10202         char source[ISC_SOCKADDR_FORMATSIZE];
10203         isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
10204         isc_result_t result;
10205         isc_time_t now;
10206         isc_boolean_t exiting = ISC_FALSE;
10207         isc_interval_t i;
10208         unsigned int j, soacount;
10209
10210         stub = revent->ev_arg;
10211         INSIST(DNS_STUB_VALID(stub));
10212
10213         UNUSED(task);
10214
10215         zone = stub->zone;
10216
10217         ENTER;
10218
10219         TIME_NOW(&now);
10220
10221         LOCK_ZONE(zone);
10222
10223         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10224                 zone_debuglog(zone, me, 1, "exiting");
10225                 exiting = ISC_TRUE;
10226                 goto next_master;
10227         }
10228
10229         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10230         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10231
10232         if (revent->result != ISC_R_SUCCESS) {
10233                 if (revent->result == ISC_R_TIMEDOUT &&
10234                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10235                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10236                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10237                                      "refreshing stub: timeout retrying "
10238                                      " without EDNS master %s (source %s)",
10239                                      master, source);
10240                         goto same_master;
10241                 }
10242                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
10243                                            &zone->sourceaddr, &now);
10244                 dns_zone_log(zone, ISC_LOG_INFO,
10245                              "could not refresh stub from master %s"
10246                              " (source %s): %s", master, source,
10247                              dns_result_totext(revent->result));
10248                 goto next_master;
10249         }
10250
10251         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10252         if (result != ISC_R_SUCCESS)
10253                 goto next_master;
10254
10255         result = dns_request_getresponse(revent->request, msg, 0);
10256         if (result != ISC_R_SUCCESS)
10257                 goto next_master;
10258
10259         /*
10260          * Unexpected rcode.
10261          */
10262         if (msg->rcode != dns_rcode_noerror) {
10263                 char rcode[128];
10264                 isc_buffer_t rb;
10265
10266                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10267                 (void)dns_rcode_totext(msg->rcode, &rb);
10268
10269                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10270                     (msg->rcode == dns_rcode_servfail ||
10271                      msg->rcode == dns_rcode_notimp ||
10272                      msg->rcode == dns_rcode_formerr)) {
10273                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10274                                      "refreshing stub: rcode (%.*s) retrying "
10275                                      "without EDNS master %s (source %s)",
10276                                      (int)rb.used, rcode, master, source);
10277                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10278                         goto same_master;
10279                 }
10280
10281                 dns_zone_log(zone, ISC_LOG_INFO,
10282                              "refreshing stub: "
10283                              "unexpected rcode (%.*s) from %s (source %s)",
10284                              (int)rb.used, rcode, master, source);
10285                 goto next_master;
10286         }
10287
10288         /*
10289          * We need complete messages.
10290          */
10291         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10292                 if (dns_request_usedtcp(revent->request)) {
10293                         dns_zone_log(zone, ISC_LOG_INFO,
10294                                      "refreshing stub: truncated TCP "
10295                                      "response from master %s (source %s)",
10296                                      master, source);
10297                         goto next_master;
10298                 }
10299                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10300                 goto same_master;
10301         }
10302
10303         /*
10304          * If non-auth log and next master.
10305          */
10306         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10307                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10308                              "non-authoritative answer from "
10309                              "master %s (source %s)", master, source);
10310                 goto next_master;
10311         }
10312
10313         /*
10314          * Sanity checks.
10315          */
10316         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10317         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
10318
10319         if (cnamecnt != 0) {
10320                 dns_zone_log(zone, ISC_LOG_INFO,
10321                              "refreshing stub: unexpected CNAME response "
10322                              "from master %s (source %s)", master, source);
10323                 goto next_master;
10324         }
10325
10326         if (nscnt == 0) {
10327                 dns_zone_log(zone, ISC_LOG_INFO,
10328                              "refreshing stub: no NS records in response "
10329                              "from master %s (source %s)", master, source);
10330                 goto next_master;
10331         }
10332
10333         /*
10334          * Save answer.
10335          */
10336         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
10337         if (result != ISC_R_SUCCESS) {
10338                 dns_zone_log(zone, ISC_LOG_INFO,
10339                              "refreshing stub: unable to save NS records "
10340                              "from master %s (source %s)", master, source);
10341                 goto next_master;
10342         }
10343
10344         /*
10345          * Tidy up.
10346          */
10347         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
10348         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
10349         if (zone->db == NULL)
10350                 zone_attachdb(zone, stub->db);
10351         result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
10352                                   &refresh, &retry, &expire, NULL, NULL);
10353         if (result == ISC_R_SUCCESS && soacount > 0U) {
10354                 zone->refresh = RANGE(refresh, zone->minrefresh,
10355                                       zone->maxrefresh);
10356                 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
10357                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
10358                                      DNS_MAX_EXPIRE);
10359                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10360         }
10361         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
10362         dns_db_detach(&stub->db);
10363
10364         dns_message_destroy(&msg);
10365         isc_event_free(&event);
10366         dns_request_destroy(&zone->request);
10367
10368         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10369         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10370         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10371         isc_interval_set(&i, zone->expire, 0);
10372         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10373
10374         if (zone->masterfile != NULL)
10375                 zone_needdump(zone, 0);
10376
10377         zone_settimer(zone, &now);
10378         goto free_stub;
10379
10380  next_master:
10381         if (stub->version != NULL)
10382                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
10383         if (stub->db != NULL)
10384                 dns_db_detach(&stub->db);
10385         if (msg != NULL)
10386                 dns_message_destroy(&msg);
10387         isc_event_free(&event);
10388         dns_request_destroy(&zone->request);
10389         /*
10390          * Skip to next failed / untried master.
10391          */
10392         do {
10393                 zone->curmaster++;
10394         } while (zone->curmaster < zone->masterscnt &&
10395                  zone->mastersok[zone->curmaster]);
10396         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10397         if (exiting || zone->curmaster >= zone->masterscnt) {
10398                 isc_boolean_t done = ISC_TRUE;
10399                 if (!exiting &&
10400                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10401                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10402                         /*
10403                          * Did we get a good answer from all the masters?
10404                          */
10405                         for (j = 0; j < zone->masterscnt; j++)
10406                                 if (zone->mastersok[j] == ISC_FALSE) {
10407                                         done = ISC_FALSE;
10408                                         break;
10409                                 }
10410                 } else
10411                         done = ISC_TRUE;
10412                 if (!done) {
10413                         zone->curmaster = 0;
10414                         /*
10415                          * Find the next failed master.
10416                          */
10417                         while (zone->curmaster < zone->masterscnt &&
10418                                zone->mastersok[zone->curmaster])
10419                                 zone->curmaster++;
10420                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10421                 } else {
10422                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10423
10424                         zone_settimer(zone, &now);
10425                         goto free_stub;
10426                 }
10427         }
10428         queue_soa_query(zone);
10429         goto free_stub;
10430
10431  same_master:
10432         if (msg != NULL)
10433                 dns_message_destroy(&msg);
10434         isc_event_free(&event);
10435         dns_request_destroy(&zone->request);
10436         ns_query(zone, NULL, stub);
10437         UNLOCK_ZONE(zone);
10438         goto done;
10439
10440  free_stub:
10441         UNLOCK_ZONE(zone);
10442         stub->magic = 0;
10443         dns_zone_idetach(&stub->zone);
10444         INSIST(stub->db == NULL);
10445         INSIST(stub->version == NULL);
10446         isc_mem_put(stub->mctx, stub, sizeof(*stub));
10447
10448  done:
10449         INSIST(event == NULL);
10450         return;
10451 }
10452
10453 /*
10454  * An SOA query has finished (successfully or not).
10455  */
10456 static void
10457 refresh_callback(isc_task_t *task, isc_event_t *event) {
10458         const char me[] = "refresh_callback";
10459         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10460         dns_zone_t *zone;
10461         dns_message_t *msg = NULL;
10462         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
10463         isc_time_t now;
10464         char master[ISC_SOCKADDR_FORMATSIZE];
10465         char source[ISC_SOCKADDR_FORMATSIZE];
10466         dns_rdataset_t *rdataset = NULL;
10467         dns_rdata_t rdata = DNS_RDATA_INIT;
10468         dns_rdata_soa_t soa;
10469         isc_result_t result;
10470         isc_uint32_t serial, oldserial = 0;
10471         unsigned int j;
10472         isc_boolean_t do_queue_xfrin = ISC_FALSE;
10473
10474         zone = revent->ev_arg;
10475         INSIST(DNS_ZONE_VALID(zone));
10476
10477         UNUSED(task);
10478
10479         ENTER;
10480
10481         TIME_NOW(&now);
10482
10483         LOCK_ZONE(zone);
10484
10485         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10486                 isc_event_free(&event);
10487                 dns_request_destroy(&zone->request);
10488                 goto detach;
10489         }
10490
10491         /*
10492          * if timeout log and next master;
10493          */
10494
10495         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10496         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10497
10498         if (revent->result != ISC_R_SUCCESS) {
10499                 if (revent->result == ISC_R_TIMEDOUT &&
10500                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10501                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10502                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10503                                      "refresh: timeout retrying without EDNS "
10504                                      "master %s (source %s)", master, source);
10505                         goto same_master;
10506                 }
10507                 if (revent->result == ISC_R_TIMEDOUT &&
10508                     !dns_request_usedtcp(revent->request)) {
10509                         dns_zone_log(zone, ISC_LOG_INFO,
10510                                      "refresh: retry limit for "
10511                                      "master %s exceeded (source %s)",
10512                                      master, source);
10513                         /* Try with slave with TCP. */
10514                         if ((zone->type == dns_zone_slave ||
10515                              zone->type == dns_zone_redirect) &&
10516                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
10517                                 if (!dns_zonemgr_unreachable(zone->zmgr,
10518                                                              &zone->masteraddr,
10519                                                              &zone->sourceaddr,
10520                                                              &now))
10521                                 {
10522                                         DNS_ZONE_SETFLAG(zone,
10523                                                      DNS_ZONEFLG_SOABEFOREAXFR);
10524                                         goto tcp_transfer;
10525                                 }
10526                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10527                                              "refresh: skipped tcp fallback "
10528                                              "as master %s (source %s) is "
10529                                              "unreachable (cached)",
10530                                               master, source);
10531                         }
10532                 } else
10533                         dns_zone_log(zone, ISC_LOG_INFO,
10534                                      "refresh: failure trying master "
10535                                      "%s (source %s): %s", master, source,
10536                                      dns_result_totext(revent->result));
10537                 goto next_master;
10538         }
10539
10540         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10541         if (result != ISC_R_SUCCESS)
10542                 goto next_master;
10543         result = dns_request_getresponse(revent->request, msg, 0);
10544         if (result != ISC_R_SUCCESS) {
10545                 dns_zone_log(zone, ISC_LOG_INFO,
10546                              "refresh: failure trying master "
10547                              "%s (source %s): %s", master, source,
10548                              dns_result_totext(result));
10549                 goto next_master;
10550         }
10551
10552         /*
10553          * Unexpected rcode.
10554          */
10555         if (msg->rcode != dns_rcode_noerror) {
10556                 char rcode[128];
10557                 isc_buffer_t rb;
10558
10559                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10560                 (void)dns_rcode_totext(msg->rcode, &rb);
10561
10562                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10563                     (msg->rcode == dns_rcode_servfail ||
10564                      msg->rcode == dns_rcode_notimp ||
10565                      msg->rcode == dns_rcode_formerr)) {
10566                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10567                                      "refresh: rcode (%.*s) retrying without "
10568                                      "EDNS master %s (source %s)",
10569                                      (int)rb.used, rcode, master, source);
10570                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10571                         goto same_master;
10572                 }
10573                 dns_zone_log(zone, ISC_LOG_INFO,
10574                              "refresh: unexpected rcode (%.*s) from "
10575                              "master %s (source %s)", (int)rb.used, rcode,
10576                              master, source);
10577                 /*
10578                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
10579                  */
10580                 if (msg->rcode == dns_rcode_refused &&
10581                     (zone->type == dns_zone_slave ||
10582                      zone->type == dns_zone_redirect))
10583                         goto tcp_transfer;
10584                 goto next_master;
10585         }
10586
10587         /*
10588          * If truncated punt to zone transfer which will query again.
10589          */
10590         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10591                 if (zone->type == dns_zone_slave ||
10592                     zone->type == dns_zone_redirect) {
10593                         dns_zone_log(zone, ISC_LOG_INFO,
10594                                      "refresh: truncated UDP answer, "
10595                                      "initiating TCP zone xfer "
10596                                      "for master %s (source %s)",
10597                                      master, source);
10598                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
10599                         goto tcp_transfer;
10600                 } else {
10601                         INSIST(zone->type == dns_zone_stub);
10602                         if (dns_request_usedtcp(revent->request)) {
10603                                 dns_zone_log(zone, ISC_LOG_INFO,
10604                                              "refresh: truncated TCP response "
10605                                              "from master %s (source %s)",
10606                                              master, source);
10607                                 goto next_master;
10608                         }
10609                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10610                         goto same_master;
10611                 }
10612         }
10613
10614         /*
10615          * if non-auth log and next master;
10616          */
10617         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10618                 dns_zone_log(zone, ISC_LOG_INFO,
10619                              "refresh: non-authoritative answer from "
10620                              "master %s (source %s)", master, source);
10621                 goto next_master;
10622         }
10623
10624         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10625         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
10626         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
10627         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
10628                                  dns_rdatatype_soa);
10629
10630         /*
10631          * There should not be a CNAME record at top of zone.
10632          */
10633         if (cnamecnt != 0) {
10634                 dns_zone_log(zone, ISC_LOG_INFO,
10635                              "refresh: CNAME at top of zone "
10636                              "in master %s (source %s)", master, source);
10637                 goto next_master;
10638         }
10639
10640         /*
10641          * if referral log and next master;
10642          */
10643         if (soacnt == 0 && soacount == 0 && nscount != 0) {
10644                 dns_zone_log(zone, ISC_LOG_INFO,
10645                              "refresh: referral response "
10646                              "from master %s (source %s)", master, source);
10647                 goto next_master;
10648         }
10649
10650         /*
10651          * if nodata log and next master;
10652          */
10653         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
10654                 dns_zone_log(zone, ISC_LOG_INFO,
10655                              "refresh: NODATA response "
10656                              "from master %s (source %s)", master, source);
10657                 goto next_master;
10658         }
10659
10660         /*
10661          * Only one soa at top of zone.
10662          */
10663         if (soacnt != 1) {
10664                 dns_zone_log(zone, ISC_LOG_INFO,
10665                              "refresh: answer SOA count (%d) != 1 "
10666                              "from master %s (source %s)",
10667                              soacnt, master, source);
10668                 goto next_master;
10669         }
10670
10671         /*
10672          * Extract serial
10673          */
10674         rdataset = NULL;
10675         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
10676                                       dns_rdatatype_soa, dns_rdatatype_none,
10677                                       NULL, &rdataset);
10678         if (result != ISC_R_SUCCESS) {
10679                 dns_zone_log(zone, ISC_LOG_INFO,
10680                              "refresh: unable to get SOA record "
10681                              "from master %s (source %s)", master, source);
10682                 goto next_master;
10683         }
10684
10685         result = dns_rdataset_first(rdataset);
10686         if (result != ISC_R_SUCCESS) {
10687                 dns_zone_log(zone, ISC_LOG_INFO,
10688                              "refresh: dns_rdataset_first() failed");
10689                 goto next_master;
10690         }
10691
10692         dns_rdataset_current(rdataset, &rdata);
10693         result = dns_rdata_tostruct(&rdata, &soa, NULL);
10694         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10695
10696         serial = soa.serial;
10697         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10698                 unsigned int soacount;
10699                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
10700                                           &oldserial, NULL, NULL, NULL, NULL,
10701                                           NULL);
10702                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10703                 RUNTIME_CHECK(soacount > 0U);
10704                 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
10705                               serial, oldserial);
10706         } else
10707                 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
10708                               serial);
10709
10710         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
10711             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
10712             isc_serial_gt(serial, oldserial)) {
10713                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
10714                                             &zone->sourceaddr, &now))
10715                 {
10716                         dns_zone_log(zone, ISC_LOG_INFO,
10717                                      "refresh: skipping %s as master %s "
10718                                      "(source %s) is unreachable (cached)",
10719                                      (zone->type == dns_zone_slave ||
10720                                       zone->type == dns_zone_redirect) ?
10721                                      "zone transfer" : "NS query",
10722                                      master, source);
10723                         goto next_master;
10724                 }
10725  tcp_transfer:
10726                 isc_event_free(&event);
10727                 dns_request_destroy(&zone->request);
10728                 if (zone->type == dns_zone_slave ||
10729                     zone->type == dns_zone_redirect) {
10730                         do_queue_xfrin = ISC_TRUE;
10731                 } else {
10732                         INSIST(zone->type == dns_zone_stub);
10733                         ns_query(zone, rdataset, NULL);
10734                 }
10735                 if (msg != NULL)
10736                         dns_message_destroy(&msg);
10737         } else if (isc_serial_eq(soa.serial, oldserial)) {
10738                 if (zone->masterfile != NULL) {
10739                         result = ISC_R_FAILURE;
10740                         if (zone->journal != NULL)
10741                                 result = isc_file_settime(zone->journal, &now);
10742                         if (result == ISC_R_SUCCESS &&
10743                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10744                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10745                                 result = isc_file_settime(zone->masterfile,
10746                                                           &now);
10747                         } else if (result != ISC_R_SUCCESS)
10748                                 result = isc_file_settime(zone->masterfile,
10749                                                           &now);
10750                         /* Someone removed the file from underneath us! */
10751                         if (result == ISC_R_FILENOTFOUND) {
10752                                 zone_needdump(zone, DNS_DUMP_DELAY);
10753                         } else if (result != ISC_R_SUCCESS)
10754                                 dns_zone_log(zone, ISC_LOG_ERROR,
10755                                              "refresh: could not set file "
10756                                              "modification time of '%s': %s",
10757                                              zone->masterfile,
10758                                              dns_result_totext(result));
10759                 }
10760                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10761                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10762                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10763                 goto next_master;
10764         } else {
10765                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
10766                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
10767                                      "received from master %s < ours (%u)",
10768                                      soa.serial, master, oldserial);
10769                 else
10770                         zone_debuglog(zone, me, 1, "ahead");
10771                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10772                 goto next_master;
10773         }
10774         if (msg != NULL)
10775                 dns_message_destroy(&msg);
10776         goto detach;
10777
10778  next_master:
10779         if (msg != NULL)
10780                 dns_message_destroy(&msg);
10781         isc_event_free(&event);
10782         dns_request_destroy(&zone->request);
10783         /*
10784          * Skip to next failed / untried master.
10785          */
10786         do {
10787                 zone->curmaster++;
10788         } while (zone->curmaster < zone->masterscnt &&
10789                  zone->mastersok[zone->curmaster]);
10790         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10791         if (zone->curmaster >= zone->masterscnt) {
10792                 isc_boolean_t done = ISC_TRUE;
10793                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10794                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10795                         /*
10796                          * Did we get a good answer from all the masters?
10797                          */
10798                         for (j = 0; j < zone->masterscnt; j++)
10799                                 if (zone->mastersok[j] == ISC_FALSE) {
10800                                         done = ISC_FALSE;
10801                                         break;
10802                                 }
10803                 } else
10804                         done = ISC_TRUE;
10805                 if (!done) {
10806                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10807                         zone->curmaster = 0;
10808                         /*
10809                          * Find the next failed master.
10810                          */
10811                         while (zone->curmaster < zone->masterscnt &&
10812                                zone->mastersok[zone->curmaster])
10813                                 zone->curmaster++;
10814                         goto requeue;
10815                 }
10816                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10817                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
10818                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10819                         zone->refreshtime = now;
10820                 }
10821                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10822                 zone_settimer(zone, &now);
10823                 goto detach;
10824         }
10825
10826  requeue:
10827         queue_soa_query(zone);
10828         goto detach;
10829
10830  same_master:
10831         if (msg != NULL)
10832                 dns_message_destroy(&msg);
10833         isc_event_free(&event);
10834         dns_request_destroy(&zone->request);
10835         queue_soa_query(zone);
10836
10837  detach:
10838         UNLOCK_ZONE(zone);
10839         if (do_queue_xfrin)
10840                 queue_xfrin(zone);
10841         dns_zone_idetach(&zone);
10842         return;
10843 }
10844
10845 static void
10846 queue_soa_query(dns_zone_t *zone) {
10847         const char me[] = "queue_soa_query";
10848         isc_event_t *e;
10849         dns_zone_t *dummy = NULL;
10850         isc_result_t result;
10851
10852         ENTER;
10853         /*
10854          * Locked by caller
10855          */
10856         REQUIRE(LOCKED_ZONE(zone));
10857
10858         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10859                 cancel_refresh(zone);
10860                 return;
10861         }
10862
10863         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
10864                                soa_query, zone, sizeof(isc_event_t));
10865         if (e == NULL) {
10866                 cancel_refresh(zone);
10867                 return;
10868         }
10869
10870         /*
10871          * Attach so that we won't clean up
10872          * until the event is delivered.
10873          */
10874         zone_iattach(zone, &dummy);
10875
10876         e->ev_arg = zone;
10877         e->ev_sender = NULL;
10878         result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
10879         if (result != ISC_R_SUCCESS) {
10880                 zone_idetach(&dummy);
10881                 isc_event_free(&e);
10882                 cancel_refresh(zone);
10883         }
10884 }
10885
10886 static inline isc_result_t
10887 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
10888              dns_message_t **messagep)
10889 {
10890         dns_message_t *message = NULL;
10891         dns_name_t *qname = NULL;
10892         dns_rdataset_t *qrdataset = NULL;
10893         isc_result_t result;
10894
10895         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10896                                     &message);
10897         if (result != ISC_R_SUCCESS)
10898                 goto cleanup;
10899
10900         message->opcode = dns_opcode_query;
10901         message->rdclass = zone->rdclass;
10902
10903         result = dns_message_gettempname(message, &qname);
10904         if (result != ISC_R_SUCCESS)
10905                 goto cleanup;
10906
10907         result = dns_message_gettemprdataset(message, &qrdataset);
10908         if (result != ISC_R_SUCCESS)
10909                 goto cleanup;
10910
10911         /*
10912          * Make question.
10913          */
10914         dns_name_init(qname, NULL);
10915         dns_name_clone(&zone->origin, qname);
10916         dns_rdataset_init(qrdataset);
10917         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
10918         ISC_LIST_APPEND(qname->list, qrdataset, link);
10919         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
10920
10921         *messagep = message;
10922         return (ISC_R_SUCCESS);
10923
10924  cleanup:
10925         if (qname != NULL)
10926                 dns_message_puttempname(message, &qname);
10927         if (qrdataset != NULL)
10928                 dns_message_puttemprdataset(message, &qrdataset);
10929         if (message != NULL)
10930                 dns_message_destroy(&message);
10931         return (result);
10932 }
10933
10934 static isc_result_t
10935 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
10936         dns_rdataset_t *rdataset = NULL;
10937         dns_rdatalist_t *rdatalist = NULL;
10938         dns_rdata_t *rdata = NULL;
10939         isc_result_t result;
10940
10941         result = dns_message_gettemprdatalist(message, &rdatalist);
10942         if (result != ISC_R_SUCCESS)
10943                 goto cleanup;
10944         result = dns_message_gettemprdata(message, &rdata);
10945         if (result != ISC_R_SUCCESS)
10946                 goto cleanup;
10947         result = dns_message_gettemprdataset(message, &rdataset);
10948         if (result != ISC_R_SUCCESS)
10949                 goto cleanup;
10950         dns_rdataset_init(rdataset);
10951
10952         rdatalist->type = dns_rdatatype_opt;
10953         rdatalist->covers = 0;
10954
10955         /*
10956          * Set Maximum UDP buffer size.
10957          */
10958         rdatalist->rdclass = udpsize;
10959
10960         /*
10961          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
10962          */
10963         rdatalist->ttl = 0;
10964
10965         /* Set EDNS options if applicable */
10966         if (reqnsid) {
10967                 unsigned char data[4];
10968                 isc_buffer_t buf;
10969
10970                 isc_buffer_init(&buf, data, sizeof(data));
10971                 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
10972                 isc_buffer_putuint16(&buf, 0);
10973                 rdata->data = data;
10974                 rdata->length = sizeof(data);
10975         } else {
10976                 rdata->data = NULL;
10977                 rdata->length = 0;
10978         }
10979
10980         rdata->rdclass = rdatalist->rdclass;
10981         rdata->type = rdatalist->type;
10982         rdata->flags = 0;
10983
10984         ISC_LIST_INIT(rdatalist->rdata);
10985         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
10986         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
10987                       == ISC_R_SUCCESS);
10988
10989         return (dns_message_setopt(message, rdataset));
10990
10991  cleanup:
10992         if (rdatalist != NULL)
10993                 dns_message_puttemprdatalist(message, &rdatalist);
10994         if (rdataset != NULL)
10995                 dns_message_puttemprdataset(message, &rdataset);
10996         if (rdata != NULL)
10997                 dns_message_puttemprdata(message, &rdata);
10998
10999         return (result);
11000 }
11001
11002 static void
11003 soa_query(isc_task_t *task, isc_event_t *event) {
11004         const char me[] = "soa_query";
11005         isc_result_t result = ISC_R_FAILURE;
11006         dns_message_t *message = NULL;
11007         dns_zone_t *zone = event->ev_arg;
11008         dns_zone_t *dummy = NULL;
11009         isc_netaddr_t masterip;
11010         dns_tsigkey_t *key = NULL;
11011         isc_uint32_t options;
11012         isc_boolean_t cancel = ISC_TRUE;
11013         int timeout;
11014         isc_boolean_t have_xfrsource, reqnsid;
11015         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11016
11017         REQUIRE(DNS_ZONE_VALID(zone));
11018
11019         UNUSED(task);
11020
11021         ENTER;
11022
11023         LOCK_ZONE(zone);
11024         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
11025             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11026             zone->view->requestmgr == NULL) {
11027                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11028                         cancel = ISC_FALSE;
11029                 goto cleanup;
11030         }
11031
11032         /*
11033          * XXX Optimisation: Create message when zone is setup and reuse.
11034          */
11035         result = create_query(zone, dns_rdatatype_soa, &message);
11036         if (result != ISC_R_SUCCESS)
11037                 goto cleanup;
11038
11039  again:
11040         INSIST(zone->masterscnt > 0);
11041         INSIST(zone->curmaster < zone->masterscnt);
11042
11043         zone->masteraddr = zone->masters[zone->curmaster];
11044
11045         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11046         /*
11047          * First, look for a tsig key in the master statement, then
11048          * try for a server key.
11049          */
11050         if ((zone->masterkeynames != NULL) &&
11051             (zone->masterkeynames[zone->curmaster] != NULL)) {
11052                 dns_view_t *view = dns_zone_getview(zone);
11053                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11054                 result = dns_view_gettsig(view, keyname, &key);
11055                 if (result != ISC_R_SUCCESS) {
11056                         char namebuf[DNS_NAME_FORMATSIZE];
11057                         dns_name_format(keyname, namebuf, sizeof(namebuf));
11058                         dns_zone_log(zone, ISC_LOG_ERROR,
11059                                      "unable to find key: %s", namebuf);
11060                         goto skip_master;
11061                 }
11062         }
11063         if (key == NULL) {
11064                 result = dns_view_getpeertsig(zone->view, &masterip, &key);
11065                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11066                         char addrbuf[ISC_NETADDR_FORMATSIZE];
11067                         isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
11068                         dns_zone_log(zone, ISC_LOG_ERROR,
11069                                      "unable to find TSIG key for %s", addrbuf);
11070                         goto skip_master;
11071                 }
11072         }
11073
11074         have_xfrsource = ISC_FALSE;
11075         reqnsid = zone->view->requestnsid;
11076         if (zone->view->peers != NULL) {
11077                 dns_peer_t *peer = NULL;
11078                 isc_boolean_t edns;
11079                 result = dns_peerlist_peerbyaddr(zone->view->peers,
11080                                                  &masterip, &peer);
11081                 if (result == ISC_R_SUCCESS) {
11082                         result = dns_peer_getsupportedns(peer, &edns);
11083                         if (result == ISC_R_SUCCESS && !edns)
11084                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11085                         result = dns_peer_gettransfersource(peer,
11086                                                             &zone->sourceaddr);
11087                         if (result == ISC_R_SUCCESS)
11088                                 have_xfrsource = ISC_TRUE;
11089                         if (zone->view->resolver != NULL)
11090                                 udpsize =
11091                                   dns_resolver_getudpsize(zone->view->resolver);
11092                         (void)dns_peer_getudpsize(peer, &udpsize);
11093                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
11094                 }
11095         }
11096
11097         switch (isc_sockaddr_pf(&zone->masteraddr)) {
11098         case PF_INET:
11099                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11100                         if (isc_sockaddr_equal(&zone->altxfrsource4,
11101                                                &zone->xfrsource4))
11102                                 goto skip_master;
11103                         zone->sourceaddr = zone->altxfrsource4;
11104                 } else if (!have_xfrsource)
11105                         zone->sourceaddr = zone->xfrsource4;
11106                 break;
11107         case PF_INET6:
11108                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11109                         if (isc_sockaddr_equal(&zone->altxfrsource6,
11110                                                &zone->xfrsource6))
11111                                 goto skip_master;
11112                         zone->sourceaddr = zone->altxfrsource6;
11113                 } else if (!have_xfrsource)
11114                         zone->sourceaddr = zone->xfrsource6;
11115                 break;
11116         default:
11117                 result = ISC_R_NOTIMPLEMENTED;
11118                 goto cleanup;
11119         }
11120
11121         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
11122                   DNS_REQUESTOPT_TCP : 0;
11123
11124         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11125                 result = add_opt(message, udpsize, reqnsid);
11126                 if (result != ISC_R_SUCCESS)
11127                         zone_debuglog(zone, me, 1,
11128                                       "unable to add opt record: %s",
11129                                       dns_result_totext(result));
11130         }
11131
11132         zone_iattach(zone, &dummy);
11133         timeout = 15;
11134         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11135                 timeout = 30;
11136         result = dns_request_createvia2(zone->view->requestmgr, message,
11137                                         &zone->sourceaddr, &zone->masteraddr,
11138                                         options, key, timeout * 3, timeout,
11139                                         zone->task, refresh_callback, zone,
11140                                         &zone->request);
11141         if (result != ISC_R_SUCCESS) {
11142                 zone_idetach(&dummy);
11143                 zone_debuglog(zone, me, 1,
11144                               "dns_request_createvia2() failed: %s",
11145                               dns_result_totext(result));
11146                 goto cleanup;
11147         } else {
11148                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
11149                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
11150                 else
11151                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
11152         }
11153         cancel = ISC_FALSE;
11154
11155  cleanup:
11156         if (key != NULL)
11157                 dns_tsigkey_detach(&key);
11158         if (result != ISC_R_SUCCESS)
11159                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11160         if (message != NULL)
11161                 dns_message_destroy(&message);
11162         if (cancel)
11163                 cancel_refresh(zone);
11164         isc_event_free(&event);
11165         UNLOCK_ZONE(zone);
11166         dns_zone_idetach(&zone);
11167         return;
11168
11169  skip_master:
11170         if (key != NULL)
11171                 dns_tsigkey_detach(&key);
11172         /*
11173          * Skip to next failed / untried master.
11174          */
11175         do {
11176                 zone->curmaster++;
11177         } while (zone->curmaster < zone->masterscnt &&
11178                  zone->mastersok[zone->curmaster]);
11179         if (zone->curmaster < zone->masterscnt)
11180                 goto again;
11181         zone->curmaster = 0;
11182         goto cleanup;
11183 }
11184
11185 static void
11186 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
11187         const char me[] = "ns_query";
11188         isc_result_t result;
11189         dns_message_t *message = NULL;
11190         isc_netaddr_t masterip;
11191         dns_tsigkey_t *key = NULL;
11192         dns_dbnode_t *node = NULL;
11193         int timeout;
11194         isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
11195         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11196
11197         REQUIRE(DNS_ZONE_VALID(zone));
11198         REQUIRE(LOCKED_ZONE(zone));
11199         REQUIRE((soardataset != NULL && stub == NULL) ||
11200                 (soardataset == NULL && stub != NULL));
11201         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
11202
11203         ENTER;
11204
11205         if (stub == NULL) {
11206                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
11207                 if (stub == NULL)
11208                         goto cleanup;
11209                 stub->magic = STUB_MAGIC;
11210                 stub->mctx = zone->mctx;
11211                 stub->zone = NULL;
11212                 stub->db = NULL;
11213                 stub->version = NULL;
11214
11215                 /*
11216                  * Attach so that the zone won't disappear from under us.
11217                  */
11218                 zone_iattach(zone, &stub->zone);
11219
11220                 /*
11221                  * If a db exists we will update it, otherwise we create a
11222                  * new one and attach it to the zone once we have the NS
11223                  * RRset and glue.
11224                  */
11225                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11226                 if (zone->db != NULL) {
11227                         dns_db_attach(zone->db, &stub->db);
11228                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11229                 } else {
11230                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11231
11232                         INSIST(zone->db_argc >= 1);
11233                         result = dns_db_create(zone->mctx, zone->db_argv[0],
11234                                                &zone->origin, dns_dbtype_stub,
11235                                                zone->rdclass,
11236                                                zone->db_argc - 1,
11237                                                zone->db_argv + 1,
11238                                                &stub->db);
11239                         if (result != ISC_R_SUCCESS) {
11240                                 dns_zone_log(zone, ISC_LOG_ERROR,
11241                                              "refreshing stub: "
11242                                              "could not create "
11243                                              "database: %s",
11244                                              dns_result_totext(result));
11245                                 goto cleanup;
11246                         }
11247                         dns_db_settask(stub->db, zone->task);
11248                 }
11249
11250                 result = dns_db_newversion(stub->db, &stub->version);
11251                 if (result != ISC_R_SUCCESS) {
11252                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11253                                      "dns_db_newversion() failed: %s",
11254                                      dns_result_totext(result));
11255                         goto cleanup;
11256                 }
11257
11258                 /*
11259                  * Update SOA record.
11260                  */
11261                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
11262                                          &node);
11263                 if (result != ISC_R_SUCCESS) {
11264                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11265                                      "dns_db_findnode() failed: %s",
11266                                      dns_result_totext(result));
11267                         goto cleanup;
11268                 }
11269
11270                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
11271                                             soardataset, 0, NULL);
11272                 dns_db_detachnode(stub->db, &node);
11273                 if (result != ISC_R_SUCCESS) {
11274                         dns_zone_log(zone, ISC_LOG_INFO,
11275                                      "refreshing stub: "
11276                                      "dns_db_addrdataset() failed: %s",
11277                                      dns_result_totext(result));
11278                         goto cleanup;
11279                 }
11280         }
11281
11282         /*
11283          * XXX Optimisation: Create message when zone is setup and reuse.
11284          */
11285         result = create_query(zone, dns_rdatatype_ns, &message);
11286         INSIST(result == ISC_R_SUCCESS);
11287
11288         INSIST(zone->masterscnt > 0);
11289         INSIST(zone->curmaster < zone->masterscnt);
11290         zone->masteraddr = zone->masters[zone->curmaster];
11291
11292         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11293         /*
11294          * First, look for a tsig key in the master statement, then
11295          * try for a server key.
11296          */
11297         if ((zone->masterkeynames != NULL) &&
11298             (zone->masterkeynames[zone->curmaster] != NULL)) {
11299                 dns_view_t *view = dns_zone_getview(zone);
11300                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11301                 result = dns_view_gettsig(view, keyname, &key);
11302                 if (result != ISC_R_SUCCESS) {
11303                         char namebuf[DNS_NAME_FORMATSIZE];
11304                         dns_name_format(keyname, namebuf, sizeof(namebuf));
11305                         dns_zone_log(zone, ISC_LOG_ERROR,
11306                                      "unable to find key: %s", namebuf);
11307                 }
11308         }
11309         if (key == NULL)
11310                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
11311
11312         reqnsid = zone->view->requestnsid;
11313         if (zone->view->peers != NULL) {
11314                 dns_peer_t *peer = NULL;
11315                 isc_boolean_t edns;
11316                 result = dns_peerlist_peerbyaddr(zone->view->peers,
11317                                                  &masterip, &peer);
11318                 if (result == ISC_R_SUCCESS) {
11319                         result = dns_peer_getsupportedns(peer, &edns);
11320                         if (result == ISC_R_SUCCESS && !edns)
11321                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11322                         result = dns_peer_gettransfersource(peer,
11323                                                             &zone->sourceaddr);
11324                         if (result == ISC_R_SUCCESS)
11325                                 have_xfrsource = ISC_TRUE;
11326                         if (zone->view->resolver != NULL)
11327                                 udpsize =
11328                                   dns_resolver_getudpsize(zone->view->resolver);
11329                         (void)dns_peer_getudpsize(peer, &udpsize);
11330                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
11331                 }
11332
11333         }
11334         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11335                 result = add_opt(message, udpsize, reqnsid);
11336                 if (result != ISC_R_SUCCESS)
11337                         zone_debuglog(zone, me, 1,
11338                                       "unable to add opt record: %s",
11339                                       dns_result_totext(result));
11340         }
11341
11342         /*
11343          * Always use TCP so that we shouldn't truncate in additional section.
11344          */
11345         switch (isc_sockaddr_pf(&zone->masteraddr)) {
11346         case PF_INET:
11347                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11348                         zone->sourceaddr = zone->altxfrsource4;
11349                 else if (!have_xfrsource)
11350                         zone->sourceaddr = zone->xfrsource4;
11351                 break;
11352         case PF_INET6:
11353                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11354                         zone->sourceaddr = zone->altxfrsource6;
11355                 else if (!have_xfrsource)
11356                         zone->sourceaddr = zone->xfrsource6;
11357                 break;
11358         default:
11359                 result = ISC_R_NOTIMPLEMENTED;
11360                 POST(result);
11361                 goto cleanup;
11362         }
11363         timeout = 15;
11364         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11365                 timeout = 30;
11366         result = dns_request_createvia2(zone->view->requestmgr, message,
11367                                         &zone->sourceaddr, &zone->masteraddr,
11368                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
11369                                         timeout, zone->task, stub_callback,
11370                                         stub, &zone->request);
11371         if (result != ISC_R_SUCCESS) {
11372                 zone_debuglog(zone, me, 1,
11373                               "dns_request_createvia() failed: %s",
11374                               dns_result_totext(result));
11375                 goto cleanup;
11376         }
11377         dns_message_destroy(&message);
11378         goto unlock;
11379
11380  cleanup:
11381         cancel_refresh(zone);
11382         if (stub != NULL) {
11383                 stub->magic = 0;
11384                 if (stub->version != NULL)
11385                         dns_db_closeversion(stub->db, &stub->version,
11386                                             ISC_FALSE);
11387                 if (stub->db != NULL)
11388                         dns_db_detach(&stub->db);
11389                 if (stub->zone != NULL)
11390                         zone_idetach(&stub->zone);
11391                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
11392         }
11393         if (message != NULL)
11394                 dns_message_destroy(&message);
11395  unlock:
11396         if (key != NULL)
11397                 dns_tsigkey_detach(&key);
11398         return;
11399 }
11400
11401 /*
11402  * Handle the control event.  Note that although this event causes the zone
11403  * to shut down, it is not a shutdown event in the sense of the task library.
11404  */
11405 static void
11406 zone_shutdown(isc_task_t *task, isc_event_t *event) {
11407         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
11408         isc_boolean_t free_needed, linked = ISC_FALSE;
11409         dns_zone_t *raw = NULL, *secure = NULL;
11410
11411         UNUSED(task);
11412         REQUIRE(DNS_ZONE_VALID(zone));
11413         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
11414         INSIST(isc_refcount_current(&zone->erefs) == 0);
11415
11416         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
11417
11418         /*
11419          * Stop things being restarted after we cancel them below.
11420          */
11421         LOCK_ZONE(zone);
11422         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
11423         UNLOCK_ZONE(zone);
11424
11425         /*
11426          * If we were waiting for xfrin quota, step out of
11427          * the queue.
11428          * If there's no zone manager, we can't be waiting for the
11429          * xfrin quota
11430          */
11431         if (zone->zmgr != NULL) {
11432                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11433                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
11434                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
11435                                         statelink);
11436                         linked = ISC_TRUE;
11437                         zone->statelist = NULL;
11438                 }
11439                 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
11440                         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
11441                                         statelink);
11442                         zone->statelist = NULL;
11443                         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
11444                 }
11445                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11446         }
11447
11448         /*
11449          * In task context, no locking required.  See zone_xfrdone().
11450          */
11451         if (zone->xfr != NULL)
11452                 dns_xfrin_shutdown(zone->xfr);
11453
11454         /* Safe to release the zone now */
11455         if (zone->zmgr != NULL)
11456                 dns_zonemgr_releasezone(zone->zmgr, zone);
11457
11458         LOCK_ZONE(zone);
11459         if (linked) {
11460                 INSIST(zone->irefs > 0);
11461                 zone->irefs--;
11462         }
11463         if (zone->request != NULL) {
11464                 dns_request_cancel(zone->request);
11465         }
11466
11467         if (zone->readio != NULL)
11468                 zonemgr_cancelio(zone->readio);
11469
11470         if (zone->lctx != NULL)
11471                 dns_loadctx_cancel(zone->lctx);
11472
11473         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11474             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11475                 if (zone->writeio != NULL)
11476                         zonemgr_cancelio(zone->writeio);
11477
11478                 if (zone->dctx != NULL)
11479                         dns_dumpctx_cancel(zone->dctx);
11480         }
11481
11482         notify_cancel(zone);
11483
11484         forward_cancel(zone);
11485
11486         if (zone->timer != NULL) {
11487                 isc_timer_detach(&zone->timer);
11488                 INSIST(zone->irefs > 0);
11489                 zone->irefs--;
11490         }
11491
11492         if (zone->view != NULL)
11493                 dns_view_weakdetach(&zone->view);
11494
11495         /*
11496          * We have now canceled everything set the flag to allow exit_check()
11497          * to succeed.  We must not unlock between setting this flag and
11498          * calling exit_check().
11499          */
11500         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
11501         free_needed = exit_check(zone);
11502         if (inline_secure(zone)) {
11503                 raw = zone->raw;
11504                 zone->raw = NULL;
11505         }
11506         if (inline_raw(zone)) {
11507                 secure = zone->secure;
11508                 zone->secure = NULL;
11509         }
11510         UNLOCK_ZONE(zone);
11511         if (raw != NULL)
11512                 dns_zone_detach(&raw);
11513         if (secure != NULL)
11514                 dns_zone_idetach(&secure);
11515         if (free_needed)
11516                 zone_free(zone);
11517 }
11518
11519 static void
11520 zone_timer(isc_task_t *task, isc_event_t *event) {
11521         const char me[] = "zone_timer";
11522         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
11523
11524         UNUSED(task);
11525         REQUIRE(DNS_ZONE_VALID(zone));
11526
11527         ENTER;
11528
11529         zone_maintenance(zone);
11530
11531         isc_event_free(&event);
11532 }
11533
11534 static void
11535 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
11536         const char me[] = "zone_settimer";
11537         isc_time_t next;
11538         isc_result_t result;
11539
11540         ENTER;
11541         REQUIRE(DNS_ZONE_VALID(zone));
11542         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11543                 return;
11544
11545         isc_time_settoepoch(&next);
11546
11547         switch (zone->type) {
11548         case dns_zone_redirect:
11549                 if (zone->masters != NULL)
11550                         goto treat_as_slave;
11551                 /* FALLTHROUGH */
11552
11553         case dns_zone_master:
11554                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
11555                         next = zone->notifytime;
11556                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11557                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11558                         INSIST(!isc_time_isepoch(&zone->dumptime));
11559                         if (isc_time_isepoch(&next) ||
11560                             isc_time_compare(&zone->dumptime, &next) < 0)
11561                                 next = zone->dumptime;
11562                 }
11563                 if (zone->type == dns_zone_redirect)
11564                         break;
11565                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
11566                     !isc_time_isepoch(&zone->refreshkeytime)) {
11567                         if (isc_time_isepoch(&next) ||
11568                             isc_time_compare(&zone->refreshkeytime, &next) < 0)
11569                                 next = zone->refreshkeytime;
11570                 }
11571                 if (!isc_time_isepoch(&zone->resigntime)) {
11572                         if (isc_time_isepoch(&next) ||
11573                             isc_time_compare(&zone->resigntime, &next) < 0)
11574                                 next = zone->resigntime;
11575                 }
11576                 if (!isc_time_isepoch(&zone->keywarntime)) {
11577                         if (isc_time_isepoch(&next) ||
11578                             isc_time_compare(&zone->keywarntime, &next) < 0)
11579                                 next = zone->keywarntime;
11580                 }
11581                 if (!isc_time_isepoch(&zone->signingtime)) {
11582                         if (isc_time_isepoch(&next) ||
11583                             isc_time_compare(&zone->signingtime, &next) < 0)
11584                                 next = zone->signingtime;
11585                 }
11586                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
11587                         if (isc_time_isepoch(&next) ||
11588                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
11589                                 next = zone->nsec3chaintime;
11590                 }
11591                 break;
11592
11593         case dns_zone_slave:
11594         treat_as_slave:
11595                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
11596                         next = zone->notifytime;
11597                 /* FALLTHROUGH */
11598
11599         case dns_zone_stub:
11600                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
11601                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
11602                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
11603                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
11604                         INSIST(!isc_time_isepoch(&zone->refreshtime));
11605                         if (isc_time_isepoch(&next) ||
11606                             isc_time_compare(&zone->refreshtime, &next) < 0)
11607                                 next = zone->refreshtime;
11608                 }
11609                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11610                     !isc_time_isepoch(&zone->expiretime)) {
11611                         if (isc_time_isepoch(&next) ||
11612                              isc_time_compare(&zone->expiretime, &next) < 0)
11613                                 next = zone->expiretime;
11614                 }
11615                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11616                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11617                         INSIST(!isc_time_isepoch(&zone->dumptime));
11618                         if (isc_time_isepoch(&next) ||
11619                             isc_time_compare(&zone->dumptime, &next) < 0)
11620                                 next = zone->dumptime;
11621                 }
11622                 break;
11623
11624         case dns_zone_key:
11625                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11626                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11627                         INSIST(!isc_time_isepoch(&zone->dumptime));
11628                         if (isc_time_isepoch(&next) ||
11629                             isc_time_compare(&zone->dumptime, &next) < 0)
11630                                 next = zone->dumptime;
11631                 }
11632                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
11633                         if (isc_time_isepoch(&next) ||
11634                             (!isc_time_isepoch(&zone->refreshkeytime) &&
11635                             isc_time_compare(&zone->refreshkeytime, &next) < 0))
11636                                 next = zone->refreshkeytime;
11637                 }
11638                 break;
11639
11640         default:
11641                 break;
11642         }
11643
11644         if (isc_time_isepoch(&next)) {
11645                 zone_debuglog(zone, me, 10, "settimer inactive");
11646                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
11647                                           NULL, NULL, ISC_TRUE);
11648                 if (result != ISC_R_SUCCESS)
11649                         dns_zone_log(zone, ISC_LOG_ERROR,
11650                                      "could not deactivate zone timer: %s",
11651                                      isc_result_totext(result));
11652         } else {
11653                 if (isc_time_compare(&next, now) <= 0)
11654                         next = *now;
11655                 result = isc_timer_reset(zone->timer, isc_timertype_once,
11656                                          &next, NULL, ISC_TRUE);
11657                 if (result != ISC_R_SUCCESS)
11658                         dns_zone_log(zone, ISC_LOG_ERROR,
11659                                      "could not reset zone timer: %s",
11660                                      isc_result_totext(result));
11661         }
11662 }
11663
11664 static void
11665 cancel_refresh(dns_zone_t *zone) {
11666         const char me[] = "cancel_refresh";
11667         isc_time_t now;
11668
11669         /*
11670          * 'zone' locked by caller.
11671          */
11672
11673         REQUIRE(DNS_ZONE_VALID(zone));
11674         REQUIRE(LOCKED_ZONE(zone));
11675
11676         ENTER;
11677
11678         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11679         TIME_NOW(&now);
11680         zone_settimer(zone, &now);
11681 }
11682
11683 static isc_result_t
11684 notify_createmessage(dns_zone_t *zone, unsigned int flags,
11685                      dns_message_t **messagep)
11686 {
11687         dns_db_t *zonedb = NULL;
11688         dns_dbnode_t *node = NULL;
11689         dns_dbversion_t *version = NULL;
11690         dns_message_t *message = NULL;
11691         dns_rdataset_t rdataset;
11692         dns_rdata_t rdata = DNS_RDATA_INIT;
11693
11694         dns_name_t *tempname = NULL;
11695         dns_rdata_t *temprdata = NULL;
11696         dns_rdatalist_t *temprdatalist = NULL;
11697         dns_rdataset_t *temprdataset = NULL;
11698
11699         isc_result_t result;
11700         isc_region_t r;
11701         isc_buffer_t *b = NULL;
11702
11703         REQUIRE(DNS_ZONE_VALID(zone));
11704         REQUIRE(messagep != NULL && *messagep == NULL);
11705
11706         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11707                                     &message);
11708         if (result != ISC_R_SUCCESS)
11709                 return (result);
11710
11711         message->opcode = dns_opcode_notify;
11712         message->flags |= DNS_MESSAGEFLAG_AA;
11713         message->rdclass = zone->rdclass;
11714
11715         result = dns_message_gettempname(message, &tempname);
11716         if (result != ISC_R_SUCCESS)
11717                 goto cleanup;
11718
11719         result = dns_message_gettemprdataset(message, &temprdataset);
11720         if (result != ISC_R_SUCCESS)
11721                 goto cleanup;
11722
11723         /*
11724          * Make question.
11725          */
11726         dns_name_init(tempname, NULL);
11727         dns_name_clone(&zone->origin, tempname);
11728         dns_rdataset_init(temprdataset);
11729         dns_rdataset_makequestion(temprdataset, zone->rdclass,
11730                                   dns_rdatatype_soa);
11731         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11732         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
11733         tempname = NULL;
11734         temprdataset = NULL;
11735
11736         if ((flags & DNS_NOTIFY_NOSOA) != 0)
11737                 goto done;
11738
11739         result = dns_message_gettempname(message, &tempname);
11740         if (result != ISC_R_SUCCESS)
11741                 goto soa_cleanup;
11742         result = dns_message_gettemprdata(message, &temprdata);
11743         if (result != ISC_R_SUCCESS)
11744                 goto soa_cleanup;
11745         result = dns_message_gettemprdataset(message, &temprdataset);
11746         if (result != ISC_R_SUCCESS)
11747                 goto soa_cleanup;
11748         result = dns_message_gettemprdatalist(message, &temprdatalist);
11749         if (result != ISC_R_SUCCESS)
11750                 goto soa_cleanup;
11751
11752         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11753         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
11754         dns_db_attach(zone->db, &zonedb);
11755         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11756
11757         dns_name_init(tempname, NULL);
11758         dns_name_clone(&zone->origin, tempname);
11759         dns_db_currentversion(zonedb, &version);
11760         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
11761         if (result != ISC_R_SUCCESS)
11762                 goto soa_cleanup;
11763
11764         dns_rdataset_init(&rdataset);
11765         result = dns_db_findrdataset(zonedb, node, version,
11766                                      dns_rdatatype_soa,
11767                                      dns_rdatatype_none, 0, &rdataset,
11768                                      NULL);
11769         if (result != ISC_R_SUCCESS)
11770                 goto soa_cleanup;
11771         result = dns_rdataset_first(&rdataset);
11772         if (result != ISC_R_SUCCESS)
11773                 goto soa_cleanup;
11774         dns_rdataset_current(&rdataset, &rdata);
11775         dns_rdata_toregion(&rdata, &r);
11776         result = isc_buffer_allocate(zone->mctx, &b, r.length);
11777         if (result != ISC_R_SUCCESS)
11778                 goto soa_cleanup;
11779         isc_buffer_putmem(b, r.base, r.length);
11780         isc_buffer_usedregion(b, &r);
11781         dns_rdata_init(temprdata);
11782         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
11783         dns_message_takebuffer(message, &b);
11784         result = dns_rdataset_next(&rdataset);
11785         dns_rdataset_disassociate(&rdataset);
11786         if (result != ISC_R_NOMORE)
11787                 goto soa_cleanup;
11788         temprdatalist->rdclass = rdata.rdclass;
11789         temprdatalist->type = rdata.type;
11790         temprdatalist->covers = 0;
11791         temprdatalist->ttl = rdataset.ttl;
11792         ISC_LIST_INIT(temprdatalist->rdata);
11793         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
11794
11795         dns_rdataset_init(temprdataset);
11796         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
11797         if (result != ISC_R_SUCCESS)
11798                 goto soa_cleanup;
11799
11800         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11801         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
11802         temprdatalist = NULL;
11803         temprdataset = NULL;
11804         temprdata = NULL;
11805         tempname = NULL;
11806
11807  soa_cleanup:
11808         if (node != NULL)
11809                 dns_db_detachnode(zonedb, &node);
11810         if (version != NULL)
11811                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
11812         if (zonedb != NULL)
11813                 dns_db_detach(&zonedb);
11814         if (tempname != NULL)
11815                 dns_message_puttempname(message, &tempname);
11816         if (temprdata != NULL)
11817                 dns_message_puttemprdata(message, &temprdata);
11818         if (temprdataset != NULL)
11819                 dns_message_puttemprdataset(message, &temprdataset);
11820         if (temprdatalist != NULL)
11821                 dns_message_puttemprdatalist(message, &temprdatalist);
11822
11823  done:
11824         *messagep = message;
11825         return (ISC_R_SUCCESS);
11826
11827  cleanup:
11828         if (tempname != NULL)
11829                 dns_message_puttempname(message, &tempname);
11830         if (temprdataset != NULL)
11831                 dns_message_puttemprdataset(message, &temprdataset);
11832         dns_message_destroy(&message);
11833         return (result);
11834 }
11835
11836 isc_result_t
11837 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
11838                        dns_message_t *msg)
11839 {
11840         unsigned int i;
11841         dns_rdata_soa_t soa;
11842         dns_rdataset_t *rdataset = NULL;
11843         dns_rdata_t rdata = DNS_RDATA_INIT;
11844         isc_result_t result;
11845         char fromtext[ISC_SOCKADDR_FORMATSIZE];
11846         int match = 0;
11847         isc_netaddr_t netaddr;
11848         isc_sockaddr_t local, remote;
11849
11850         REQUIRE(DNS_ZONE_VALID(zone));
11851
11852         /*
11853          * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
11854          * ROLLOVER.
11855          *
11856          * SOA: RFC1996
11857          * Check that 'from' is a valid notify source, (zone->masters).
11858          *      Return DNS_R_REFUSED if not.
11859          *
11860          * If the notify message contains a serial number check it
11861          * against the zones serial and return if <= current serial
11862          *
11863          * If a refresh check is progress, if so just record the
11864          * fact we received a NOTIFY and from where and return.
11865          * We will perform a new refresh check when the current one
11866          * completes. Return ISC_R_SUCCESS.
11867          *
11868          * Otherwise initiate a refresh check using 'from' as the
11869          * first address to check.  Return ISC_R_SUCCESS.
11870          */
11871
11872         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
11873
11874         /*
11875          * Notify messages are processed by the raw zone.
11876          */
11877         LOCK_ZONE(zone);
11878         if (inline_secure(zone)) {
11879                 result = dns_zone_notifyreceive(zone->raw, from, msg);
11880                 UNLOCK_ZONE(zone);
11881                 return (result);
11882         }
11883         /*
11884          *  We only handle NOTIFY (SOA) at the present.
11885          */
11886         if (isc_sockaddr_pf(from) == PF_INET)
11887                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
11888         else
11889                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
11890         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
11891             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
11892                                  dns_rdatatype_soa, dns_rdatatype_none,
11893                                  NULL, NULL) != ISC_R_SUCCESS) {
11894                 UNLOCK_ZONE(zone);
11895                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
11896                         dns_zone_log(zone, ISC_LOG_NOTICE,
11897                                      "NOTIFY with no "
11898                                      "question section from: %s", fromtext);
11899                         return (DNS_R_FORMERR);
11900                 }
11901                 dns_zone_log(zone, ISC_LOG_NOTICE,
11902                              "NOTIFY zone does not match");
11903                 return (DNS_R_NOTIMP);
11904         }
11905
11906         /*
11907          * If we are a master zone just succeed.
11908          */
11909         if (zone->type == dns_zone_master) {
11910                 UNLOCK_ZONE(zone);
11911                 return (ISC_R_SUCCESS);
11912         }
11913
11914         isc_netaddr_fromsockaddr(&netaddr, from);
11915         for (i = 0; i < zone->masterscnt; i++) {
11916                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
11917                         break;
11918                 if (zone->view->aclenv.match_mapped &&
11919                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
11920                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
11921                         isc_netaddr_t na1, na2;
11922                         isc_netaddr_fromv4mapped(&na1, &netaddr);
11923                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
11924                         if (isc_netaddr_equal(&na1, &na2))
11925                                 break;
11926                 }
11927         }
11928
11929         /*
11930          * Accept notify requests from non masters if they are on
11931          * 'zone->notify_acl'.
11932          */
11933         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
11934             dns_acl_match(&netaddr, NULL, zone->notify_acl,
11935                           &zone->view->aclenv,
11936                           &match, NULL) == ISC_R_SUCCESS &&
11937             match > 0)
11938         {
11939                 /* Accept notify. */
11940         } else if (i >= zone->masterscnt) {
11941                 UNLOCK_ZONE(zone);
11942                 dns_zone_log(zone, ISC_LOG_INFO,
11943                              "refused notify from non-master: %s", fromtext);
11944                 inc_stats(zone, dns_zonestatscounter_notifyrej);
11945                 return (DNS_R_REFUSED);
11946         }
11947
11948         /*
11949          * If the zone is loaded and there are answers check the serial
11950          * to see if we need to do a refresh.  Do not worry about this
11951          * check if we are a dialup zone as we use the notify request
11952          * to trigger a refresh check.
11953          */
11954         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
11955             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11956             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
11957                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
11958                                               &zone->origin,
11959                                               dns_rdatatype_soa,
11960                                               dns_rdatatype_none, NULL,
11961                                               &rdataset);
11962                 if (result == ISC_R_SUCCESS)
11963                         result = dns_rdataset_first(rdataset);
11964                 if (result == ISC_R_SUCCESS) {
11965                         isc_uint32_t serial = 0, oldserial;
11966                         unsigned int soacount;
11967
11968                         dns_rdataset_current(rdataset, &rdata);
11969                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
11970                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11971                         serial = soa.serial;
11972                         /*
11973                          * The following should safely be performed without DB
11974                          * lock and succeed in this context.
11975                          */
11976                         result = zone_get_from_db(zone, zone->db, NULL,
11977                                                   &soacount, &oldserial, NULL,
11978                                                   NULL, NULL, NULL, NULL);
11979                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11980                         RUNTIME_CHECK(soacount > 0U);
11981                         if (isc_serial_le(serial, oldserial)) {
11982                                 dns_zone_log(zone,
11983                                              ISC_LOG_INFO,
11984                                              "notify from %s: "
11985                                              "zone is up to date",
11986                                              fromtext);
11987                                 UNLOCK_ZONE(zone);
11988                                 return (ISC_R_SUCCESS);
11989                         }
11990                 }
11991         }
11992
11993         /*
11994          * If we got this far and there was a refresh in progress just
11995          * let it complete.  Record where we got the notify from so we
11996          * can perform a refresh check when the current one completes
11997          */
11998         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
11999                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12000                 zone->notifyfrom = *from;
12001                 UNLOCK_ZONE(zone);
12002                 dns_zone_log(zone, ISC_LOG_INFO,
12003                              "notify from %s: refresh in progress, "
12004                              "refresh check queued",
12005                              fromtext);
12006                 return (ISC_R_SUCCESS);
12007         }
12008         zone->notifyfrom = *from;
12009         local = zone->masteraddr;
12010         remote = zone->sourceaddr;
12011         UNLOCK_ZONE(zone);
12012         dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
12013         dns_zone_refresh(zone);
12014         return (ISC_R_SUCCESS);
12015 }
12016
12017 void
12018 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
12019
12020         REQUIRE(DNS_ZONE_VALID(zone));
12021
12022         LOCK_ZONE(zone);
12023         if (zone->notify_acl != NULL)
12024                 dns_acl_detach(&zone->notify_acl);
12025         dns_acl_attach(acl, &zone->notify_acl);
12026         UNLOCK_ZONE(zone);
12027 }
12028
12029 void
12030 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
12031
12032         REQUIRE(DNS_ZONE_VALID(zone));
12033
12034         LOCK_ZONE(zone);
12035         if (zone->query_acl != NULL)
12036                 dns_acl_detach(&zone->query_acl);
12037         dns_acl_attach(acl, &zone->query_acl);
12038         UNLOCK_ZONE(zone);
12039 }
12040
12041 void
12042 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
12043
12044         REQUIRE(DNS_ZONE_VALID(zone));
12045
12046         LOCK_ZONE(zone);
12047         if (zone->queryon_acl != NULL)
12048                 dns_acl_detach(&zone->queryon_acl);
12049         dns_acl_attach(acl, &zone->queryon_acl);
12050         UNLOCK_ZONE(zone);
12051 }
12052
12053 void
12054 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
12055
12056         REQUIRE(DNS_ZONE_VALID(zone));
12057
12058         LOCK_ZONE(zone);
12059         if (zone->update_acl != NULL)
12060                 dns_acl_detach(&zone->update_acl);
12061         dns_acl_attach(acl, &zone->update_acl);
12062         UNLOCK_ZONE(zone);
12063 }
12064
12065 void
12066 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
12067
12068         REQUIRE(DNS_ZONE_VALID(zone));
12069
12070         LOCK_ZONE(zone);
12071         if (zone->forward_acl != NULL)
12072                 dns_acl_detach(&zone->forward_acl);
12073         dns_acl_attach(acl, &zone->forward_acl);
12074         UNLOCK_ZONE(zone);
12075 }
12076
12077 void
12078 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
12079
12080         REQUIRE(DNS_ZONE_VALID(zone));
12081
12082         LOCK_ZONE(zone);
12083         if (zone->xfr_acl != NULL)
12084                 dns_acl_detach(&zone->xfr_acl);
12085         dns_acl_attach(acl, &zone->xfr_acl);
12086         UNLOCK_ZONE(zone);
12087 }
12088
12089 dns_acl_t *
12090 dns_zone_getnotifyacl(dns_zone_t *zone) {
12091
12092         REQUIRE(DNS_ZONE_VALID(zone));
12093
12094         return (zone->notify_acl);
12095 }
12096
12097 dns_acl_t *
12098 dns_zone_getqueryacl(dns_zone_t *zone) {
12099
12100         REQUIRE(DNS_ZONE_VALID(zone));
12101
12102         return (zone->query_acl);
12103 }
12104
12105 dns_acl_t *
12106 dns_zone_getqueryonacl(dns_zone_t *zone) {
12107
12108         REQUIRE(DNS_ZONE_VALID(zone));
12109
12110         return (zone->queryon_acl);
12111 }
12112
12113 dns_acl_t *
12114 dns_zone_getupdateacl(dns_zone_t *zone) {
12115
12116         REQUIRE(DNS_ZONE_VALID(zone));
12117
12118         return (zone->update_acl);
12119 }
12120
12121 dns_acl_t *
12122 dns_zone_getforwardacl(dns_zone_t *zone) {
12123
12124         REQUIRE(DNS_ZONE_VALID(zone));
12125
12126         return (zone->forward_acl);
12127 }
12128
12129 dns_acl_t *
12130 dns_zone_getxfracl(dns_zone_t *zone) {
12131
12132         REQUIRE(DNS_ZONE_VALID(zone));
12133
12134         return (zone->xfr_acl);
12135 }
12136
12137 void
12138 dns_zone_clearupdateacl(dns_zone_t *zone) {
12139
12140         REQUIRE(DNS_ZONE_VALID(zone));
12141
12142         LOCK_ZONE(zone);
12143         if (zone->update_acl != NULL)
12144                 dns_acl_detach(&zone->update_acl);
12145         UNLOCK_ZONE(zone);
12146 }
12147
12148 void
12149 dns_zone_clearforwardacl(dns_zone_t *zone) {
12150
12151         REQUIRE(DNS_ZONE_VALID(zone));
12152
12153         LOCK_ZONE(zone);
12154         if (zone->forward_acl != NULL)
12155                 dns_acl_detach(&zone->forward_acl);
12156         UNLOCK_ZONE(zone);
12157 }
12158
12159 void
12160 dns_zone_clearnotifyacl(dns_zone_t *zone) {
12161
12162         REQUIRE(DNS_ZONE_VALID(zone));
12163
12164         LOCK_ZONE(zone);
12165         if (zone->notify_acl != NULL)
12166                 dns_acl_detach(&zone->notify_acl);
12167         UNLOCK_ZONE(zone);
12168 }
12169
12170 void
12171 dns_zone_clearqueryacl(dns_zone_t *zone) {
12172
12173         REQUIRE(DNS_ZONE_VALID(zone));
12174
12175         LOCK_ZONE(zone);
12176         if (zone->query_acl != NULL)
12177                 dns_acl_detach(&zone->query_acl);
12178         UNLOCK_ZONE(zone);
12179 }
12180
12181 void
12182 dns_zone_clearqueryonacl(dns_zone_t *zone) {
12183
12184         REQUIRE(DNS_ZONE_VALID(zone));
12185
12186         LOCK_ZONE(zone);
12187         if (zone->queryon_acl != NULL)
12188                 dns_acl_detach(&zone->queryon_acl);
12189         UNLOCK_ZONE(zone);
12190 }
12191
12192 void
12193 dns_zone_clearxfracl(dns_zone_t *zone) {
12194
12195         REQUIRE(DNS_ZONE_VALID(zone));
12196
12197         LOCK_ZONE(zone);
12198         if (zone->xfr_acl != NULL)
12199                 dns_acl_detach(&zone->xfr_acl);
12200         UNLOCK_ZONE(zone);
12201 }
12202
12203 isc_boolean_t
12204 dns_zone_getupdatedisabled(dns_zone_t *zone) {
12205         REQUIRE(DNS_ZONE_VALID(zone));
12206         return (zone->update_disabled);
12207
12208 }
12209
12210 void
12211 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
12212         REQUIRE(DNS_ZONE_VALID(zone));
12213         zone->update_disabled = state;
12214 }
12215
12216 isc_boolean_t
12217 dns_zone_getzeronosoattl(dns_zone_t *zone) {
12218         REQUIRE(DNS_ZONE_VALID(zone));
12219         return (zone->zero_no_soa_ttl);
12220
12221 }
12222
12223 void
12224 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
12225         REQUIRE(DNS_ZONE_VALID(zone));
12226         zone->zero_no_soa_ttl = state;
12227 }
12228
12229 void
12230 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
12231
12232         REQUIRE(DNS_ZONE_VALID(zone));
12233
12234         zone->check_names = severity;
12235 }
12236
12237 dns_severity_t
12238 dns_zone_getchecknames(dns_zone_t *zone) {
12239
12240         REQUIRE(DNS_ZONE_VALID(zone));
12241
12242         return (zone->check_names);
12243 }
12244
12245 void
12246 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
12247
12248         REQUIRE(DNS_ZONE_VALID(zone));
12249
12250         zone->journalsize = size;
12251 }
12252
12253 isc_int32_t
12254 dns_zone_getjournalsize(dns_zone_t *zone) {
12255
12256         REQUIRE(DNS_ZONE_VALID(zone));
12257
12258         return (zone->journalsize);
12259 }
12260
12261 static void
12262 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
12263         isc_result_t result = ISC_R_FAILURE;
12264         isc_buffer_t buffer;
12265
12266         REQUIRE(buf != NULL);
12267         REQUIRE(length > 1U);
12268
12269         /*
12270          * Leave space for terminating '\0'.
12271          */
12272         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12273         if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
12274                 if (dns_name_dynamic(&zone->origin))
12275                         result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12276                 if (result != ISC_R_SUCCESS &&
12277                     isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12278                         isc_buffer_putstr(&buffer, "<UNKNOWN>");
12279
12280                 if (isc_buffer_availablelength(&buffer) > 0)
12281                         isc_buffer_putstr(&buffer, "/");
12282                 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
12283         }
12284
12285         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
12286             strcmp(zone->view->name, "_default") != 0 &&
12287             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
12288                 isc_buffer_putstr(&buffer, "/");
12289                 isc_buffer_putstr(&buffer, zone->view->name);
12290         }
12291         if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
12292                 isc_buffer_putstr(&buffer, " (signed)");
12293         if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
12294                 isc_buffer_putstr(&buffer, " (unsigned)");
12295
12296         buf[isc_buffer_usedlength(&buffer)] = '\0';
12297 }
12298
12299 static void
12300 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
12301         isc_result_t result = ISC_R_FAILURE;
12302         isc_buffer_t buffer;
12303
12304         REQUIRE(buf != NULL);
12305         REQUIRE(length > 1U);
12306
12307         /*
12308          * Leave space for terminating '\0'.
12309          */
12310         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12311         if (dns_name_dynamic(&zone->origin))
12312                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12313         if (result != ISC_R_SUCCESS &&
12314             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12315                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
12316
12317         buf[isc_buffer_usedlength(&buffer)] = '\0';
12318 }
12319
12320 static void
12321 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
12322         isc_buffer_t buffer;
12323
12324         REQUIRE(buf != NULL);
12325         REQUIRE(length > 1U);
12326
12327         /*
12328          * Leave space for terminating '\0'.
12329          */
12330         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12331         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
12332
12333         buf[isc_buffer_usedlength(&buffer)] = '\0';
12334 }
12335
12336 static void
12337 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
12338         isc_buffer_t buffer;
12339
12340         REQUIRE(buf != NULL);
12341         REQUIRE(length > 1U);
12342
12343
12344         /*
12345          * Leave space for terminating '\0'.
12346          */
12347         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12348
12349         if (zone->view == NULL) {
12350                 isc_buffer_putstr(&buffer, "_none");
12351         } else if (strlen(zone->view->name)
12352                    < isc_buffer_availablelength(&buffer)) {
12353                 isc_buffer_putstr(&buffer, zone->view->name);
12354         } else {
12355                 isc_buffer_putstr(&buffer, "_toolong");
12356         }
12357
12358         buf[isc_buffer_usedlength(&buffer)] = '\0';
12359 }
12360
12361 void
12362 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
12363         REQUIRE(DNS_ZONE_VALID(zone));
12364         REQUIRE(buf != NULL);
12365         zone_namerd_tostr(zone, buf, length);
12366 }
12367
12368 static void
12369 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12370         va_list ap;
12371         char message[4096];
12372
12373         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12374                 return;
12375
12376         va_start(ap, fmt);
12377         vsnprintf(message, sizeof(message), fmt, ap);
12378         va_end(ap);
12379         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
12380                       level, "zone %s: %s", zone->strnamerd, message);
12381 }
12382
12383 void
12384 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
12385               int level, const char *fmt, ...) {
12386         va_list ap;
12387         char message[4096];
12388
12389         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12390                 return;
12391
12392         va_start(ap, fmt);
12393         vsnprintf(message, sizeof(message), fmt, ap);
12394         va_end(ap);
12395         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
12396                       level, "%s%s: %s", (zone->type == dns_zone_key) ?
12397                       "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12398                       "redirect-zone" : "zone ", zone->strnamerd, message);
12399 }
12400
12401 void
12402 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12403         va_list ap;
12404         char message[4096];
12405
12406         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12407                 return;
12408
12409         va_start(ap, fmt);
12410         vsnprintf(message, sizeof(message), fmt, ap);
12411         va_end(ap);
12412         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12413                       level, "%s%s: %s", (zone->type == dns_zone_key) ?
12414                       "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12415                       "redirect-zone" : "zone ", zone->strnamerd, message);
12416 }
12417
12418 static void
12419 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
12420               const char *fmt, ...)
12421 {
12422         va_list ap;
12423         char message[4096];
12424         int level = ISC_LOG_DEBUG(debuglevel);
12425         const char *zstr;
12426
12427         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12428                 return;
12429
12430         va_start(ap, fmt);
12431         vsnprintf(message, sizeof(message), fmt, ap);
12432         va_end(ap);
12433
12434         switch (zone->type) {
12435         case dns_zone_key:
12436                 zstr = "managed-keys-zone";
12437                 break;
12438         case dns_zone_redirect:
12439                 zstr = "redirect-zone";
12440                 break;
12441         default:
12442                 zstr = "zone";
12443         }
12444
12445         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12446                       level, "%s: %s %s: %s", me, zstr, zone->strnamerd,
12447                       message);
12448 }
12449
12450 static int
12451 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
12452 {
12453         isc_result_t result;
12454         dns_name_t *name;
12455         dns_rdataset_t *curr;
12456         int count = 0;
12457
12458         result = dns_message_firstname(msg, section);
12459         while (result == ISC_R_SUCCESS) {
12460                 name = NULL;
12461                 dns_message_currentname(msg, section, &name);
12462
12463                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
12464                      curr = ISC_LIST_PREV(curr, link)) {
12465                         if (curr->type == type)
12466                                 count++;
12467                 }
12468                 result = dns_message_nextname(msg, section);
12469         }
12470
12471         return (count);
12472 }
12473
12474 void
12475 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
12476         REQUIRE(DNS_ZONE_VALID(zone));
12477
12478         zone->maxxfrin = maxxfrin;
12479 }
12480
12481 isc_uint32_t
12482 dns_zone_getmaxxfrin(dns_zone_t *zone) {
12483         REQUIRE(DNS_ZONE_VALID(zone));
12484
12485         return (zone->maxxfrin);
12486 }
12487
12488 void
12489 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
12490         REQUIRE(DNS_ZONE_VALID(zone));
12491         zone->maxxfrout = maxxfrout;
12492 }
12493
12494 isc_uint32_t
12495 dns_zone_getmaxxfrout(dns_zone_t *zone) {
12496         REQUIRE(DNS_ZONE_VALID(zone));
12497
12498         return (zone->maxxfrout);
12499 }
12500
12501 dns_zonetype_t
12502 dns_zone_gettype(dns_zone_t *zone) {
12503         REQUIRE(DNS_ZONE_VALID(zone));
12504
12505         return (zone->type);
12506 }
12507
12508 dns_name_t *
12509 dns_zone_getorigin(dns_zone_t *zone) {
12510         REQUIRE(DNS_ZONE_VALID(zone));
12511
12512         return (&zone->origin);
12513 }
12514
12515 void
12516 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
12517         REQUIRE(DNS_ZONE_VALID(zone));
12518
12519         LOCK_ZONE(zone);
12520         if (zone->task != NULL)
12521                 isc_task_detach(&zone->task);
12522         isc_task_attach(task, &zone->task);
12523         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12524         if (zone->db != NULL)
12525                 dns_db_settask(zone->db, zone->task);
12526         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12527         UNLOCK_ZONE(zone);
12528 }
12529
12530 void
12531 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
12532         REQUIRE(DNS_ZONE_VALID(zone));
12533         isc_task_attach(zone->task, target);
12534 }
12535
12536 void
12537 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
12538         REQUIRE(DNS_ZONE_VALID(zone));
12539
12540         if (idlein == 0)
12541                 idlein = DNS_DEFAULT_IDLEIN;
12542         zone->idlein = idlein;
12543 }
12544
12545 isc_uint32_t
12546 dns_zone_getidlein(dns_zone_t *zone) {
12547         REQUIRE(DNS_ZONE_VALID(zone));
12548
12549         return (zone->idlein);
12550 }
12551
12552 void
12553 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
12554         REQUIRE(DNS_ZONE_VALID(zone));
12555
12556         zone->idleout = idleout;
12557 }
12558
12559 isc_uint32_t
12560 dns_zone_getidleout(dns_zone_t *zone) {
12561         REQUIRE(DNS_ZONE_VALID(zone));
12562
12563         return (zone->idleout);
12564 }
12565
12566 static void
12567 notify_done(isc_task_t *task, isc_event_t *event) {
12568         dns_requestevent_t *revent = (dns_requestevent_t *)event;
12569         dns_notify_t *notify;
12570         isc_result_t result;
12571         dns_message_t *message = NULL;
12572         isc_buffer_t buf;
12573         char rcode[128];
12574         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12575
12576         UNUSED(task);
12577
12578         notify = event->ev_arg;
12579         REQUIRE(DNS_NOTIFY_VALID(notify));
12580         INSIST(task == notify->zone->task);
12581
12582         isc_buffer_init(&buf, rcode, sizeof(rcode));
12583         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12584
12585         result = revent->result;
12586         if (result == ISC_R_SUCCESS)
12587                 result = dns_message_create(notify->zone->mctx,
12588                                             DNS_MESSAGE_INTENTPARSE, &message);
12589         if (result == ISC_R_SUCCESS)
12590                 result = dns_request_getresponse(revent->request, message,
12591                                         DNS_MESSAGEPARSE_PRESERVEORDER);
12592         if (result == ISC_R_SUCCESS)
12593                 result = dns_rcode_totext(message->rcode, &buf);
12594         if (result == ISC_R_SUCCESS)
12595                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12596                            "notify response from %s: %.*s",
12597                            addrbuf, (int)buf.used, rcode);
12598         else
12599                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
12600                            "notify to %s failed: %s", addrbuf,
12601                            dns_result_totext(result));
12602
12603         /*
12604          * Old bind's return formerr if they see a soa record.  Retry w/o
12605          * the soa if we see a formerr and had sent a SOA.
12606          */
12607         isc_event_free(&event);
12608         if (message != NULL && message->rcode == dns_rcode_formerr &&
12609             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
12610                 notify->flags |= DNS_NOTIFY_NOSOA;
12611                 dns_request_destroy(&notify->request);
12612                 result = notify_send_queue(notify);
12613                 if (result != ISC_R_SUCCESS)
12614                         notify_destroy(notify, ISC_FALSE);
12615         } else {
12616                 if (result == ISC_R_TIMEDOUT)
12617                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
12618                                    "notify to %s: retries exceeded", addrbuf);
12619                 notify_destroy(notify, ISC_FALSE);
12620         }
12621         if (message != NULL)
12622                 dns_message_destroy(&message);
12623 }
12624
12625 struct secure_event {
12626         isc_event_t e;
12627         dns_db_t *db;
12628         isc_uint32_t serial;
12629 };
12630
12631 static void
12632 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
12633         UNUSED(arg);
12634         dns_zone_log(zone, level, "%s", message);
12635 }
12636
12637 static isc_result_t
12638 sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal,
12639                     isc_uint32_t start, isc_uint32_t end,
12640                     dns_difftuple_t **soatuplep, dns_diff_t *diff)
12641 {
12642         isc_result_t result;
12643         dns_difftuple_t *tuple = NULL;
12644         dns_diffop_t op = DNS_DIFFOP_ADD;
12645         int n_soa = 0;
12646
12647         REQUIRE(soatuplep != NULL);
12648
12649         if (start == end)
12650                 return (DNS_R_UNCHANGED);
12651
12652         CHECK(dns_journal_iter_init(journal, start, end));
12653         for (result = dns_journal_first_rr(journal);
12654              result == ISC_R_SUCCESS;
12655              result = dns_journal_next_rr(journal))
12656         {
12657                 dns_name_t *name = NULL;
12658                 isc_uint32_t ttl;
12659                 dns_rdata_t *rdata = NULL;
12660                 dns_journal_current_rr(journal, &name, &ttl, &rdata);
12661
12662                 if (rdata->type == dns_rdatatype_soa) {
12663                         n_soa++;
12664                         if (n_soa == 2) {
12665                                 /*
12666                                  * Save the latest raw SOA record.
12667                                  */
12668                                 if (*soatuplep != NULL)
12669                                         dns_difftuple_free(soatuplep);
12670                                 CHECK(dns_difftuple_create(diff->mctx,
12671                                                            DNS_DIFFOP_ADD,
12672                                                            name, ttl, rdata,
12673                                                            soatuplep));
12674                         }
12675                         if (n_soa == 3)
12676                                 n_soa = 1;
12677                         continue;
12678                 }
12679
12680                 /* Sanity. */
12681                 if (n_soa == 0) {
12682                         dns_zone_log(zone->raw, ISC_LOG_ERROR,
12683                                      "corrupt journal file: '%s'\n",
12684                                      zone->raw->journal);
12685                         return (ISC_R_FAILURE);
12686                 }
12687
12688                 if (zone->privatetype != 0 &&
12689                     rdata->type == zone->privatetype)
12690                         continue;
12691
12692                 if (rdata->type == dns_rdatatype_nsec ||
12693                     rdata->type == dns_rdatatype_rrsig ||
12694                     rdata->type == dns_rdatatype_nsec3 ||
12695                     rdata->type == dns_rdatatype_dnskey ||
12696                     rdata->type == dns_rdatatype_nsec3param)
12697                         continue;
12698
12699                 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
12700
12701                 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
12702                                            &tuple));
12703                 dns_diff_appendminimal(diff, &tuple);
12704         }
12705         if (result == ISC_R_NOMORE)
12706                 result = ISC_R_SUCCESS;
12707
12708  failure:
12709         return(result);
12710 }
12711
12712 static isc_result_t
12713 sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb,
12714                dns_dbversion_t *secver, dns_difftuple_t **soatuple,
12715                dns_diff_t *diff)
12716 {
12717         isc_result_t result;
12718         dns_db_t *rawdb = NULL;
12719         dns_dbversion_t *rawver = NULL;
12720         dns_difftuple_t *tuple = NULL, *next;
12721         dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
12722         dns_rdata_soa_t oldsoa, newsoa;
12723
12724         REQUIRE(DNS_ZONE_VALID(seczone));
12725         REQUIRE(inline_secure(seczone));
12726         REQUIRE(soatuple != NULL && *soatuple == NULL);
12727
12728         if (!seczone->sourceserialset)
12729                 return (DNS_R_UNCHANGED);
12730
12731         dns_db_attach(seczone->raw->db, &rawdb);
12732         dns_db_currentversion(rawdb, &rawver);
12733         result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
12734         dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
12735         dns_db_detach(&rawdb);
12736
12737         if (result != ISC_R_SUCCESS)
12738                 return (result);
12739
12740         for (tuple = ISC_LIST_HEAD(diff->tuples);
12741              tuple != NULL;
12742              tuple = next)
12743         {
12744                 next = ISC_LIST_NEXT(tuple, link);
12745                 if (tuple->rdata.type == dns_rdatatype_nsec ||
12746                     tuple->rdata.type == dns_rdatatype_rrsig ||
12747                     tuple->rdata.type == dns_rdatatype_dnskey ||
12748                     tuple->rdata.type == dns_rdatatype_nsec3 ||
12749                     tuple->rdata.type == dns_rdatatype_nsec3param)
12750                 {
12751                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
12752                         dns_difftuple_free(&tuple);
12753                         continue;
12754                 }
12755                 if (tuple->rdata.type == dns_rdatatype_soa) {
12756                         if (tuple->op == DNS_DIFFOP_DEL) {
12757                                 INSIST(oldtuple == NULL);
12758                                 oldtuple = tuple;
12759                         }
12760                         if (tuple->op == DNS_DIFFOP_ADD) {
12761                                 INSIST(newtuple == NULL);
12762                                 newtuple = tuple;
12763                         }
12764                 }
12765         }
12766
12767         if (oldtuple != NULL && newtuple != NULL) {
12768
12769                 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
12770                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12771
12772                 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
12773                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12774
12775                 /*
12776                  * If the SOA records are the same except for the serial
12777                  * remove them from the diff.
12778                  */
12779                 if (oldsoa.refresh == newsoa.refresh &&
12780                     oldsoa.retry == newsoa.retry &&
12781                     oldsoa.minimum == newsoa.minimum &&
12782                     oldsoa.expire == newsoa.expire &&
12783                     dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
12784                     dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
12785                         ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12786                         dns_difftuple_free(&oldtuple);
12787                         ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12788                         dns_difftuple_free(&newtuple);
12789                 }
12790         }
12791
12792         if (ISC_LIST_EMPTY(diff->tuples))
12793                 return (DNS_R_UNCHANGED);
12794
12795         /*
12796          * If there are still SOA records in the diff they can now be removed
12797          * saving the new SOA record.
12798          */
12799         if (oldtuple != NULL) {
12800                 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12801                 dns_difftuple_free(&oldtuple);
12802         }
12803
12804         if (newtuple != NULL) {
12805                 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12806                 *soatuple = newtuple;
12807         }
12808
12809         return (ISC_R_SUCCESS);
12810 }
12811
12812 static void
12813 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
12814         static char me[] = "receive_secure_serial";
12815         isc_result_t result;
12816         dns_journal_t *rjournal = NULL;
12817         isc_uint32_t start, end;
12818         dns_zone_t *zone;
12819         dns_db_t *db = NULL;
12820         dns_dbversion_t *newver = NULL, *oldver = NULL;
12821         dns_diff_t diff;
12822         dns_difftuple_t *tuple = NULL, *soatuple = NULL;
12823         dns_update_log_t log = { update_log_cb, NULL };
12824         isc_time_t timenow;
12825
12826         zone = event->ev_arg;
12827         end = ((struct secure_event *)event)->serial;
12828         isc_event_free(&event);
12829
12830         ENTER;
12831
12832         LOCK_ZONE(zone);
12833
12834         dns_diff_init(zone->mctx, &diff);
12835
12836         UNUSED(task);
12837
12838         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12839         if (zone->db != NULL)
12840                 dns_db_attach(zone->db, &db);
12841         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12842
12843         /*
12844          * zone->db may be NULL if the load from disk failed.
12845          */
12846         if (db == NULL || !inline_secure(zone)) {
12847                 result = ISC_R_FAILURE;
12848                 goto failure;
12849         }
12850
12851         /*
12852          * We first attempt to sync the raw zone to the secure zone
12853          * by using the raw zone's journal, applying all the deltas
12854          * from the latest source-serial of the secure zone up to
12855          * the current serial number of the raw zone.
12856          *
12857          * If that fails, then we'll fall back to a direct comparison
12858          * between raw and secure zones.
12859          */
12860         result = dns_journal_open(zone->raw->mctx, zone->raw->journal,
12861                                   DNS_JOURNAL_WRITE, &rjournal);
12862         if (result != ISC_R_SUCCESS)
12863                 goto failure;
12864         else {
12865                 dns_journal_t *sjournal = NULL;
12866
12867                 result = dns_journal_open(zone->mctx, zone->journal,
12868                                           DNS_JOURNAL_READ, &sjournal);
12869                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
12870                         goto failure;
12871
12872                 if (!dns_journal_get_sourceserial(rjournal, &start)) {
12873                         start = dns_journal_first_serial(rjournal);
12874                         dns_journal_set_sourceserial(rjournal, start);
12875                 }
12876                 if (sjournal != NULL) {
12877                         isc_uint32_t serial;
12878                         /*
12879                          * We read the secure journal first, if that exists
12880                          * use its value provided it is greater that from the
12881                          * raw journal.
12882                          */
12883                         if (dns_journal_get_sourceserial(sjournal, &serial)) {
12884                                 if (isc_serial_gt(serial, start))
12885                                         start = serial;
12886                         }
12887                         dns_journal_destroy(&sjournal);
12888                 }
12889         }
12890
12891         dns_db_currentversion(db, &oldver);
12892         CHECK(dns_db_newversion(db, &newver));
12893
12894         /*
12895          * Try to apply diffs from the raw zone's journal to the secure
12896          * zone.  If that fails, we recover by syncing up the databases
12897          * directly.
12898          */
12899         result = sync_secure_journal(zone, rjournal, start, end,
12900                                      &soatuple, &diff);
12901         if (result == DNS_R_UNCHANGED)
12902                 goto failure;
12903         else if (result != ISC_R_SUCCESS)
12904                 CHECK(sync_secure_db(zone, db, oldver, &soatuple, &diff));
12905
12906         CHECK(dns_diff_apply(&diff, db, newver));
12907
12908         if (soatuple != NULL) {
12909                 isc_uint32_t oldserial, newserial, desired;
12910
12911                 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
12912                                             DNS_DIFFOP_DEL, &tuple));
12913                 oldserial = dns_soa_getserial(&tuple->rdata);
12914                 newserial = desired = dns_soa_getserial(&soatuple->rdata);
12915                 if (!isc_serial_gt(newserial, oldserial)) {
12916                         newserial = oldserial + 1;
12917                         if (newserial == 0)
12918                                 newserial++;
12919                         dns_soa_setserial(newserial, &soatuple->rdata);
12920                 }
12921                 CHECK(do_one_tuple(&tuple, db, newver, &diff));
12922                 CHECK(do_one_tuple(&soatuple, db, newver, &diff));
12923                 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
12924                              newserial, desired);
12925         } else
12926                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
12927                                         zone->updatemethod));
12928
12929         CHECK(dns_update_signatures(&log, zone, db, oldver, newver,
12930                                     &diff, zone->sigvalidityinterval));
12931
12932         CHECK(zone_journal(zone, &diff, &end, "receive_secure_serial"));
12933
12934         dns_journal_set_sourceserial(rjournal, end);
12935         dns_journal_commit(rjournal);
12936
12937         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12938
12939         zone->sourceserial = end;
12940         zone->sourceserialset = ISC_TRUE;
12941         zone_needdump(zone, DNS_DUMP_DELAY);
12942
12943         TIME_NOW(&timenow);
12944         zone_settimer(zone, &timenow);
12945
12946         dns_db_closeversion(db, &oldver, ISC_FALSE);
12947         dns_db_closeversion(db, &newver, ISC_TRUE);
12948
12949  failure:
12950         UNLOCK_ZONE(zone);
12951         if (result != ISC_R_SUCCESS)
12952                 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
12953                              dns_result_totext(result));
12954         if (tuple != NULL)
12955                 dns_difftuple_free(&tuple);
12956         if (soatuple != NULL)
12957                 dns_difftuple_free(&soatuple);
12958         if (db != NULL) {
12959                 if (oldver != NULL)
12960                         dns_db_closeversion(db, &oldver, ISC_FALSE);
12961                 if (newver != NULL)
12962                         dns_db_closeversion(db, &newver, ISC_FALSE);
12963                 dns_db_detach(&db);
12964         }
12965         if (rjournal != NULL)
12966                 dns_journal_destroy(&rjournal);
12967         dns_diff_clear(&diff);
12968         dns_zone_idetach(&zone);
12969 }
12970
12971 static isc_result_t
12972 zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) {
12973         isc_event_t *e;
12974         dns_zone_t *dummy = NULL;
12975
12976         e = isc_event_allocate(zone->secure->mctx, zone,
12977                                DNS_EVENT_ZONESECURESERIAL,
12978                                receive_secure_serial, zone->secure,
12979                                sizeof(struct secure_event));
12980         if (e == NULL)
12981                 return (ISC_R_NOMEMORY);
12982         ((struct secure_event *)e)->serial = serial;
12983         INSIST(LOCKED_ZONE(zone->secure));
12984         zone_iattach(zone->secure, &dummy);
12985         isc_task_send(zone->secure->task, &e);
12986
12987         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
12988         return (ISC_R_SUCCESS);
12989 }
12990
12991 static isc_result_t
12992 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
12993                dns_rdataset_t *rdataset, isc_uint32_t oldserial)
12994 {
12995         dns_rdata_soa_t soa;
12996         dns_rdata_t rdata = DNS_RDATA_INIT;
12997         dns_rdatalist_t temprdatalist;
12998         dns_rdataset_t temprdataset;
12999         isc_buffer_t b;
13000         isc_result_t result;
13001         unsigned char buf[DNS_SOA_BUFFERSIZE];
13002
13003         result = dns_rdataset_first(rdataset);
13004         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13005         dns_rdataset_current(rdataset, &rdata);
13006         result = dns_rdata_tostruct(&rdata, &soa, NULL);
13007         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13008
13009         if (isc_serial_gt(soa.serial, oldserial))
13010                 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
13011                                            NULL));
13012         /*
13013          * Always bump the serial.
13014          */
13015         oldserial++;
13016         if (oldserial == 0)
13017                 oldserial++;
13018         soa.serial = oldserial;
13019
13020         /*
13021          * Construct a replacement rdataset.
13022          */
13023         dns_rdata_reset(&rdata);
13024         isc_buffer_init(&b, buf, sizeof(buf));
13025         result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
13026                                       dns_rdatatype_soa, &soa, &b);
13027         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13028         temprdatalist.rdclass = rdata.rdclass;
13029         temprdatalist.type = rdata.type;
13030         temprdatalist.covers = 0;
13031         temprdatalist.ttl = rdataset->ttl;
13032         ISC_LIST_INIT(temprdatalist.rdata);
13033         ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
13034
13035         dns_rdataset_init(&temprdataset);
13036         result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
13037         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13038         return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
13039                                    0, NULL));
13040 }
13041
13042 /*
13043  * This function should populate an nsec3paramlist_t with the
13044  * nsecparam_t data from a zone.
13045  */
13046 static isc_result_t
13047 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
13048         isc_result_t result;
13049         dns_dbnode_t *node = NULL;
13050         dns_rdataset_t rdataset, prdataset;
13051         dns_rdata_t rdata_in, prdata_in, prdata_out;
13052         dns_dbversion_t *version = NULL;
13053         nsec3param_t *nsec3param = NULL;
13054         nsec3param_t *nsec3p = NULL;
13055         nsec3param_t *next;
13056         dns_db_t *db = NULL;
13057         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
13058
13059         REQUIRE(DNS_ZONE_VALID(zone));
13060         REQUIRE(nsec3list != NULL);
13061         REQUIRE(ISC_LIST_EMPTY(*nsec3list));
13062
13063         dns_db_attach(zone->db, &db);
13064         CHECK(dns_db_getoriginnode(db, &node));
13065
13066         dns_rdataset_init(&rdataset);
13067         dns_db_currentversion(db, &version);
13068         result = dns_db_findrdataset(db, node, version,
13069                                      dns_rdatatype_nsec3param,
13070                                      dns_rdatatype_none, 0, &rdataset, NULL);
13071
13072         if (result != ISC_R_SUCCESS)
13073                 goto getprivate;
13074
13075         /*
13076          * walk nsec3param rdataset making a list of parameters (note that
13077          * multiple simultaneous nsec3 chains are annoyingly legal -- this
13078          * is why we use an nsec3list, even tho we will usually only have
13079          * one)
13080          */
13081         for (result = dns_rdataset_first(&rdataset);
13082              result == ISC_R_SUCCESS;
13083              result = dns_rdataset_next(&rdataset))
13084         {
13085                 dns_rdata_init(&rdata_in);
13086                 dns_rdataset_current(&rdataset, &rdata_in);
13087                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13088                               DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13089                               "looping through nsec3param data");
13090                 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13091                 if (nsec3param == NULL)
13092                         CHECK(ISC_R_NOMEMORY);
13093                 ISC_LINK_INIT(nsec3param, link);
13094
13095                 /*
13096                  * now transfer the data from the rdata to
13097                  * the nsec3param
13098                  */
13099                 dns_rdata_init(&prdata_out);
13100                 dns_nsec3param_toprivate(&rdata_in, &prdata_out,
13101                                          zone->privatetype, nsec3param->data,
13102                                          sizeof(nsec3param->data));
13103                 nsec3param->length = prdata_out.length;
13104                 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13105         }
13106
13107  getprivate:
13108         dns_rdataset_init(&prdataset);
13109         result = dns_db_findrdataset(db, node, version, zone->privatetype,
13110                                      dns_rdatatype_none, 0, &prdataset, NULL);
13111         if (result != ISC_R_SUCCESS)
13112                 goto done;
13113
13114         /*
13115          * walk private type records, converting them to nsec3 parameters
13116          * using dns_nsec3param_fromprivate(), do the right thing based on
13117          * CREATE and REMOVE flags
13118          */
13119         for (result = dns_rdataset_first(&prdataset);
13120              result == ISC_R_SUCCESS;
13121              result = dns_rdataset_next(&prdataset))
13122         {
13123                 dns_rdata_init(&prdata_in);
13124                 dns_rdataset_current(&prdataset, &prdata_in);
13125                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13126                               DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13127                               "looping through nsec3param private data");
13128
13129                 if (!dns_nsec3param_fromprivate(&prdata_in, &prdata_out,
13130                                                 buf, sizeof(buf)))
13131                         continue;
13132
13133                 if ((prdata_out.data[1] & DNS_NSEC3FLAG_REMOVE) !=0) {
13134                         prdata_out.data[1] = 0;
13135
13136                         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13137                              nsec3p != NULL;
13138                              nsec3p = next)
13139                         {
13140                                 next = ISC_LIST_NEXT(nsec3p, link);
13141                                 if (memcmp(prdata_out.data, nsec3p->data,
13142                                     sizeof(nsec3p->data)) == 0) {
13143                                         ISC_LIST_UNLINK(*nsec3list,
13144                                                         nsec3p, link);
13145                                         isc_mem_put(zone->mctx, nsec3p,
13146                                                     sizeof(nsec3param_t));
13147                                 }
13148                         }
13149                         continue;
13150                 }
13151
13152                 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13153                 if (nsec3param == NULL)
13154                         CHECK(ISC_R_NOMEMORY);
13155                 ISC_LINK_INIT(nsec3param, link);
13156
13157                 dns_rdata_init(&prdata_out);
13158                 dns_nsec3param_toprivate(&prdata_in, &prdata_out,
13159                         zone->privatetype, nsec3param->data,
13160                         sizeof(nsec3param->data));
13161                 nsec3param->length = prdata_out.length;
13162                 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13163         }
13164
13165  done:
13166         if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
13167                 result = ISC_R_SUCCESS;
13168
13169  failure:
13170         if (node != NULL)
13171                 dns_db_detachnode(db, &node);
13172         if (version != NULL)
13173                 dns_db_closeversion(db, &version, ISC_FALSE);
13174         if (db != NULL)
13175                 dns_db_detach(&db);
13176         if (dns_rdataset_isassociated(&rdataset))
13177                 dns_rdataset_disassociate(&rdataset);
13178         if (dns_rdataset_isassociated(&prdataset))
13179                 dns_rdataset_disassociate(&prdataset);
13180         return (result);
13181 }
13182
13183 /*
13184  * Walk the list of the nsec3 chains desired for the zone, converting
13185  * parameters to private type records using dns_nsec3param_toprivate(),
13186  * and insert them into the new zone db.
13187  */
13188 static isc_result_t
13189 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
13190                    nsec3paramlist_t *nsec3list)
13191 {
13192         isc_result_t result;
13193         dns_diff_t diff;
13194         dns_rdata_t rdata;
13195         nsec3param_t *nsec3p = NULL;
13196         nsec3param_t *next;
13197
13198         REQUIRE(DNS_ZONE_VALID(zone));
13199         REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
13200
13201         dns_diff_init(zone->mctx, &diff);
13202
13203         /*
13204          * Loop through the list of private-type records, set the INITIAL
13205          * and CREATE flags, and the add the record to the apex of the tree
13206          * in db.
13207          */
13208         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13209              nsec3p != NULL;
13210              nsec3p = next)
13211         {
13212                 next = ISC_LIST_NEXT(nsec3p, link);
13213                 dns_rdata_init(&rdata);
13214                 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
13215                 rdata.length = nsec3p->length;
13216                 rdata.data = nsec3p->data;
13217                 rdata.type = zone->privatetype;
13218                 rdata.rdclass = zone->rdclass;
13219                 CHECK(update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
13220                                     &zone->origin, 0, &rdata));
13221         }
13222
13223         result = ISC_R_SUCCESS;
13224
13225 failure:
13226         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13227              nsec3p != NULL;
13228              nsec3p = next)
13229         {
13230                 next = ISC_LIST_NEXT(nsec3p, link);
13231                 ISC_LIST_UNLINK(*nsec3list, nsec3p, link);
13232                 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
13233         }
13234
13235         dns_diff_clear(&diff);
13236         return (result);
13237 }
13238
13239 static void
13240 receive_secure_db(isc_task_t *task, isc_event_t *event) {
13241         isc_result_t result;
13242         dns_zone_t *zone;
13243         dns_db_t *rawdb, *db = NULL;
13244         dns_dbnode_t *rawnode = NULL, *node = NULL;
13245         dns_fixedname_t fname;
13246         dns_name_t *name;
13247         dns_dbiterator_t *dbiterator = NULL;
13248         dns_rdatasetiter_t *rdsit = NULL;
13249         dns_rdataset_t rdataset;
13250         dns_dbversion_t *version = NULL;
13251         isc_time_t loadtime;
13252         unsigned int oldserial = 0;
13253         isc_boolean_t have_oldserial = ISC_FALSE;
13254         nsec3paramlist_t nsec3list;
13255
13256         UNUSED(task);
13257
13258         ISC_LIST_INIT(nsec3list);
13259
13260         zone = event->ev_arg;
13261         rawdb = ((struct secure_event *)event)->db;
13262         isc_event_free(&event);
13263
13264         dns_fixedname_init(&fname);
13265         name = dns_fixedname_name(&fname);
13266         dns_rdataset_init(&rdataset);
13267
13268         LOCK_ZONE(zone);
13269         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
13270                 result = ISC_R_SHUTTINGDOWN;
13271                 goto failure;
13272         }
13273
13274         TIME_NOW(&loadtime);
13275         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13276         if (zone->db != NULL) {
13277                 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
13278                 if (result == ISC_R_SUCCESS)
13279                         have_oldserial = ISC_TRUE;
13280
13281                 /*
13282                  * assemble nsec3parameters from the old zone, and set a flag
13283                  * if any are found
13284                  */
13285                 result = save_nsec3param(zone, &nsec3list);
13286                 if (result != ISC_R_SUCCESS) {
13287                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13288                         goto failure;
13289                 }
13290         }
13291         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13292
13293         result = dns_db_create(zone->mctx, zone->db_argv[0],
13294                                &zone->origin, dns_dbtype_zone, zone->rdclass,
13295                                zone->db_argc - 1, zone->db_argv + 1, &db);
13296         if (result != ISC_R_SUCCESS)
13297                 goto failure;
13298
13299         result = dns_db_newversion(db, &version);
13300         if (result != ISC_R_SUCCESS)
13301                 goto failure;
13302
13303         result = dns_db_createiterator(rawdb, 0, &dbiterator);
13304         if (result != ISC_R_SUCCESS)
13305                 goto failure;
13306
13307         for (result = dns_dbiterator_first(dbiterator);
13308              result == ISC_R_SUCCESS;
13309              result = dns_dbiterator_next(dbiterator)) {
13310                 result = dns_dbiterator_current(dbiterator, &rawnode, name);
13311                 if (result != ISC_R_SUCCESS)
13312                         continue;
13313
13314                 result = dns_db_findnode(db, name, ISC_TRUE, &node);
13315                 if (result != ISC_R_SUCCESS)
13316                         goto failure;
13317
13318                 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
13319                 if (result != ISC_R_SUCCESS)
13320                         goto failure;
13321
13322                 for (result = dns_rdatasetiter_first(rdsit);
13323                      result == ISC_R_SUCCESS;
13324                      result = dns_rdatasetiter_next(rdsit)) {
13325                         dns_rdatasetiter_current(rdsit, &rdataset);
13326                         if (rdataset.type == dns_rdatatype_nsec ||
13327                             rdataset.type == dns_rdatatype_rrsig ||
13328                             rdataset.type == dns_rdatatype_nsec3 ||
13329                             rdataset.type == dns_rdatatype_dnskey ||
13330                             rdataset.type == dns_rdatatype_nsec3param) {
13331                                 dns_rdataset_disassociate(&rdataset);
13332                                 continue;
13333                         }
13334                         if (rdataset.type == dns_rdatatype_soa &&
13335                             have_oldserial) {
13336                                 result = checkandaddsoa(db, node, version,
13337                                                         &rdataset, oldserial);
13338                         } else
13339                                 result = dns_db_addrdataset(db, node, version,
13340                                                             0, &rdataset, 0,
13341                                                             NULL);
13342                         if (result != ISC_R_SUCCESS)
13343                                 goto failure;
13344
13345                         dns_rdataset_disassociate(&rdataset);
13346                 }
13347                 dns_rdatasetiter_destroy(&rdsit);
13348                 dns_db_detachnode(rawdb, &rawnode);
13349                 dns_db_detachnode(db, &node);
13350         }
13351
13352         /*
13353          * Call restore_nsec3param() to create private-type records from
13354          * the old nsec3 parameters and insert them into db
13355          */
13356         if (!ISC_LIST_EMPTY(nsec3list))
13357                 restore_nsec3param(zone, db, version, &nsec3list);
13358
13359         dns_db_closeversion(db, &version, ISC_TRUE);
13360
13361         /*
13362          * Lock hierarchy: zmgr, zone, raw.
13363          */
13364         INSIST(zone != zone->raw);
13365         LOCK_ZONE(zone->raw);
13366         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13367         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
13368         zone_needdump(zone, 0); /* XXXMPA */
13369         UNLOCK_ZONE(zone->raw);
13370
13371  failure:
13372         UNLOCK_ZONE(zone);
13373         if (result != ISC_R_SUCCESS)
13374                 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
13375                              dns_result_totext(result));
13376
13377         if (dns_rdataset_isassociated(&rdataset))
13378                 dns_rdataset_disassociate(&rdataset);
13379         if (db != NULL) {
13380                 if (node != NULL)
13381                         dns_db_detachnode(db, &node);
13382                 dns_db_detach(&db);
13383         }
13384         if (rawnode != NULL)
13385                 dns_db_detachnode(rawdb, &rawnode);
13386         dns_db_detach(&rawdb);
13387         if (dbiterator != NULL)
13388                 dns_dbiterator_destroy(&dbiterator);
13389         dns_zone_idetach(&zone);
13390 }
13391
13392 static isc_result_t
13393 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
13394         isc_event_t *e;
13395         dns_db_t *dummy = NULL;
13396         dns_zone_t *secure = NULL;
13397
13398         e = isc_event_allocate(zone->secure->mctx, zone,
13399                                DNS_EVENT_ZONESECUREDB,
13400                                receive_secure_db, zone->secure,
13401                                sizeof(struct secure_event));
13402         if (e == NULL)
13403                 return (ISC_R_NOMEMORY);
13404         dns_db_attach(db, &dummy);
13405         ((struct secure_event *)e)->db = dummy;
13406         INSIST(LOCKED_ZONE(zone->secure));
13407         zone_iattach(zone->secure, &secure);
13408         isc_task_send(zone->secure->task, &e);
13409         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
13410         return (ISC_R_SUCCESS);
13411 }
13412
13413 isc_result_t
13414 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13415         isc_result_t result;
13416         dns_zone_t *secure = NULL;
13417
13418         REQUIRE(DNS_ZONE_VALID(zone));
13419  again:
13420         LOCK_ZONE(zone);
13421         if (inline_raw(zone)) {
13422                 secure = zone->secure;
13423                 INSIST(secure != zone);
13424                 TRYLOCK_ZONE(result, secure);
13425                 if (result != ISC_R_SUCCESS) {
13426                         UNLOCK_ZONE(zone);
13427                         secure = NULL;
13428 #if ISC_PLATFORM_USETHREADS
13429                         isc_thread_yield();
13430 #endif
13431                         goto again;
13432                 }
13433         }
13434         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13435         result = zone_replacedb(zone, db, dump);
13436         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13437         if (secure != NULL)
13438                 UNLOCK_ZONE(secure);
13439         UNLOCK_ZONE(zone);
13440         return (result);
13441 }
13442
13443 static isc_result_t
13444 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13445         dns_dbversion_t *ver;
13446         isc_result_t result;
13447         unsigned int soacount = 0;
13448         unsigned int nscount = 0;
13449
13450         /*
13451          * 'zone' and 'zonedb' locked by caller.
13452          */
13453         REQUIRE(DNS_ZONE_VALID(zone));
13454         REQUIRE(LOCKED_ZONE(zone));
13455         if (inline_raw(zone))
13456                 REQUIRE(LOCKED_ZONE(zone->secure));
13457
13458         result = zone_get_from_db(zone, db, &nscount, &soacount,
13459                                   NULL, NULL, NULL, NULL, NULL, NULL);
13460         if (result == ISC_R_SUCCESS) {
13461                 if (soacount != 1) {
13462                         dns_zone_log(zone, ISC_LOG_ERROR,
13463                                      "has %d SOA records", soacount);
13464                         result = DNS_R_BADZONE;
13465                 }
13466                 if (nscount == 0 && zone->type != dns_zone_key) {
13467                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
13468                         result = DNS_R_BADZONE;
13469                 }
13470                 if (result != ISC_R_SUCCESS)
13471                         return (result);
13472         } else {
13473                 dns_zone_log(zone, ISC_LOG_ERROR,
13474                             "retrieving SOA and NS records failed: %s",
13475                             dns_result_totext(result));
13476                 return (result);
13477         }
13478
13479         result = check_nsec3param(zone, db);
13480         if (result != ISC_R_SUCCESS)
13481                 return (result);
13482
13483         ver = NULL;
13484         dns_db_currentversion(db, &ver);
13485
13486         /*
13487          * The initial version of a slave zone is always dumped;
13488          * subsequent versions may be journaled instead if this
13489          * is enabled in the configuration.
13490          */
13491         if (zone->db != NULL && zone->journal != NULL &&
13492             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
13493             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
13494         {
13495                 isc_uint32_t serial, oldserial;
13496                 unsigned int soacount;
13497
13498                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
13499
13500                 result = dns_db_getsoaserial(db, ver, &serial);
13501                 if (result != ISC_R_SUCCESS) {
13502                         dns_zone_log(zone, ISC_LOG_ERROR,
13503                                      "ixfr-from-differences: unable to get "
13504                                      "new serial");
13505                         goto fail;
13506                 }
13507
13508                 /*
13509                  * This is checked in zone_postload() for master zones.
13510                  */
13511                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
13512                                           &oldserial, NULL, NULL, NULL, NULL,
13513                                           NULL);
13514                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13515                 RUNTIME_CHECK(soacount > 0U);
13516                 if ((zone->type == dns_zone_slave ||
13517                      (zone->type == dns_zone_redirect &&
13518                       zone->masters != NULL))
13519                     && !isc_serial_gt(serial, oldserial)) {
13520                         isc_uint32_t serialmin, serialmax;
13521                         serialmin = (oldserial + 1) & 0xffffffffU;
13522                         serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
13523                         dns_zone_log(zone, ISC_LOG_ERROR,
13524                                      "ixfr-from-differences: failed: "
13525                                      "new serial (%u) out of range [%u - %u]",
13526                                      serial, serialmin, serialmax);
13527                         result = ISC_R_RANGE;
13528                         goto fail;
13529                 }
13530
13531                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
13532                                      zone->journal);
13533                 if (result != ISC_R_SUCCESS)
13534                         goto fail;
13535                 if (dump)
13536                         zone_needdump(zone, DNS_DUMP_DELAY);
13537                 else if (zone->journalsize != -1) {
13538                         result = dns_journal_compact(zone->mctx, zone->journal,
13539                                                      serial, zone->journalsize);
13540                         switch (result) {
13541                         case ISC_R_SUCCESS:
13542                         case ISC_R_NOSPACE:
13543                         case ISC_R_NOTFOUND:
13544                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
13545                                              "dns_journal_compact: %s",
13546                                              dns_result_totext(result));
13547                                 break;
13548                         default:
13549                                 dns_zone_log(zone, ISC_LOG_ERROR,
13550                                              "dns_journal_compact failed: %s",
13551                                              dns_result_totext(result));
13552                                 break;
13553                         }
13554                 }
13555                 if (zone->type == dns_zone_master && inline_raw(zone))
13556                         zone_send_secureserial(zone, serial);
13557         } else {
13558                 if (dump && zone->masterfile != NULL) {
13559                         /*
13560                          * If DNS_ZONEFLG_FORCEXFER was set we don't want
13561                          * to keep the old masterfile.
13562                          */
13563                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
13564                             remove(zone->masterfile) < 0 && errno != ENOENT) {
13565                                 char strbuf[ISC_STRERRORSIZE];
13566                                 isc__strerror(errno, strbuf, sizeof(strbuf));
13567                                 isc_log_write(dns_lctx,
13568                                               DNS_LOGCATEGORY_GENERAL,
13569                                               DNS_LOGMODULE_ZONE,
13570                                               ISC_LOG_WARNING,
13571                                               "unable to remove masterfile "
13572                                               "'%s': '%s'",
13573                                               zone->masterfile, strbuf);
13574                         }
13575                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
13576                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
13577                         else
13578                                 zone_needdump(zone, 0);
13579                 }
13580                 if (dump && zone->journal != NULL) {
13581                         /*
13582                          * The in-memory database just changed, and
13583                          * because 'dump' is set, it didn't change by
13584                          * being loaded from disk.  Also, we have not
13585                          * journaled diffs for this change.
13586                          * Therefore, the on-disk journal is missing
13587                          * the deltas for this change.  Since it can
13588                          * no longer be used to bring the zone
13589                          * up-to-date, it is useless and should be
13590                          * removed.
13591                          */
13592                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13593                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13594                                       "removing journal file");
13595                         if (remove(zone->journal) < 0 && errno != ENOENT) {
13596                                 char strbuf[ISC_STRERRORSIZE];
13597                                 isc__strerror(errno, strbuf, sizeof(strbuf));
13598                                 isc_log_write(dns_lctx,
13599                                               DNS_LOGCATEGORY_GENERAL,
13600                                               DNS_LOGMODULE_ZONE,
13601                                               ISC_LOG_WARNING,
13602                                               "unable to remove journal "
13603                                               "'%s': '%s'",
13604                                               zone->journal, strbuf);
13605                         }
13606                 }
13607
13608                 if (inline_raw(zone))
13609                         zone_send_securedb(zone, db);
13610         }
13611
13612         dns_db_closeversion(db, &ver, ISC_FALSE);
13613
13614         dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
13615
13616         if (zone->db != NULL)
13617                 zone_detachdb(zone);
13618         zone_attachdb(zone, db);
13619         dns_db_settask(zone->db, zone->task);
13620         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
13621         return (ISC_R_SUCCESS);
13622
13623  fail:
13624         dns_db_closeversion(db, &ver, ISC_FALSE);
13625         return (result);
13626 }
13627
13628 /* The caller must hold the dblock as a writer. */
13629 static inline void
13630 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
13631         REQUIRE(zone->db == NULL && db != NULL);
13632
13633         dns_db_attach(db, &zone->db);
13634         if (zone->acache != NULL) {
13635                 isc_result_t result;
13636                 result = dns_acache_setdb(zone->acache, db);
13637                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
13638                         UNEXPECTED_ERROR(__FILE__, __LINE__,
13639                                          "dns_acache_setdb() failed: %s",
13640                                          isc_result_totext(result));
13641                 }
13642         }
13643 }
13644
13645 /* The caller must hold the dblock as a writer. */
13646 static inline void
13647 zone_detachdb(dns_zone_t *zone) {
13648         REQUIRE(zone->db != NULL);
13649
13650         if (zone->acache != NULL)
13651                 (void)dns_acache_putdb(zone->acache, zone->db);
13652         dns_db_detach(&zone->db);
13653 }
13654
13655 static void
13656 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
13657         isc_time_t now;
13658         isc_boolean_t again = ISC_FALSE;
13659         unsigned int soacount;
13660         unsigned int nscount;
13661         isc_uint32_t serial, refresh, retry, expire, minimum;
13662         isc_result_t xfrresult = result;
13663         isc_boolean_t free_needed;
13664         dns_zone_t *secure = NULL;
13665
13666         REQUIRE(DNS_ZONE_VALID(zone));
13667
13668         dns_zone_log(zone, ISC_LOG_DEBUG(1),
13669                      "zone transfer finished: %s", dns_result_totext(result));
13670
13671         /*
13672          * Obtaining a lock on the zone->secure (see zone_send_secureserial)
13673          * could result in a deadlock due to a LOR so we will spin if we
13674          * can't obtain the both locks.
13675          */
13676  again:
13677         LOCK_ZONE(zone);
13678         if (inline_raw(zone)) {
13679                 secure = zone->secure;
13680                 INSIST(secure != zone);
13681                 TRYLOCK_ZONE(result, secure);
13682                 if (result != ISC_R_SUCCESS) {
13683                         UNLOCK_ZONE(zone);
13684                         secure = NULL;
13685 #if ISC_PLATFORM_USETHREADS
13686                         isc_thread_yield();
13687 #endif
13688                         goto again;
13689                 }
13690         }
13691
13692         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
13693         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13694         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
13695
13696         TIME_NOW(&now);
13697         switch (result) {
13698         case ISC_R_SUCCESS:
13699                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13700                 /*FALLTHROUGH*/
13701         case DNS_R_UPTODATE:
13702                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13703                 /*
13704                  * Has the zone expired underneath us?
13705                  */
13706                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13707                 if (zone->db == NULL) {
13708                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13709                         goto same_master;
13710                 }
13711
13712                 /*
13713                  * Update the zone structure's data from the actual
13714                  * SOA received.
13715                  */
13716                 nscount = 0;
13717                 soacount = 0;
13718                 INSIST(zone->db != NULL);
13719                 result = zone_get_from_db(zone, zone->db, &nscount,
13720                                           &soacount, &serial, &refresh,
13721                                           &retry, &expire, &minimum, NULL);
13722                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13723                 if (result == ISC_R_SUCCESS) {
13724                         if (soacount != 1)
13725                                 dns_zone_log(zone, ISC_LOG_ERROR,
13726                                              "transferred zone "
13727                                              "has %d SOA record%s", soacount,
13728                                              (soacount != 0) ? "s" : "");
13729                         if (nscount == 0) {
13730                                 dns_zone_log(zone, ISC_LOG_ERROR,
13731                                              "transferred zone "
13732                                              "has no NS records");
13733                                 if (DNS_ZONE_FLAG(zone,
13734                                                   DNS_ZONEFLG_HAVETIMERS)) {
13735                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
13736                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
13737                                 }
13738                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13739                                 zone_unload(zone);
13740                                 goto next_master;
13741                         }
13742                         zone->refresh = RANGE(refresh, zone->minrefresh,
13743                                               zone->maxrefresh);
13744                         zone->retry = RANGE(retry, zone->minretry,
13745                                             zone->maxretry);
13746                         zone->expire = RANGE(expire,
13747                                              zone->refresh + zone->retry,
13748                                              DNS_MAX_EXPIRE);
13749                         zone->minimum = minimum;
13750                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13751                 }
13752
13753                 /*
13754                  * Set our next update/expire times.
13755                  */
13756                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
13757                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13758                         zone->refreshtime = now;
13759                         DNS_ZONE_TIME_ADD(&now, zone->expire,
13760                                           &zone->expiretime);
13761                 } else {
13762                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
13763                                             &zone->refreshtime);
13764                         DNS_ZONE_TIME_ADD(&now, zone->expire,
13765                                           &zone->expiretime);
13766                 }
13767                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
13768                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
13769                         if (zone->tsigkey != NULL) {
13770                                 char namebuf[DNS_NAME_FORMATSIZE];
13771                                 dns_name_format(&zone->tsigkey->name, namebuf,
13772                                                 sizeof(namebuf));
13773                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
13774                                          namebuf);
13775                         } else
13776                                 buf[0] = '\0';
13777                         dns_zone_log(zone, ISC_LOG_INFO,
13778                                      "transferred serial %u%s",
13779                                      serial, buf);
13780                         if (inline_raw(zone))
13781                                 zone_send_secureserial(zone, serial);
13782                 }
13783
13784                 /*
13785                  * This is not necessary if we just performed a AXFR
13786                  * however it is necessary for an IXFR / UPTODATE and
13787                  * won't hurt with an AXFR.
13788                  */
13789                 if (zone->masterfile != NULL || zone->journal != NULL) {
13790                         unsigned int delay = DNS_DUMP_DELAY;
13791
13792                         result = ISC_R_FAILURE;
13793                         if (zone->journal != NULL)
13794                                 result = isc_file_settime(zone->journal, &now);
13795                         if (result != ISC_R_SUCCESS &&
13796                             zone->masterfile != NULL)
13797                                 result = isc_file_settime(zone->masterfile,
13798                                                           &now);
13799
13800                         if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
13801                             result == ISC_R_FILENOTFOUND)
13802                                 delay = 0;
13803
13804                         if ((result == ISC_R_SUCCESS ||
13805                             result == ISC_R_FILENOTFOUND) &&
13806                             zone->masterfile != NULL)
13807                                 zone_needdump(zone, delay);
13808                         else if (result != ISC_R_SUCCESS)
13809                                 dns_zone_log(zone, ISC_LOG_ERROR,
13810                                              "transfer: could not set file "
13811                                              "modification time of '%s': %s",
13812                                              zone->masterfile,
13813                                              dns_result_totext(result));
13814                 }
13815                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
13816                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
13817                 break;
13818
13819         case DNS_R_BADIXFR:
13820                 /* Force retry with AXFR. */
13821                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
13822                 goto same_master;
13823
13824         default:
13825         next_master:
13826                 /*
13827                  * Skip to next failed / untried master.
13828                  */
13829                 do {
13830                         zone->curmaster++;
13831                 } while (zone->curmaster < zone->masterscnt &&
13832                          zone->mastersok[zone->curmaster]);
13833                 /* FALLTHROUGH */
13834         same_master:
13835                 if (zone->curmaster >= zone->masterscnt) {
13836                         zone->curmaster = 0;
13837                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13838                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13839                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
13840                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13841                                 while (zone->curmaster < zone->masterscnt &&
13842                                        zone->mastersok[zone->curmaster])
13843                                         zone->curmaster++;
13844                                 again = ISC_TRUE;
13845                         } else
13846                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13847                 } else {
13848                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
13849                         again = ISC_TRUE;
13850                 }
13851                 inc_stats(zone, dns_zonestatscounter_xfrfail);
13852                 break;
13853         }
13854         zone_settimer(zone, &now);
13855
13856         /*
13857          * If creating the transfer object failed, zone->xfr is NULL.
13858          * Otherwise, we are called as the done callback of a zone
13859          * transfer object that just entered its shutting-down
13860          * state.  Since we are no longer responsible for shutting
13861          * it down, we can detach our reference.
13862          */
13863         if (zone->xfr != NULL)
13864                 dns_xfrin_detach(&zone->xfr);
13865
13866         if (zone->tsigkey != NULL)
13867                 dns_tsigkey_detach(&zone->tsigkey);
13868
13869         /*
13870          * Handle any deferred journal compaction.
13871          */
13872         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
13873                 result = dns_journal_compact(zone->mctx, zone->journal,
13874                                              zone->compact_serial,
13875                                              zone->journalsize);
13876                 switch (result) {
13877                 case ISC_R_SUCCESS:
13878                 case ISC_R_NOSPACE:
13879                 case ISC_R_NOTFOUND:
13880                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
13881                                      "dns_journal_compact: %s",
13882                                      dns_result_totext(result));
13883                         break;
13884                 default:
13885                         dns_zone_log(zone, ISC_LOG_ERROR,
13886                                      "dns_journal_compact failed: %s",
13887                                      dns_result_totext(result));
13888                         break;
13889                 }
13890                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
13891         }
13892
13893         if (secure != NULL)
13894                 UNLOCK_ZONE(secure);
13895         /*
13896          * This transfer finishing freed up a transfer quota slot.
13897          * Let any other zones waiting for quota have it.
13898          */
13899         if (zone->zmgr != NULL &&
13900             zone->statelist == &zone->zmgr->xfrin_in_progress) {
13901                 UNLOCK_ZONE(zone);
13902                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13903                 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
13904                 zone->statelist = NULL;
13905                 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
13906                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13907                 LOCK_ZONE(zone);
13908         }
13909
13910         /*
13911          * Retry with a different server if necessary.
13912          */
13913         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
13914                 queue_soa_query(zone);
13915
13916         INSIST(zone->irefs > 0);
13917         zone->irefs--;
13918         free_needed = exit_check(zone);
13919         UNLOCK_ZONE(zone);
13920         if (free_needed)
13921                 zone_free(zone);
13922 }
13923
13924 static void
13925 zone_loaddone(void *arg, isc_result_t result) {
13926         static char me[] = "zone_loaddone";
13927         dns_load_t *load = arg;
13928         dns_zone_t *zone;
13929         isc_result_t tresult;
13930         dns_zone_t *secure = NULL;
13931
13932         REQUIRE(DNS_LOAD_VALID(load));
13933         zone = load->zone;
13934
13935         ENTER;
13936
13937         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
13938         if (tresult != ISC_R_SUCCESS &&
13939             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
13940                 result = tresult;
13941
13942         /*
13943          * Lock hierarchy: zmgr, zone, raw.
13944          */
13945  again:
13946         LOCK_ZONE(zone);
13947         if (inline_secure(zone))
13948                 LOCK_ZONE(zone->raw);
13949         else if (inline_raw(zone)) {
13950                 secure = zone->secure;
13951                 TRYLOCK_ZONE(result, secure);
13952                 if (result != ISC_R_SUCCESS) {
13953                         UNLOCK_ZONE(zone);
13954                         secure = NULL;
13955 #if ISC_PLATFORM_USETHREADS
13956                         isc_thread_yield();
13957 #endif
13958                         goto again;
13959                 }
13960         }
13961         (void)zone_postload(zone, load->db, load->loadtime, result);
13962         zonemgr_putio(&zone->readio);
13963         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
13964         zone_idetach(&load->callbacks.zone);
13965         /*
13966          * Leave the zone frozen if the reload fails.
13967          */
13968         if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
13969              DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
13970                 zone->update_disabled = ISC_FALSE;
13971         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
13972         if (inline_secure(zone))
13973                 UNLOCK_ZONE(zone->raw);
13974         else if (secure != NULL)
13975                 UNLOCK_ZONE(secure);
13976         UNLOCK_ZONE(zone);
13977
13978         load->magic = 0;
13979         dns_db_detach(&load->db);
13980         if (load->zone->lctx != NULL)
13981                 dns_loadctx_detach(&load->zone->lctx);
13982         dns_zone_idetach(&load->zone);
13983         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
13984 }
13985
13986 void
13987 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
13988         REQUIRE(DNS_ZONE_VALID(zone));
13989         REQUIRE(table != NULL);
13990         REQUIRE(*table == NULL);
13991
13992         LOCK_ZONE(zone);
13993         if (zone->ssutable != NULL)
13994                 dns_ssutable_attach(zone->ssutable, table);
13995         UNLOCK_ZONE(zone);
13996 }
13997
13998 void
13999 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
14000         REQUIRE(DNS_ZONE_VALID(zone));
14001
14002         LOCK_ZONE(zone);
14003         if (zone->ssutable != NULL)
14004                 dns_ssutable_detach(&zone->ssutable);
14005         if (table != NULL)
14006                 dns_ssutable_attach(table, &zone->ssutable);
14007         UNLOCK_ZONE(zone);
14008 }
14009
14010 void
14011 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
14012         REQUIRE(DNS_ZONE_VALID(zone));
14013
14014         zone->sigvalidityinterval = interval;
14015 }
14016
14017 isc_uint32_t
14018 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
14019         REQUIRE(DNS_ZONE_VALID(zone));
14020
14021         return (zone->sigvalidityinterval);
14022 }
14023
14024 void
14025 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
14026         isc_time_t now;
14027
14028         REQUIRE(DNS_ZONE_VALID(zone));
14029
14030         LOCK_ZONE(zone);
14031         zone->sigresigninginterval = interval;
14032         set_resigntime(zone);
14033         if (zone->task != NULL) {
14034                 TIME_NOW(&now);
14035                 zone_settimer(zone, &now);
14036         }
14037         UNLOCK_ZONE(zone);
14038 }
14039
14040 isc_uint32_t
14041 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
14042         REQUIRE(DNS_ZONE_VALID(zone));
14043
14044         return (zone->sigresigninginterval);
14045 }
14046
14047 static void
14048 queue_xfrin(dns_zone_t *zone) {
14049         const char me[] = "queue_xfrin";
14050         isc_result_t result;
14051         dns_zonemgr_t *zmgr = zone->zmgr;
14052
14053         ENTER;
14054
14055         INSIST(zone->statelist == NULL);
14056
14057         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14058         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
14059         LOCK_ZONE(zone);
14060         zone->irefs++;
14061         UNLOCK_ZONE(zone);
14062         zone->statelist = &zmgr->waiting_for_xfrin;
14063         result = zmgr_start_xfrin_ifquota(zmgr, zone);
14064         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14065
14066         if (result == ISC_R_QUOTA) {
14067                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14068                               "zone transfer deferred due to quota");
14069         } else if (result != ISC_R_SUCCESS) {
14070                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
14071                               "starting zone transfer: %s",
14072                               isc_result_totext(result));
14073         }
14074 }
14075
14076 /*
14077  * This event callback is called when a zone has received
14078  * any necessary zone transfer quota.  This is the time
14079  * to go ahead and start the transfer.
14080  */
14081 static void
14082 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
14083         isc_result_t result = ISC_R_SUCCESS;
14084         dns_peer_t *peer = NULL;
14085         char master[ISC_SOCKADDR_FORMATSIZE];
14086         char source[ISC_SOCKADDR_FORMATSIZE];
14087         dns_rdatatype_t xfrtype;
14088         dns_zone_t *zone = event->ev_arg;
14089         isc_netaddr_t masterip;
14090         isc_sockaddr_t sourceaddr;
14091         isc_sockaddr_t masteraddr;
14092         isc_time_t now;
14093         const char *soa_before = "";
14094         isc_boolean_t loaded;
14095
14096         UNUSED(task);
14097
14098         INSIST(task == zone->task);
14099
14100         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14101                 result = ISC_R_CANCELED;
14102                 goto cleanup;
14103         }
14104
14105         TIME_NOW(&now);
14106
14107         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
14108         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
14109                                     &zone->sourceaddr, &now))
14110         {
14111                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14112                 dns_zone_log(zone, ISC_LOG_INFO,
14113                              "got_transfer_quota: skipping zone transfer as "
14114                              "master %s (source %s) is unreachable (cached)",
14115                              master, source);
14116                 result = ISC_R_CANCELED;
14117                 goto cleanup;
14118         }
14119
14120         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14121         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
14122
14123         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14124                 soa_before = "SOA before ";
14125         /*
14126          * Decide whether we should request IXFR or AXFR.
14127          */
14128         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14129         loaded = ISC_TF(zone->db != NULL);
14130         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14131
14132         if (!loaded) {
14133                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14134                              "no database exists yet, requesting AXFR of "
14135                              "initial version from %s", master);
14136                 xfrtype = dns_rdatatype_axfr;
14137         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
14138                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14139                              "forced reload, requesting AXFR of "
14140                              "initial version from %s", master);
14141                 xfrtype = dns_rdatatype_axfr;
14142         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
14143                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14144                              "retrying with AXFR from %s due to "
14145                              "previous IXFR failure", master);
14146                 xfrtype = dns_rdatatype_axfr;
14147                 LOCK_ZONE(zone);
14148                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
14149                 UNLOCK_ZONE(zone);
14150         } else {
14151                 isc_boolean_t use_ixfr = ISC_TRUE;
14152                 if (peer != NULL)
14153                         result = dns_peer_getrequestixfr(peer, &use_ixfr);
14154                 if (peer == NULL || result != ISC_R_SUCCESS)
14155                         use_ixfr = zone->requestixfr;
14156                 if (use_ixfr == ISC_FALSE) {
14157                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
14158                                      "IXFR disabled, requesting %sAXFR from %s",
14159                                      soa_before, master);
14160                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14161                                 xfrtype = dns_rdatatype_soa;
14162                         else
14163                                 xfrtype = dns_rdatatype_axfr;
14164                 } else {
14165                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
14166                                      "requesting IXFR from %s", master);
14167                         xfrtype = dns_rdatatype_ixfr;
14168                 }
14169         }
14170
14171         /*
14172          * Determine if we should attempt to sign the request with TSIG.
14173          */
14174         result = ISC_R_NOTFOUND;
14175         /*
14176          * First, look for a tsig key in the master statement, then
14177          * try for a server key.
14178          */
14179         if ((zone->masterkeynames != NULL) &&
14180             (zone->masterkeynames[zone->curmaster] != NULL)) {
14181                 dns_view_t *view = dns_zone_getview(zone);
14182                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14183                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
14184         }
14185         if (zone->tsigkey == NULL)
14186                 result = dns_view_getpeertsig(zone->view, &masterip,
14187                                               &zone->tsigkey);
14188
14189         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14190                 dns_zone_log(zone, ISC_LOG_ERROR,
14191                              "could not get TSIG key for zone transfer: %s",
14192                              isc_result_totext(result));
14193         }
14194
14195         LOCK_ZONE(zone);
14196         masteraddr = zone->masteraddr;
14197         sourceaddr = zone->sourceaddr;
14198         UNLOCK_ZONE(zone);
14199         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
14200         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
14201                                    zone->tsigkey, zone->mctx,
14202                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
14203                                    zone->task, zone_xfrdone, &zone->xfr);
14204         if (result == ISC_R_SUCCESS) {
14205                 LOCK_ZONE(zone);
14206                 if (xfrtype == dns_rdatatype_axfr) {
14207                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14208                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
14209                         else
14210                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
14211                 } else if (xfrtype == dns_rdatatype_ixfr) {
14212                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14213                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
14214                         else
14215                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
14216                 }
14217                 UNLOCK_ZONE(zone);
14218         }
14219  cleanup:
14220         /*
14221          * Any failure in this function is handled like a failed
14222          * zone transfer.  This ensures that we get removed from
14223          * zmgr->xfrin_in_progress.
14224          */
14225         if (result != ISC_R_SUCCESS)
14226                 zone_xfrdone(zone, result);
14227
14228         isc_event_free(&event);
14229 }
14230
14231 /*
14232  * Update forwarding support.
14233  */
14234
14235 static void
14236 forward_destroy(dns_forward_t *forward) {
14237
14238         forward->magic = 0;
14239         if (forward->request != NULL)
14240                 dns_request_destroy(&forward->request);
14241         if (forward->msgbuf != NULL)
14242                 isc_buffer_free(&forward->msgbuf);
14243         if (forward->zone != NULL) {
14244                 LOCK(&forward->zone->lock);
14245                 if (ISC_LINK_LINKED(forward, link))
14246                         ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
14247                 UNLOCK(&forward->zone->lock);
14248                 dns_zone_idetach(&forward->zone);
14249         }
14250         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
14251 }
14252
14253 static isc_result_t
14254 sendtomaster(dns_forward_t *forward) {
14255         isc_result_t result;
14256         isc_sockaddr_t src;
14257
14258         LOCK_ZONE(forward->zone);
14259
14260         if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
14261                 UNLOCK_ZONE(forward->zone);
14262                 return (ISC_R_CANCELED);
14263         }
14264
14265         if (forward->which >= forward->zone->masterscnt) {
14266                 UNLOCK_ZONE(forward->zone);
14267                 return (ISC_R_NOMORE);
14268         }
14269
14270         forward->addr = forward->zone->masters[forward->which];
14271         /*
14272          * Always use TCP regardless of whether the original update
14273          * used TCP.
14274          * XXX The timeout may but a bit small if we are far down a
14275          * transfer graph and the master has to try several masters.
14276          */
14277         switch (isc_sockaddr_pf(&forward->addr)) {
14278         case PF_INET:
14279                 src = forward->zone->xfrsource4;
14280                 break;
14281         case PF_INET6:
14282                 src = forward->zone->xfrsource6;
14283                 break;
14284         default:
14285                 result = ISC_R_NOTIMPLEMENTED;
14286                 goto unlock;
14287         }
14288         result = dns_request_createraw(forward->zone->view->requestmgr,
14289                                        forward->msgbuf,
14290                                        &src, &forward->addr,
14291                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
14292                                        forward->zone->task,
14293                                        forward_callback, forward,
14294                                        &forward->request);
14295         if (result == ISC_R_SUCCESS) {
14296                 if (!ISC_LINK_LINKED(forward, link))
14297                         ISC_LIST_APPEND(forward->zone->forwards, forward, link);
14298         }
14299
14300  unlock:
14301         UNLOCK_ZONE(forward->zone);
14302         return (result);
14303 }
14304
14305 static void
14306 forward_callback(isc_task_t *task, isc_event_t *event) {
14307         const char me[] = "forward_callback";
14308         dns_requestevent_t *revent = (dns_requestevent_t *)event;
14309         dns_message_t *msg = NULL;
14310         char master[ISC_SOCKADDR_FORMATSIZE];
14311         isc_result_t result;
14312         dns_forward_t *forward;
14313         dns_zone_t *zone;
14314
14315         UNUSED(task);
14316
14317         forward = revent->ev_arg;
14318         INSIST(DNS_FORWARD_VALID(forward));
14319         zone = forward->zone;
14320         INSIST(DNS_ZONE_VALID(zone));
14321
14322         ENTER;
14323
14324         isc_sockaddr_format(&forward->addr, master, sizeof(master));
14325
14326         if (revent->result != ISC_R_SUCCESS) {
14327                 dns_zone_log(zone, ISC_LOG_INFO,
14328                              "could not forward dynamic update to %s: %s",
14329                              master, dns_result_totext(revent->result));
14330                 goto next_master;
14331         }
14332
14333         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
14334         if (result != ISC_R_SUCCESS)
14335                 goto next_master;
14336
14337         result = dns_request_getresponse(revent->request, msg,
14338                                          DNS_MESSAGEPARSE_PRESERVEORDER |
14339                                          DNS_MESSAGEPARSE_CLONEBUFFER);
14340         if (result != ISC_R_SUCCESS)
14341                 goto next_master;
14342
14343         switch (msg->rcode) {
14344         /*
14345          * Pass these rcodes back to client.
14346          */
14347         case dns_rcode_noerror:
14348         case dns_rcode_yxdomain:
14349         case dns_rcode_yxrrset:
14350         case dns_rcode_nxrrset:
14351         case dns_rcode_refused:
14352         case dns_rcode_nxdomain: {
14353                 char rcode[128];
14354                 isc_buffer_t rb;
14355
14356                 isc_buffer_init(&rb, rcode, sizeof(rcode));
14357                 (void)dns_rcode_totext(msg->rcode, &rb);
14358                 dns_zone_log(zone, ISC_LOG_INFO,
14359                              "forwarded dynamic update: "
14360                              "master %s returned: %.*s",
14361                              master, (int)rb.used, rcode);
14362                 break;
14363         }
14364
14365         /* These should not occur if the masters/zone are valid. */
14366         case dns_rcode_notzone:
14367         case dns_rcode_notauth: {
14368                 char rcode[128];
14369                 isc_buffer_t rb;
14370
14371                 isc_buffer_init(&rb, rcode, sizeof(rcode));
14372                 (void)dns_rcode_totext(msg->rcode, &rb);
14373                 dns_zone_log(zone, ISC_LOG_WARNING,
14374                              "forwarding dynamic update: "
14375                              "unexpected response: master %s returned: %.*s",
14376                              master, (int)rb.used, rcode);
14377                 goto next_master;
14378         }
14379
14380         /* Try another server for these rcodes. */
14381         case dns_rcode_formerr:
14382         case dns_rcode_servfail:
14383         case dns_rcode_notimp:
14384         case dns_rcode_badvers:
14385         default:
14386                 goto next_master;
14387         }
14388
14389         /* call callback */
14390         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
14391         msg = NULL;
14392         dns_request_destroy(&forward->request);
14393         forward_destroy(forward);
14394         isc_event_free(&event);
14395         return;
14396
14397  next_master:
14398         if (msg != NULL)
14399                 dns_message_destroy(&msg);
14400         isc_event_free(&event);
14401         forward->which++;
14402         dns_request_destroy(&forward->request);
14403         result = sendtomaster(forward);
14404         if (result != ISC_R_SUCCESS) {
14405                 /* call callback */
14406                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
14407                              "exhausted dynamic update forwarder list");
14408                 (forward->callback)(forward->callback_arg, result, NULL);
14409                 forward_destroy(forward);
14410         }
14411 }
14412
14413 isc_result_t
14414 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
14415                        dns_updatecallback_t callback, void *callback_arg)
14416 {
14417         dns_forward_t *forward;
14418         isc_result_t result;
14419         isc_region_t *mr;
14420
14421         REQUIRE(DNS_ZONE_VALID(zone));
14422         REQUIRE(msg != NULL);
14423         REQUIRE(callback != NULL);
14424
14425         forward = isc_mem_get(zone->mctx, sizeof(*forward));
14426         if (forward == NULL)
14427                 return (ISC_R_NOMEMORY);
14428
14429         forward->request = NULL;
14430         forward->zone = NULL;
14431         forward->msgbuf = NULL;
14432         forward->which = 0;
14433         forward->mctx = 0;
14434         forward->callback = callback;
14435         forward->callback_arg = callback_arg;
14436         ISC_LINK_INIT(forward, link);
14437         forward->magic = FORWARD_MAGIC;
14438
14439         mr = dns_message_getrawmessage(msg);
14440         if (mr == NULL) {
14441                 result = ISC_R_UNEXPECTEDEND;
14442                 goto cleanup;
14443         }
14444
14445         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
14446         if (result != ISC_R_SUCCESS)
14447                 goto cleanup;
14448         result = isc_buffer_copyregion(forward->msgbuf, mr);
14449         if (result != ISC_R_SUCCESS)
14450                 goto cleanup;
14451
14452         isc_mem_attach(zone->mctx, &forward->mctx);
14453         dns_zone_iattach(zone, &forward->zone);
14454         result = sendtomaster(forward);
14455
14456  cleanup:
14457         if (result != ISC_R_SUCCESS) {
14458                 forward_destroy(forward);
14459         }
14460         return (result);
14461 }
14462
14463 isc_result_t
14464 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
14465         REQUIRE(DNS_ZONE_VALID(zone));
14466         REQUIRE(next != NULL && *next == NULL);
14467
14468         *next = ISC_LIST_NEXT(zone, link);
14469         if (*next == NULL)
14470                 return (ISC_R_NOMORE);
14471         else
14472                 return (ISC_R_SUCCESS);
14473 }
14474
14475 isc_result_t
14476 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
14477         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14478         REQUIRE(first != NULL && *first == NULL);
14479
14480         *first = ISC_LIST_HEAD(zmgr->zones);
14481         if (*first == NULL)
14482                 return (ISC_R_NOMORE);
14483         else
14484                 return (ISC_R_SUCCESS);
14485 }
14486
14487 /***
14488  ***    Zone manager.
14489  ***/
14490
14491 isc_result_t
14492 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
14493                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
14494                    dns_zonemgr_t **zmgrp)
14495 {
14496         dns_zonemgr_t *zmgr;
14497         isc_result_t result;
14498         isc_interval_t interval;
14499
14500         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
14501         if (zmgr == NULL)
14502                 return (ISC_R_NOMEMORY);
14503         zmgr->mctx = NULL;
14504         zmgr->refs = 1;
14505         isc_mem_attach(mctx, &zmgr->mctx);
14506         zmgr->taskmgr = taskmgr;
14507         zmgr->timermgr = timermgr;
14508         zmgr->socketmgr = socketmgr;
14509         zmgr->zonetasks = NULL;
14510         zmgr->loadtasks = NULL;
14511         zmgr->mctxpool = NULL;
14512         zmgr->task = NULL;
14513         zmgr->notifyrl = NULL;
14514         zmgr->refreshrl = NULL;
14515         ISC_LIST_INIT(zmgr->zones);
14516         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
14517         ISC_LIST_INIT(zmgr->xfrin_in_progress);
14518         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
14519         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
14520         if (result != ISC_R_SUCCESS)
14521                 goto free_mem;
14522
14523         zmgr->transfersin = 10;
14524         zmgr->transfersperns = 2;
14525
14526         /* Unreachable lock. */
14527         result = isc_rwlock_init(&zmgr->urlock, 0, 0);
14528         if (result != ISC_R_SUCCESS)
14529                 goto free_rwlock;
14530
14531         /* Create a single task for queueing of SOA queries. */
14532         result = isc_task_create(taskmgr, 1, &zmgr->task);
14533         if (result != ISC_R_SUCCESS)
14534                 goto free_urlock;
14535
14536         isc_task_setname(zmgr->task, "zmgr", zmgr);
14537         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14538                                         &zmgr->notifyrl);
14539         if (result != ISC_R_SUCCESS)
14540                 goto free_task;
14541
14542         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14543                                         &zmgr->refreshrl);
14544         if (result != ISC_R_SUCCESS)
14545                 goto free_notifyrl;
14546
14547         /* default to 20 refresh queries / notifies per second. */
14548         isc_interval_set(&interval, 0, 1000000000/2);
14549         result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
14550         RUNTIME_CHECK(result == ISC_R_SUCCESS);
14551         isc_ratelimiter_setpertic(zmgr->notifyrl, 10);
14552
14553         result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
14554         RUNTIME_CHECK(result == ISC_R_SUCCESS);
14555         isc_ratelimiter_setpertic(zmgr->refreshrl, 10);
14556
14557         zmgr->iolimit = 1;
14558         zmgr->ioactive = 0;
14559         ISC_LIST_INIT(zmgr->high);
14560         ISC_LIST_INIT(zmgr->low);
14561
14562         result = isc_mutex_init(&zmgr->iolock);
14563         if (result != ISC_R_SUCCESS)
14564                 goto free_refreshrl;
14565
14566         zmgr->magic = ZONEMGR_MAGIC;
14567
14568         *zmgrp = zmgr;
14569         return (ISC_R_SUCCESS);
14570
14571 #if 0
14572  free_iolock:
14573         DESTROYLOCK(&zmgr->iolock);
14574 #endif
14575  free_refreshrl:
14576         isc_ratelimiter_detach(&zmgr->refreshrl);
14577  free_notifyrl:
14578         isc_ratelimiter_detach(&zmgr->notifyrl);
14579  free_task:
14580         isc_task_detach(&zmgr->task);
14581  free_urlock:
14582         isc_rwlock_destroy(&zmgr->urlock);
14583  free_rwlock:
14584         isc_rwlock_destroy(&zmgr->rwlock);
14585  free_mem:
14586         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14587         isc_mem_detach(&mctx);
14588         return (result);
14589 }
14590
14591 isc_result_t
14592 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
14593         isc_result_t result;
14594         isc_mem_t *mctx = NULL;
14595         dns_zone_t *zone = NULL;
14596         void *item;
14597
14598         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14599         REQUIRE(zonep != NULL && *zonep == NULL);
14600
14601         if (zmgr->mctxpool == NULL)
14602                 return (ISC_R_FAILURE);
14603
14604         item = isc_pool_get(zmgr->mctxpool);
14605         if (item == NULL)
14606                 return (ISC_R_FAILURE);
14607
14608         isc_mem_attach((isc_mem_t *) item, &mctx);
14609         result = dns_zone_create(&zone, mctx);
14610         isc_mem_detach(&mctx);
14611
14612         if (result == ISC_R_SUCCESS)
14613                 *zonep = zone;
14614
14615         return (result);
14616 }
14617
14618 isc_result_t
14619 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14620         isc_result_t result;
14621
14622         REQUIRE(DNS_ZONE_VALID(zone));
14623         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14624
14625         if (zmgr->zonetasks == NULL)
14626                 return (ISC_R_FAILURE);
14627
14628         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14629         LOCK_ZONE(zone);
14630         REQUIRE(zone->task == NULL);
14631         REQUIRE(zone->timer == NULL);
14632         REQUIRE(zone->zmgr == NULL);
14633
14634         isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
14635         isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
14636
14637         /*
14638          * Set the task name.  The tag will arbitrarily point to one
14639          * of the zones sharing the task (in practice, the one
14640          * to be managed last).
14641          */
14642         isc_task_setname(zone->task, "zone", zone);
14643         isc_task_setname(zone->loadtask, "loadzone", zone);
14644
14645         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
14646                                   NULL, NULL,
14647                                   zone->task, zone_timer, zone,
14648                                   &zone->timer);
14649
14650         if (result != ISC_R_SUCCESS)
14651                 goto cleanup_tasks;
14652
14653         /*
14654          * The timer "holds" a iref.
14655          */
14656         zone->irefs++;
14657         INSIST(zone->irefs != 0);
14658
14659         ISC_LIST_APPEND(zmgr->zones, zone, link);
14660         zone->zmgr = zmgr;
14661         zmgr->refs++;
14662
14663         goto unlock;
14664
14665  cleanup_tasks:
14666         isc_task_detach(&zone->loadtask);
14667         isc_task_detach(&zone->task);
14668
14669  unlock:
14670         UNLOCK_ZONE(zone);
14671         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14672         return (result);
14673 }
14674
14675 void
14676 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14677         isc_boolean_t free_now = ISC_FALSE;
14678
14679         REQUIRE(DNS_ZONE_VALID(zone));
14680         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14681         REQUIRE(zone->zmgr == zmgr);
14682
14683         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14684         LOCK_ZONE(zone);
14685
14686         ISC_LIST_UNLINK(zmgr->zones, zone, link);
14687         zone->zmgr = NULL;
14688         zmgr->refs--;
14689         if (zmgr->refs == 0)
14690                 free_now = ISC_TRUE;
14691
14692         UNLOCK_ZONE(zone);
14693         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14694
14695         if (free_now)
14696                 zonemgr_free(zmgr);
14697         ENSURE(zone->zmgr == NULL);
14698 }
14699
14700 void
14701 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
14702         REQUIRE(DNS_ZONEMGR_VALID(source));
14703         REQUIRE(target != NULL && *target == NULL);
14704
14705         RWLOCK(&source->rwlock, isc_rwlocktype_write);
14706         REQUIRE(source->refs > 0);
14707         source->refs++;
14708         INSIST(source->refs > 0);
14709         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
14710         *target = source;
14711 }
14712
14713 void
14714 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
14715         dns_zonemgr_t *zmgr;
14716         isc_boolean_t free_now = ISC_FALSE;
14717
14718         REQUIRE(zmgrp != NULL);
14719         zmgr = *zmgrp;
14720         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14721
14722         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14723         zmgr->refs--;
14724         if (zmgr->refs == 0)
14725                 free_now = ISC_TRUE;
14726         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14727
14728         if (free_now)
14729                 zonemgr_free(zmgr);
14730         *zmgrp = NULL;
14731 }
14732
14733 isc_result_t
14734 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
14735         dns_zone_t *p;
14736
14737         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14738
14739         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14740         for (p = ISC_LIST_HEAD(zmgr->zones);
14741              p != NULL;
14742              p = ISC_LIST_NEXT(p, link))
14743         {
14744                 dns_zone_maintenance(p);
14745         }
14746         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14747
14748         /*
14749          * Recent configuration changes may have increased the
14750          * amount of available transfers quota.  Make sure any
14751          * transfers currently blocked on quota get started if
14752          * possible.
14753          */
14754         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14755         zmgr_resume_xfrs(zmgr, ISC_TRUE);
14756         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14757         return (ISC_R_SUCCESS);
14758 }
14759
14760 void
14761 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
14762
14763         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14764
14765         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14766         zmgr_resume_xfrs(zmgr, ISC_TRUE);
14767         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14768 }
14769
14770 void
14771 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
14772         dns_zone_t *zone;
14773
14774         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14775
14776         isc_ratelimiter_shutdown(zmgr->notifyrl);
14777         isc_ratelimiter_shutdown(zmgr->refreshrl);
14778
14779         if (zmgr->task != NULL)
14780                 isc_task_destroy(&zmgr->task);
14781         if (zmgr->zonetasks != NULL)
14782                 isc_taskpool_destroy(&zmgr->zonetasks);
14783         if (zmgr->loadtasks != NULL)
14784                 isc_taskpool_destroy(&zmgr->loadtasks);
14785         if (zmgr->mctxpool != NULL)
14786                 isc_pool_destroy(&zmgr->mctxpool);
14787
14788         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14789         for (zone = ISC_LIST_HEAD(zmgr->zones);
14790              zone != NULL;
14791              zone = ISC_LIST_NEXT(zone, link))
14792         {
14793                 LOCK_ZONE(zone);
14794                 forward_cancel(zone);
14795                 UNLOCK_ZONE(zone);
14796         }
14797         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14798 }
14799
14800 static isc_result_t
14801 mctxinit(void **target, void *arg) {
14802         isc_result_t result;
14803         isc_mem_t *mctx = NULL;
14804
14805         UNUSED(arg);
14806
14807         REQUIRE(target != NULL && *target == NULL);
14808
14809         result = isc_mem_create(0, 0, &mctx);
14810         if (result != ISC_R_SUCCESS)
14811                 return (result);
14812         isc_mem_setname(mctx, "zonemgr-pool", NULL);
14813
14814         *target = mctx;
14815         return (ISC_R_SUCCESS);
14816 }
14817
14818 static void
14819 mctxfree(void **target) {
14820         isc_mem_t *mctx = *(isc_mem_t **) target;
14821         isc_mem_detach(&mctx);
14822         *target = NULL;
14823 }
14824
14825 #define ZONES_PER_TASK 100
14826 #define ZONES_PER_MCTX 1000
14827
14828 isc_result_t
14829 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
14830         isc_result_t result;
14831         int ntasks = num_zones / ZONES_PER_TASK;
14832         int nmctx = num_zones / ZONES_PER_MCTX;
14833         isc_taskpool_t *pool = NULL;
14834         isc_pool_t *mctxpool = NULL;
14835
14836         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14837
14838         /*
14839          * For anything fewer than 1000 zones we use 10 tasks in
14840          * the task pools.  More than that, and we'll scale at one
14841          * task per 100 zones.  Similarly, for anything smaller than
14842          * 2000 zones we use 2 memory contexts, then scale at 1:1000.
14843          */
14844         if (ntasks < 10)
14845                 ntasks = 10;
14846         if (nmctx < 2)
14847                 nmctx = 2;
14848
14849         /* Create or resize the zone task pools. */
14850         if (zmgr->zonetasks == NULL)
14851                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
14852                                              ntasks, 2, &pool);
14853         else
14854                 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
14855
14856         if (result == ISC_R_SUCCESS)
14857                 zmgr->zonetasks = pool;
14858
14859         pool = NULL;
14860         if (zmgr->loadtasks == NULL)
14861                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
14862                                              ntasks, 2, &pool);
14863         else
14864                 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
14865
14866         if (result == ISC_R_SUCCESS)
14867                 zmgr->loadtasks = pool;
14868
14869 #ifdef BIND9
14870         /*
14871          * We always set all tasks in the zone-load task pool to
14872          * privileged.  This prevents other tasks in the system from
14873          * running while the server task manager is in privileged
14874          * mode.
14875          *
14876          * NOTE: If we start using task privileges for any other
14877          * part of the system than zone tasks, then this will need to be
14878          * revisted.  In that case we'd want to turn on privileges for
14879          * zone tasks only when we were loading, and turn them off the
14880          * rest of the time.  For now, however, it's okay to just
14881          * set it and forget it.
14882          */
14883         isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
14884 #endif
14885
14886         /* Create or resize the zone memory context pool. */
14887         if (zmgr->mctxpool == NULL)
14888                 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
14889                                          mctxinit, NULL, &mctxpool);
14890         else
14891                 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
14892
14893         if (result == ISC_R_SUCCESS)
14894                 zmgr->mctxpool = mctxpool;
14895
14896         return (result);
14897 }
14898
14899 static void
14900 zonemgr_free(dns_zonemgr_t *zmgr) {
14901         isc_mem_t *mctx;
14902
14903         INSIST(zmgr->refs == 0);
14904         INSIST(ISC_LIST_EMPTY(zmgr->zones));
14905
14906         zmgr->magic = 0;
14907
14908         DESTROYLOCK(&zmgr->iolock);
14909         isc_ratelimiter_detach(&zmgr->notifyrl);
14910         isc_ratelimiter_detach(&zmgr->refreshrl);
14911
14912         isc_rwlock_destroy(&zmgr->urlock);
14913         isc_rwlock_destroy(&zmgr->rwlock);
14914         mctx = zmgr->mctx;
14915         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14916         isc_mem_detach(&mctx);
14917 }
14918
14919 void
14920 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
14921         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14922
14923         zmgr->transfersin = value;
14924 }
14925
14926 isc_uint32_t
14927 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
14928         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14929
14930         return (zmgr->transfersin);
14931 }
14932
14933 void
14934 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
14935         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14936
14937         zmgr->transfersperns = value;
14938 }
14939
14940 isc_uint32_t
14941 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
14942         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14943
14944         return (zmgr->transfersperns);
14945 }
14946
14947 /*
14948  * Try to start a new incoming zone transfer to fill a quota
14949  * slot that was just vacated.
14950  *
14951  * Requires:
14952  *      The zone manager is locked by the caller.
14953  */
14954 static void
14955 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
14956         dns_zone_t *zone;
14957         dns_zone_t *next;
14958
14959         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
14960              zone != NULL;
14961              zone = next)
14962         {
14963                 isc_result_t result;
14964                 next = ISC_LIST_NEXT(zone, statelink);
14965                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
14966                 if (result == ISC_R_SUCCESS) {
14967                         if (multi)
14968                                 continue;
14969                         /*
14970                          * We successfully filled the slot.  We're done.
14971                          */
14972                         break;
14973                 } else if (result == ISC_R_QUOTA) {
14974                         /*
14975                          * Not enough quota.  This is probably the per-server
14976                          * quota, because we usually get called when a unit of
14977                          * global quota has just been freed.  Try the next
14978                          * zone, it may succeed if it uses another master.
14979                          */
14980                         continue;
14981                 } else {
14982                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
14983                                      "starting zone transfer: %s",
14984                                      isc_result_totext(result));
14985                         break;
14986                 }
14987         }
14988 }
14989
14990 /*
14991  * Try to start an incoming zone transfer for 'zone', quota permitting.
14992  *
14993  * Requires:
14994  *      The zone manager is locked by the caller.
14995  *
14996  * Returns:
14997  *      ISC_R_SUCCESS   There was enough quota and we attempted to
14998  *                      start a transfer.  zone_xfrdone() has been or will
14999  *                      be called.
15000  *      ISC_R_QUOTA     Not enough quota.
15001  *      Others          Failure.
15002  */
15003 static isc_result_t
15004 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15005         dns_peer_t *peer = NULL;
15006         isc_netaddr_t masterip;
15007         isc_uint32_t nxfrsin, nxfrsperns;
15008         dns_zone_t *x;
15009         isc_uint32_t maxtransfersin, maxtransfersperns;
15010         isc_event_t *e;
15011
15012         /*
15013          * If we are exiting just pretend we got quota so the zone will
15014          * be cleaned up in the zone's task context.
15015          */
15016         LOCK_ZONE(zone);
15017         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15018                 UNLOCK_ZONE(zone);
15019                 goto gotquota;
15020         }
15021
15022         /*
15023          * Find any configured information about the server we'd
15024          * like to transfer this zone from.
15025          */
15026         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
15027         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
15028         UNLOCK_ZONE(zone);
15029
15030         /*
15031          * Determine the total maximum number of simultaneous
15032          * transfers allowed, and the maximum for this specific
15033          * master.
15034          */
15035         maxtransfersin = zmgr->transfersin;
15036         maxtransfersperns = zmgr->transfersperns;
15037         if (peer != NULL)
15038                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
15039
15040         /*
15041          * Count the total number of transfers that are in progress,
15042          * and the number of transfers in progress from this master.
15043          * We linearly scan a list of all transfers; if this turns
15044          * out to be too slow, we could hash on the master address.
15045          */
15046         nxfrsin = nxfrsperns = 0;
15047         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15048              x != NULL;
15049              x = ISC_LIST_NEXT(x, statelink))
15050         {
15051                 isc_netaddr_t xip;
15052
15053                 LOCK_ZONE(x);
15054                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
15055                 UNLOCK_ZONE(x);
15056
15057                 nxfrsin++;
15058                 if (isc_netaddr_equal(&xip, &masterip))
15059                         nxfrsperns++;
15060         }
15061
15062         /* Enforce quota. */
15063         if (nxfrsin >= maxtransfersin)
15064                 return (ISC_R_QUOTA);
15065
15066         if (nxfrsperns >= maxtransfersperns)
15067                 return (ISC_R_QUOTA);
15068
15069  gotquota:
15070         /*
15071          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
15072          * list and send it an event to let it start the actual transfer in the
15073          * context of its own task.
15074          */
15075         e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
15076                                got_transfer_quota, zone, sizeof(isc_event_t));
15077         if (e == NULL)
15078                 return (ISC_R_NOMEMORY);
15079
15080         LOCK_ZONE(zone);
15081         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
15082         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
15083         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
15084         zone->statelist = &zmgr->xfrin_in_progress;
15085         isc_task_send(zone->task, &e);
15086         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
15087         UNLOCK_ZONE(zone);
15088
15089         return (ISC_R_SUCCESS);
15090 }
15091
15092 void
15093 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
15094
15095         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15096         REQUIRE(iolimit > 0);
15097
15098         zmgr->iolimit = iolimit;
15099 }
15100
15101 isc_uint32_t
15102 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
15103
15104         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15105
15106         return (zmgr->iolimit);
15107 }
15108
15109 /*
15110  * Get permission to request a file handle from the OS.
15111  * An event will be sent to action when one is available.
15112  * There are two queues available (high and low), the high
15113  * queue will be serviced before the low one.
15114  *
15115  * zonemgr_putio() must be called after the event is delivered to
15116  * 'action'.
15117  */
15118
15119 static isc_result_t
15120 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
15121               isc_task_t *task, isc_taskaction_t action, void *arg,
15122               dns_io_t **iop)
15123 {
15124         dns_io_t *io;
15125         isc_boolean_t queue;
15126
15127         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15128         REQUIRE(iop != NULL && *iop == NULL);
15129
15130         io = isc_mem_get(zmgr->mctx, sizeof(*io));
15131         if (io == NULL)
15132                 return (ISC_R_NOMEMORY);
15133
15134         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
15135                                        action, arg, sizeof(*io->event));
15136         if (io->event == NULL) {
15137                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
15138                 return (ISC_R_NOMEMORY);
15139         }
15140
15141         io->zmgr = zmgr;
15142         io->high = high;
15143         io->task = NULL;
15144         isc_task_attach(task, &io->task);
15145         ISC_LINK_INIT(io, link);
15146         io->magic = IO_MAGIC;
15147
15148         LOCK(&zmgr->iolock);
15149         zmgr->ioactive++;
15150         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
15151         if (queue) {
15152                 if (io->high)
15153                         ISC_LIST_APPEND(zmgr->high, io, link);
15154                 else
15155                         ISC_LIST_APPEND(zmgr->low, io, link);
15156         }
15157         UNLOCK(&zmgr->iolock);
15158         *iop = io;
15159
15160         if (!queue)
15161                 isc_task_send(io->task, &io->event);
15162         return (ISC_R_SUCCESS);
15163 }
15164
15165 static void
15166 zonemgr_putio(dns_io_t **iop) {
15167         dns_io_t *io;
15168         dns_io_t *next;
15169         dns_zonemgr_t *zmgr;
15170
15171         REQUIRE(iop != NULL);
15172         io = *iop;
15173         REQUIRE(DNS_IO_VALID(io));
15174
15175         *iop = NULL;
15176
15177         INSIST(!ISC_LINK_LINKED(io, link));
15178         INSIST(io->event == NULL);
15179
15180         zmgr = io->zmgr;
15181         isc_task_detach(&io->task);
15182         io->magic = 0;
15183         isc_mem_put(zmgr->mctx, io, sizeof(*io));
15184
15185         LOCK(&zmgr->iolock);
15186         INSIST(zmgr->ioactive > 0);
15187         zmgr->ioactive--;
15188         next = HEAD(zmgr->high);
15189         if (next == NULL)
15190                 next = HEAD(zmgr->low);
15191         if (next != NULL) {
15192                 if (next->high)
15193                         ISC_LIST_UNLINK(zmgr->high, next, link);
15194                 else
15195                         ISC_LIST_UNLINK(zmgr->low, next, link);
15196                 INSIST(next->event != NULL);
15197         }
15198         UNLOCK(&zmgr->iolock);
15199         if (next != NULL)
15200                 isc_task_send(next->task, &next->event);
15201 }
15202
15203 static void
15204 zonemgr_cancelio(dns_io_t *io) {
15205         isc_boolean_t send_event = ISC_FALSE;
15206
15207         REQUIRE(DNS_IO_VALID(io));
15208
15209         /*
15210          * If we are queued to be run then dequeue.
15211          */
15212         LOCK(&io->zmgr->iolock);
15213         if (ISC_LINK_LINKED(io, link)) {
15214                 if (io->high)
15215                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
15216                 else
15217                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
15218
15219                 send_event = ISC_TRUE;
15220                 INSIST(io->event != NULL);
15221         }
15222         UNLOCK(&io->zmgr->iolock);
15223         if (send_event) {
15224                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
15225                 isc_task_send(io->task, &io->event);
15226         }
15227 }
15228
15229 static void
15230 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
15231         char *buf;
15232         int buflen;
15233         isc_result_t result;
15234
15235         buflen = strlen(path) + strlen(templat) + 2;
15236
15237         buf = isc_mem_get(zone->mctx, buflen);
15238         if (buf == NULL)
15239                 return;
15240
15241         result = isc_file_template(path, templat, buf, buflen);
15242         if (result != ISC_R_SUCCESS)
15243                 goto cleanup;
15244
15245         result = isc_file_renameunique(path, buf);
15246         if (result != ISC_R_SUCCESS)
15247                 goto cleanup;
15248
15249         dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
15250                      "renaming file to '%s' for failure analysis and "
15251                      "retransferring.", path, buf);
15252
15253  cleanup:
15254         isc_mem_put(zone->mctx, buf, buflen);
15255 }
15256
15257 #if 0
15258 /* Hook for ondestroy notification from a database. */
15259
15260 static void
15261 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
15262         dns_db_t *db = event->sender;
15263         UNUSED(task);
15264
15265         isc_event_free(&event);
15266
15267         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15268                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15269                       "database (%p) destroyed", (void*) db);
15270 }
15271 #endif
15272
15273 void
15274 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
15275         isc_interval_t interval;
15276         isc_uint32_t s, ns;
15277         isc_uint32_t pertic;
15278         isc_result_t result;
15279
15280         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15281
15282         if (value == 0)
15283                 value = 1;
15284
15285         if (value == 1) {
15286                 s = 1;
15287                 ns = 0;
15288                 pertic = 1;
15289         } else if (value <= 10) {
15290                 s = 0;
15291                 ns = 1000000000 / value;
15292                 pertic = 1;
15293         } else {
15294                 s = 0;
15295                 ns = (1000000000 / value) * 10;
15296                 pertic = 10;
15297         }
15298
15299         isc_interval_set(&interval, s, ns);
15300
15301         result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
15302         RUNTIME_CHECK(result == ISC_R_SUCCESS);
15303         isc_ratelimiter_setpertic(zmgr->notifyrl, pertic);
15304
15305         result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
15306         RUNTIME_CHECK(result == ISC_R_SUCCESS);
15307         isc_ratelimiter_setpertic(zmgr->refreshrl, pertic);
15308
15309         zmgr->serialqueryrate = value;
15310 }
15311
15312 unsigned int
15313 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
15314         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15315
15316         return (zmgr->serialqueryrate);
15317 }
15318
15319 isc_boolean_t
15320 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15321                         isc_sockaddr_t *local, isc_time_t *now)
15322 {
15323         unsigned int i;
15324         isc_rwlocktype_t locktype;
15325         isc_result_t result;
15326         isc_uint32_t seconds = isc_time_seconds(now);
15327         isc_uint32_t count = 0;
15328
15329         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15330
15331         locktype = isc_rwlocktype_read;
15332         RWLOCK(&zmgr->urlock, locktype);
15333         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15334                 if (zmgr->unreachable[i].expire >= seconds &&
15335                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15336                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
15337                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
15338                         if (result == ISC_R_SUCCESS) {
15339                                 locktype = isc_rwlocktype_write;
15340                                 zmgr->unreachable[i].last = seconds;
15341                                 count = zmgr->unreachable[i].count;
15342                         }
15343                         break;
15344                 }
15345         }
15346         RWUNLOCK(&zmgr->urlock, locktype);
15347         return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
15348 }
15349
15350 void
15351 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15352                            isc_sockaddr_t *local)
15353 {
15354         unsigned int i;
15355         isc_rwlocktype_t locktype;
15356         isc_result_t result;
15357
15358         char master[ISC_SOCKADDR_FORMATSIZE];
15359         char source[ISC_SOCKADDR_FORMATSIZE];
15360
15361         isc_sockaddr_format(remote, master, sizeof(master));
15362         isc_sockaddr_format(local, source, sizeof(source));
15363
15364         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15365
15366         locktype = isc_rwlocktype_read;
15367         RWLOCK(&zmgr->urlock, locktype);
15368         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15369                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15370                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
15371                         if (zmgr->unreachable[i].expire == 0)
15372                                 break;
15373                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
15374                         if (result == ISC_R_SUCCESS) {
15375                                 locktype = isc_rwlocktype_write;
15376                                 zmgr->unreachable[i].expire = 0;
15377                                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15378                                               DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
15379                                               "master %s (source %s) deleted "
15380                                               "from unreachable cache",
15381                                               master, source);
15382                         }
15383                         break;
15384                 }
15385         }
15386         RWUNLOCK(&zmgr->urlock, locktype);
15387 }
15388
15389 void
15390 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15391                            isc_sockaddr_t *local, isc_time_t *now)
15392 {
15393         isc_uint32_t seconds = isc_time_seconds(now);
15394         isc_uint32_t last = seconds;
15395         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
15396
15397         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15398
15399         RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
15400         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15401                 /* Existing entry? */
15402                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15403                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
15404                         break;
15405                 /* Empty slot? */
15406                 if (zmgr->unreachable[i].expire < seconds)
15407                         slot = i;
15408                 /* Least recently used slot? */
15409                 if (zmgr->unreachable[i].last < last) {
15410                         last = zmgr->unreachable[i].last;
15411                         oldest = i;
15412                 }
15413         }
15414         if (i < UNREACH_CHACHE_SIZE) {
15415                 /*
15416                  * Found a existing entry.  Update the expire timer and
15417                  * last usage timestamps.
15418                  */
15419                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
15420                 zmgr->unreachable[i].last = seconds;
15421                 if (zmgr->unreachable[i].expire < seconds)
15422                         zmgr->unreachable[i].count = 1;
15423                 else
15424                         zmgr->unreachable[i].count++;
15425         } else if (slot != UNREACH_CHACHE_SIZE) {
15426                 /*
15427                  * Found a empty slot. Add a new entry to the cache.
15428                  */
15429                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
15430                 zmgr->unreachable[slot].last = seconds;
15431                 zmgr->unreachable[slot].remote = *remote;
15432                 zmgr->unreachable[slot].local = *local;
15433                 zmgr->unreachable[slot].count = 1;
15434         } else {
15435                 /*
15436                  * Replace the least recently used entry in the cache.
15437                  */
15438                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
15439                 zmgr->unreachable[oldest].last = seconds;
15440                 zmgr->unreachable[oldest].remote = *remote;
15441                 zmgr->unreachable[oldest].local = *local;
15442                 zmgr->unreachable[oldest].count = 1;
15443         }
15444         RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
15445 }
15446
15447 void
15448 dns_zone_forcereload(dns_zone_t *zone) {
15449         REQUIRE(DNS_ZONE_VALID(zone));
15450
15451         if (zone->type == dns_zone_master ||
15452             (zone->type == dns_zone_redirect && zone->masters == NULL))
15453                 return;
15454
15455         LOCK_ZONE(zone);
15456         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
15457         UNLOCK_ZONE(zone);
15458         dns_zone_refresh(zone);
15459 }
15460
15461 isc_boolean_t
15462 dns_zone_isforced(dns_zone_t *zone) {
15463         REQUIRE(DNS_ZONE_VALID(zone));
15464
15465         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
15466 }
15467
15468 isc_result_t
15469 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
15470         /*
15471          * This function is obsoleted.
15472          */
15473         UNUSED(zone);
15474         UNUSED(on);
15475         return (ISC_R_NOTIMPLEMENTED);
15476 }
15477
15478 isc_uint64_t *
15479 dns_zone_getstatscounters(dns_zone_t *zone) {
15480         /*
15481          * This function is obsoleted.
15482          */
15483         UNUSED(zone);
15484         return (NULL);
15485 }
15486
15487 void
15488 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
15489         REQUIRE(DNS_ZONE_VALID(zone));
15490         REQUIRE(zone->stats == NULL);
15491
15492         LOCK_ZONE(zone);
15493         zone->stats = NULL;
15494         isc_stats_attach(stats, &zone->stats);
15495         UNLOCK_ZONE(zone);
15496 }
15497
15498 void
15499 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
15500
15501         REQUIRE(DNS_ZONE_VALID(zone));
15502
15503         LOCK_ZONE(zone);
15504         if (zone->requeststats_on && stats == NULL)
15505                 zone->requeststats_on = ISC_FALSE;
15506         else if (!zone->requeststats_on && stats != NULL) {
15507                 if (zone->requeststats == NULL) {
15508                         isc_stats_attach(stats, &zone->requeststats);
15509                         zone->requeststats_on = ISC_TRUE;
15510                 }
15511         }
15512         UNLOCK_ZONE(zone);
15513 }
15514
15515 #ifdef NEWSTATS
15516 void
15517 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
15518
15519         REQUIRE(DNS_ZONE_VALID(zone));
15520
15521         LOCK_ZONE(zone);
15522         if (zone->requeststats_on && stats != NULL) {
15523                 if (zone->rcvquerystats == NULL) {
15524                         dns_stats_attach(stats, &zone->rcvquerystats);
15525                         zone->requeststats_on = ISC_TRUE;
15526                 }
15527         }
15528         UNLOCK_ZONE(zone);
15529 }
15530 #endif
15531
15532 isc_stats_t *
15533 dns_zone_getrequeststats(dns_zone_t *zone) {
15534         /*
15535          * We don't lock zone for efficiency reason.  This is not catastrophic
15536          * because requeststats must always be valid when requeststats_on is
15537          * true.
15538          * Some counters may be incremented while requeststats_on is becoming
15539          * false, or some cannot be incremented just after the statistics are
15540          * installed, but it shouldn't matter much in practice.
15541          */
15542         if (zone->requeststats_on)
15543                 return (zone->requeststats);
15544         else
15545                 return (NULL);
15546 }
15547
15548 #ifdef NEWSTATS
15549 /*
15550  * Return the received query stats bucket
15551  * see note from dns_zone_getrequeststats()
15552  */
15553 dns_stats_t *
15554 dns_zone_getrcvquerystats(dns_zone_t *zone) {
15555         if (zone->requeststats_on)
15556                 return (zone->rcvquerystats);
15557         else
15558                 return (NULL);
15559 }
15560 #endif
15561
15562 void
15563 dns_zone_dialup(dns_zone_t *zone) {
15564
15565         REQUIRE(DNS_ZONE_VALID(zone));
15566
15567         zone_debuglog(zone, "dns_zone_dialup", 3,
15568                       "notify = %d, refresh = %d",
15569                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
15570                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
15571
15572         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
15573                 dns_zone_notify(zone);
15574         if (zone->type != dns_zone_master && zone->masters != NULL &&
15575             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
15576                 dns_zone_refresh(zone);
15577 }
15578
15579 void
15580 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
15581         REQUIRE(DNS_ZONE_VALID(zone));
15582
15583         LOCK_ZONE(zone);
15584         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
15585                          DNS_ZONEFLG_DIALREFRESH |
15586                          DNS_ZONEFLG_NOREFRESH);
15587         switch (dialup) {
15588         case dns_dialuptype_no:
15589                 break;
15590         case dns_dialuptype_yes:
15591                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
15592                                  DNS_ZONEFLG_DIALREFRESH |
15593                                  DNS_ZONEFLG_NOREFRESH));
15594                 break;
15595         case dns_dialuptype_notify:
15596                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15597                 break;
15598         case dns_dialuptype_notifypassive:
15599                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15600                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15601                 break;
15602         case dns_dialuptype_refresh:
15603                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
15604                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15605                 break;
15606         case dns_dialuptype_passive:
15607                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15608                 break;
15609         default:
15610                 INSIST(0);
15611         }
15612         UNLOCK_ZONE(zone);
15613 }
15614
15615 isc_result_t
15616 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
15617         isc_result_t result = ISC_R_SUCCESS;
15618
15619         REQUIRE(DNS_ZONE_VALID(zone));
15620
15621         LOCK_ZONE(zone);
15622         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
15623         UNLOCK_ZONE(zone);
15624
15625         return (result);
15626 }
15627
15628 const char *
15629 dns_zone_getkeydirectory(dns_zone_t *zone) {
15630         REQUIRE(DNS_ZONE_VALID(zone));
15631
15632         return (zone->keydirectory);
15633 }
15634
15635 unsigned int
15636 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
15637         dns_zone_t *zone;
15638         unsigned int count = 0;
15639
15640         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15641
15642         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15643         switch (state) {
15644         case DNS_ZONESTATE_XFERRUNNING:
15645                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15646                      zone != NULL;
15647                      zone = ISC_LIST_NEXT(zone, statelink))
15648                         count++;
15649                 break;
15650         case DNS_ZONESTATE_XFERDEFERRED:
15651                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
15652                      zone != NULL;
15653                      zone = ISC_LIST_NEXT(zone, statelink))
15654                         count++;
15655                 break;
15656         case DNS_ZONESTATE_SOAQUERY:
15657                 for (zone = ISC_LIST_HEAD(zmgr->zones);
15658                      zone != NULL;
15659                      zone = ISC_LIST_NEXT(zone, link))
15660                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
15661                                 count++;
15662                 break;
15663         case DNS_ZONESTATE_ANY:
15664                 for (zone = ISC_LIST_HEAD(zmgr->zones);
15665                      zone != NULL;
15666                      zone = ISC_LIST_NEXT(zone, link)) {
15667                         dns_view_t *view = zone->view;
15668                         if (view != NULL && strcmp(view->name, "_bind") == 0)
15669                                 continue;
15670                         count++;
15671                 }
15672                 break;
15673         default:
15674                 INSIST(0);
15675         }
15676
15677         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15678
15679         return (count);
15680 }
15681
15682 isc_result_t
15683 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
15684         isc_boolean_t ok = ISC_TRUE;
15685         isc_boolean_t fail = ISC_FALSE;
15686         char namebuf[DNS_NAME_FORMATSIZE];
15687         char namebuf2[DNS_NAME_FORMATSIZE];
15688         char typebuf[DNS_RDATATYPE_FORMATSIZE];
15689         int level = ISC_LOG_WARNING;
15690         dns_name_t bad;
15691
15692         REQUIRE(DNS_ZONE_VALID(zone));
15693
15694         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
15695                 return (ISC_R_SUCCESS);
15696
15697         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
15698                 level = ISC_LOG_ERROR;
15699                 fail = ISC_TRUE;
15700         }
15701
15702         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
15703         if (!ok) {
15704                 dns_name_format(name, namebuf, sizeof(namebuf));
15705                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
15706                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
15707                              dns_result_totext(DNS_R_BADOWNERNAME));
15708                 if (fail)
15709                         return (DNS_R_BADOWNERNAME);
15710         }
15711
15712         dns_name_init(&bad, NULL);
15713         ok = dns_rdata_checknames(rdata, name, &bad);
15714         if (!ok) {
15715                 dns_name_format(name, namebuf, sizeof(namebuf));
15716                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
15717                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
15718                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
15719                              namebuf2, dns_result_totext(DNS_R_BADNAME));
15720                 if (fail)
15721                         return (DNS_R_BADNAME);
15722         }
15723
15724         return (ISC_R_SUCCESS);
15725 }
15726
15727 void
15728 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
15729         REQUIRE(DNS_ZONE_VALID(zone));
15730         zone->checkmx = checkmx;
15731 }
15732
15733 void
15734 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
15735         REQUIRE(DNS_ZONE_VALID(zone));
15736         zone->checksrv = checksrv;
15737 }
15738
15739 void
15740 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
15741         REQUIRE(DNS_ZONE_VALID(zone));
15742         zone->checkns = checkns;
15743 }
15744
15745 void
15746 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
15747         REQUIRE(DNS_ZONE_VALID(zone));
15748
15749         LOCK_ZONE(zone);
15750         zone->isself = isself;
15751         zone->isselfarg = arg;
15752         UNLOCK_ZONE(zone);
15753 }
15754
15755 void
15756 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
15757         REQUIRE(DNS_ZONE_VALID(zone));
15758
15759         LOCK_ZONE(zone);
15760         zone->notifydelay = delay;
15761         UNLOCK_ZONE(zone);
15762 }
15763
15764 isc_uint32_t
15765 dns_zone_getnotifydelay(dns_zone_t *zone) {
15766         REQUIRE(DNS_ZONE_VALID(zone));
15767
15768         return (zone->notifydelay);
15769 }
15770
15771 isc_result_t
15772 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
15773                      isc_uint16_t keyid, isc_boolean_t delete)
15774 {
15775         isc_result_t result;
15776         REQUIRE(DNS_ZONE_VALID(zone));
15777
15778         dns_zone_log(zone, ISC_LOG_NOTICE,
15779                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
15780                      algorithm, keyid);
15781         LOCK_ZONE(zone);
15782         result = zone_signwithkey(zone, algorithm, keyid, delete);
15783         UNLOCK_ZONE(zone);
15784
15785         return (result);
15786 }
15787
15788 static const char *hex = "0123456789ABCDEF";
15789
15790 isc_result_t
15791 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
15792         isc_result_t result;
15793         char salt[255*2+1];
15794         unsigned int i, j;
15795
15796         REQUIRE(DNS_ZONE_VALID(zone));
15797
15798         if (nsec3param->salt_length != 0) {
15799                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
15800                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
15801                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
15802                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
15803                 }
15804                 salt[j] = '\0';
15805         } else
15806                 strcpy(salt, "-");
15807         dns_zone_log(zone, ISC_LOG_NOTICE,
15808                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
15809                      nsec3param->hash, nsec3param->iterations,
15810                      salt);
15811         LOCK_ZONE(zone);
15812         result = zone_addnsec3chain(zone, nsec3param);
15813         UNLOCK_ZONE(zone);
15814
15815         return (result);
15816 }
15817
15818 void
15819 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
15820         REQUIRE(DNS_ZONE_VALID(zone));
15821
15822         if (nodes == 0)
15823                 nodes = 1;
15824         zone->nodes = nodes;
15825 }
15826
15827 void
15828 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
15829         REQUIRE(DNS_ZONE_VALID(zone));
15830
15831         /*
15832          * We treat signatures as a signed value so explicitly
15833          * limit its range here.
15834          */
15835         if (signatures > ISC_INT32_MAX)
15836                 signatures = ISC_INT32_MAX;
15837         else if (signatures == 0)
15838                 signatures = 1;
15839         zone->signatures = signatures;
15840 }
15841
15842 void
15843 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
15844         REQUIRE(DNS_ZONE_VALID(zone));
15845         zone->privatetype = type;
15846 }
15847
15848 dns_rdatatype_t
15849 dns_zone_getprivatetype(dns_zone_t *zone) {
15850         REQUIRE(DNS_ZONE_VALID(zone));
15851         return (zone->privatetype);
15852 }
15853
15854 static isc_result_t
15855 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
15856                  isc_boolean_t delete)
15857 {
15858         dns_signing_t *signing;
15859         dns_signing_t *current;
15860         isc_result_t result = ISC_R_SUCCESS;
15861         isc_time_t now;
15862         dns_db_t *db = NULL;
15863
15864         signing = isc_mem_get(zone->mctx, sizeof *signing);
15865         if (signing == NULL)
15866                 return (ISC_R_NOMEMORY);
15867
15868         signing->magic = 0;
15869         signing->db  = NULL;
15870         signing->dbiterator = NULL;
15871         signing->algorithm = algorithm;
15872         signing->keyid = keyid;
15873         signing->delete = delete;
15874         signing->done = ISC_FALSE;
15875
15876         TIME_NOW(&now);
15877
15878         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15879         if (zone->db != NULL)
15880                 dns_db_attach(zone->db, &db);
15881         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15882
15883         if (db == NULL) {
15884                 result = ISC_R_NOTFOUND;
15885                 goto cleanup;
15886         }
15887
15888         dns_db_attach(db, &signing->db);
15889
15890         for (current = ISC_LIST_HEAD(zone->signing);
15891              current != NULL;
15892              current = ISC_LIST_NEXT(current, link)) {
15893                 if (current->db == signing->db &&
15894                     current->algorithm == signing->algorithm &&
15895                     current->keyid == signing->keyid) {
15896                         if (current->delete != signing->delete)
15897                                 current->done = ISC_TRUE;
15898                         else
15899                                 goto cleanup;
15900                 }
15901         }
15902
15903         result = dns_db_createiterator(signing->db, 0,
15904                                        &signing->dbiterator);
15905
15906         if (result == ISC_R_SUCCESS)
15907                 result = dns_dbiterator_first(signing->dbiterator);
15908         if (result == ISC_R_SUCCESS) {
15909                 dns_dbiterator_pause(signing->dbiterator);
15910                 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
15911                 signing = NULL;
15912                 if (isc_time_isepoch(&zone->signingtime)) {
15913                         zone->signingtime = now;
15914                         if (zone->task != NULL)
15915                                 zone_settimer(zone, &now);
15916                 }
15917         }
15918
15919  cleanup:
15920         if (signing != NULL) {
15921                 if (signing->db != NULL)
15922                         dns_db_detach(&signing->db);
15923                 if (signing->dbiterator != NULL)
15924                         dns_dbiterator_destroy(&signing->dbiterator);
15925                 isc_mem_put(zone->mctx, signing, sizeof *signing);
15926         }
15927         if (db != NULL)
15928                 dns_db_detach(&db);
15929         return (result);
15930 }
15931
15932 static void
15933 logmsg(const char *format, ...) {
15934         va_list args;
15935         va_start(args, format);
15936         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
15937                        ISC_LOG_DEBUG(1), format, args);
15938         va_end(args);
15939 }
15940
15941 static void
15942 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
15943         dns_dnsseckey_t *key;
15944         while (!ISC_LIST_EMPTY(*list)) {
15945                 key = ISC_LIST_HEAD(*list);
15946                 ISC_LIST_UNLINK(*list, key, link);
15947                 dns_dnsseckey_destroy(mctx, &key);
15948         }
15949 }
15950
15951 /* Called once; *timep should be set to the current time. */
15952 static isc_result_t
15953 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
15954         isc_result_t result;
15955         isc_stdtime_t now, then = 0, event;
15956         int i;
15957
15958         now = *timep;
15959
15960         for (i = 0; i <= DST_MAX_TIMES; i++) {
15961                 result = dst_key_gettime(key, i, &event);
15962                 if (result == ISC_R_SUCCESS && event > now &&
15963                     (then == 0 || event < then))
15964                         then = event;
15965         }
15966
15967         if (then != 0) {
15968                 *timep = then;
15969                 return (ISC_R_SUCCESS);
15970         }
15971
15972         return (ISC_R_NOTFOUND);
15973 }
15974
15975 static isc_result_t
15976 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
15977           const dns_rdata_t *rdata, isc_boolean_t *flag)
15978 {
15979         dns_rdataset_t rdataset;
15980         dns_dbnode_t *node = NULL;
15981         isc_result_t result;
15982
15983         dns_rdataset_init(&rdataset);
15984         if (rdata->type == dns_rdatatype_nsec3)
15985                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
15986         else
15987                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
15988         result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
15989                                      (isc_stdtime_t) 0, &rdataset, NULL);
15990         if (result == ISC_R_NOTFOUND) {
15991                 *flag = ISC_FALSE;
15992                 result = ISC_R_SUCCESS;
15993                 goto failure;
15994         }
15995
15996         for (result = dns_rdataset_first(&rdataset);
15997              result == ISC_R_SUCCESS;
15998              result = dns_rdataset_next(&rdataset)) {
15999                 dns_rdata_t myrdata = DNS_RDATA_INIT;
16000                 dns_rdataset_current(&rdataset, &myrdata);
16001                 if (!dns_rdata_compare(&myrdata, rdata))
16002                         break;
16003         }
16004         dns_rdataset_disassociate(&rdataset);
16005         if (result == ISC_R_SUCCESS) {
16006                 *flag = ISC_TRUE;
16007         } else if (result == ISC_R_NOMORE) {
16008                 *flag = ISC_FALSE;
16009                 result = ISC_R_SUCCESS;
16010         }
16011
16012  failure:
16013         if (node != NULL)
16014                 dns_db_detachnode(db, &node);
16015         return (result);
16016 }
16017
16018 /*
16019  * Add records to signal the state of signing or of key removal.
16020  */
16021 static isc_result_t
16022 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
16023                     dns_dbversion_t *ver, dns_diff_t *diff,
16024                     isc_boolean_t sign_all)
16025 {
16026         dns_difftuple_t *tuple, *newtuple = NULL;
16027         dns_rdata_dnskey_t dnskey;
16028         dns_rdata_t rdata = DNS_RDATA_INIT;
16029         isc_boolean_t flag;
16030         isc_region_t r;
16031         isc_result_t result = ISC_R_SUCCESS;
16032         isc_uint16_t keyid;
16033         unsigned char buf[5];
16034         dns_name_t *name = dns_db_origin(db);
16035
16036         for (tuple = ISC_LIST_HEAD(diff->tuples);
16037              tuple != NULL;
16038              tuple = ISC_LIST_NEXT(tuple, link)) {
16039                 if (tuple->rdata.type != dns_rdatatype_dnskey)
16040                         continue;
16041
16042                 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
16043                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16044                 if ((dnskey.flags &
16045                      (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
16046                          != DNS_KEYOWNER_ZONE)
16047                         continue;
16048
16049                 dns_rdata_toregion(&tuple->rdata, &r);
16050
16051                 keyid = dst_region_computeid(&r, dnskey.algorithm);
16052
16053                 buf[0] = dnskey.algorithm;
16054                 buf[1] = (keyid & 0xff00) >> 8;
16055                 buf[2] = (keyid & 0xff);
16056                 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
16057                 buf[4] = 0;
16058                 rdata.data = buf;
16059                 rdata.length = sizeof(buf);
16060                 rdata.type = privatetype;
16061                 rdata.rdclass = tuple->rdata.rdclass;
16062
16063                 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
16064                         CHECK(rr_exists(db, ver, name, &rdata, &flag));
16065                         if (flag)
16066                                 continue;
16067                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
16068                                                    name, 0, &rdata, &newtuple));
16069                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
16070                         INSIST(newtuple == NULL);
16071                 }
16072
16073                 /*
16074                  * Remove any record which says this operation has already
16075                  * completed.
16076                  */
16077                 buf[4] = 1;
16078                 CHECK(rr_exists(db, ver, name, &rdata, &flag));
16079                 if (flag) {
16080                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
16081                                                    name, 0, &rdata, &newtuple));
16082                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
16083                         INSIST(newtuple == NULL);
16084                 }
16085         }
16086  failure:
16087         return (result);
16088 }
16089
16090 static isc_result_t
16091 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16092           dns_diff_t *diff, zonediff_t *zonediff)
16093 {
16094         isc_result_t result;
16095         isc_stdtime_t now, inception, soaexpire;
16096         isc_boolean_t check_ksk, keyset_kskonly;
16097         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
16098         unsigned int nkeys = 0, i;
16099         dns_difftuple_t *tuple;
16100
16101         result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
16102                                 zone_keys, &nkeys);
16103         if (result != ISC_R_SUCCESS) {
16104                 dns_zone_log(zone, ISC_LOG_ERROR,
16105                              "sign_apex:find_zone_keys -> %s",
16106                              dns_result_totext(result));
16107                 return (result);
16108         }
16109
16110         isc_stdtime_get(&now);
16111         inception = now - 3600; /* Allow for clock skew. */
16112         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
16113
16114         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16115         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
16116
16117         /*
16118          * See if update_sigs will update DNSKEY signature and if not
16119          * cause them to sign so that so that newly activated keys
16120          * are used.
16121          */
16122         for (tuple = ISC_LIST_HEAD(diff->tuples);
16123              tuple != NULL;
16124              tuple = ISC_LIST_NEXT(tuple, link)) {
16125                 if (tuple->rdata.type == dns_rdatatype_dnskey &&
16126                     dns_name_equal(&tuple->name, &zone->origin))
16127                         break;
16128         }
16129
16130         if (tuple == NULL) {
16131                 result = del_sigs(zone, db, ver, &zone->origin,
16132                                   dns_rdatatype_dnskey, zonediff,
16133                                   zone_keys, nkeys, now, ISC_FALSE);
16134                 if (result != ISC_R_SUCCESS) {
16135                         dns_zone_log(zone, ISC_LOG_ERROR,
16136                                      "sign_apex:del_sigs -> %s",
16137                                      dns_result_totext(result));
16138                         goto failure;
16139                 }
16140                 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
16141                                   zonediff->diff, zone_keys, nkeys, zone->mctx,
16142                                   inception, soaexpire, check_ksk,
16143                                   keyset_kskonly);
16144                 if (result != ISC_R_SUCCESS) {
16145                         dns_zone_log(zone, ISC_LOG_ERROR,
16146                                      "sign_apex:add_sigs -> %s",
16147                                      dns_result_totext(result));
16148                         goto failure;
16149                 }
16150         }
16151
16152         result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
16153                              inception, soaexpire, now, check_ksk,
16154                              keyset_kskonly, zonediff);
16155
16156         if (result != ISC_R_SUCCESS) {
16157                 dns_zone_log(zone, ISC_LOG_ERROR,
16158                              "sign_apex:update_sigs -> %s",
16159                              dns_result_totext(result));
16160                 goto failure;
16161         }
16162
16163  failure:
16164         for (i = 0; i < nkeys; i++)
16165                 dst_key_free(&zone_keys[i]);
16166         return (result);
16167 }
16168
16169 /*
16170  * Prevent the zone entering a inconsistent state where
16171  * NSEC only DNSKEYs are present with NSEC3 chains.
16172  * See update.c:check_dnssec()
16173  */
16174 static isc_boolean_t
16175 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16176             dns_diff_t *diff)
16177 {
16178         isc_result_t result;
16179         dns_difftuple_t *tuple;
16180         isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
16181         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
16182
16183         /* Scan the tuples for an NSEC-only DNSKEY */
16184         for (tuple = ISC_LIST_HEAD(diff->tuples);
16185              tuple != NULL;
16186              tuple = ISC_LIST_NEXT(tuple, link)) {
16187                 isc_uint8_t alg;
16188                 if (tuple->rdata.type != dns_rdatatype_dnskey ||
16189                     tuple->op != DNS_DIFFOP_ADD)
16190                         continue;
16191
16192                 alg = tuple->rdata.data[3];
16193                 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
16194                     alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
16195                         nseconly = ISC_TRUE;
16196                         break;
16197                 }
16198         }
16199
16200         /* Check existing DB for NSEC-only DNSKEY */
16201         if (!nseconly) {
16202                 result = dns_nsec_nseconly(db, ver, &nseconly);
16203                 if (result == ISC_R_NOTFOUND)
16204                         result = ISC_R_SUCCESS;
16205                 CHECK(result);
16206         }
16207
16208         /* Check existing DB for NSEC3 */
16209         if (!nsec3)
16210                 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
16211                                         privatetype, &nsec3));
16212
16213         /* Refuse to allow NSEC3 with NSEC-only keys */
16214         if (nseconly && nsec3) {
16215                 dns_zone_log(zone, ISC_LOG_ERROR,
16216                            "NSEC only DNSKEYs and NSEC3 chains not allowed");
16217                 goto failure;
16218         }
16219
16220         return (ISC_TRUE);
16221
16222  failure:
16223         return (ISC_FALSE);
16224 }
16225
16226 static isc_result_t
16227 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16228                  dns_diff_t *diff)
16229 {
16230         isc_result_t result;
16231         dns_dbnode_t *node = NULL;
16232         dns_rdataset_t rdataset;
16233
16234         dns_rdataset_init(&rdataset);
16235         CHECK(dns_db_getoriginnode(db, &node));
16236
16237         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16238                                      dns_rdatatype_none, 0, &rdataset, NULL);
16239         if (dns_rdataset_isassociated(&rdataset))
16240                 dns_rdataset_disassociate(&rdataset);
16241         if (result != ISC_R_NOTFOUND)
16242                 goto failure;
16243
16244         result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
16245
16246  failure:
16247         if (node != NULL)
16248                 dns_db_detachnode(db, &node);
16249         return (result);
16250 }
16251
16252 /*
16253  * Given an RRSIG rdataset and an algorithm, determine whether there
16254  * are any signatures using that algorithm.
16255  */
16256 static isc_boolean_t
16257 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
16258         dns_rdata_t rdata = DNS_RDATA_INIT;
16259         dns_rdata_rrsig_t rrsig;
16260         isc_result_t result;
16261
16262         REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
16263         if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
16264                 return (ISC_FALSE);
16265         }
16266
16267         for (result = dns_rdataset_first(rdataset);
16268              result == ISC_R_SUCCESS;
16269              result = dns_rdataset_next(rdataset))
16270         {
16271                 dns_rdataset_current(rdataset, &rdata);
16272                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
16273                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16274                 dns_rdata_reset(&rdata);
16275                 if (rrsig.algorithm == alg)
16276                         return (ISC_TRUE);
16277         }
16278
16279         return (ISC_FALSE);
16280 }
16281
16282 static isc_result_t
16283 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16284            dns_diff_t *diff)
16285 {
16286         dns_name_t *origin;
16287         isc_boolean_t build_nsec3;
16288         isc_result_t result;
16289
16290         origin = dns_db_origin(db);
16291         CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
16292                                  &build_nsec3));
16293         if (build_nsec3)
16294                 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
16295                                            ISC_FALSE, zone->privatetype, diff));
16296         CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
16297
16298  failure:
16299         return (result);
16300 }
16301
16302 static void
16303 zone_rekey(dns_zone_t *zone) {
16304         isc_result_t result;
16305         dns_db_t *db = NULL;
16306         dns_dbnode_t *node = NULL;
16307         dns_dbversion_t *ver = NULL;
16308         dns_rdataset_t soaset, soasigs, keyset, keysigs;
16309         dns_dnsseckeylist_t dnskeys, keys, rmkeys;
16310         dns_dnsseckey_t *key;
16311         dns_diff_t diff, _sig_diff;
16312         zonediff_t zonediff;
16313         isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
16314         isc_boolean_t newalg = ISC_FALSE;
16315         isc_boolean_t fullsign;
16316         dns_ttl_t ttl = 3600;
16317         const char *dir;
16318         isc_mem_t *mctx;
16319         isc_stdtime_t now;
16320         isc_time_t timenow;
16321         isc_interval_t ival;
16322         char timebuf[80];
16323
16324         REQUIRE(DNS_ZONE_VALID(zone));
16325
16326         ISC_LIST_INIT(dnskeys);
16327         ISC_LIST_INIT(keys);
16328         ISC_LIST_INIT(rmkeys);
16329         dns_rdataset_init(&soaset);
16330         dns_rdataset_init(&soasigs);
16331         dns_rdataset_init(&keyset);
16332         dns_rdataset_init(&keysigs);
16333         dir = dns_zone_getkeydirectory(zone);
16334         mctx = zone->mctx;
16335         dns_diff_init(mctx, &diff);
16336         dns_diff_init(mctx, &_sig_diff);
16337         zonediff_init(&zonediff, &_sig_diff);
16338
16339         CHECK(dns_zone_getdb(zone, &db));
16340         CHECK(dns_db_newversion(db, &ver));
16341         CHECK(dns_db_getoriginnode(db, &node));
16342
16343         TIME_NOW(&timenow);
16344         now = isc_time_seconds(&timenow);
16345
16346         dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
16347
16348         /* Get the SOA record's TTL */
16349         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
16350                                   dns_rdatatype_none, 0, &soaset, &soasigs));
16351         ttl = soaset.ttl;
16352         dns_rdataset_disassociate(&soaset);
16353
16354         /* Get the DNSKEY rdataset */
16355         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16356                                      dns_rdatatype_none, 0, &keyset, &keysigs);
16357         if (result == ISC_R_SUCCESS) {
16358                 ttl = keyset.ttl;
16359                 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
16360                                                      mctx, &keyset,
16361                                                      &keysigs, &soasigs,
16362                                                      ISC_FALSE, ISC_FALSE,
16363                                                      &dnskeys));
16364         } else if (result != ISC_R_NOTFOUND)
16365                 goto failure;
16366
16367         /*
16368          * True when called from "rndc sign".  Indicates the zone should be
16369          * fully signed now.
16370          */
16371         fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
16372
16373         result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
16374         if (result == ISC_R_SUCCESS) {
16375                 isc_boolean_t check_ksk;
16376                 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16377
16378                 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
16379                                                &zone->origin, ttl, &diff,
16380                                                ISC_TF(!check_ksk),
16381                                                mctx, logmsg);
16382
16383                 /* Keys couldn't be updated for some reason;
16384                  * try again later. */
16385                 if (result != ISC_R_SUCCESS) {
16386                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
16387                                      "couldn't update zone keys: %s",
16388                                      isc_result_totext(result));
16389                         goto failure;
16390                 }
16391
16392                 /*
16393                  * See if any pre-existing keys have newly become active;
16394                  * also, see if any new key is for a new algorithm, as in that
16395                  * event, we need to sign the zone fully.  (If there's a new
16396                  * key, but it's for an already-existing algorithm, then
16397                  * the zone signing can be handled incrementally.)
16398                  */
16399                 for (key = ISC_LIST_HEAD(dnskeys);
16400                      key != NULL;
16401                      key = ISC_LIST_NEXT(key, link)) {
16402                         if (!key->first_sign)
16403                                 continue;
16404
16405                         newactive = ISC_TRUE;
16406
16407                         if (!dns_rdataset_isassociated(&keysigs)) {
16408                                 newalg = ISC_TRUE;
16409                                 break;
16410                         }
16411
16412                         if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
16413                                 /*
16414                                  * This isn't a new algorithm; clear
16415                                  * first_sign so we won't sign the
16416                                  * whole zone with this key later
16417                                  */
16418                                 key->first_sign = ISC_FALSE;
16419                         } else {
16420                                 newalg = ISC_TRUE;
16421                                 break;
16422                         }
16423                 }
16424
16425                 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
16426                     dnskey_sane(zone, db, ver, &diff)) {
16427                         CHECK(dns_diff_apply(&diff, db, ver));
16428                         CHECK(clean_nsec3param(zone, db, ver, &diff));
16429                         CHECK(add_signing_records(db, zone->privatetype,
16430                                                   ver, &diff,
16431                                                   ISC_TF(newalg || fullsign)));
16432                         CHECK(update_soa_serial(db, ver, &diff, mctx,
16433                                                 zone->updatemethod));
16434                         CHECK(add_chains(zone, db, ver, &diff));
16435                         CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
16436                         CHECK(zone_journal(zone, zonediff.diff, NULL,
16437                                            "zone_rekey"));
16438                         commit = ISC_TRUE;
16439                 }
16440         }
16441
16442         dns_db_closeversion(db, &ver, ISC_TRUE);
16443
16444         if (commit) {
16445                 dns_difftuple_t *tuple;
16446
16447                 LOCK_ZONE(zone);
16448                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16449
16450                 zone_needdump(zone, DNS_DUMP_DELAY);
16451
16452                 zone_settimer(zone, &timenow);
16453
16454                 /* Remove any signatures from removed keys.  */
16455                 if (!ISC_LIST_EMPTY(rmkeys)) {
16456                         for (key = ISC_LIST_HEAD(rmkeys);
16457                              key != NULL;
16458                              key = ISC_LIST_NEXT(key, link)) {
16459                                 result = zone_signwithkey(zone,
16460                                                           dst_key_alg(key->key),
16461                                                           dst_key_id(key->key),
16462                                                           ISC_TRUE);
16463                                 if (result != ISC_R_SUCCESS) {
16464                                         dns_zone_log(zone, ISC_LOG_ERROR,
16465                                              "zone_signwithkey failed: %s",
16466                                              dns_result_totext(result));
16467                                 }
16468                         }
16469                 }
16470
16471                 if (fullsign) {
16472                         /*
16473                          * "rndc sign" was called, so we now sign the zone
16474                          * with all active keys, whether they're new or not.
16475                          */
16476                         for (key = ISC_LIST_HEAD(dnskeys);
16477                              key != NULL;
16478                              key = ISC_LIST_NEXT(key, link)) {
16479                                 if (!key->force_sign && !key->hint_sign)
16480                                         continue;
16481
16482                                 result = zone_signwithkey(zone,
16483                                                           dst_key_alg(key->key),
16484                                                           dst_key_id(key->key),
16485                                                           ISC_FALSE);
16486                                 if (result != ISC_R_SUCCESS) {
16487                                         dns_zone_log(zone, ISC_LOG_ERROR,
16488                                              "zone_signwithkey failed: %s",
16489                                              dns_result_totext(result));
16490                                 }
16491                         }
16492                 } else if (newalg) {
16493                         /*
16494                          * We haven't been told to sign fully, but a new
16495                          * algorithm was added to the DNSKEY.  We sign
16496                          * the full zone, but only with newly active
16497                          * keys.
16498                          */
16499                         for (key = ISC_LIST_HEAD(dnskeys);
16500                              key != NULL;
16501                              key = ISC_LIST_NEXT(key, link)) {
16502                                 if (!key->first_sign)
16503                                         continue;
16504
16505                                 result = zone_signwithkey(zone,
16506                                                           dst_key_alg(key->key),
16507                                                           dst_key_id(key->key),
16508                                                           ISC_FALSE);
16509                                 if (result != ISC_R_SUCCESS) {
16510                                         dns_zone_log(zone, ISC_LOG_ERROR,
16511                                              "zone_signwithkey failed: %s",
16512                                              dns_result_totext(result));
16513                                 }
16514                         }
16515                 }
16516
16517                 /*
16518                  * Clear fullsign flag, if it was set, so we don't do
16519                  * another full signing next time
16520                  */
16521                 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
16522
16523                 /*
16524                  * Cause the zone to add/delete NSEC3 chains for the
16525                  * deferred NSEC3PARAM changes.
16526                  */
16527                 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
16528                      tuple != NULL;
16529                      tuple = ISC_LIST_NEXT(tuple, link)) {
16530                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16531                         dns_rdata_t rdata = DNS_RDATA_INIT;
16532                         dns_rdata_nsec3param_t nsec3param;
16533
16534                         if (tuple->rdata.type != zone->privatetype ||
16535                             tuple->op != DNS_DIFFOP_ADD)
16536                                 continue;
16537
16538                         if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
16539                                                         buf, sizeof(buf)))
16540                                 continue;
16541                         result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
16542                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
16543                         if (nsec3param.flags == 0)
16544                                 continue;
16545
16546                         result = zone_addnsec3chain(zone, &nsec3param);
16547                         if (result != ISC_R_SUCCESS) {
16548                                 dns_zone_log(zone, ISC_LOG_ERROR,
16549                                              "zone_addnsec3chain failed: %s",
16550                                              dns_result_totext(result));
16551                         }
16552                 }
16553
16554                 /*
16555                  * Activate any NSEC3 chain updates that may have
16556                  * been scheduled before this rekey.
16557                  */
16558                 if (fullsign || newalg)
16559                         resume_addnsec3chain(zone);
16560
16561                 /*
16562                  * Schedule the next resigning event
16563                  */
16564                 set_resigntime(zone);
16565                 UNLOCK_ZONE(zone);
16566         }
16567
16568         isc_time_settoepoch(&zone->refreshkeytime);
16569
16570         /*
16571          * If we're doing key maintenance, set the key refresh timer to
16572          * the next scheduled key event or to 'dnssec-loadkeys-interval'
16573          * seconds in the future, whichever is sooner.
16574          */
16575         if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
16576                 isc_time_t timethen;
16577                 isc_stdtime_t then;
16578
16579                 LOCK_ZONE(zone);
16580                 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
16581                                   &timethen);
16582                 zone->refreshkeytime = timethen;
16583                 UNLOCK_ZONE(zone);
16584
16585                 for (key = ISC_LIST_HEAD(dnskeys);
16586                      key != NULL;
16587                      key = ISC_LIST_NEXT(key, link)) {
16588                         then = now;
16589                         result = next_keyevent(key->key, &then);
16590                         if (result != ISC_R_SUCCESS)
16591                                 continue;
16592
16593                         DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
16594                         LOCK_ZONE(zone);
16595                         if (isc_time_compare(&timethen,
16596                                              &zone->refreshkeytime) < 0) {
16597                                 zone->refreshkeytime = timethen;
16598                         }
16599                         UNLOCK_ZONE(zone);
16600                 }
16601
16602                 zone_settimer(zone, &timenow);
16603
16604                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
16605                 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
16606         }
16607
16608  done:
16609         dns_diff_clear(&diff);
16610         dns_diff_clear(&_sig_diff);
16611
16612         clear_keylist(&dnskeys, mctx);
16613         clear_keylist(&keys, mctx);
16614         clear_keylist(&rmkeys, mctx);
16615
16616         if (ver != NULL)
16617                 dns_db_closeversion(db, &ver, ISC_FALSE);
16618         if (dns_rdataset_isassociated(&keyset))
16619                 dns_rdataset_disassociate(&keyset);
16620         if (dns_rdataset_isassociated(&keysigs))
16621                 dns_rdataset_disassociate(&keysigs);
16622         if (dns_rdataset_isassociated(&soasigs))
16623                 dns_rdataset_disassociate(&soasigs);
16624         if (node != NULL)
16625                 dns_db_detachnode(db, &node);
16626         if (db != NULL)
16627                 dns_db_detach(&db);
16628         return;
16629
16630  failure:
16631         /*
16632          * Something went wrong; try again in ten minutes or
16633          * after a key refresh interval, whichever is shorter.
16634          */
16635         isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
16636         isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
16637         goto done;
16638 }
16639
16640 void
16641 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
16642         isc_time_t now;
16643
16644         if (zone->type == dns_zone_master && zone->task != NULL) {
16645                 LOCK_ZONE(zone);
16646
16647                 if (fullsign)
16648                         zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
16649
16650                 TIME_NOW(&now);
16651                 zone->refreshkeytime = now;
16652                 zone_settimer(zone, &now);
16653
16654                 UNLOCK_ZONE(zone);
16655         }
16656 }
16657
16658 isc_result_t
16659 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
16660                  unsigned int *errors)
16661 {
16662         isc_result_t result;
16663         dns_dbnode_t *node = NULL;
16664
16665         REQUIRE(DNS_ZONE_VALID(zone));
16666         REQUIRE(errors != NULL);
16667
16668         result = dns_db_getoriginnode(db, &node);
16669         if (result != ISC_R_SUCCESS)
16670                 return (result);
16671         result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
16672                                   ISC_FALSE);
16673         dns_db_detachnode(db, &node);
16674         return (result);
16675 }
16676
16677 void
16678 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
16679         REQUIRE(DNS_ZONE_VALID(zone));
16680         LOCK_ZONE(zone);
16681         zone->added = added;
16682         UNLOCK_ZONE(zone);
16683 }
16684
16685 isc_boolean_t
16686 dns_zone_getadded(dns_zone_t *zone) {
16687         REQUIRE(DNS_ZONE_VALID(zone));
16688         return (zone->added);
16689 }
16690
16691 isc_result_t
16692 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
16693 {
16694         isc_time_t loadtime;
16695         isc_result_t result;
16696         dns_zone_t *secure = NULL;
16697
16698         TIME_NOW(&loadtime);
16699
16700         /*
16701          * Lock hierarchy: zmgr, zone, raw.
16702          */
16703  again:
16704         LOCK_ZONE(zone);
16705         if (inline_secure(zone))
16706                 LOCK_ZONE(zone->raw);
16707         else if (inline_raw(zone)) {
16708                 secure = zone->secure;
16709                 TRYLOCK_ZONE(result, secure);
16710                 if (result != ISC_R_SUCCESS) {
16711                         UNLOCK_ZONE(zone);
16712                         secure = NULL;
16713 #if ISC_PLATFORM_USETHREADS
16714                         isc_thread_yield();
16715 #endif
16716                         goto again;
16717                 }
16718         }
16719         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
16720         if (inline_secure(zone))
16721                 UNLOCK_ZONE(zone->raw);
16722         else if (secure != NULL)
16723                 UNLOCK_ZONE(secure);
16724         UNLOCK_ZONE(zone);
16725         return result;
16726 }
16727
16728 isc_result_t
16729 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
16730         REQUIRE(DNS_ZONE_VALID(zone));
16731         if (interval == 0)
16732                 return (ISC_R_RANGE);
16733         /* Maximum value: 24 hours (3600 minutes) */
16734         if (interval > (24 * 60))
16735                 interval = (24 * 60);
16736         /* Multiply by 60 for seconds */
16737         zone->refreshkeyinterval = interval * 60;
16738         return (ISC_R_SUCCESS);
16739 }
16740
16741 void
16742 dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) {
16743         REQUIRE(DNS_ZONE_VALID(zone));
16744         zone->requestixfr = flag;
16745 }
16746
16747 isc_boolean_t
16748 dns_zone_getrequestixfr(dns_zone_t *zone) {
16749         REQUIRE(DNS_ZONE_VALID(zone));
16750         return (zone->requestixfr);
16751 }
16752
16753 void
16754 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
16755         REQUIRE(DNS_ZONE_VALID(zone));
16756         zone->updatemethod = method;
16757 }
16758
16759 dns_updatemethod_t
16760 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
16761         REQUIRE(DNS_ZONE_VALID(zone));
16762         return(zone->updatemethod);
16763 }
16764
16765 /*
16766  * Lock hierarchy: zmgr, zone, raw.
16767  */
16768 isc_result_t
16769 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
16770         isc_result_t result;
16771         dns_zonemgr_t *zmgr;
16772
16773         REQUIRE(DNS_ZONE_VALID(zone));
16774         REQUIRE(zone->zmgr != NULL);
16775         REQUIRE(zone->task != NULL);
16776         REQUIRE(zone->loadtask != NULL);
16777         REQUIRE(zone->raw == NULL);
16778
16779         REQUIRE(DNS_ZONE_VALID(raw));
16780         REQUIRE(raw->zmgr == NULL);
16781         REQUIRE(raw->task == NULL);
16782         REQUIRE(raw->loadtask == NULL);
16783         REQUIRE(raw->secure == NULL);
16784
16785         /*
16786          * Lock hierarchy: zmgr, zone, raw.
16787          */
16788         zmgr = zone->zmgr;
16789         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16790         LOCK_ZONE(zone);
16791         LOCK_ZONE(raw);
16792
16793         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
16794                                   NULL, NULL, zone->task, zone_timer, raw,
16795                                   &raw->timer);
16796         if (result != ISC_R_SUCCESS)
16797                 goto unlock;
16798
16799         /*
16800          * The timer "holds" a iref.
16801          */
16802         raw->irefs++;
16803         INSIST(raw->irefs != 0);
16804
16805
16806         /* dns_zone_attach(raw, &zone->raw); */
16807         isc_refcount_increment(&raw->erefs, NULL);
16808         zone->raw = raw;
16809
16810         /* dns_zone_iattach(zone,  &raw->secure); */
16811         zone_iattach(zone, &raw->secure);
16812
16813         isc_task_attach(zone->task, &raw->task);
16814         isc_task_attach(zone->loadtask, &raw->loadtask);
16815
16816         ISC_LIST_APPEND(zmgr->zones, raw, link);
16817         raw->zmgr = zmgr;
16818         zmgr->refs++;
16819
16820  unlock:
16821         UNLOCK_ZONE(raw);
16822         UNLOCK_ZONE(zone);
16823         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16824         return (result);
16825 }
16826
16827 void
16828 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
16829         REQUIRE(DNS_ZONE_VALID(zone));
16830         REQUIRE(raw != NULL && *raw == NULL);
16831
16832         LOCK(&zone->lock);
16833         if (zone->raw != NULL)
16834                 dns_zone_attach(zone->raw, raw);
16835         UNLOCK(&zone->lock);
16836 }
16837
16838 struct keydone {
16839         isc_event_t event;
16840         isc_boolean_t all;
16841         unsigned char data[5];
16842 };
16843
16844 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
16845
16846 static void
16847 keydone(isc_task_t *task, isc_event_t *event) {
16848         const char *me = "keydone";
16849         isc_boolean_t commit = ISC_FALSE;
16850         isc_result_t result;
16851         dns_rdata_t rdata = DNS_RDATA_INIT;
16852         dns_dbversion_t *oldver = NULL, *newver = NULL;
16853         dns_zone_t *zone;
16854         dns_db_t *db = NULL;
16855         dns_dbnode_t *node = NULL;
16856         dns_rdataset_t rdataset;
16857         dns_diff_t diff;
16858         struct keydone *keydone = (struct keydone *)event;
16859         dns_update_log_t log = { update_log_cb, NULL };
16860         isc_boolean_t clear_pending = ISC_FALSE;
16861
16862         UNUSED(task);
16863
16864         zone = event->ev_arg;
16865         INSIST(DNS_ZONE_VALID(zone));
16866
16867         ENTER;
16868
16869         dns_rdataset_init(&rdataset);
16870         dns_diff_init(zone->mctx, &diff);
16871
16872         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16873         if (zone->db != NULL) {
16874                 dns_db_attach(zone->db, &db);
16875                 dns_db_currentversion(db, &oldver);
16876                 result = dns_db_newversion(db, &newver);
16877                 if (result != ISC_R_SUCCESS) {
16878                         dns_zone_log(zone, ISC_LOG_ERROR,
16879                                      "keydone:dns_db_newversion -> %s",
16880                                      dns_result_totext(result));
16881                         goto failure;
16882                 }
16883         }
16884         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16885         if (db == NULL)
16886                 goto failure;
16887
16888         result = dns_db_getoriginnode(db, &node);
16889         if (result != ISC_R_SUCCESS)
16890                 goto failure;
16891
16892         result = dns_db_findrdataset(db, node, newver, zone->privatetype,
16893                                      dns_rdatatype_none, 0, &rdataset, NULL);
16894         if (result == ISC_R_NOTFOUND) {
16895                 INSIST(!dns_rdataset_isassociated(&rdataset));
16896                 goto failure;
16897         }
16898         if (result != ISC_R_SUCCESS) {
16899                 INSIST(!dns_rdataset_isassociated(&rdataset));
16900                 goto failure;
16901         }
16902
16903         for (result = dns_rdataset_first(&rdataset);
16904              result == ISC_R_SUCCESS;
16905              result = dns_rdataset_next(&rdataset)) {
16906                 isc_boolean_t found = ISC_FALSE;
16907
16908                 dns_rdataset_current(&rdataset, &rdata);
16909
16910                 if (keydone->all) {
16911                         if (rdata.length == 5 && rdata.data[0] != 0 &&
16912                                rdata.data[3] == 0 && rdata.data[4] == 1)
16913                                 found = ISC_TRUE;
16914                         else if (rdata.data[0] == 0 &&
16915                                  (rdata.data[2] & PENDINGFLAGS) != 0) {
16916                                 found = ISC_TRUE;
16917                                 clear_pending = ISC_TRUE;
16918                         }
16919                 } else if (rdata.length == 5 &&
16920                            memcmp(rdata.data, keydone->data, 5) == 0)
16921                         found = ISC_TRUE;
16922
16923                 if (found)
16924                         CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
16925                                             &zone->origin, rdataset.ttl,
16926                                             &rdata));
16927                 dns_rdata_reset(&rdata);
16928         }
16929
16930         if (!ISC_LIST_EMPTY(diff.tuples)) {
16931                 /* Write changes to journal file. */
16932                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
16933                                         zone->updatemethod));
16934
16935                 result = dns_update_signatures(&log, zone, db,
16936                                                oldver, newver, &diff,
16937                                                zone->sigvalidityinterval);
16938                 if (!clear_pending)
16939                         CHECK(result);
16940
16941                 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
16942                 commit = ISC_TRUE;
16943
16944                 LOCK_ZONE(zone);
16945                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
16946                 zone_needdump(zone, 30);
16947                 UNLOCK_ZONE(zone);
16948         }
16949
16950  failure:
16951         if (dns_rdataset_isassociated(&rdataset))
16952                 dns_rdataset_disassociate(&rdataset);
16953         if (db != NULL) {
16954                 if (node != NULL)
16955                         dns_db_detachnode(db, &node);
16956                 if (oldver != NULL)
16957                         dns_db_closeversion(db, &oldver, ISC_FALSE);
16958                 if (newver != NULL)
16959                         dns_db_closeversion(db, &newver, commit);
16960                 dns_db_detach(&db);
16961         }
16962         dns_diff_clear(&diff);
16963         isc_event_free(&event);
16964         dns_zone_idetach(&zone);
16965 }
16966
16967 isc_result_t
16968 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
16969         isc_result_t result = ISC_R_SUCCESS;
16970         isc_event_t *e;
16971         isc_buffer_t b;
16972         dns_zone_t *dummy = NULL;
16973         struct keydone *kd;
16974
16975         REQUIRE(DNS_ZONE_VALID(zone));
16976
16977         LOCK_ZONE(zone);
16978
16979         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
16980                                zone, sizeof(struct keydone));
16981         if (e == NULL) {
16982                 result = ISC_R_NOMEMORY;
16983                 goto failure;
16984         }
16985
16986         kd = (struct keydone *) e;
16987         if (strcasecmp(keystr, "all") == 0)
16988                 kd->all = ISC_TRUE;
16989         else {
16990                 isc_textregion_t r;
16991                 char *algstr;
16992                 dns_keytag_t keyid;
16993                 dns_secalg_t alg;
16994                 size_t n;
16995
16996                 kd->all = ISC_FALSE;
16997
16998                 n = sscanf(keystr, "%hd/", &keyid);
16999                 if (n == 0U)
17000                         CHECK(ISC_R_FAILURE);
17001
17002                 algstr = strchr(keystr, '/');
17003                 if (algstr != NULL)
17004                         algstr++;
17005                 else
17006                         CHECK(ISC_R_FAILURE);
17007
17008                 n = sscanf(algstr, "%hhd", &alg);
17009                 if (n == 0U) {
17010                         DE_CONST(algstr, r.base);
17011                         r.length = strlen(algstr);
17012                         CHECK(dns_secalg_fromtext(&alg, &r));
17013                 }
17014
17015                 /* construct a private-type rdata */
17016                 isc_buffer_init(&b, kd->data, sizeof(kd->data));
17017                 isc_buffer_putuint8(&b, alg);
17018                 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
17019                 isc_buffer_putuint8(&b, (keyid & 0xff));
17020                 isc_buffer_putuint8(&b, 0);
17021                 isc_buffer_putuint8(&b, 1);
17022         }
17023
17024         zone_iattach(zone, &dummy);
17025         isc_task_send(zone->task, &e);
17026
17027  failure:
17028         if (e != NULL)
17029                 isc_event_free(&e);
17030         UNLOCK_ZONE(zone);
17031         return (result);
17032 }
17033
17034 static void
17035 setnsec3param(isc_task_t *task, isc_event_t *event) {
17036         const char *me = "setnsec3param";
17037         isc_boolean_t commit = ISC_FALSE;
17038         isc_result_t result;
17039         dns_dbversion_t *oldver = NULL, *newver = NULL;
17040         dns_zone_t *zone;
17041         dns_db_t *db = NULL;
17042         dns_dbnode_t *node = NULL;
17043         dns_rdataset_t prdataset, nrdataset;
17044         dns_diff_t diff;
17045         struct np3event *npe = (struct np3event *)event;
17046         nsec3param_t *np;
17047         dns_update_log_t log = { update_log_cb, NULL };
17048         dns_rdata_t rdata;
17049         isc_boolean_t nseconly;
17050         isc_boolean_t exists = ISC_FALSE;
17051
17052         UNUSED(task);
17053
17054         zone = event->ev_arg;
17055         INSIST(DNS_ZONE_VALID(zone));
17056
17057         ENTER;
17058
17059         np = &npe->params;
17060
17061         dns_rdataset_init(&prdataset);
17062         dns_rdataset_init(&nrdataset);
17063         dns_diff_init(zone->mctx, &diff);
17064
17065         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17066         if (zone->db != NULL) {
17067                 dns_db_attach(zone->db, &db);
17068                 dns_db_currentversion(db, &oldver);
17069                 result = dns_db_newversion(db, &newver);
17070                 if (result != ISC_R_SUCCESS) {
17071                         dns_zone_log(zone, ISC_LOG_ERROR,
17072                                      "setnsec3param:dns_db_newversion -> %s",
17073                                      dns_result_totext(result));
17074                         goto failure;
17075                 }
17076         }
17077         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17078         if (db == NULL)
17079                 goto failure;
17080
17081         CHECK(dns_db_getoriginnode(db, &node));
17082
17083         /*
17084          * Does a private-type record already exist for this chain?
17085          */
17086         result = dns_db_findrdataset(db, node, newver, zone->privatetype,
17087                                      dns_rdatatype_none, 0, &prdataset, NULL);
17088         if (result == ISC_R_SUCCESS) {
17089                 for (result = dns_rdataset_first(&prdataset);
17090                      result == ISC_R_SUCCESS;
17091                      result = dns_rdataset_next(&prdataset)) {
17092                         dns_rdata_init(&rdata);
17093                         dns_rdataset_current(&prdataset, &rdata);
17094
17095                         if (np->length == rdata.length &&
17096                             memcmp(rdata.data, np->data, np->length) == 0) {
17097                                 exists = ISC_TRUE;
17098                                 break;
17099                         }
17100                 }
17101         } else if (result != ISC_R_NOTFOUND) {
17102                 INSIST(!dns_rdataset_isassociated(&prdataset));
17103                 goto failure;
17104         }
17105
17106         /*
17107          * Does the chain already exist?
17108          */
17109         result = dns_db_findrdataset(db, node, newver,
17110                                      dns_rdatatype_nsec3param,
17111                                      dns_rdatatype_none, 0, &nrdataset, NULL);
17112         if (result == ISC_R_SUCCESS) {
17113                 for (result = dns_rdataset_first(&nrdataset);
17114                      result == ISC_R_SUCCESS;
17115                      result = dns_rdataset_next(&nrdataset)) {
17116                         dns_rdata_init(&rdata);
17117                         dns_rdataset_current(&nrdataset, &rdata);
17118
17119                         if (np->length == (rdata.length + 1) &&
17120                             memcmp(rdata.data, np->data + 1,
17121                                    np->length - 1) == 0)
17122                         {
17123                                 exists = ISC_TRUE;
17124                                 break;
17125                         }
17126                 }
17127         } else if (result != ISC_R_NOTFOUND) {
17128                 INSIST(!dns_rdataset_isassociated(&nrdataset));
17129                 goto failure;
17130         }
17131
17132
17133         /*
17134          * We need to remove any existing NSEC3 chains.
17135          */
17136         if (!exists && np->replace && (np->length != 0 || np->nsec))
17137                 CHECK(dns_nsec3param_deletechains(db, newver, zone,
17138                                                   !np->nsec, &diff));
17139
17140         if (!exists && np->length != 0) {
17141                 /*
17142                  * We're creating an NSEC3 chain.
17143                  *
17144                  * If the zone is not currently capable of supporting
17145                  * an NSEC3 chain, add the INITIAL flag, so these
17146                  * parameters can be used later when NSEC3 becomes
17147                  * available.
17148                  */
17149                 dns_rdata_init(&rdata);
17150
17151                 np->data[2] |= DNS_NSEC3FLAG_CREATE;
17152                 result = dns_nsec_nseconly(db, newver, &nseconly);
17153                 if (result == ISC_R_NOTFOUND || nseconly)
17154                         np->data[2] |= DNS_NSEC3FLAG_INITIAL;
17155
17156                 rdata.length = np->length;
17157                 rdata.data = np->data;
17158                 rdata.type = zone->privatetype;
17159                 rdata.rdclass = zone->rdclass;
17160                 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
17161                                     &zone->origin, 0, &rdata));
17162         }
17163
17164         if (!ISC_LIST_EMPTY(diff.tuples)) {
17165                 /* Write changes to journal file. */
17166                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
17167                                         zone->updatemethod));
17168                 result = dns_update_signatures(&log, zone, db,
17169                                                oldver, newver, &diff,
17170                                                zone->sigvalidityinterval);
17171                 if (result != ISC_R_NOTFOUND)
17172                         CHECK(result);
17173                 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
17174                 commit = ISC_TRUE;
17175
17176                 LOCK_ZONE(zone);
17177                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
17178                 zone_needdump(zone, 30);
17179                 UNLOCK_ZONE(zone);
17180         }
17181
17182  failure:
17183         if (dns_rdataset_isassociated(&prdataset))
17184                 dns_rdataset_disassociate(&prdataset);
17185         if (dns_rdataset_isassociated(&nrdataset))
17186                 dns_rdataset_disassociate(&nrdataset);
17187         if (node != NULL)
17188                 dns_db_detachnode(db, &node);
17189         if (oldver != NULL)
17190                 dns_db_closeversion(db, &oldver, ISC_FALSE);
17191         if (newver != NULL)
17192                 dns_db_closeversion(db, &newver, commit);
17193         if (db != NULL)
17194                 dns_db_detach(&db);
17195         if (commit)
17196                 resume_addnsec3chain(zone);
17197         dns_diff_clear(&diff);
17198         isc_event_free(&event);
17199         dns_zone_idetach(&zone);
17200 }
17201
17202 isc_result_t
17203 dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
17204                        isc_uint16_t iter, isc_uint8_t saltlen,
17205                        unsigned char *salt, isc_boolean_t replace)
17206 {
17207         isc_result_t result = ISC_R_SUCCESS;
17208         dns_rdata_nsec3param_t param;
17209         dns_rdata_t nrdata = DNS_RDATA_INIT;
17210         dns_rdata_t prdata = DNS_RDATA_INIT;
17211         unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
17212         struct np3event *npe;
17213         nsec3param_t *np;
17214         dns_zone_t *dummy = NULL;
17215         isc_buffer_t b;
17216         isc_event_t *e;
17217
17218         REQUIRE(DNS_ZONE_VALID(zone));
17219         REQUIRE(salt != NULL);
17220
17221         LOCK_ZONE(zone);
17222
17223         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
17224                                setnsec3param, zone, sizeof(struct np3event));
17225         if (e == NULL) {
17226                 result = ISC_R_NOMEMORY;
17227                 goto failure;
17228         }
17229
17230         npe = (struct np3event *) e;
17231         np = &npe->params;
17232
17233         np->replace = replace;
17234         if (hash == 0) {
17235                 np->length = 0;
17236                 np->nsec = ISC_TRUE;
17237         } else {
17238                 param.common.rdclass = zone->rdclass;
17239                 param.common.rdtype = dns_rdatatype_nsec3param;
17240                 ISC_LINK_INIT(&param.common, link);
17241                 param.mctx = NULL;
17242                 param.hash = hash;
17243                 param.flags = flags;
17244                 param.iterations = iter;
17245                 param.salt_length = saltlen;
17246                 param.salt = salt;
17247                 isc_buffer_init(&b, nbuf, sizeof(nbuf));
17248                 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
17249                                            dns_rdatatype_nsec3param,
17250                                            &param, &b));
17251                 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
17252                                          np->data, sizeof(np->data));
17253                 np->length = prdata.length;
17254         }
17255
17256         zone_iattach(zone, &dummy);
17257         isc_task_send(zone->task, &e);
17258
17259  failure:
17260         if (e != NULL)
17261                 isc_event_free(&e);
17262         UNLOCK_ZONE(zone);
17263         return (result);
17264 }
17265
17266 void
17267 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
17268         REQUIRE(DNS_ZONE_VALID(zone));
17269
17270         zone->statlevel = level;
17271 }
17272
17273 dns_zonestat_level_t
17274 dns_zone_getstatlevel(dns_zone_t *zone) {
17275         REQUIRE(DNS_ZONE_VALID(zone));
17276
17277         return (zone->statlevel);
17278 }