]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/bind9/lib/dns/zone.c
Fix integer overflow in IGMP protocol. [SA-15:04]
[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                 } else {
8500                         /*
8501                          * No previously known key, and the key is not
8502                          * secure, so skip it.
8503                          */
8504                         continue;
8505                 }
8506
8507                 /* Delete old version */
8508                 if (deletekey || !newkey)
8509                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8510                                             DNS_DIFFOP_DEL, keyname, 0,
8511                                             &keydatarr));
8512
8513                 if (updatekey) {
8514                         /* Set refresh timer */
8515                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8516                         dns_rdata_reset(&keydatarr);
8517                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8518                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8519                                              dns_rdatatype_keydata,
8520                                              &keydata, &keyb);
8521
8522                         /* Insert updated version */
8523                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8524                                             DNS_DIFFOP_ADD, keyname, 0,
8525                                             &keydatarr));
8526                 } else if (newkey) {
8527                         /* Convert DNSKEY to KEYDATA */
8528                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8529                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8530                         dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
8531                                                NULL);
8532                         keydata.addhd = initializing ? now : now + MONTH;
8533                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8534                         dns_rdata_reset(&keydatarr);
8535                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8536                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8537                                              dns_rdatatype_keydata,
8538                                              &keydata, &keyb);
8539
8540                         /* Insert into key zone */
8541                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8542                                             DNS_DIFFOP_ADD, keyname, 0,
8543                                             &keydatarr));
8544                 }
8545
8546                 if (trustkey) {
8547                         /* Trust this key. */
8548                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8549                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8550                         trust_key(zone, keyname, &dnskey, mctx);
8551                 }
8552
8553                 if (secure && !deletekey)
8554                         set_refreshkeytimer(zone, &keydata, now);
8555         }
8556
8557         /*
8558          * RFC5011 says, "A trust point that has all of its trust anchors
8559          * revoked is considered deleted and is treated as if the trust
8560          * point was never configured."  But if someone revoked their
8561          * active key before the standby was trusted, that would mean the
8562          * zone would suddenly be nonsecured.  We avoid this by checking to
8563          * see if there's pending keydata.  If so, we put a null key in
8564          * the security roots; then all queries to the zone will fail.
8565          */
8566         if (pending != 0)
8567                 fail_secure(zone, keyname);
8568
8569  done:
8570
8571         if (!ISC_LIST_EMPTY(diff.tuples)) {
8572                 /* Write changes to journal file. */
8573                 CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
8574                                         zone->updatemethod));
8575                 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
8576                 commit = ISC_TRUE;
8577
8578                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8579                 zone_needdump(zone, 30);
8580         }
8581
8582   failure:
8583
8584         dns_diff_clear(&diff);
8585         if (ver != NULL)
8586                 dns_db_closeversion(kfetch->db, &ver, commit);
8587
8588  cleanup:
8589         dns_db_detach(&kfetch->db);
8590
8591         INSIST(zone->irefs > 0);
8592         zone->irefs--;
8593         kfetch->zone = NULL;
8594
8595         if (dns_rdataset_isassociated(&kfetch->keydataset))
8596                 dns_rdataset_disassociate(&kfetch->keydataset);
8597         if (dns_rdataset_isassociated(&kfetch->dnskeyset))
8598                 dns_rdataset_disassociate(&kfetch->dnskeyset);
8599         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8600                 dns_rdataset_disassociate(&kfetch->dnskeysigset);
8601
8602         dns_name_free(keyname, mctx);
8603         isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
8604         isc_mem_detach(&mctx);
8605
8606         if (secroots != NULL)
8607                 dns_keytable_detach(&secroots);
8608
8609         free_needed = exit_check(zone);
8610         UNLOCK_ZONE(zone);
8611         if (free_needed)
8612                 zone_free(zone);
8613 }
8614
8615 /*
8616  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
8617  * records from the zone apex.
8618  */
8619 static void
8620 zone_refreshkeys(dns_zone_t *zone) {
8621         const char me[] = "zone_refreshkeys";
8622         isc_result_t result;
8623         dns_rriterator_t rrit;
8624         dns_db_t *db = NULL;
8625         dns_dbversion_t *ver = NULL;
8626         dns_diff_t diff;
8627         dns_rdata_t rdata = DNS_RDATA_INIT;
8628         dns_rdata_keydata_t kd;
8629         isc_stdtime_t now;
8630         isc_boolean_t commit = ISC_FALSE;
8631         isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
8632
8633         ENTER;
8634         REQUIRE(zone->db != NULL);
8635
8636         isc_stdtime_get(&now);
8637
8638         LOCK_ZONE(zone);
8639         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
8640                 isc_time_settoepoch(&zone->refreshkeytime);
8641                 UNLOCK_ZONE(zone);
8642                 return;
8643         }
8644
8645         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8646         dns_db_attach(zone->db, &db);
8647         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8648
8649         dns_diff_init(zone->mctx, &diff);
8650
8651         CHECK(dns_db_newversion(db, &ver));
8652
8653         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
8654
8655         dns_rriterator_init(&rrit, db, ver, 0);
8656         for (result = dns_rriterator_first(&rrit);
8657              result == ISC_R_SUCCESS;
8658              result = dns_rriterator_nextrrset(&rrit)) {
8659                 isc_stdtime_t timer = 0xffffffff;
8660                 dns_name_t *name = NULL, *kname = NULL;
8661                 dns_rdataset_t *kdset = NULL;
8662                 dns_keyfetch_t *kfetch;
8663                 isc_uint32_t ttl;
8664
8665                 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
8666                 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
8667                     !dns_rdataset_isassociated(kdset))
8668                         continue;
8669
8670                 /*
8671                  * Scan the stored keys looking for ones that need
8672                  * removal or refreshing
8673                  */
8674                 for (result = dns_rdataset_first(kdset);
8675                      result == ISC_R_SUCCESS;
8676                      result = dns_rdataset_next(kdset)) {
8677                         dns_rdata_reset(&rdata);
8678                         dns_rdataset_current(kdset, &rdata);
8679                         result = dns_rdata_tostruct(&rdata, &kd, NULL);
8680                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8681
8682                         /* Removal timer expired? */
8683                         if (kd.removehd != 0 && kd.removehd < now) {
8684                                 CHECK(update_one_rr(db, ver, &diff,
8685                                                     DNS_DIFFOP_DEL, name, ttl,
8686                                                     &rdata));
8687                                 continue;
8688                         }
8689
8690                         /* Acceptance timer expired? */
8691                         if (kd.addhd != 0 && kd.addhd < now)
8692                                 timer = kd.addhd;
8693
8694                         /* Or do we just need to refresh the keyset? */
8695                         if (timer > kd.refresh)
8696                                 timer = kd.refresh;
8697                 }
8698
8699                 if (timer > now)
8700                         continue;
8701
8702                 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
8703                 if (kfetch == NULL) {
8704                         fetch_err = ISC_TRUE;
8705                         goto failure;
8706                 }
8707
8708                 zone->refreshkeycount++;
8709                 kfetch->zone = zone;
8710                 zone->irefs++;
8711                 INSIST(zone->irefs != 0);
8712                 dns_fixedname_init(&kfetch->name);
8713                 kname = dns_fixedname_name(&kfetch->name);
8714                 dns_name_dup(name, zone->mctx, kname);
8715                 dns_rdataset_init(&kfetch->dnskeyset);
8716                 dns_rdataset_init(&kfetch->dnskeysigset);
8717                 dns_rdataset_init(&kfetch->keydataset);
8718                 dns_rdataset_clone(kdset, &kfetch->keydataset);
8719                 kfetch->db = NULL;
8720                 dns_db_attach(db, &kfetch->db);
8721                 kfetch->fetch = NULL;
8722
8723                 result = dns_resolver_createfetch(zone->view->resolver,
8724                                                   kname, dns_rdatatype_dnskey,
8725                                                   NULL, NULL, NULL,
8726                                                   DNS_FETCHOPT_NOVALIDATE,
8727                                                   zone->task,
8728                                                   keyfetch_done, kfetch,
8729                                                   &kfetch->dnskeyset,
8730                                                   &kfetch->dnskeysigset,
8731                                                   &kfetch->fetch);
8732                 if (result == ISC_R_SUCCESS)
8733                         fetching = ISC_TRUE;
8734                 else {
8735                         zone->refreshkeycount--;
8736                         zone->irefs--;
8737                         dns_db_detach(&kfetch->db);
8738                         dns_rdataset_disassociate(&kfetch->keydataset);
8739                         dns_name_free(kname, zone->mctx);
8740                         isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
8741                         dns_zone_log(zone, ISC_LOG_WARNING,
8742                                      "Failed to create fetch for "
8743                                      "DNSKEY update");
8744                         fetch_err = ISC_TRUE;
8745                 }
8746         }
8747         if (!ISC_LIST_EMPTY(diff.tuples)) {
8748                 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
8749                                         zone->updatemethod));
8750                 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
8751                 commit = ISC_TRUE;
8752                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8753                 zone_needdump(zone, 30);
8754         }
8755
8756   failure:
8757         if (fetch_err) {
8758                 /*
8759                  * Error during a key fetch; retry in an hour.
8760                  */
8761                 isc_time_t timenow, timethen;
8762                 char timebuf[80];
8763
8764                 TIME_NOW(&timenow);
8765                 DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
8766                 zone->refreshkeytime = timethen;
8767                 zone_settimer(zone, &timenow);
8768
8769                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
8770                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
8771                              timebuf);
8772
8773                 if (!fetching)
8774                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8775         }
8776
8777         UNLOCK_ZONE(zone);
8778
8779         dns_diff_clear(&diff);
8780         if (ver != NULL) {
8781                 dns_rriterator_destroy(&rrit);
8782                 dns_db_closeversion(db, &ver, commit);
8783         }
8784         dns_db_detach(&db);
8785 }
8786
8787 static void
8788 zone_maintenance(dns_zone_t *zone) {
8789         const char me[] = "zone_maintenance";
8790         isc_time_t now;
8791         isc_result_t result;
8792         isc_boolean_t dumping;
8793
8794         REQUIRE(DNS_ZONE_VALID(zone));
8795         ENTER;
8796
8797         /*
8798          * Are we pending load/reload?
8799          */
8800         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
8801                 return;
8802
8803         /*
8804          * Configuring the view of this zone may have
8805          * failed, for example because the config file
8806          * had a syntax error.  In that case, the view
8807          * adb or resolver will be NULL, and we had better not try
8808          * to do further maintenance on it.
8809          */
8810         if (zone->view == NULL || zone->view->adb == NULL)
8811                 return;
8812
8813         TIME_NOW(&now);
8814
8815         /*
8816          * Expire check.
8817          */
8818         switch (zone->type) {
8819         case dns_zone_redirect:
8820                 if (zone->masters == NULL)
8821                         break;
8822         case dns_zone_slave:
8823         case dns_zone_stub:
8824                 LOCK_ZONE(zone);
8825                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
8826                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8827                         zone_expire(zone);
8828                         zone->refreshtime = now;
8829                 }
8830                 UNLOCK_ZONE(zone);
8831                 break;
8832         default:
8833                 break;
8834         }
8835
8836         /*
8837          * Up to date check.
8838          */
8839         switch (zone->type) {
8840         case dns_zone_redirect:
8841                 if (zone->masters == NULL)
8842                         break;
8843         case dns_zone_slave:
8844         case dns_zone_stub:
8845                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8846                     isc_time_compare(&now, &zone->refreshtime) >= 0)
8847                         dns_zone_refresh(zone);
8848                 break;
8849         default:
8850                 break;
8851         }
8852
8853         /*
8854          * Slaves send notifies before backing up to disk, masters after.
8855          */
8856         if (zone->type == dns_zone_slave &&
8857             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8858             isc_time_compare(&now, &zone->notifytime) >= 0)
8859                 zone_notify(zone, &now);
8860
8861         /*
8862          * Do we need to consolidate the backing store?
8863          */
8864         switch (zone->type) {
8865         case dns_zone_master:
8866         case dns_zone_slave:
8867         case dns_zone_key:
8868         case dns_zone_redirect:
8869         case dns_zone_stub:
8870                 LOCK_ZONE(zone);
8871                 if (zone->masterfile != NULL &&
8872                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
8873                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8874                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
8875                         dumping = was_dumping(zone);
8876                 } else
8877                         dumping = ISC_TRUE;
8878                 UNLOCK_ZONE(zone);
8879                 if (!dumping) {
8880                         result = zone_dump(zone, ISC_TRUE); /* task locked */
8881                         if (result != ISC_R_SUCCESS)
8882                                 dns_zone_log(zone, ISC_LOG_WARNING,
8883                                              "dump failed: %s",
8884                                              dns_result_totext(result));
8885                 }
8886                 break;
8887         default:
8888                 break;
8889         }
8890
8891         /*
8892          * Master/redirect zones send notifies now, if needed
8893          */
8894         switch (zone->type) {
8895         case dns_zone_master:
8896         case dns_zone_redirect:
8897                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8898                     isc_time_compare(&now, &zone->notifytime) >= 0)
8899                         zone_notify(zone, &now);
8900         default:
8901                 break;
8902         }
8903
8904         /*
8905          * Do we need to refresh keys?
8906          */
8907         switch (zone->type) {
8908         case dns_zone_key:
8909                 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
8910                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8911                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
8912                                 zone_refreshkeys(zone);
8913                         }
8914                 }
8915                 break;
8916         case dns_zone_master:
8917                 if (!isc_time_isepoch(&zone->refreshkeytime) &&
8918                     isc_time_compare(&now, &zone->refreshkeytime) >= 0)
8919                         zone_rekey(zone);
8920         default:
8921                 break;
8922         }
8923
8924         switch (zone->type) {
8925         case dns_zone_master:
8926         case dns_zone_redirect:
8927         case dns_zone_slave:
8928                 /*
8929                  * Do we need to sign/resign some RRsets?
8930                  */
8931                 if (!isc_time_isepoch(&zone->signingtime) &&
8932                     isc_time_compare(&now, &zone->signingtime) >= 0)
8933                         zone_sign(zone);
8934                 else if (!isc_time_isepoch(&zone->resigntime) &&
8935                     isc_time_compare(&now, &zone->resigntime) >= 0)
8936                         zone_resigninc(zone);
8937                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
8938                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
8939                         zone_nsec3chain(zone);
8940                 /*
8941                  * Do we need to issue a key expiry warning?
8942                  */
8943                 if (!isc_time_isepoch(&zone->keywarntime) &&
8944                     isc_time_compare(&now, &zone->keywarntime) >= 0)
8945                         set_key_expiry_warning(zone, zone->key_expiry,
8946                                                isc_time_seconds(&now));
8947                 break;
8948
8949         default:
8950                 break;
8951         }
8952         zone_settimer(zone, &now);
8953 }
8954
8955 void
8956 dns_zone_markdirty(dns_zone_t *zone) {
8957         isc_uint32_t serial;
8958         isc_result_t result = ISC_R_SUCCESS;
8959         dns_zone_t *secure = NULL;
8960
8961         /*
8962          * Obtaining a lock on the zone->secure (see zone_send_secureserial)
8963          * could result in a deadlock due to a LOR so we will spin if we
8964          * can't obtain the both locks.
8965          */
8966  again:
8967         LOCK_ZONE(zone);
8968         if (zone->type == dns_zone_master) {
8969                 if (inline_raw(zone)) {
8970                         unsigned int soacount;
8971                         secure = zone->secure;
8972                         INSIST(secure != zone);
8973                         TRYLOCK_ZONE(result, secure);
8974                         if (result != ISC_R_SUCCESS) {
8975                                 UNLOCK_ZONE(zone);
8976                                 secure = NULL;
8977 #ifdef ISC_PLATFORM_USETHREADS
8978                                 isc_thread_yield();
8979 #endif
8980                                 goto again;
8981                         }
8982
8983                         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8984                         if (zone->db != NULL) {
8985                                 result = zone_get_from_db(zone, zone->db, NULL,
8986                                                           &soacount, &serial,
8987                                                           NULL, NULL, NULL,
8988                                                           NULL, NULL);
8989                         } else
8990                                 result = DNS_R_NOTLOADED;
8991                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8992                         if (result == ISC_R_SUCCESS && soacount > 0U)
8993                                 zone_send_secureserial(zone, serial);
8994                 }
8995
8996                 /* XXXMPA make separate call back */
8997                 if (result == ISC_R_SUCCESS)
8998                         set_resigntime(zone);
8999         }
9000         if (secure != NULL)
9001                 UNLOCK_ZONE(secure);
9002         zone_needdump(zone, DNS_DUMP_DELAY);
9003         UNLOCK_ZONE(zone);
9004 }
9005
9006 void
9007 dns_zone_expire(dns_zone_t *zone) {
9008         REQUIRE(DNS_ZONE_VALID(zone));
9009
9010         LOCK_ZONE(zone);
9011         zone_expire(zone);
9012         UNLOCK_ZONE(zone);
9013 }
9014
9015 static void
9016 zone_expire(dns_zone_t *zone) {
9017         /*
9018          * 'zone' locked by caller.
9019          */
9020
9021         REQUIRE(LOCKED_ZONE(zone));
9022
9023         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
9024
9025         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
9026         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
9027         zone->retry = DNS_ZONE_DEFAULTRETRY;
9028         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9029         zone_unload(zone);
9030 }
9031
9032 void
9033 dns_zone_refresh(dns_zone_t *zone) {
9034         isc_interval_t i;
9035         isc_uint32_t oldflags;
9036         unsigned int j;
9037         isc_result_t result;
9038
9039         REQUIRE(DNS_ZONE_VALID(zone));
9040
9041         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
9042                 return;
9043
9044         /*
9045          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
9046          * in progress at a time.
9047          */
9048
9049         LOCK_ZONE(zone);
9050         oldflags = zone->flags;
9051         if (zone->masterscnt == 0) {
9052                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
9053                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
9054                         dns_zone_log(zone, ISC_LOG_ERROR,
9055                                      "cannot refresh: no masters");
9056                 goto unlock;
9057         }
9058         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
9059         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9060         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9061         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
9062                 goto unlock;
9063
9064         /*
9065          * Set the next refresh time as if refresh check has failed.
9066          * Setting this to the retry time will do that.  XXXMLG
9067          * If we are successful it will be reset using zone->refresh.
9068          */
9069         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
9070                          0);
9071         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
9072         if (result != ISC_R_SUCCESS)
9073                 dns_zone_log(zone, ISC_LOG_WARNING,
9074                              "isc_time_nowplusinterval() failed: %s",
9075                              dns_result_totext(result));
9076
9077         /*
9078          * When lacking user-specified timer values from the SOA,
9079          * do exponential backoff of the retry time up to a
9080          * maximum of six hours.
9081          */
9082         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
9083                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
9084
9085         zone->curmaster = 0;
9086         for (j = 0; j < zone->masterscnt; j++)
9087                 zone->mastersok[j] = ISC_FALSE;
9088         /* initiate soa query */
9089         queue_soa_query(zone);
9090  unlock:
9091         UNLOCK_ZONE(zone);
9092 }
9093
9094 isc_result_t
9095 dns_zone_flush(dns_zone_t *zone) {
9096         isc_result_t result = ISC_R_SUCCESS;
9097         isc_boolean_t dumping;
9098
9099         REQUIRE(DNS_ZONE_VALID(zone));
9100
9101         LOCK_ZONE(zone);
9102         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
9103         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9104             zone->masterfile != NULL) {
9105                 result = ISC_R_ALREADYRUNNING;
9106                 dumping = was_dumping(zone);
9107         } else
9108                 dumping = ISC_TRUE;
9109         UNLOCK_ZONE(zone);
9110         if (!dumping)
9111                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
9112         return (result);
9113 }
9114
9115 isc_result_t
9116 dns_zone_dump(dns_zone_t *zone) {
9117         isc_result_t result = ISC_R_ALREADYRUNNING;
9118         isc_boolean_t dumping;
9119
9120         REQUIRE(DNS_ZONE_VALID(zone));
9121
9122         LOCK_ZONE(zone);
9123         dumping = was_dumping(zone);
9124         UNLOCK_ZONE(zone);
9125         if (!dumping)
9126                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
9127         return (result);
9128 }
9129
9130 static void
9131 zone_needdump(dns_zone_t *zone, unsigned int delay) {
9132         const char me[] = "zone_needdump";
9133         isc_time_t dumptime;
9134         isc_time_t now;
9135
9136         /*
9137          * 'zone' locked by caller
9138          */
9139
9140         REQUIRE(DNS_ZONE_VALID(zone));
9141         REQUIRE(LOCKED_ZONE(zone));
9142         ENTER;
9143
9144         /*
9145          * Do we have a place to dump to and are we loaded?
9146          */
9147         if (zone->masterfile == NULL ||
9148             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
9149                 return;
9150
9151         TIME_NOW(&now);
9152         /* add some noise */
9153         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
9154
9155         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9156         if (isc_time_isepoch(&zone->dumptime) ||
9157             isc_time_compare(&zone->dumptime, &dumptime) > 0)
9158                 zone->dumptime = dumptime;
9159         if (zone->task != NULL)
9160                 zone_settimer(zone, &now);
9161 }
9162
9163 static void
9164 dump_done(void *arg, isc_result_t result) {
9165         const char me[] = "dump_done";
9166         dns_zone_t *zone = arg;
9167         dns_db_t *db;
9168         dns_dbversion_t *version;
9169         isc_boolean_t again = ISC_FALSE;
9170         isc_boolean_t compact = ISC_FALSE;
9171         isc_uint32_t serial;
9172         isc_result_t tresult;
9173
9174         REQUIRE(DNS_ZONE_VALID(zone));
9175
9176         ENTER;
9177
9178         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
9179             zone->journalsize != -1) {
9180
9181                 /*
9182                  * We don't own these, zone->dctx must stay valid.
9183                  */
9184                 db = dns_dumpctx_db(zone->dctx);
9185                 version = dns_dumpctx_version(zone->dctx);
9186
9187                 tresult = dns_db_getsoaserial(db, version, &serial);
9188                 /*
9189                  * If there is a secure version of this zone
9190                  * use its serial if it is less than ours.
9191                  */
9192                 if (tresult == ISC_R_SUCCESS && inline_raw(zone) &&
9193                     zone->secure->db != NULL)
9194                 {
9195                         isc_uint32_t sserial;
9196                         isc_result_t mresult;
9197
9198                         mresult = dns_db_getsoaserial(zone->secure->db,
9199                                                       NULL, &sserial);
9200                         if (mresult == ISC_R_SUCCESS &&
9201                             isc_serial_lt(sserial, serial))
9202                                 serial = sserial;
9203                 }
9204                 /*
9205                  * Note: we are task locked here so we can test
9206                  * zone->xfr safely.
9207                  */
9208                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
9209                         tresult = dns_journal_compact(zone->mctx,
9210                                                       zone->journal,
9211                                                       serial,
9212                                                       zone->journalsize);
9213                         switch (tresult) {
9214                         case ISC_R_SUCCESS:
9215                         case ISC_R_NOSPACE:
9216                         case ISC_R_NOTFOUND:
9217                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9218                                              "dns_journal_compact: %s",
9219                                              dns_result_totext(tresult));
9220                                 break;
9221                         default:
9222                                 dns_zone_log(zone, ISC_LOG_ERROR,
9223                                              "dns_journal_compact failed: %s",
9224                                              dns_result_totext(tresult));
9225                                 break;
9226                         }
9227                 } else if (tresult == ISC_R_SUCCESS) {
9228                         compact = ISC_TRUE;
9229                         zone->compact_serial = serial;
9230                 }
9231         }
9232
9233         LOCK_ZONE(zone);
9234         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9235         if (compact)
9236                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
9237         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
9238                 /*
9239                  * Try again in a short while.
9240                  */
9241                 zone_needdump(zone, DNS_DUMP_DELAY);
9242         } else if (result == ISC_R_SUCCESS &&
9243                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9244                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9245                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9246                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9247                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9248                 isc_time_settoepoch(&zone->dumptime);
9249                 again = ISC_TRUE;
9250         } else if (result == ISC_R_SUCCESS)
9251                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9252
9253         if (zone->dctx != NULL)
9254                 dns_dumpctx_detach(&zone->dctx);
9255         zonemgr_putio(&zone->writeio);
9256         UNLOCK_ZONE(zone);
9257         if (again)
9258                 (void)zone_dump(zone, ISC_FALSE);
9259         dns_zone_idetach(&zone);
9260 }
9261
9262 static isc_result_t
9263 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
9264         const char me[] = "zone_dump";
9265         isc_result_t result;
9266         dns_dbversion_t *version = NULL;
9267         isc_boolean_t again;
9268         dns_db_t *db = NULL;
9269         char *masterfile = NULL;
9270         dns_masterformat_t masterformat = dns_masterformat_none;
9271
9272 /*
9273  * 'compact' MUST only be set if we are task locked.
9274  */
9275
9276         REQUIRE(DNS_ZONE_VALID(zone));
9277         ENTER;
9278
9279  redo:
9280         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9281         if (zone->db != NULL)
9282                 dns_db_attach(zone->db, &db);
9283         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9284         LOCK_ZONE(zone);
9285         if (zone->masterfile != NULL) {
9286                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
9287                 masterformat = zone->masterformat;
9288         }
9289         UNLOCK_ZONE(zone);
9290         if (db == NULL) {
9291                 result = DNS_R_NOTLOADED;
9292                 goto fail;
9293         }
9294         if (masterfile == NULL) {
9295                 result = DNS_R_NOMASTERFILE;
9296                 goto fail;
9297         }
9298
9299         if (compact && zone->type != dns_zone_stub) {
9300                 dns_zone_t *dummy = NULL;
9301                 LOCK_ZONE(zone);
9302                 zone_iattach(zone, &dummy);
9303                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
9304                                        zone_gotwritehandle, zone,
9305                                        &zone->writeio);
9306                 if (result != ISC_R_SUCCESS)
9307                         zone_idetach(&dummy);
9308                 else
9309                         result = DNS_R_CONTINUE;
9310                 UNLOCK_ZONE(zone);
9311         } else {
9312                 const dns_master_style_t *output_style;
9313
9314                 dns_masterrawheader_t rawdata;
9315                 dns_db_currentversion(db, &version);
9316                 dns_master_initrawheader(&rawdata);
9317                 if (inline_secure(zone))
9318                         get_raw_serial(zone->raw, &rawdata);
9319                 if (zone->type == dns_zone_key)
9320                         output_style = &dns_master_style_keyzone;
9321                 else
9322                         output_style = &dns_master_style_default;
9323                 result = dns_master_dump3(zone->mctx, db, version,
9324                                           output_style, masterfile,
9325                                           masterformat, &rawdata);
9326                 dns_db_closeversion(db, &version, ISC_FALSE);
9327         }
9328  fail:
9329         if (db != NULL)
9330                 dns_db_detach(&db);
9331         if (masterfile != NULL)
9332                 isc_mem_free(zone->mctx, masterfile);
9333         masterfile = NULL;
9334
9335         if (result == DNS_R_CONTINUE)
9336                 return (ISC_R_SUCCESS); /* XXXMPA */
9337
9338         again = ISC_FALSE;
9339         LOCK_ZONE(zone);
9340         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9341         if (result != ISC_R_SUCCESS) {
9342                 /*
9343                  * Try again in a short while.
9344                  */
9345                 zone_needdump(zone, DNS_DUMP_DELAY);
9346         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9347                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9348                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9349                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9350                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9351                 isc_time_settoepoch(&zone->dumptime);
9352                 again = ISC_TRUE;
9353         } else
9354                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9355         UNLOCK_ZONE(zone);
9356         if (again)
9357                 goto redo;
9358
9359         return (result);
9360 }
9361
9362 static isc_result_t
9363 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
9364              dns_masterformat_t format, const isc_uint32_t rawversion)
9365 {
9366         isc_result_t result;
9367         dns_dbversion_t *version = NULL;
9368         dns_db_t *db = NULL;
9369         dns_masterrawheader_t rawdata;
9370
9371         REQUIRE(DNS_ZONE_VALID(zone));
9372
9373         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9374         if (zone->db != NULL)
9375                 dns_db_attach(zone->db, &db);
9376         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9377         if (db == NULL)
9378                 return (DNS_R_NOTLOADED);
9379
9380         dns_db_currentversion(db, &version);
9381         dns_master_initrawheader(&rawdata);
9382         if (rawversion == 0)
9383                 rawdata.flags |= DNS_MASTERRAW_COMPAT;
9384         else if (inline_secure(zone))
9385                 get_raw_serial(zone->raw, &rawdata);
9386         else if (zone->sourceserialset) {
9387                 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
9388                 rawdata.sourceserial = zone->sourceserial;
9389         }
9390         result = dns_master_dumptostream3(zone->mctx, db, version, style,
9391                                           format, &rawdata, fd);
9392         dns_db_closeversion(db, &version, ISC_FALSE);
9393         dns_db_detach(&db);
9394         return (result);
9395 }
9396
9397 isc_result_t
9398 dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9399                        const dns_master_style_t *style,
9400                        const isc_uint32_t rawversion)
9401 {
9402         return (dumptostream(zone, fd, style, format, rawversion));
9403 }
9404
9405 isc_result_t
9406 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9407                        const dns_master_style_t *style) {
9408         return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
9409 }
9410
9411 isc_result_t
9412 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
9413         return (dumptostream(zone, fd, &dns_master_style_default,
9414                              dns_masterformat_text, 0));
9415 }
9416
9417 isc_result_t
9418 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
9419         return (dumptostream(zone, fd, &dns_master_style_full,
9420                              dns_masterformat_text, 0));
9421 }
9422
9423 void
9424 dns_zone_unload(dns_zone_t *zone) {
9425         REQUIRE(DNS_ZONE_VALID(zone));
9426
9427         LOCK_ZONE(zone);
9428         zone_unload(zone);
9429         UNLOCK_ZONE(zone);
9430 }
9431
9432 static void
9433 notify_cancel(dns_zone_t *zone) {
9434         dns_notify_t *notify;
9435
9436         /*
9437          * 'zone' locked by caller.
9438          */
9439
9440         REQUIRE(LOCKED_ZONE(zone));
9441
9442         for (notify = ISC_LIST_HEAD(zone->notifies);
9443              notify != NULL;
9444              notify = ISC_LIST_NEXT(notify, link)) {
9445                 if (notify->find != NULL)
9446                         dns_adb_cancelfind(notify->find);
9447                 if (notify->request != NULL)
9448                         dns_request_cancel(notify->request);
9449         }
9450 }
9451
9452 static void
9453 forward_cancel(dns_zone_t *zone) {
9454         dns_forward_t *forward;
9455
9456         /*
9457          * 'zone' locked by caller.
9458          */
9459
9460         REQUIRE(LOCKED_ZONE(zone));
9461
9462         for (forward = ISC_LIST_HEAD(zone->forwards);
9463              forward != NULL;
9464              forward = ISC_LIST_NEXT(forward, link)) {
9465                 if (forward->request != NULL)
9466                         dns_request_cancel(forward->request);
9467         }
9468 }
9469
9470 static void
9471 zone_unload(dns_zone_t *zone) {
9472         /*
9473          * 'zone' locked by caller.
9474          */
9475
9476         REQUIRE(LOCKED_ZONE(zone));
9477
9478         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
9479             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9480                 if (zone->writeio != NULL)
9481                         zonemgr_cancelio(zone->writeio);
9482
9483                 if (zone->dctx != NULL)
9484                         dns_dumpctx_cancel(zone->dctx);
9485         }
9486         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9487         zone_detachdb(zone);
9488         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9489         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
9490         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9491 }
9492
9493 void
9494 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9495         REQUIRE(DNS_ZONE_VALID(zone));
9496         REQUIRE(val > 0);
9497
9498         zone->minrefresh = val;
9499 }
9500
9501 void
9502 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9503         REQUIRE(DNS_ZONE_VALID(zone));
9504         REQUIRE(val > 0);
9505
9506         zone->maxrefresh = val;
9507 }
9508
9509 void
9510 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
9511         REQUIRE(DNS_ZONE_VALID(zone));
9512         REQUIRE(val > 0);
9513
9514         zone->minretry = val;
9515 }
9516
9517 void
9518 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
9519         REQUIRE(DNS_ZONE_VALID(zone));
9520         REQUIRE(val > 0);
9521
9522         zone->maxretry = val;
9523 }
9524
9525 static isc_boolean_t
9526 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
9527         dns_notify_t *notify;
9528
9529         for (notify = ISC_LIST_HEAD(zone->notifies);
9530              notify != NULL;
9531              notify = ISC_LIST_NEXT(notify, link)) {
9532                 if (notify->request != NULL)
9533                         continue;
9534                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
9535                     dns_name_equal(name, &notify->ns))
9536                         return (ISC_TRUE);
9537                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
9538                         return (ISC_TRUE);
9539         }
9540         return (ISC_FALSE);
9541 }
9542
9543 static isc_boolean_t
9544 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
9545         dns_tsigkey_t *key = NULL;
9546         isc_sockaddr_t src;
9547         isc_sockaddr_t any;
9548         isc_boolean_t isself;
9549         isc_netaddr_t dstaddr;
9550         isc_result_t result;
9551
9552         if (zone->view == NULL || zone->isself == NULL)
9553                 return (ISC_FALSE);
9554
9555         switch (isc_sockaddr_pf(dst)) {
9556         case PF_INET:
9557                 src = zone->notifysrc4;
9558                 isc_sockaddr_any(&any);
9559                 break;
9560         case PF_INET6:
9561                 src = zone->notifysrc6;
9562                 isc_sockaddr_any6(&any);
9563                 break;
9564         default:
9565                 return (ISC_FALSE);
9566         }
9567
9568         /*
9569          * When sending from any the kernel will assign a source address
9570          * that matches the destination address.
9571          */
9572         if (isc_sockaddr_eqaddr(&any, &src))
9573                 src = *dst;
9574
9575         isc_netaddr_fromsockaddr(&dstaddr, dst);
9576         result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
9577         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
9578                 return (ISC_FALSE);
9579         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
9580                                 zone->isselfarg);
9581         if (key != NULL)
9582                 dns_tsigkey_detach(&key);
9583         return (isself);
9584 }
9585
9586 static void
9587 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
9588         isc_mem_t *mctx;
9589
9590         /*
9591          * Caller holds zone lock.
9592          */
9593         REQUIRE(DNS_NOTIFY_VALID(notify));
9594
9595         if (notify->zone != NULL) {
9596                 if (!locked)
9597                         LOCK_ZONE(notify->zone);
9598                 REQUIRE(LOCKED_ZONE(notify->zone));
9599                 if (ISC_LINK_LINKED(notify, link))
9600                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
9601                 if (!locked)
9602                         UNLOCK_ZONE(notify->zone);
9603                 if (locked)
9604                         zone_idetach(&notify->zone);
9605                 else
9606                         dns_zone_idetach(&notify->zone);
9607         }
9608         if (notify->find != NULL)
9609                 dns_adb_destroyfind(&notify->find);
9610         if (notify->request != NULL)
9611                 dns_request_destroy(&notify->request);
9612         if (dns_name_dynamic(&notify->ns))
9613                 dns_name_free(&notify->ns, notify->mctx);
9614         if (notify->key != NULL)
9615                 dns_tsigkey_detach(&notify->key);
9616         mctx = notify->mctx;
9617         isc_mem_put(notify->mctx, notify, sizeof(*notify));
9618         isc_mem_detach(&mctx);
9619 }
9620
9621 static isc_result_t
9622 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
9623         dns_notify_t *notify;
9624
9625         REQUIRE(notifyp != NULL && *notifyp == NULL);
9626
9627         notify = isc_mem_get(mctx, sizeof(*notify));
9628         if (notify == NULL)
9629                 return (ISC_R_NOMEMORY);
9630
9631         notify->mctx = NULL;
9632         isc_mem_attach(mctx, &notify->mctx);
9633         notify->flags = flags;
9634         notify->zone = NULL;
9635         notify->find = NULL;
9636         notify->request = NULL;
9637         notify->key = NULL;
9638         isc_sockaddr_any(&notify->dst);
9639         dns_name_init(&notify->ns, NULL);
9640         ISC_LINK_INIT(notify, link);
9641         notify->magic = NOTIFY_MAGIC;
9642         *notifyp = notify;
9643         return (ISC_R_SUCCESS);
9644 }
9645
9646 /*
9647  * XXXAG should check for DNS_ZONEFLG_EXITING
9648  */
9649 static void
9650 process_adb_event(isc_task_t *task, isc_event_t *ev) {
9651         dns_notify_t *notify;
9652         isc_eventtype_t result;
9653
9654         UNUSED(task);
9655
9656         notify = ev->ev_arg;
9657         REQUIRE(DNS_NOTIFY_VALID(notify));
9658         INSIST(task == notify->zone->task);
9659         result = ev->ev_type;
9660         isc_event_free(&ev);
9661         if (result == DNS_EVENT_ADBMOREADDRESSES) {
9662                 dns_adb_destroyfind(&notify->find);
9663                 notify_find_address(notify);
9664                 return;
9665         }
9666         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
9667                 LOCK_ZONE(notify->zone);
9668                 notify_send(notify);
9669                 UNLOCK_ZONE(notify->zone);
9670         }
9671         notify_destroy(notify, ISC_FALSE);
9672 }
9673
9674 static void
9675 notify_find_address(dns_notify_t *notify) {
9676         isc_result_t result;
9677         unsigned int options;
9678
9679         REQUIRE(DNS_NOTIFY_VALID(notify));
9680         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
9681                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
9682
9683         if (notify->zone->view->adb == NULL)
9684                 goto destroy;
9685
9686         result = dns_adb_createfind(notify->zone->view->adb,
9687                                     notify->zone->task,
9688                                     process_adb_event, notify,
9689                                     &notify->ns, dns_rootname, 0,
9690                                     options, 0, NULL,
9691                                     notify->zone->view->dstport,
9692                                     &notify->find);
9693
9694         /* Something failed? */
9695         if (result != ISC_R_SUCCESS)
9696                 goto destroy;
9697
9698         /* More addresses pending? */
9699         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
9700                 return;
9701
9702         /* We have as many addresses as we can get. */
9703         LOCK_ZONE(notify->zone);
9704         notify_send(notify);
9705         UNLOCK_ZONE(notify->zone);
9706
9707  destroy:
9708         notify_destroy(notify, ISC_FALSE);
9709 }
9710
9711
9712 static isc_result_t
9713 notify_send_queue(dns_notify_t *notify) {
9714         isc_event_t *e;
9715         isc_result_t result;
9716
9717         e = isc_event_allocate(notify->mctx, NULL,
9718                                DNS_EVENT_NOTIFYSENDTOADDR,
9719                                notify_send_toaddr,
9720                                notify, sizeof(isc_event_t));
9721         if (e == NULL)
9722                 return (ISC_R_NOMEMORY);
9723         e->ev_arg = notify;
9724         e->ev_sender = NULL;
9725         result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
9726                                          notify->zone->task, &e);
9727         if (result != ISC_R_SUCCESS)
9728                 isc_event_free(&e);
9729         return (result);
9730 }
9731
9732 static void
9733 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
9734         dns_notify_t *notify;
9735         isc_result_t result;
9736         dns_message_t *message = NULL;
9737         isc_netaddr_t dstip;
9738         dns_tsigkey_t *key = NULL;
9739         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9740         isc_sockaddr_t src;
9741         int timeout;
9742         isc_boolean_t have_notifysource = ISC_FALSE;
9743
9744         notify = event->ev_arg;
9745         REQUIRE(DNS_NOTIFY_VALID(notify));
9746
9747         UNUSED(task);
9748
9749         LOCK_ZONE(notify->zone);
9750
9751         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
9752                 result = ISC_R_CANCELED;
9753                 goto cleanup;
9754         }
9755
9756         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
9757             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
9758             notify->zone->view->requestmgr == NULL ||
9759             notify->zone->db == NULL) {
9760                 result = ISC_R_CANCELED;
9761                 goto cleanup;
9762         }
9763
9764         /*
9765          * The raw IPv4 address should also exist.  Don't send to the
9766          * mapped form.
9767          */
9768         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
9769             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
9770                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9771                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
9772                            "notify: ignoring IPv6 mapped IPV4 address: %s",
9773                            addrbuf);
9774                 result = ISC_R_CANCELED;
9775                 goto cleanup;
9776         }
9777
9778         result = notify_createmessage(notify->zone, notify->flags, &message);
9779         if (result != ISC_R_SUCCESS)
9780                 goto cleanup;
9781
9782         if (notify->key != NULL) {
9783                 /* Transfer ownership of key */
9784                 key = notify->key;
9785                 notify->key = NULL;
9786         } else {
9787                 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
9788                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9789                 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
9790                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9791                         notify_log(notify->zone, ISC_LOG_ERROR,
9792                                    "NOTIFY to %s not sent. "
9793                                    "Peer TSIG key lookup failure.", addrbuf);
9794                         goto cleanup_message;
9795                 }
9796         }
9797
9798         /* XXX: should we log the tsig key too? */
9799         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
9800                    addrbuf);
9801         if (notify->zone->view->peers != NULL) {
9802                 dns_peer_t *peer = NULL;
9803                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
9804                                                  &dstip, &peer);
9805                 if (result == ISC_R_SUCCESS) {
9806                         result = dns_peer_getnotifysource(peer, &src);
9807                         if (result == ISC_R_SUCCESS)
9808                                 have_notifysource = ISC_TRUE;
9809                 }
9810         }
9811         switch (isc_sockaddr_pf(&notify->dst)) {
9812         case PF_INET:
9813                 if (!have_notifysource)
9814                         src = notify->zone->notifysrc4;
9815                 break;
9816         case PF_INET6:
9817                 if (!have_notifysource)
9818                         src = notify->zone->notifysrc6;
9819                 break;
9820         default:
9821                 result = ISC_R_NOTIMPLEMENTED;
9822                 goto cleanup_key;
9823         }
9824         timeout = 15;
9825         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
9826                 timeout = 30;
9827         result = dns_request_createvia2(notify->zone->view->requestmgr,
9828                                         message, &src, &notify->dst, 0, key,
9829                                         timeout * 3, timeout,
9830                                         notify->zone->task, notify_done,
9831                                         notify, &notify->request);
9832         if (result == ISC_R_SUCCESS) {
9833                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
9834                         inc_stats(notify->zone,
9835                                   dns_zonestatscounter_notifyoutv4);
9836                 } else {
9837                         inc_stats(notify->zone,
9838                                   dns_zonestatscounter_notifyoutv6);
9839                 }
9840         }
9841
9842  cleanup_key:
9843         if (key != NULL)
9844                 dns_tsigkey_detach(&key);
9845  cleanup_message:
9846         dns_message_destroy(&message);
9847  cleanup:
9848         UNLOCK_ZONE(notify->zone);
9849         isc_event_free(&event);
9850         if (result != ISC_R_SUCCESS)
9851                 notify_destroy(notify, ISC_FALSE);
9852 }
9853
9854 static void
9855 notify_send(dns_notify_t *notify) {
9856         dns_adbaddrinfo_t *ai;
9857         isc_sockaddr_t dst;
9858         isc_result_t result;
9859         dns_notify_t *new = NULL;
9860
9861         /*
9862          * Zone lock held by caller.
9863          */
9864         REQUIRE(DNS_NOTIFY_VALID(notify));
9865         REQUIRE(LOCKED_ZONE(notify->zone));
9866
9867         for (ai = ISC_LIST_HEAD(notify->find->list);
9868              ai != NULL;
9869              ai = ISC_LIST_NEXT(ai, publink)) {
9870                 dst = ai->sockaddr;
9871                 if (notify_isqueued(notify->zone, NULL, &dst))
9872                         continue;
9873                 if (notify_isself(notify->zone, &dst))
9874                         continue;
9875                 new = NULL;
9876                 result = notify_create(notify->mctx,
9877                                        (notify->flags & DNS_NOTIFY_NOSOA),
9878                                        &new);
9879                 if (result != ISC_R_SUCCESS)
9880                         goto cleanup;
9881                 zone_iattach(notify->zone, &new->zone);
9882                 ISC_LIST_APPEND(new->zone->notifies, new, link);
9883                 new->dst = dst;
9884                 result = notify_send_queue(new);
9885                 if (result != ISC_R_SUCCESS)
9886                         goto cleanup;
9887                 new = NULL;
9888         }
9889
9890  cleanup:
9891         if (new != NULL)
9892                 notify_destroy(new, ISC_TRUE);
9893 }
9894
9895 void
9896 dns_zone_notify(dns_zone_t *zone) {
9897         isc_time_t now;
9898
9899         REQUIRE(DNS_ZONE_VALID(zone));
9900
9901         LOCK_ZONE(zone);
9902         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9903
9904         TIME_NOW(&now);
9905         zone_settimer(zone, &now);
9906         UNLOCK_ZONE(zone);
9907 }
9908
9909 static void
9910 zone_notify(dns_zone_t *zone, isc_time_t *now) {
9911         dns_dbnode_t *node = NULL;
9912         dns_db_t *zonedb = NULL;
9913         dns_dbversion_t *version = NULL;
9914         dns_name_t *origin = NULL;
9915         dns_name_t master;
9916         dns_rdata_ns_t ns;
9917         dns_rdata_soa_t soa;
9918         isc_uint32_t serial;
9919         dns_rdata_t rdata = DNS_RDATA_INIT;
9920         dns_rdataset_t nsrdset;
9921         dns_rdataset_t soardset;
9922         isc_result_t result;
9923         dns_notify_t *notify = NULL;
9924         unsigned int i;
9925         isc_sockaddr_t dst;
9926         isc_boolean_t isqueued;
9927         dns_notifytype_t notifytype;
9928         unsigned int flags = 0;
9929         isc_boolean_t loggednotify = ISC_FALSE;
9930
9931         REQUIRE(DNS_ZONE_VALID(zone));
9932
9933         LOCK_ZONE(zone);
9934         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9935         notifytype = zone->notifytype;
9936         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
9937         UNLOCK_ZONE(zone);
9938
9939         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
9940                 return;
9941
9942         if (notifytype == dns_notifytype_no)
9943                 return;
9944
9945         if (notifytype == dns_notifytype_masteronly &&
9946             zone->type != dns_zone_master)
9947                 return;
9948
9949         origin = &zone->origin;
9950
9951         /*
9952          * If the zone is dialup we are done as we don't want to send
9953          * the current soa so as to force a refresh query.
9954          */
9955         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
9956                 flags |= DNS_NOTIFY_NOSOA;
9957
9958         /*
9959          * Get SOA RRset.
9960          */
9961         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9962         if (zone->db != NULL)
9963                 dns_db_attach(zone->db, &zonedb);
9964         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9965         if (zonedb == NULL)
9966                 return;
9967         dns_db_currentversion(zonedb, &version);
9968         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
9969         if (result != ISC_R_SUCCESS)
9970                 goto cleanup1;
9971
9972         dns_rdataset_init(&soardset);
9973         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
9974                                      dns_rdatatype_none, 0, &soardset, NULL);
9975         if (result != ISC_R_SUCCESS)
9976                 goto cleanup2;
9977
9978         /*
9979          * Find serial and master server's name.
9980          */
9981         dns_name_init(&master, NULL);
9982         result = dns_rdataset_first(&soardset);
9983         if (result != ISC_R_SUCCESS)
9984                 goto cleanup3;
9985         dns_rdataset_current(&soardset, &rdata);
9986         result = dns_rdata_tostruct(&rdata, &soa, NULL);
9987         RUNTIME_CHECK(result == ISC_R_SUCCESS);
9988         dns_rdata_reset(&rdata);
9989         result = dns_name_dup(&soa.origin, zone->mctx, &master);
9990         serial = soa.serial;
9991         dns_rdataset_disassociate(&soardset);
9992         if (result != ISC_R_SUCCESS)
9993                 goto cleanup3;
9994
9995         /*
9996          * Enqueue notify requests for 'also-notify' servers.
9997          */
9998         LOCK_ZONE(zone);
9999         for (i = 0; i < zone->notifycnt; i++) {
10000                 dns_tsigkey_t *key = NULL;
10001
10002                 dst = zone->notify[i];
10003                 if (notify_isqueued(zone, NULL, &dst))
10004                         continue;
10005
10006                 result = notify_create(zone->mctx, flags, &notify);
10007                 if (result != ISC_R_SUCCESS)
10008                         continue;
10009
10010                 zone_iattach(zone, &notify->zone);
10011                 notify->dst = dst;
10012
10013                 if ((zone->notifykeynames != NULL) &&
10014                     (zone->notifykeynames[i] != NULL)) {
10015                         dns_view_t *view = dns_zone_getview(zone);
10016                         dns_name_t *keyname = zone->notifykeynames[i];
10017                         result = dns_view_gettsig(view, keyname, &key);
10018                         if (result == ISC_R_SUCCESS) {
10019                                 notify->key = key;
10020                                 key = NULL;
10021                         }
10022                 }
10023
10024                 ISC_LIST_APPEND(zone->notifies, notify, link);
10025                 result = notify_send_queue(notify);
10026                 if (result != ISC_R_SUCCESS)
10027                         notify_destroy(notify, ISC_TRUE);
10028                 if (!loggednotify) {
10029                         notify_log(zone, ISC_LOG_INFO,
10030                                    "sending notifies (serial %u)",
10031                                    serial);
10032                         loggednotify = ISC_TRUE;
10033                 }
10034                 notify = NULL;
10035         }
10036         UNLOCK_ZONE(zone);
10037
10038         if (notifytype == dns_notifytype_explicit)
10039                 goto cleanup3;
10040
10041         /*
10042          * Process NS RRset to generate notifies.
10043          */
10044
10045         dns_rdataset_init(&nsrdset);
10046         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
10047                                      dns_rdatatype_none, 0, &nsrdset, NULL);
10048         if (result != ISC_R_SUCCESS)
10049                 goto cleanup3;
10050
10051         result = dns_rdataset_first(&nsrdset);
10052         while (result == ISC_R_SUCCESS) {
10053                 dns_rdataset_current(&nsrdset, &rdata);
10054                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
10055                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10056                 dns_rdata_reset(&rdata);
10057                 /*
10058                  * Don't notify the master server unless explicitly
10059                  * configured to do so.
10060                  */
10061                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
10062                     dns_name_compare(&master, &ns.name) == 0) {
10063                         result = dns_rdataset_next(&nsrdset);
10064                         continue;
10065                 }
10066
10067                 if (!loggednotify) {
10068                         notify_log(zone, ISC_LOG_INFO,
10069                                    "sending notifies (serial %u)",
10070                                    serial);
10071                         loggednotify = ISC_TRUE;
10072                 }
10073
10074                 LOCK_ZONE(zone);
10075                 isqueued = notify_isqueued(zone, &ns.name, NULL);
10076                 UNLOCK_ZONE(zone);
10077                 if (isqueued) {
10078                         result = dns_rdataset_next(&nsrdset);
10079                         continue;
10080                 }
10081                 result = notify_create(zone->mctx, flags, &notify);
10082                 if (result != ISC_R_SUCCESS)
10083                         continue;
10084                 dns_zone_iattach(zone, &notify->zone);
10085                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
10086                 if (result != ISC_R_SUCCESS) {
10087                         LOCK_ZONE(zone);
10088                         notify_destroy(notify, ISC_TRUE);
10089                         UNLOCK_ZONE(zone);
10090                         continue;
10091                 }
10092                 LOCK_ZONE(zone);
10093                 ISC_LIST_APPEND(zone->notifies, notify, link);
10094                 UNLOCK_ZONE(zone);
10095                 notify_find_address(notify);
10096                 notify = NULL;
10097                 result = dns_rdataset_next(&nsrdset);
10098         }
10099         dns_rdataset_disassociate(&nsrdset);
10100
10101  cleanup3:
10102         if (dns_name_dynamic(&master))
10103                 dns_name_free(&master, zone->mctx);
10104  cleanup2:
10105         dns_db_detachnode(zonedb, &node);
10106  cleanup1:
10107         dns_db_closeversion(zonedb, &version, ISC_FALSE);
10108         dns_db_detach(&zonedb);
10109 }
10110
10111 /***
10112  *** Private
10113  ***/
10114
10115 static inline isc_result_t
10116 save_nsrrset(dns_message_t *message, dns_name_t *name,
10117              dns_db_t *db, dns_dbversion_t *version)
10118 {
10119         dns_rdataset_t *nsrdataset = NULL;
10120         dns_rdataset_t *rdataset = NULL;
10121         dns_dbnode_t *node = NULL;
10122         dns_rdata_ns_t ns;
10123         isc_result_t result;
10124         dns_rdata_t rdata = DNS_RDATA_INIT;
10125
10126         /*
10127          * Extract NS RRset from message.
10128          */
10129         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
10130                                       dns_rdatatype_ns, dns_rdatatype_none,
10131                                       NULL, &nsrdataset);
10132         if (result != ISC_R_SUCCESS)
10133                 goto fail;
10134
10135         /*
10136          * Add NS rdataset.
10137          */
10138         result = dns_db_findnode(db, name, ISC_TRUE, &node);
10139         if (result != ISC_R_SUCCESS)
10140                 goto fail;
10141         result = dns_db_addrdataset(db, node, version, 0,
10142                                     nsrdataset, 0, NULL);
10143         dns_db_detachnode(db, &node);
10144         if (result != ISC_R_SUCCESS)
10145                 goto fail;
10146         /*
10147          * Add glue rdatasets.
10148          */
10149         for (result = dns_rdataset_first(nsrdataset);
10150              result == ISC_R_SUCCESS;
10151              result = dns_rdataset_next(nsrdataset)) {
10152                 dns_rdataset_current(nsrdataset, &rdata);
10153                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
10154                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10155                 dns_rdata_reset(&rdata);
10156                 if (!dns_name_issubdomain(&ns.name, name))
10157                         continue;
10158                 rdataset = NULL;
10159                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10160                                               &ns.name, dns_rdatatype_aaaa,
10161                                               dns_rdatatype_none, NULL,
10162                                               &rdataset);
10163                 if (result == ISC_R_SUCCESS) {
10164                         result = dns_db_findnode(db, &ns.name,
10165                                                  ISC_TRUE, &node);
10166                         if (result != ISC_R_SUCCESS)
10167                                 goto fail;
10168                         result = dns_db_addrdataset(db, node, version, 0,
10169                                                     rdataset, 0, NULL);
10170                         dns_db_detachnode(db, &node);
10171                         if (result != ISC_R_SUCCESS)
10172                                 goto fail;
10173                 }
10174                 rdataset = NULL;
10175                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10176                                               &ns.name, dns_rdatatype_a,
10177                                               dns_rdatatype_none, NULL,
10178                                               &rdataset);
10179                 if (result == ISC_R_SUCCESS) {
10180                         result = dns_db_findnode(db, &ns.name,
10181                                                  ISC_TRUE, &node);
10182                         if (result != ISC_R_SUCCESS)
10183                                 goto fail;
10184                         result = dns_db_addrdataset(db, node, version, 0,
10185                                                     rdataset, 0, NULL);
10186                         dns_db_detachnode(db, &node);
10187                         if (result != ISC_R_SUCCESS)
10188                                 goto fail;
10189                 }
10190         }
10191         if (result != ISC_R_NOMORE)
10192                 goto fail;
10193
10194         return (ISC_R_SUCCESS);
10195
10196 fail:
10197         return (result);
10198 }
10199
10200 static void
10201 stub_callback(isc_task_t *task, isc_event_t *event) {
10202         const char me[] = "stub_callback";
10203         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10204         dns_stub_t *stub = NULL;
10205         dns_message_t *msg = NULL;
10206         dns_zone_t *zone = NULL;
10207         char master[ISC_SOCKADDR_FORMATSIZE];
10208         char source[ISC_SOCKADDR_FORMATSIZE];
10209         isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
10210         isc_result_t result;
10211         isc_time_t now;
10212         isc_boolean_t exiting = ISC_FALSE;
10213         isc_interval_t i;
10214         unsigned int j, soacount;
10215
10216         stub = revent->ev_arg;
10217         INSIST(DNS_STUB_VALID(stub));
10218
10219         UNUSED(task);
10220
10221         zone = stub->zone;
10222
10223         ENTER;
10224
10225         TIME_NOW(&now);
10226
10227         LOCK_ZONE(zone);
10228
10229         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10230                 zone_debuglog(zone, me, 1, "exiting");
10231                 exiting = ISC_TRUE;
10232                 goto next_master;
10233         }
10234
10235         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10236         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10237
10238         if (revent->result != ISC_R_SUCCESS) {
10239                 if (revent->result == ISC_R_TIMEDOUT &&
10240                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10241                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10242                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10243                                      "refreshing stub: timeout retrying "
10244                                      " without EDNS master %s (source %s)",
10245                                      master, source);
10246                         goto same_master;
10247                 }
10248                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
10249                                            &zone->sourceaddr, &now);
10250                 dns_zone_log(zone, ISC_LOG_INFO,
10251                              "could not refresh stub from master %s"
10252                              " (source %s): %s", master, source,
10253                              dns_result_totext(revent->result));
10254                 goto next_master;
10255         }
10256
10257         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10258         if (result != ISC_R_SUCCESS)
10259                 goto next_master;
10260
10261         result = dns_request_getresponse(revent->request, msg, 0);
10262         if (result != ISC_R_SUCCESS)
10263                 goto next_master;
10264
10265         /*
10266          * Unexpected rcode.
10267          */
10268         if (msg->rcode != dns_rcode_noerror) {
10269                 char rcode[128];
10270                 isc_buffer_t rb;
10271
10272                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10273                 (void)dns_rcode_totext(msg->rcode, &rb);
10274
10275                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10276                     (msg->rcode == dns_rcode_servfail ||
10277                      msg->rcode == dns_rcode_notimp ||
10278                      msg->rcode == dns_rcode_formerr)) {
10279                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10280                                      "refreshing stub: rcode (%.*s) retrying "
10281                                      "without EDNS master %s (source %s)",
10282                                      (int)rb.used, rcode, master, source);
10283                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10284                         goto same_master;
10285                 }
10286
10287                 dns_zone_log(zone, ISC_LOG_INFO,
10288                              "refreshing stub: "
10289                              "unexpected rcode (%.*s) from %s (source %s)",
10290                              (int)rb.used, rcode, master, source);
10291                 goto next_master;
10292         }
10293
10294         /*
10295          * We need complete messages.
10296          */
10297         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10298                 if (dns_request_usedtcp(revent->request)) {
10299                         dns_zone_log(zone, ISC_LOG_INFO,
10300                                      "refreshing stub: truncated TCP "
10301                                      "response from master %s (source %s)",
10302                                      master, source);
10303                         goto next_master;
10304                 }
10305                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10306                 goto same_master;
10307         }
10308
10309         /*
10310          * If non-auth log and next master.
10311          */
10312         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10313                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10314                              "non-authoritative answer from "
10315                              "master %s (source %s)", master, source);
10316                 goto next_master;
10317         }
10318
10319         /*
10320          * Sanity checks.
10321          */
10322         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10323         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
10324
10325         if (cnamecnt != 0) {
10326                 dns_zone_log(zone, ISC_LOG_INFO,
10327                              "refreshing stub: unexpected CNAME response "
10328                              "from master %s (source %s)", master, source);
10329                 goto next_master;
10330         }
10331
10332         if (nscnt == 0) {
10333                 dns_zone_log(zone, ISC_LOG_INFO,
10334                              "refreshing stub: no NS records in response "
10335                              "from master %s (source %s)", master, source);
10336                 goto next_master;
10337         }
10338
10339         /*
10340          * Save answer.
10341          */
10342         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
10343         if (result != ISC_R_SUCCESS) {
10344                 dns_zone_log(zone, ISC_LOG_INFO,
10345                              "refreshing stub: unable to save NS records "
10346                              "from master %s (source %s)", master, source);
10347                 goto next_master;
10348         }
10349
10350         /*
10351          * Tidy up.
10352          */
10353         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
10354         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
10355         if (zone->db == NULL)
10356                 zone_attachdb(zone, stub->db);
10357         result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
10358                                   &refresh, &retry, &expire, NULL, NULL);
10359         if (result == ISC_R_SUCCESS && soacount > 0U) {
10360                 zone->refresh = RANGE(refresh, zone->minrefresh,
10361                                       zone->maxrefresh);
10362                 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
10363                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
10364                                      DNS_MAX_EXPIRE);
10365                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10366         }
10367         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
10368         dns_db_detach(&stub->db);
10369
10370         dns_message_destroy(&msg);
10371         isc_event_free(&event);
10372         dns_request_destroy(&zone->request);
10373
10374         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10375         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10376         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10377         isc_interval_set(&i, zone->expire, 0);
10378         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10379
10380         if (zone->masterfile != NULL)
10381                 zone_needdump(zone, 0);
10382
10383         zone_settimer(zone, &now);
10384         goto free_stub;
10385
10386  next_master:
10387         if (stub->version != NULL)
10388                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
10389         if (stub->db != NULL)
10390                 dns_db_detach(&stub->db);
10391         if (msg != NULL)
10392                 dns_message_destroy(&msg);
10393         isc_event_free(&event);
10394         dns_request_destroy(&zone->request);
10395         /*
10396          * Skip to next failed / untried master.
10397          */
10398         do {
10399                 zone->curmaster++;
10400         } while (zone->curmaster < zone->masterscnt &&
10401                  zone->mastersok[zone->curmaster]);
10402         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10403         if (exiting || zone->curmaster >= zone->masterscnt) {
10404                 isc_boolean_t done = ISC_TRUE;
10405                 if (!exiting &&
10406                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10407                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10408                         /*
10409                          * Did we get a good answer from all the masters?
10410                          */
10411                         for (j = 0; j < zone->masterscnt; j++)
10412                                 if (zone->mastersok[j] == ISC_FALSE) {
10413                                         done = ISC_FALSE;
10414                                         break;
10415                                 }
10416                 } else
10417                         done = ISC_TRUE;
10418                 if (!done) {
10419                         zone->curmaster = 0;
10420                         /*
10421                          * Find the next failed master.
10422                          */
10423                         while (zone->curmaster < zone->masterscnt &&
10424                                zone->mastersok[zone->curmaster])
10425                                 zone->curmaster++;
10426                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10427                 } else {
10428                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10429
10430                         zone_settimer(zone, &now);
10431                         goto free_stub;
10432                 }
10433         }
10434         queue_soa_query(zone);
10435         goto free_stub;
10436
10437  same_master:
10438         if (msg != NULL)
10439                 dns_message_destroy(&msg);
10440         isc_event_free(&event);
10441         dns_request_destroy(&zone->request);
10442         ns_query(zone, NULL, stub);
10443         UNLOCK_ZONE(zone);
10444         goto done;
10445
10446  free_stub:
10447         UNLOCK_ZONE(zone);
10448         stub->magic = 0;
10449         dns_zone_idetach(&stub->zone);
10450         INSIST(stub->db == NULL);
10451         INSIST(stub->version == NULL);
10452         isc_mem_put(stub->mctx, stub, sizeof(*stub));
10453
10454  done:
10455         INSIST(event == NULL);
10456         return;
10457 }
10458
10459 /*
10460  * An SOA query has finished (successfully or not).
10461  */
10462 static void
10463 refresh_callback(isc_task_t *task, isc_event_t *event) {
10464         const char me[] = "refresh_callback";
10465         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10466         dns_zone_t *zone;
10467         dns_message_t *msg = NULL;
10468         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
10469         isc_time_t now;
10470         char master[ISC_SOCKADDR_FORMATSIZE];
10471         char source[ISC_SOCKADDR_FORMATSIZE];
10472         dns_rdataset_t *rdataset = NULL;
10473         dns_rdata_t rdata = DNS_RDATA_INIT;
10474         dns_rdata_soa_t soa;
10475         isc_result_t result;
10476         isc_uint32_t serial, oldserial = 0;
10477         unsigned int j;
10478         isc_boolean_t do_queue_xfrin = ISC_FALSE;
10479
10480         zone = revent->ev_arg;
10481         INSIST(DNS_ZONE_VALID(zone));
10482
10483         UNUSED(task);
10484
10485         ENTER;
10486
10487         TIME_NOW(&now);
10488
10489         LOCK_ZONE(zone);
10490
10491         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10492                 isc_event_free(&event);
10493                 dns_request_destroy(&zone->request);
10494                 goto detach;
10495         }
10496
10497         /*
10498          * if timeout log and next master;
10499          */
10500
10501         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10502         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10503
10504         if (revent->result != ISC_R_SUCCESS) {
10505                 if (revent->result == ISC_R_TIMEDOUT &&
10506                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10507                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10508                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10509                                      "refresh: timeout retrying without EDNS "
10510                                      "master %s (source %s)", master, source);
10511                         goto same_master;
10512                 }
10513                 if (revent->result == ISC_R_TIMEDOUT &&
10514                     !dns_request_usedtcp(revent->request)) {
10515                         dns_zone_log(zone, ISC_LOG_INFO,
10516                                      "refresh: retry limit for "
10517                                      "master %s exceeded (source %s)",
10518                                      master, source);
10519                         /* Try with slave with TCP. */
10520                         if ((zone->type == dns_zone_slave ||
10521                              zone->type == dns_zone_redirect) &&
10522                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
10523                                 if (!dns_zonemgr_unreachable(zone->zmgr,
10524                                                              &zone->masteraddr,
10525                                                              &zone->sourceaddr,
10526                                                              &now))
10527                                 {
10528                                         DNS_ZONE_SETFLAG(zone,
10529                                                      DNS_ZONEFLG_SOABEFOREAXFR);
10530                                         goto tcp_transfer;
10531                                 }
10532                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10533                                              "refresh: skipped tcp fallback "
10534                                              "as master %s (source %s) is "
10535                                              "unreachable (cached)",
10536                                               master, source);
10537                         }
10538                 } else
10539                         dns_zone_log(zone, ISC_LOG_INFO,
10540                                      "refresh: failure trying master "
10541                                      "%s (source %s): %s", master, source,
10542                                      dns_result_totext(revent->result));
10543                 goto next_master;
10544         }
10545
10546         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10547         if (result != ISC_R_SUCCESS)
10548                 goto next_master;
10549         result = dns_request_getresponse(revent->request, msg, 0);
10550         if (result != ISC_R_SUCCESS) {
10551                 dns_zone_log(zone, ISC_LOG_INFO,
10552                              "refresh: failure trying master "
10553                              "%s (source %s): %s", master, source,
10554                              dns_result_totext(result));
10555                 goto next_master;
10556         }
10557
10558         /*
10559          * Unexpected rcode.
10560          */
10561         if (msg->rcode != dns_rcode_noerror) {
10562                 char rcode[128];
10563                 isc_buffer_t rb;
10564
10565                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10566                 (void)dns_rcode_totext(msg->rcode, &rb);
10567
10568                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10569                     (msg->rcode == dns_rcode_servfail ||
10570                      msg->rcode == dns_rcode_notimp ||
10571                      msg->rcode == dns_rcode_formerr)) {
10572                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10573                                      "refresh: rcode (%.*s) retrying without "
10574                                      "EDNS master %s (source %s)",
10575                                      (int)rb.used, rcode, master, source);
10576                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10577                         goto same_master;
10578                 }
10579                 dns_zone_log(zone, ISC_LOG_INFO,
10580                              "refresh: unexpected rcode (%.*s) from "
10581                              "master %s (source %s)", (int)rb.used, rcode,
10582                              master, source);
10583                 /*
10584                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
10585                  */
10586                 if (msg->rcode == dns_rcode_refused &&
10587                     (zone->type == dns_zone_slave ||
10588                      zone->type == dns_zone_redirect))
10589                         goto tcp_transfer;
10590                 goto next_master;
10591         }
10592
10593         /*
10594          * If truncated punt to zone transfer which will query again.
10595          */
10596         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10597                 if (zone->type == dns_zone_slave ||
10598                     zone->type == dns_zone_redirect) {
10599                         dns_zone_log(zone, ISC_LOG_INFO,
10600                                      "refresh: truncated UDP answer, "
10601                                      "initiating TCP zone xfer "
10602                                      "for master %s (source %s)",
10603                                      master, source);
10604                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
10605                         goto tcp_transfer;
10606                 } else {
10607                         INSIST(zone->type == dns_zone_stub);
10608                         if (dns_request_usedtcp(revent->request)) {
10609                                 dns_zone_log(zone, ISC_LOG_INFO,
10610                                              "refresh: truncated TCP response "
10611                                              "from master %s (source %s)",
10612                                              master, source);
10613                                 goto next_master;
10614                         }
10615                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10616                         goto same_master;
10617                 }
10618         }
10619
10620         /*
10621          * if non-auth log and next master;
10622          */
10623         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10624                 dns_zone_log(zone, ISC_LOG_INFO,
10625                              "refresh: non-authoritative answer from "
10626                              "master %s (source %s)", master, source);
10627                 goto next_master;
10628         }
10629
10630         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10631         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
10632         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
10633         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
10634                                  dns_rdatatype_soa);
10635
10636         /*
10637          * There should not be a CNAME record at top of zone.
10638          */
10639         if (cnamecnt != 0) {
10640                 dns_zone_log(zone, ISC_LOG_INFO,
10641                              "refresh: CNAME at top of zone "
10642                              "in master %s (source %s)", master, source);
10643                 goto next_master;
10644         }
10645
10646         /*
10647          * if referral log and next master;
10648          */
10649         if (soacnt == 0 && soacount == 0 && nscount != 0) {
10650                 dns_zone_log(zone, ISC_LOG_INFO,
10651                              "refresh: referral response "
10652                              "from master %s (source %s)", master, source);
10653                 goto next_master;
10654         }
10655
10656         /*
10657          * if nodata log and next master;
10658          */
10659         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
10660                 dns_zone_log(zone, ISC_LOG_INFO,
10661                              "refresh: NODATA response "
10662                              "from master %s (source %s)", master, source);
10663                 goto next_master;
10664         }
10665
10666         /*
10667          * Only one soa at top of zone.
10668          */
10669         if (soacnt != 1) {
10670                 dns_zone_log(zone, ISC_LOG_INFO,
10671                              "refresh: answer SOA count (%d) != 1 "
10672                              "from master %s (source %s)",
10673                              soacnt, master, source);
10674                 goto next_master;
10675         }
10676
10677         /*
10678          * Extract serial
10679          */
10680         rdataset = NULL;
10681         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
10682                                       dns_rdatatype_soa, dns_rdatatype_none,
10683                                       NULL, &rdataset);
10684         if (result != ISC_R_SUCCESS) {
10685                 dns_zone_log(zone, ISC_LOG_INFO,
10686                              "refresh: unable to get SOA record "
10687                              "from master %s (source %s)", master, source);
10688                 goto next_master;
10689         }
10690
10691         result = dns_rdataset_first(rdataset);
10692         if (result != ISC_R_SUCCESS) {
10693                 dns_zone_log(zone, ISC_LOG_INFO,
10694                              "refresh: dns_rdataset_first() failed");
10695                 goto next_master;
10696         }
10697
10698         dns_rdataset_current(rdataset, &rdata);
10699         result = dns_rdata_tostruct(&rdata, &soa, NULL);
10700         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10701
10702         serial = soa.serial;
10703         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10704                 unsigned int soacount;
10705                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
10706                                           &oldserial, NULL, NULL, NULL, NULL,
10707                                           NULL);
10708                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10709                 RUNTIME_CHECK(soacount > 0U);
10710                 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
10711                               serial, oldserial);
10712         } else
10713                 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
10714                               serial);
10715
10716         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
10717             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
10718             isc_serial_gt(serial, oldserial)) {
10719                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
10720                                             &zone->sourceaddr, &now))
10721                 {
10722                         dns_zone_log(zone, ISC_LOG_INFO,
10723                                      "refresh: skipping %s as master %s "
10724                                      "(source %s) is unreachable (cached)",
10725                                      (zone->type == dns_zone_slave ||
10726                                       zone->type == dns_zone_redirect) ?
10727                                      "zone transfer" : "NS query",
10728                                      master, source);
10729                         goto next_master;
10730                 }
10731  tcp_transfer:
10732                 isc_event_free(&event);
10733                 dns_request_destroy(&zone->request);
10734                 if (zone->type == dns_zone_slave ||
10735                     zone->type == dns_zone_redirect) {
10736                         do_queue_xfrin = ISC_TRUE;
10737                 } else {
10738                         INSIST(zone->type == dns_zone_stub);
10739                         ns_query(zone, rdataset, NULL);
10740                 }
10741                 if (msg != NULL)
10742                         dns_message_destroy(&msg);
10743         } else if (isc_serial_eq(soa.serial, oldserial)) {
10744                 if (zone->masterfile != NULL) {
10745                         result = ISC_R_FAILURE;
10746                         if (zone->journal != NULL)
10747                                 result = isc_file_settime(zone->journal, &now);
10748                         if (result == ISC_R_SUCCESS &&
10749                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10750                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10751                                 result = isc_file_settime(zone->masterfile,
10752                                                           &now);
10753                         } else if (result != ISC_R_SUCCESS)
10754                                 result = isc_file_settime(zone->masterfile,
10755                                                           &now);
10756                         /* Someone removed the file from underneath us! */
10757                         if (result == ISC_R_FILENOTFOUND) {
10758                                 zone_needdump(zone, DNS_DUMP_DELAY);
10759                         } else if (result != ISC_R_SUCCESS)
10760                                 dns_zone_log(zone, ISC_LOG_ERROR,
10761                                              "refresh: could not set file "
10762                                              "modification time of '%s': %s",
10763                                              zone->masterfile,
10764                                              dns_result_totext(result));
10765                 }
10766                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10767                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10768                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10769                 goto next_master;
10770         } else {
10771                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
10772                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
10773                                      "received from master %s < ours (%u)",
10774                                      soa.serial, master, oldserial);
10775                 else
10776                         zone_debuglog(zone, me, 1, "ahead");
10777                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10778                 goto next_master;
10779         }
10780         if (msg != NULL)
10781                 dns_message_destroy(&msg);
10782         goto detach;
10783
10784  next_master:
10785         if (msg != NULL)
10786                 dns_message_destroy(&msg);
10787         isc_event_free(&event);
10788         dns_request_destroy(&zone->request);
10789         /*
10790          * Skip to next failed / untried master.
10791          */
10792         do {
10793                 zone->curmaster++;
10794         } while (zone->curmaster < zone->masterscnt &&
10795                  zone->mastersok[zone->curmaster]);
10796         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10797         if (zone->curmaster >= zone->masterscnt) {
10798                 isc_boolean_t done = ISC_TRUE;
10799                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10800                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10801                         /*
10802                          * Did we get a good answer from all the masters?
10803                          */
10804                         for (j = 0; j < zone->masterscnt; j++)
10805                                 if (zone->mastersok[j] == ISC_FALSE) {
10806                                         done = ISC_FALSE;
10807                                         break;
10808                                 }
10809                 } else
10810                         done = ISC_TRUE;
10811                 if (!done) {
10812                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10813                         zone->curmaster = 0;
10814                         /*
10815                          * Find the next failed master.
10816                          */
10817                         while (zone->curmaster < zone->masterscnt &&
10818                                zone->mastersok[zone->curmaster])
10819                                 zone->curmaster++;
10820                         goto requeue;
10821                 }
10822                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10823                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
10824                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10825                         zone->refreshtime = now;
10826                 }
10827                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10828                 zone_settimer(zone, &now);
10829                 goto detach;
10830         }
10831
10832  requeue:
10833         queue_soa_query(zone);
10834         goto detach;
10835
10836  same_master:
10837         if (msg != NULL)
10838                 dns_message_destroy(&msg);
10839         isc_event_free(&event);
10840         dns_request_destroy(&zone->request);
10841         queue_soa_query(zone);
10842
10843  detach:
10844         UNLOCK_ZONE(zone);
10845         if (do_queue_xfrin)
10846                 queue_xfrin(zone);
10847         dns_zone_idetach(&zone);
10848         return;
10849 }
10850
10851 static void
10852 queue_soa_query(dns_zone_t *zone) {
10853         const char me[] = "queue_soa_query";
10854         isc_event_t *e;
10855         dns_zone_t *dummy = NULL;
10856         isc_result_t result;
10857
10858         ENTER;
10859         /*
10860          * Locked by caller
10861          */
10862         REQUIRE(LOCKED_ZONE(zone));
10863
10864         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10865                 cancel_refresh(zone);
10866                 return;
10867         }
10868
10869         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
10870                                soa_query, zone, sizeof(isc_event_t));
10871         if (e == NULL) {
10872                 cancel_refresh(zone);
10873                 return;
10874         }
10875
10876         /*
10877          * Attach so that we won't clean up
10878          * until the event is delivered.
10879          */
10880         zone_iattach(zone, &dummy);
10881
10882         e->ev_arg = zone;
10883         e->ev_sender = NULL;
10884         result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
10885         if (result != ISC_R_SUCCESS) {
10886                 zone_idetach(&dummy);
10887                 isc_event_free(&e);
10888                 cancel_refresh(zone);
10889         }
10890 }
10891
10892 static inline isc_result_t
10893 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
10894              dns_message_t **messagep)
10895 {
10896         dns_message_t *message = NULL;
10897         dns_name_t *qname = NULL;
10898         dns_rdataset_t *qrdataset = NULL;
10899         isc_result_t result;
10900
10901         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10902                                     &message);
10903         if (result != ISC_R_SUCCESS)
10904                 goto cleanup;
10905
10906         message->opcode = dns_opcode_query;
10907         message->rdclass = zone->rdclass;
10908
10909         result = dns_message_gettempname(message, &qname);
10910         if (result != ISC_R_SUCCESS)
10911                 goto cleanup;
10912
10913         result = dns_message_gettemprdataset(message, &qrdataset);
10914         if (result != ISC_R_SUCCESS)
10915                 goto cleanup;
10916
10917         /*
10918          * Make question.
10919          */
10920         dns_name_init(qname, NULL);
10921         dns_name_clone(&zone->origin, qname);
10922         dns_rdataset_init(qrdataset);
10923         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
10924         ISC_LIST_APPEND(qname->list, qrdataset, link);
10925         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
10926
10927         *messagep = message;
10928         return (ISC_R_SUCCESS);
10929
10930  cleanup:
10931         if (qname != NULL)
10932                 dns_message_puttempname(message, &qname);
10933         if (qrdataset != NULL)
10934                 dns_message_puttemprdataset(message, &qrdataset);
10935         if (message != NULL)
10936                 dns_message_destroy(&message);
10937         return (result);
10938 }
10939
10940 static isc_result_t
10941 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
10942         dns_rdataset_t *rdataset = NULL;
10943         dns_rdatalist_t *rdatalist = NULL;
10944         dns_rdata_t *rdata = NULL;
10945         isc_result_t result;
10946
10947         result = dns_message_gettemprdatalist(message, &rdatalist);
10948         if (result != ISC_R_SUCCESS)
10949                 goto cleanup;
10950         result = dns_message_gettemprdata(message, &rdata);
10951         if (result != ISC_R_SUCCESS)
10952                 goto cleanup;
10953         result = dns_message_gettemprdataset(message, &rdataset);
10954         if (result != ISC_R_SUCCESS)
10955                 goto cleanup;
10956         dns_rdataset_init(rdataset);
10957
10958         rdatalist->type = dns_rdatatype_opt;
10959         rdatalist->covers = 0;
10960
10961         /*
10962          * Set Maximum UDP buffer size.
10963          */
10964         rdatalist->rdclass = udpsize;
10965
10966         /*
10967          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
10968          */
10969         rdatalist->ttl = 0;
10970
10971         /* Set EDNS options if applicable */
10972         if (reqnsid) {
10973                 unsigned char data[4];
10974                 isc_buffer_t buf;
10975
10976                 isc_buffer_init(&buf, data, sizeof(data));
10977                 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
10978                 isc_buffer_putuint16(&buf, 0);
10979                 rdata->data = data;
10980                 rdata->length = sizeof(data);
10981         } else {
10982                 rdata->data = NULL;
10983                 rdata->length = 0;
10984         }
10985
10986         rdata->rdclass = rdatalist->rdclass;
10987         rdata->type = rdatalist->type;
10988         rdata->flags = 0;
10989
10990         ISC_LIST_INIT(rdatalist->rdata);
10991         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
10992         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
10993                       == ISC_R_SUCCESS);
10994
10995         return (dns_message_setopt(message, rdataset));
10996
10997  cleanup:
10998         if (rdatalist != NULL)
10999                 dns_message_puttemprdatalist(message, &rdatalist);
11000         if (rdataset != NULL)
11001                 dns_message_puttemprdataset(message, &rdataset);
11002         if (rdata != NULL)
11003                 dns_message_puttemprdata(message, &rdata);
11004
11005         return (result);
11006 }
11007
11008 static void
11009 soa_query(isc_task_t *task, isc_event_t *event) {
11010         const char me[] = "soa_query";
11011         isc_result_t result = ISC_R_FAILURE;
11012         dns_message_t *message = NULL;
11013         dns_zone_t *zone = event->ev_arg;
11014         dns_zone_t *dummy = NULL;
11015         isc_netaddr_t masterip;
11016         dns_tsigkey_t *key = NULL;
11017         isc_uint32_t options;
11018         isc_boolean_t cancel = ISC_TRUE;
11019         int timeout;
11020         isc_boolean_t have_xfrsource, reqnsid;
11021         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11022
11023         REQUIRE(DNS_ZONE_VALID(zone));
11024
11025         UNUSED(task);
11026
11027         ENTER;
11028
11029         LOCK_ZONE(zone);
11030         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
11031             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11032             zone->view->requestmgr == NULL) {
11033                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11034                         cancel = ISC_FALSE;
11035                 goto cleanup;
11036         }
11037
11038         /*
11039          * XXX Optimisation: Create message when zone is setup and reuse.
11040          */
11041         result = create_query(zone, dns_rdatatype_soa, &message);
11042         if (result != ISC_R_SUCCESS)
11043                 goto cleanup;
11044
11045  again:
11046         INSIST(zone->masterscnt > 0);
11047         INSIST(zone->curmaster < zone->masterscnt);
11048
11049         zone->masteraddr = zone->masters[zone->curmaster];
11050
11051         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11052         /*
11053          * First, look for a tsig key in the master statement, then
11054          * try for a server key.
11055          */
11056         if ((zone->masterkeynames != NULL) &&
11057             (zone->masterkeynames[zone->curmaster] != NULL)) {
11058                 dns_view_t *view = dns_zone_getview(zone);
11059                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11060                 result = dns_view_gettsig(view, keyname, &key);
11061                 if (result != ISC_R_SUCCESS) {
11062                         char namebuf[DNS_NAME_FORMATSIZE];
11063                         dns_name_format(keyname, namebuf, sizeof(namebuf));
11064                         dns_zone_log(zone, ISC_LOG_ERROR,
11065                                      "unable to find key: %s", namebuf);
11066                         goto skip_master;
11067                 }
11068         }
11069         if (key == NULL) {
11070                 result = dns_view_getpeertsig(zone->view, &masterip, &key);
11071                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11072                         char addrbuf[ISC_NETADDR_FORMATSIZE];
11073                         isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
11074                         dns_zone_log(zone, ISC_LOG_ERROR,
11075                                      "unable to find TSIG key for %s", addrbuf);
11076                         goto skip_master;
11077                 }
11078         }
11079
11080         have_xfrsource = ISC_FALSE;
11081         reqnsid = zone->view->requestnsid;
11082         if (zone->view->peers != NULL) {
11083                 dns_peer_t *peer = NULL;
11084                 isc_boolean_t edns;
11085                 result = dns_peerlist_peerbyaddr(zone->view->peers,
11086                                                  &masterip, &peer);
11087                 if (result == ISC_R_SUCCESS) {
11088                         result = dns_peer_getsupportedns(peer, &edns);
11089                         if (result == ISC_R_SUCCESS && !edns)
11090                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11091                         result = dns_peer_gettransfersource(peer,
11092                                                             &zone->sourceaddr);
11093                         if (result == ISC_R_SUCCESS)
11094                                 have_xfrsource = ISC_TRUE;
11095                         if (zone->view->resolver != NULL)
11096                                 udpsize =
11097                                   dns_resolver_getudpsize(zone->view->resolver);
11098                         (void)dns_peer_getudpsize(peer, &udpsize);
11099                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
11100                 }
11101         }
11102
11103         switch (isc_sockaddr_pf(&zone->masteraddr)) {
11104         case PF_INET:
11105                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11106                         if (isc_sockaddr_equal(&zone->altxfrsource4,
11107                                                &zone->xfrsource4))
11108                                 goto skip_master;
11109                         zone->sourceaddr = zone->altxfrsource4;
11110                 } else if (!have_xfrsource)
11111                         zone->sourceaddr = zone->xfrsource4;
11112                 break;
11113         case PF_INET6:
11114                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11115                         if (isc_sockaddr_equal(&zone->altxfrsource6,
11116                                                &zone->xfrsource6))
11117                                 goto skip_master;
11118                         zone->sourceaddr = zone->altxfrsource6;
11119                 } else if (!have_xfrsource)
11120                         zone->sourceaddr = zone->xfrsource6;
11121                 break;
11122         default:
11123                 result = ISC_R_NOTIMPLEMENTED;
11124                 goto cleanup;
11125         }
11126
11127         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
11128                   DNS_REQUESTOPT_TCP : 0;
11129
11130         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11131                 result = add_opt(message, udpsize, reqnsid);
11132                 if (result != ISC_R_SUCCESS)
11133                         zone_debuglog(zone, me, 1,
11134                                       "unable to add opt record: %s",
11135                                       dns_result_totext(result));
11136         }
11137
11138         zone_iattach(zone, &dummy);
11139         timeout = 15;
11140         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11141                 timeout = 30;
11142         result = dns_request_createvia2(zone->view->requestmgr, message,
11143                                         &zone->sourceaddr, &zone->masteraddr,
11144                                         options, key, timeout * 3, timeout,
11145                                         zone->task, refresh_callback, zone,
11146                                         &zone->request);
11147         if (result != ISC_R_SUCCESS) {
11148                 zone_idetach(&dummy);
11149                 zone_debuglog(zone, me, 1,
11150                               "dns_request_createvia2() failed: %s",
11151                               dns_result_totext(result));
11152                 goto cleanup;
11153         } else {
11154                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
11155                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
11156                 else
11157                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
11158         }
11159         cancel = ISC_FALSE;
11160
11161  cleanup:
11162         if (key != NULL)
11163                 dns_tsigkey_detach(&key);
11164         if (result != ISC_R_SUCCESS)
11165                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11166         if (message != NULL)
11167                 dns_message_destroy(&message);
11168         if (cancel)
11169                 cancel_refresh(zone);
11170         isc_event_free(&event);
11171         UNLOCK_ZONE(zone);
11172         dns_zone_idetach(&zone);
11173         return;
11174
11175  skip_master:
11176         if (key != NULL)
11177                 dns_tsigkey_detach(&key);
11178         /*
11179          * Skip to next failed / untried master.
11180          */
11181         do {
11182                 zone->curmaster++;
11183         } while (zone->curmaster < zone->masterscnt &&
11184                  zone->mastersok[zone->curmaster]);
11185         if (zone->curmaster < zone->masterscnt)
11186                 goto again;
11187         zone->curmaster = 0;
11188         goto cleanup;
11189 }
11190
11191 static void
11192 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
11193         const char me[] = "ns_query";
11194         isc_result_t result;
11195         dns_message_t *message = NULL;
11196         isc_netaddr_t masterip;
11197         dns_tsigkey_t *key = NULL;
11198         dns_dbnode_t *node = NULL;
11199         int timeout;
11200         isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
11201         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11202
11203         REQUIRE(DNS_ZONE_VALID(zone));
11204         REQUIRE(LOCKED_ZONE(zone));
11205         REQUIRE((soardataset != NULL && stub == NULL) ||
11206                 (soardataset == NULL && stub != NULL));
11207         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
11208
11209         ENTER;
11210
11211         if (stub == NULL) {
11212                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
11213                 if (stub == NULL)
11214                         goto cleanup;
11215                 stub->magic = STUB_MAGIC;
11216                 stub->mctx = zone->mctx;
11217                 stub->zone = NULL;
11218                 stub->db = NULL;
11219                 stub->version = NULL;
11220
11221                 /*
11222                  * Attach so that the zone won't disappear from under us.
11223                  */
11224                 zone_iattach(zone, &stub->zone);
11225
11226                 /*
11227                  * If a db exists we will update it, otherwise we create a
11228                  * new one and attach it to the zone once we have the NS
11229                  * RRset and glue.
11230                  */
11231                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11232                 if (zone->db != NULL) {
11233                         dns_db_attach(zone->db, &stub->db);
11234                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11235                 } else {
11236                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11237
11238                         INSIST(zone->db_argc >= 1);
11239                         result = dns_db_create(zone->mctx, zone->db_argv[0],
11240                                                &zone->origin, dns_dbtype_stub,
11241                                                zone->rdclass,
11242                                                zone->db_argc - 1,
11243                                                zone->db_argv + 1,
11244                                                &stub->db);
11245                         if (result != ISC_R_SUCCESS) {
11246                                 dns_zone_log(zone, ISC_LOG_ERROR,
11247                                              "refreshing stub: "
11248                                              "could not create "
11249                                              "database: %s",
11250                                              dns_result_totext(result));
11251                                 goto cleanup;
11252                         }
11253                         dns_db_settask(stub->db, zone->task);
11254                 }
11255
11256                 result = dns_db_newversion(stub->db, &stub->version);
11257                 if (result != ISC_R_SUCCESS) {
11258                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11259                                      "dns_db_newversion() failed: %s",
11260                                      dns_result_totext(result));
11261                         goto cleanup;
11262                 }
11263
11264                 /*
11265                  * Update SOA record.
11266                  */
11267                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
11268                                          &node);
11269                 if (result != ISC_R_SUCCESS) {
11270                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11271                                      "dns_db_findnode() failed: %s",
11272                                      dns_result_totext(result));
11273                         goto cleanup;
11274                 }
11275
11276                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
11277                                             soardataset, 0, NULL);
11278                 dns_db_detachnode(stub->db, &node);
11279                 if (result != ISC_R_SUCCESS) {
11280                         dns_zone_log(zone, ISC_LOG_INFO,
11281                                      "refreshing stub: "
11282                                      "dns_db_addrdataset() failed: %s",
11283                                      dns_result_totext(result));
11284                         goto cleanup;
11285                 }
11286         }
11287
11288         /*
11289          * XXX Optimisation: Create message when zone is setup and reuse.
11290          */
11291         result = create_query(zone, dns_rdatatype_ns, &message);
11292         INSIST(result == ISC_R_SUCCESS);
11293
11294         INSIST(zone->masterscnt > 0);
11295         INSIST(zone->curmaster < zone->masterscnt);
11296         zone->masteraddr = zone->masters[zone->curmaster];
11297
11298         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11299         /*
11300          * First, look for a tsig key in the master statement, then
11301          * try for a server key.
11302          */
11303         if ((zone->masterkeynames != NULL) &&
11304             (zone->masterkeynames[zone->curmaster] != NULL)) {
11305                 dns_view_t *view = dns_zone_getview(zone);
11306                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11307                 result = dns_view_gettsig(view, keyname, &key);
11308                 if (result != ISC_R_SUCCESS) {
11309                         char namebuf[DNS_NAME_FORMATSIZE];
11310                         dns_name_format(keyname, namebuf, sizeof(namebuf));
11311                         dns_zone_log(zone, ISC_LOG_ERROR,
11312                                      "unable to find key: %s", namebuf);
11313                 }
11314         }
11315         if (key == NULL)
11316                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
11317
11318         reqnsid = zone->view->requestnsid;
11319         if (zone->view->peers != NULL) {
11320                 dns_peer_t *peer = NULL;
11321                 isc_boolean_t edns;
11322                 result = dns_peerlist_peerbyaddr(zone->view->peers,
11323                                                  &masterip, &peer);
11324                 if (result == ISC_R_SUCCESS) {
11325                         result = dns_peer_getsupportedns(peer, &edns);
11326                         if (result == ISC_R_SUCCESS && !edns)
11327                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11328                         result = dns_peer_gettransfersource(peer,
11329                                                             &zone->sourceaddr);
11330                         if (result == ISC_R_SUCCESS)
11331                                 have_xfrsource = ISC_TRUE;
11332                         if (zone->view->resolver != NULL)
11333                                 udpsize =
11334                                   dns_resolver_getudpsize(zone->view->resolver);
11335                         (void)dns_peer_getudpsize(peer, &udpsize);
11336                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
11337                 }
11338
11339         }
11340         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11341                 result = add_opt(message, udpsize, reqnsid);
11342                 if (result != ISC_R_SUCCESS)
11343                         zone_debuglog(zone, me, 1,
11344                                       "unable to add opt record: %s",
11345                                       dns_result_totext(result));
11346         }
11347
11348         /*
11349          * Always use TCP so that we shouldn't truncate in additional section.
11350          */
11351         switch (isc_sockaddr_pf(&zone->masteraddr)) {
11352         case PF_INET:
11353                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11354                         zone->sourceaddr = zone->altxfrsource4;
11355                 else if (!have_xfrsource)
11356                         zone->sourceaddr = zone->xfrsource4;
11357                 break;
11358         case PF_INET6:
11359                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11360                         zone->sourceaddr = zone->altxfrsource6;
11361                 else if (!have_xfrsource)
11362                         zone->sourceaddr = zone->xfrsource6;
11363                 break;
11364         default:
11365                 result = ISC_R_NOTIMPLEMENTED;
11366                 POST(result);
11367                 goto cleanup;
11368         }
11369         timeout = 15;
11370         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11371                 timeout = 30;
11372         result = dns_request_createvia2(zone->view->requestmgr, message,
11373                                         &zone->sourceaddr, &zone->masteraddr,
11374                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
11375                                         timeout, zone->task, stub_callback,
11376                                         stub, &zone->request);
11377         if (result != ISC_R_SUCCESS) {
11378                 zone_debuglog(zone, me, 1,
11379                               "dns_request_createvia() failed: %s",
11380                               dns_result_totext(result));
11381                 goto cleanup;
11382         }
11383         dns_message_destroy(&message);
11384         goto unlock;
11385
11386  cleanup:
11387         cancel_refresh(zone);
11388         if (stub != NULL) {
11389                 stub->magic = 0;
11390                 if (stub->version != NULL)
11391                         dns_db_closeversion(stub->db, &stub->version,
11392                                             ISC_FALSE);
11393                 if (stub->db != NULL)
11394                         dns_db_detach(&stub->db);
11395                 if (stub->zone != NULL)
11396                         zone_idetach(&stub->zone);
11397                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
11398         }
11399         if (message != NULL)
11400                 dns_message_destroy(&message);
11401  unlock:
11402         if (key != NULL)
11403                 dns_tsigkey_detach(&key);
11404         return;
11405 }
11406
11407 /*
11408  * Handle the control event.  Note that although this event causes the zone
11409  * to shut down, it is not a shutdown event in the sense of the task library.
11410  */
11411 static void
11412 zone_shutdown(isc_task_t *task, isc_event_t *event) {
11413         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
11414         isc_boolean_t free_needed, linked = ISC_FALSE;
11415         dns_zone_t *raw = NULL, *secure = NULL;
11416
11417         UNUSED(task);
11418         REQUIRE(DNS_ZONE_VALID(zone));
11419         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
11420         INSIST(isc_refcount_current(&zone->erefs) == 0);
11421
11422         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
11423
11424         /*
11425          * Stop things being restarted after we cancel them below.
11426          */
11427         LOCK_ZONE(zone);
11428         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
11429         UNLOCK_ZONE(zone);
11430
11431         /*
11432          * If we were waiting for xfrin quota, step out of
11433          * the queue.
11434          * If there's no zone manager, we can't be waiting for the
11435          * xfrin quota
11436          */
11437         if (zone->zmgr != NULL) {
11438                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11439                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
11440                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
11441                                         statelink);
11442                         linked = ISC_TRUE;
11443                         zone->statelist = NULL;
11444                 }
11445                 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
11446                         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
11447                                         statelink);
11448                         zone->statelist = NULL;
11449                         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
11450                 }
11451                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11452         }
11453
11454         /*
11455          * In task context, no locking required.  See zone_xfrdone().
11456          */
11457         if (zone->xfr != NULL)
11458                 dns_xfrin_shutdown(zone->xfr);
11459
11460         /* Safe to release the zone now */
11461         if (zone->zmgr != NULL)
11462                 dns_zonemgr_releasezone(zone->zmgr, zone);
11463
11464         LOCK_ZONE(zone);
11465         if (linked) {
11466                 INSIST(zone->irefs > 0);
11467                 zone->irefs--;
11468         }
11469         if (zone->request != NULL) {
11470                 dns_request_cancel(zone->request);
11471         }
11472
11473         if (zone->readio != NULL)
11474                 zonemgr_cancelio(zone->readio);
11475
11476         if (zone->lctx != NULL)
11477                 dns_loadctx_cancel(zone->lctx);
11478
11479         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11480             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11481                 if (zone->writeio != NULL)
11482                         zonemgr_cancelio(zone->writeio);
11483
11484                 if (zone->dctx != NULL)
11485                         dns_dumpctx_cancel(zone->dctx);
11486         }
11487
11488         notify_cancel(zone);
11489
11490         forward_cancel(zone);
11491
11492         if (zone->timer != NULL) {
11493                 isc_timer_detach(&zone->timer);
11494                 INSIST(zone->irefs > 0);
11495                 zone->irefs--;
11496         }
11497
11498         if (zone->view != NULL)
11499                 dns_view_weakdetach(&zone->view);
11500
11501         /*
11502          * We have now canceled everything set the flag to allow exit_check()
11503          * to succeed.  We must not unlock between setting this flag and
11504          * calling exit_check().
11505          */
11506         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
11507         free_needed = exit_check(zone);
11508         if (inline_secure(zone)) {
11509                 raw = zone->raw;
11510                 zone->raw = NULL;
11511         }
11512         if (inline_raw(zone)) {
11513                 secure = zone->secure;
11514                 zone->secure = NULL;
11515         }
11516         UNLOCK_ZONE(zone);
11517         if (raw != NULL)
11518                 dns_zone_detach(&raw);
11519         if (secure != NULL)
11520                 dns_zone_idetach(&secure);
11521         if (free_needed)
11522                 zone_free(zone);
11523 }
11524
11525 static void
11526 zone_timer(isc_task_t *task, isc_event_t *event) {
11527         const char me[] = "zone_timer";
11528         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
11529
11530         UNUSED(task);
11531         REQUIRE(DNS_ZONE_VALID(zone));
11532
11533         ENTER;
11534
11535         zone_maintenance(zone);
11536
11537         isc_event_free(&event);
11538 }
11539
11540 static void
11541 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
11542         const char me[] = "zone_settimer";
11543         isc_time_t next;
11544         isc_result_t result;
11545
11546         ENTER;
11547         REQUIRE(DNS_ZONE_VALID(zone));
11548         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11549                 return;
11550
11551         isc_time_settoepoch(&next);
11552
11553         switch (zone->type) {
11554         case dns_zone_redirect:
11555                 if (zone->masters != NULL)
11556                         goto treat_as_slave;
11557                 /* FALLTHROUGH */
11558
11559         case dns_zone_master:
11560                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
11561                         next = zone->notifytime;
11562                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11563                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11564                         INSIST(!isc_time_isepoch(&zone->dumptime));
11565                         if (isc_time_isepoch(&next) ||
11566                             isc_time_compare(&zone->dumptime, &next) < 0)
11567                                 next = zone->dumptime;
11568                 }
11569                 if (zone->type == dns_zone_redirect)
11570                         break;
11571                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
11572                     !isc_time_isepoch(&zone->refreshkeytime)) {
11573                         if (isc_time_isepoch(&next) ||
11574                             isc_time_compare(&zone->refreshkeytime, &next) < 0)
11575                                 next = zone->refreshkeytime;
11576                 }
11577                 if (!isc_time_isepoch(&zone->resigntime)) {
11578                         if (isc_time_isepoch(&next) ||
11579                             isc_time_compare(&zone->resigntime, &next) < 0)
11580                                 next = zone->resigntime;
11581                 }
11582                 if (!isc_time_isepoch(&zone->keywarntime)) {
11583                         if (isc_time_isepoch(&next) ||
11584                             isc_time_compare(&zone->keywarntime, &next) < 0)
11585                                 next = zone->keywarntime;
11586                 }
11587                 if (!isc_time_isepoch(&zone->signingtime)) {
11588                         if (isc_time_isepoch(&next) ||
11589                             isc_time_compare(&zone->signingtime, &next) < 0)
11590                                 next = zone->signingtime;
11591                 }
11592                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
11593                         if (isc_time_isepoch(&next) ||
11594                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
11595                                 next = zone->nsec3chaintime;
11596                 }
11597                 break;
11598
11599         case dns_zone_slave:
11600         treat_as_slave:
11601                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
11602                         next = zone->notifytime;
11603                 /* FALLTHROUGH */
11604
11605         case dns_zone_stub:
11606                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
11607                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
11608                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
11609                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
11610                         INSIST(!isc_time_isepoch(&zone->refreshtime));
11611                         if (isc_time_isepoch(&next) ||
11612                             isc_time_compare(&zone->refreshtime, &next) < 0)
11613                                 next = zone->refreshtime;
11614                 }
11615                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11616                     !isc_time_isepoch(&zone->expiretime)) {
11617                         if (isc_time_isepoch(&next) ||
11618                              isc_time_compare(&zone->expiretime, &next) < 0)
11619                                 next = zone->expiretime;
11620                 }
11621                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11622                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11623                         INSIST(!isc_time_isepoch(&zone->dumptime));
11624                         if (isc_time_isepoch(&next) ||
11625                             isc_time_compare(&zone->dumptime, &next) < 0)
11626                                 next = zone->dumptime;
11627                 }
11628                 break;
11629
11630         case dns_zone_key:
11631                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11632                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11633                         INSIST(!isc_time_isepoch(&zone->dumptime));
11634                         if (isc_time_isepoch(&next) ||
11635                             isc_time_compare(&zone->dumptime, &next) < 0)
11636                                 next = zone->dumptime;
11637                 }
11638                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
11639                         if (isc_time_isepoch(&next) ||
11640                             (!isc_time_isepoch(&zone->refreshkeytime) &&
11641                             isc_time_compare(&zone->refreshkeytime, &next) < 0))
11642                                 next = zone->refreshkeytime;
11643                 }
11644                 break;
11645
11646         default:
11647                 break;
11648         }
11649
11650         if (isc_time_isepoch(&next)) {
11651                 zone_debuglog(zone, me, 10, "settimer inactive");
11652                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
11653                                           NULL, NULL, ISC_TRUE);
11654                 if (result != ISC_R_SUCCESS)
11655                         dns_zone_log(zone, ISC_LOG_ERROR,
11656                                      "could not deactivate zone timer: %s",
11657                                      isc_result_totext(result));
11658         } else {
11659                 if (isc_time_compare(&next, now) <= 0)
11660                         next = *now;
11661                 result = isc_timer_reset(zone->timer, isc_timertype_once,
11662                                          &next, NULL, ISC_TRUE);
11663                 if (result != ISC_R_SUCCESS)
11664                         dns_zone_log(zone, ISC_LOG_ERROR,
11665                                      "could not reset zone timer: %s",
11666                                      isc_result_totext(result));
11667         }
11668 }
11669
11670 static void
11671 cancel_refresh(dns_zone_t *zone) {
11672         const char me[] = "cancel_refresh";
11673         isc_time_t now;
11674
11675         /*
11676          * 'zone' locked by caller.
11677          */
11678
11679         REQUIRE(DNS_ZONE_VALID(zone));
11680         REQUIRE(LOCKED_ZONE(zone));
11681
11682         ENTER;
11683
11684         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11685         TIME_NOW(&now);
11686         zone_settimer(zone, &now);
11687 }
11688
11689 static isc_result_t
11690 notify_createmessage(dns_zone_t *zone, unsigned int flags,
11691                      dns_message_t **messagep)
11692 {
11693         dns_db_t *zonedb = NULL;
11694         dns_dbnode_t *node = NULL;
11695         dns_dbversion_t *version = NULL;
11696         dns_message_t *message = NULL;
11697         dns_rdataset_t rdataset;
11698         dns_rdata_t rdata = DNS_RDATA_INIT;
11699
11700         dns_name_t *tempname = NULL;
11701         dns_rdata_t *temprdata = NULL;
11702         dns_rdatalist_t *temprdatalist = NULL;
11703         dns_rdataset_t *temprdataset = NULL;
11704
11705         isc_result_t result;
11706         isc_region_t r;
11707         isc_buffer_t *b = NULL;
11708
11709         REQUIRE(DNS_ZONE_VALID(zone));
11710         REQUIRE(messagep != NULL && *messagep == NULL);
11711
11712         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11713                                     &message);
11714         if (result != ISC_R_SUCCESS)
11715                 return (result);
11716
11717         message->opcode = dns_opcode_notify;
11718         message->flags |= DNS_MESSAGEFLAG_AA;
11719         message->rdclass = zone->rdclass;
11720
11721         result = dns_message_gettempname(message, &tempname);
11722         if (result != ISC_R_SUCCESS)
11723                 goto cleanup;
11724
11725         result = dns_message_gettemprdataset(message, &temprdataset);
11726         if (result != ISC_R_SUCCESS)
11727                 goto cleanup;
11728
11729         /*
11730          * Make question.
11731          */
11732         dns_name_init(tempname, NULL);
11733         dns_name_clone(&zone->origin, tempname);
11734         dns_rdataset_init(temprdataset);
11735         dns_rdataset_makequestion(temprdataset, zone->rdclass,
11736                                   dns_rdatatype_soa);
11737         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11738         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
11739         tempname = NULL;
11740         temprdataset = NULL;
11741
11742         if ((flags & DNS_NOTIFY_NOSOA) != 0)
11743                 goto done;
11744
11745         result = dns_message_gettempname(message, &tempname);
11746         if (result != ISC_R_SUCCESS)
11747                 goto soa_cleanup;
11748         result = dns_message_gettemprdata(message, &temprdata);
11749         if (result != ISC_R_SUCCESS)
11750                 goto soa_cleanup;
11751         result = dns_message_gettemprdataset(message, &temprdataset);
11752         if (result != ISC_R_SUCCESS)
11753                 goto soa_cleanup;
11754         result = dns_message_gettemprdatalist(message, &temprdatalist);
11755         if (result != ISC_R_SUCCESS)
11756                 goto soa_cleanup;
11757
11758         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11759         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
11760         dns_db_attach(zone->db, &zonedb);
11761         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11762
11763         dns_name_init(tempname, NULL);
11764         dns_name_clone(&zone->origin, tempname);
11765         dns_db_currentversion(zonedb, &version);
11766         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
11767         if (result != ISC_R_SUCCESS)
11768                 goto soa_cleanup;
11769
11770         dns_rdataset_init(&rdataset);
11771         result = dns_db_findrdataset(zonedb, node, version,
11772                                      dns_rdatatype_soa,
11773                                      dns_rdatatype_none, 0, &rdataset,
11774                                      NULL);
11775         if (result != ISC_R_SUCCESS)
11776                 goto soa_cleanup;
11777         result = dns_rdataset_first(&rdataset);
11778         if (result != ISC_R_SUCCESS)
11779                 goto soa_cleanup;
11780         dns_rdataset_current(&rdataset, &rdata);
11781         dns_rdata_toregion(&rdata, &r);
11782         result = isc_buffer_allocate(zone->mctx, &b, r.length);
11783         if (result != ISC_R_SUCCESS)
11784                 goto soa_cleanup;
11785         isc_buffer_putmem(b, r.base, r.length);
11786         isc_buffer_usedregion(b, &r);
11787         dns_rdata_init(temprdata);
11788         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
11789         dns_message_takebuffer(message, &b);
11790         result = dns_rdataset_next(&rdataset);
11791         dns_rdataset_disassociate(&rdataset);
11792         if (result != ISC_R_NOMORE)
11793                 goto soa_cleanup;
11794         temprdatalist->rdclass = rdata.rdclass;
11795         temprdatalist->type = rdata.type;
11796         temprdatalist->covers = 0;
11797         temprdatalist->ttl = rdataset.ttl;
11798         ISC_LIST_INIT(temprdatalist->rdata);
11799         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
11800
11801         dns_rdataset_init(temprdataset);
11802         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
11803         if (result != ISC_R_SUCCESS)
11804                 goto soa_cleanup;
11805
11806         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11807         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
11808         temprdatalist = NULL;
11809         temprdataset = NULL;
11810         temprdata = NULL;
11811         tempname = NULL;
11812
11813  soa_cleanup:
11814         if (node != NULL)
11815                 dns_db_detachnode(zonedb, &node);
11816         if (version != NULL)
11817                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
11818         if (zonedb != NULL)
11819                 dns_db_detach(&zonedb);
11820         if (tempname != NULL)
11821                 dns_message_puttempname(message, &tempname);
11822         if (temprdata != NULL)
11823                 dns_message_puttemprdata(message, &temprdata);
11824         if (temprdataset != NULL)
11825                 dns_message_puttemprdataset(message, &temprdataset);
11826         if (temprdatalist != NULL)
11827                 dns_message_puttemprdatalist(message, &temprdatalist);
11828
11829  done:
11830         *messagep = message;
11831         return (ISC_R_SUCCESS);
11832
11833  cleanup:
11834         if (tempname != NULL)
11835                 dns_message_puttempname(message, &tempname);
11836         if (temprdataset != NULL)
11837                 dns_message_puttemprdataset(message, &temprdataset);
11838         dns_message_destroy(&message);
11839         return (result);
11840 }
11841
11842 isc_result_t
11843 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
11844                        dns_message_t *msg)
11845 {
11846         unsigned int i;
11847         dns_rdata_soa_t soa;
11848         dns_rdataset_t *rdataset = NULL;
11849         dns_rdata_t rdata = DNS_RDATA_INIT;
11850         isc_result_t result;
11851         char fromtext[ISC_SOCKADDR_FORMATSIZE];
11852         int match = 0;
11853         isc_netaddr_t netaddr;
11854         isc_sockaddr_t local, remote;
11855
11856         REQUIRE(DNS_ZONE_VALID(zone));
11857
11858         /*
11859          * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
11860          * ROLLOVER.
11861          *
11862          * SOA: RFC1996
11863          * Check that 'from' is a valid notify source, (zone->masters).
11864          *      Return DNS_R_REFUSED if not.
11865          *
11866          * If the notify message contains a serial number check it
11867          * against the zones serial and return if <= current serial
11868          *
11869          * If a refresh check is progress, if so just record the
11870          * fact we received a NOTIFY and from where and return.
11871          * We will perform a new refresh check when the current one
11872          * completes. Return ISC_R_SUCCESS.
11873          *
11874          * Otherwise initiate a refresh check using 'from' as the
11875          * first address to check.  Return ISC_R_SUCCESS.
11876          */
11877
11878         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
11879
11880         /*
11881          * Notify messages are processed by the raw zone.
11882          */
11883         LOCK_ZONE(zone);
11884         if (inline_secure(zone)) {
11885                 result = dns_zone_notifyreceive(zone->raw, from, msg);
11886                 UNLOCK_ZONE(zone);
11887                 return (result);
11888         }
11889         /*
11890          *  We only handle NOTIFY (SOA) at the present.
11891          */
11892         if (isc_sockaddr_pf(from) == PF_INET)
11893                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
11894         else
11895                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
11896         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
11897             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
11898                                  dns_rdatatype_soa, dns_rdatatype_none,
11899                                  NULL, NULL) != ISC_R_SUCCESS) {
11900                 UNLOCK_ZONE(zone);
11901                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
11902                         dns_zone_log(zone, ISC_LOG_NOTICE,
11903                                      "NOTIFY with no "
11904                                      "question section from: %s", fromtext);
11905                         return (DNS_R_FORMERR);
11906                 }
11907                 dns_zone_log(zone, ISC_LOG_NOTICE,
11908                              "NOTIFY zone does not match");
11909                 return (DNS_R_NOTIMP);
11910         }
11911
11912         /*
11913          * If we are a master zone just succeed.
11914          */
11915         if (zone->type == dns_zone_master) {
11916                 UNLOCK_ZONE(zone);
11917                 return (ISC_R_SUCCESS);
11918         }
11919
11920         isc_netaddr_fromsockaddr(&netaddr, from);
11921         for (i = 0; i < zone->masterscnt; i++) {
11922                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
11923                         break;
11924                 if (zone->view->aclenv.match_mapped &&
11925                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
11926                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
11927                         isc_netaddr_t na1, na2;
11928                         isc_netaddr_fromv4mapped(&na1, &netaddr);
11929                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
11930                         if (isc_netaddr_equal(&na1, &na2))
11931                                 break;
11932                 }
11933         }
11934
11935         /*
11936          * Accept notify requests from non masters if they are on
11937          * 'zone->notify_acl'.
11938          */
11939         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
11940             dns_acl_match(&netaddr, NULL, zone->notify_acl,
11941                           &zone->view->aclenv,
11942                           &match, NULL) == ISC_R_SUCCESS &&
11943             match > 0)
11944         {
11945                 /* Accept notify. */
11946         } else if (i >= zone->masterscnt) {
11947                 UNLOCK_ZONE(zone);
11948                 dns_zone_log(zone, ISC_LOG_INFO,
11949                              "refused notify from non-master: %s", fromtext);
11950                 inc_stats(zone, dns_zonestatscounter_notifyrej);
11951                 return (DNS_R_REFUSED);
11952         }
11953
11954         /*
11955          * If the zone is loaded and there are answers check the serial
11956          * to see if we need to do a refresh.  Do not worry about this
11957          * check if we are a dialup zone as we use the notify request
11958          * to trigger a refresh check.
11959          */
11960         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
11961             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11962             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
11963                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
11964                                               &zone->origin,
11965                                               dns_rdatatype_soa,
11966                                               dns_rdatatype_none, NULL,
11967                                               &rdataset);
11968                 if (result == ISC_R_SUCCESS)
11969                         result = dns_rdataset_first(rdataset);
11970                 if (result == ISC_R_SUCCESS) {
11971                         isc_uint32_t serial = 0, oldserial;
11972                         unsigned int soacount;
11973
11974                         dns_rdataset_current(rdataset, &rdata);
11975                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
11976                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11977                         serial = soa.serial;
11978                         /*
11979                          * The following should safely be performed without DB
11980                          * lock and succeed in this context.
11981                          */
11982                         result = zone_get_from_db(zone, zone->db, NULL,
11983                                                   &soacount, &oldserial, NULL,
11984                                                   NULL, NULL, NULL, NULL);
11985                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11986                         RUNTIME_CHECK(soacount > 0U);
11987                         if (isc_serial_le(serial, oldserial)) {
11988                                 dns_zone_log(zone,
11989                                              ISC_LOG_INFO,
11990                                              "notify from %s: "
11991                                              "zone is up to date",
11992                                              fromtext);
11993                                 UNLOCK_ZONE(zone);
11994                                 return (ISC_R_SUCCESS);
11995                         }
11996                 }
11997         }
11998
11999         /*
12000          * If we got this far and there was a refresh in progress just
12001          * let it complete.  Record where we got the notify from so we
12002          * can perform a refresh check when the current one completes
12003          */
12004         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
12005                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12006                 zone->notifyfrom = *from;
12007                 UNLOCK_ZONE(zone);
12008                 dns_zone_log(zone, ISC_LOG_INFO,
12009                              "notify from %s: refresh in progress, "
12010                              "refresh check queued",
12011                              fromtext);
12012                 return (ISC_R_SUCCESS);
12013         }
12014         zone->notifyfrom = *from;
12015         local = zone->masteraddr;
12016         remote = zone->sourceaddr;
12017         UNLOCK_ZONE(zone);
12018         dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
12019         dns_zone_refresh(zone);
12020         return (ISC_R_SUCCESS);
12021 }
12022
12023 void
12024 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
12025
12026         REQUIRE(DNS_ZONE_VALID(zone));
12027
12028         LOCK_ZONE(zone);
12029         if (zone->notify_acl != NULL)
12030                 dns_acl_detach(&zone->notify_acl);
12031         dns_acl_attach(acl, &zone->notify_acl);
12032         UNLOCK_ZONE(zone);
12033 }
12034
12035 void
12036 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
12037
12038         REQUIRE(DNS_ZONE_VALID(zone));
12039
12040         LOCK_ZONE(zone);
12041         if (zone->query_acl != NULL)
12042                 dns_acl_detach(&zone->query_acl);
12043         dns_acl_attach(acl, &zone->query_acl);
12044         UNLOCK_ZONE(zone);
12045 }
12046
12047 void
12048 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
12049
12050         REQUIRE(DNS_ZONE_VALID(zone));
12051
12052         LOCK_ZONE(zone);
12053         if (zone->queryon_acl != NULL)
12054                 dns_acl_detach(&zone->queryon_acl);
12055         dns_acl_attach(acl, &zone->queryon_acl);
12056         UNLOCK_ZONE(zone);
12057 }
12058
12059 void
12060 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
12061
12062         REQUIRE(DNS_ZONE_VALID(zone));
12063
12064         LOCK_ZONE(zone);
12065         if (zone->update_acl != NULL)
12066                 dns_acl_detach(&zone->update_acl);
12067         dns_acl_attach(acl, &zone->update_acl);
12068         UNLOCK_ZONE(zone);
12069 }
12070
12071 void
12072 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
12073
12074         REQUIRE(DNS_ZONE_VALID(zone));
12075
12076         LOCK_ZONE(zone);
12077         if (zone->forward_acl != NULL)
12078                 dns_acl_detach(&zone->forward_acl);
12079         dns_acl_attach(acl, &zone->forward_acl);
12080         UNLOCK_ZONE(zone);
12081 }
12082
12083 void
12084 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
12085
12086         REQUIRE(DNS_ZONE_VALID(zone));
12087
12088         LOCK_ZONE(zone);
12089         if (zone->xfr_acl != NULL)
12090                 dns_acl_detach(&zone->xfr_acl);
12091         dns_acl_attach(acl, &zone->xfr_acl);
12092         UNLOCK_ZONE(zone);
12093 }
12094
12095 dns_acl_t *
12096 dns_zone_getnotifyacl(dns_zone_t *zone) {
12097
12098         REQUIRE(DNS_ZONE_VALID(zone));
12099
12100         return (zone->notify_acl);
12101 }
12102
12103 dns_acl_t *
12104 dns_zone_getqueryacl(dns_zone_t *zone) {
12105
12106         REQUIRE(DNS_ZONE_VALID(zone));
12107
12108         return (zone->query_acl);
12109 }
12110
12111 dns_acl_t *
12112 dns_zone_getqueryonacl(dns_zone_t *zone) {
12113
12114         REQUIRE(DNS_ZONE_VALID(zone));
12115
12116         return (zone->queryon_acl);
12117 }
12118
12119 dns_acl_t *
12120 dns_zone_getupdateacl(dns_zone_t *zone) {
12121
12122         REQUIRE(DNS_ZONE_VALID(zone));
12123
12124         return (zone->update_acl);
12125 }
12126
12127 dns_acl_t *
12128 dns_zone_getforwardacl(dns_zone_t *zone) {
12129
12130         REQUIRE(DNS_ZONE_VALID(zone));
12131
12132         return (zone->forward_acl);
12133 }
12134
12135 dns_acl_t *
12136 dns_zone_getxfracl(dns_zone_t *zone) {
12137
12138         REQUIRE(DNS_ZONE_VALID(zone));
12139
12140         return (zone->xfr_acl);
12141 }
12142
12143 void
12144 dns_zone_clearupdateacl(dns_zone_t *zone) {
12145
12146         REQUIRE(DNS_ZONE_VALID(zone));
12147
12148         LOCK_ZONE(zone);
12149         if (zone->update_acl != NULL)
12150                 dns_acl_detach(&zone->update_acl);
12151         UNLOCK_ZONE(zone);
12152 }
12153
12154 void
12155 dns_zone_clearforwardacl(dns_zone_t *zone) {
12156
12157         REQUIRE(DNS_ZONE_VALID(zone));
12158
12159         LOCK_ZONE(zone);
12160         if (zone->forward_acl != NULL)
12161                 dns_acl_detach(&zone->forward_acl);
12162         UNLOCK_ZONE(zone);
12163 }
12164
12165 void
12166 dns_zone_clearnotifyacl(dns_zone_t *zone) {
12167
12168         REQUIRE(DNS_ZONE_VALID(zone));
12169
12170         LOCK_ZONE(zone);
12171         if (zone->notify_acl != NULL)
12172                 dns_acl_detach(&zone->notify_acl);
12173         UNLOCK_ZONE(zone);
12174 }
12175
12176 void
12177 dns_zone_clearqueryacl(dns_zone_t *zone) {
12178
12179         REQUIRE(DNS_ZONE_VALID(zone));
12180
12181         LOCK_ZONE(zone);
12182         if (zone->query_acl != NULL)
12183                 dns_acl_detach(&zone->query_acl);
12184         UNLOCK_ZONE(zone);
12185 }
12186
12187 void
12188 dns_zone_clearqueryonacl(dns_zone_t *zone) {
12189
12190         REQUIRE(DNS_ZONE_VALID(zone));
12191
12192         LOCK_ZONE(zone);
12193         if (zone->queryon_acl != NULL)
12194                 dns_acl_detach(&zone->queryon_acl);
12195         UNLOCK_ZONE(zone);
12196 }
12197
12198 void
12199 dns_zone_clearxfracl(dns_zone_t *zone) {
12200
12201         REQUIRE(DNS_ZONE_VALID(zone));
12202
12203         LOCK_ZONE(zone);
12204         if (zone->xfr_acl != NULL)
12205                 dns_acl_detach(&zone->xfr_acl);
12206         UNLOCK_ZONE(zone);
12207 }
12208
12209 isc_boolean_t
12210 dns_zone_getupdatedisabled(dns_zone_t *zone) {
12211         REQUIRE(DNS_ZONE_VALID(zone));
12212         return (zone->update_disabled);
12213
12214 }
12215
12216 void
12217 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
12218         REQUIRE(DNS_ZONE_VALID(zone));
12219         zone->update_disabled = state;
12220 }
12221
12222 isc_boolean_t
12223 dns_zone_getzeronosoattl(dns_zone_t *zone) {
12224         REQUIRE(DNS_ZONE_VALID(zone));
12225         return (zone->zero_no_soa_ttl);
12226
12227 }
12228
12229 void
12230 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
12231         REQUIRE(DNS_ZONE_VALID(zone));
12232         zone->zero_no_soa_ttl = state;
12233 }
12234
12235 void
12236 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
12237
12238         REQUIRE(DNS_ZONE_VALID(zone));
12239
12240         zone->check_names = severity;
12241 }
12242
12243 dns_severity_t
12244 dns_zone_getchecknames(dns_zone_t *zone) {
12245
12246         REQUIRE(DNS_ZONE_VALID(zone));
12247
12248         return (zone->check_names);
12249 }
12250
12251 void
12252 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
12253
12254         REQUIRE(DNS_ZONE_VALID(zone));
12255
12256         zone->journalsize = size;
12257 }
12258
12259 isc_int32_t
12260 dns_zone_getjournalsize(dns_zone_t *zone) {
12261
12262         REQUIRE(DNS_ZONE_VALID(zone));
12263
12264         return (zone->journalsize);
12265 }
12266
12267 static void
12268 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
12269         isc_result_t result = ISC_R_FAILURE;
12270         isc_buffer_t buffer;
12271
12272         REQUIRE(buf != NULL);
12273         REQUIRE(length > 1U);
12274
12275         /*
12276          * Leave space for terminating '\0'.
12277          */
12278         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12279         if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
12280                 if (dns_name_dynamic(&zone->origin))
12281                         result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12282                 if (result != ISC_R_SUCCESS &&
12283                     isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12284                         isc_buffer_putstr(&buffer, "<UNKNOWN>");
12285
12286                 if (isc_buffer_availablelength(&buffer) > 0)
12287                         isc_buffer_putstr(&buffer, "/");
12288                 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
12289         }
12290
12291         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
12292             strcmp(zone->view->name, "_default") != 0 &&
12293             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
12294                 isc_buffer_putstr(&buffer, "/");
12295                 isc_buffer_putstr(&buffer, zone->view->name);
12296         }
12297         if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
12298                 isc_buffer_putstr(&buffer, " (signed)");
12299         if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
12300                 isc_buffer_putstr(&buffer, " (unsigned)");
12301
12302         buf[isc_buffer_usedlength(&buffer)] = '\0';
12303 }
12304
12305 static void
12306 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
12307         isc_result_t result = ISC_R_FAILURE;
12308         isc_buffer_t buffer;
12309
12310         REQUIRE(buf != NULL);
12311         REQUIRE(length > 1U);
12312
12313         /*
12314          * Leave space for terminating '\0'.
12315          */
12316         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12317         if (dns_name_dynamic(&zone->origin))
12318                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12319         if (result != ISC_R_SUCCESS &&
12320             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12321                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
12322
12323         buf[isc_buffer_usedlength(&buffer)] = '\0';
12324 }
12325
12326 static void
12327 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
12328         isc_buffer_t buffer;
12329
12330         REQUIRE(buf != NULL);
12331         REQUIRE(length > 1U);
12332
12333         /*
12334          * Leave space for terminating '\0'.
12335          */
12336         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12337         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
12338
12339         buf[isc_buffer_usedlength(&buffer)] = '\0';
12340 }
12341
12342 static void
12343 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
12344         isc_buffer_t buffer;
12345
12346         REQUIRE(buf != NULL);
12347         REQUIRE(length > 1U);
12348
12349
12350         /*
12351          * Leave space for terminating '\0'.
12352          */
12353         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12354
12355         if (zone->view == NULL) {
12356                 isc_buffer_putstr(&buffer, "_none");
12357         } else if (strlen(zone->view->name)
12358                    < isc_buffer_availablelength(&buffer)) {
12359                 isc_buffer_putstr(&buffer, zone->view->name);
12360         } else {
12361                 isc_buffer_putstr(&buffer, "_toolong");
12362         }
12363
12364         buf[isc_buffer_usedlength(&buffer)] = '\0';
12365 }
12366
12367 void
12368 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
12369         REQUIRE(DNS_ZONE_VALID(zone));
12370         REQUIRE(buf != NULL);
12371         zone_namerd_tostr(zone, buf, length);
12372 }
12373
12374 static void
12375 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12376         va_list ap;
12377         char message[4096];
12378
12379         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12380                 return;
12381
12382         va_start(ap, fmt);
12383         vsnprintf(message, sizeof(message), fmt, ap);
12384         va_end(ap);
12385         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
12386                       level, "zone %s: %s", zone->strnamerd, message);
12387 }
12388
12389 void
12390 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
12391               int level, const char *fmt, ...) {
12392         va_list ap;
12393         char message[4096];
12394
12395         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12396                 return;
12397
12398         va_start(ap, fmt);
12399         vsnprintf(message, sizeof(message), fmt, ap);
12400         va_end(ap);
12401         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
12402                       level, "%s%s: %s", (zone->type == dns_zone_key) ?
12403                       "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12404                       "redirect-zone" : "zone ", zone->strnamerd, message);
12405 }
12406
12407 void
12408 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12409         va_list ap;
12410         char message[4096];
12411
12412         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12413                 return;
12414
12415         va_start(ap, fmt);
12416         vsnprintf(message, sizeof(message), fmt, ap);
12417         va_end(ap);
12418         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12419                       level, "%s%s: %s", (zone->type == dns_zone_key) ?
12420                       "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12421                       "redirect-zone" : "zone ", zone->strnamerd, message);
12422 }
12423
12424 static void
12425 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
12426               const char *fmt, ...)
12427 {
12428         va_list ap;
12429         char message[4096];
12430         int level = ISC_LOG_DEBUG(debuglevel);
12431         const char *zstr;
12432
12433         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12434                 return;
12435
12436         va_start(ap, fmt);
12437         vsnprintf(message, sizeof(message), fmt, ap);
12438         va_end(ap);
12439
12440         switch (zone->type) {
12441         case dns_zone_key:
12442                 zstr = "managed-keys-zone";
12443                 break;
12444         case dns_zone_redirect:
12445                 zstr = "redirect-zone";
12446                 break;
12447         default:
12448                 zstr = "zone";
12449         }
12450
12451         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12452                       level, "%s: %s %s: %s", me, zstr, zone->strnamerd,
12453                       message);
12454 }
12455
12456 static int
12457 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
12458 {
12459         isc_result_t result;
12460         dns_name_t *name;
12461         dns_rdataset_t *curr;
12462         int count = 0;
12463
12464         result = dns_message_firstname(msg, section);
12465         while (result == ISC_R_SUCCESS) {
12466                 name = NULL;
12467                 dns_message_currentname(msg, section, &name);
12468
12469                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
12470                      curr = ISC_LIST_PREV(curr, link)) {
12471                         if (curr->type == type)
12472                                 count++;
12473                 }
12474                 result = dns_message_nextname(msg, section);
12475         }
12476
12477         return (count);
12478 }
12479
12480 void
12481 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
12482         REQUIRE(DNS_ZONE_VALID(zone));
12483
12484         zone->maxxfrin = maxxfrin;
12485 }
12486
12487 isc_uint32_t
12488 dns_zone_getmaxxfrin(dns_zone_t *zone) {
12489         REQUIRE(DNS_ZONE_VALID(zone));
12490
12491         return (zone->maxxfrin);
12492 }
12493
12494 void
12495 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
12496         REQUIRE(DNS_ZONE_VALID(zone));
12497         zone->maxxfrout = maxxfrout;
12498 }
12499
12500 isc_uint32_t
12501 dns_zone_getmaxxfrout(dns_zone_t *zone) {
12502         REQUIRE(DNS_ZONE_VALID(zone));
12503
12504         return (zone->maxxfrout);
12505 }
12506
12507 dns_zonetype_t
12508 dns_zone_gettype(dns_zone_t *zone) {
12509         REQUIRE(DNS_ZONE_VALID(zone));
12510
12511         return (zone->type);
12512 }
12513
12514 dns_name_t *
12515 dns_zone_getorigin(dns_zone_t *zone) {
12516         REQUIRE(DNS_ZONE_VALID(zone));
12517
12518         return (&zone->origin);
12519 }
12520
12521 void
12522 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
12523         REQUIRE(DNS_ZONE_VALID(zone));
12524
12525         LOCK_ZONE(zone);
12526         if (zone->task != NULL)
12527                 isc_task_detach(&zone->task);
12528         isc_task_attach(task, &zone->task);
12529         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12530         if (zone->db != NULL)
12531                 dns_db_settask(zone->db, zone->task);
12532         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12533         UNLOCK_ZONE(zone);
12534 }
12535
12536 void
12537 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
12538         REQUIRE(DNS_ZONE_VALID(zone));
12539         isc_task_attach(zone->task, target);
12540 }
12541
12542 void
12543 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
12544         REQUIRE(DNS_ZONE_VALID(zone));
12545
12546         if (idlein == 0)
12547                 idlein = DNS_DEFAULT_IDLEIN;
12548         zone->idlein = idlein;
12549 }
12550
12551 isc_uint32_t
12552 dns_zone_getidlein(dns_zone_t *zone) {
12553         REQUIRE(DNS_ZONE_VALID(zone));
12554
12555         return (zone->idlein);
12556 }
12557
12558 void
12559 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
12560         REQUIRE(DNS_ZONE_VALID(zone));
12561
12562         zone->idleout = idleout;
12563 }
12564
12565 isc_uint32_t
12566 dns_zone_getidleout(dns_zone_t *zone) {
12567         REQUIRE(DNS_ZONE_VALID(zone));
12568
12569         return (zone->idleout);
12570 }
12571
12572 static void
12573 notify_done(isc_task_t *task, isc_event_t *event) {
12574         dns_requestevent_t *revent = (dns_requestevent_t *)event;
12575         dns_notify_t *notify;
12576         isc_result_t result;
12577         dns_message_t *message = NULL;
12578         isc_buffer_t buf;
12579         char rcode[128];
12580         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12581
12582         UNUSED(task);
12583
12584         notify = event->ev_arg;
12585         REQUIRE(DNS_NOTIFY_VALID(notify));
12586         INSIST(task == notify->zone->task);
12587
12588         isc_buffer_init(&buf, rcode, sizeof(rcode));
12589         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12590
12591         result = revent->result;
12592         if (result == ISC_R_SUCCESS)
12593                 result = dns_message_create(notify->zone->mctx,
12594                                             DNS_MESSAGE_INTENTPARSE, &message);
12595         if (result == ISC_R_SUCCESS)
12596                 result = dns_request_getresponse(revent->request, message,
12597                                         DNS_MESSAGEPARSE_PRESERVEORDER);
12598         if (result == ISC_R_SUCCESS)
12599                 result = dns_rcode_totext(message->rcode, &buf);
12600         if (result == ISC_R_SUCCESS)
12601                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12602                            "notify response from %s: %.*s",
12603                            addrbuf, (int)buf.used, rcode);
12604         else
12605                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
12606                            "notify to %s failed: %s", addrbuf,
12607                            dns_result_totext(result));
12608
12609         /*
12610          * Old bind's return formerr if they see a soa record.  Retry w/o
12611          * the soa if we see a formerr and had sent a SOA.
12612          */
12613         isc_event_free(&event);
12614         if (message != NULL && message->rcode == dns_rcode_formerr &&
12615             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
12616                 notify->flags |= DNS_NOTIFY_NOSOA;
12617                 dns_request_destroy(&notify->request);
12618                 result = notify_send_queue(notify);
12619                 if (result != ISC_R_SUCCESS)
12620                         notify_destroy(notify, ISC_FALSE);
12621         } else {
12622                 if (result == ISC_R_TIMEDOUT)
12623                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
12624                                    "notify to %s: retries exceeded", addrbuf);
12625                 notify_destroy(notify, ISC_FALSE);
12626         }
12627         if (message != NULL)
12628                 dns_message_destroy(&message);
12629 }
12630
12631 struct secure_event {
12632         isc_event_t e;
12633         dns_db_t *db;
12634         isc_uint32_t serial;
12635 };
12636
12637 static void
12638 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
12639         UNUSED(arg);
12640         dns_zone_log(zone, level, "%s", message);
12641 }
12642
12643 static isc_result_t
12644 sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal,
12645                     isc_uint32_t start, isc_uint32_t end,
12646                     dns_difftuple_t **soatuplep, dns_diff_t *diff)
12647 {
12648         isc_result_t result;
12649         dns_difftuple_t *tuple = NULL;
12650         dns_diffop_t op = DNS_DIFFOP_ADD;
12651         int n_soa = 0;
12652
12653         REQUIRE(soatuplep != NULL);
12654
12655         if (start == end)
12656                 return (DNS_R_UNCHANGED);
12657
12658         CHECK(dns_journal_iter_init(journal, start, end));
12659         for (result = dns_journal_first_rr(journal);
12660              result == ISC_R_SUCCESS;
12661              result = dns_journal_next_rr(journal))
12662         {
12663                 dns_name_t *name = NULL;
12664                 isc_uint32_t ttl;
12665                 dns_rdata_t *rdata = NULL;
12666                 dns_journal_current_rr(journal, &name, &ttl, &rdata);
12667
12668                 if (rdata->type == dns_rdatatype_soa) {
12669                         n_soa++;
12670                         if (n_soa == 2) {
12671                                 /*
12672                                  * Save the latest raw SOA record.
12673                                  */
12674                                 if (*soatuplep != NULL)
12675                                         dns_difftuple_free(soatuplep);
12676                                 CHECK(dns_difftuple_create(diff->mctx,
12677                                                            DNS_DIFFOP_ADD,
12678                                                            name, ttl, rdata,
12679                                                            soatuplep));
12680                         }
12681                         if (n_soa == 3)
12682                                 n_soa = 1;
12683                         continue;
12684                 }
12685
12686                 /* Sanity. */
12687                 if (n_soa == 0) {
12688                         dns_zone_log(zone->raw, ISC_LOG_ERROR,
12689                                      "corrupt journal file: '%s'\n",
12690                                      zone->raw->journal);
12691                         return (ISC_R_FAILURE);
12692                 }
12693
12694                 if (zone->privatetype != 0 &&
12695                     rdata->type == zone->privatetype)
12696                         continue;
12697
12698                 if (rdata->type == dns_rdatatype_nsec ||
12699                     rdata->type == dns_rdatatype_rrsig ||
12700                     rdata->type == dns_rdatatype_nsec3 ||
12701                     rdata->type == dns_rdatatype_dnskey ||
12702                     rdata->type == dns_rdatatype_nsec3param)
12703                         continue;
12704
12705                 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
12706
12707                 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
12708                                            &tuple));
12709                 dns_diff_appendminimal(diff, &tuple);
12710         }
12711         if (result == ISC_R_NOMORE)
12712                 result = ISC_R_SUCCESS;
12713
12714  failure:
12715         return(result);
12716 }
12717
12718 static isc_result_t
12719 sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb,
12720                dns_dbversion_t *secver, dns_difftuple_t **soatuple,
12721                dns_diff_t *diff)
12722 {
12723         isc_result_t result;
12724         dns_db_t *rawdb = NULL;
12725         dns_dbversion_t *rawver = NULL;
12726         dns_difftuple_t *tuple = NULL, *next;
12727         dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
12728         dns_rdata_soa_t oldsoa, newsoa;
12729
12730         REQUIRE(DNS_ZONE_VALID(seczone));
12731         REQUIRE(inline_secure(seczone));
12732         REQUIRE(soatuple != NULL && *soatuple == NULL);
12733
12734         if (!seczone->sourceserialset)
12735                 return (DNS_R_UNCHANGED);
12736
12737         dns_db_attach(seczone->raw->db, &rawdb);
12738         dns_db_currentversion(rawdb, &rawver);
12739         result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
12740         dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
12741         dns_db_detach(&rawdb);
12742
12743         if (result != ISC_R_SUCCESS)
12744                 return (result);
12745
12746         for (tuple = ISC_LIST_HEAD(diff->tuples);
12747              tuple != NULL;
12748              tuple = next)
12749         {
12750                 next = ISC_LIST_NEXT(tuple, link);
12751                 if (tuple->rdata.type == dns_rdatatype_nsec ||
12752                     tuple->rdata.type == dns_rdatatype_rrsig ||
12753                     tuple->rdata.type == dns_rdatatype_dnskey ||
12754                     tuple->rdata.type == dns_rdatatype_nsec3 ||
12755                     tuple->rdata.type == dns_rdatatype_nsec3param)
12756                 {
12757                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
12758                         dns_difftuple_free(&tuple);
12759                         continue;
12760                 }
12761                 if (tuple->rdata.type == dns_rdatatype_soa) {
12762                         if (tuple->op == DNS_DIFFOP_DEL) {
12763                                 INSIST(oldtuple == NULL);
12764                                 oldtuple = tuple;
12765                         }
12766                         if (tuple->op == DNS_DIFFOP_ADD) {
12767                                 INSIST(newtuple == NULL);
12768                                 newtuple = tuple;
12769                         }
12770                 }
12771         }
12772
12773         if (oldtuple != NULL && newtuple != NULL) {
12774
12775                 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
12776                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12777
12778                 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
12779                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12780
12781                 /*
12782                  * If the SOA records are the same except for the serial
12783                  * remove them from the diff.
12784                  */
12785                 if (oldsoa.refresh == newsoa.refresh &&
12786                     oldsoa.retry == newsoa.retry &&
12787                     oldsoa.minimum == newsoa.minimum &&
12788                     oldsoa.expire == newsoa.expire &&
12789                     dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
12790                     dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
12791                         ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12792                         dns_difftuple_free(&oldtuple);
12793                         ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12794                         dns_difftuple_free(&newtuple);
12795                 }
12796         }
12797
12798         if (ISC_LIST_EMPTY(diff->tuples))
12799                 return (DNS_R_UNCHANGED);
12800
12801         /*
12802          * If there are still SOA records in the diff they can now be removed
12803          * saving the new SOA record.
12804          */
12805         if (oldtuple != NULL) {
12806                 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12807                 dns_difftuple_free(&oldtuple);
12808         }
12809
12810         if (newtuple != NULL) {
12811                 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12812                 *soatuple = newtuple;
12813         }
12814
12815         return (ISC_R_SUCCESS);
12816 }
12817
12818 static void
12819 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
12820         static char me[] = "receive_secure_serial";
12821         isc_result_t result;
12822         dns_journal_t *rjournal = NULL;
12823         isc_uint32_t start, end;
12824         dns_zone_t *zone;
12825         dns_db_t *db = NULL;
12826         dns_dbversion_t *newver = NULL, *oldver = NULL;
12827         dns_diff_t diff;
12828         dns_difftuple_t *tuple = NULL, *soatuple = NULL;
12829         dns_update_log_t log = { update_log_cb, NULL };
12830         isc_time_t timenow;
12831
12832         zone = event->ev_arg;
12833         end = ((struct secure_event *)event)->serial;
12834         isc_event_free(&event);
12835
12836         ENTER;
12837
12838         LOCK_ZONE(zone);
12839
12840         dns_diff_init(zone->mctx, &diff);
12841
12842         UNUSED(task);
12843
12844         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12845         if (zone->db != NULL)
12846                 dns_db_attach(zone->db, &db);
12847         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12848
12849         /*
12850          * zone->db may be NULL if the load from disk failed.
12851          */
12852         if (db == NULL || !inline_secure(zone)) {
12853                 result = ISC_R_FAILURE;
12854                 goto failure;
12855         }
12856
12857         /*
12858          * We first attempt to sync the raw zone to the secure zone
12859          * by using the raw zone's journal, applying all the deltas
12860          * from the latest source-serial of the secure zone up to
12861          * the current serial number of the raw zone.
12862          *
12863          * If that fails, then we'll fall back to a direct comparison
12864          * between raw and secure zones.
12865          */
12866         result = dns_journal_open(zone->raw->mctx, zone->raw->journal,
12867                                   DNS_JOURNAL_WRITE, &rjournal);
12868         if (result != ISC_R_SUCCESS)
12869                 goto failure;
12870         else {
12871                 dns_journal_t *sjournal = NULL;
12872
12873                 result = dns_journal_open(zone->mctx, zone->journal,
12874                                           DNS_JOURNAL_READ, &sjournal);
12875                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
12876                         goto failure;
12877
12878                 if (!dns_journal_get_sourceserial(rjournal, &start)) {
12879                         start = dns_journal_first_serial(rjournal);
12880                         dns_journal_set_sourceserial(rjournal, start);
12881                 }
12882                 if (sjournal != NULL) {
12883                         isc_uint32_t serial;
12884                         /*
12885                          * We read the secure journal first, if that exists
12886                          * use its value provided it is greater that from the
12887                          * raw journal.
12888                          */
12889                         if (dns_journal_get_sourceserial(sjournal, &serial)) {
12890                                 if (isc_serial_gt(serial, start))
12891                                         start = serial;
12892                         }
12893                         dns_journal_destroy(&sjournal);
12894                 }
12895         }
12896
12897         dns_db_currentversion(db, &oldver);
12898         CHECK(dns_db_newversion(db, &newver));
12899
12900         /*
12901          * Try to apply diffs from the raw zone's journal to the secure
12902          * zone.  If that fails, we recover by syncing up the databases
12903          * directly.
12904          */
12905         result = sync_secure_journal(zone, rjournal, start, end,
12906                                      &soatuple, &diff);
12907         if (result == DNS_R_UNCHANGED)
12908                 goto failure;
12909         else if (result != ISC_R_SUCCESS)
12910                 CHECK(sync_secure_db(zone, db, oldver, &soatuple, &diff));
12911
12912         CHECK(dns_diff_apply(&diff, db, newver));
12913
12914         if (soatuple != NULL) {
12915                 isc_uint32_t oldserial, newserial, desired;
12916
12917                 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
12918                                             DNS_DIFFOP_DEL, &tuple));
12919                 oldserial = dns_soa_getserial(&tuple->rdata);
12920                 newserial = desired = dns_soa_getserial(&soatuple->rdata);
12921                 if (!isc_serial_gt(newserial, oldserial)) {
12922                         newserial = oldserial + 1;
12923                         if (newserial == 0)
12924                                 newserial++;
12925                         dns_soa_setserial(newserial, &soatuple->rdata);
12926                 }
12927                 CHECK(do_one_tuple(&tuple, db, newver, &diff));
12928                 CHECK(do_one_tuple(&soatuple, db, newver, &diff));
12929                 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
12930                              newserial, desired);
12931         } else
12932                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
12933                                         zone->updatemethod));
12934
12935         CHECK(dns_update_signatures(&log, zone, db, oldver, newver,
12936                                     &diff, zone->sigvalidityinterval));
12937
12938         CHECK(zone_journal(zone, &diff, &end, "receive_secure_serial"));
12939
12940         dns_journal_set_sourceserial(rjournal, end);
12941         dns_journal_commit(rjournal);
12942
12943         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12944
12945         zone->sourceserial = end;
12946         zone->sourceserialset = ISC_TRUE;
12947         zone_needdump(zone, DNS_DUMP_DELAY);
12948
12949         TIME_NOW(&timenow);
12950         zone_settimer(zone, &timenow);
12951
12952         dns_db_closeversion(db, &oldver, ISC_FALSE);
12953         dns_db_closeversion(db, &newver, ISC_TRUE);
12954
12955  failure:
12956         UNLOCK_ZONE(zone);
12957         if (result != ISC_R_SUCCESS)
12958                 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
12959                              dns_result_totext(result));
12960         if (tuple != NULL)
12961                 dns_difftuple_free(&tuple);
12962         if (soatuple != NULL)
12963                 dns_difftuple_free(&soatuple);
12964         if (db != NULL) {
12965                 if (oldver != NULL)
12966                         dns_db_closeversion(db, &oldver, ISC_FALSE);
12967                 if (newver != NULL)
12968                         dns_db_closeversion(db, &newver, ISC_FALSE);
12969                 dns_db_detach(&db);
12970         }
12971         if (rjournal != NULL)
12972                 dns_journal_destroy(&rjournal);
12973         dns_diff_clear(&diff);
12974         dns_zone_idetach(&zone);
12975 }
12976
12977 static isc_result_t
12978 zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) {
12979         isc_event_t *e;
12980         dns_zone_t *dummy = NULL;
12981
12982         e = isc_event_allocate(zone->secure->mctx, zone,
12983                                DNS_EVENT_ZONESECURESERIAL,
12984                                receive_secure_serial, zone->secure,
12985                                sizeof(struct secure_event));
12986         if (e == NULL)
12987                 return (ISC_R_NOMEMORY);
12988         ((struct secure_event *)e)->serial = serial;
12989         INSIST(LOCKED_ZONE(zone->secure));
12990         zone_iattach(zone->secure, &dummy);
12991         isc_task_send(zone->secure->task, &e);
12992
12993         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
12994         return (ISC_R_SUCCESS);
12995 }
12996
12997 static isc_result_t
12998 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
12999                dns_rdataset_t *rdataset, isc_uint32_t oldserial)
13000 {
13001         dns_rdata_soa_t soa;
13002         dns_rdata_t rdata = DNS_RDATA_INIT;
13003         dns_rdatalist_t temprdatalist;
13004         dns_rdataset_t temprdataset;
13005         isc_buffer_t b;
13006         isc_result_t result;
13007         unsigned char buf[DNS_SOA_BUFFERSIZE];
13008
13009         result = dns_rdataset_first(rdataset);
13010         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13011         dns_rdataset_current(rdataset, &rdata);
13012         result = dns_rdata_tostruct(&rdata, &soa, NULL);
13013         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13014
13015         if (isc_serial_gt(soa.serial, oldserial))
13016                 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
13017                                            NULL));
13018         /*
13019          * Always bump the serial.
13020          */
13021         oldserial++;
13022         if (oldserial == 0)
13023                 oldserial++;
13024         soa.serial = oldserial;
13025
13026         /*
13027          * Construct a replacement rdataset.
13028          */
13029         dns_rdata_reset(&rdata);
13030         isc_buffer_init(&b, buf, sizeof(buf));
13031         result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
13032                                       dns_rdatatype_soa, &soa, &b);
13033         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13034         temprdatalist.rdclass = rdata.rdclass;
13035         temprdatalist.type = rdata.type;
13036         temprdatalist.covers = 0;
13037         temprdatalist.ttl = rdataset->ttl;
13038         ISC_LIST_INIT(temprdatalist.rdata);
13039         ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
13040
13041         dns_rdataset_init(&temprdataset);
13042         result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
13043         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13044         return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
13045                                    0, NULL));
13046 }
13047
13048 /*
13049  * This function should populate an nsec3paramlist_t with the
13050  * nsecparam_t data from a zone.
13051  */
13052 static isc_result_t
13053 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
13054         isc_result_t result;
13055         dns_dbnode_t *node = NULL;
13056         dns_rdataset_t rdataset, prdataset;
13057         dns_rdata_t rdata_in, prdata_in, prdata_out;
13058         dns_dbversion_t *version = NULL;
13059         nsec3param_t *nsec3param = NULL;
13060         nsec3param_t *nsec3p = NULL;
13061         nsec3param_t *next;
13062         dns_db_t *db = NULL;
13063         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
13064
13065         REQUIRE(DNS_ZONE_VALID(zone));
13066         REQUIRE(nsec3list != NULL);
13067         REQUIRE(ISC_LIST_EMPTY(*nsec3list));
13068
13069         dns_db_attach(zone->db, &db);
13070         CHECK(dns_db_getoriginnode(db, &node));
13071
13072         dns_rdataset_init(&rdataset);
13073         dns_db_currentversion(db, &version);
13074         result = dns_db_findrdataset(db, node, version,
13075                                      dns_rdatatype_nsec3param,
13076                                      dns_rdatatype_none, 0, &rdataset, NULL);
13077
13078         if (result != ISC_R_SUCCESS)
13079                 goto getprivate;
13080
13081         /*
13082          * walk nsec3param rdataset making a list of parameters (note that
13083          * multiple simultaneous nsec3 chains are annoyingly legal -- this
13084          * is why we use an nsec3list, even tho we will usually only have
13085          * one)
13086          */
13087         for (result = dns_rdataset_first(&rdataset);
13088              result == ISC_R_SUCCESS;
13089              result = dns_rdataset_next(&rdataset))
13090         {
13091                 dns_rdata_init(&rdata_in);
13092                 dns_rdataset_current(&rdataset, &rdata_in);
13093                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13094                               DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13095                               "looping through nsec3param data");
13096                 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13097                 if (nsec3param == NULL)
13098                         CHECK(ISC_R_NOMEMORY);
13099                 ISC_LINK_INIT(nsec3param, link);
13100
13101                 /*
13102                  * now transfer the data from the rdata to
13103                  * the nsec3param
13104                  */
13105                 dns_rdata_init(&prdata_out);
13106                 dns_nsec3param_toprivate(&rdata_in, &prdata_out,
13107                                          zone->privatetype, nsec3param->data,
13108                                          sizeof(nsec3param->data));
13109                 nsec3param->length = prdata_out.length;
13110                 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13111         }
13112
13113  getprivate:
13114         dns_rdataset_init(&prdataset);
13115         result = dns_db_findrdataset(db, node, version, zone->privatetype,
13116                                      dns_rdatatype_none, 0, &prdataset, NULL);
13117         if (result != ISC_R_SUCCESS)
13118                 goto done;
13119
13120         /*
13121          * walk private type records, converting them to nsec3 parameters
13122          * using dns_nsec3param_fromprivate(), do the right thing based on
13123          * CREATE and REMOVE flags
13124          */
13125         for (result = dns_rdataset_first(&prdataset);
13126              result == ISC_R_SUCCESS;
13127              result = dns_rdataset_next(&prdataset))
13128         {
13129                 dns_rdata_init(&prdata_in);
13130                 dns_rdataset_current(&prdataset, &prdata_in);
13131                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13132                               DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13133                               "looping through nsec3param private data");
13134
13135                 if (!dns_nsec3param_fromprivate(&prdata_in, &prdata_out,
13136                                                 buf, sizeof(buf)))
13137                         continue;
13138
13139                 if ((prdata_out.data[1] & DNS_NSEC3FLAG_REMOVE) !=0) {
13140                         prdata_out.data[1] = 0;
13141
13142                         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13143                              nsec3p != NULL;
13144                              nsec3p = next)
13145                         {
13146                                 next = ISC_LIST_NEXT(nsec3p, link);
13147                                 if (memcmp(prdata_out.data, nsec3p->data,
13148                                     sizeof(nsec3p->data)) == 0) {
13149                                         ISC_LIST_UNLINK(*nsec3list,
13150                                                         nsec3p, link);
13151                                         isc_mem_put(zone->mctx, nsec3p,
13152                                                     sizeof(nsec3param_t));
13153                                 }
13154                         }
13155                         continue;
13156                 }
13157
13158                 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13159                 if (nsec3param == NULL)
13160                         CHECK(ISC_R_NOMEMORY);
13161                 ISC_LINK_INIT(nsec3param, link);
13162
13163                 dns_rdata_init(&prdata_out);
13164                 dns_nsec3param_toprivate(&prdata_in, &prdata_out,
13165                         zone->privatetype, nsec3param->data,
13166                         sizeof(nsec3param->data));
13167                 nsec3param->length = prdata_out.length;
13168                 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13169         }
13170
13171  done:
13172         if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
13173                 result = ISC_R_SUCCESS;
13174
13175  failure:
13176         if (node != NULL)
13177                 dns_db_detachnode(db, &node);
13178         if (version != NULL)
13179                 dns_db_closeversion(db, &version, ISC_FALSE);
13180         if (db != NULL)
13181                 dns_db_detach(&db);
13182         if (dns_rdataset_isassociated(&rdataset))
13183                 dns_rdataset_disassociate(&rdataset);
13184         if (dns_rdataset_isassociated(&prdataset))
13185                 dns_rdataset_disassociate(&prdataset);
13186         return (result);
13187 }
13188
13189 /*
13190  * Walk the list of the nsec3 chains desired for the zone, converting
13191  * parameters to private type records using dns_nsec3param_toprivate(),
13192  * and insert them into the new zone db.
13193  */
13194 static isc_result_t
13195 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
13196                    nsec3paramlist_t *nsec3list)
13197 {
13198         isc_result_t result;
13199         dns_diff_t diff;
13200         dns_rdata_t rdata;
13201         nsec3param_t *nsec3p = NULL;
13202         nsec3param_t *next;
13203
13204         REQUIRE(DNS_ZONE_VALID(zone));
13205         REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
13206
13207         dns_diff_init(zone->mctx, &diff);
13208
13209         /*
13210          * Loop through the list of private-type records, set the INITIAL
13211          * and CREATE flags, and the add the record to the apex of the tree
13212          * in db.
13213          */
13214         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13215              nsec3p != NULL;
13216              nsec3p = next)
13217         {
13218                 next = ISC_LIST_NEXT(nsec3p, link);
13219                 dns_rdata_init(&rdata);
13220                 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
13221                 rdata.length = nsec3p->length;
13222                 rdata.data = nsec3p->data;
13223                 rdata.type = zone->privatetype;
13224                 rdata.rdclass = zone->rdclass;
13225                 CHECK(update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
13226                                     &zone->origin, 0, &rdata));
13227         }
13228
13229         result = ISC_R_SUCCESS;
13230
13231 failure:
13232         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13233              nsec3p != NULL;
13234              nsec3p = next)
13235         {
13236                 next = ISC_LIST_NEXT(nsec3p, link);
13237                 ISC_LIST_UNLINK(*nsec3list, nsec3p, link);
13238                 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
13239         }
13240
13241         dns_diff_clear(&diff);
13242         return (result);
13243 }
13244
13245 static void
13246 receive_secure_db(isc_task_t *task, isc_event_t *event) {
13247         isc_result_t result;
13248         dns_zone_t *zone;
13249         dns_db_t *rawdb, *db = NULL;
13250         dns_dbnode_t *rawnode = NULL, *node = NULL;
13251         dns_fixedname_t fname;
13252         dns_name_t *name;
13253         dns_dbiterator_t *dbiterator = NULL;
13254         dns_rdatasetiter_t *rdsit = NULL;
13255         dns_rdataset_t rdataset;
13256         dns_dbversion_t *version = NULL;
13257         isc_time_t loadtime;
13258         unsigned int oldserial = 0;
13259         isc_boolean_t have_oldserial = ISC_FALSE;
13260         nsec3paramlist_t nsec3list;
13261
13262         UNUSED(task);
13263
13264         ISC_LIST_INIT(nsec3list);
13265
13266         zone = event->ev_arg;
13267         rawdb = ((struct secure_event *)event)->db;
13268         isc_event_free(&event);
13269
13270         dns_fixedname_init(&fname);
13271         name = dns_fixedname_name(&fname);
13272         dns_rdataset_init(&rdataset);
13273
13274         LOCK_ZONE(zone);
13275         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
13276                 result = ISC_R_SHUTTINGDOWN;
13277                 goto failure;
13278         }
13279
13280         TIME_NOW(&loadtime);
13281         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13282         if (zone->db != NULL) {
13283                 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
13284                 if (result == ISC_R_SUCCESS)
13285                         have_oldserial = ISC_TRUE;
13286
13287                 /*
13288                  * assemble nsec3parameters from the old zone, and set a flag
13289                  * if any are found
13290                  */
13291                 result = save_nsec3param(zone, &nsec3list);
13292                 if (result != ISC_R_SUCCESS) {
13293                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13294                         goto failure;
13295                 }
13296         }
13297         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13298
13299         result = dns_db_create(zone->mctx, zone->db_argv[0],
13300                                &zone->origin, dns_dbtype_zone, zone->rdclass,
13301                                zone->db_argc - 1, zone->db_argv + 1, &db);
13302         if (result != ISC_R_SUCCESS)
13303                 goto failure;
13304
13305         result = dns_db_newversion(db, &version);
13306         if (result != ISC_R_SUCCESS)
13307                 goto failure;
13308
13309         result = dns_db_createiterator(rawdb, 0, &dbiterator);
13310         if (result != ISC_R_SUCCESS)
13311                 goto failure;
13312
13313         for (result = dns_dbiterator_first(dbiterator);
13314              result == ISC_R_SUCCESS;
13315              result = dns_dbiterator_next(dbiterator)) {
13316                 result = dns_dbiterator_current(dbiterator, &rawnode, name);
13317                 if (result != ISC_R_SUCCESS)
13318                         continue;
13319
13320                 result = dns_db_findnode(db, name, ISC_TRUE, &node);
13321                 if (result != ISC_R_SUCCESS)
13322                         goto failure;
13323
13324                 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
13325                 if (result != ISC_R_SUCCESS)
13326                         goto failure;
13327
13328                 for (result = dns_rdatasetiter_first(rdsit);
13329                      result == ISC_R_SUCCESS;
13330                      result = dns_rdatasetiter_next(rdsit)) {
13331                         dns_rdatasetiter_current(rdsit, &rdataset);
13332                         if (rdataset.type == dns_rdatatype_nsec ||
13333                             rdataset.type == dns_rdatatype_rrsig ||
13334                             rdataset.type == dns_rdatatype_nsec3 ||
13335                             rdataset.type == dns_rdatatype_dnskey ||
13336                             rdataset.type == dns_rdatatype_nsec3param) {
13337                                 dns_rdataset_disassociate(&rdataset);
13338                                 continue;
13339                         }
13340                         if (rdataset.type == dns_rdatatype_soa &&
13341                             have_oldserial) {
13342                                 result = checkandaddsoa(db, node, version,
13343                                                         &rdataset, oldserial);
13344                         } else
13345                                 result = dns_db_addrdataset(db, node, version,
13346                                                             0, &rdataset, 0,
13347                                                             NULL);
13348                         if (result != ISC_R_SUCCESS)
13349                                 goto failure;
13350
13351                         dns_rdataset_disassociate(&rdataset);
13352                 }
13353                 dns_rdatasetiter_destroy(&rdsit);
13354                 dns_db_detachnode(rawdb, &rawnode);
13355                 dns_db_detachnode(db, &node);
13356         }
13357
13358         /*
13359          * Call restore_nsec3param() to create private-type records from
13360          * the old nsec3 parameters and insert them into db
13361          */
13362         if (!ISC_LIST_EMPTY(nsec3list))
13363                 restore_nsec3param(zone, db, version, &nsec3list);
13364
13365         dns_db_closeversion(db, &version, ISC_TRUE);
13366
13367         /*
13368          * Lock hierarchy: zmgr, zone, raw.
13369          */
13370         INSIST(zone != zone->raw);
13371         LOCK_ZONE(zone->raw);
13372         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13373         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
13374         zone_needdump(zone, 0); /* XXXMPA */
13375         UNLOCK_ZONE(zone->raw);
13376
13377  failure:
13378         UNLOCK_ZONE(zone);
13379         if (result != ISC_R_SUCCESS)
13380                 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
13381                              dns_result_totext(result));
13382
13383         if (dns_rdataset_isassociated(&rdataset))
13384                 dns_rdataset_disassociate(&rdataset);
13385         if (db != NULL) {
13386                 if (node != NULL)
13387                         dns_db_detachnode(db, &node);
13388                 dns_db_detach(&db);
13389         }
13390         if (rawnode != NULL)
13391                 dns_db_detachnode(rawdb, &rawnode);
13392         dns_db_detach(&rawdb);
13393         if (dbiterator != NULL)
13394                 dns_dbiterator_destroy(&dbiterator);
13395         dns_zone_idetach(&zone);
13396 }
13397
13398 static isc_result_t
13399 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
13400         isc_event_t *e;
13401         dns_db_t *dummy = NULL;
13402         dns_zone_t *secure = NULL;
13403
13404         e = isc_event_allocate(zone->secure->mctx, zone,
13405                                DNS_EVENT_ZONESECUREDB,
13406                                receive_secure_db, zone->secure,
13407                                sizeof(struct secure_event));
13408         if (e == NULL)
13409                 return (ISC_R_NOMEMORY);
13410         dns_db_attach(db, &dummy);
13411         ((struct secure_event *)e)->db = dummy;
13412         INSIST(LOCKED_ZONE(zone->secure));
13413         zone_iattach(zone->secure, &secure);
13414         isc_task_send(zone->secure->task, &e);
13415         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
13416         return (ISC_R_SUCCESS);
13417 }
13418
13419 isc_result_t
13420 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13421         isc_result_t result;
13422         dns_zone_t *secure = NULL;
13423
13424         REQUIRE(DNS_ZONE_VALID(zone));
13425  again:
13426         LOCK_ZONE(zone);
13427         if (inline_raw(zone)) {
13428                 secure = zone->secure;
13429                 INSIST(secure != zone);
13430                 TRYLOCK_ZONE(result, secure);
13431                 if (result != ISC_R_SUCCESS) {
13432                         UNLOCK_ZONE(zone);
13433                         secure = NULL;
13434 #if ISC_PLATFORM_USETHREADS
13435                         isc_thread_yield();
13436 #endif
13437                         goto again;
13438                 }
13439         }
13440         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13441         result = zone_replacedb(zone, db, dump);
13442         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13443         if (secure != NULL)
13444                 UNLOCK_ZONE(secure);
13445         UNLOCK_ZONE(zone);
13446         return (result);
13447 }
13448
13449 static isc_result_t
13450 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13451         dns_dbversion_t *ver;
13452         isc_result_t result;
13453         unsigned int soacount = 0;
13454         unsigned int nscount = 0;
13455
13456         /*
13457          * 'zone' and 'zonedb' locked by caller.
13458          */
13459         REQUIRE(DNS_ZONE_VALID(zone));
13460         REQUIRE(LOCKED_ZONE(zone));
13461         if (inline_raw(zone))
13462                 REQUIRE(LOCKED_ZONE(zone->secure));
13463
13464         result = zone_get_from_db(zone, db, &nscount, &soacount,
13465                                   NULL, NULL, NULL, NULL, NULL, NULL);
13466         if (result == ISC_R_SUCCESS) {
13467                 if (soacount != 1) {
13468                         dns_zone_log(zone, ISC_LOG_ERROR,
13469                                      "has %d SOA records", soacount);
13470                         result = DNS_R_BADZONE;
13471                 }
13472                 if (nscount == 0 && zone->type != dns_zone_key) {
13473                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
13474                         result = DNS_R_BADZONE;
13475                 }
13476                 if (result != ISC_R_SUCCESS)
13477                         return (result);
13478         } else {
13479                 dns_zone_log(zone, ISC_LOG_ERROR,
13480                             "retrieving SOA and NS records failed: %s",
13481                             dns_result_totext(result));
13482                 return (result);
13483         }
13484
13485         result = check_nsec3param(zone, db);
13486         if (result != ISC_R_SUCCESS)
13487                 return (result);
13488
13489         ver = NULL;
13490         dns_db_currentversion(db, &ver);
13491
13492         /*
13493          * The initial version of a slave zone is always dumped;
13494          * subsequent versions may be journaled instead if this
13495          * is enabled in the configuration.
13496          */
13497         if (zone->db != NULL && zone->journal != NULL &&
13498             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
13499             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
13500         {
13501                 isc_uint32_t serial, oldserial;
13502                 unsigned int soacount;
13503
13504                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
13505
13506                 result = dns_db_getsoaserial(db, ver, &serial);
13507                 if (result != ISC_R_SUCCESS) {
13508                         dns_zone_log(zone, ISC_LOG_ERROR,
13509                                      "ixfr-from-differences: unable to get "
13510                                      "new serial");
13511                         goto fail;
13512                 }
13513
13514                 /*
13515                  * This is checked in zone_postload() for master zones.
13516                  */
13517                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
13518                                           &oldserial, NULL, NULL, NULL, NULL,
13519                                           NULL);
13520                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13521                 RUNTIME_CHECK(soacount > 0U);
13522                 if ((zone->type == dns_zone_slave ||
13523                      (zone->type == dns_zone_redirect &&
13524                       zone->masters != NULL))
13525                     && !isc_serial_gt(serial, oldserial)) {
13526                         isc_uint32_t serialmin, serialmax;
13527                         serialmin = (oldserial + 1) & 0xffffffffU;
13528                         serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
13529                         dns_zone_log(zone, ISC_LOG_ERROR,
13530                                      "ixfr-from-differences: failed: "
13531                                      "new serial (%u) out of range [%u - %u]",
13532                                      serial, serialmin, serialmax);
13533                         result = ISC_R_RANGE;
13534                         goto fail;
13535                 }
13536
13537                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
13538                                      zone->journal);
13539                 if (result != ISC_R_SUCCESS)
13540                         goto fail;
13541                 if (dump)
13542                         zone_needdump(zone, DNS_DUMP_DELAY);
13543                 else if (zone->journalsize != -1) {
13544                         result = dns_journal_compact(zone->mctx, zone->journal,
13545                                                      serial, zone->journalsize);
13546                         switch (result) {
13547                         case ISC_R_SUCCESS:
13548                         case ISC_R_NOSPACE:
13549                         case ISC_R_NOTFOUND:
13550                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
13551                                              "dns_journal_compact: %s",
13552                                              dns_result_totext(result));
13553                                 break;
13554                         default:
13555                                 dns_zone_log(zone, ISC_LOG_ERROR,
13556                                              "dns_journal_compact failed: %s",
13557                                              dns_result_totext(result));
13558                                 break;
13559                         }
13560                 }
13561                 if (zone->type == dns_zone_master && inline_raw(zone))
13562                         zone_send_secureserial(zone, serial);
13563         } else {
13564                 if (dump && zone->masterfile != NULL) {
13565                         /*
13566                          * If DNS_ZONEFLG_FORCEXFER was set we don't want
13567                          * to keep the old masterfile.
13568                          */
13569                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
13570                             remove(zone->masterfile) < 0 && errno != ENOENT) {
13571                                 char strbuf[ISC_STRERRORSIZE];
13572                                 isc__strerror(errno, strbuf, sizeof(strbuf));
13573                                 isc_log_write(dns_lctx,
13574                                               DNS_LOGCATEGORY_GENERAL,
13575                                               DNS_LOGMODULE_ZONE,
13576                                               ISC_LOG_WARNING,
13577                                               "unable to remove masterfile "
13578                                               "'%s': '%s'",
13579                                               zone->masterfile, strbuf);
13580                         }
13581                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
13582                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
13583                         else
13584                                 zone_needdump(zone, 0);
13585                 }
13586                 if (dump && zone->journal != NULL) {
13587                         /*
13588                          * The in-memory database just changed, and
13589                          * because 'dump' is set, it didn't change by
13590                          * being loaded from disk.  Also, we have not
13591                          * journaled diffs for this change.
13592                          * Therefore, the on-disk journal is missing
13593                          * the deltas for this change.  Since it can
13594                          * no longer be used to bring the zone
13595                          * up-to-date, it is useless and should be
13596                          * removed.
13597                          */
13598                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13599                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13600                                       "removing journal file");
13601                         if (remove(zone->journal) < 0 && errno != ENOENT) {
13602                                 char strbuf[ISC_STRERRORSIZE];
13603                                 isc__strerror(errno, strbuf, sizeof(strbuf));
13604                                 isc_log_write(dns_lctx,
13605                                               DNS_LOGCATEGORY_GENERAL,
13606                                               DNS_LOGMODULE_ZONE,
13607                                               ISC_LOG_WARNING,
13608                                               "unable to remove journal "
13609                                               "'%s': '%s'",
13610                                               zone->journal, strbuf);
13611                         }
13612                 }
13613
13614                 if (inline_raw(zone))
13615                         zone_send_securedb(zone, db);
13616         }
13617
13618         dns_db_closeversion(db, &ver, ISC_FALSE);
13619
13620         dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
13621
13622         if (zone->db != NULL)
13623                 zone_detachdb(zone);
13624         zone_attachdb(zone, db);
13625         dns_db_settask(zone->db, zone->task);
13626         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
13627         return (ISC_R_SUCCESS);
13628
13629  fail:
13630         dns_db_closeversion(db, &ver, ISC_FALSE);
13631         return (result);
13632 }
13633
13634 /* The caller must hold the dblock as a writer. */
13635 static inline void
13636 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
13637         REQUIRE(zone->db == NULL && db != NULL);
13638
13639         dns_db_attach(db, &zone->db);
13640         if (zone->acache != NULL) {
13641                 isc_result_t result;
13642                 result = dns_acache_setdb(zone->acache, db);
13643                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
13644                         UNEXPECTED_ERROR(__FILE__, __LINE__,
13645                                          "dns_acache_setdb() failed: %s",
13646                                          isc_result_totext(result));
13647                 }
13648         }
13649 }
13650
13651 /* The caller must hold the dblock as a writer. */
13652 static inline void
13653 zone_detachdb(dns_zone_t *zone) {
13654         REQUIRE(zone->db != NULL);
13655
13656         if (zone->acache != NULL)
13657                 (void)dns_acache_putdb(zone->acache, zone->db);
13658         dns_db_detach(&zone->db);
13659 }
13660
13661 static void
13662 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
13663         isc_time_t now;
13664         isc_boolean_t again = ISC_FALSE;
13665         unsigned int soacount;
13666         unsigned int nscount;
13667         isc_uint32_t serial, refresh, retry, expire, minimum;
13668         isc_result_t xfrresult = result;
13669         isc_boolean_t free_needed;
13670         dns_zone_t *secure = NULL;
13671
13672         REQUIRE(DNS_ZONE_VALID(zone));
13673
13674         dns_zone_log(zone, ISC_LOG_DEBUG(1),
13675                      "zone transfer finished: %s", dns_result_totext(result));
13676
13677         /*
13678          * Obtaining a lock on the zone->secure (see zone_send_secureserial)
13679          * could result in a deadlock due to a LOR so we will spin if we
13680          * can't obtain the both locks.
13681          */
13682  again:
13683         LOCK_ZONE(zone);
13684         if (inline_raw(zone)) {
13685                 secure = zone->secure;
13686                 INSIST(secure != zone);
13687                 TRYLOCK_ZONE(result, secure);
13688                 if (result != ISC_R_SUCCESS) {
13689                         UNLOCK_ZONE(zone);
13690                         secure = NULL;
13691 #if ISC_PLATFORM_USETHREADS
13692                         isc_thread_yield();
13693 #endif
13694                         goto again;
13695                 }
13696         }
13697
13698         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
13699         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13700         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
13701
13702         TIME_NOW(&now);
13703         switch (result) {
13704         case ISC_R_SUCCESS:
13705                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13706                 /*FALLTHROUGH*/
13707         case DNS_R_UPTODATE:
13708                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13709                 /*
13710                  * Has the zone expired underneath us?
13711                  */
13712                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13713                 if (zone->db == NULL) {
13714                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13715                         goto same_master;
13716                 }
13717
13718                 /*
13719                  * Update the zone structure's data from the actual
13720                  * SOA received.
13721                  */
13722                 nscount = 0;
13723                 soacount = 0;
13724                 INSIST(zone->db != NULL);
13725                 result = zone_get_from_db(zone, zone->db, &nscount,
13726                                           &soacount, &serial, &refresh,
13727                                           &retry, &expire, &minimum, NULL);
13728                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13729                 if (result == ISC_R_SUCCESS) {
13730                         if (soacount != 1)
13731                                 dns_zone_log(zone, ISC_LOG_ERROR,
13732                                              "transferred zone "
13733                                              "has %d SOA record%s", soacount,
13734                                              (soacount != 0) ? "s" : "");
13735                         if (nscount == 0) {
13736                                 dns_zone_log(zone, ISC_LOG_ERROR,
13737                                              "transferred zone "
13738                                              "has no NS records");
13739                                 if (DNS_ZONE_FLAG(zone,
13740                                                   DNS_ZONEFLG_HAVETIMERS)) {
13741                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
13742                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
13743                                 }
13744                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13745                                 zone_unload(zone);
13746                                 goto next_master;
13747                         }
13748                         zone->refresh = RANGE(refresh, zone->minrefresh,
13749                                               zone->maxrefresh);
13750                         zone->retry = RANGE(retry, zone->minretry,
13751                                             zone->maxretry);
13752                         zone->expire = RANGE(expire,
13753                                              zone->refresh + zone->retry,
13754                                              DNS_MAX_EXPIRE);
13755                         zone->minimum = minimum;
13756                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13757                 }
13758
13759                 /*
13760                  * Set our next update/expire times.
13761                  */
13762                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
13763                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13764                         zone->refreshtime = now;
13765                         DNS_ZONE_TIME_ADD(&now, zone->expire,
13766                                           &zone->expiretime);
13767                 } else {
13768                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
13769                                             &zone->refreshtime);
13770                         DNS_ZONE_TIME_ADD(&now, zone->expire,
13771                                           &zone->expiretime);
13772                 }
13773                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
13774                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
13775                         if (zone->tsigkey != NULL) {
13776                                 char namebuf[DNS_NAME_FORMATSIZE];
13777                                 dns_name_format(&zone->tsigkey->name, namebuf,
13778                                                 sizeof(namebuf));
13779                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
13780                                          namebuf);
13781                         } else
13782                                 buf[0] = '\0';
13783                         dns_zone_log(zone, ISC_LOG_INFO,
13784                                      "transferred serial %u%s",
13785                                      serial, buf);
13786                         if (inline_raw(zone))
13787                                 zone_send_secureserial(zone, serial);
13788                 }
13789
13790                 /*
13791                  * This is not necessary if we just performed a AXFR
13792                  * however it is necessary for an IXFR / UPTODATE and
13793                  * won't hurt with an AXFR.
13794                  */
13795                 if (zone->masterfile != NULL || zone->journal != NULL) {
13796                         unsigned int delay = DNS_DUMP_DELAY;
13797
13798                         result = ISC_R_FAILURE;
13799                         if (zone->journal != NULL)
13800                                 result = isc_file_settime(zone->journal, &now);
13801                         if (result != ISC_R_SUCCESS &&
13802                             zone->masterfile != NULL)
13803                                 result = isc_file_settime(zone->masterfile,
13804                                                           &now);
13805
13806                         if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
13807                             result == ISC_R_FILENOTFOUND)
13808                                 delay = 0;
13809
13810                         if ((result == ISC_R_SUCCESS ||
13811                             result == ISC_R_FILENOTFOUND) &&
13812                             zone->masterfile != NULL)
13813                                 zone_needdump(zone, delay);
13814                         else if (result != ISC_R_SUCCESS)
13815                                 dns_zone_log(zone, ISC_LOG_ERROR,
13816                                              "transfer: could not set file "
13817                                              "modification time of '%s': %s",
13818                                              zone->masterfile,
13819                                              dns_result_totext(result));
13820                 }
13821                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
13822                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
13823                 break;
13824
13825         case DNS_R_BADIXFR:
13826                 /* Force retry with AXFR. */
13827                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
13828                 goto same_master;
13829
13830         default:
13831         next_master:
13832                 /*
13833                  * Skip to next failed / untried master.
13834                  */
13835                 do {
13836                         zone->curmaster++;
13837                 } while (zone->curmaster < zone->masterscnt &&
13838                          zone->mastersok[zone->curmaster]);
13839                 /* FALLTHROUGH */
13840         same_master:
13841                 if (zone->curmaster >= zone->masterscnt) {
13842                         zone->curmaster = 0;
13843                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13844                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13845                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
13846                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13847                                 while (zone->curmaster < zone->masterscnt &&
13848                                        zone->mastersok[zone->curmaster])
13849                                         zone->curmaster++;
13850                                 again = ISC_TRUE;
13851                         } else
13852                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13853                 } else {
13854                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
13855                         again = ISC_TRUE;
13856                 }
13857                 inc_stats(zone, dns_zonestatscounter_xfrfail);
13858                 break;
13859         }
13860         zone_settimer(zone, &now);
13861
13862         /*
13863          * If creating the transfer object failed, zone->xfr is NULL.
13864          * Otherwise, we are called as the done callback of a zone
13865          * transfer object that just entered its shutting-down
13866          * state.  Since we are no longer responsible for shutting
13867          * it down, we can detach our reference.
13868          */
13869         if (zone->xfr != NULL)
13870                 dns_xfrin_detach(&zone->xfr);
13871
13872         if (zone->tsigkey != NULL)
13873                 dns_tsigkey_detach(&zone->tsigkey);
13874
13875         /*
13876          * Handle any deferred journal compaction.
13877          */
13878         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
13879                 result = dns_journal_compact(zone->mctx, zone->journal,
13880                                              zone->compact_serial,
13881                                              zone->journalsize);
13882                 switch (result) {
13883                 case ISC_R_SUCCESS:
13884                 case ISC_R_NOSPACE:
13885                 case ISC_R_NOTFOUND:
13886                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
13887                                      "dns_journal_compact: %s",
13888                                      dns_result_totext(result));
13889                         break;
13890                 default:
13891                         dns_zone_log(zone, ISC_LOG_ERROR,
13892                                      "dns_journal_compact failed: %s",
13893                                      dns_result_totext(result));
13894                         break;
13895                 }
13896                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
13897         }
13898
13899         if (secure != NULL)
13900                 UNLOCK_ZONE(secure);
13901         /*
13902          * This transfer finishing freed up a transfer quota slot.
13903          * Let any other zones waiting for quota have it.
13904          */
13905         if (zone->zmgr != NULL &&
13906             zone->statelist == &zone->zmgr->xfrin_in_progress) {
13907                 UNLOCK_ZONE(zone);
13908                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13909                 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
13910                 zone->statelist = NULL;
13911                 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
13912                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13913                 LOCK_ZONE(zone);
13914         }
13915
13916         /*
13917          * Retry with a different server if necessary.
13918          */
13919         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
13920                 queue_soa_query(zone);
13921
13922         INSIST(zone->irefs > 0);
13923         zone->irefs--;
13924         free_needed = exit_check(zone);
13925         UNLOCK_ZONE(zone);
13926         if (free_needed)
13927                 zone_free(zone);
13928 }
13929
13930 static void
13931 zone_loaddone(void *arg, isc_result_t result) {
13932         static char me[] = "zone_loaddone";
13933         dns_load_t *load = arg;
13934         dns_zone_t *zone;
13935         isc_result_t tresult;
13936         dns_zone_t *secure = NULL;
13937
13938         REQUIRE(DNS_LOAD_VALID(load));
13939         zone = load->zone;
13940
13941         ENTER;
13942
13943         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
13944         if (tresult != ISC_R_SUCCESS &&
13945             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
13946                 result = tresult;
13947
13948         /*
13949          * Lock hierarchy: zmgr, zone, raw.
13950          */
13951  again:
13952         LOCK_ZONE(zone);
13953         if (inline_secure(zone))
13954                 LOCK_ZONE(zone->raw);
13955         else if (inline_raw(zone)) {
13956                 secure = zone->secure;
13957                 TRYLOCK_ZONE(result, secure);
13958                 if (result != ISC_R_SUCCESS) {
13959                         UNLOCK_ZONE(zone);
13960                         secure = NULL;
13961 #if ISC_PLATFORM_USETHREADS
13962                         isc_thread_yield();
13963 #endif
13964                         goto again;
13965                 }
13966         }
13967         (void)zone_postload(zone, load->db, load->loadtime, result);
13968         zonemgr_putio(&zone->readio);
13969         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
13970         zone_idetach(&load->callbacks.zone);
13971         /*
13972          * Leave the zone frozen if the reload fails.
13973          */
13974         if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
13975              DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
13976                 zone->update_disabled = ISC_FALSE;
13977         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
13978         if (inline_secure(zone))
13979                 UNLOCK_ZONE(zone->raw);
13980         else if (secure != NULL)
13981                 UNLOCK_ZONE(secure);
13982         UNLOCK_ZONE(zone);
13983
13984         load->magic = 0;
13985         dns_db_detach(&load->db);
13986         if (load->zone->lctx != NULL)
13987                 dns_loadctx_detach(&load->zone->lctx);
13988         dns_zone_idetach(&load->zone);
13989         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
13990 }
13991
13992 void
13993 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
13994         REQUIRE(DNS_ZONE_VALID(zone));
13995         REQUIRE(table != NULL);
13996         REQUIRE(*table == NULL);
13997
13998         LOCK_ZONE(zone);
13999         if (zone->ssutable != NULL)
14000                 dns_ssutable_attach(zone->ssutable, table);
14001         UNLOCK_ZONE(zone);
14002 }
14003
14004 void
14005 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
14006         REQUIRE(DNS_ZONE_VALID(zone));
14007
14008         LOCK_ZONE(zone);
14009         if (zone->ssutable != NULL)
14010                 dns_ssutable_detach(&zone->ssutable);
14011         if (table != NULL)
14012                 dns_ssutable_attach(table, &zone->ssutable);
14013         UNLOCK_ZONE(zone);
14014 }
14015
14016 void
14017 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
14018         REQUIRE(DNS_ZONE_VALID(zone));
14019
14020         zone->sigvalidityinterval = interval;
14021 }
14022
14023 isc_uint32_t
14024 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
14025         REQUIRE(DNS_ZONE_VALID(zone));
14026
14027         return (zone->sigvalidityinterval);
14028 }
14029
14030 void
14031 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
14032         isc_time_t now;
14033
14034         REQUIRE(DNS_ZONE_VALID(zone));
14035
14036         LOCK_ZONE(zone);
14037         zone->sigresigninginterval = interval;
14038         set_resigntime(zone);
14039         if (zone->task != NULL) {
14040                 TIME_NOW(&now);
14041                 zone_settimer(zone, &now);
14042         }
14043         UNLOCK_ZONE(zone);
14044 }
14045
14046 isc_uint32_t
14047 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
14048         REQUIRE(DNS_ZONE_VALID(zone));
14049
14050         return (zone->sigresigninginterval);
14051 }
14052
14053 static void
14054 queue_xfrin(dns_zone_t *zone) {
14055         const char me[] = "queue_xfrin";
14056         isc_result_t result;
14057         dns_zonemgr_t *zmgr = zone->zmgr;
14058
14059         ENTER;
14060
14061         INSIST(zone->statelist == NULL);
14062
14063         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14064         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
14065         LOCK_ZONE(zone);
14066         zone->irefs++;
14067         UNLOCK_ZONE(zone);
14068         zone->statelist = &zmgr->waiting_for_xfrin;
14069         result = zmgr_start_xfrin_ifquota(zmgr, zone);
14070         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14071
14072         if (result == ISC_R_QUOTA) {
14073                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14074                               "zone transfer deferred due to quota");
14075         } else if (result != ISC_R_SUCCESS) {
14076                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
14077                               "starting zone transfer: %s",
14078                               isc_result_totext(result));
14079         }
14080 }
14081
14082 /*
14083  * This event callback is called when a zone has received
14084  * any necessary zone transfer quota.  This is the time
14085  * to go ahead and start the transfer.
14086  */
14087 static void
14088 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
14089         isc_result_t result = ISC_R_SUCCESS;
14090         dns_peer_t *peer = NULL;
14091         char master[ISC_SOCKADDR_FORMATSIZE];
14092         char source[ISC_SOCKADDR_FORMATSIZE];
14093         dns_rdatatype_t xfrtype;
14094         dns_zone_t *zone = event->ev_arg;
14095         isc_netaddr_t masterip;
14096         isc_sockaddr_t sourceaddr;
14097         isc_sockaddr_t masteraddr;
14098         isc_time_t now;
14099         const char *soa_before = "";
14100         isc_boolean_t loaded;
14101
14102         UNUSED(task);
14103
14104         INSIST(task == zone->task);
14105
14106         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14107                 result = ISC_R_CANCELED;
14108                 goto cleanup;
14109         }
14110
14111         TIME_NOW(&now);
14112
14113         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
14114         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
14115                                     &zone->sourceaddr, &now))
14116         {
14117                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14118                 dns_zone_log(zone, ISC_LOG_INFO,
14119                              "got_transfer_quota: skipping zone transfer as "
14120                              "master %s (source %s) is unreachable (cached)",
14121                              master, source);
14122                 result = ISC_R_CANCELED;
14123                 goto cleanup;
14124         }
14125
14126         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14127         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
14128
14129         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14130                 soa_before = "SOA before ";
14131         /*
14132          * Decide whether we should request IXFR or AXFR.
14133          */
14134         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14135         loaded = ISC_TF(zone->db != NULL);
14136         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14137
14138         if (!loaded) {
14139                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14140                              "no database exists yet, requesting AXFR of "
14141                              "initial version from %s", master);
14142                 xfrtype = dns_rdatatype_axfr;
14143         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
14144                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14145                              "forced reload, requesting AXFR of "
14146                              "initial version from %s", master);
14147                 xfrtype = dns_rdatatype_axfr;
14148         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
14149                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14150                              "retrying with AXFR from %s due to "
14151                              "previous IXFR failure", master);
14152                 xfrtype = dns_rdatatype_axfr;
14153                 LOCK_ZONE(zone);
14154                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
14155                 UNLOCK_ZONE(zone);
14156         } else {
14157                 isc_boolean_t use_ixfr = ISC_TRUE;
14158                 if (peer != NULL)
14159                         result = dns_peer_getrequestixfr(peer, &use_ixfr);
14160                 if (peer == NULL || result != ISC_R_SUCCESS)
14161                         use_ixfr = zone->requestixfr;
14162                 if (use_ixfr == ISC_FALSE) {
14163                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
14164                                      "IXFR disabled, requesting %sAXFR from %s",
14165                                      soa_before, master);
14166                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14167                                 xfrtype = dns_rdatatype_soa;
14168                         else
14169                                 xfrtype = dns_rdatatype_axfr;
14170                 } else {
14171                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
14172                                      "requesting IXFR from %s", master);
14173                         xfrtype = dns_rdatatype_ixfr;
14174                 }
14175         }
14176
14177         /*
14178          * Determine if we should attempt to sign the request with TSIG.
14179          */
14180         result = ISC_R_NOTFOUND;
14181         /*
14182          * First, look for a tsig key in the master statement, then
14183          * try for a server key.
14184          */
14185         if ((zone->masterkeynames != NULL) &&
14186             (zone->masterkeynames[zone->curmaster] != NULL)) {
14187                 dns_view_t *view = dns_zone_getview(zone);
14188                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14189                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
14190         }
14191         if (zone->tsigkey == NULL)
14192                 result = dns_view_getpeertsig(zone->view, &masterip,
14193                                               &zone->tsigkey);
14194
14195         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14196                 dns_zone_log(zone, ISC_LOG_ERROR,
14197                              "could not get TSIG key for zone transfer: %s",
14198                              isc_result_totext(result));
14199         }
14200
14201         LOCK_ZONE(zone);
14202         masteraddr = zone->masteraddr;
14203         sourceaddr = zone->sourceaddr;
14204         UNLOCK_ZONE(zone);
14205         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
14206         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
14207                                    zone->tsigkey, zone->mctx,
14208                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
14209                                    zone->task, zone_xfrdone, &zone->xfr);
14210         if (result == ISC_R_SUCCESS) {
14211                 LOCK_ZONE(zone);
14212                 if (xfrtype == dns_rdatatype_axfr) {
14213                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14214                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
14215                         else
14216                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
14217                 } else if (xfrtype == dns_rdatatype_ixfr) {
14218                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14219                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
14220                         else
14221                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
14222                 }
14223                 UNLOCK_ZONE(zone);
14224         }
14225  cleanup:
14226         /*
14227          * Any failure in this function is handled like a failed
14228          * zone transfer.  This ensures that we get removed from
14229          * zmgr->xfrin_in_progress.
14230          */
14231         if (result != ISC_R_SUCCESS)
14232                 zone_xfrdone(zone, result);
14233
14234         isc_event_free(&event);
14235 }
14236
14237 /*
14238  * Update forwarding support.
14239  */
14240
14241 static void
14242 forward_destroy(dns_forward_t *forward) {
14243
14244         forward->magic = 0;
14245         if (forward->request != NULL)
14246                 dns_request_destroy(&forward->request);
14247         if (forward->msgbuf != NULL)
14248                 isc_buffer_free(&forward->msgbuf);
14249         if (forward->zone != NULL) {
14250                 LOCK(&forward->zone->lock);
14251                 if (ISC_LINK_LINKED(forward, link))
14252                         ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
14253                 UNLOCK(&forward->zone->lock);
14254                 dns_zone_idetach(&forward->zone);
14255         }
14256         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
14257 }
14258
14259 static isc_result_t
14260 sendtomaster(dns_forward_t *forward) {
14261         isc_result_t result;
14262         isc_sockaddr_t src;
14263
14264         LOCK_ZONE(forward->zone);
14265
14266         if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
14267                 UNLOCK_ZONE(forward->zone);
14268                 return (ISC_R_CANCELED);
14269         }
14270
14271         if (forward->which >= forward->zone->masterscnt) {
14272                 UNLOCK_ZONE(forward->zone);
14273                 return (ISC_R_NOMORE);
14274         }
14275
14276         forward->addr = forward->zone->masters[forward->which];
14277         /*
14278          * Always use TCP regardless of whether the original update
14279          * used TCP.
14280          * XXX The timeout may but a bit small if we are far down a
14281          * transfer graph and the master has to try several masters.
14282          */
14283         switch (isc_sockaddr_pf(&forward->addr)) {
14284         case PF_INET:
14285                 src = forward->zone->xfrsource4;
14286                 break;
14287         case PF_INET6:
14288                 src = forward->zone->xfrsource6;
14289                 break;
14290         default:
14291                 result = ISC_R_NOTIMPLEMENTED;
14292                 goto unlock;
14293         }
14294         result = dns_request_createraw(forward->zone->view->requestmgr,
14295                                        forward->msgbuf,
14296                                        &src, &forward->addr,
14297                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
14298                                        forward->zone->task,
14299                                        forward_callback, forward,
14300                                        &forward->request);
14301         if (result == ISC_R_SUCCESS) {
14302                 if (!ISC_LINK_LINKED(forward, link))
14303                         ISC_LIST_APPEND(forward->zone->forwards, forward, link);
14304         }
14305
14306  unlock:
14307         UNLOCK_ZONE(forward->zone);
14308         return (result);
14309 }
14310
14311 static void
14312 forward_callback(isc_task_t *task, isc_event_t *event) {
14313         const char me[] = "forward_callback";
14314         dns_requestevent_t *revent = (dns_requestevent_t *)event;
14315         dns_message_t *msg = NULL;
14316         char master[ISC_SOCKADDR_FORMATSIZE];
14317         isc_result_t result;
14318         dns_forward_t *forward;
14319         dns_zone_t *zone;
14320
14321         UNUSED(task);
14322
14323         forward = revent->ev_arg;
14324         INSIST(DNS_FORWARD_VALID(forward));
14325         zone = forward->zone;
14326         INSIST(DNS_ZONE_VALID(zone));
14327
14328         ENTER;
14329
14330         isc_sockaddr_format(&forward->addr, master, sizeof(master));
14331
14332         if (revent->result != ISC_R_SUCCESS) {
14333                 dns_zone_log(zone, ISC_LOG_INFO,
14334                              "could not forward dynamic update to %s: %s",
14335                              master, dns_result_totext(revent->result));
14336                 goto next_master;
14337         }
14338
14339         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
14340         if (result != ISC_R_SUCCESS)
14341                 goto next_master;
14342
14343         result = dns_request_getresponse(revent->request, msg,
14344                                          DNS_MESSAGEPARSE_PRESERVEORDER |
14345                                          DNS_MESSAGEPARSE_CLONEBUFFER);
14346         if (result != ISC_R_SUCCESS)
14347                 goto next_master;
14348
14349         switch (msg->rcode) {
14350         /*
14351          * Pass these rcodes back to client.
14352          */
14353         case dns_rcode_noerror:
14354         case dns_rcode_yxdomain:
14355         case dns_rcode_yxrrset:
14356         case dns_rcode_nxrrset:
14357         case dns_rcode_refused:
14358         case dns_rcode_nxdomain: {
14359                 char rcode[128];
14360                 isc_buffer_t rb;
14361
14362                 isc_buffer_init(&rb, rcode, sizeof(rcode));
14363                 (void)dns_rcode_totext(msg->rcode, &rb);
14364                 dns_zone_log(zone, ISC_LOG_INFO,
14365                              "forwarded dynamic update: "
14366                              "master %s returned: %.*s",
14367                              master, (int)rb.used, rcode);
14368                 break;
14369         }
14370
14371         /* These should not occur if the masters/zone are valid. */
14372         case dns_rcode_notzone:
14373         case dns_rcode_notauth: {
14374                 char rcode[128];
14375                 isc_buffer_t rb;
14376
14377                 isc_buffer_init(&rb, rcode, sizeof(rcode));
14378                 (void)dns_rcode_totext(msg->rcode, &rb);
14379                 dns_zone_log(zone, ISC_LOG_WARNING,
14380                              "forwarding dynamic update: "
14381                              "unexpected response: master %s returned: %.*s",
14382                              master, (int)rb.used, rcode);
14383                 goto next_master;
14384         }
14385
14386         /* Try another server for these rcodes. */
14387         case dns_rcode_formerr:
14388         case dns_rcode_servfail:
14389         case dns_rcode_notimp:
14390         case dns_rcode_badvers:
14391         default:
14392                 goto next_master;
14393         }
14394
14395         /* call callback */
14396         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
14397         msg = NULL;
14398         dns_request_destroy(&forward->request);
14399         forward_destroy(forward);
14400         isc_event_free(&event);
14401         return;
14402
14403  next_master:
14404         if (msg != NULL)
14405                 dns_message_destroy(&msg);
14406         isc_event_free(&event);
14407         forward->which++;
14408         dns_request_destroy(&forward->request);
14409         result = sendtomaster(forward);
14410         if (result != ISC_R_SUCCESS) {
14411                 /* call callback */
14412                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
14413                              "exhausted dynamic update forwarder list");
14414                 (forward->callback)(forward->callback_arg, result, NULL);
14415                 forward_destroy(forward);
14416         }
14417 }
14418
14419 isc_result_t
14420 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
14421                        dns_updatecallback_t callback, void *callback_arg)
14422 {
14423         dns_forward_t *forward;
14424         isc_result_t result;
14425         isc_region_t *mr;
14426
14427         REQUIRE(DNS_ZONE_VALID(zone));
14428         REQUIRE(msg != NULL);
14429         REQUIRE(callback != NULL);
14430
14431         forward = isc_mem_get(zone->mctx, sizeof(*forward));
14432         if (forward == NULL)
14433                 return (ISC_R_NOMEMORY);
14434
14435         forward->request = NULL;
14436         forward->zone = NULL;
14437         forward->msgbuf = NULL;
14438         forward->which = 0;
14439         forward->mctx = 0;
14440         forward->callback = callback;
14441         forward->callback_arg = callback_arg;
14442         ISC_LINK_INIT(forward, link);
14443         forward->magic = FORWARD_MAGIC;
14444
14445         mr = dns_message_getrawmessage(msg);
14446         if (mr == NULL) {
14447                 result = ISC_R_UNEXPECTEDEND;
14448                 goto cleanup;
14449         }
14450
14451         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
14452         if (result != ISC_R_SUCCESS)
14453                 goto cleanup;
14454         result = isc_buffer_copyregion(forward->msgbuf, mr);
14455         if (result != ISC_R_SUCCESS)
14456                 goto cleanup;
14457
14458         isc_mem_attach(zone->mctx, &forward->mctx);
14459         dns_zone_iattach(zone, &forward->zone);
14460         result = sendtomaster(forward);
14461
14462  cleanup:
14463         if (result != ISC_R_SUCCESS) {
14464                 forward_destroy(forward);
14465         }
14466         return (result);
14467 }
14468
14469 isc_result_t
14470 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
14471         REQUIRE(DNS_ZONE_VALID(zone));
14472         REQUIRE(next != NULL && *next == NULL);
14473
14474         *next = ISC_LIST_NEXT(zone, link);
14475         if (*next == NULL)
14476                 return (ISC_R_NOMORE);
14477         else
14478                 return (ISC_R_SUCCESS);
14479 }
14480
14481 isc_result_t
14482 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
14483         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14484         REQUIRE(first != NULL && *first == NULL);
14485
14486         *first = ISC_LIST_HEAD(zmgr->zones);
14487         if (*first == NULL)
14488                 return (ISC_R_NOMORE);
14489         else
14490                 return (ISC_R_SUCCESS);
14491 }
14492
14493 /***
14494  ***    Zone manager.
14495  ***/
14496
14497 isc_result_t
14498 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
14499                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
14500                    dns_zonemgr_t **zmgrp)
14501 {
14502         dns_zonemgr_t *zmgr;
14503         isc_result_t result;
14504         isc_interval_t interval;
14505
14506         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
14507         if (zmgr == NULL)
14508                 return (ISC_R_NOMEMORY);
14509         zmgr->mctx = NULL;
14510         zmgr->refs = 1;
14511         isc_mem_attach(mctx, &zmgr->mctx);
14512         zmgr->taskmgr = taskmgr;
14513         zmgr->timermgr = timermgr;
14514         zmgr->socketmgr = socketmgr;
14515         zmgr->zonetasks = NULL;
14516         zmgr->loadtasks = NULL;
14517         zmgr->mctxpool = NULL;
14518         zmgr->task = NULL;
14519         zmgr->notifyrl = NULL;
14520         zmgr->refreshrl = NULL;
14521         ISC_LIST_INIT(zmgr->zones);
14522         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
14523         ISC_LIST_INIT(zmgr->xfrin_in_progress);
14524         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
14525         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
14526         if (result != ISC_R_SUCCESS)
14527                 goto free_mem;
14528
14529         zmgr->transfersin = 10;
14530         zmgr->transfersperns = 2;
14531
14532         /* Unreachable lock. */
14533         result = isc_rwlock_init(&zmgr->urlock, 0, 0);
14534         if (result != ISC_R_SUCCESS)
14535                 goto free_rwlock;
14536
14537         /* Create a single task for queueing of SOA queries. */
14538         result = isc_task_create(taskmgr, 1, &zmgr->task);
14539         if (result != ISC_R_SUCCESS)
14540                 goto free_urlock;
14541
14542         isc_task_setname(zmgr->task, "zmgr", zmgr);
14543         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14544                                         &zmgr->notifyrl);
14545         if (result != ISC_R_SUCCESS)
14546                 goto free_task;
14547
14548         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14549                                         &zmgr->refreshrl);
14550         if (result != ISC_R_SUCCESS)
14551                 goto free_notifyrl;
14552
14553         /* default to 20 refresh queries / notifies per second. */
14554         isc_interval_set(&interval, 0, 1000000000/2);
14555         result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
14556         RUNTIME_CHECK(result == ISC_R_SUCCESS);
14557         isc_ratelimiter_setpertic(zmgr->notifyrl, 10);
14558
14559         result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
14560         RUNTIME_CHECK(result == ISC_R_SUCCESS);
14561         isc_ratelimiter_setpertic(zmgr->refreshrl, 10);
14562
14563         zmgr->iolimit = 1;
14564         zmgr->ioactive = 0;
14565         ISC_LIST_INIT(zmgr->high);
14566         ISC_LIST_INIT(zmgr->low);
14567
14568         result = isc_mutex_init(&zmgr->iolock);
14569         if (result != ISC_R_SUCCESS)
14570                 goto free_refreshrl;
14571
14572         zmgr->magic = ZONEMGR_MAGIC;
14573
14574         *zmgrp = zmgr;
14575         return (ISC_R_SUCCESS);
14576
14577 #if 0
14578  free_iolock:
14579         DESTROYLOCK(&zmgr->iolock);
14580 #endif
14581  free_refreshrl:
14582         isc_ratelimiter_detach(&zmgr->refreshrl);
14583  free_notifyrl:
14584         isc_ratelimiter_detach(&zmgr->notifyrl);
14585  free_task:
14586         isc_task_detach(&zmgr->task);
14587  free_urlock:
14588         isc_rwlock_destroy(&zmgr->urlock);
14589  free_rwlock:
14590         isc_rwlock_destroy(&zmgr->rwlock);
14591  free_mem:
14592         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14593         isc_mem_detach(&mctx);
14594         return (result);
14595 }
14596
14597 isc_result_t
14598 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
14599         isc_result_t result;
14600         isc_mem_t *mctx = NULL;
14601         dns_zone_t *zone = NULL;
14602         void *item;
14603
14604         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14605         REQUIRE(zonep != NULL && *zonep == NULL);
14606
14607         if (zmgr->mctxpool == NULL)
14608                 return (ISC_R_FAILURE);
14609
14610         item = isc_pool_get(zmgr->mctxpool);
14611         if (item == NULL)
14612                 return (ISC_R_FAILURE);
14613
14614         isc_mem_attach((isc_mem_t *) item, &mctx);
14615         result = dns_zone_create(&zone, mctx);
14616         isc_mem_detach(&mctx);
14617
14618         if (result == ISC_R_SUCCESS)
14619                 *zonep = zone;
14620
14621         return (result);
14622 }
14623
14624 isc_result_t
14625 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14626         isc_result_t result;
14627
14628         REQUIRE(DNS_ZONE_VALID(zone));
14629         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14630
14631         if (zmgr->zonetasks == NULL)
14632                 return (ISC_R_FAILURE);
14633
14634         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14635         LOCK_ZONE(zone);
14636         REQUIRE(zone->task == NULL);
14637         REQUIRE(zone->timer == NULL);
14638         REQUIRE(zone->zmgr == NULL);
14639
14640         isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
14641         isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
14642
14643         /*
14644          * Set the task name.  The tag will arbitrarily point to one
14645          * of the zones sharing the task (in practice, the one
14646          * to be managed last).
14647          */
14648         isc_task_setname(zone->task, "zone", zone);
14649         isc_task_setname(zone->loadtask, "loadzone", zone);
14650
14651         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
14652                                   NULL, NULL,
14653                                   zone->task, zone_timer, zone,
14654                                   &zone->timer);
14655
14656         if (result != ISC_R_SUCCESS)
14657                 goto cleanup_tasks;
14658
14659         /*
14660          * The timer "holds" a iref.
14661          */
14662         zone->irefs++;
14663         INSIST(zone->irefs != 0);
14664
14665         ISC_LIST_APPEND(zmgr->zones, zone, link);
14666         zone->zmgr = zmgr;
14667         zmgr->refs++;
14668
14669         goto unlock;
14670
14671  cleanup_tasks:
14672         isc_task_detach(&zone->loadtask);
14673         isc_task_detach(&zone->task);
14674
14675  unlock:
14676         UNLOCK_ZONE(zone);
14677         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14678         return (result);
14679 }
14680
14681 void
14682 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14683         isc_boolean_t free_now = ISC_FALSE;
14684
14685         REQUIRE(DNS_ZONE_VALID(zone));
14686         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14687         REQUIRE(zone->zmgr == zmgr);
14688
14689         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14690         LOCK_ZONE(zone);
14691
14692         ISC_LIST_UNLINK(zmgr->zones, zone, link);
14693         zone->zmgr = NULL;
14694         zmgr->refs--;
14695         if (zmgr->refs == 0)
14696                 free_now = ISC_TRUE;
14697
14698         UNLOCK_ZONE(zone);
14699         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14700
14701         if (free_now)
14702                 zonemgr_free(zmgr);
14703         ENSURE(zone->zmgr == NULL);
14704 }
14705
14706 void
14707 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
14708         REQUIRE(DNS_ZONEMGR_VALID(source));
14709         REQUIRE(target != NULL && *target == NULL);
14710
14711         RWLOCK(&source->rwlock, isc_rwlocktype_write);
14712         REQUIRE(source->refs > 0);
14713         source->refs++;
14714         INSIST(source->refs > 0);
14715         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
14716         *target = source;
14717 }
14718
14719 void
14720 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
14721         dns_zonemgr_t *zmgr;
14722         isc_boolean_t free_now = ISC_FALSE;
14723
14724         REQUIRE(zmgrp != NULL);
14725         zmgr = *zmgrp;
14726         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14727
14728         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14729         zmgr->refs--;
14730         if (zmgr->refs == 0)
14731                 free_now = ISC_TRUE;
14732         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14733
14734         if (free_now)
14735                 zonemgr_free(zmgr);
14736         *zmgrp = NULL;
14737 }
14738
14739 isc_result_t
14740 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
14741         dns_zone_t *p;
14742
14743         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14744
14745         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14746         for (p = ISC_LIST_HEAD(zmgr->zones);
14747              p != NULL;
14748              p = ISC_LIST_NEXT(p, link))
14749         {
14750                 dns_zone_maintenance(p);
14751         }
14752         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14753
14754         /*
14755          * Recent configuration changes may have increased the
14756          * amount of available transfers quota.  Make sure any
14757          * transfers currently blocked on quota get started if
14758          * possible.
14759          */
14760         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14761         zmgr_resume_xfrs(zmgr, ISC_TRUE);
14762         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14763         return (ISC_R_SUCCESS);
14764 }
14765
14766 void
14767 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
14768
14769         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14770
14771         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14772         zmgr_resume_xfrs(zmgr, ISC_TRUE);
14773         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14774 }
14775
14776 void
14777 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
14778         dns_zone_t *zone;
14779
14780         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14781
14782         isc_ratelimiter_shutdown(zmgr->notifyrl);
14783         isc_ratelimiter_shutdown(zmgr->refreshrl);
14784
14785         if (zmgr->task != NULL)
14786                 isc_task_destroy(&zmgr->task);
14787         if (zmgr->zonetasks != NULL)
14788                 isc_taskpool_destroy(&zmgr->zonetasks);
14789         if (zmgr->loadtasks != NULL)
14790                 isc_taskpool_destroy(&zmgr->loadtasks);
14791         if (zmgr->mctxpool != NULL)
14792                 isc_pool_destroy(&zmgr->mctxpool);
14793
14794         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14795         for (zone = ISC_LIST_HEAD(zmgr->zones);
14796              zone != NULL;
14797              zone = ISC_LIST_NEXT(zone, link))
14798         {
14799                 LOCK_ZONE(zone);
14800                 forward_cancel(zone);
14801                 UNLOCK_ZONE(zone);
14802         }
14803         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14804 }
14805
14806 static isc_result_t
14807 mctxinit(void **target, void *arg) {
14808         isc_result_t result;
14809         isc_mem_t *mctx = NULL;
14810
14811         UNUSED(arg);
14812
14813         REQUIRE(target != NULL && *target == NULL);
14814
14815         result = isc_mem_create(0, 0, &mctx);
14816         if (result != ISC_R_SUCCESS)
14817                 return (result);
14818         isc_mem_setname(mctx, "zonemgr-pool", NULL);
14819
14820         *target = mctx;
14821         return (ISC_R_SUCCESS);
14822 }
14823
14824 static void
14825 mctxfree(void **target) {
14826         isc_mem_t *mctx = *(isc_mem_t **) target;
14827         isc_mem_detach(&mctx);
14828         *target = NULL;
14829 }
14830
14831 #define ZONES_PER_TASK 100
14832 #define ZONES_PER_MCTX 1000
14833
14834 isc_result_t
14835 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
14836         isc_result_t result;
14837         int ntasks = num_zones / ZONES_PER_TASK;
14838         int nmctx = num_zones / ZONES_PER_MCTX;
14839         isc_taskpool_t *pool = NULL;
14840         isc_pool_t *mctxpool = NULL;
14841
14842         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14843
14844         /*
14845          * For anything fewer than 1000 zones we use 10 tasks in
14846          * the task pools.  More than that, and we'll scale at one
14847          * task per 100 zones.  Similarly, for anything smaller than
14848          * 2000 zones we use 2 memory contexts, then scale at 1:1000.
14849          */
14850         if (ntasks < 10)
14851                 ntasks = 10;
14852         if (nmctx < 2)
14853                 nmctx = 2;
14854
14855         /* Create or resize the zone task pools. */
14856         if (zmgr->zonetasks == NULL)
14857                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
14858                                              ntasks, 2, &pool);
14859         else
14860                 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
14861
14862         if (result == ISC_R_SUCCESS)
14863                 zmgr->zonetasks = pool;
14864
14865         pool = NULL;
14866         if (zmgr->loadtasks == NULL)
14867                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
14868                                              ntasks, 2, &pool);
14869         else
14870                 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
14871
14872         if (result == ISC_R_SUCCESS)
14873                 zmgr->loadtasks = pool;
14874
14875 #ifdef BIND9
14876         /*
14877          * We always set all tasks in the zone-load task pool to
14878          * privileged.  This prevents other tasks in the system from
14879          * running while the server task manager is in privileged
14880          * mode.
14881          *
14882          * NOTE: If we start using task privileges for any other
14883          * part of the system than zone tasks, then this will need to be
14884          * revisted.  In that case we'd want to turn on privileges for
14885          * zone tasks only when we were loading, and turn them off the
14886          * rest of the time.  For now, however, it's okay to just
14887          * set it and forget it.
14888          */
14889         isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
14890 #endif
14891
14892         /* Create or resize the zone memory context pool. */
14893         if (zmgr->mctxpool == NULL)
14894                 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
14895                                          mctxinit, NULL, &mctxpool);
14896         else
14897                 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
14898
14899         if (result == ISC_R_SUCCESS)
14900                 zmgr->mctxpool = mctxpool;
14901
14902         return (result);
14903 }
14904
14905 static void
14906 zonemgr_free(dns_zonemgr_t *zmgr) {
14907         isc_mem_t *mctx;
14908
14909         INSIST(zmgr->refs == 0);
14910         INSIST(ISC_LIST_EMPTY(zmgr->zones));
14911
14912         zmgr->magic = 0;
14913
14914         DESTROYLOCK(&zmgr->iolock);
14915         isc_ratelimiter_detach(&zmgr->notifyrl);
14916         isc_ratelimiter_detach(&zmgr->refreshrl);
14917
14918         isc_rwlock_destroy(&zmgr->urlock);
14919         isc_rwlock_destroy(&zmgr->rwlock);
14920         mctx = zmgr->mctx;
14921         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14922         isc_mem_detach(&mctx);
14923 }
14924
14925 void
14926 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
14927         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14928
14929         zmgr->transfersin = value;
14930 }
14931
14932 isc_uint32_t
14933 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
14934         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14935
14936         return (zmgr->transfersin);
14937 }
14938
14939 void
14940 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
14941         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14942
14943         zmgr->transfersperns = value;
14944 }
14945
14946 isc_uint32_t
14947 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
14948         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14949
14950         return (zmgr->transfersperns);
14951 }
14952
14953 /*
14954  * Try to start a new incoming zone transfer to fill a quota
14955  * slot that was just vacated.
14956  *
14957  * Requires:
14958  *      The zone manager is locked by the caller.
14959  */
14960 static void
14961 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
14962         dns_zone_t *zone;
14963         dns_zone_t *next;
14964
14965         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
14966              zone != NULL;
14967              zone = next)
14968         {
14969                 isc_result_t result;
14970                 next = ISC_LIST_NEXT(zone, statelink);
14971                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
14972                 if (result == ISC_R_SUCCESS) {
14973                         if (multi)
14974                                 continue;
14975                         /*
14976                          * We successfully filled the slot.  We're done.
14977                          */
14978                         break;
14979                 } else if (result == ISC_R_QUOTA) {
14980                         /*
14981                          * Not enough quota.  This is probably the per-server
14982                          * quota, because we usually get called when a unit of
14983                          * global quota has just been freed.  Try the next
14984                          * zone, it may succeed if it uses another master.
14985                          */
14986                         continue;
14987                 } else {
14988                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
14989                                      "starting zone transfer: %s",
14990                                      isc_result_totext(result));
14991                         break;
14992                 }
14993         }
14994 }
14995
14996 /*
14997  * Try to start an incoming zone transfer for 'zone', quota permitting.
14998  *
14999  * Requires:
15000  *      The zone manager is locked by the caller.
15001  *
15002  * Returns:
15003  *      ISC_R_SUCCESS   There was enough quota and we attempted to
15004  *                      start a transfer.  zone_xfrdone() has been or will
15005  *                      be called.
15006  *      ISC_R_QUOTA     Not enough quota.
15007  *      Others          Failure.
15008  */
15009 static isc_result_t
15010 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15011         dns_peer_t *peer = NULL;
15012         isc_netaddr_t masterip;
15013         isc_uint32_t nxfrsin, nxfrsperns;
15014         dns_zone_t *x;
15015         isc_uint32_t maxtransfersin, maxtransfersperns;
15016         isc_event_t *e;
15017
15018         /*
15019          * If we are exiting just pretend we got quota so the zone will
15020          * be cleaned up in the zone's task context.
15021          */
15022         LOCK_ZONE(zone);
15023         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15024                 UNLOCK_ZONE(zone);
15025                 goto gotquota;
15026         }
15027
15028         /*
15029          * Find any configured information about the server we'd
15030          * like to transfer this zone from.
15031          */
15032         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
15033         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
15034         UNLOCK_ZONE(zone);
15035
15036         /*
15037          * Determine the total maximum number of simultaneous
15038          * transfers allowed, and the maximum for this specific
15039          * master.
15040          */
15041         maxtransfersin = zmgr->transfersin;
15042         maxtransfersperns = zmgr->transfersperns;
15043         if (peer != NULL)
15044                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
15045
15046         /*
15047          * Count the total number of transfers that are in progress,
15048          * and the number of transfers in progress from this master.
15049          * We linearly scan a list of all transfers; if this turns
15050          * out to be too slow, we could hash on the master address.
15051          */
15052         nxfrsin = nxfrsperns = 0;
15053         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15054              x != NULL;
15055              x = ISC_LIST_NEXT(x, statelink))
15056         {
15057                 isc_netaddr_t xip;
15058
15059                 LOCK_ZONE(x);
15060                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
15061                 UNLOCK_ZONE(x);
15062
15063                 nxfrsin++;
15064                 if (isc_netaddr_equal(&xip, &masterip))
15065                         nxfrsperns++;
15066         }
15067
15068         /* Enforce quota. */
15069         if (nxfrsin >= maxtransfersin)
15070                 return (ISC_R_QUOTA);
15071
15072         if (nxfrsperns >= maxtransfersperns)
15073                 return (ISC_R_QUOTA);
15074
15075  gotquota:
15076         /*
15077          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
15078          * list and send it an event to let it start the actual transfer in the
15079          * context of its own task.
15080          */
15081         e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
15082                                got_transfer_quota, zone, sizeof(isc_event_t));
15083         if (e == NULL)
15084                 return (ISC_R_NOMEMORY);
15085
15086         LOCK_ZONE(zone);
15087         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
15088         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
15089         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
15090         zone->statelist = &zmgr->xfrin_in_progress;
15091         isc_task_send(zone->task, &e);
15092         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
15093         UNLOCK_ZONE(zone);
15094
15095         return (ISC_R_SUCCESS);
15096 }
15097
15098 void
15099 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
15100
15101         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15102         REQUIRE(iolimit > 0);
15103
15104         zmgr->iolimit = iolimit;
15105 }
15106
15107 isc_uint32_t
15108 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
15109
15110         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15111
15112         return (zmgr->iolimit);
15113 }
15114
15115 /*
15116  * Get permission to request a file handle from the OS.
15117  * An event will be sent to action when one is available.
15118  * There are two queues available (high and low), the high
15119  * queue will be serviced before the low one.
15120  *
15121  * zonemgr_putio() must be called after the event is delivered to
15122  * 'action'.
15123  */
15124
15125 static isc_result_t
15126 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
15127               isc_task_t *task, isc_taskaction_t action, void *arg,
15128               dns_io_t **iop)
15129 {
15130         dns_io_t *io;
15131         isc_boolean_t queue;
15132
15133         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15134         REQUIRE(iop != NULL && *iop == NULL);
15135
15136         io = isc_mem_get(zmgr->mctx, sizeof(*io));
15137         if (io == NULL)
15138                 return (ISC_R_NOMEMORY);
15139
15140         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
15141                                        action, arg, sizeof(*io->event));
15142         if (io->event == NULL) {
15143                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
15144                 return (ISC_R_NOMEMORY);
15145         }
15146
15147         io->zmgr = zmgr;
15148         io->high = high;
15149         io->task = NULL;
15150         isc_task_attach(task, &io->task);
15151         ISC_LINK_INIT(io, link);
15152         io->magic = IO_MAGIC;
15153
15154         LOCK(&zmgr->iolock);
15155         zmgr->ioactive++;
15156         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
15157         if (queue) {
15158                 if (io->high)
15159                         ISC_LIST_APPEND(zmgr->high, io, link);
15160                 else
15161                         ISC_LIST_APPEND(zmgr->low, io, link);
15162         }
15163         UNLOCK(&zmgr->iolock);
15164         *iop = io;
15165
15166         if (!queue)
15167                 isc_task_send(io->task, &io->event);
15168         return (ISC_R_SUCCESS);
15169 }
15170
15171 static void
15172 zonemgr_putio(dns_io_t **iop) {
15173         dns_io_t *io;
15174         dns_io_t *next;
15175         dns_zonemgr_t *zmgr;
15176
15177         REQUIRE(iop != NULL);
15178         io = *iop;
15179         REQUIRE(DNS_IO_VALID(io));
15180
15181         *iop = NULL;
15182
15183         INSIST(!ISC_LINK_LINKED(io, link));
15184         INSIST(io->event == NULL);
15185
15186         zmgr = io->zmgr;
15187         isc_task_detach(&io->task);
15188         io->magic = 0;
15189         isc_mem_put(zmgr->mctx, io, sizeof(*io));
15190
15191         LOCK(&zmgr->iolock);
15192         INSIST(zmgr->ioactive > 0);
15193         zmgr->ioactive--;
15194         next = HEAD(zmgr->high);
15195         if (next == NULL)
15196                 next = HEAD(zmgr->low);
15197         if (next != NULL) {
15198                 if (next->high)
15199                         ISC_LIST_UNLINK(zmgr->high, next, link);
15200                 else
15201                         ISC_LIST_UNLINK(zmgr->low, next, link);
15202                 INSIST(next->event != NULL);
15203         }
15204         UNLOCK(&zmgr->iolock);
15205         if (next != NULL)
15206                 isc_task_send(next->task, &next->event);
15207 }
15208
15209 static void
15210 zonemgr_cancelio(dns_io_t *io) {
15211         isc_boolean_t send_event = ISC_FALSE;
15212
15213         REQUIRE(DNS_IO_VALID(io));
15214
15215         /*
15216          * If we are queued to be run then dequeue.
15217          */
15218         LOCK(&io->zmgr->iolock);
15219         if (ISC_LINK_LINKED(io, link)) {
15220                 if (io->high)
15221                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
15222                 else
15223                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
15224
15225                 send_event = ISC_TRUE;
15226                 INSIST(io->event != NULL);
15227         }
15228         UNLOCK(&io->zmgr->iolock);
15229         if (send_event) {
15230                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
15231                 isc_task_send(io->task, &io->event);
15232         }
15233 }
15234
15235 static void
15236 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
15237         char *buf;
15238         int buflen;
15239         isc_result_t result;
15240
15241         buflen = strlen(path) + strlen(templat) + 2;
15242
15243         buf = isc_mem_get(zone->mctx, buflen);
15244         if (buf == NULL)
15245                 return;
15246
15247         result = isc_file_template(path, templat, buf, buflen);
15248         if (result != ISC_R_SUCCESS)
15249                 goto cleanup;
15250
15251         result = isc_file_renameunique(path, buf);
15252         if (result != ISC_R_SUCCESS)
15253                 goto cleanup;
15254
15255         dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
15256                      "renaming file to '%s' for failure analysis and "
15257                      "retransferring.", path, buf);
15258
15259  cleanup:
15260         isc_mem_put(zone->mctx, buf, buflen);
15261 }
15262
15263 #if 0
15264 /* Hook for ondestroy notification from a database. */
15265
15266 static void
15267 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
15268         dns_db_t *db = event->sender;
15269         UNUSED(task);
15270
15271         isc_event_free(&event);
15272
15273         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15274                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15275                       "database (%p) destroyed", (void*) db);
15276 }
15277 #endif
15278
15279 void
15280 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
15281         isc_interval_t interval;
15282         isc_uint32_t s, ns;
15283         isc_uint32_t pertic;
15284         isc_result_t result;
15285
15286         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15287
15288         if (value == 0)
15289                 value = 1;
15290
15291         if (value == 1) {
15292                 s = 1;
15293                 ns = 0;
15294                 pertic = 1;
15295         } else if (value <= 10) {
15296                 s = 0;
15297                 ns = 1000000000 / value;
15298                 pertic = 1;
15299         } else {
15300                 s = 0;
15301                 ns = (1000000000 / value) * 10;
15302                 pertic = 10;
15303         }
15304
15305         isc_interval_set(&interval, s, ns);
15306
15307         result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval);
15308         RUNTIME_CHECK(result == ISC_R_SUCCESS);
15309         isc_ratelimiter_setpertic(zmgr->notifyrl, pertic);
15310
15311         result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval);
15312         RUNTIME_CHECK(result == ISC_R_SUCCESS);
15313         isc_ratelimiter_setpertic(zmgr->refreshrl, pertic);
15314
15315         zmgr->serialqueryrate = value;
15316 }
15317
15318 unsigned int
15319 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
15320         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15321
15322         return (zmgr->serialqueryrate);
15323 }
15324
15325 isc_boolean_t
15326 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15327                         isc_sockaddr_t *local, isc_time_t *now)
15328 {
15329         unsigned int i;
15330         isc_rwlocktype_t locktype;
15331         isc_result_t result;
15332         isc_uint32_t seconds = isc_time_seconds(now);
15333         isc_uint32_t count = 0;
15334
15335         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15336
15337         locktype = isc_rwlocktype_read;
15338         RWLOCK(&zmgr->urlock, locktype);
15339         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15340                 if (zmgr->unreachable[i].expire >= seconds &&
15341                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15342                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
15343                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
15344                         if (result == ISC_R_SUCCESS) {
15345                                 locktype = isc_rwlocktype_write;
15346                                 zmgr->unreachable[i].last = seconds;
15347                                 count = zmgr->unreachable[i].count;
15348                         }
15349                         break;
15350                 }
15351         }
15352         RWUNLOCK(&zmgr->urlock, locktype);
15353         return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
15354 }
15355
15356 void
15357 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15358                            isc_sockaddr_t *local)
15359 {
15360         unsigned int i;
15361         isc_rwlocktype_t locktype;
15362         isc_result_t result;
15363
15364         char master[ISC_SOCKADDR_FORMATSIZE];
15365         char source[ISC_SOCKADDR_FORMATSIZE];
15366
15367         isc_sockaddr_format(remote, master, sizeof(master));
15368         isc_sockaddr_format(local, source, sizeof(source));
15369
15370         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15371
15372         locktype = isc_rwlocktype_read;
15373         RWLOCK(&zmgr->urlock, locktype);
15374         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15375                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15376                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
15377                         if (zmgr->unreachable[i].expire == 0)
15378                                 break;
15379                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
15380                         if (result == ISC_R_SUCCESS) {
15381                                 locktype = isc_rwlocktype_write;
15382                                 zmgr->unreachable[i].expire = 0;
15383                                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15384                                               DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
15385                                               "master %s (source %s) deleted "
15386                                               "from unreachable cache",
15387                                               master, source);
15388                         }
15389                         break;
15390                 }
15391         }
15392         RWUNLOCK(&zmgr->urlock, locktype);
15393 }
15394
15395 void
15396 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15397                            isc_sockaddr_t *local, isc_time_t *now)
15398 {
15399         isc_uint32_t seconds = isc_time_seconds(now);
15400         isc_uint32_t last = seconds;
15401         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
15402
15403         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15404
15405         RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
15406         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15407                 /* Existing entry? */
15408                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15409                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
15410                         break;
15411                 /* Empty slot? */
15412                 if (zmgr->unreachable[i].expire < seconds)
15413                         slot = i;
15414                 /* Least recently used slot? */
15415                 if (zmgr->unreachable[i].last < last) {
15416                         last = zmgr->unreachable[i].last;
15417                         oldest = i;
15418                 }
15419         }
15420         if (i < UNREACH_CHACHE_SIZE) {
15421                 /*
15422                  * Found a existing entry.  Update the expire timer and
15423                  * last usage timestamps.
15424                  */
15425                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
15426                 zmgr->unreachable[i].last = seconds;
15427                 if (zmgr->unreachable[i].expire < seconds)
15428                         zmgr->unreachable[i].count = 1;
15429                 else
15430                         zmgr->unreachable[i].count++;
15431         } else if (slot != UNREACH_CHACHE_SIZE) {
15432                 /*
15433                  * Found a empty slot. Add a new entry to the cache.
15434                  */
15435                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
15436                 zmgr->unreachable[slot].last = seconds;
15437                 zmgr->unreachable[slot].remote = *remote;
15438                 zmgr->unreachable[slot].local = *local;
15439                 zmgr->unreachable[slot].count = 1;
15440         } else {
15441                 /*
15442                  * Replace the least recently used entry in the cache.
15443                  */
15444                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
15445                 zmgr->unreachable[oldest].last = seconds;
15446                 zmgr->unreachable[oldest].remote = *remote;
15447                 zmgr->unreachable[oldest].local = *local;
15448                 zmgr->unreachable[oldest].count = 1;
15449         }
15450         RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
15451 }
15452
15453 void
15454 dns_zone_forcereload(dns_zone_t *zone) {
15455         REQUIRE(DNS_ZONE_VALID(zone));
15456
15457         if (zone->type == dns_zone_master ||
15458             (zone->type == dns_zone_redirect && zone->masters == NULL))
15459                 return;
15460
15461         LOCK_ZONE(zone);
15462         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
15463         UNLOCK_ZONE(zone);
15464         dns_zone_refresh(zone);
15465 }
15466
15467 isc_boolean_t
15468 dns_zone_isforced(dns_zone_t *zone) {
15469         REQUIRE(DNS_ZONE_VALID(zone));
15470
15471         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
15472 }
15473
15474 isc_result_t
15475 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
15476         /*
15477          * This function is obsoleted.
15478          */
15479         UNUSED(zone);
15480         UNUSED(on);
15481         return (ISC_R_NOTIMPLEMENTED);
15482 }
15483
15484 isc_uint64_t *
15485 dns_zone_getstatscounters(dns_zone_t *zone) {
15486         /*
15487          * This function is obsoleted.
15488          */
15489         UNUSED(zone);
15490         return (NULL);
15491 }
15492
15493 void
15494 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
15495         REQUIRE(DNS_ZONE_VALID(zone));
15496         REQUIRE(zone->stats == NULL);
15497
15498         LOCK_ZONE(zone);
15499         zone->stats = NULL;
15500         isc_stats_attach(stats, &zone->stats);
15501         UNLOCK_ZONE(zone);
15502 }
15503
15504 void
15505 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
15506
15507         REQUIRE(DNS_ZONE_VALID(zone));
15508
15509         LOCK_ZONE(zone);
15510         if (zone->requeststats_on && stats == NULL)
15511                 zone->requeststats_on = ISC_FALSE;
15512         else if (!zone->requeststats_on && stats != NULL) {
15513                 if (zone->requeststats == NULL) {
15514                         isc_stats_attach(stats, &zone->requeststats);
15515                         zone->requeststats_on = ISC_TRUE;
15516                 }
15517         }
15518         UNLOCK_ZONE(zone);
15519 }
15520
15521 #ifdef NEWSTATS
15522 void
15523 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
15524
15525         REQUIRE(DNS_ZONE_VALID(zone));
15526
15527         LOCK_ZONE(zone);
15528         if (zone->requeststats_on && stats != NULL) {
15529                 if (zone->rcvquerystats == NULL) {
15530                         dns_stats_attach(stats, &zone->rcvquerystats);
15531                         zone->requeststats_on = ISC_TRUE;
15532                 }
15533         }
15534         UNLOCK_ZONE(zone);
15535 }
15536 #endif
15537
15538 isc_stats_t *
15539 dns_zone_getrequeststats(dns_zone_t *zone) {
15540         /*
15541          * We don't lock zone for efficiency reason.  This is not catastrophic
15542          * because requeststats must always be valid when requeststats_on is
15543          * true.
15544          * Some counters may be incremented while requeststats_on is becoming
15545          * false, or some cannot be incremented just after the statistics are
15546          * installed, but it shouldn't matter much in practice.
15547          */
15548         if (zone->requeststats_on)
15549                 return (zone->requeststats);
15550         else
15551                 return (NULL);
15552 }
15553
15554 #ifdef NEWSTATS
15555 /*
15556  * Return the received query stats bucket
15557  * see note from dns_zone_getrequeststats()
15558  */
15559 dns_stats_t *
15560 dns_zone_getrcvquerystats(dns_zone_t *zone) {
15561         if (zone->requeststats_on)
15562                 return (zone->rcvquerystats);
15563         else
15564                 return (NULL);
15565 }
15566 #endif
15567
15568 void
15569 dns_zone_dialup(dns_zone_t *zone) {
15570
15571         REQUIRE(DNS_ZONE_VALID(zone));
15572
15573         zone_debuglog(zone, "dns_zone_dialup", 3,
15574                       "notify = %d, refresh = %d",
15575                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
15576                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
15577
15578         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
15579                 dns_zone_notify(zone);
15580         if (zone->type != dns_zone_master && zone->masters != NULL &&
15581             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
15582                 dns_zone_refresh(zone);
15583 }
15584
15585 void
15586 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
15587         REQUIRE(DNS_ZONE_VALID(zone));
15588
15589         LOCK_ZONE(zone);
15590         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
15591                          DNS_ZONEFLG_DIALREFRESH |
15592                          DNS_ZONEFLG_NOREFRESH);
15593         switch (dialup) {
15594         case dns_dialuptype_no:
15595                 break;
15596         case dns_dialuptype_yes:
15597                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
15598                                  DNS_ZONEFLG_DIALREFRESH |
15599                                  DNS_ZONEFLG_NOREFRESH));
15600                 break;
15601         case dns_dialuptype_notify:
15602                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15603                 break;
15604         case dns_dialuptype_notifypassive:
15605                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15606                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15607                 break;
15608         case dns_dialuptype_refresh:
15609                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
15610                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15611                 break;
15612         case dns_dialuptype_passive:
15613                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15614                 break;
15615         default:
15616                 INSIST(0);
15617         }
15618         UNLOCK_ZONE(zone);
15619 }
15620
15621 isc_result_t
15622 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
15623         isc_result_t result = ISC_R_SUCCESS;
15624
15625         REQUIRE(DNS_ZONE_VALID(zone));
15626
15627         LOCK_ZONE(zone);
15628         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
15629         UNLOCK_ZONE(zone);
15630
15631         return (result);
15632 }
15633
15634 const char *
15635 dns_zone_getkeydirectory(dns_zone_t *zone) {
15636         REQUIRE(DNS_ZONE_VALID(zone));
15637
15638         return (zone->keydirectory);
15639 }
15640
15641 unsigned int
15642 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
15643         dns_zone_t *zone;
15644         unsigned int count = 0;
15645
15646         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15647
15648         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15649         switch (state) {
15650         case DNS_ZONESTATE_XFERRUNNING:
15651                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15652                      zone != NULL;
15653                      zone = ISC_LIST_NEXT(zone, statelink))
15654                         count++;
15655                 break;
15656         case DNS_ZONESTATE_XFERDEFERRED:
15657                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
15658                      zone != NULL;
15659                      zone = ISC_LIST_NEXT(zone, statelink))
15660                         count++;
15661                 break;
15662         case DNS_ZONESTATE_SOAQUERY:
15663                 for (zone = ISC_LIST_HEAD(zmgr->zones);
15664                      zone != NULL;
15665                      zone = ISC_LIST_NEXT(zone, link))
15666                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
15667                                 count++;
15668                 break;
15669         case DNS_ZONESTATE_ANY:
15670                 for (zone = ISC_LIST_HEAD(zmgr->zones);
15671                      zone != NULL;
15672                      zone = ISC_LIST_NEXT(zone, link)) {
15673                         dns_view_t *view = zone->view;
15674                         if (view != NULL && strcmp(view->name, "_bind") == 0)
15675                                 continue;
15676                         count++;
15677                 }
15678                 break;
15679         default:
15680                 INSIST(0);
15681         }
15682
15683         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15684
15685         return (count);
15686 }
15687
15688 isc_result_t
15689 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
15690         isc_boolean_t ok = ISC_TRUE;
15691         isc_boolean_t fail = ISC_FALSE;
15692         char namebuf[DNS_NAME_FORMATSIZE];
15693         char namebuf2[DNS_NAME_FORMATSIZE];
15694         char typebuf[DNS_RDATATYPE_FORMATSIZE];
15695         int level = ISC_LOG_WARNING;
15696         dns_name_t bad;
15697
15698         REQUIRE(DNS_ZONE_VALID(zone));
15699
15700         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
15701                 return (ISC_R_SUCCESS);
15702
15703         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
15704                 level = ISC_LOG_ERROR;
15705                 fail = ISC_TRUE;
15706         }
15707
15708         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
15709         if (!ok) {
15710                 dns_name_format(name, namebuf, sizeof(namebuf));
15711                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
15712                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
15713                              dns_result_totext(DNS_R_BADOWNERNAME));
15714                 if (fail)
15715                         return (DNS_R_BADOWNERNAME);
15716         }
15717
15718         dns_name_init(&bad, NULL);
15719         ok = dns_rdata_checknames(rdata, name, &bad);
15720         if (!ok) {
15721                 dns_name_format(name, namebuf, sizeof(namebuf));
15722                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
15723                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
15724                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
15725                              namebuf2, dns_result_totext(DNS_R_BADNAME));
15726                 if (fail)
15727                         return (DNS_R_BADNAME);
15728         }
15729
15730         return (ISC_R_SUCCESS);
15731 }
15732
15733 void
15734 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
15735         REQUIRE(DNS_ZONE_VALID(zone));
15736         zone->checkmx = checkmx;
15737 }
15738
15739 void
15740 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
15741         REQUIRE(DNS_ZONE_VALID(zone));
15742         zone->checksrv = checksrv;
15743 }
15744
15745 void
15746 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
15747         REQUIRE(DNS_ZONE_VALID(zone));
15748         zone->checkns = checkns;
15749 }
15750
15751 void
15752 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
15753         REQUIRE(DNS_ZONE_VALID(zone));
15754
15755         LOCK_ZONE(zone);
15756         zone->isself = isself;
15757         zone->isselfarg = arg;
15758         UNLOCK_ZONE(zone);
15759 }
15760
15761 void
15762 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
15763         REQUIRE(DNS_ZONE_VALID(zone));
15764
15765         LOCK_ZONE(zone);
15766         zone->notifydelay = delay;
15767         UNLOCK_ZONE(zone);
15768 }
15769
15770 isc_uint32_t
15771 dns_zone_getnotifydelay(dns_zone_t *zone) {
15772         REQUIRE(DNS_ZONE_VALID(zone));
15773
15774         return (zone->notifydelay);
15775 }
15776
15777 isc_result_t
15778 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
15779                      isc_uint16_t keyid, isc_boolean_t delete)
15780 {
15781         isc_result_t result;
15782         REQUIRE(DNS_ZONE_VALID(zone));
15783
15784         dns_zone_log(zone, ISC_LOG_NOTICE,
15785                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
15786                      algorithm, keyid);
15787         LOCK_ZONE(zone);
15788         result = zone_signwithkey(zone, algorithm, keyid, delete);
15789         UNLOCK_ZONE(zone);
15790
15791         return (result);
15792 }
15793
15794 static const char *hex = "0123456789ABCDEF";
15795
15796 isc_result_t
15797 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
15798         isc_result_t result;
15799         char salt[255*2+1];
15800         unsigned int i, j;
15801
15802         REQUIRE(DNS_ZONE_VALID(zone));
15803
15804         if (nsec3param->salt_length != 0) {
15805                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
15806                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
15807                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
15808                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
15809                 }
15810                 salt[j] = '\0';
15811         } else
15812                 strcpy(salt, "-");
15813         dns_zone_log(zone, ISC_LOG_NOTICE,
15814                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
15815                      nsec3param->hash, nsec3param->iterations,
15816                      salt);
15817         LOCK_ZONE(zone);
15818         result = zone_addnsec3chain(zone, nsec3param);
15819         UNLOCK_ZONE(zone);
15820
15821         return (result);
15822 }
15823
15824 void
15825 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
15826         REQUIRE(DNS_ZONE_VALID(zone));
15827
15828         if (nodes == 0)
15829                 nodes = 1;
15830         zone->nodes = nodes;
15831 }
15832
15833 void
15834 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
15835         REQUIRE(DNS_ZONE_VALID(zone));
15836
15837         /*
15838          * We treat signatures as a signed value so explicitly
15839          * limit its range here.
15840          */
15841         if (signatures > ISC_INT32_MAX)
15842                 signatures = ISC_INT32_MAX;
15843         else if (signatures == 0)
15844                 signatures = 1;
15845         zone->signatures = signatures;
15846 }
15847
15848 void
15849 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
15850         REQUIRE(DNS_ZONE_VALID(zone));
15851         zone->privatetype = type;
15852 }
15853
15854 dns_rdatatype_t
15855 dns_zone_getprivatetype(dns_zone_t *zone) {
15856         REQUIRE(DNS_ZONE_VALID(zone));
15857         return (zone->privatetype);
15858 }
15859
15860 static isc_result_t
15861 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
15862                  isc_boolean_t delete)
15863 {
15864         dns_signing_t *signing;
15865         dns_signing_t *current;
15866         isc_result_t result = ISC_R_SUCCESS;
15867         isc_time_t now;
15868         dns_db_t *db = NULL;
15869
15870         signing = isc_mem_get(zone->mctx, sizeof *signing);
15871         if (signing == NULL)
15872                 return (ISC_R_NOMEMORY);
15873
15874         signing->magic = 0;
15875         signing->db  = NULL;
15876         signing->dbiterator = NULL;
15877         signing->algorithm = algorithm;
15878         signing->keyid = keyid;
15879         signing->delete = delete;
15880         signing->done = ISC_FALSE;
15881
15882         TIME_NOW(&now);
15883
15884         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15885         if (zone->db != NULL)
15886                 dns_db_attach(zone->db, &db);
15887         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15888
15889         if (db == NULL) {
15890                 result = ISC_R_NOTFOUND;
15891                 goto cleanup;
15892         }
15893
15894         dns_db_attach(db, &signing->db);
15895
15896         for (current = ISC_LIST_HEAD(zone->signing);
15897              current != NULL;
15898              current = ISC_LIST_NEXT(current, link)) {
15899                 if (current->db == signing->db &&
15900                     current->algorithm == signing->algorithm &&
15901                     current->keyid == signing->keyid) {
15902                         if (current->delete != signing->delete)
15903                                 current->done = ISC_TRUE;
15904                         else
15905                                 goto cleanup;
15906                 }
15907         }
15908
15909         result = dns_db_createiterator(signing->db, 0,
15910                                        &signing->dbiterator);
15911
15912         if (result == ISC_R_SUCCESS)
15913                 result = dns_dbiterator_first(signing->dbiterator);
15914         if (result == ISC_R_SUCCESS) {
15915                 dns_dbiterator_pause(signing->dbiterator);
15916                 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
15917                 signing = NULL;
15918                 if (isc_time_isepoch(&zone->signingtime)) {
15919                         zone->signingtime = now;
15920                         if (zone->task != NULL)
15921                                 zone_settimer(zone, &now);
15922                 }
15923         }
15924
15925  cleanup:
15926         if (signing != NULL) {
15927                 if (signing->db != NULL)
15928                         dns_db_detach(&signing->db);
15929                 if (signing->dbiterator != NULL)
15930                         dns_dbiterator_destroy(&signing->dbiterator);
15931                 isc_mem_put(zone->mctx, signing, sizeof *signing);
15932         }
15933         if (db != NULL)
15934                 dns_db_detach(&db);
15935         return (result);
15936 }
15937
15938 static void
15939 logmsg(const char *format, ...) {
15940         va_list args;
15941         va_start(args, format);
15942         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
15943                        ISC_LOG_DEBUG(1), format, args);
15944         va_end(args);
15945 }
15946
15947 static void
15948 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
15949         dns_dnsseckey_t *key;
15950         while (!ISC_LIST_EMPTY(*list)) {
15951                 key = ISC_LIST_HEAD(*list);
15952                 ISC_LIST_UNLINK(*list, key, link);
15953                 dns_dnsseckey_destroy(mctx, &key);
15954         }
15955 }
15956
15957 /* Called once; *timep should be set to the current time. */
15958 static isc_result_t
15959 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
15960         isc_result_t result;
15961         isc_stdtime_t now, then = 0, event;
15962         int i;
15963
15964         now = *timep;
15965
15966         for (i = 0; i <= DST_MAX_TIMES; i++) {
15967                 result = dst_key_gettime(key, i, &event);
15968                 if (result == ISC_R_SUCCESS && event > now &&
15969                     (then == 0 || event < then))
15970                         then = event;
15971         }
15972
15973         if (then != 0) {
15974                 *timep = then;
15975                 return (ISC_R_SUCCESS);
15976         }
15977
15978         return (ISC_R_NOTFOUND);
15979 }
15980
15981 static isc_result_t
15982 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
15983           const dns_rdata_t *rdata, isc_boolean_t *flag)
15984 {
15985         dns_rdataset_t rdataset;
15986         dns_dbnode_t *node = NULL;
15987         isc_result_t result;
15988
15989         dns_rdataset_init(&rdataset);
15990         if (rdata->type == dns_rdatatype_nsec3)
15991                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
15992         else
15993                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
15994         result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
15995                                      (isc_stdtime_t) 0, &rdataset, NULL);
15996         if (result == ISC_R_NOTFOUND) {
15997                 *flag = ISC_FALSE;
15998                 result = ISC_R_SUCCESS;
15999                 goto failure;
16000         }
16001
16002         for (result = dns_rdataset_first(&rdataset);
16003              result == ISC_R_SUCCESS;
16004              result = dns_rdataset_next(&rdataset)) {
16005                 dns_rdata_t myrdata = DNS_RDATA_INIT;
16006                 dns_rdataset_current(&rdataset, &myrdata);
16007                 if (!dns_rdata_compare(&myrdata, rdata))
16008                         break;
16009         }
16010         dns_rdataset_disassociate(&rdataset);
16011         if (result == ISC_R_SUCCESS) {
16012                 *flag = ISC_TRUE;
16013         } else if (result == ISC_R_NOMORE) {
16014                 *flag = ISC_FALSE;
16015                 result = ISC_R_SUCCESS;
16016         }
16017
16018  failure:
16019         if (node != NULL)
16020                 dns_db_detachnode(db, &node);
16021         return (result);
16022 }
16023
16024 /*
16025  * Add records to signal the state of signing or of key removal.
16026  */
16027 static isc_result_t
16028 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
16029                     dns_dbversion_t *ver, dns_diff_t *diff,
16030                     isc_boolean_t sign_all)
16031 {
16032         dns_difftuple_t *tuple, *newtuple = NULL;
16033         dns_rdata_dnskey_t dnskey;
16034         dns_rdata_t rdata = DNS_RDATA_INIT;
16035         isc_boolean_t flag;
16036         isc_region_t r;
16037         isc_result_t result = ISC_R_SUCCESS;
16038         isc_uint16_t keyid;
16039         unsigned char buf[5];
16040         dns_name_t *name = dns_db_origin(db);
16041
16042         for (tuple = ISC_LIST_HEAD(diff->tuples);
16043              tuple != NULL;
16044              tuple = ISC_LIST_NEXT(tuple, link)) {
16045                 if (tuple->rdata.type != dns_rdatatype_dnskey)
16046                         continue;
16047
16048                 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
16049                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16050                 if ((dnskey.flags &
16051                      (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
16052                          != DNS_KEYOWNER_ZONE)
16053                         continue;
16054
16055                 dns_rdata_toregion(&tuple->rdata, &r);
16056
16057                 keyid = dst_region_computeid(&r, dnskey.algorithm);
16058
16059                 buf[0] = dnskey.algorithm;
16060                 buf[1] = (keyid & 0xff00) >> 8;
16061                 buf[2] = (keyid & 0xff);
16062                 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
16063                 buf[4] = 0;
16064                 rdata.data = buf;
16065                 rdata.length = sizeof(buf);
16066                 rdata.type = privatetype;
16067                 rdata.rdclass = tuple->rdata.rdclass;
16068
16069                 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
16070                         CHECK(rr_exists(db, ver, name, &rdata, &flag));
16071                         if (flag)
16072                                 continue;
16073                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
16074                                                    name, 0, &rdata, &newtuple));
16075                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
16076                         INSIST(newtuple == NULL);
16077                 }
16078
16079                 /*
16080                  * Remove any record which says this operation has already
16081                  * completed.
16082                  */
16083                 buf[4] = 1;
16084                 CHECK(rr_exists(db, ver, name, &rdata, &flag));
16085                 if (flag) {
16086                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
16087                                                    name, 0, &rdata, &newtuple));
16088                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
16089                         INSIST(newtuple == NULL);
16090                 }
16091         }
16092  failure:
16093         return (result);
16094 }
16095
16096 static isc_result_t
16097 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16098           dns_diff_t *diff, zonediff_t *zonediff)
16099 {
16100         isc_result_t result;
16101         isc_stdtime_t now, inception, soaexpire;
16102         isc_boolean_t check_ksk, keyset_kskonly;
16103         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
16104         unsigned int nkeys = 0, i;
16105         dns_difftuple_t *tuple;
16106
16107         result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
16108                                 zone_keys, &nkeys);
16109         if (result != ISC_R_SUCCESS) {
16110                 dns_zone_log(zone, ISC_LOG_ERROR,
16111                              "sign_apex:find_zone_keys -> %s",
16112                              dns_result_totext(result));
16113                 return (result);
16114         }
16115
16116         isc_stdtime_get(&now);
16117         inception = now - 3600; /* Allow for clock skew. */
16118         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
16119
16120         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16121         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
16122
16123         /*
16124          * See if update_sigs will update DNSKEY signature and if not
16125          * cause them to sign so that so that newly activated keys
16126          * are used.
16127          */
16128         for (tuple = ISC_LIST_HEAD(diff->tuples);
16129              tuple != NULL;
16130              tuple = ISC_LIST_NEXT(tuple, link)) {
16131                 if (tuple->rdata.type == dns_rdatatype_dnskey &&
16132                     dns_name_equal(&tuple->name, &zone->origin))
16133                         break;
16134         }
16135
16136         if (tuple == NULL) {
16137                 result = del_sigs(zone, db, ver, &zone->origin,
16138                                   dns_rdatatype_dnskey, zonediff,
16139                                   zone_keys, nkeys, now, ISC_FALSE);
16140                 if (result != ISC_R_SUCCESS) {
16141                         dns_zone_log(zone, ISC_LOG_ERROR,
16142                                      "sign_apex:del_sigs -> %s",
16143                                      dns_result_totext(result));
16144                         goto failure;
16145                 }
16146                 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
16147                                   zonediff->diff, zone_keys, nkeys, zone->mctx,
16148                                   inception, soaexpire, check_ksk,
16149                                   keyset_kskonly);
16150                 if (result != ISC_R_SUCCESS) {
16151                         dns_zone_log(zone, ISC_LOG_ERROR,
16152                                      "sign_apex:add_sigs -> %s",
16153                                      dns_result_totext(result));
16154                         goto failure;
16155                 }
16156         }
16157
16158         result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
16159                              inception, soaexpire, now, check_ksk,
16160                              keyset_kskonly, zonediff);
16161
16162         if (result != ISC_R_SUCCESS) {
16163                 dns_zone_log(zone, ISC_LOG_ERROR,
16164                              "sign_apex:update_sigs -> %s",
16165                              dns_result_totext(result));
16166                 goto failure;
16167         }
16168
16169  failure:
16170         for (i = 0; i < nkeys; i++)
16171                 dst_key_free(&zone_keys[i]);
16172         return (result);
16173 }
16174
16175 /*
16176  * Prevent the zone entering a inconsistent state where
16177  * NSEC only DNSKEYs are present with NSEC3 chains.
16178  * See update.c:check_dnssec()
16179  */
16180 static isc_boolean_t
16181 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16182             dns_diff_t *diff)
16183 {
16184         isc_result_t result;
16185         dns_difftuple_t *tuple;
16186         isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
16187         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
16188
16189         /* Scan the tuples for an NSEC-only DNSKEY */
16190         for (tuple = ISC_LIST_HEAD(diff->tuples);
16191              tuple != NULL;
16192              tuple = ISC_LIST_NEXT(tuple, link)) {
16193                 isc_uint8_t alg;
16194                 if (tuple->rdata.type != dns_rdatatype_dnskey ||
16195                     tuple->op != DNS_DIFFOP_ADD)
16196                         continue;
16197
16198                 alg = tuple->rdata.data[3];
16199                 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
16200                     alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
16201                         nseconly = ISC_TRUE;
16202                         break;
16203                 }
16204         }
16205
16206         /* Check existing DB for NSEC-only DNSKEY */
16207         if (!nseconly) {
16208                 result = dns_nsec_nseconly(db, ver, &nseconly);
16209                 if (result == ISC_R_NOTFOUND)
16210                         result = ISC_R_SUCCESS;
16211                 CHECK(result);
16212         }
16213
16214         /* Check existing DB for NSEC3 */
16215         if (!nsec3)
16216                 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
16217                                         privatetype, &nsec3));
16218
16219         /* Refuse to allow NSEC3 with NSEC-only keys */
16220         if (nseconly && nsec3) {
16221                 dns_zone_log(zone, ISC_LOG_ERROR,
16222                            "NSEC only DNSKEYs and NSEC3 chains not allowed");
16223                 goto failure;
16224         }
16225
16226         return (ISC_TRUE);
16227
16228  failure:
16229         return (ISC_FALSE);
16230 }
16231
16232 static isc_result_t
16233 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16234                  dns_diff_t *diff)
16235 {
16236         isc_result_t result;
16237         dns_dbnode_t *node = NULL;
16238         dns_rdataset_t rdataset;
16239
16240         dns_rdataset_init(&rdataset);
16241         CHECK(dns_db_getoriginnode(db, &node));
16242
16243         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16244                                      dns_rdatatype_none, 0, &rdataset, NULL);
16245         if (dns_rdataset_isassociated(&rdataset))
16246                 dns_rdataset_disassociate(&rdataset);
16247         if (result != ISC_R_NOTFOUND)
16248                 goto failure;
16249
16250         result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
16251
16252  failure:
16253         if (node != NULL)
16254                 dns_db_detachnode(db, &node);
16255         return (result);
16256 }
16257
16258 /*
16259  * Given an RRSIG rdataset and an algorithm, determine whether there
16260  * are any signatures using that algorithm.
16261  */
16262 static isc_boolean_t
16263 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
16264         dns_rdata_t rdata = DNS_RDATA_INIT;
16265         dns_rdata_rrsig_t rrsig;
16266         isc_result_t result;
16267
16268         REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
16269         if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
16270                 return (ISC_FALSE);
16271         }
16272
16273         for (result = dns_rdataset_first(rdataset);
16274              result == ISC_R_SUCCESS;
16275              result = dns_rdataset_next(rdataset))
16276         {
16277                 dns_rdataset_current(rdataset, &rdata);
16278                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
16279                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16280                 dns_rdata_reset(&rdata);
16281                 if (rrsig.algorithm == alg)
16282                         return (ISC_TRUE);
16283         }
16284
16285         return (ISC_FALSE);
16286 }
16287
16288 static isc_result_t
16289 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16290            dns_diff_t *diff)
16291 {
16292         dns_name_t *origin;
16293         isc_boolean_t build_nsec3;
16294         isc_result_t result;
16295
16296         origin = dns_db_origin(db);
16297         CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
16298                                  &build_nsec3));
16299         if (build_nsec3)
16300                 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
16301                                            ISC_FALSE, zone->privatetype, diff));
16302         CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
16303
16304  failure:
16305         return (result);
16306 }
16307
16308 static void
16309 zone_rekey(dns_zone_t *zone) {
16310         isc_result_t result;
16311         dns_db_t *db = NULL;
16312         dns_dbnode_t *node = NULL;
16313         dns_dbversion_t *ver = NULL;
16314         dns_rdataset_t soaset, soasigs, keyset, keysigs;
16315         dns_dnsseckeylist_t dnskeys, keys, rmkeys;
16316         dns_dnsseckey_t *key;
16317         dns_diff_t diff, _sig_diff;
16318         zonediff_t zonediff;
16319         isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
16320         isc_boolean_t newalg = ISC_FALSE;
16321         isc_boolean_t fullsign;
16322         dns_ttl_t ttl = 3600;
16323         const char *dir;
16324         isc_mem_t *mctx;
16325         isc_stdtime_t now;
16326         isc_time_t timenow;
16327         isc_interval_t ival;
16328         char timebuf[80];
16329
16330         REQUIRE(DNS_ZONE_VALID(zone));
16331
16332         ISC_LIST_INIT(dnskeys);
16333         ISC_LIST_INIT(keys);
16334         ISC_LIST_INIT(rmkeys);
16335         dns_rdataset_init(&soaset);
16336         dns_rdataset_init(&soasigs);
16337         dns_rdataset_init(&keyset);
16338         dns_rdataset_init(&keysigs);
16339         dir = dns_zone_getkeydirectory(zone);
16340         mctx = zone->mctx;
16341         dns_diff_init(mctx, &diff);
16342         dns_diff_init(mctx, &_sig_diff);
16343         zonediff_init(&zonediff, &_sig_diff);
16344
16345         CHECK(dns_zone_getdb(zone, &db));
16346         CHECK(dns_db_newversion(db, &ver));
16347         CHECK(dns_db_getoriginnode(db, &node));
16348
16349         TIME_NOW(&timenow);
16350         now = isc_time_seconds(&timenow);
16351
16352         dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
16353
16354         /* Get the SOA record's TTL */
16355         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
16356                                   dns_rdatatype_none, 0, &soaset, &soasigs));
16357         ttl = soaset.ttl;
16358         dns_rdataset_disassociate(&soaset);
16359
16360         /* Get the DNSKEY rdataset */
16361         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16362                                      dns_rdatatype_none, 0, &keyset, &keysigs);
16363         if (result == ISC_R_SUCCESS) {
16364                 ttl = keyset.ttl;
16365                 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
16366                                                      mctx, &keyset,
16367                                                      &keysigs, &soasigs,
16368                                                      ISC_FALSE, ISC_FALSE,
16369                                                      &dnskeys));
16370         } else if (result != ISC_R_NOTFOUND)
16371                 goto failure;
16372
16373         /*
16374          * True when called from "rndc sign".  Indicates the zone should be
16375          * fully signed now.
16376          */
16377         fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
16378
16379         result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
16380         if (result == ISC_R_SUCCESS) {
16381                 isc_boolean_t check_ksk;
16382                 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16383
16384                 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
16385                                                &zone->origin, ttl, &diff,
16386                                                ISC_TF(!check_ksk),
16387                                                mctx, logmsg);
16388
16389                 /* Keys couldn't be updated for some reason;
16390                  * try again later. */
16391                 if (result != ISC_R_SUCCESS) {
16392                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
16393                                      "couldn't update zone keys: %s",
16394                                      isc_result_totext(result));
16395                         goto failure;
16396                 }
16397
16398                 /*
16399                  * See if any pre-existing keys have newly become active;
16400                  * also, see if any new key is for a new algorithm, as in that
16401                  * event, we need to sign the zone fully.  (If there's a new
16402                  * key, but it's for an already-existing algorithm, then
16403                  * the zone signing can be handled incrementally.)
16404                  */
16405                 for (key = ISC_LIST_HEAD(dnskeys);
16406                      key != NULL;
16407                      key = ISC_LIST_NEXT(key, link)) {
16408                         if (!key->first_sign)
16409                                 continue;
16410
16411                         newactive = ISC_TRUE;
16412
16413                         if (!dns_rdataset_isassociated(&keysigs)) {
16414                                 newalg = ISC_TRUE;
16415                                 break;
16416                         }
16417
16418                         if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
16419                                 /*
16420                                  * This isn't a new algorithm; clear
16421                                  * first_sign so we won't sign the
16422                                  * whole zone with this key later
16423                                  */
16424                                 key->first_sign = ISC_FALSE;
16425                         } else {
16426                                 newalg = ISC_TRUE;
16427                                 break;
16428                         }
16429                 }
16430
16431                 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
16432                     dnskey_sane(zone, db, ver, &diff)) {
16433                         CHECK(dns_diff_apply(&diff, db, ver));
16434                         CHECK(clean_nsec3param(zone, db, ver, &diff));
16435                         CHECK(add_signing_records(db, zone->privatetype,
16436                                                   ver, &diff,
16437                                                   ISC_TF(newalg || fullsign)));
16438                         CHECK(update_soa_serial(db, ver, &diff, mctx,
16439                                                 zone->updatemethod));
16440                         CHECK(add_chains(zone, db, ver, &diff));
16441                         CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
16442                         CHECK(zone_journal(zone, zonediff.diff, NULL,
16443                                            "zone_rekey"));
16444                         commit = ISC_TRUE;
16445                 }
16446         }
16447
16448         dns_db_closeversion(db, &ver, ISC_TRUE);
16449
16450         if (commit) {
16451                 dns_difftuple_t *tuple;
16452
16453                 LOCK_ZONE(zone);
16454                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16455
16456                 zone_needdump(zone, DNS_DUMP_DELAY);
16457
16458                 zone_settimer(zone, &timenow);
16459
16460                 /* Remove any signatures from removed keys.  */
16461                 if (!ISC_LIST_EMPTY(rmkeys)) {
16462                         for (key = ISC_LIST_HEAD(rmkeys);
16463                              key != NULL;
16464                              key = ISC_LIST_NEXT(key, link)) {
16465                                 result = zone_signwithkey(zone,
16466                                                           dst_key_alg(key->key),
16467                                                           dst_key_id(key->key),
16468                                                           ISC_TRUE);
16469                                 if (result != ISC_R_SUCCESS) {
16470                                         dns_zone_log(zone, ISC_LOG_ERROR,
16471                                              "zone_signwithkey failed: %s",
16472                                              dns_result_totext(result));
16473                                 }
16474                         }
16475                 }
16476
16477                 if (fullsign) {
16478                         /*
16479                          * "rndc sign" was called, so we now sign the zone
16480                          * with all active keys, whether they're new or not.
16481                          */
16482                         for (key = ISC_LIST_HEAD(dnskeys);
16483                              key != NULL;
16484                              key = ISC_LIST_NEXT(key, link)) {
16485                                 if (!key->force_sign && !key->hint_sign)
16486                                         continue;
16487
16488                                 result = zone_signwithkey(zone,
16489                                                           dst_key_alg(key->key),
16490                                                           dst_key_id(key->key),
16491                                                           ISC_FALSE);
16492                                 if (result != ISC_R_SUCCESS) {
16493                                         dns_zone_log(zone, ISC_LOG_ERROR,
16494                                              "zone_signwithkey failed: %s",
16495                                              dns_result_totext(result));
16496                                 }
16497                         }
16498                 } else if (newalg) {
16499                         /*
16500                          * We haven't been told to sign fully, but a new
16501                          * algorithm was added to the DNSKEY.  We sign
16502                          * the full zone, but only with newly active
16503                          * keys.
16504                          */
16505                         for (key = ISC_LIST_HEAD(dnskeys);
16506                              key != NULL;
16507                              key = ISC_LIST_NEXT(key, link)) {
16508                                 if (!key->first_sign)
16509                                         continue;
16510
16511                                 result = zone_signwithkey(zone,
16512                                                           dst_key_alg(key->key),
16513                                                           dst_key_id(key->key),
16514                                                           ISC_FALSE);
16515                                 if (result != ISC_R_SUCCESS) {
16516                                         dns_zone_log(zone, ISC_LOG_ERROR,
16517                                              "zone_signwithkey failed: %s",
16518                                              dns_result_totext(result));
16519                                 }
16520                         }
16521                 }
16522
16523                 /*
16524                  * Clear fullsign flag, if it was set, so we don't do
16525                  * another full signing next time
16526                  */
16527                 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
16528
16529                 /*
16530                  * Cause the zone to add/delete NSEC3 chains for the
16531                  * deferred NSEC3PARAM changes.
16532                  */
16533                 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
16534                      tuple != NULL;
16535                      tuple = ISC_LIST_NEXT(tuple, link)) {
16536                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16537                         dns_rdata_t rdata = DNS_RDATA_INIT;
16538                         dns_rdata_nsec3param_t nsec3param;
16539
16540                         if (tuple->rdata.type != zone->privatetype ||
16541                             tuple->op != DNS_DIFFOP_ADD)
16542                                 continue;
16543
16544                         if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
16545                                                         buf, sizeof(buf)))
16546                                 continue;
16547                         result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
16548                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
16549                         if (nsec3param.flags == 0)
16550                                 continue;
16551
16552                         result = zone_addnsec3chain(zone, &nsec3param);
16553                         if (result != ISC_R_SUCCESS) {
16554                                 dns_zone_log(zone, ISC_LOG_ERROR,
16555                                              "zone_addnsec3chain failed: %s",
16556                                              dns_result_totext(result));
16557                         }
16558                 }
16559
16560                 /*
16561                  * Activate any NSEC3 chain updates that may have
16562                  * been scheduled before this rekey.
16563                  */
16564                 if (fullsign || newalg)
16565                         resume_addnsec3chain(zone);
16566
16567                 /*
16568                  * Schedule the next resigning event
16569                  */
16570                 set_resigntime(zone);
16571                 UNLOCK_ZONE(zone);
16572         }
16573
16574         isc_time_settoepoch(&zone->refreshkeytime);
16575
16576         /*
16577          * If we're doing key maintenance, set the key refresh timer to
16578          * the next scheduled key event or to 'dnssec-loadkeys-interval'
16579          * seconds in the future, whichever is sooner.
16580          */
16581         if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
16582                 isc_time_t timethen;
16583                 isc_stdtime_t then;
16584
16585                 LOCK_ZONE(zone);
16586                 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
16587                                   &timethen);
16588                 zone->refreshkeytime = timethen;
16589                 UNLOCK_ZONE(zone);
16590
16591                 for (key = ISC_LIST_HEAD(dnskeys);
16592                      key != NULL;
16593                      key = ISC_LIST_NEXT(key, link)) {
16594                         then = now;
16595                         result = next_keyevent(key->key, &then);
16596                         if (result != ISC_R_SUCCESS)
16597                                 continue;
16598
16599                         DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
16600                         LOCK_ZONE(zone);
16601                         if (isc_time_compare(&timethen,
16602                                              &zone->refreshkeytime) < 0) {
16603                                 zone->refreshkeytime = timethen;
16604                         }
16605                         UNLOCK_ZONE(zone);
16606                 }
16607
16608                 zone_settimer(zone, &timenow);
16609
16610                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
16611                 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
16612         }
16613
16614  done:
16615         dns_diff_clear(&diff);
16616         dns_diff_clear(&_sig_diff);
16617
16618         clear_keylist(&dnskeys, mctx);
16619         clear_keylist(&keys, mctx);
16620         clear_keylist(&rmkeys, mctx);
16621
16622         if (ver != NULL)
16623                 dns_db_closeversion(db, &ver, ISC_FALSE);
16624         if (dns_rdataset_isassociated(&keyset))
16625                 dns_rdataset_disassociate(&keyset);
16626         if (dns_rdataset_isassociated(&keysigs))
16627                 dns_rdataset_disassociate(&keysigs);
16628         if (dns_rdataset_isassociated(&soasigs))
16629                 dns_rdataset_disassociate(&soasigs);
16630         if (node != NULL)
16631                 dns_db_detachnode(db, &node);
16632         if (db != NULL)
16633                 dns_db_detach(&db);
16634         return;
16635
16636  failure:
16637         /*
16638          * Something went wrong; try again in ten minutes or
16639          * after a key refresh interval, whichever is shorter.
16640          */
16641         isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
16642         isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
16643         goto done;
16644 }
16645
16646 void
16647 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
16648         isc_time_t now;
16649
16650         if (zone->type == dns_zone_master && zone->task != NULL) {
16651                 LOCK_ZONE(zone);
16652
16653                 if (fullsign)
16654                         zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
16655
16656                 TIME_NOW(&now);
16657                 zone->refreshkeytime = now;
16658                 zone_settimer(zone, &now);
16659
16660                 UNLOCK_ZONE(zone);
16661         }
16662 }
16663
16664 isc_result_t
16665 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
16666                  unsigned int *errors)
16667 {
16668         isc_result_t result;
16669         dns_dbnode_t *node = NULL;
16670
16671         REQUIRE(DNS_ZONE_VALID(zone));
16672         REQUIRE(errors != NULL);
16673
16674         result = dns_db_getoriginnode(db, &node);
16675         if (result != ISC_R_SUCCESS)
16676                 return (result);
16677         result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
16678                                   ISC_FALSE);
16679         dns_db_detachnode(db, &node);
16680         return (result);
16681 }
16682
16683 void
16684 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
16685         REQUIRE(DNS_ZONE_VALID(zone));
16686         LOCK_ZONE(zone);
16687         zone->added = added;
16688         UNLOCK_ZONE(zone);
16689 }
16690
16691 isc_boolean_t
16692 dns_zone_getadded(dns_zone_t *zone) {
16693         REQUIRE(DNS_ZONE_VALID(zone));
16694         return (zone->added);
16695 }
16696
16697 isc_result_t
16698 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
16699 {
16700         isc_time_t loadtime;
16701         isc_result_t result;
16702         dns_zone_t *secure = NULL;
16703
16704         TIME_NOW(&loadtime);
16705
16706         /*
16707          * Lock hierarchy: zmgr, zone, raw.
16708          */
16709  again:
16710         LOCK_ZONE(zone);
16711         if (inline_secure(zone))
16712                 LOCK_ZONE(zone->raw);
16713         else if (inline_raw(zone)) {
16714                 secure = zone->secure;
16715                 TRYLOCK_ZONE(result, secure);
16716                 if (result != ISC_R_SUCCESS) {
16717                         UNLOCK_ZONE(zone);
16718                         secure = NULL;
16719 #if ISC_PLATFORM_USETHREADS
16720                         isc_thread_yield();
16721 #endif
16722                         goto again;
16723                 }
16724         }
16725         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
16726         if (inline_secure(zone))
16727                 UNLOCK_ZONE(zone->raw);
16728         else if (secure != NULL)
16729                 UNLOCK_ZONE(secure);
16730         UNLOCK_ZONE(zone);
16731         return result;
16732 }
16733
16734 isc_result_t
16735 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
16736         REQUIRE(DNS_ZONE_VALID(zone));
16737         if (interval == 0)
16738                 return (ISC_R_RANGE);
16739         /* Maximum value: 24 hours (3600 minutes) */
16740         if (interval > (24 * 60))
16741                 interval = (24 * 60);
16742         /* Multiply by 60 for seconds */
16743         zone->refreshkeyinterval = interval * 60;
16744         return (ISC_R_SUCCESS);
16745 }
16746
16747 void
16748 dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) {
16749         REQUIRE(DNS_ZONE_VALID(zone));
16750         zone->requestixfr = flag;
16751 }
16752
16753 isc_boolean_t
16754 dns_zone_getrequestixfr(dns_zone_t *zone) {
16755         REQUIRE(DNS_ZONE_VALID(zone));
16756         return (zone->requestixfr);
16757 }
16758
16759 void
16760 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
16761         REQUIRE(DNS_ZONE_VALID(zone));
16762         zone->updatemethod = method;
16763 }
16764
16765 dns_updatemethod_t
16766 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
16767         REQUIRE(DNS_ZONE_VALID(zone));
16768         return(zone->updatemethod);
16769 }
16770
16771 /*
16772  * Lock hierarchy: zmgr, zone, raw.
16773  */
16774 isc_result_t
16775 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
16776         isc_result_t result;
16777         dns_zonemgr_t *zmgr;
16778
16779         REQUIRE(DNS_ZONE_VALID(zone));
16780         REQUIRE(zone->zmgr != NULL);
16781         REQUIRE(zone->task != NULL);
16782         REQUIRE(zone->loadtask != NULL);
16783         REQUIRE(zone->raw == NULL);
16784
16785         REQUIRE(DNS_ZONE_VALID(raw));
16786         REQUIRE(raw->zmgr == NULL);
16787         REQUIRE(raw->task == NULL);
16788         REQUIRE(raw->loadtask == NULL);
16789         REQUIRE(raw->secure == NULL);
16790
16791         /*
16792          * Lock hierarchy: zmgr, zone, raw.
16793          */
16794         zmgr = zone->zmgr;
16795         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16796         LOCK_ZONE(zone);
16797         LOCK_ZONE(raw);
16798
16799         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
16800                                   NULL, NULL, zone->task, zone_timer, raw,
16801                                   &raw->timer);
16802         if (result != ISC_R_SUCCESS)
16803                 goto unlock;
16804
16805         /*
16806          * The timer "holds" a iref.
16807          */
16808         raw->irefs++;
16809         INSIST(raw->irefs != 0);
16810
16811
16812         /* dns_zone_attach(raw, &zone->raw); */
16813         isc_refcount_increment(&raw->erefs, NULL);
16814         zone->raw = raw;
16815
16816         /* dns_zone_iattach(zone,  &raw->secure); */
16817         zone_iattach(zone, &raw->secure);
16818
16819         isc_task_attach(zone->task, &raw->task);
16820         isc_task_attach(zone->loadtask, &raw->loadtask);
16821
16822         ISC_LIST_APPEND(zmgr->zones, raw, link);
16823         raw->zmgr = zmgr;
16824         zmgr->refs++;
16825
16826  unlock:
16827         UNLOCK_ZONE(raw);
16828         UNLOCK_ZONE(zone);
16829         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16830         return (result);
16831 }
16832
16833 void
16834 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
16835         REQUIRE(DNS_ZONE_VALID(zone));
16836         REQUIRE(raw != NULL && *raw == NULL);
16837
16838         LOCK(&zone->lock);
16839         if (zone->raw != NULL)
16840                 dns_zone_attach(zone->raw, raw);
16841         UNLOCK(&zone->lock);
16842 }
16843
16844 struct keydone {
16845         isc_event_t event;
16846         isc_boolean_t all;
16847         unsigned char data[5];
16848 };
16849
16850 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
16851
16852 static void
16853 keydone(isc_task_t *task, isc_event_t *event) {
16854         const char *me = "keydone";
16855         isc_boolean_t commit = ISC_FALSE;
16856         isc_result_t result;
16857         dns_rdata_t rdata = DNS_RDATA_INIT;
16858         dns_dbversion_t *oldver = NULL, *newver = NULL;
16859         dns_zone_t *zone;
16860         dns_db_t *db = NULL;
16861         dns_dbnode_t *node = NULL;
16862         dns_rdataset_t rdataset;
16863         dns_diff_t diff;
16864         struct keydone *keydone = (struct keydone *)event;
16865         dns_update_log_t log = { update_log_cb, NULL };
16866         isc_boolean_t clear_pending = ISC_FALSE;
16867
16868         UNUSED(task);
16869
16870         zone = event->ev_arg;
16871         INSIST(DNS_ZONE_VALID(zone));
16872
16873         ENTER;
16874
16875         dns_rdataset_init(&rdataset);
16876         dns_diff_init(zone->mctx, &diff);
16877
16878         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16879         if (zone->db != NULL) {
16880                 dns_db_attach(zone->db, &db);
16881                 dns_db_currentversion(db, &oldver);
16882                 result = dns_db_newversion(db, &newver);
16883                 if (result != ISC_R_SUCCESS) {
16884                         dns_zone_log(zone, ISC_LOG_ERROR,
16885                                      "keydone:dns_db_newversion -> %s",
16886                                      dns_result_totext(result));
16887                         goto failure;
16888                 }
16889         }
16890         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16891         if (db == NULL)
16892                 goto failure;
16893
16894         result = dns_db_getoriginnode(db, &node);
16895         if (result != ISC_R_SUCCESS)
16896                 goto failure;
16897
16898         result = dns_db_findrdataset(db, node, newver, zone->privatetype,
16899                                      dns_rdatatype_none, 0, &rdataset, NULL);
16900         if (result == ISC_R_NOTFOUND) {
16901                 INSIST(!dns_rdataset_isassociated(&rdataset));
16902                 goto failure;
16903         }
16904         if (result != ISC_R_SUCCESS) {
16905                 INSIST(!dns_rdataset_isassociated(&rdataset));
16906                 goto failure;
16907         }
16908
16909         for (result = dns_rdataset_first(&rdataset);
16910              result == ISC_R_SUCCESS;
16911              result = dns_rdataset_next(&rdataset)) {
16912                 isc_boolean_t found = ISC_FALSE;
16913
16914                 dns_rdataset_current(&rdataset, &rdata);
16915
16916                 if (keydone->all) {
16917                         if (rdata.length == 5 && rdata.data[0] != 0 &&
16918                                rdata.data[3] == 0 && rdata.data[4] == 1)
16919                                 found = ISC_TRUE;
16920                         else if (rdata.data[0] == 0 &&
16921                                  (rdata.data[2] & PENDINGFLAGS) != 0) {
16922                                 found = ISC_TRUE;
16923                                 clear_pending = ISC_TRUE;
16924                         }
16925                 } else if (rdata.length == 5 &&
16926                            memcmp(rdata.data, keydone->data, 5) == 0)
16927                         found = ISC_TRUE;
16928
16929                 if (found)
16930                         CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
16931                                             &zone->origin, rdataset.ttl,
16932                                             &rdata));
16933                 dns_rdata_reset(&rdata);
16934         }
16935
16936         if (!ISC_LIST_EMPTY(diff.tuples)) {
16937                 /* Write changes to journal file. */
16938                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
16939                                         zone->updatemethod));
16940
16941                 result = dns_update_signatures(&log, zone, db,
16942                                                oldver, newver, &diff,
16943                                                zone->sigvalidityinterval);
16944                 if (!clear_pending)
16945                         CHECK(result);
16946
16947                 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
16948                 commit = ISC_TRUE;
16949
16950                 LOCK_ZONE(zone);
16951                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
16952                 zone_needdump(zone, 30);
16953                 UNLOCK_ZONE(zone);
16954         }
16955
16956  failure:
16957         if (dns_rdataset_isassociated(&rdataset))
16958                 dns_rdataset_disassociate(&rdataset);
16959         if (db != NULL) {
16960                 if (node != NULL)
16961                         dns_db_detachnode(db, &node);
16962                 if (oldver != NULL)
16963                         dns_db_closeversion(db, &oldver, ISC_FALSE);
16964                 if (newver != NULL)
16965                         dns_db_closeversion(db, &newver, commit);
16966                 dns_db_detach(&db);
16967         }
16968         dns_diff_clear(&diff);
16969         isc_event_free(&event);
16970         dns_zone_idetach(&zone);
16971 }
16972
16973 isc_result_t
16974 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
16975         isc_result_t result = ISC_R_SUCCESS;
16976         isc_event_t *e;
16977         isc_buffer_t b;
16978         dns_zone_t *dummy = NULL;
16979         struct keydone *kd;
16980
16981         REQUIRE(DNS_ZONE_VALID(zone));
16982
16983         LOCK_ZONE(zone);
16984
16985         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
16986                                zone, sizeof(struct keydone));
16987         if (e == NULL) {
16988                 result = ISC_R_NOMEMORY;
16989                 goto failure;
16990         }
16991
16992         kd = (struct keydone *) e;
16993         if (strcasecmp(keystr, "all") == 0)
16994                 kd->all = ISC_TRUE;
16995         else {
16996                 isc_textregion_t r;
16997                 char *algstr;
16998                 dns_keytag_t keyid;
16999                 dns_secalg_t alg;
17000                 size_t n;
17001
17002                 kd->all = ISC_FALSE;
17003
17004                 n = sscanf(keystr, "%hd/", &keyid);
17005                 if (n == 0U)
17006                         CHECK(ISC_R_FAILURE);
17007
17008                 algstr = strchr(keystr, '/');
17009                 if (algstr != NULL)
17010                         algstr++;
17011                 else
17012                         CHECK(ISC_R_FAILURE);
17013
17014                 n = sscanf(algstr, "%hhd", &alg);
17015                 if (n == 0U) {
17016                         DE_CONST(algstr, r.base);
17017                         r.length = strlen(algstr);
17018                         CHECK(dns_secalg_fromtext(&alg, &r));
17019                 }
17020
17021                 /* construct a private-type rdata */
17022                 isc_buffer_init(&b, kd->data, sizeof(kd->data));
17023                 isc_buffer_putuint8(&b, alg);
17024                 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
17025                 isc_buffer_putuint8(&b, (keyid & 0xff));
17026                 isc_buffer_putuint8(&b, 0);
17027                 isc_buffer_putuint8(&b, 1);
17028         }
17029
17030         zone_iattach(zone, &dummy);
17031         isc_task_send(zone->task, &e);
17032
17033  failure:
17034         if (e != NULL)
17035                 isc_event_free(&e);
17036         UNLOCK_ZONE(zone);
17037         return (result);
17038 }
17039
17040 static void
17041 setnsec3param(isc_task_t *task, isc_event_t *event) {
17042         const char *me = "setnsec3param";
17043         isc_boolean_t commit = ISC_FALSE;
17044         isc_result_t result;
17045         dns_dbversion_t *oldver = NULL, *newver = NULL;
17046         dns_zone_t *zone;
17047         dns_db_t *db = NULL;
17048         dns_dbnode_t *node = NULL;
17049         dns_rdataset_t prdataset, nrdataset;
17050         dns_diff_t diff;
17051         struct np3event *npe = (struct np3event *)event;
17052         nsec3param_t *np;
17053         dns_update_log_t log = { update_log_cb, NULL };
17054         dns_rdata_t rdata;
17055         isc_boolean_t nseconly;
17056         isc_boolean_t exists = ISC_FALSE;
17057
17058         UNUSED(task);
17059
17060         zone = event->ev_arg;
17061         INSIST(DNS_ZONE_VALID(zone));
17062
17063         ENTER;
17064
17065         np = &npe->params;
17066
17067         dns_rdataset_init(&prdataset);
17068         dns_rdataset_init(&nrdataset);
17069         dns_diff_init(zone->mctx, &diff);
17070
17071         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17072         if (zone->db != NULL) {
17073                 dns_db_attach(zone->db, &db);
17074                 dns_db_currentversion(db, &oldver);
17075                 result = dns_db_newversion(db, &newver);
17076                 if (result != ISC_R_SUCCESS) {
17077                         dns_zone_log(zone, ISC_LOG_ERROR,
17078                                      "setnsec3param:dns_db_newversion -> %s",
17079                                      dns_result_totext(result));
17080                         goto failure;
17081                 }
17082         }
17083         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17084         if (db == NULL)
17085                 goto failure;
17086
17087         CHECK(dns_db_getoriginnode(db, &node));
17088
17089         /*
17090          * Does a private-type record already exist for this chain?
17091          */
17092         result = dns_db_findrdataset(db, node, newver, zone->privatetype,
17093                                      dns_rdatatype_none, 0, &prdataset, NULL);
17094         if (result == ISC_R_SUCCESS) {
17095                 for (result = dns_rdataset_first(&prdataset);
17096                      result == ISC_R_SUCCESS;
17097                      result = dns_rdataset_next(&prdataset)) {
17098                         dns_rdata_init(&rdata);
17099                         dns_rdataset_current(&prdataset, &rdata);
17100
17101                         if (np->length == rdata.length &&
17102                             memcmp(rdata.data, np->data, np->length) == 0) {
17103                                 exists = ISC_TRUE;
17104                                 break;
17105                         }
17106                 }
17107         } else if (result != ISC_R_NOTFOUND) {
17108                 INSIST(!dns_rdataset_isassociated(&prdataset));
17109                 goto failure;
17110         }
17111
17112         /*
17113          * Does the chain already exist?
17114          */
17115         result = dns_db_findrdataset(db, node, newver,
17116                                      dns_rdatatype_nsec3param,
17117                                      dns_rdatatype_none, 0, &nrdataset, NULL);
17118         if (result == ISC_R_SUCCESS) {
17119                 for (result = dns_rdataset_first(&nrdataset);
17120                      result == ISC_R_SUCCESS;
17121                      result = dns_rdataset_next(&nrdataset)) {
17122                         dns_rdata_init(&rdata);
17123                         dns_rdataset_current(&nrdataset, &rdata);
17124
17125                         if (np->length == (rdata.length + 1) &&
17126                             memcmp(rdata.data, np->data + 1,
17127                                    np->length - 1) == 0)
17128                         {
17129                                 exists = ISC_TRUE;
17130                                 break;
17131                         }
17132                 }
17133         } else if (result != ISC_R_NOTFOUND) {
17134                 INSIST(!dns_rdataset_isassociated(&nrdataset));
17135                 goto failure;
17136         }
17137
17138
17139         /*
17140          * We need to remove any existing NSEC3 chains.
17141          */
17142         if (!exists && np->replace && (np->length != 0 || np->nsec))
17143                 CHECK(dns_nsec3param_deletechains(db, newver, zone,
17144                                                   !np->nsec, &diff));
17145
17146         if (!exists && np->length != 0) {
17147                 /*
17148                  * We're creating an NSEC3 chain.
17149                  *
17150                  * If the zone is not currently capable of supporting
17151                  * an NSEC3 chain, add the INITIAL flag, so these
17152                  * parameters can be used later when NSEC3 becomes
17153                  * available.
17154                  */
17155                 dns_rdata_init(&rdata);
17156
17157                 np->data[2] |= DNS_NSEC3FLAG_CREATE;
17158                 result = dns_nsec_nseconly(db, newver, &nseconly);
17159                 if (result == ISC_R_NOTFOUND || nseconly)
17160                         np->data[2] |= DNS_NSEC3FLAG_INITIAL;
17161
17162                 rdata.length = np->length;
17163                 rdata.data = np->data;
17164                 rdata.type = zone->privatetype;
17165                 rdata.rdclass = zone->rdclass;
17166                 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
17167                                     &zone->origin, 0, &rdata));
17168         }
17169
17170         if (!ISC_LIST_EMPTY(diff.tuples)) {
17171                 /* Write changes to journal file. */
17172                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
17173                                         zone->updatemethod));
17174                 result = dns_update_signatures(&log, zone, db,
17175                                                oldver, newver, &diff,
17176                                                zone->sigvalidityinterval);
17177                 if (result != ISC_R_NOTFOUND)
17178                         CHECK(result);
17179                 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
17180                 commit = ISC_TRUE;
17181
17182                 LOCK_ZONE(zone);
17183                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
17184                 zone_needdump(zone, 30);
17185                 UNLOCK_ZONE(zone);
17186         }
17187
17188  failure:
17189         if (dns_rdataset_isassociated(&prdataset))
17190                 dns_rdataset_disassociate(&prdataset);
17191         if (dns_rdataset_isassociated(&nrdataset))
17192                 dns_rdataset_disassociate(&nrdataset);
17193         if (node != NULL)
17194                 dns_db_detachnode(db, &node);
17195         if (oldver != NULL)
17196                 dns_db_closeversion(db, &oldver, ISC_FALSE);
17197         if (newver != NULL)
17198                 dns_db_closeversion(db, &newver, commit);
17199         if (db != NULL)
17200                 dns_db_detach(&db);
17201         if (commit)
17202                 resume_addnsec3chain(zone);
17203         dns_diff_clear(&diff);
17204         isc_event_free(&event);
17205         dns_zone_idetach(&zone);
17206 }
17207
17208 isc_result_t
17209 dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
17210                        isc_uint16_t iter, isc_uint8_t saltlen,
17211                        unsigned char *salt, isc_boolean_t replace)
17212 {
17213         isc_result_t result = ISC_R_SUCCESS;
17214         dns_rdata_nsec3param_t param;
17215         dns_rdata_t nrdata = DNS_RDATA_INIT;
17216         dns_rdata_t prdata = DNS_RDATA_INIT;
17217         unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
17218         struct np3event *npe;
17219         nsec3param_t *np;
17220         dns_zone_t *dummy = NULL;
17221         isc_buffer_t b;
17222         isc_event_t *e;
17223
17224         REQUIRE(DNS_ZONE_VALID(zone));
17225         REQUIRE(salt != NULL);
17226
17227         LOCK_ZONE(zone);
17228
17229         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
17230                                setnsec3param, zone, sizeof(struct np3event));
17231         if (e == NULL) {
17232                 result = ISC_R_NOMEMORY;
17233                 goto failure;
17234         }
17235
17236         npe = (struct np3event *) e;
17237         np = &npe->params;
17238
17239         np->replace = replace;
17240         if (hash == 0) {
17241                 np->length = 0;
17242                 np->nsec = ISC_TRUE;
17243         } else {
17244                 param.common.rdclass = zone->rdclass;
17245                 param.common.rdtype = dns_rdatatype_nsec3param;
17246                 ISC_LINK_INIT(&param.common, link);
17247                 param.mctx = NULL;
17248                 param.hash = hash;
17249                 param.flags = flags;
17250                 param.iterations = iter;
17251                 param.salt_length = saltlen;
17252                 param.salt = salt;
17253                 isc_buffer_init(&b, nbuf, sizeof(nbuf));
17254                 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
17255                                            dns_rdatatype_nsec3param,
17256                                            &param, &b));
17257                 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
17258                                          np->data, sizeof(np->data));
17259                 np->length = prdata.length;
17260         }
17261
17262         zone_iattach(zone, &dummy);
17263         isc_task_send(zone->task, &e);
17264
17265  failure:
17266         if (e != NULL)
17267                 isc_event_free(&e);
17268         UNLOCK_ZONE(zone);
17269         return (result);
17270 }
17271
17272 void
17273 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
17274         REQUIRE(DNS_ZONE_VALID(zone));
17275
17276         zone->statlevel = level;
17277 }
17278
17279 dns_zonestat_level_t
17280 dns_zone_getstatlevel(dns_zone_t *zone) {
17281         REQUIRE(DNS_ZONE_VALID(zone));
17282
17283         return (zone->statlevel);
17284 }