]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/lib/dns/zone.c
MFC r254651:
[FreeBSD/stable/9.git] / contrib / bind9 / lib / dns / zone.c
1 /*
2  * Copyright (C) 2004-2013  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/timer.h>
41 #include <isc/util.h>
42
43 #include <dns/acache.h>
44 #include <dns/acl.h>
45 #include <dns/adb.h>
46 #include <dns/callbacks.h>
47 #include <dns/db.h>
48 #include <dns/dbiterator.h>
49 #include <dns/dnssec.h>
50 #include <dns/events.h>
51 #include <dns/journal.h>
52 #include <dns/keydata.h>
53 #include <dns/keytable.h>
54 #include <dns/keyvalues.h>
55 #include <dns/log.h>
56 #include <dns/master.h>
57 #include <dns/masterdump.h>
58 #include <dns/message.h>
59 #include <dns/name.h>
60 #include <dns/nsec.h>
61 #include <dns/nsec3.h>
62 #include <dns/peer.h>
63 #include <dns/private.h>
64 #include <dns/rbt.h>
65 #include <dns/rcode.h>
66 #include <dns/rdata.h>
67 #include <dns/rdataclass.h>
68 #include <dns/rdatalist.h>
69 #include <dns/rdataset.h>
70 #include <dns/rdatasetiter.h>
71 #include <dns/rdatastruct.h>
72 #include <dns/rdatatype.h>
73 #include <dns/request.h>
74 #include <dns/resolver.h>
75 #include <dns/result.h>
76 #include <dns/rriterator.h>
77 #include <dns/soa.h>
78 #include <dns/ssu.h>
79 #include <dns/stats.h>
80 #include <dns/time.h>
81 #include <dns/tsig.h>
82 #include <dns/update.h>
83 #include <dns/xfrin.h>
84 #include <dns/zone.h>
85 #include <dns/zt.h>
86
87 #include <dst/dst.h>
88
89 #define ZONE_MAGIC                      ISC_MAGIC('Z', 'O', 'N', 'E')
90 #define DNS_ZONE_VALID(zone)            ISC_MAGIC_VALID(zone, ZONE_MAGIC)
91
92 #define NOTIFY_MAGIC                    ISC_MAGIC('N', 't', 'f', 'y')
93 #define DNS_NOTIFY_VALID(notify)        ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
94
95 #define STUB_MAGIC                      ISC_MAGIC('S', 't', 'u', 'b')
96 #define DNS_STUB_VALID(stub)            ISC_MAGIC_VALID(stub, STUB_MAGIC)
97
98 #define ZONEMGR_MAGIC                   ISC_MAGIC('Z', 'm', 'g', 'r')
99 #define DNS_ZONEMGR_VALID(stub)         ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
100
101 #define LOAD_MAGIC                      ISC_MAGIC('L', 'o', 'a', 'd')
102 #define DNS_LOAD_VALID(load)            ISC_MAGIC_VALID(load, LOAD_MAGIC)
103
104 #define FORWARD_MAGIC                   ISC_MAGIC('F', 'o', 'r', 'w')
105 #define DNS_FORWARD_VALID(load)         ISC_MAGIC_VALID(load, FORWARD_MAGIC)
106
107 #define IO_MAGIC                        ISC_MAGIC('Z', 'm', 'I', 'O')
108 #define DNS_IO_VALID(load)              ISC_MAGIC_VALID(load, IO_MAGIC)
109
110 /*%
111  * Ensure 'a' is at least 'min' but not more than 'max'.
112  */
113 #define RANGE(a, min, max) \
114                 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
115
116 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
117
118 /*%
119  * Key flags
120  */
121 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
122 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
123 #define ALG(x) dst_key_alg(x)
124
125 /*
126  * Default values.
127  */
128 #define DNS_DEFAULT_IDLEIN 3600         /*%< 1 hour */
129 #define DNS_DEFAULT_IDLEOUT 3600        /*%< 1 hour */
130 #define MAX_XFER_TIME (2*3600)          /*%< Documented default is 2 hours */
131 #define RESIGN_DELAY 3600               /*%< 1 hour */
132
133 #ifndef DNS_MAX_EXPIRE
134 #define DNS_MAX_EXPIRE  14515200        /*%< 24 weeks */
135 #endif
136
137 #ifndef DNS_DUMP_DELAY
138 #define DNS_DUMP_DELAY 900              /*%< 15 minutes */
139 #endif
140
141 typedef struct dns_notify dns_notify_t;
142 typedef struct dns_stub dns_stub_t;
143 typedef struct dns_load dns_load_t;
144 typedef struct dns_forward dns_forward_t;
145 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
146 typedef struct dns_io dns_io_t;
147 typedef ISC_LIST(dns_io_t) dns_iolist_t;
148 typedef struct dns_signing dns_signing_t;
149 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
150 typedef struct dns_nsec3chain dns_nsec3chain_t;
151 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
152 typedef struct dns_keyfetch dns_keyfetch_t;
153 typedef struct dns_asyncload dns_asyncload_t;
154
155 #define DNS_ZONE_CHECKLOCK
156 #ifdef DNS_ZONE_CHECKLOCK
157 #define LOCK_ZONE(z) \
158          do { LOCK(&(z)->lock); \
159               INSIST((z)->locked == ISC_FALSE); \
160              (z)->locked = ISC_TRUE; \
161                 } while (0)
162 #define UNLOCK_ZONE(z) \
163         do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
164 #define LOCKED_ZONE(z) ((z)->locked)
165 #else
166 #define LOCK_ZONE(z) LOCK(&(z)->lock)
167 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
168 #define LOCKED_ZONE(z) ISC_TRUE
169 #endif
170
171 #ifdef ISC_RWLOCK_USEATOMIC
172 #define ZONEDB_INITLOCK(l)      isc_rwlock_init((l), 0, 0)
173 #define ZONEDB_DESTROYLOCK(l)   isc_rwlock_destroy(l)
174 #define ZONEDB_LOCK(l, t)       RWLOCK((l), (t))
175 #define ZONEDB_UNLOCK(l, t)     RWUNLOCK((l), (t))
176 #else
177 #define ZONEDB_INITLOCK(l)      isc_mutex_init(l)
178 #define ZONEDB_DESTROYLOCK(l)   DESTROYLOCK(l)
179 #define ZONEDB_LOCK(l, t)       LOCK(l)
180 #define ZONEDB_UNLOCK(l, t)     UNLOCK(l)
181 #endif
182
183 struct dns_zone {
184         /* Unlocked */
185         unsigned int            magic;
186         isc_mutex_t             lock;
187 #ifdef DNS_ZONE_CHECKLOCK
188         isc_boolean_t           locked;
189 #endif
190         isc_mem_t               *mctx;
191         isc_refcount_t          erefs;
192
193 #ifdef ISC_RWLOCK_USEATOMIC
194         isc_rwlock_t            dblock;
195 #else
196         isc_mutex_t             dblock;
197 #endif
198         dns_db_t                *db;            /* Locked by dblock */
199
200         /* Locked */
201         dns_zonemgr_t           *zmgr;
202         ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
203         isc_timer_t             *timer;
204         unsigned int            irefs;
205         dns_name_t              origin;
206         char                    *masterfile;
207         dns_masterformat_t      masterformat;
208         char                    *journal;
209         isc_int32_t             journalsize;
210         dns_rdataclass_t        rdclass;
211         dns_zonetype_t          type;
212         unsigned int            flags;
213         unsigned int            options;
214         unsigned int            db_argc;
215         char                    **db_argv;
216         isc_time_t              expiretime;
217         isc_time_t              refreshtime;
218         isc_time_t              dumptime;
219         isc_time_t              loadtime;
220         isc_time_t              notifytime;
221         isc_time_t              resigntime;
222         isc_time_t              keywarntime;
223         isc_time_t              signingtime;
224         isc_time_t              nsec3chaintime;
225         isc_time_t              refreshkeytime;
226         isc_uint32_t            refreshkeyinterval;
227         isc_uint32_t            refreshkeycount;
228         isc_uint32_t            refresh;
229         isc_uint32_t            retry;
230         isc_uint32_t            expire;
231         isc_uint32_t            minimum;
232         isc_stdtime_t           key_expiry;
233         isc_stdtime_t           log_key_expired_timer;
234         char                    *keydirectory;
235
236         isc_uint32_t            maxrefresh;
237         isc_uint32_t            minrefresh;
238         isc_uint32_t            maxretry;
239         isc_uint32_t            minretry;
240
241         isc_sockaddr_t          *masters;
242         dns_name_t              **masterkeynames;
243         isc_boolean_t           *mastersok;
244         unsigned int            masterscnt;
245         unsigned int            curmaster;
246         isc_sockaddr_t          masteraddr;
247         dns_notifytype_t        notifytype;
248         isc_sockaddr_t          *notify;
249         dns_name_t              **notifykeynames;
250         unsigned int            notifycnt;
251         isc_sockaddr_t          notifyfrom;
252         isc_task_t              *task;
253         isc_task_t              *loadtask;
254         isc_sockaddr_t          notifysrc4;
255         isc_sockaddr_t          notifysrc6;
256         isc_sockaddr_t          xfrsource4;
257         isc_sockaddr_t          xfrsource6;
258         isc_sockaddr_t          altxfrsource4;
259         isc_sockaddr_t          altxfrsource6;
260         isc_sockaddr_t          sourceaddr;
261         dns_xfrin_ctx_t         *xfr;           /* task locked */
262         dns_tsigkey_t           *tsigkey;       /* key used for xfr */
263         /* Access Control Lists */
264         dns_acl_t               *update_acl;
265         dns_acl_t               *forward_acl;
266         dns_acl_t               *notify_acl;
267         dns_acl_t               *query_acl;
268         dns_acl_t               *queryon_acl;
269         dns_acl_t               *xfr_acl;
270         isc_boolean_t           update_disabled;
271         isc_boolean_t           zero_no_soa_ttl;
272         dns_severity_t          check_names;
273         ISC_LIST(dns_notify_t)  notifies;
274         dns_request_t           *request;
275         dns_loadctx_t           *lctx;
276         dns_io_t                *readio;
277         dns_dumpctx_t           *dctx;
278         dns_io_t                *writeio;
279         isc_uint32_t            maxxfrin;
280         isc_uint32_t            maxxfrout;
281         isc_uint32_t            idlein;
282         isc_uint32_t            idleout;
283         isc_event_t             ctlevent;
284         dns_ssutable_t          *ssutable;
285         isc_uint32_t            sigvalidityinterval;
286         isc_uint32_t            sigresigninginterval;
287         dns_view_t              *view;
288         dns_acache_t            *acache;
289         dns_checkmxfunc_t       checkmx;
290         dns_checksrvfunc_t      checksrv;
291         dns_checknsfunc_t       checkns;
292         /*%
293          * Zones in certain states such as "waiting for zone transfer"
294          * or "zone transfer in progress" are kept on per-state linked lists
295          * in the zone manager using the 'statelink' field.  The 'statelist'
296          * field points at the list the zone is currently on.  It the zone
297          * is not on any such list, statelist is NULL.
298          */
299         ISC_LINK(dns_zone_t)    statelink;
300         dns_zonelist_t          *statelist;
301         /*%
302          * Statistics counters about zone management.
303          */
304         isc_stats_t             *stats;
305         /*%
306          * Optional per-zone statistics counters.  Counted outside of this
307          * module.
308          */
309         dns_zonestat_level_t    statlevel;
310         isc_boolean_t           requeststats_on;
311         isc_stats_t             *requeststats;
312         dns_stats_t             *rcvquerystats;
313         isc_uint32_t            notifydelay;
314         dns_isselffunc_t        isself;
315         void                    *isselfarg;
316
317         char *                  strnamerd;
318         char *                  strname;
319         char *                  strrdclass;
320         char *                  strviewname;
321
322         /*%
323          * Serial number for deferred journal compaction.
324          */
325         isc_uint32_t            compact_serial;
326         /*%
327          * Keys that are signing the zone for the first time.
328          */
329         dns_signinglist_t       signing;
330         dns_nsec3chainlist_t    nsec3chain;
331         /*%
332          * Signing / re-signing quantum stopping parameters.
333          */
334         isc_uint32_t            signatures;
335         isc_uint32_t            nodes;
336         dns_rdatatype_t         privatetype;
337
338         /*%
339          * Autosigning/key-maintenance options
340          */
341         isc_uint32_t            keyopts;
342
343         /*%
344          * True if added by "rndc addzone"
345          */
346         isc_boolean_t           added;
347
348         /*%
349          * whether this is a response policy zone
350          */
351         isc_boolean_t           is_rpz;
352
353         /*%
354          * Serial number update method.
355          */
356         dns_updatemethod_t      updatemethod;
357
358         /*%
359          * whether ixfr is requested
360          */
361         isc_boolean_t           requestixfr;
362
363         /*%
364          * Outstanding forwarded UPDATE requests.
365          */
366         dns_forwardlist_t       forwards;
367
368         dns_zone_t              *raw;
369         dns_zone_t              *secure;
370
371         isc_boolean_t           sourceserialset;
372         isc_uint32_t            sourceserial;
373 };
374
375 typedef struct {
376         dns_diff_t      *diff;
377         isc_boolean_t   offline;
378 } zonediff_t;
379
380 #define zonediff_init(z, d) \
381         do { \
382                 zonediff_t *_z = (z); \
383                 (_z)->diff = (d); \
384                 (_z)->offline = ISC_FALSE; \
385         } while (0)
386
387 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
388 #define DNS_ZONE_SETFLAG(z,f) do { \
389                 INSIST(LOCKED_ZONE(z)); \
390                 (z)->flags |= (f); \
391                 } while (0)
392 #define DNS_ZONE_CLRFLAG(z,f) do { \
393                 INSIST(LOCKED_ZONE(z)); \
394                 (z)->flags &= ~(f); \
395                 } while (0)
396         /* XXX MPA these may need to go back into zone.h */
397 #define DNS_ZONEFLG_REFRESH     0x00000001U     /*%< refresh check in progress */
398 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /*%< zone need consolidation */
399 #define DNS_ZONEFLG_USEVC       0x00000004U     /*%< use tcp for refresh query */
400 #define DNS_ZONEFLG_DUMPING     0x00000008U     /*%< a dump is in progress */
401 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /*%< $INCLUDE in zone file */
402 #define DNS_ZONEFLG_LOADED      0x00000020U     /*%< database has loaded */
403 #define DNS_ZONEFLG_EXITING     0x00000040U     /*%< zone is being destroyed */
404 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /*%< zone has expired */
405 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /*%< refresh check needed */
406 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /*%< zone contents are
407                                                  * uptodate */
408 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /*%< need to send out notify
409                                                  * messages */
410 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /*%< generate a journal diff on
411                                                  * reload */
412 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /*%< an attempt to refresh a
413                                                  * zone with no masters
414                                                  * occurred */
415 #define DNS_ZONEFLG_LOADING     0x00002000U     /*%< load from disk in progress*/
416 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /*%< timer values have been set
417                                                  * from SOA (if not set, we
418                                                  * are still using
419                                                  * default timer values) */
420 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
421 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
422 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
423 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
424 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
425 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /*%< IXFR failed, force AXFR */
426 #define DNS_ZONEFLG_FLUSH       0x00200000U
427 #define DNS_ZONEFLG_NOEDNS      0x00400000U
428 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
429 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
430 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
431 #define DNS_ZONEFLG_REFRESHING  0x04000000U     /*%< Refreshing keydata */
432 #define DNS_ZONEFLG_THAW        0x08000000U
433 #define DNS_ZONEFLG_LOADPENDING 0x10000000U     /*%< Loading scheduled */
434 #define DNS_ZONEFLG_NODELAY     0x20000000U
435 #define DNS_ZONEFLG_SENDSECURE  0x40000000U
436
437 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
438 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
439
440 /* Flags for zone_load() */
441 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
442 #define DNS_ZONELOADFLAG_THAW   0x00000002U     /* Thaw the zone on successful
443                                                    load. */
444
445 #define UNREACH_CHACHE_SIZE     10U
446 #define UNREACH_HOLD_TIME       600     /* 10 minutes */
447
448 #define CHECK(op) \
449         do { result = (op); \
450                 if (result != ISC_R_SUCCESS) goto failure; \
451         } while (0)
452
453 struct dns_unreachable {
454         isc_sockaddr_t  remote;
455         isc_sockaddr_t  local;
456         isc_uint32_t    expire;
457         isc_uint32_t    last;
458 };
459
460 struct dns_zonemgr {
461         unsigned int            magic;
462         isc_mem_t *             mctx;
463         int                     refs;           /* Locked by rwlock */
464         isc_taskmgr_t *         taskmgr;
465         isc_timermgr_t *        timermgr;
466         isc_socketmgr_t *       socketmgr;
467         isc_taskpool_t *        zonetasks;
468         isc_taskpool_t *        loadtasks;
469         isc_task_t *            task;
470         isc_pool_t *            mctxpool;
471         isc_ratelimiter_t *     rl;
472         isc_rwlock_t            rwlock;
473         isc_mutex_t             iolock;
474         isc_rwlock_t            urlock;
475
476         /* Locked by rwlock. */
477         dns_zonelist_t          zones;
478         dns_zonelist_t          waiting_for_xfrin;
479         dns_zonelist_t          xfrin_in_progress;
480
481         /* Configuration data. */
482         isc_uint32_t            transfersin;
483         isc_uint32_t            transfersperns;
484         unsigned int            serialqueryrate;
485
486         /* Locked by iolock */
487         isc_uint32_t            iolimit;
488         isc_uint32_t            ioactive;
489         dns_iolist_t            high;
490         dns_iolist_t            low;
491
492         /* Locked by urlock. */
493         /* LRU cache */
494         struct dns_unreachable  unreachable[UNREACH_CHACHE_SIZE];
495 };
496
497 /*%
498  * Hold notify state.
499  */
500 struct dns_notify {
501         unsigned int            magic;
502         unsigned int            flags;
503         isc_mem_t               *mctx;
504         dns_zone_t              *zone;
505         dns_adbfind_t           *find;
506         dns_request_t           *request;
507         dns_name_t              ns;
508         isc_sockaddr_t          dst;
509         dns_tsigkey_t           *key;
510         ISC_LINK(dns_notify_t)  link;
511 };
512
513 #define DNS_NOTIFY_NOSOA        0x0001U
514
515 /*%
516  *      dns_stub holds state while performing a 'stub' transfer.
517  *      'db' is the zone's 'db' or a new one if this is the initial
518  *      transfer.
519  */
520
521 struct dns_stub {
522         unsigned int            magic;
523         isc_mem_t               *mctx;
524         dns_zone_t              *zone;
525         dns_db_t                *db;
526         dns_dbversion_t         *version;
527 };
528
529 /*%
530  *      Hold load state.
531  */
532 struct dns_load {
533         unsigned int            magic;
534         isc_mem_t               *mctx;
535         dns_zone_t              *zone;
536         dns_db_t                *db;
537         isc_time_t              loadtime;
538         dns_rdatacallbacks_t    callbacks;
539 };
540
541 /*%
542  *      Hold forward state.
543  */
544 struct dns_forward {
545         unsigned int            magic;
546         isc_mem_t               *mctx;
547         dns_zone_t              *zone;
548         isc_buffer_t            *msgbuf;
549         dns_request_t           *request;
550         isc_uint32_t            which;
551         isc_sockaddr_t          addr;
552         dns_updatecallback_t    callback;
553         void                    *callback_arg;
554         ISC_LINK(dns_forward_t) link;
555 };
556
557 /*%
558  *      Hold IO request state.
559  */
560 struct dns_io {
561         unsigned int    magic;
562         dns_zonemgr_t   *zmgr;
563         isc_boolean_t   high;
564         isc_task_t      *task;
565         ISC_LINK(dns_io_t) link;
566         isc_event_t     *event;
567 };
568
569 /*%
570  *      Hold state for when we are signing a zone with a new
571  *      DNSKEY as result of an update.
572  */
573 struct dns_signing {
574         unsigned int            magic;
575         dns_db_t                *db;
576         dns_dbiterator_t        *dbiterator;
577         dns_secalg_t            algorithm;
578         isc_uint16_t            keyid;
579         isc_boolean_t           delete;
580         isc_boolean_t           done;
581         ISC_LINK(dns_signing_t) link;
582 };
583
584 struct dns_nsec3chain {
585         unsigned int                    magic;
586         dns_db_t                        *db;
587         dns_dbiterator_t                *dbiterator;
588         dns_rdata_nsec3param_t          nsec3param;
589         unsigned char                   salt[255];
590         isc_boolean_t                   done;
591         isc_boolean_t                   seen_nsec;
592         isc_boolean_t                   delete_nsec;
593         isc_boolean_t                   save_delete_nsec;
594         ISC_LINK(dns_nsec3chain_t)      link;
595 };
596 /*%<
597  * 'dbiterator' contains a iterator for the database.  If we are creating
598  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
599  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
600  * iterated.
601  *
602  * 'nsec3param' contains the parameters of the NSEC3 chain being created
603  * or removed.
604  *
605  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
606  *
607  * 'seen_nsec' will be set to true if, while iterating the zone to create a
608  * NSEC3 chain, a NSEC record is seen.
609  *
610  * 'delete_nsec' will be set to true if, at the completion of the creation
611  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
612  * are in the process of deleting the NSEC chain.
613  *
614  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
615  * so it can be recovered in the event of a error.
616  */
617
618 struct dns_keyfetch {
619         dns_fixedname_t name;
620         dns_rdataset_t keydataset;
621         dns_rdataset_t dnskeyset;
622         dns_rdataset_t dnskeysigset;
623         dns_zone_t *zone;
624         dns_db_t *db;
625         dns_fetch_t *fetch;
626 };
627
628 /*%
629  * Hold state for an asynchronous load
630  */
631 struct dns_asyncload {
632         dns_zone_t *zone;
633         dns_zt_zoneloaded_t loaded;
634         void *loaded_arg;
635 };
636
637 #define HOUR 3600
638 #define DAY (24*HOUR)
639 #define MONTH (30*DAY)
640
641 #define SEND_BUFFER_SIZE 2048
642
643 static void zone_settimer(dns_zone_t *, isc_time_t *);
644 static void cancel_refresh(dns_zone_t *);
645 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
646                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
647 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
648      ISC_FORMAT_PRINTF(3, 4);
649 static void queue_xfrin(dns_zone_t *zone);
650 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
651                                   dns_diff_t *diff, dns_diffop_t op,
652                                   dns_name_t *name, dns_ttl_t ttl,
653                                   dns_rdata_t *rdata);
654 static void zone_unload(dns_zone_t *zone);
655 static void zone_expire(dns_zone_t *zone);
656 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
657 static void zone_idetach(dns_zone_t **zonep);
658 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
659                                    isc_boolean_t dump);
660 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
661 static inline void zone_detachdb(dns_zone_t *zone);
662 static isc_result_t default_journal(dns_zone_t *zone);
663 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
664 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
665                                   isc_time_t loadtime, isc_result_t result);
666 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
667 static void zone_shutdown(isc_task_t *, isc_event_t *);
668 static void zone_loaddone(void *arg, isc_result_t result);
669 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
670                                    isc_time_t loadtime);
671 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
672 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
673 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
674 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
675 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
676                                            isc_boolean_t secure_locked,
677                                            isc_uint32_t serial);
678
679 #if 0
680 /* ondestroy example */
681 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
682 #endif
683
684 static void refresh_callback(isc_task_t *, isc_event_t *);
685 static void stub_callback(isc_task_t *, isc_event_t *);
686 static void queue_soa_query(dns_zone_t *zone);
687 static void soa_query(isc_task_t *, isc_event_t *);
688 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
689                      dns_stub_t *stub);
690 static int message_count(dns_message_t *msg, dns_section_t section,
691                          dns_rdatatype_t type);
692 static void notify_cancel(dns_zone_t *zone);
693 static void notify_find_address(dns_notify_t *notify);
694 static void notify_send(dns_notify_t *notify);
695 static isc_result_t notify_createmessage(dns_zone_t *zone,
696                                          unsigned int flags,
697                                          dns_message_t **messagep);
698 static void notify_done(isc_task_t *task, isc_event_t *event);
699 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
700 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
701 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
702 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
703                                              dns_zone_t *zone);
704 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
705 static void zonemgr_free(dns_zonemgr_t *zmgr);
706 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
707                                   isc_task_t *task, isc_taskaction_t action,
708                                   void *arg, dns_io_t **iop);
709 static void zonemgr_putio(dns_io_t **iop);
710 static void zonemgr_cancelio(dns_io_t *io);
711
712 static isc_result_t
713 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
714                  unsigned int *soacount, isc_uint32_t *serial,
715                  isc_uint32_t *refresh, isc_uint32_t *retry,
716                  isc_uint32_t *expire, isc_uint32_t *minimum,
717                  unsigned int *errors);
718
719 static void zone_freedbargs(dns_zone_t *zone);
720 static void forward_callback(isc_task_t *task, isc_event_t *event);
721 static void zone_saveunique(dns_zone_t *zone, const char *path,
722                             const char *templat);
723 static void zone_maintenance(dns_zone_t *zone);
724 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
725 static void dump_done(void *arg, isc_result_t result);
726 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
727                                      isc_uint16_t keyid, isc_boolean_t delete);
728 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
729                                 dns_dbnode_t *node, dns_name_t *name,
730                                 dns_diff_t *diff);
731 static void zone_rekey(dns_zone_t *zone);
732 static isc_boolean_t delsig_ok(dns_rdata_rrsig_t *rrsig_ptr,
733                                dst_key_t **keys, unsigned int nkeys);
734 static isc_result_t zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked,
735                                        dns_db_t *db);
736
737 #define ENTER zone_debuglog(zone, me, 1, "enter")
738
739 static const unsigned int dbargc_default = 1;
740 static const char *dbargv_default[] = { "rbt" };
741
742 #define DNS_ZONE_JITTER_ADD(a, b, c) \
743         do { \
744                 isc_interval_t _i; \
745                 isc_uint32_t _j; \
746                 _j = isc_random_jitter((b), (b)/4); \
747                 isc_interval_set(&_i, _j, 0); \
748                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
749                         dns_zone_log(zone, ISC_LOG_WARNING, \
750                                      "epoch approaching: upgrade required: " \
751                                      "now + %s failed", #b); \
752                         isc_interval_set(&_i, _j/2, 0); \
753                         (void)isc_time_add((a), &_i, (c)); \
754                 } \
755         } while (0)
756
757 #define DNS_ZONE_TIME_ADD(a, b, c) \
758         do { \
759                 isc_interval_t _i; \
760                 isc_interval_set(&_i, (b), 0); \
761                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
762                         dns_zone_log(zone, ISC_LOG_WARNING, \
763                                      "epoch approaching: upgrade required: " \
764                                      "now + %s failed", #b); \
765                         isc_interval_set(&_i, (b)/2, 0); \
766                         (void)isc_time_add((a), &_i, (c)); \
767                 } \
768         } while (0)
769
770 /*%
771  * Increment resolver-related statistics counters.  Zone must be locked.
772  */
773 static inline void
774 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
775         if (zone->stats != NULL)
776                 isc_stats_increment(zone->stats, counter);
777 }
778
779 /***
780  ***    Public functions.
781  ***/
782
783 isc_result_t
784 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
785         isc_result_t result;
786         dns_zone_t *zone;
787         isc_time_t now;
788
789         REQUIRE(zonep != NULL && *zonep == NULL);
790         REQUIRE(mctx != NULL);
791
792         TIME_NOW(&now);
793         zone = isc_mem_get(mctx, sizeof(*zone));
794         if (zone == NULL)
795                 return (ISC_R_NOMEMORY);
796
797         zone->mctx = NULL;
798         isc_mem_attach(mctx, &zone->mctx);
799
800         result = isc_mutex_init(&zone->lock);
801         if (result != ISC_R_SUCCESS)
802                 goto free_zone;
803
804         result = ZONEDB_INITLOCK(&zone->dblock);
805         if (result != ISC_R_SUCCESS)
806                 goto free_mutex;
807
808         /* XXX MPA check that all elements are initialised */
809 #ifdef DNS_ZONE_CHECKLOCK
810         zone->locked = ISC_FALSE;
811 #endif
812         zone->db = NULL;
813         zone->zmgr = NULL;
814         ISC_LINK_INIT(zone, link);
815         result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
816         if (result != ISC_R_SUCCESS)
817                 goto free_dblock;
818         zone->irefs = 0;
819         dns_name_init(&zone->origin, NULL);
820         zone->strnamerd = NULL;
821         zone->strname = NULL;
822         zone->strrdclass = NULL;
823         zone->strviewname = NULL;
824         zone->masterfile = NULL;
825         zone->masterformat = dns_masterformat_none;
826         zone->keydirectory = NULL;
827         zone->journalsize = -1;
828         zone->journal = NULL;
829         zone->rdclass = dns_rdataclass_none;
830         zone->type = dns_zone_none;
831         zone->flags = 0;
832         zone->options = 0;
833         zone->keyopts = 0;
834         zone->db_argc = 0;
835         zone->db_argv = NULL;
836         isc_time_settoepoch(&zone->expiretime);
837         isc_time_settoepoch(&zone->refreshtime);
838         isc_time_settoepoch(&zone->dumptime);
839         isc_time_settoepoch(&zone->loadtime);
840         zone->notifytime = now;
841         isc_time_settoepoch(&zone->resigntime);
842         isc_time_settoepoch(&zone->keywarntime);
843         isc_time_settoepoch(&zone->signingtime);
844         isc_time_settoepoch(&zone->nsec3chaintime);
845         isc_time_settoepoch(&zone->refreshkeytime);
846         zone->refreshkeyinterval = 0;
847         zone->refreshkeycount = 0;
848         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
849         zone->retry = DNS_ZONE_DEFAULTRETRY;
850         zone->expire = 0;
851         zone->minimum = 0;
852         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
853         zone->minrefresh = DNS_ZONE_MINREFRESH;
854         zone->maxretry = DNS_ZONE_MAXRETRY;
855         zone->minretry = DNS_ZONE_MINRETRY;
856         zone->masters = NULL;
857         zone->masterkeynames = NULL;
858         zone->mastersok = NULL;
859         zone->masterscnt = 0;
860         zone->curmaster = 0;
861         zone->notify = NULL;
862         zone->notifykeynames = NULL;
863         zone->notifytype = dns_notifytype_yes;
864         zone->notifycnt = 0;
865         zone->task = NULL;
866         zone->loadtask = NULL;
867         zone->update_acl = NULL;
868         zone->forward_acl = NULL;
869         zone->notify_acl = NULL;
870         zone->query_acl = NULL;
871         zone->queryon_acl = NULL;
872         zone->xfr_acl = NULL;
873         zone->update_disabled = ISC_FALSE;
874         zone->zero_no_soa_ttl = ISC_TRUE;
875         zone->check_names = dns_severity_ignore;
876         zone->request = NULL;
877         zone->lctx = NULL;
878         zone->readio = NULL;
879         zone->dctx = NULL;
880         zone->writeio = NULL;
881         zone->timer = NULL;
882         zone->idlein = DNS_DEFAULT_IDLEIN;
883         zone->idleout = DNS_DEFAULT_IDLEOUT;
884         zone->log_key_expired_timer = 0;
885         ISC_LIST_INIT(zone->notifies);
886         isc_sockaddr_any(&zone->notifysrc4);
887         isc_sockaddr_any6(&zone->notifysrc6);
888         isc_sockaddr_any(&zone->xfrsource4);
889         isc_sockaddr_any6(&zone->xfrsource6);
890         isc_sockaddr_any(&zone->altxfrsource4);
891         isc_sockaddr_any6(&zone->altxfrsource6);
892         zone->xfr = NULL;
893         zone->tsigkey = NULL;
894         zone->maxxfrin = MAX_XFER_TIME;
895         zone->maxxfrout = MAX_XFER_TIME;
896         zone->ssutable = NULL;
897         zone->sigvalidityinterval = 30 * 24 * 3600;
898         zone->sigresigninginterval = 7 * 24 * 3600;
899         zone->view = NULL;
900         zone->acache = NULL;
901         zone->checkmx = NULL;
902         zone->checksrv = NULL;
903         zone->checkns = NULL;
904         ISC_LINK_INIT(zone, statelink);
905         zone->statelist = NULL;
906         zone->stats = NULL;
907         zone->requeststats_on = ISC_FALSE;
908         zone->statlevel = dns_zonestat_none;
909         zone->requeststats = NULL;
910         zone->rcvquerystats = NULL;
911         zone->notifydelay = 5;
912         zone->isself = NULL;
913         zone->isselfarg = NULL;
914         ISC_LIST_INIT(zone->signing);
915         ISC_LIST_INIT(zone->nsec3chain);
916         zone->signatures = 10;
917         zone->nodes = 100;
918         zone->privatetype = (dns_rdatatype_t)0xffffU;
919         zone->added = ISC_FALSE;
920         zone->is_rpz = ISC_FALSE;
921         ISC_LIST_INIT(zone->forwards);
922         zone->raw = NULL;
923         zone->secure = NULL;
924         zone->sourceserial = 0;
925         zone->sourceserialset = ISC_FALSE;
926
927         zone->magic = ZONE_MAGIC;
928
929         /* Must be after magic is set. */
930         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
931         if (result != ISC_R_SUCCESS)
932                 goto free_erefs;
933
934         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
935                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
936                        NULL, NULL);
937         *zonep = zone;
938         return (ISC_R_SUCCESS);
939
940  free_erefs:
941         isc_refcount_decrement(&zone->erefs, NULL);
942         isc_refcount_destroy(&zone->erefs);
943
944  free_dblock:
945         ZONEDB_DESTROYLOCK(&zone->dblock);
946
947  free_mutex:
948         DESTROYLOCK(&zone->lock);
949
950  free_zone:
951         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
952         return (result);
953 }
954
955 /*
956  * Free a zone.  Because we require that there be no more
957  * outstanding events or references, no locking is necessary.
958  */
959 static void
960 zone_free(dns_zone_t *zone) {
961         isc_mem_t *mctx = NULL;
962         dns_signing_t *signing;
963         dns_nsec3chain_t *nsec3chain;
964
965         REQUIRE(DNS_ZONE_VALID(zone));
966         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
967         REQUIRE(zone->irefs == 0);
968         REQUIRE(!LOCKED_ZONE(zone));
969         REQUIRE(zone->timer == NULL);
970
971         /*
972          * Managed objects.  Order is important.
973          */
974         if (zone->request != NULL)
975                 dns_request_destroy(&zone->request); /* XXXMPA */
976         INSIST(zone->readio == NULL);
977         INSIST(zone->statelist == NULL);
978         INSIST(zone->writeio == NULL);
979
980         if (zone->task != NULL)
981                 isc_task_detach(&zone->task);
982         if (zone->loadtask != NULL)
983                 isc_task_detach(&zone->loadtask);
984         if (zone->zmgr != NULL)
985                 dns_zonemgr_releasezone(zone->zmgr, zone);
986
987         /* Unmanaged objects */
988         for (signing = ISC_LIST_HEAD(zone->signing);
989              signing != NULL;
990              signing = ISC_LIST_HEAD(zone->signing)) {
991                 ISC_LIST_UNLINK(zone->signing, signing, link);
992                 dns_db_detach(&signing->db);
993                 dns_dbiterator_destroy(&signing->dbiterator);
994                 isc_mem_put(zone->mctx, signing, sizeof *signing);
995         }
996         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
997              nsec3chain != NULL;
998              nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
999                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1000                 dns_db_detach(&nsec3chain->db);
1001                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1002                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1003         }
1004         if (zone->masterfile != NULL)
1005                 isc_mem_free(zone->mctx, zone->masterfile);
1006         zone->masterfile = NULL;
1007         if (zone->keydirectory != NULL)
1008                 isc_mem_free(zone->mctx, zone->keydirectory);
1009         zone->keydirectory = NULL;
1010         zone->journalsize = -1;
1011         if (zone->journal != NULL)
1012                 isc_mem_free(zone->mctx, zone->journal);
1013         zone->journal = NULL;
1014         if (zone->stats != NULL)
1015                 isc_stats_detach(&zone->stats);
1016         if (zone->requeststats != NULL)
1017                 isc_stats_detach(&zone->requeststats);
1018         if(zone->rcvquerystats != NULL )
1019                 dns_stats_detach(&zone->rcvquerystats);
1020         if (zone->db != NULL)
1021                 zone_detachdb(zone);
1022         if (zone->acache != NULL)
1023                 dns_acache_detach(&zone->acache);
1024         zone_freedbargs(zone);
1025         RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
1026                       == ISC_R_SUCCESS);
1027         RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
1028                       == ISC_R_SUCCESS);
1029         zone->check_names = dns_severity_ignore;
1030         if (zone->update_acl != NULL)
1031                 dns_acl_detach(&zone->update_acl);
1032         if (zone->forward_acl != NULL)
1033                 dns_acl_detach(&zone->forward_acl);
1034         if (zone->notify_acl != NULL)
1035                 dns_acl_detach(&zone->notify_acl);
1036         if (zone->query_acl != NULL)
1037                 dns_acl_detach(&zone->query_acl);
1038         if (zone->queryon_acl != NULL)
1039                 dns_acl_detach(&zone->queryon_acl);
1040         if (zone->xfr_acl != NULL)
1041                 dns_acl_detach(&zone->xfr_acl);
1042         if (dns_name_dynamic(&zone->origin))
1043                 dns_name_free(&zone->origin, zone->mctx);
1044         if (zone->strnamerd != NULL)
1045                 isc_mem_free(zone->mctx, zone->strnamerd);
1046         if (zone->strname != NULL)
1047                 isc_mem_free(zone->mctx, zone->strname);
1048         if (zone->strrdclass != NULL)
1049                 isc_mem_free(zone->mctx, zone->strrdclass);
1050         if (zone->strviewname != NULL)
1051                 isc_mem_free(zone->mctx, zone->strviewname);
1052         if (zone->ssutable != NULL)
1053                 dns_ssutable_detach(&zone->ssutable);
1054
1055         /* last stuff */
1056         ZONEDB_DESTROYLOCK(&zone->dblock);
1057         DESTROYLOCK(&zone->lock);
1058         isc_refcount_destroy(&zone->erefs);
1059         zone->magic = 0;
1060         mctx = zone->mctx;
1061         isc_mem_put(mctx, zone, sizeof(*zone));
1062         isc_mem_detach(&mctx);
1063 }
1064
1065 /*
1066  * Returns ISC_TRUE iff this the signed side of an inline-signing zone.
1067  * Caller should hold zone lock.
1068  */
1069 static inline isc_boolean_t
1070 inline_secure(dns_zone_t *zone) {
1071         REQUIRE(DNS_ZONE_VALID(zone));
1072         if (zone->raw != NULL)
1073                 return (ISC_TRUE);
1074         return (ISC_FALSE);
1075 }
1076
1077 /*
1078  * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone
1079  * Caller should hold zone lock.
1080  */
1081 static inline isc_boolean_t
1082 inline_raw(dns_zone_t *zone) {
1083         REQUIRE(DNS_ZONE_VALID(zone));
1084         if (zone->secure != NULL)
1085                 return (ISC_TRUE);
1086         return (ISC_FALSE);
1087 }
1088
1089 /*
1090  *      Single shot.
1091  */
1092 void
1093 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1094         char namebuf[1024];
1095
1096         REQUIRE(DNS_ZONE_VALID(zone));
1097         REQUIRE(rdclass != dns_rdataclass_none);
1098
1099         /*
1100          * Test and set.
1101          */
1102         LOCK_ZONE(zone);
1103         REQUIRE(zone->rdclass == dns_rdataclass_none ||
1104                 zone->rdclass == rdclass);
1105         zone->rdclass = rdclass;
1106
1107         if (zone->strnamerd != NULL)
1108                 isc_mem_free(zone->mctx, zone->strnamerd);
1109         if (zone->strrdclass != NULL)
1110                 isc_mem_free(zone->mctx, zone->strrdclass);
1111
1112         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1113         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1114         zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1115         zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1116
1117         if (inline_secure(zone))
1118                 dns_zone_setclass(zone->raw, rdclass);
1119         UNLOCK_ZONE(zone);
1120 }
1121
1122 dns_rdataclass_t
1123 dns_zone_getclass(dns_zone_t *zone) {
1124         REQUIRE(DNS_ZONE_VALID(zone));
1125
1126         return (zone->rdclass);
1127 }
1128
1129 void
1130 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1131         REQUIRE(DNS_ZONE_VALID(zone));
1132
1133         LOCK_ZONE(zone);
1134         zone->notifytype = notifytype;
1135         UNLOCK_ZONE(zone);
1136 }
1137
1138 isc_result_t
1139 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1140         isc_result_t result;
1141         unsigned int soacount;
1142
1143         REQUIRE(DNS_ZONE_VALID(zone));
1144         REQUIRE(serialp != NULL);
1145
1146         LOCK_ZONE(zone);
1147         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1148         if (zone->db != NULL) {
1149                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1150                                           serialp, NULL, NULL, NULL, NULL,
1151                                           NULL);
1152                 if (result == ISC_R_SUCCESS && soacount == 0)
1153                         result = ISC_R_FAILURE;
1154         } else
1155                 result = DNS_R_NOTLOADED;
1156         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1157         UNLOCK_ZONE(zone);
1158
1159         return (result);
1160 }
1161
1162 isc_uint32_t
1163 dns_zone_getserial(dns_zone_t *zone) {
1164         isc_result_t result;
1165         isc_uint32_t serial;
1166
1167         result = dns_zone_getserial2(zone, &serial);
1168         if (result != ISC_R_SUCCESS)
1169                 serial = 0; /* XXX: not really correct, but no other choice */
1170
1171         return (serial);
1172 }
1173
1174 /*
1175  *      Single shot.
1176  */
1177 void
1178 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1179         char namebuf[1024];
1180
1181         REQUIRE(DNS_ZONE_VALID(zone));
1182         REQUIRE(type != dns_zone_none);
1183
1184         /*
1185          * Test and set.
1186          */
1187         LOCK_ZONE(zone);
1188         REQUIRE(zone->type == dns_zone_none || zone->type == type);
1189         zone->type = type;
1190
1191         if (zone->strnamerd != NULL)
1192                 isc_mem_free(zone->mctx, zone->strnamerd);
1193
1194         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1195         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1196         UNLOCK_ZONE(zone);
1197 }
1198
1199 static void
1200 zone_freedbargs(dns_zone_t *zone) {
1201         unsigned int i;
1202
1203         /* Free the old database argument list. */
1204         if (zone->db_argv != NULL) {
1205                 for (i = 0; i < zone->db_argc; i++)
1206                         isc_mem_free(zone->mctx, zone->db_argv[i]);
1207                 isc_mem_put(zone->mctx, zone->db_argv,
1208                             zone->db_argc * sizeof(*zone->db_argv));
1209         }
1210         zone->db_argc = 0;
1211         zone->db_argv = NULL;
1212 }
1213
1214 isc_result_t
1215 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1216         size_t size = 0;
1217         unsigned int i;
1218         isc_result_t result = ISC_R_SUCCESS;
1219         void *mem;
1220         char **tmp, *tmp2;
1221
1222         REQUIRE(DNS_ZONE_VALID(zone));
1223         REQUIRE(argv != NULL && *argv == NULL);
1224
1225         LOCK_ZONE(zone);
1226         size = (zone->db_argc + 1) * sizeof(char *);
1227         for (i = 0; i < zone->db_argc; i++)
1228                 size += strlen(zone->db_argv[i]) + 1;
1229         mem = isc_mem_allocate(mctx, size);
1230         if (mem != NULL) {
1231                 tmp = mem;
1232                 tmp2 = mem;
1233                 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1234                 for (i = 0; i < zone->db_argc; i++) {
1235                         *tmp++ = tmp2;
1236                         strcpy(tmp2, zone->db_argv[i]);
1237                         tmp2 += strlen(tmp2) + 1;
1238                 }
1239                 *tmp = NULL;
1240         } else
1241                 result = ISC_R_NOMEMORY;
1242         UNLOCK_ZONE(zone);
1243         *argv = mem;
1244         return (result);
1245 }
1246
1247 isc_result_t
1248 dns_zone_setdbtype(dns_zone_t *zone,
1249                    unsigned int dbargc, const char * const *dbargv) {
1250         isc_result_t result = ISC_R_SUCCESS;
1251         char **new = NULL;
1252         unsigned int i;
1253
1254         REQUIRE(DNS_ZONE_VALID(zone));
1255         REQUIRE(dbargc >= 1);
1256         REQUIRE(dbargv != NULL);
1257
1258         LOCK_ZONE(zone);
1259
1260         /* Set up a new database argument list. */
1261         new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1262         if (new == NULL)
1263                 goto nomem;
1264         for (i = 0; i < dbargc; i++)
1265                 new[i] = NULL;
1266         for (i = 0; i < dbargc; i++) {
1267                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1268                 if (new[i] == NULL)
1269                         goto nomem;
1270         }
1271
1272         /* Free the old list. */
1273         zone_freedbargs(zone);
1274
1275         zone->db_argc = dbargc;
1276         zone->db_argv = new;
1277         result = ISC_R_SUCCESS;
1278         goto unlock;
1279
1280  nomem:
1281         if (new != NULL) {
1282                 for (i = 0; i < dbargc; i++)
1283                         if (new[i] != NULL)
1284                                 isc_mem_free(zone->mctx, new[i]);
1285                 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1286         }
1287         result = ISC_R_NOMEMORY;
1288
1289  unlock:
1290         UNLOCK_ZONE(zone);
1291         return (result);
1292 }
1293
1294 void
1295 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1296         char namebuf[1024];
1297         REQUIRE(DNS_ZONE_VALID(zone));
1298
1299         LOCK_ZONE(zone);
1300         if (zone->view != NULL)
1301                 dns_view_weakdetach(&zone->view);
1302         dns_view_weakattach(view, &zone->view);
1303
1304         if (zone->strviewname != NULL)
1305                 isc_mem_free(zone->mctx, zone->strviewname);
1306         if (zone->strnamerd != NULL)
1307                 isc_mem_free(zone->mctx, zone->strnamerd);
1308
1309         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1310         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1311         zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1312         zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1313
1314         if (inline_secure(zone))
1315                 dns_zone_setview(zone->raw, view);
1316
1317         UNLOCK_ZONE(zone);
1318 }
1319
1320 dns_view_t *
1321 dns_zone_getview(dns_zone_t *zone) {
1322         REQUIRE(DNS_ZONE_VALID(zone));
1323
1324         return (zone->view);
1325 }
1326
1327
1328 isc_result_t
1329 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1330         isc_result_t result;
1331         char namebuf[1024];
1332
1333         REQUIRE(DNS_ZONE_VALID(zone));
1334         REQUIRE(origin != NULL);
1335
1336         LOCK_ZONE(zone);
1337         if (dns_name_dynamic(&zone->origin)) {
1338                 dns_name_free(&zone->origin, zone->mctx);
1339                 dns_name_init(&zone->origin, NULL);
1340         }
1341         result = dns_name_dup(origin, zone->mctx, &zone->origin);
1342
1343         if (zone->strnamerd != NULL)
1344                 isc_mem_free(zone->mctx, zone->strnamerd);
1345         if (zone->strname != NULL)
1346                 isc_mem_free(zone->mctx, zone->strname);
1347
1348         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1349         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1350         zone_name_tostr(zone, namebuf, sizeof namebuf);
1351         zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1352
1353         if (result == ISC_R_SUCCESS && inline_secure(zone))
1354                 result = dns_zone_setorigin(zone->raw, origin);
1355         UNLOCK_ZONE(zone);
1356         return (result);
1357 }
1358
1359 void
1360 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1361         REQUIRE(DNS_ZONE_VALID(zone));
1362         REQUIRE(acache != NULL);
1363
1364         LOCK_ZONE(zone);
1365         if (zone->acache != NULL)
1366                 dns_acache_detach(&zone->acache);
1367         dns_acache_attach(acache, &zone->acache);
1368         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1369         if (zone->db != NULL) {
1370                 isc_result_t result;
1371
1372                 /*
1373                  * If the zone reuses an existing DB, the DB needs to be
1374                  * set in the acache explicitly.  We can safely ignore the
1375                  * case where the DB is already set.  If other error happens,
1376                  * the acache will not work effectively.
1377                  */
1378                 result = dns_acache_setdb(acache, zone->db);
1379                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1380                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1381                                          "dns_acache_setdb() failed: %s",
1382                                          isc_result_totext(result));
1383                 }
1384         }
1385         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1386         UNLOCK_ZONE(zone);
1387 }
1388
1389 static isc_result_t
1390 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1391         char *copy;
1392
1393         if (value != NULL) {
1394                 copy = isc_mem_strdup(zone->mctx, value);
1395                 if (copy == NULL)
1396                         return (ISC_R_NOMEMORY);
1397         } else {
1398                 copy = NULL;
1399         }
1400
1401         if (*field != NULL)
1402                 isc_mem_free(zone->mctx, *field);
1403
1404         *field = copy;
1405         return (ISC_R_SUCCESS);
1406 }
1407
1408 isc_result_t
1409 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1410         return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1411 }
1412
1413 isc_result_t
1414 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1415                   dns_masterformat_t format) {
1416         isc_result_t result = ISC_R_SUCCESS;
1417
1418         REQUIRE(DNS_ZONE_VALID(zone));
1419
1420         LOCK_ZONE(zone);
1421         result = dns_zone_setstring(zone, &zone->masterfile, file);
1422         if (result == ISC_R_SUCCESS) {
1423                 zone->masterformat = format;
1424                 result = default_journal(zone);
1425         }
1426         UNLOCK_ZONE(zone);
1427
1428         return (result);
1429 }
1430
1431 const char *
1432 dns_zone_getfile(dns_zone_t *zone) {
1433         REQUIRE(DNS_ZONE_VALID(zone));
1434
1435         return (zone->masterfile);
1436 }
1437
1438 static isc_result_t
1439 default_journal(dns_zone_t *zone) {
1440         isc_result_t result;
1441         char *journal;
1442
1443         REQUIRE(DNS_ZONE_VALID(zone));
1444         REQUIRE(LOCKED_ZONE(zone));
1445
1446         if (zone->masterfile != NULL) {
1447                 /* Calculate string length including '\0'. */
1448                 int len = strlen(zone->masterfile) + sizeof(".jnl");
1449                 journal = isc_mem_allocate(zone->mctx, len);
1450                 if (journal == NULL)
1451                         return (ISC_R_NOMEMORY);
1452                 strcpy(journal, zone->masterfile);
1453                 strcat(journal, ".jnl");
1454         } else {
1455                 journal = NULL;
1456         }
1457         result = dns_zone_setstring(zone, &zone->journal, journal);
1458         if (journal != NULL)
1459                 isc_mem_free(zone->mctx, journal);
1460         return (result);
1461 }
1462
1463 isc_result_t
1464 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1465         isc_result_t result = ISC_R_SUCCESS;
1466
1467         REQUIRE(DNS_ZONE_VALID(zone));
1468
1469         LOCK_ZONE(zone);
1470         result = dns_zone_setstring(zone, &zone->journal, journal);
1471         UNLOCK_ZONE(zone);
1472
1473         return (result);
1474 }
1475
1476 char *
1477 dns_zone_getjournal(dns_zone_t *zone) {
1478         REQUIRE(DNS_ZONE_VALID(zone));
1479
1480         return (zone->journal);
1481 }
1482
1483 /*
1484  * Return true iff the zone is "dynamic", in the sense that the zone's
1485  * master file (if any) is written by the server, rather than being
1486  * updated manually and read by the server.
1487  *
1488  * This is true for slave zones, stub zones, key zones, and zones that
1489  * allow dynamic updates either by having an update policy ("ssutable")
1490  * or an "allow-update" ACL with a value other than exactly "{ none; }".
1491  */
1492 isc_boolean_t
1493 dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) {
1494         REQUIRE(DNS_ZONE_VALID(zone));
1495
1496         if (zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1497             zone->type == dns_zone_key ||
1498             (zone->type == dns_zone_redirect && zone->masters != NULL))
1499                 return (ISC_TRUE);
1500
1501         /* If !ignore_freeze, we need check whether updates are disabled.  */
1502         if (zone->type == dns_zone_master &&
1503             (!zone->update_disabled || ignore_freeze) &&
1504             ((zone->ssutable != NULL) ||
1505              (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1506                 return (ISC_TRUE);
1507
1508         return (ISC_FALSE);
1509
1510 }
1511
1512 /*
1513  * Set the response policy index and information for a zone.
1514  */
1515 isc_result_t
1516 dns_zone_rpz_enable(dns_zone_t *zone) {
1517         /*
1518          * Only RBTDB zones can be used for response policy zones,
1519          * because only they have the code to load the create the summary data.
1520          * Only zones that are loaded instead of mmap()ed create the
1521          * summary data and so can be policy zones.
1522          */
1523         if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1524             strcmp(zone->db_argv[0], "rbt64") != 0)
1525                 return (ISC_R_NOTIMPLEMENTED);
1526
1527         zone->is_rpz = ISC_TRUE;
1528
1529         return (ISC_R_SUCCESS);
1530 }
1531
1532 isc_boolean_t
1533 dns_zone_get_rpz(dns_zone_t *zone) {
1534         return (zone->is_rpz);
1535 }
1536
1537 static isc_result_t
1538 zone_load(dns_zone_t *zone, unsigned int flags) {
1539         isc_result_t result;
1540         isc_time_t now;
1541         isc_time_t loadtime, filetime;
1542         dns_db_t *db = NULL;
1543         isc_boolean_t rbt, hasraw;
1544
1545         REQUIRE(DNS_ZONE_VALID(zone));
1546
1547         LOCK_ZONE(zone);
1548         hasraw = inline_secure(zone);
1549         if (hasraw) {
1550                 result = zone_load(zone->raw, flags);
1551                 if (result != ISC_R_SUCCESS) {
1552                         UNLOCK_ZONE(zone);
1553                         return(result);
1554                 }
1555                 LOCK_ZONE(zone->raw);
1556         }
1557
1558         TIME_NOW(&now);
1559
1560         INSIST(zone->type != dns_zone_none);
1561
1562         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1563                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1564                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1565                 result = DNS_R_CONTINUE;
1566                 goto cleanup;
1567         }
1568
1569         INSIST(zone->db_argc >= 1);
1570
1571         rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1572               strcmp(zone->db_argv[0], "rbt64") == 0;
1573
1574         if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1575                 /*
1576                  * The zone has no master file configured.
1577                  */
1578                 result = ISC_R_SUCCESS;
1579                 goto cleanup;
1580         }
1581
1582         if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) {
1583                 /*
1584                  * This is a slave, stub, or dynamically updated
1585                  * zone being reloaded.  Do nothing - the database
1586                  * we already have is guaranteed to be up-to-date.
1587                  */
1588                 if (zone->type == dns_zone_master)
1589                         result = DNS_R_DYNAMIC;
1590                 else
1591                         result = ISC_R_SUCCESS;
1592                 goto cleanup;
1593         }
1594
1595         /*
1596          * Store the current time before the zone is loaded, so that if the
1597          * file changes between the time of the load and the time that
1598          * zone->loadtime is set, then the file will still be reloaded
1599          * the next time dns_zone_load is called.
1600          */
1601         TIME_NOW(&loadtime);
1602
1603         /*
1604          * Don't do the load if the file that stores the zone is older
1605          * than the last time the zone was loaded.  If the zone has not
1606          * been loaded yet, zone->loadtime will be the epoch.
1607          */
1608         if (zone->masterfile != NULL) {
1609                 /*
1610                  * The file is already loaded.  If we are just doing a
1611                  * "rndc reconfig", we are done.
1612                  */
1613                 if (!isc_time_isepoch(&zone->loadtime) &&
1614                     (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1615                         result = ISC_R_SUCCESS;
1616                         goto cleanup;
1617                 }
1618
1619                 result = isc_file_getmodtime(zone->masterfile, &filetime);
1620                 if (result == ISC_R_SUCCESS) {
1621                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1622                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1623                             isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1624                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1625                                              "skipping load: master file "
1626                                              "older than last load");
1627                                 result = DNS_R_UPTODATE;
1628                                 goto cleanup;
1629                         }
1630                         loadtime = filetime;
1631                 }
1632         }
1633
1634         /*
1635          * Built in zones (with the exception of empty zones) don't need
1636          * to be reloaded.
1637          */
1638         if (zone->type == dns_zone_master &&
1639             strcmp(zone->db_argv[0], "_builtin") == 0 &&
1640             (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1641             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1642                 result = ISC_R_SUCCESS;
1643                 goto cleanup;
1644         }
1645
1646         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1647              (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
1648             rbt) {
1649                 if (zone->masterfile == NULL ||
1650                     !isc_file_exists(zone->masterfile)) {
1651                         if (zone->masterfile != NULL) {
1652                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1653                                              "no master file");
1654                         }
1655                         zone->refreshtime = now;
1656                         if (zone->task != NULL)
1657                                 zone_settimer(zone, &now);
1658                         result = ISC_R_SUCCESS;
1659                         goto cleanup;
1660                 }
1661         }
1662
1663         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1664
1665         result = dns_db_create(zone->mctx, zone->db_argv[0],
1666                                &zone->origin, (zone->type == dns_zone_stub) ?
1667                                dns_dbtype_stub : dns_dbtype_zone,
1668                                zone->rdclass,
1669                                zone->db_argc - 1, zone->db_argv + 1,
1670                                &db);
1671
1672         if (result != ISC_R_SUCCESS) {
1673                 dns_zone_log(zone, ISC_LOG_ERROR,
1674                              "loading zone: creating database: %s",
1675                              isc_result_totext(result));
1676                 goto cleanup;
1677         }
1678         dns_db_settask(db, zone->task);
1679
1680         if (! dns_db_ispersistent(db)) {
1681                 if (zone->masterfile != NULL) {
1682                         result = zone_startload(db, zone, loadtime);
1683                 } else {
1684                         result = DNS_R_NOMASTERFILE;
1685                         if (zone->type == dns_zone_master ||
1686                             (zone->type == dns_zone_redirect &&
1687                              zone->masters == NULL)) {
1688                                 dns_zone_log(zone, ISC_LOG_ERROR,
1689                                              "loading zone: "
1690                                              "no master file configured");
1691                                 goto cleanup;
1692                         }
1693                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1694                                      "no master file configured: continuing");
1695                 }
1696         }
1697
1698         if (result == DNS_R_CONTINUE) {
1699                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1700                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1701                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1702                 goto cleanup;
1703         }
1704
1705         result = zone_postload(zone, db, loadtime, result);
1706
1707  cleanup:
1708         if (hasraw)
1709                 UNLOCK_ZONE(zone->raw);
1710         UNLOCK_ZONE(zone);
1711         if (db != NULL)
1712                 dns_db_detach(&db);
1713         return (result);
1714 }
1715
1716 isc_result_t
1717 dns_zone_load(dns_zone_t *zone) {
1718         return (zone_load(zone, 0));
1719 }
1720
1721 isc_result_t
1722 dns_zone_loadnew(dns_zone_t *zone) {
1723         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1724 }
1725
1726 static void
1727 zone_asyncload(isc_task_t *task, isc_event_t *event) {
1728         dns_asyncload_t *asl = event->ev_arg;
1729         dns_zone_t *zone = asl->zone;
1730         isc_result_t result = ISC_R_SUCCESS;
1731
1732         UNUSED(task);
1733
1734         REQUIRE(DNS_ZONE_VALID(zone));
1735
1736         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1737                 result = ISC_R_CANCELED;
1738         isc_event_free(&event);
1739         if (result == ISC_R_CANCELED ||
1740             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
1741                 goto cleanup;
1742
1743         zone_load(zone, 0);
1744
1745         LOCK_ZONE(zone);
1746         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1747         UNLOCK_ZONE(zone);
1748
1749         /* Inform the zone table we've finished loading */
1750         if (asl->loaded != NULL)
1751                 (asl->loaded)(asl->loaded_arg, zone, task);
1752
1753  cleanup:
1754         isc_mem_put(zone->mctx, asl, sizeof (*asl));
1755         dns_zone_idetach(&zone);
1756 }
1757
1758 isc_result_t
1759 dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
1760         isc_event_t *e;
1761         dns_asyncload_t *asl = NULL;
1762         isc_result_t result = ISC_R_SUCCESS;
1763
1764         REQUIRE(DNS_ZONE_VALID(zone));
1765
1766         if (zone->zmgr == NULL)
1767                 return (ISC_R_FAILURE);
1768
1769         asl = isc_mem_get(zone->mctx, sizeof (*asl));
1770         if (asl == NULL)
1771                 CHECK(ISC_R_NOMEMORY);
1772
1773         asl->zone = NULL;
1774         asl->loaded = done;
1775         asl->loaded_arg = arg;
1776
1777         e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
1778                                DNS_EVENT_ZONELOAD,
1779                                zone_asyncload, asl,
1780                                sizeof(isc_event_t));
1781         if (e == NULL)
1782                 CHECK(ISC_R_NOMEMORY);
1783
1784         LOCK_ZONE(zone);
1785         zone_iattach(zone, &asl->zone);
1786         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1787         isc_task_send(zone->loadtask, &e);
1788         UNLOCK_ZONE(zone);
1789
1790         return (ISC_R_SUCCESS);
1791
1792   failure:
1793         if (asl != NULL)
1794                 isc_mem_put(zone->mctx, asl, sizeof (*asl));
1795         return (result);
1796 }
1797
1798 isc_boolean_t
1799 dns__zone_loadpending(dns_zone_t *zone) {
1800         REQUIRE(DNS_ZONE_VALID(zone));
1801
1802         return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)));
1803 }
1804
1805 isc_result_t
1806 dns_zone_loadandthaw(dns_zone_t *zone) {
1807         isc_result_t result;
1808
1809         if (inline_raw(zone))
1810                 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW);
1811         else
1812                 result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1813
1814         switch (result) {
1815         case DNS_R_CONTINUE:
1816                 /* Deferred thaw. */
1817                 break;
1818         case DNS_R_UPTODATE:
1819         case ISC_R_SUCCESS:
1820         case DNS_R_SEENINCLUDE:
1821                 zone->update_disabled = ISC_FALSE;
1822                 break;
1823         case DNS_R_NOMASTERFILE:
1824                 zone->update_disabled = ISC_FALSE;
1825                 break;
1826         default:
1827                 /* Error, remain in disabled state. */
1828                 break;
1829         }
1830         return (result);
1831 }
1832
1833 static unsigned int
1834 get_master_options(dns_zone_t *zone) {
1835         unsigned int options;
1836
1837         options = DNS_MASTER_ZONE;
1838         if (zone->type == dns_zone_slave ||
1839             (zone->type == dns_zone_redirect && zone->masters == NULL))
1840                 options |= DNS_MASTER_SLAVE;
1841         if (zone->type == dns_zone_key)
1842                 options |= DNS_MASTER_KEY;
1843         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1844                 options |= DNS_MASTER_CHECKNS;
1845         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1846                 options |= DNS_MASTER_FATALNS;
1847         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1848                 options |= DNS_MASTER_CHECKNAMES;
1849         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1850                 options |= DNS_MASTER_CHECKNAMESFAIL;
1851         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1852                 options |= DNS_MASTER_CHECKMX;
1853         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1854                 options |= DNS_MASTER_CHECKMXFAIL;
1855         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1856                 options |= DNS_MASTER_CHECKWILDCARD;
1857         if (inline_secure(zone) || (zone->type == dns_zone_master &&
1858             ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1859               zone->ssutable != NULL)))
1860                 options |= DNS_MASTER_RESIGN;
1861         return (options);
1862 }
1863
1864 static void
1865 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1866         dns_load_t *load = event->ev_arg;
1867         isc_result_t result = ISC_R_SUCCESS;
1868         unsigned int options;
1869
1870         REQUIRE(DNS_LOAD_VALID(load));
1871
1872         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1873                 result = ISC_R_CANCELED;
1874         isc_event_free(&event);
1875         if (result == ISC_R_CANCELED)
1876                 goto fail;
1877
1878         options = get_master_options(load->zone);
1879
1880         result = dns_master_loadfileinc3(load->zone->masterfile,
1881                                          dns_db_origin(load->db),
1882                                          dns_db_origin(load->db),
1883                                          load->zone->rdclass, options,
1884                                          load->zone->sigresigninginterval,
1885                                          &load->callbacks, task,
1886                                          zone_loaddone, load,
1887                                          &load->zone->lctx, load->zone->mctx,
1888                                          load->zone->masterformat);
1889         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1890             result != DNS_R_SEENINCLUDE)
1891                 goto fail;
1892         return;
1893
1894  fail:
1895         zone_loaddone(load, result);
1896 }
1897
1898 static void
1899 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
1900         isc_result_t result;
1901         unsigned int soacount;
1902
1903         LOCK(&raw->lock);
1904         if (raw->db != NULL) {
1905                 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
1906                                           &rawdata->sourceserial,
1907                                           NULL, NULL, NULL, NULL,
1908                                           NULL);
1909                 if (result == ISC_R_SUCCESS && soacount > 0U)
1910                         rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
1911         }
1912         UNLOCK(&raw->lock);
1913 }
1914
1915 static void
1916 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1917         const char me[] = "zone_gotwritehandle";
1918         dns_zone_t *zone = event->ev_arg;
1919         isc_result_t result = ISC_R_SUCCESS;
1920         dns_dbversion_t *version = NULL;
1921         dns_masterrawheader_t rawdata;
1922
1923         REQUIRE(DNS_ZONE_VALID(zone));
1924         INSIST(task == zone->task);
1925         ENTER;
1926
1927         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1928                 result = ISC_R_CANCELED;
1929         isc_event_free(&event);
1930         if (result == ISC_R_CANCELED)
1931                 goto fail;
1932
1933         LOCK_ZONE(zone);
1934         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1935         if (zone->db != NULL) {
1936                 dns_db_currentversion(zone->db, &version);
1937                 dns_master_initrawheader(&rawdata);
1938                 if (inline_secure(zone))
1939                         get_raw_serial(zone->raw, &rawdata);
1940                 result = dns_master_dumpinc3(zone->mctx, zone->db, version,
1941                                              &dns_master_style_default,
1942                                              zone->masterfile, zone->task,
1943                                              dump_done, zone, &zone->dctx,
1944                                              zone->masterformat, &rawdata);
1945                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
1946         } else
1947                 result = ISC_R_CANCELED;
1948         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1949         UNLOCK_ZONE(zone);
1950         if (result != DNS_R_CONTINUE)
1951                 goto fail;
1952         return;
1953
1954  fail:
1955         dump_done(zone, result);
1956 }
1957
1958 /*
1959  * Save the raw serial number for inline-signing zones.
1960  * (XXX: Other information from the header will be used
1961  * for other purposes in the future, but for now this is
1962  * all we're interested in.)
1963  */
1964 static void
1965 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
1966         if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
1967                 return;
1968
1969         zone->sourceserial = header->sourceserial;
1970         zone->sourceserialset = ISC_TRUE;
1971 }
1972
1973 void
1974 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
1975         if (zone == NULL)
1976                 return;
1977
1978         LOCK_ZONE(zone);
1979         zone_setrawdata(zone, header);
1980         UNLOCK_ZONE(zone);
1981 }
1982
1983 static isc_result_t
1984 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1985         dns_load_t *load;
1986         isc_result_t result;
1987         isc_result_t tresult;
1988         unsigned int options;
1989
1990 #ifdef BIND9
1991         if (zone->is_rpz) {
1992                 result = dns_db_rpz_enabled(db, NULL);
1993                 if (result != ISC_R_SUCCESS)
1994                         return (result);
1995         }
1996 #endif
1997
1998         options = get_master_options(zone);
1999         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
2000                 options |= DNS_MASTER_MANYERRORS;
2001
2002         if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2003                 load = isc_mem_get(zone->mctx, sizeof(*load));
2004                 if (load == NULL)
2005                         return (ISC_R_NOMEMORY);
2006
2007                 load->mctx = NULL;
2008                 load->zone = NULL;
2009                 load->db = NULL;
2010                 load->loadtime = loadtime;
2011                 load->magic = LOAD_MAGIC;
2012
2013                 isc_mem_attach(zone->mctx, &load->mctx);
2014                 zone_iattach(zone, &load->zone);
2015                 dns_db_attach(db, &load->db);
2016                 dns_rdatacallbacks_init(&load->callbacks);
2017                 load->callbacks.rawdata = zone_setrawdata;
2018                 zone_iattach(zone, &load->callbacks.zone);
2019                 result = dns_db_beginload(db, &load->callbacks.add,
2020                                           &load->callbacks.add_private);
2021                 if (result != ISC_R_SUCCESS)
2022                         goto cleanup;
2023                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask,
2024                                        zone_gotreadhandle, load,
2025                                        &zone->readio);
2026                 if (result != ISC_R_SUCCESS) {
2027                         /*
2028                          * We can't report multiple errors so ignore
2029                          * the result of dns_db_endload().
2030                          */
2031                         (void)dns_db_endload(load->db,
2032                                              &load->callbacks.add_private);
2033                         goto cleanup;
2034                 } else
2035                         result = DNS_R_CONTINUE;
2036         } else {
2037                 dns_rdatacallbacks_t callbacks;
2038
2039                 dns_rdatacallbacks_init(&callbacks);
2040                 callbacks.rawdata = zone_setrawdata;
2041                 zone_iattach(zone, &callbacks.zone);
2042                 result = dns_db_beginload(db, &callbacks.add,
2043                                           &callbacks.add_private);
2044                 if (result != ISC_R_SUCCESS) {
2045                         zone_idetach(&callbacks.zone);
2046                         return (result);
2047                 }
2048                 result = dns_master_loadfile3(zone->masterfile,
2049                                               &zone->origin, &zone->origin,
2050                                               zone->rdclass, options,
2051                                               zone->sigresigninginterval,
2052                                               &callbacks, zone->mctx,
2053                                               zone->masterformat);
2054                 tresult = dns_db_endload(db, &callbacks.add_private);
2055                 if (result == ISC_R_SUCCESS)
2056                         result = tresult;
2057                 zone_idetach(&callbacks.zone);
2058         }
2059
2060         return (result);
2061
2062  cleanup:
2063         load->magic = 0;
2064         dns_db_detach(&load->db);
2065         zone_idetach(&load->zone);
2066         zone_idetach(&load->callbacks.zone);
2067         isc_mem_detach(&load->mctx);
2068         isc_mem_put(zone->mctx, load, sizeof(*load));
2069         return (result);
2070 }
2071
2072 static isc_boolean_t
2073 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2074               dns_name_t *owner)
2075 {
2076         isc_result_t result;
2077         char ownerbuf[DNS_NAME_FORMATSIZE];
2078         char namebuf[DNS_NAME_FORMATSIZE];
2079         char altbuf[DNS_NAME_FORMATSIZE];
2080         dns_fixedname_t fixed;
2081         dns_name_t *foundname;
2082         int level;
2083
2084         /*
2085          * "." means the services does not exist.
2086          */
2087         if (dns_name_equal(name, dns_rootname))
2088                 return (ISC_TRUE);
2089
2090         /*
2091          * Outside of zone.
2092          */
2093         if (!dns_name_issubdomain(name, &zone->origin)) {
2094                 if (zone->checkmx != NULL)
2095                         return ((zone->checkmx)(zone, name, owner));
2096                 return (ISC_TRUE);
2097         }
2098
2099         if (zone->type == dns_zone_master)
2100                 level = ISC_LOG_ERROR;
2101         else
2102                 level = ISC_LOG_WARNING;
2103
2104         dns_fixedname_init(&fixed);
2105         foundname = dns_fixedname_name(&fixed);
2106
2107         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2108                              0, 0, NULL, foundname, NULL, NULL);
2109         if (result == ISC_R_SUCCESS)
2110                 return (ISC_TRUE);
2111
2112         if (result == DNS_R_NXRRSET) {
2113                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2114                                      0, 0, NULL, foundname, NULL, NULL);
2115                 if (result == ISC_R_SUCCESS)
2116                         return (ISC_TRUE);
2117         }
2118
2119         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2120         dns_name_format(name, namebuf, sizeof namebuf);
2121         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2122             result == DNS_R_EMPTYNAME) {
2123                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2124                         level = ISC_LOG_WARNING;
2125                 dns_zone_log(zone, level,
2126                              "%s/MX '%s' has no address records (A or AAAA)",
2127                              ownerbuf, namebuf);
2128                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2129         }
2130
2131         if (result == DNS_R_CNAME) {
2132                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2133                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2134                         level = ISC_LOG_WARNING;
2135                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2136                         dns_zone_log(zone, level,
2137                                      "%s/MX '%s' is a CNAME (illegal)",
2138                                      ownerbuf, namebuf);
2139                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2140         }
2141
2142         if (result == DNS_R_DNAME) {
2143                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2144                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2145                         level = ISC_LOG_WARNING;
2146                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2147                         dns_name_format(foundname, altbuf, sizeof altbuf);
2148                         dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2149                                      " '%s' (illegal)", ownerbuf, namebuf,
2150                                      altbuf);
2151                 }
2152                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2153         }
2154
2155         if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2156                 return ((zone->checkmx)(zone, name, owner));
2157
2158         return (ISC_TRUE);
2159 }
2160
2161 static isc_boolean_t
2162 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2163                dns_name_t *owner)
2164 {
2165         isc_result_t result;
2166         char ownerbuf[DNS_NAME_FORMATSIZE];
2167         char namebuf[DNS_NAME_FORMATSIZE];
2168         char altbuf[DNS_NAME_FORMATSIZE];
2169         dns_fixedname_t fixed;
2170         dns_name_t *foundname;
2171         int level;
2172
2173         /*
2174          * "." means the services does not exist.
2175          */
2176         if (dns_name_equal(name, dns_rootname))
2177                 return (ISC_TRUE);
2178
2179         /*
2180          * Outside of zone.
2181          */
2182         if (!dns_name_issubdomain(name, &zone->origin)) {
2183                 if (zone->checksrv != NULL)
2184                         return ((zone->checksrv)(zone, name, owner));
2185                 return (ISC_TRUE);
2186         }
2187
2188         if (zone->type == dns_zone_master)
2189                 level = ISC_LOG_ERROR;
2190         else
2191                 level = ISC_LOG_WARNING;
2192
2193         dns_fixedname_init(&fixed);
2194         foundname = dns_fixedname_name(&fixed);
2195
2196         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2197                              0, 0, NULL, foundname, NULL, NULL);
2198         if (result == ISC_R_SUCCESS)
2199                 return (ISC_TRUE);
2200
2201         if (result == DNS_R_NXRRSET) {
2202                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2203                                      0, 0, NULL, foundname, NULL, NULL);
2204                 if (result == ISC_R_SUCCESS)
2205                         return (ISC_TRUE);
2206         }
2207
2208         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2209         dns_name_format(name, namebuf, sizeof namebuf);
2210         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2211             result == DNS_R_EMPTYNAME) {
2212                 dns_zone_log(zone, level,
2213                              "%s/SRV '%s' has no address records (A or AAAA)",
2214                              ownerbuf, namebuf);
2215                 /* XXX950 make fatal for 9.5.0. */
2216                 return (ISC_TRUE);
2217         }
2218
2219         if (result == DNS_R_CNAME) {
2220                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2221                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2222                         level = ISC_LOG_WARNING;
2223                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2224                         dns_zone_log(zone, level,
2225                                      "%s/SRV '%s' is a CNAME (illegal)",
2226                                      ownerbuf, namebuf);
2227                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2228         }
2229
2230         if (result == DNS_R_DNAME) {
2231                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2232                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2233                         level = ISC_LOG_WARNING;
2234                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2235                         dns_name_format(foundname, altbuf, sizeof altbuf);
2236                         dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2237                                      "DNAME '%s' (illegal)", ownerbuf, namebuf,
2238                                      altbuf);
2239                 }
2240                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2241         }
2242
2243         if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2244                 return ((zone->checksrv)(zone, name, owner));
2245
2246         return (ISC_TRUE);
2247 }
2248
2249 static isc_boolean_t
2250 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2251                 dns_name_t *owner)
2252 {
2253         isc_boolean_t answer = ISC_TRUE;
2254         isc_result_t result, tresult;
2255         char ownerbuf[DNS_NAME_FORMATSIZE];
2256         char namebuf[DNS_NAME_FORMATSIZE];
2257         char altbuf[DNS_NAME_FORMATSIZE];
2258         dns_fixedname_t fixed;
2259         dns_name_t *foundname;
2260         dns_rdataset_t a;
2261         dns_rdataset_t aaaa;
2262         int level;
2263
2264         /*
2265          * Outside of zone.
2266          */
2267         if (!dns_name_issubdomain(name, &zone->origin)) {
2268                 if (zone->checkns != NULL)
2269                         return ((zone->checkns)(zone, name, owner, NULL, NULL));
2270                 return (ISC_TRUE);
2271         }
2272
2273         if (zone->type == dns_zone_master)
2274                 level = ISC_LOG_ERROR;
2275         else
2276                 level = ISC_LOG_WARNING;
2277
2278         dns_fixedname_init(&fixed);
2279         foundname = dns_fixedname_name(&fixed);
2280         dns_rdataset_init(&a);
2281         dns_rdataset_init(&aaaa);
2282
2283         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2284                              DNS_DBFIND_GLUEOK, 0, NULL,
2285                              foundname, &a, NULL);
2286
2287         if (result == ISC_R_SUCCESS) {
2288                 dns_rdataset_disassociate(&a);
2289                 return (ISC_TRUE);
2290         } else if (result == DNS_R_DELEGATION)
2291                 dns_rdataset_disassociate(&a);
2292
2293         if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2294             result == DNS_R_GLUE) {
2295                 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2296                                      DNS_DBFIND_GLUEOK, 0, NULL,
2297                                      foundname, &aaaa, NULL);
2298                 if (tresult == ISC_R_SUCCESS) {
2299                         dns_rdataset_disassociate(&aaaa);
2300                         return (ISC_TRUE);
2301                 }
2302                 if (tresult == DNS_R_DELEGATION)
2303                         dns_rdataset_disassociate(&aaaa);
2304                 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2305                         /*
2306                          * Check glue against child zone.
2307                          */
2308                         if (zone->checkns != NULL)
2309                                 answer = (zone->checkns)(zone, name, owner,
2310                                                          &a, &aaaa);
2311                         if (dns_rdataset_isassociated(&a))
2312                                 dns_rdataset_disassociate(&a);
2313                         if (dns_rdataset_isassociated(&aaaa))
2314                                 dns_rdataset_disassociate(&aaaa);
2315                         return (answer);
2316                 }
2317         }
2318
2319         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2320         dns_name_format(name, namebuf, sizeof namebuf);
2321         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2322             result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2323                 const char *what;
2324                 isc_boolean_t required = ISC_FALSE;
2325                 if (dns_name_issubdomain(name, owner)) {
2326                         what = "REQUIRED GLUE ";
2327                         required = ISC_TRUE;
2328                  } else if (result == DNS_R_DELEGATION)
2329                         what = "SIBLING GLUE ";
2330                 else
2331                         what = "";
2332
2333                 if (result != DNS_R_DELEGATION || required ||
2334                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2335                         dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2336                                      "address records (A or AAAA)",
2337                                      ownerbuf, namebuf, what);
2338                         /*
2339                          * Log missing address record.
2340                          */
2341                         if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2342                                 (void)(zone->checkns)(zone, name, owner,
2343                                                       &a, &aaaa);
2344                         /* XXX950 make fatal for 9.5.0. */
2345                         /* answer = ISC_FALSE; */
2346                 }
2347         } else if (result == DNS_R_CNAME) {
2348                 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2349                              ownerbuf, namebuf);
2350                 /* XXX950 make fatal for 9.5.0. */
2351                 /* answer = ISC_FALSE; */
2352         } else if (result == DNS_R_DNAME) {
2353                 dns_name_format(foundname, altbuf, sizeof altbuf);
2354                 dns_zone_log(zone, level,
2355                              "%s/NS '%s' is below a DNAME '%s' (illegal)",
2356                              ownerbuf, namebuf, altbuf);
2357                 /* XXX950 make fatal for 9.5.0. */
2358                 /* answer = ISC_FALSE; */
2359         }
2360
2361         if (dns_rdataset_isassociated(&a))
2362                 dns_rdataset_disassociate(&a);
2363         if (dns_rdataset_isassociated(&aaaa))
2364                 dns_rdataset_disassociate(&aaaa);
2365         return (answer);
2366 }
2367
2368 static isc_boolean_t
2369 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2370                      dns_rdataset_t *rdataset)
2371 {
2372         dns_rdataset_t tmprdataset;
2373         isc_result_t result;
2374         isc_boolean_t answer = ISC_TRUE;
2375         isc_boolean_t format = ISC_TRUE;
2376         int level = ISC_LOG_WARNING;
2377         char ownerbuf[DNS_NAME_FORMATSIZE];
2378         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2379         unsigned int count1 = 0;
2380
2381         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2382                 level = ISC_LOG_ERROR;
2383
2384         dns_rdataset_init(&tmprdataset);
2385         for (result = dns_rdataset_first(rdataset);
2386              result == ISC_R_SUCCESS;
2387              result = dns_rdataset_next(rdataset)) {
2388                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2389                 unsigned int count2 = 0;
2390
2391                 count1++;
2392                 dns_rdataset_current(rdataset, &rdata1);
2393                 dns_rdataset_clone(rdataset, &tmprdataset);
2394                 for (result = dns_rdataset_first(&tmprdataset);
2395                      result == ISC_R_SUCCESS;
2396                      result = dns_rdataset_next(&tmprdataset)) {
2397                         dns_rdata_t rdata2 = DNS_RDATA_INIT;
2398                         count2++;
2399                         if (count1 >= count2)
2400                                 continue;
2401                         dns_rdataset_current(&tmprdataset, &rdata2);
2402                         if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2403                                 if (format) {
2404                                         dns_name_format(owner, ownerbuf,
2405                                                         sizeof ownerbuf);
2406                                         dns_rdatatype_format(rdata1.type,
2407                                                              typebuf,
2408                                                              sizeof(typebuf));
2409                                         format = ISC_FALSE;
2410                                 }
2411                                 dns_zone_log(zone, level, "%s/%s has "
2412                                              "semantically identical records",
2413                                              ownerbuf, typebuf);
2414                                 if (level == ISC_LOG_ERROR)
2415                                         answer = ISC_FALSE;
2416                                 break;
2417                         }
2418                 }
2419                 dns_rdataset_disassociate(&tmprdataset);
2420                 if (!format)
2421                         break;
2422         }
2423         return (answer);
2424 }
2425
2426 static isc_boolean_t
2427 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2428         dns_dbiterator_t *dbiterator = NULL;
2429         dns_dbnode_t *node = NULL;
2430         dns_fixedname_t fixed;
2431         dns_name_t *name;
2432         dns_rdataset_t rdataset;
2433         dns_rdatasetiter_t *rdsit = NULL;
2434         isc_boolean_t ok = ISC_TRUE;
2435         isc_result_t result;
2436
2437         dns_fixedname_init(&fixed);
2438         name = dns_fixedname_name(&fixed);
2439         dns_rdataset_init(&rdataset);
2440
2441         result = dns_db_createiterator(db, 0, &dbiterator);
2442         if (result != ISC_R_SUCCESS)
2443                 return (ISC_TRUE);
2444
2445         for (result = dns_dbiterator_first(dbiterator);
2446              result == ISC_R_SUCCESS;
2447              result = dns_dbiterator_next(dbiterator)) {
2448                 result = dns_dbiterator_current(dbiterator, &node, name);
2449                 if (result != ISC_R_SUCCESS)
2450                         continue;
2451
2452                 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2453                 if (result != ISC_R_SUCCESS)
2454                         continue;
2455
2456                 for (result = dns_rdatasetiter_first(rdsit);
2457                      result == ISC_R_SUCCESS;
2458                      result = dns_rdatasetiter_next(rdsit)) {
2459                         dns_rdatasetiter_current(rdsit, &rdataset);
2460                         if (!zone_rrset_check_dup(zone, name, &rdataset))
2461                                 ok = ISC_FALSE;
2462                         dns_rdataset_disassociate(&rdataset);
2463                 }
2464                 dns_rdatasetiter_destroy(&rdsit);
2465                 dns_db_detachnode(db, &node);
2466         }
2467
2468         if (node != NULL)
2469                 dns_db_detachnode(db, &node);
2470         dns_dbiterator_destroy(&dbiterator);
2471
2472         return (ok);
2473 }
2474
2475 static isc_boolean_t
2476 isspf(const dns_rdata_t *rdata) {
2477         char buf[1024];
2478         const unsigned char *data = rdata->data;
2479         unsigned int rdl = rdata->length, i = 0, tl, len;
2480
2481         while (rdl > 0U) {
2482                 len = tl = *data;
2483                 ++data;
2484                 --rdl;
2485                 INSIST(tl <= rdl);
2486                 if (len > sizeof(buf) - i - 1)
2487                         len = sizeof(buf) - i - 1;
2488                 memcpy(buf + i, data, len);
2489                 i += len;
2490                 data += tl;
2491                 rdl -= tl;
2492         }
2493
2494         if (i < 6U)
2495                 return(ISC_FALSE);
2496
2497         buf[i] = 0;
2498         if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
2499                 return (ISC_TRUE);
2500         return (ISC_FALSE);
2501 }
2502
2503 static isc_boolean_t
2504 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2505         dns_dbiterator_t *dbiterator = NULL;
2506         dns_dbnode_t *node = NULL;
2507         dns_rdataset_t rdataset;
2508         dns_fixedname_t fixed;
2509         dns_fixedname_t fixedbottom;
2510         dns_rdata_mx_t mx;
2511         dns_rdata_ns_t ns;
2512         dns_rdata_in_srv_t srv;
2513         dns_rdata_t rdata;
2514         dns_name_t *name;
2515         dns_name_t *bottom;
2516         isc_result_t result;
2517         isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
2518
2519         dns_fixedname_init(&fixed);
2520         name = dns_fixedname_name(&fixed);
2521         dns_fixedname_init(&fixedbottom);
2522         bottom = dns_fixedname_name(&fixedbottom);
2523         dns_rdataset_init(&rdataset);
2524         dns_rdata_init(&rdata);
2525
2526         result = dns_db_createiterator(db, 0, &dbiterator);
2527         if (result != ISC_R_SUCCESS)
2528                 return (ISC_TRUE);
2529
2530         result = dns_dbiterator_first(dbiterator);
2531         while (result == ISC_R_SUCCESS) {
2532                 result = dns_dbiterator_current(dbiterator, &node, name);
2533                 if (result != ISC_R_SUCCESS)
2534                         goto cleanup;
2535
2536                 /*
2537                  * Is this name visible in the zone?
2538                  */
2539                 if (!dns_name_issubdomain(name, &zone->origin) ||
2540                     (dns_name_countlabels(bottom) > 0 &&
2541                      dns_name_issubdomain(name, bottom)))
2542                         goto next;
2543
2544                 /*
2545                  * Don't check the NS records at the origin.
2546                  */
2547                 if (dns_name_equal(name, &zone->origin))
2548                         goto checkmx;
2549
2550                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2551                                              0, 0, &rdataset, NULL);
2552                 if (result != ISC_R_SUCCESS)
2553                         goto checkmx;
2554                 /*
2555                  * Remember bottom of zone.
2556                  */
2557                 dns_name_copy(name, bottom, NULL);
2558
2559                 result = dns_rdataset_first(&rdataset);
2560                 while (result == ISC_R_SUCCESS) {
2561                         dns_rdataset_current(&rdataset, &rdata);
2562                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
2563                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2564                         if (!zone_check_glue(zone, db, &ns.name, name))
2565                                 ok = ISC_FALSE;
2566                         dns_rdata_reset(&rdata);
2567                         result = dns_rdataset_next(&rdataset);
2568                 }
2569                 dns_rdataset_disassociate(&rdataset);
2570                 goto next;
2571
2572  checkmx:
2573                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2574                                              0, 0, &rdataset, NULL);
2575                 if (result != ISC_R_SUCCESS)
2576                         goto checksrv;
2577                 result = dns_rdataset_first(&rdataset);
2578                 while (result == ISC_R_SUCCESS) {
2579                         dns_rdataset_current(&rdataset, &rdata);
2580                         result = dns_rdata_tostruct(&rdata, &mx, NULL);
2581                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2582                         if (!zone_check_mx(zone, db, &mx.mx, name))
2583                                 ok = ISC_FALSE;
2584                         dns_rdata_reset(&rdata);
2585                         result = dns_rdataset_next(&rdataset);
2586                 }
2587                 dns_rdataset_disassociate(&rdataset);
2588
2589  checksrv:
2590                 if (zone->rdclass != dns_rdataclass_in)
2591                         goto next;
2592                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2593                                              0, 0, &rdataset, NULL);
2594                 if (result != ISC_R_SUCCESS)
2595                         goto checkspf;
2596                 result = dns_rdataset_first(&rdataset);
2597                 while (result == ISC_R_SUCCESS) {
2598                         dns_rdataset_current(&rdataset, &rdata);
2599                         result = dns_rdata_tostruct(&rdata, &srv, NULL);
2600                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2601                         if (!zone_check_srv(zone, db, &srv.target, name))
2602                                 ok = ISC_FALSE;
2603                         dns_rdata_reset(&rdata);
2604                         result = dns_rdataset_next(&rdataset);
2605                 }
2606                 dns_rdataset_disassociate(&rdataset);
2607
2608  checkspf:
2609                 /*
2610                  * Check if there is a type TXT spf record without a type SPF
2611                  * RRset being present.
2612                  */
2613                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
2614                         goto next;
2615                 if (zone->rdclass != dns_rdataclass_in)
2616                         goto next;
2617                 have_spf = have_txt = ISC_FALSE;
2618                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
2619                                              0, 0, &rdataset, NULL);
2620                 if (result == ISC_R_SUCCESS) {
2621                         dns_rdataset_disassociate(&rdataset);
2622                         have_spf = ISC_TRUE;
2623                 }
2624                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
2625                                              0, 0, &rdataset, NULL);
2626                 if (result != ISC_R_SUCCESS)
2627                         goto notxt;
2628                 result = dns_rdataset_first(&rdataset);
2629                 while (result == ISC_R_SUCCESS) {
2630                         dns_rdataset_current(&rdataset, &rdata);
2631                         have_txt = isspf(&rdata);
2632                         dns_rdata_reset(&rdata);
2633                         if (have_txt)
2634                                 break;
2635                         result = dns_rdataset_next(&rdataset);
2636                 }
2637                 dns_rdataset_disassociate(&rdataset);
2638
2639  notxt:
2640                 if (have_spf != have_txt) {
2641                         char namebuf[DNS_NAME_FORMATSIZE];
2642                         const char *found = have_txt ? "TXT" : "SPF";
2643                         const char *need = have_txt ? "SPF" : "TXT";
2644
2645                         dns_name_format(name, namebuf, sizeof(namebuf));
2646                         dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found SPF/%s "
2647                                      "record but no SPF/%s record found, add "
2648                                      "matching type %s record", namebuf, found,
2649                                      need, need);
2650                 }
2651
2652  next:
2653                 dns_db_detachnode(db, &node);
2654                 result = dns_dbiterator_next(dbiterator);
2655         }
2656
2657  cleanup:
2658         if (node != NULL)
2659                 dns_db_detachnode(db, &node);
2660         dns_dbiterator_destroy(&dbiterator);
2661
2662         return (ok);
2663 }
2664
2665 /*
2666  * OpenSSL verification of RSA keys with exponent 3 is known to be
2667  * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
2668  * if they are in use.
2669  */
2670 static void
2671 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2672         dns_dbnode_t *node = NULL;
2673         dns_dbversion_t *version = NULL;
2674         dns_rdata_dnskey_t dnskey;
2675         dns_rdata_t rdata = DNS_RDATA_INIT;
2676         dns_rdataset_t rdataset;
2677         isc_result_t result;
2678         isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2679         const char *algorithm;
2680
2681         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2682         if (result != ISC_R_SUCCESS)
2683                 goto cleanup;
2684
2685         dns_db_currentversion(db, &version);
2686         dns_rdataset_init(&rdataset);
2687         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2688                                      dns_rdatatype_none, 0, &rdataset, NULL);
2689         if (result != ISC_R_SUCCESS)
2690                 goto cleanup;
2691
2692         for (result = dns_rdataset_first(&rdataset);
2693              result == ISC_R_SUCCESS;
2694              result = dns_rdataset_next(&rdataset))
2695         {
2696                 dns_rdataset_current(&rdataset, &rdata);
2697                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2698                 INSIST(result == ISC_R_SUCCESS);
2699
2700                 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2701                      dnskey.algorithm == DST_ALG_RSAMD5) &&
2702                      dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2703                      dnskey.data[1] == 3)
2704                 {
2705                         if (dnskey.algorithm == DST_ALG_RSASHA1) {
2706                                 logit = !foundrsa;
2707                                 foundrsa = ISC_TRUE;
2708                                 algorithm = "RSASHA1";
2709                         } else {
2710                                 logit = !foundmd5;
2711                                 foundmd5 = ISC_TRUE;
2712                                 algorithm = "RSAMD5";
2713                         }
2714                         if (logit)
2715                                 dns_zone_log(zone, ISC_LOG_WARNING,
2716                                              "weak %s (%u) key found "
2717                                              "(exponent=3)", algorithm,
2718                                              dnskey.algorithm);
2719                         if (foundrsa && foundmd5)
2720                                 break;
2721                 }
2722                 dns_rdata_reset(&rdata);
2723         }
2724         dns_rdataset_disassociate(&rdataset);
2725
2726  cleanup:
2727         if (node != NULL)
2728                 dns_db_detachnode(db, &node);
2729         if (version != NULL)
2730                 dns_db_closeversion(db, &version, ISC_FALSE);
2731 }
2732
2733 static void
2734 resume_signingwithkey(dns_zone_t *zone) {
2735         dns_dbnode_t *node = NULL;
2736         dns_dbversion_t *version = NULL;
2737         dns_rdata_t rdata = DNS_RDATA_INIT;
2738         dns_rdataset_t rdataset;
2739         isc_result_t result;
2740
2741         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2742         if (result != ISC_R_SUCCESS)
2743                 goto cleanup;
2744
2745         dns_db_currentversion(zone->db, &version);
2746         dns_rdataset_init(&rdataset);
2747         result = dns_db_findrdataset(zone->db, node, version,
2748                                      zone->privatetype,
2749                                      dns_rdatatype_none, 0,
2750                                      &rdataset, NULL);
2751         if (result != ISC_R_SUCCESS) {
2752                 INSIST(!dns_rdataset_isassociated(&rdataset));
2753                 goto cleanup;
2754         }
2755
2756         for (result = dns_rdataset_first(&rdataset);
2757              result == ISC_R_SUCCESS;
2758              result = dns_rdataset_next(&rdataset))
2759         {
2760                 dns_rdataset_current(&rdataset, &rdata);
2761                 if (rdata.length != 5 ||
2762                     rdata.data[0] == 0 || rdata.data[4] != 0) {
2763                         dns_rdata_reset(&rdata);
2764                         continue;
2765                 }
2766
2767                 result = zone_signwithkey(zone, rdata.data[0],
2768                                           (rdata.data[1] << 8) | rdata.data[2],
2769                                           ISC_TF(rdata.data[3]));
2770                 if (result != ISC_R_SUCCESS) {
2771                         dns_zone_log(zone, ISC_LOG_ERROR,
2772                                      "zone_signwithkey failed: %s",
2773                                      dns_result_totext(result));
2774                 }
2775                 dns_rdata_reset(&rdata);
2776         }
2777         dns_rdataset_disassociate(&rdataset);
2778
2779  cleanup:
2780         if (node != NULL)
2781                 dns_db_detachnode(zone->db, &node);
2782         if (version != NULL)
2783                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2784 }
2785
2786 static isc_result_t
2787 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2788         dns_nsec3chain_t *nsec3chain, *current;
2789         dns_dbversion_t *version = NULL;
2790         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
2791         isc_result_t result;
2792         isc_time_t now;
2793         unsigned int options = 0;
2794         char saltbuf[255*2+1];
2795         char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
2796         int i;
2797
2798         dns_db_currentversion(zone->db, &version);
2799         result = dns_nsec_nseconly(zone->db, version, &nseconly);
2800         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
2801         dns_db_closeversion(zone->db, &version, ISC_FALSE);
2802         if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0)
2803                 return (ISC_R_SUCCESS);
2804
2805         nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2806         if (nsec3chain == NULL)
2807                 return (ISC_R_NOMEMORY);
2808
2809         nsec3chain->magic = 0;
2810         nsec3chain->done = ISC_FALSE;
2811         nsec3chain->db = NULL;
2812         nsec3chain->dbiterator = NULL;
2813         nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2814         nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2815         nsec3chain->nsec3param.hash = nsec3param->hash;
2816         nsec3chain->nsec3param.iterations = nsec3param->iterations;
2817         nsec3chain->nsec3param.flags = nsec3param->flags;
2818         nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2819         memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2820         nsec3chain->nsec3param.salt = nsec3chain->salt;
2821         nsec3chain->seen_nsec = ISC_FALSE;
2822         nsec3chain->delete_nsec = ISC_FALSE;
2823         nsec3chain->save_delete_nsec = ISC_FALSE;
2824
2825         if (nsec3param->flags == 0)
2826                 strlcpy(flags, "NONE", sizeof(flags));
2827         else {
2828                 flags[0] = '\0';
2829                 if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2830                         strlcat(flags, "REMOVE", sizeof(flags));
2831                 if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) {
2832                         if (flags[0] == '\0')
2833                                 strlcpy(flags, "INITIAL", sizeof(flags));
2834                         else
2835                                 strlcat(flags, "|INITIAL", sizeof(flags));
2836                 }
2837                 if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2838                         if (flags[0] == '\0')
2839                                 strlcpy(flags, "CREATE", sizeof(flags));
2840                         else
2841                                 strlcat(flags, "|CREATE", sizeof(flags));
2842                 }
2843                 if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2844                         if (flags[0] == '\0')
2845                                 strlcpy(flags, "NONSEC", sizeof(flags));
2846                         else
2847                                 strlcat(flags, "|NONSEC", sizeof(flags));
2848                 }
2849                 if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2850                         if (flags[0] == '\0')
2851                                 strlcpy(flags, "OPTOUT", sizeof(flags));
2852                         else
2853                                 strlcat(flags, "|OPTOUT", sizeof(flags));
2854                 }
2855         }
2856         if (nsec3param->salt_length == 0)
2857                 strlcpy(saltbuf, "-", sizeof(saltbuf));
2858         else
2859                 for (i = 0; i < nsec3param->salt_length; i++)
2860                         sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2861         dns_zone_log(zone, ISC_LOG_INFO,
2862                      "zone_addnsec3chain(%u,%s,%u,%s)",
2863                       nsec3param->hash, flags, nsec3param->iterations,
2864                       saltbuf);
2865
2866         for (current = ISC_LIST_HEAD(zone->nsec3chain);
2867              current != NULL;
2868              current = ISC_LIST_NEXT(current, link)) {
2869                 if (current->db == zone->db &&
2870                     current->nsec3param.hash == nsec3param->hash &&
2871                     current->nsec3param.iterations == nsec3param->iterations &&
2872                     current->nsec3param.salt_length == nsec3param->salt_length
2873                     && !memcmp(current->nsec3param.salt, nsec3param->salt,
2874                                nsec3param->salt_length))
2875                         current->done = ISC_TRUE;
2876         }
2877
2878         if (zone->db != NULL) {
2879                 dns_db_attach(zone->db, &nsec3chain->db);
2880                 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2881                         options = DNS_DB_NONSEC3;
2882                 result = dns_db_createiterator(nsec3chain->db, options,
2883                                                &nsec3chain->dbiterator);
2884                 if (result == ISC_R_SUCCESS)
2885                         dns_dbiterator_first(nsec3chain->dbiterator);
2886                 if (result == ISC_R_SUCCESS) {
2887                         dns_dbiterator_pause(nsec3chain->dbiterator);
2888                         ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2889                                                nsec3chain, link);
2890                         nsec3chain = NULL;
2891                         if (isc_time_isepoch(&zone->nsec3chaintime)) {
2892                                 TIME_NOW(&now);
2893                                 zone->nsec3chaintime = now;
2894                                 if (zone->task != NULL)
2895                                         zone_settimer(zone, &now);
2896                         }
2897                 }
2898         } else
2899                 result = ISC_R_NOTFOUND;
2900
2901         if (nsec3chain != NULL) {
2902                 if (nsec3chain->db != NULL)
2903                         dns_db_detach(&nsec3chain->db);
2904                 if (nsec3chain->dbiterator != NULL)
2905                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
2906                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2907         }
2908         return (result);
2909 }
2910
2911 static void
2912 resume_addnsec3chain(dns_zone_t *zone) {
2913         dns_dbnode_t *node = NULL;
2914         dns_dbversion_t *version = NULL;
2915         dns_rdataset_t rdataset;
2916         isc_result_t result;
2917         dns_rdata_nsec3param_t nsec3param;
2918         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
2919
2920         if (zone->privatetype == 0)
2921                 return;
2922
2923         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2924         if (result != ISC_R_SUCCESS)
2925                 goto cleanup;
2926
2927         dns_db_currentversion(zone->db, &version);
2928
2929         result = dns_nsec_nseconly(zone->db, version, &nseconly);
2930         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
2931
2932         dns_rdataset_init(&rdataset);
2933         result = dns_db_findrdataset(zone->db, node, version,
2934                                      zone->privatetype, dns_rdatatype_none,
2935                                      0, &rdataset, NULL);
2936         if (result != ISC_R_SUCCESS) {
2937                 INSIST(!dns_rdataset_isassociated(&rdataset));
2938                 goto cleanup;
2939         }
2940
2941         for (result = dns_rdataset_first(&rdataset);
2942              result == ISC_R_SUCCESS;
2943              result = dns_rdataset_next(&rdataset))
2944         {
2945                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
2946                 dns_rdata_t rdata = DNS_RDATA_INIT;
2947                 dns_rdata_t private = DNS_RDATA_INIT;
2948
2949                 dns_rdataset_current(&rdataset, &private);
2950                 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
2951                                                 sizeof(buf)))
2952                         continue;
2953                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2954                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2955                 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
2956                     ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
2957                 {
2958                         result = zone_addnsec3chain(zone, &nsec3param);
2959                         if (result != ISC_R_SUCCESS) {
2960                                 dns_zone_log(zone, ISC_LOG_ERROR,
2961                                              "zone_addnsec3chain failed: %s",
2962                                              dns_result_totext(result));
2963                         }
2964                 }
2965         }
2966         dns_rdataset_disassociate(&rdataset);
2967  cleanup:
2968         if (node != NULL)
2969                 dns_db_detachnode(zone->db, &node);
2970         if (version != NULL)
2971                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2972 }
2973
2974 static void
2975 set_resigntime(dns_zone_t *zone) {
2976         dns_rdataset_t rdataset;
2977         dns_fixedname_t fixed;
2978         unsigned int resign;
2979         isc_result_t result;
2980         isc_uint32_t nanosecs;
2981
2982         dns_rdataset_init(&rdataset);
2983         dns_fixedname_init(&fixed);
2984         result = dns_db_getsigningtime(zone->db, &rdataset,
2985                                        dns_fixedname_name(&fixed));
2986         if (result != ISC_R_SUCCESS) {
2987                 isc_time_settoepoch(&zone->resigntime);
2988                 return;
2989         }
2990         resign = rdataset.resign;
2991         dns_rdataset_disassociate(&rdataset);
2992         isc_random_get(&nanosecs);
2993         nanosecs %= 1000000000;
2994         isc_time_set(&zone->resigntime, resign, nanosecs);
2995 }
2996
2997 static isc_result_t
2998 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
2999         dns_dbnode_t *node = NULL;
3000         dns_rdataset_t rdataset;
3001         dns_dbversion_t *version = NULL;
3002         dns_rdata_nsec3param_t nsec3param;
3003         isc_boolean_t ok = ISC_FALSE;
3004         isc_result_t result;
3005         dns_rdata_t rdata = DNS_RDATA_INIT;
3006         isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
3007                                 dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE;
3008
3009         dns_rdataset_init(&rdataset);
3010         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3011         if (result != ISC_R_SUCCESS) {
3012                 dns_zone_log(zone, ISC_LOG_ERROR,
3013                              "nsec3param lookup failure: %s",
3014                              dns_result_totext(result));
3015                 return (result);
3016         }
3017         dns_db_currentversion(db, &version);
3018
3019         result = dns_db_findrdataset(db, node, version,
3020                                      dns_rdatatype_nsec3param,
3021                                      dns_rdatatype_none, 0, &rdataset, NULL);
3022         if (result == ISC_R_NOTFOUND) {
3023                 INSIST(!dns_rdataset_isassociated(&rdataset));
3024                 result = ISC_R_SUCCESS;
3025                 goto cleanup;
3026         }
3027         if (result != ISC_R_SUCCESS) {
3028                 INSIST(!dns_rdataset_isassociated(&rdataset));
3029                 dns_zone_log(zone, ISC_LOG_ERROR,
3030                              "nsec3param lookup failure: %s",
3031                              dns_result_totext(result));
3032                 goto cleanup;
3033         }
3034
3035         /*
3036          * For dynamic zones we must support every algorithm so we can
3037          * regenerate all the NSEC3 chains.
3038          * For non-dynamic zones we only need to find a supported algorithm.
3039          */
3040         for (result = dns_rdataset_first(&rdataset);
3041              result == ISC_R_SUCCESS;
3042              result = dns_rdataset_next(&rdataset))
3043         {
3044                 dns_rdataset_current(&rdataset, &rdata);
3045                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3046                 dns_rdata_reset(&rdata);
3047                 INSIST(result == ISC_R_SUCCESS);
3048                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3049                     nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3050                 {
3051                         dns_zone_log(zone, ISC_LOG_WARNING,
3052                              "nsec3 test \"unknown\" hash algorithm found: %u",
3053                                      nsec3param.hash);
3054                         ok = ISC_TRUE;
3055                 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3056                         if (dynamic) {
3057                                 dns_zone_log(zone, ISC_LOG_ERROR,
3058                                              "unsupported nsec3 hash algorithm"
3059                                              " in dynamic zone: %u",
3060                                              nsec3param.hash);
3061                                 result = DNS_R_BADZONE;
3062                                 /* Stop second error message. */
3063                                 ok = ISC_TRUE;
3064                                 break;
3065                         } else
3066                                 dns_zone_log(zone, ISC_LOG_WARNING,
3067                                      "unsupported nsec3 hash algorithm: %u",
3068                                              nsec3param.hash);
3069                 } else
3070                         ok = ISC_TRUE;
3071         }
3072         if (result == ISC_R_NOMORE)
3073                 result = ISC_R_SUCCESS;
3074
3075         if (!ok) {
3076                 result = DNS_R_BADZONE;
3077                 dns_zone_log(zone, ISC_LOG_ERROR,
3078                              "no supported nsec3 hash algorithm");
3079         }
3080
3081  cleanup:
3082         if (dns_rdataset_isassociated(&rdataset))
3083                 dns_rdataset_disassociate(&rdataset);
3084         dns_db_closeversion(db, &version, ISC_FALSE);
3085         dns_db_detachnode(db, &node);
3086         return (result);
3087 }
3088
3089 /*
3090  * Set the timer for refreshing the key zone to the soonest future time
3091  * of the set (current timer, keydata->refresh, keydata->addhd,
3092  * keydata->removehd).
3093  */
3094 static void
3095 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3096                     isc_stdtime_t now)
3097 {
3098         const char me[] = "set_refreshkeytimer";
3099         isc_stdtime_t then;
3100         isc_time_t timenow, timethen;
3101         char timebuf[80];
3102
3103         ENTER;
3104         then = key->refresh;
3105         if (key->addhd > now && key->addhd < then)
3106                 then = key->addhd;
3107         if (key->removehd > now && key->removehd < then)
3108                 then = key->removehd;
3109
3110         TIME_NOW(&timenow);
3111         if (then > now)
3112                 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
3113         else
3114                 timethen = timenow;
3115         if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
3116             isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
3117                 zone->refreshkeytime = timethen;
3118
3119         isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
3120         dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
3121         zone_settimer(zone, &timenow);
3122 }
3123
3124 /*
3125  * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3126  * If the key zone is changed, set '*changed' to ISC_TRUE.
3127  */
3128 static isc_result_t
3129 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3130                dns_diff_t *diff, dns_keytable_t *keytable,
3131                dns_keynode_t **keynodep, isc_boolean_t *changed)
3132 {
3133         const char me[] = "create_keydata";
3134         isc_result_t result = ISC_R_SUCCESS;
3135         isc_buffer_t keyb, dstb;
3136         unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3137         dns_rdata_keydata_t keydata;
3138         dns_rdata_dnskey_t dnskey;
3139         dns_rdata_t rdata = DNS_RDATA_INIT;
3140         dns_keynode_t *keynode;
3141         isc_stdtime_t now;
3142         isc_region_t r;
3143         dst_key_t *key;
3144
3145         REQUIRE(keynodep != NULL);
3146         keynode = *keynodep;
3147
3148         ENTER;
3149         isc_stdtime_get(&now);
3150
3151         /* Loop in case there's more than one key. */
3152         while (result == ISC_R_SUCCESS) {
3153                 dns_keynode_t *nextnode = NULL;
3154
3155                 key = dns_keynode_key(keynode);
3156                 if (key == NULL)
3157                         goto skip;
3158
3159                 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3160                 CHECK(dst_key_todns(key, &dstb));
3161
3162                 /* Convert DST key to DNSKEY. */
3163                 dns_rdata_reset(&rdata);
3164                 isc_buffer_usedregion(&dstb, &r);
3165                 dns_rdata_fromregion(&rdata, dst_key_class(key),
3166                                      dns_rdatatype_dnskey, &r);
3167
3168                 /* DSTKEY to KEYDATA. */
3169                 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3170                 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3171                                              NULL));
3172
3173                 /* KEYDATA to rdata. */
3174                 dns_rdata_reset(&rdata);
3175                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3176                 CHECK(dns_rdata_fromstruct(&rdata,
3177                                            zone->rdclass, dns_rdatatype_keydata,
3178                                            &keydata, &keyb));
3179
3180                 /* Add rdata to zone. */
3181                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3182                                     dst_key_name(key), 0, &rdata));
3183                 *changed = ISC_TRUE;
3184                 /* Refresh new keys from the zone apex as soon as possible. */
3185                 set_refreshkeytimer(zone, &keydata, now);
3186
3187  skip:
3188                 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3189                 if (result != ISC_R_NOTFOUND) {
3190                         dns_keytable_detachkeynode(keytable, &keynode);
3191                         keynode = nextnode;
3192                 }
3193         }
3194
3195         if (keynode != NULL)
3196                 dns_keytable_detachkeynode(keytable, &keynode);
3197         *keynodep = NULL;
3198
3199         return (ISC_R_SUCCESS);
3200
3201   failure:
3202         return (result);
3203 }
3204
3205 /*
3206  * Remove from the key zone all the KEYDATA records found in rdataset.
3207  */
3208 static isc_result_t
3209 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3210                dns_name_t *name, dns_rdataset_t *rdataset)
3211 {
3212         dns_rdata_t rdata = DNS_RDATA_INIT;
3213         isc_result_t result, uresult;
3214
3215         for (result = dns_rdataset_first(rdataset);
3216              result == ISC_R_SUCCESS;
3217              result = dns_rdataset_next(rdataset)) {
3218                 dns_rdata_reset(&rdata);
3219                 dns_rdataset_current(rdataset, &rdata);
3220                 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3221                                         name, 0, &rdata);
3222                 if (uresult != ISC_R_SUCCESS)
3223                         return (uresult);
3224         }
3225         if (result == ISC_R_NOMORE)
3226                 result = ISC_R_SUCCESS;
3227         return (result);
3228 }
3229
3230 /*
3231  * Compute the DNSSEC key ID for a DNSKEY record.
3232  */
3233 static isc_result_t
3234 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3235             dns_keytag_t *tag)
3236 {
3237         isc_result_t result;
3238         dns_rdata_t rdata = DNS_RDATA_INIT;
3239         unsigned char data[4096];
3240         isc_buffer_t buffer;
3241         dst_key_t *dstkey = NULL;
3242
3243         isc_buffer_init(&buffer, data, sizeof(data));
3244         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3245                              dns_rdatatype_dnskey, dnskey, &buffer);
3246
3247         result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3248         if (result == ISC_R_SUCCESS)
3249                 *tag = dst_key_id(dstkey);
3250         dst_key_free(&dstkey);
3251
3252         return (result);
3253 }
3254
3255 /*
3256  * Add key to the security roots.
3257  */
3258 static void
3259 trust_key(dns_zone_t *zone, dns_name_t *keyname,
3260           dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
3261         isc_result_t result;
3262         dns_rdata_t rdata = DNS_RDATA_INIT;
3263         unsigned char data[4096];
3264         isc_buffer_t buffer;
3265         dns_keytable_t *sr = NULL;
3266         dst_key_t *dstkey = NULL;
3267
3268         /* Convert dnskey to DST key. */
3269         isc_buffer_init(&buffer, data, sizeof(data));
3270         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3271                              dns_rdatatype_dnskey, dnskey, &buffer);
3272
3273         result = dns_view_getsecroots(zone->view, &sr);
3274         if (result != ISC_R_SUCCESS)
3275                 goto failure;
3276
3277         CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
3278         CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
3279         dns_keytable_detach(&sr);
3280
3281   failure:
3282         if (dstkey != NULL)
3283                 dst_key_free(&dstkey);
3284         if (sr != NULL)
3285                 dns_keytable_detach(&sr);
3286         return;
3287 }
3288
3289 /*
3290  * Add a null key to the security roots for so that all queries
3291  * to the zone will fail.
3292  */
3293 static void
3294 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
3295         isc_result_t result;
3296         dns_keytable_t *sr = NULL;
3297
3298         result = dns_view_getsecroots(zone->view, &sr);
3299         if (result == ISC_R_SUCCESS) {
3300                 dns_keytable_marksecure(sr, keyname);
3301                 dns_keytable_detach(&sr);
3302         }
3303 }
3304
3305 /*
3306  * Scan a set of KEYDATA records from the key zone.  The ones that are
3307  * valid (i.e., the add holddown timer has expired) become trusted keys.
3308  */
3309 static void
3310 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
3311         isc_result_t result;
3312         dns_rdata_t rdata = DNS_RDATA_INIT;
3313         dns_rdata_keydata_t keydata;
3314         dns_rdata_dnskey_t dnskey;
3315         isc_mem_t *mctx = zone->mctx;
3316         int trusted = 0, revoked = 0, pending = 0;
3317         isc_stdtime_t now;
3318         dns_keytable_t *sr = NULL;
3319
3320         isc_stdtime_get(&now);
3321
3322         result = dns_view_getsecroots(zone->view, &sr);
3323         if (result == ISC_R_SUCCESS) {
3324                 dns_keytable_delete(sr, name);
3325                 dns_keytable_detach(&sr);
3326         }
3327
3328         /* Now insert all the accepted trust anchors from this keydata set. */
3329         for (result = dns_rdataset_first(rdataset);
3330              result == ISC_R_SUCCESS;
3331              result = dns_rdataset_next(rdataset)) {
3332                 dns_rdata_reset(&rdata);
3333                 dns_rdataset_current(rdataset, &rdata);
3334
3335                 /* Convert rdata to keydata. */
3336                 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
3337                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3338
3339                 /* Set the key refresh timer. */
3340                 set_refreshkeytimer(zone, &keydata, now);
3341
3342                 /* If the removal timer is nonzero, this key was revoked. */
3343                 if (keydata.removehd != 0) {
3344                         revoked++;
3345                         continue;
3346                 }
3347
3348                 /*
3349                  * If the add timer is still pending, this key is not
3350                  * trusted yet.
3351                  */
3352                 if (now < keydata.addhd) {
3353                         pending++;
3354                         continue;
3355                 }
3356
3357                 /* Convert keydata to dnskey. */
3358                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
3359
3360                 /* Add to keytables. */
3361                 trusted++;
3362                 trust_key(zone, name, &dnskey, mctx);
3363         }
3364
3365         if (trusted == 0 && pending != 0) {
3366                 char namebuf[DNS_NAME_FORMATSIZE];
3367                 dns_name_format(name, namebuf, sizeof namebuf);
3368                 dns_zone_log(zone, ISC_LOG_ERROR,
3369                              "No valid trust anchors for '%s'!", namebuf);
3370                 dns_zone_log(zone, ISC_LOG_ERROR,
3371                              "%d key(s) revoked, %d still pending",
3372                              revoked, pending);
3373                 dns_zone_log(zone, ISC_LOG_ERROR,
3374                              "All queries to '%s' will fail", namebuf);
3375                 fail_secure(zone, name);
3376         }
3377 }
3378
3379 static isc_result_t
3380 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3381              dns_diff_t *diff)
3382 {
3383         dns_diff_t temp_diff;
3384         isc_result_t result;
3385
3386         /*
3387          * Create a singleton diff.
3388          */
3389         dns_diff_init(diff->mctx, &temp_diff);
3390         temp_diff.resign = diff->resign;
3391         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3392
3393         /*
3394          * Apply it to the database.
3395          */
3396         result = dns_diff_apply(&temp_diff, db, ver);
3397         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3398         if (result != ISC_R_SUCCESS) {
3399                 dns_difftuple_free(tuple);
3400                 return (result);
3401         }
3402
3403         /*
3404          * Merge it into the current pending journal entry.
3405          */
3406         dns_diff_appendminimal(diff, tuple);
3407
3408         /*
3409          * Do not clear temp_diff.
3410          */
3411         return (ISC_R_SUCCESS);
3412 }
3413
3414 static isc_result_t
3415 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3416               dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3417               dns_rdata_t *rdata)
3418 {
3419         dns_difftuple_t *tuple = NULL;
3420         isc_result_t result;
3421         result = dns_difftuple_create(diff->mctx, op,
3422                                       name, ttl, rdata, &tuple);
3423         if (result != ISC_R_SUCCESS)
3424                 return (result);
3425         return (do_one_tuple(&tuple, db, ver, diff));
3426 }
3427
3428 static isc_result_t
3429 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3430                   isc_mem_t *mctx, dns_updatemethod_t method) {
3431         dns_difftuple_t *deltuple = NULL;
3432         dns_difftuple_t *addtuple = NULL;
3433         isc_uint32_t serial;
3434         isc_result_t result;
3435
3436         CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3437         CHECK(dns_difftuple_copy(deltuple, &addtuple));
3438         addtuple->op = DNS_DIFFOP_ADD;
3439
3440         serial = dns_soa_getserial(&addtuple->rdata);
3441         serial = dns_update_soaserial(serial, method);
3442         dns_soa_setserial(serial, &addtuple->rdata);
3443         CHECK(do_one_tuple(&deltuple, db, ver, diff));
3444         CHECK(do_one_tuple(&addtuple, db, ver, diff));
3445         result = ISC_R_SUCCESS;
3446
3447         failure:
3448         if (addtuple != NULL)
3449                 dns_difftuple_free(&addtuple);
3450         if (deltuple != NULL)
3451                 dns_difftuple_free(&deltuple);
3452         return (result);
3453 }
3454
3455 /*
3456  * Write all transactions in 'diff' to the zone journal file.
3457  */
3458 static isc_result_t
3459 zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial,
3460              const char *caller)
3461 {
3462         const char me[] = "zone_journal";
3463         const char *journalfile;
3464         isc_result_t result = ISC_R_SUCCESS;
3465         dns_journal_t *journal = NULL;
3466         unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
3467
3468         ENTER;
3469         journalfile = dns_zone_getjournal(zone);
3470         if (journalfile != NULL) {
3471                 result = dns_journal_open(zone->mctx, journalfile, mode,
3472                                           &journal);
3473                 if (result != ISC_R_SUCCESS) {
3474                         dns_zone_log(zone, ISC_LOG_ERROR,
3475                                      "%s:dns_journal_open -> %s",
3476                                      caller, dns_result_totext(result));
3477                         return (result);
3478                 }
3479
3480                 if (sourceserial != NULL)
3481                         dns_journal_set_sourceserial(journal, *sourceserial);
3482
3483                 result = dns_journal_write_transaction(journal, diff);
3484                 if (result != ISC_R_SUCCESS) {
3485                         dns_zone_log(zone, ISC_LOG_ERROR,
3486                                      "%s:dns_journal_write_transaction -> %s",
3487                                      caller, dns_result_totext(result));
3488                 }
3489                 dns_journal_destroy(&journal);
3490         }
3491
3492         return (result);
3493 }
3494
3495 /*
3496  * Create an SOA record for a newly-created zone
3497  */
3498 static isc_result_t
3499 add_soa(dns_zone_t *zone, dns_db_t *db) {
3500         isc_result_t result;
3501         dns_rdata_t rdata = DNS_RDATA_INIT;
3502         unsigned char buf[DNS_SOA_BUFFERSIZE];
3503         dns_dbversion_t *ver = NULL;
3504         dns_diff_t diff;
3505
3506         dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3507
3508         dns_diff_init(zone->mctx, &diff);
3509         result = dns_db_newversion(db, &ver);
3510         if (result != ISC_R_SUCCESS) {
3511                 dns_zone_log(zone, ISC_LOG_ERROR,
3512                              "add_soa:dns_db_newversion -> %s",
3513                              dns_result_totext(result));
3514                 goto failure;
3515         }
3516
3517         /* Build SOA record */
3518         result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3519                                     0, 0, 0, 0, 0, buf, &rdata);
3520         if (result != ISC_R_SUCCESS) {
3521                 dns_zone_log(zone, ISC_LOG_ERROR,
3522                              "add_soa:dns_soa_buildrdata -> %s",
3523                              dns_result_totext(result));
3524                 goto failure;
3525         }
3526
3527         result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3528                                &zone->origin, 0, &rdata);
3529
3530 failure:
3531         dns_diff_clear(&diff);
3532         if (ver != NULL)
3533                 dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3534
3535         return (result);
3536 }
3537
3538 /*
3539  * Synchronize the set of initializing keys found in managed-keys {}
3540  * statements with the set of trust anchors found in the managed-keys.bind
3541  * zone.  If a domain is no longer named in managed-keys, delete all keys
3542  * from that domain from the key zone.  If a domain is mentioned in in
3543  * managed-keys but there are no references to it in the key zone, load
3544  * the key zone with the initializing key(s) for that domain.
3545  */
3546 static isc_result_t
3547 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3548         isc_result_t result = ISC_R_SUCCESS;
3549         isc_boolean_t changed = ISC_FALSE;
3550         isc_boolean_t commit = ISC_FALSE;
3551         dns_rbtnodechain_t chain;
3552         dns_fixedname_t fn;
3553         dns_name_t foundname, *origin;
3554         dns_keynode_t *keynode = NULL;
3555         dns_view_t *view = zone->view;
3556         dns_keytable_t *sr = NULL;
3557         dns_dbversion_t *ver = NULL;
3558         dns_diff_t diff;
3559         dns_rriterator_t rrit;
3560
3561         dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3562
3563         dns_name_init(&foundname, NULL);
3564         dns_fixedname_init(&fn);
3565         origin = dns_fixedname_name(&fn);
3566
3567         dns_diff_init(zone->mctx, &diff);
3568
3569         CHECK(dns_view_getsecroots(view, &sr));
3570
3571         result = dns_db_newversion(db, &ver);
3572         if (result != ISC_R_SUCCESS) {
3573                 dns_zone_log(zone, ISC_LOG_ERROR,
3574                              "sync_keyzone:dns_db_newversion -> %s",
3575                              dns_result_totext(result));
3576                 goto failure;
3577         }
3578
3579         /*
3580          * Walk the zone DB.  If we find any keys whose names are no longer
3581          * in managed-keys (or *are* in trusted-keys, meaning they are
3582          * permanent and not RFC5011-maintained), delete them from the
3583          * zone.  Otherwise call load_secroots(), which loads keys into
3584          * secroots as appropriate.
3585          */
3586         dns_rriterator_init(&rrit, db, ver, 0);
3587         for (result = dns_rriterator_first(&rrit);
3588              result == ISC_R_SUCCESS;
3589              result = dns_rriterator_nextrrset(&rrit)) {
3590                 dns_rdataset_t *rdataset = NULL;
3591                 dns_name_t *rrname = NULL;
3592                 isc_uint32_t ttl;
3593
3594                 dns_rriterator_current(&rrit, &rrname, &ttl,
3595                                        &rdataset, NULL);
3596                 if (!dns_rdataset_isassociated(rdataset)) {
3597                         dns_rriterator_destroy(&rrit);
3598                         goto failure;
3599                 }
3600
3601                 if (rdataset->type != dns_rdatatype_keydata)
3602                         continue;
3603
3604                 result = dns_keytable_find(sr, rrname, &keynode);
3605                 if ((result != ISC_R_SUCCESS &&
3606                      result != DNS_R_PARTIALMATCH) ||
3607                     dns_keynode_managed(keynode) == ISC_FALSE) {
3608                         CHECK(delete_keydata(db, ver, &diff,
3609                                              rrname, rdataset));
3610                         changed = ISC_TRUE;
3611                 } else {
3612                         load_secroots(zone, rrname, rdataset);
3613                 }
3614
3615                 if (keynode != NULL)
3616                         dns_keytable_detachkeynode(sr, &keynode);
3617         }
3618         dns_rriterator_destroy(&rrit);
3619
3620         /*
3621          * Now walk secroots to find any managed keys that aren't
3622          * in the zone.  If we find any, we add them to the zone.
3623          */
3624         RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3625         dns_rbtnodechain_init(&chain, zone->mctx);
3626         result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3627         if (result == ISC_R_NOTFOUND)
3628                 result = ISC_R_NOMORE;
3629         while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3630                 dns_rbtnode_t *rbtnode = NULL;
3631
3632                 dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3633                 if (rbtnode->data == NULL)
3634                         goto skip;
3635
3636                 dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3637                 if (dns_keynode_managed(keynode)) {
3638                         dns_fixedname_t fname;
3639                         dns_name_t *keyname;
3640                         dst_key_t *key;
3641
3642                         key = dns_keynode_key(keynode);
3643                         dns_fixedname_init(&fname);
3644
3645                         if (key == NULL)   /* fail_secure() was called. */
3646                                 goto skip;
3647
3648                         keyname = dst_key_name(key);
3649                         result = dns_db_find(db, keyname, ver,
3650                                              dns_rdatatype_keydata,
3651                                              DNS_DBFIND_NOWILD, 0, NULL,
3652                                              dns_fixedname_name(&fname),
3653                                              NULL, NULL);
3654                         if (result != ISC_R_SUCCESS)
3655                                 result = create_keydata(zone, db, ver, &diff,
3656                                                         sr, &keynode, &changed);
3657                         if (result != ISC_R_SUCCESS)
3658                                 break;
3659                 }
3660   skip:
3661                 result = dns_rbtnodechain_next(&chain, &foundname, origin);
3662                 if (keynode != NULL)
3663                         dns_keytable_detachkeynode(sr, &keynode);
3664         }
3665         RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3666
3667         if (result == ISC_R_NOMORE)
3668                 result = ISC_R_SUCCESS;
3669
3670         if (changed) {
3671                 /* Write changes to journal file. */
3672                 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
3673                                         zone->updatemethod));
3674                 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
3675
3676                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3677                 zone_needdump(zone, 30);
3678                 commit = ISC_TRUE;
3679         }
3680
3681  failure:
3682         if (result != ISC_R_SUCCESS &&
3683             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3684                 dns_zone_log(zone, ISC_LOG_ERROR,
3685                              "unable to synchronize managed keys: %s",
3686                              dns_result_totext(result));
3687                 isc_time_settoepoch(&zone->refreshkeytime);
3688         }
3689         if (keynode != NULL)
3690                 dns_keytable_detachkeynode(sr, &keynode);
3691         if (sr != NULL)
3692                 dns_keytable_detach(&sr);
3693         if (ver != NULL)
3694                 dns_db_closeversion(db, &ver, commit);
3695         dns_diff_clear(&diff);
3696
3697         return (result);
3698 }
3699
3700 isc_result_t
3701 dns_zone_synckeyzone(dns_zone_t *zone) {
3702         isc_result_t result;
3703         dns_db_t *db = NULL;
3704
3705         if (zone->type != dns_zone_key)
3706                 return (DNS_R_BADZONE);
3707
3708         CHECK(dns_zone_getdb(zone, &db));
3709
3710         LOCK_ZONE(zone);
3711         result = sync_keyzone(zone, db);
3712         UNLOCK_ZONE(zone);
3713
3714  failure:
3715         if (db != NULL)
3716                 dns_db_detach(&db);
3717         return (result);
3718 }
3719
3720 static void
3721 maybe_send_secure(dns_zone_t *zone) {
3722         isc_result_t result;
3723
3724         /*
3725          * We've finished loading, or else failed to load, an inline-signing
3726          * 'secure' zone.  We now need information about the status of the
3727          * 'raw' zone.  If we failed to load, then we need it to send a
3728          * copy of its database; if we succeeded, we need it to send its
3729          * serial number so that we can sync with it.  If it has not yet
3730          * loaded, we set a flag so that it will send the necessary
3731          * information when it has finished loading.
3732          */
3733         if (zone->raw->db != NULL) {
3734                 if (zone->db != NULL) {
3735                         isc_uint32_t serial;
3736                         unsigned int soacount;
3737
3738                         result = zone_get_from_db(zone->raw, zone->raw->db,
3739                                                   NULL, &soacount, &serial, NULL,
3740                                                   NULL, NULL, NULL, NULL);
3741                         if (result == ISC_R_SUCCESS && soacount > 0U)
3742                                 zone_send_secureserial(zone->raw, ISC_TRUE, serial);
3743                 } else
3744                         zone_send_securedb(zone->raw, ISC_TRUE, zone->raw->db);
3745
3746         } else
3747                 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
3748 }
3749
3750 static isc_boolean_t
3751 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
3752         isc_result_t result;
3753         isc_boolean_t answer = ISC_FALSE;
3754         dns_diff_t diff;
3755
3756         dns_diff_init(mctx, &diff);
3757         result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
3758         if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
3759                 answer = ISC_TRUE;
3760         dns_diff_clear(&diff);
3761         return (answer);
3762 }
3763
3764 /*
3765  * The zone is presumed to be locked.
3766  */
3767 static isc_result_t
3768 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3769               isc_result_t result)
3770 {
3771         unsigned int soacount = 0;
3772         unsigned int nscount = 0;
3773         unsigned int errors = 0;
3774         isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3775         isc_time_t now;
3776         isc_boolean_t needdump = ISC_FALSE;
3777         isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3778         isc_boolean_t nomaster = ISC_FALSE;
3779         unsigned int options;
3780
3781         TIME_NOW(&now);
3782
3783         /*
3784          * Initiate zone transfer?  We may need a error code that
3785          * indicates that the "permanent" form does not exist.
3786          * XXX better error feedback to log.
3787          */
3788         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3789                 if (zone->type == dns_zone_slave ||
3790                     zone->type == dns_zone_stub ||
3791                     (zone->type == dns_zone_redirect &&
3792                      zone->masters == NULL)) {
3793                         if (result == ISC_R_FILENOTFOUND)
3794                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3795                                              "no master file");
3796                         else if (result != DNS_R_NOMASTERFILE)
3797                                 dns_zone_log(zone, ISC_LOG_ERROR,
3798                                              "loading from master file %s "
3799                                              "failed: %s",
3800                                              zone->masterfile,
3801                                              dns_result_totext(result));
3802                 } else if (zone->type == dns_zone_master &&
3803                            inline_secure(zone) && result == ISC_R_FILENOTFOUND)
3804                 {
3805                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
3806                                      "no master file, requesting db");
3807                         maybe_send_secure(zone);
3808                 } else {
3809                         int level = ISC_LOG_ERROR;
3810                         if (zone->type == dns_zone_key &&
3811                             result == ISC_R_FILENOTFOUND)
3812                                 level = ISC_LOG_DEBUG(1);
3813                         dns_zone_log(zone, level,
3814                                      "loading from master file %s failed: %s",
3815                                      zone->masterfile,
3816                                      dns_result_totext(result));
3817                         nomaster = ISC_TRUE;
3818                 }
3819
3820                 if (zone->type != dns_zone_key)
3821                         goto cleanup;
3822         }
3823
3824         dns_zone_log(zone, ISC_LOG_DEBUG(2),
3825                      "number of nodes in database: %u",
3826                      dns_db_nodecount(db));
3827
3828         if (result == DNS_R_SEENINCLUDE)
3829                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3830         else
3831                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3832
3833         /*
3834          * If there's no master file for a key zone, then the zone is new:
3835          * create an SOA record.  (We do this now, instead of later, so that
3836          * if there happens to be a journal file, we can roll forward from
3837          * a sane starting point.)
3838          */
3839         if (nomaster && zone->type == dns_zone_key) {
3840                 result = add_soa(zone, db);
3841                 if (result != ISC_R_SUCCESS)
3842                         goto cleanup;
3843         }
3844
3845         /*
3846          * Apply update log, if any, on initial load.
3847          */
3848         if (zone->journal != NULL &&
3849             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
3850             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3851         {
3852                 if (zone->type == dns_zone_master &&
3853                     (zone->update_acl != NULL || zone->ssutable != NULL))
3854                         options = DNS_JOURNALOPT_RESIGN;
3855                 else
3856                         options = 0;
3857                 result = dns_journal_rollforward2(zone->mctx, db, options,
3858                                                   zone->sigresigninginterval,
3859                                                   zone->journal);
3860                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
3861                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
3862                     result != ISC_R_RANGE) {
3863                         dns_zone_log(zone, ISC_LOG_ERROR,
3864                                      "journal rollforward failed: %s",
3865                                      dns_result_totext(result));
3866                         goto cleanup;
3867
3868
3869                 }
3870                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
3871                         dns_zone_log(zone, ISC_LOG_ERROR,
3872                                      "journal rollforward failed: "
3873                                      "journal out of sync with zone");
3874                         goto cleanup;
3875                 }
3876                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3877                              "journal rollforward completed "
3878                              "successfully: %s",
3879                              dns_result_totext(result));
3880                 if (result == ISC_R_SUCCESS)
3881                         needdump = ISC_TRUE;
3882         }
3883
3884         /*
3885          * Obtain ns, soa and cname counts for top of zone.
3886          */
3887         INSIST(db != NULL);
3888         result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
3889                                   &refresh, &retry, &expire, &minimum,
3890                                   &errors);
3891         if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
3892                 dns_zone_log(zone, ISC_LOG_ERROR,
3893                              "could not find NS and/or SOA records");
3894         }
3895
3896         /*
3897          * Check to make sure the journal is up to date, and remove the
3898          * journal file if it isn't, as we wouldn't be able to apply
3899          * updates otherwise.
3900          */
3901         if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) &&
3902             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
3903                 isc_uint32_t jserial;
3904                 dns_journal_t *journal = NULL;
3905
3906                 result = dns_journal_open(zone->mctx, zone->journal,
3907                                           DNS_JOURNAL_READ, &journal);
3908                 if (result == ISC_R_SUCCESS) {
3909                         jserial = dns_journal_last_serial(journal);
3910                         dns_journal_destroy(&journal);
3911                 } else {
3912                         jserial = serial;
3913                         result = ISC_R_SUCCESS;
3914                 }
3915
3916                 if (jserial != serial) {
3917                         dns_zone_log(zone, ISC_LOG_INFO,
3918                                      "journal file is out of date: "
3919                                      "removing journal file");
3920                         if (remove(zone->journal) < 0 && errno != ENOENT) {
3921                                 char strbuf[ISC_STRERRORSIZE];
3922                                 isc__strerror(errno, strbuf, sizeof(strbuf));
3923                                 isc_log_write(dns_lctx,
3924                                               DNS_LOGCATEGORY_GENERAL,
3925                                               DNS_LOGMODULE_ZONE,
3926                                               ISC_LOG_WARNING,
3927                                               "unable to remove journal "
3928                                               "'%s': '%s'",
3929                                               zone->journal, strbuf);
3930                         }
3931                 }
3932         }
3933
3934         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
3935
3936         /*
3937          * Master / Slave / Stub zones require both NS and SOA records at
3938          * the top of the zone.
3939          */
3940
3941         switch (zone->type) {
3942         case dns_zone_dlz:
3943         case dns_zone_master:
3944         case dns_zone_slave:
3945         case dns_zone_stub:
3946         case dns_zone_redirect:
3947                 if (soacount != 1) {
3948                         dns_zone_log(zone, ISC_LOG_ERROR,
3949                                      "has %d SOA records", soacount);
3950                         result = DNS_R_BADZONE;
3951                 }
3952                 if (nscount == 0) {
3953                         dns_zone_log(zone, ISC_LOG_ERROR,
3954                                      "has no NS records");
3955                         result = DNS_R_BADZONE;
3956                 }
3957                 if (result != ISC_R_SUCCESS)
3958                         goto cleanup;
3959                 if (zone->type == dns_zone_master && errors != 0) {
3960                         result = DNS_R_BADZONE;
3961                         goto cleanup;
3962                 }
3963                 if (zone->type != dns_zone_stub &&
3964                     zone->type != dns_zone_redirect) {
3965                         result = check_nsec3param(zone, db);
3966                         if (result != ISC_R_SUCCESS)
3967                                 goto cleanup;
3968                 }
3969                 if (zone->type == dns_zone_master &&
3970                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
3971                     !integrity_checks(zone, db)) {
3972                         result = DNS_R_BADZONE;
3973                         goto cleanup;
3974                 }
3975                 if (zone->type == dns_zone_master &&
3976                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
3977                     !zone_check_dup(zone, db)) {
3978                         result = DNS_R_BADZONE;
3979                         goto cleanup;
3980                 }
3981
3982                 if (zone->db != NULL) {
3983                         unsigned int oldsoacount;
3984
3985                         /*
3986                          * This is checked in zone_replacedb() for slave zones
3987                          * as they don't reload from disk.
3988                          */
3989                         result = zone_get_from_db(zone, zone->db, NULL,
3990                                                   &oldsoacount, &oldserial,
3991                                                   NULL, NULL, NULL, NULL,
3992                                                   NULL);
3993                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3994                         RUNTIME_CHECK(soacount > 0U);
3995                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
3996                             !isc_serial_gt(serial, oldserial)) {
3997                                 isc_uint32_t serialmin, serialmax;
3998
3999                                 INSIST(zone->type == dns_zone_master);
4000
4001                                 if (serial == oldserial &&
4002                                     zone_unchanged(zone->db, db, zone->mctx)) {
4003                                         dns_zone_log(zone, ISC_LOG_INFO,
4004                                                      "ixfr-from-differences: "
4005                                                      "unchanged");
4006                                         return(ISC_R_SUCCESS);
4007                                 }
4008
4009                                 serialmin = (oldserial + 1) & 0xffffffffU;
4010                                 serialmax = (oldserial + 0x7fffffffU) &
4011                                              0xffffffffU;
4012                                 dns_zone_log(zone, ISC_LOG_ERROR,
4013                                              "ixfr-from-differences: "
4014                                              "new serial (%u) out of range "
4015                                              "[%u - %u]", serial, serialmin,
4016                                              serialmax);
4017                                 result = DNS_R_BADZONE;
4018                                 goto cleanup;
4019                         } else if (!isc_serial_ge(serial, oldserial))
4020                                 dns_zone_log(zone, ISC_LOG_ERROR,
4021                                              "zone serial (%u/%u) has gone "
4022                                              "backwards", serial, oldserial);
4023                         else if (serial == oldserial && !hasinclude &&
4024                                  strcmp(zone->db_argv[0], "_builtin") != 0)
4025                                 dns_zone_log(zone, ISC_LOG_ERROR,
4026                                              "zone serial (%u) unchanged. "
4027                                              "zone may fail to transfer "
4028                                              "to slaves.", serial);
4029                 }
4030
4031                 if (zone->type == dns_zone_master &&
4032                     (zone->update_acl != NULL || zone->ssutable != NULL) &&
4033                     zone->sigresigninginterval < (3 * refresh) &&
4034                     dns_db_issecure(db))
4035                 {
4036                         dns_zone_log(zone, ISC_LOG_WARNING,
4037                                      "sig-re-signing-interval less than "
4038                                      "3 * refresh.");
4039                 }
4040
4041                 zone->refresh = RANGE(refresh,
4042                                       zone->minrefresh, zone->maxrefresh);
4043                 zone->retry = RANGE(retry,
4044                                     zone->minretry, zone->maxretry);
4045                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
4046                                      DNS_MAX_EXPIRE);
4047                 zone->minimum = minimum;
4048                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4049
4050                 if (zone->type == dns_zone_slave ||
4051                     zone->type == dns_zone_stub ||
4052                     (zone->type == dns_zone_redirect &&
4053                      zone->masters != NULL)) {
4054                         isc_time_t t;
4055                         isc_uint32_t delay;
4056
4057                         result = isc_file_getmodtime(zone->journal, &t);
4058                         if (result != ISC_R_SUCCESS)
4059                                 result = isc_file_getmodtime(zone->masterfile,
4060                                                              &t);
4061                         if (result == ISC_R_SUCCESS)
4062                                 DNS_ZONE_TIME_ADD(&t, zone->expire,
4063                                                   &zone->expiretime);
4064                         else
4065                                 DNS_ZONE_TIME_ADD(&now, zone->retry,
4066                                                   &zone->expiretime);
4067
4068                         delay = isc_random_jitter(zone->retry,
4069                                                   (zone->retry * 3) / 4);
4070                         DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
4071                         if (isc_time_compare(&zone->refreshtime,
4072                                              &zone->expiretime) >= 0)
4073                                 zone->refreshtime = now;
4074                 }
4075
4076                 break;
4077
4078         case dns_zone_key:
4079                 result = sync_keyzone(zone, db);
4080                 if (result != ISC_R_SUCCESS)
4081                         goto cleanup;
4082                 break;
4083
4084         default:
4085                 UNEXPECTED_ERROR(__FILE__, __LINE__,
4086                                  "unexpected zone type %d", zone->type);
4087                 result = ISC_R_UNEXPECTED;
4088                 goto cleanup;
4089         }
4090
4091         /*
4092          * Check for weak DNSKEY's.
4093          */
4094         if (zone->type == dns_zone_master)
4095                 zone_check_dnskeys(zone, db);
4096
4097         /*
4098          * Schedule DNSSEC key refresh.
4099          */
4100         if (zone->type == dns_zone_master &&
4101             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
4102                 zone->refreshkeytime = now;
4103
4104 #if 0
4105         /* destroy notification example. */
4106         {
4107                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
4108                                                     DNS_EVENT_DBDESTROYED,
4109                                                     dns_zonemgr_dbdestroyed,
4110                                                     zone,
4111                                                     sizeof(isc_event_t));
4112                 dns_db_ondestroy(db, zone->task, &e);
4113         }
4114 #endif
4115
4116         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4117         if (zone->db != NULL) {
4118                 result = zone_replacedb(zone, db, ISC_FALSE);
4119                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4120                 if (result != ISC_R_SUCCESS)
4121                         goto cleanup;
4122         } else {
4123                 zone_attachdb(zone, db);
4124                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4125                 DNS_ZONE_SETFLAG(zone,
4126                                  DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
4127                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
4128                     inline_raw(zone))
4129                 {
4130                         if (zone->secure->db == NULL)
4131                                 zone_send_securedb(zone, ISC_FALSE, db);
4132                         else
4133                                 zone_send_secureserial(zone, ISC_FALSE, serial);
4134                 }
4135         }
4136
4137         /*
4138          * Finished loading inline-signing zone; need to get status
4139          * from the raw side now.
4140          */
4141         if (zone->type == dns_zone_master && inline_secure(zone))
4142                 maybe_send_secure(zone);
4143
4144
4145         result = ISC_R_SUCCESS;
4146
4147         if (needdump) {
4148                 if (zone->type == dns_zone_key)
4149                         zone_needdump(zone, 30);
4150                 else
4151                         zone_needdump(zone, DNS_DUMP_DELAY);
4152         }
4153
4154         if (zone->task != NULL) {
4155                 if (zone->type == dns_zone_master) {
4156                         set_resigntime(zone);
4157                         resume_signingwithkey(zone);
4158                         resume_addnsec3chain(zone);
4159                 }
4160
4161                 if (zone->type == dns_zone_master &&
4162                     !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4163                     dns_zone_isdynamic(zone, ISC_FALSE) &&
4164                     dns_db_issecure(db)) {
4165                         dns_name_t *name;
4166                         dns_fixedname_t fixed;
4167                         dns_rdataset_t next;
4168
4169                         dns_rdataset_init(&next);
4170                         dns_fixedname_init(&fixed);
4171                         name = dns_fixedname_name(&fixed);
4172
4173                         result = dns_db_getsigningtime(db, &next, name);
4174                         if (result == ISC_R_SUCCESS) {
4175                                 isc_stdtime_t timenow;
4176                                 char namebuf[DNS_NAME_FORMATSIZE];
4177                                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4178
4179                                 isc_stdtime_get(&timenow);
4180                                 dns_name_format(name, namebuf, sizeof(namebuf));
4181                                 dns_rdatatype_format(next.covers,
4182                                                      typebuf, sizeof(typebuf));
4183                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
4184                                              "next resign: %s/%s in %d seconds",
4185                                              namebuf, typebuf,
4186                                              next.resign - timenow);
4187                                 dns_rdataset_disassociate(&next);
4188                         } else
4189                                 dns_zone_log(zone, ISC_LOG_WARNING,
4190                                              "signed dynamic zone has no "
4191                                              "resign event scheduled");
4192                 }
4193
4194                 zone_settimer(zone, &now);
4195         }
4196
4197         if (! dns_db_ispersistent(db))
4198                 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
4199                              dns_db_issecure(db) ? " (DNSSEC signed)" : "");
4200
4201         zone->loadtime = loadtime;
4202         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
4203         return (result);
4204
4205  cleanup:
4206         if (zone->type == dns_zone_slave ||
4207             zone->type == dns_zone_stub ||
4208             zone->type == dns_zone_key ||
4209             (zone->type == dns_zone_redirect && zone->masters != NULL)) {
4210                 if (zone->journal != NULL)
4211                         zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
4212                 if (zone->masterfile != NULL)
4213                         zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
4214
4215                 /* Mark the zone for immediate refresh. */
4216                 zone->refreshtime = now;
4217                 if (zone->task != NULL)
4218                         zone_settimer(zone, &now);
4219                 result = ISC_R_SUCCESS;
4220         } else if (zone->type == dns_zone_master ||
4221                    zone->type == dns_zone_redirect) {
4222                 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND))
4223                         dns_zone_log(zone, ISC_LOG_ERROR,
4224                                      "not loaded due to errors.");
4225                 else if (zone->type == dns_zone_master)
4226                         result = ISC_R_SUCCESS;
4227         }
4228
4229         return (result);
4230 }
4231
4232 static isc_boolean_t
4233 exit_check(dns_zone_t *zone) {
4234
4235         REQUIRE(LOCKED_ZONE(zone));
4236
4237         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
4238             zone->irefs == 0)
4239         {
4240                 /*
4241                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
4242                  */
4243                 INSIST(isc_refcount_current(&zone->erefs) == 0);
4244                 return (ISC_TRUE);
4245         }
4246         return (ISC_FALSE);
4247 }
4248
4249 static isc_boolean_t
4250 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
4251               dns_name_t *name, isc_boolean_t logit)
4252 {
4253         isc_result_t result;
4254         char namebuf[DNS_NAME_FORMATSIZE];
4255         char altbuf[DNS_NAME_FORMATSIZE];
4256         dns_fixedname_t fixed;
4257         dns_name_t *foundname;
4258         int level;
4259
4260         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
4261                 return (ISC_TRUE);
4262
4263         if (zone->type == dns_zone_master)
4264                 level = ISC_LOG_ERROR;
4265         else
4266                 level = ISC_LOG_WARNING;
4267
4268         dns_fixedname_init(&fixed);
4269         foundname = dns_fixedname_name(&fixed);
4270
4271         result = dns_db_find(db, name, version, dns_rdatatype_a,
4272                              0, 0, NULL, foundname, NULL, NULL);
4273         if (result == ISC_R_SUCCESS)
4274                 return (ISC_TRUE);
4275
4276         if (result == DNS_R_NXRRSET) {
4277                 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
4278                                      0, 0, NULL, foundname, NULL, NULL);
4279                 if (result == ISC_R_SUCCESS)
4280                         return (ISC_TRUE);
4281         }
4282
4283         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
4284             result == DNS_R_EMPTYNAME) {
4285                 if (logit) {
4286                         dns_name_format(name, namebuf, sizeof namebuf);
4287                         dns_zone_log(zone, level, "NS '%s' has no address "
4288                                      "records (A or AAAA)", namebuf);
4289                 }
4290                 return (ISC_FALSE);
4291         }
4292
4293         if (result == DNS_R_CNAME) {
4294                 if (logit) {
4295                         dns_name_format(name, namebuf, sizeof namebuf);
4296                         dns_zone_log(zone, level, "NS '%s' is a CNAME "
4297                                      "(illegal)", namebuf);
4298                 }
4299                 return (ISC_FALSE);
4300         }
4301
4302         if (result == DNS_R_DNAME) {
4303                 if (logit) {
4304                         dns_name_format(name, namebuf, sizeof namebuf);
4305                         dns_name_format(foundname, altbuf, sizeof altbuf);
4306                         dns_zone_log(zone, level, "NS '%s' is below a DNAME "
4307                                      "'%s' (illegal)", namebuf, altbuf);
4308                 }
4309                 return (ISC_FALSE);
4310         }
4311
4312         return (ISC_TRUE);
4313 }
4314
4315 static isc_result_t
4316 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
4317                  dns_dbversion_t *version, unsigned int *nscount,
4318                  unsigned int *errors, isc_boolean_t logit)
4319 {
4320         isc_result_t result;
4321         unsigned int count = 0;
4322         unsigned int ecount = 0;
4323         dns_rdataset_t rdataset;
4324         dns_rdata_t rdata;
4325         dns_rdata_ns_t ns;
4326
4327         dns_rdataset_init(&rdataset);
4328         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
4329                                      dns_rdatatype_none, 0, &rdataset, NULL);
4330         if (result == ISC_R_NOTFOUND) {
4331                 INSIST(!dns_rdataset_isassociated(&rdataset));
4332                 goto success;
4333         }
4334         if (result != ISC_R_SUCCESS) {
4335                 INSIST(!dns_rdataset_isassociated(&rdataset));
4336                 goto invalidate_rdataset;
4337         }
4338
4339         result = dns_rdataset_first(&rdataset);
4340         while (result == ISC_R_SUCCESS) {
4341                 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
4342                     (zone->type == dns_zone_master ||
4343                      zone->type == dns_zone_slave)) {
4344                         dns_rdata_init(&rdata);
4345                         dns_rdataset_current(&rdataset, &rdata);
4346                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
4347                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4348                         if (dns_name_issubdomain(&ns.name, &zone->origin) &&
4349                             !zone_check_ns(zone, db, version, &ns.name, logit))
4350                                 ecount++;
4351                 }
4352                 count++;
4353                 result = dns_rdataset_next(&rdataset);
4354         }
4355         dns_rdataset_disassociate(&rdataset);
4356
4357  success:
4358         if (nscount != NULL)
4359                 *nscount = count;
4360         if (errors != NULL)
4361                 *errors = ecount;
4362
4363         result = ISC_R_SUCCESS;
4364
4365  invalidate_rdataset:
4366         dns_rdataset_invalidate(&rdataset);
4367
4368         return (result);
4369 }
4370
4371 static isc_result_t
4372 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
4373                  unsigned int *soacount,
4374                  isc_uint32_t *serial, isc_uint32_t *refresh,
4375                  isc_uint32_t *retry, isc_uint32_t *expire,
4376                  isc_uint32_t *minimum)
4377 {
4378         isc_result_t result;
4379         unsigned int count;
4380         dns_rdataset_t rdataset;
4381         dns_rdata_t rdata = DNS_RDATA_INIT;
4382         dns_rdata_soa_t soa;
4383
4384         dns_rdataset_init(&rdataset);
4385         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
4386                                      dns_rdatatype_none, 0, &rdataset, NULL);
4387         if (result == ISC_R_NOTFOUND) {
4388                 INSIST(!dns_rdataset_isassociated(&rdataset));
4389                 if (soacount != NULL)
4390                         *soacount = 0;
4391                 if (serial != NULL)
4392                         *serial = 0;
4393                 if (refresh != NULL)
4394                         *refresh = 0;
4395                 if (retry != NULL)
4396                         *retry = 0;
4397                 if (expire != NULL)
4398                         *expire = 0;
4399                 if (minimum != NULL)
4400                         *minimum = 0;
4401                 result = ISC_R_SUCCESS;
4402                 goto invalidate_rdataset;
4403         }
4404         if (result != ISC_R_SUCCESS) {
4405                 INSIST(!dns_rdataset_isassociated(&rdataset));
4406                 goto invalidate_rdataset;
4407         }
4408
4409         count = 0;
4410         result = dns_rdataset_first(&rdataset);
4411         while (result == ISC_R_SUCCESS) {
4412                 dns_rdata_init(&rdata);
4413                 dns_rdataset_current(&rdataset, &rdata);
4414                 count++;
4415                 if (count == 1) {
4416                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
4417                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4418                 }
4419
4420                 result = dns_rdataset_next(&rdataset);
4421                 dns_rdata_reset(&rdata);
4422         }
4423         dns_rdataset_disassociate(&rdataset);
4424
4425         if (soacount != NULL)
4426                 *soacount = count;
4427
4428         if (count > 0) {
4429                 if (serial != NULL)
4430                         *serial = soa.serial;
4431                 if (refresh != NULL)
4432                         *refresh = soa.refresh;
4433                 if (retry != NULL)
4434                         *retry = soa.retry;
4435                 if (expire != NULL)
4436                         *expire = soa.expire;
4437                 if (minimum != NULL)
4438                         *minimum = soa.minimum;
4439         } else {
4440                 if (soacount != NULL)
4441                         *soacount = 0;
4442                 if (serial != NULL)
4443                         *serial = 0;
4444                 if (refresh != NULL)
4445                         *refresh = 0;
4446                 if (retry != NULL)
4447                         *retry = 0;
4448                 if (expire != NULL)
4449                         *expire = 0;
4450                 if (minimum != NULL)
4451                         *minimum = 0;
4452         }
4453
4454         result = ISC_R_SUCCESS;
4455
4456  invalidate_rdataset:
4457         dns_rdataset_invalidate(&rdataset);
4458
4459         return (result);
4460 }
4461
4462 /*
4463  * zone must be locked.
4464  */
4465 static isc_result_t
4466 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
4467                  unsigned int *soacount, isc_uint32_t *serial,
4468                  isc_uint32_t *refresh, isc_uint32_t *retry,
4469                  isc_uint32_t *expire, isc_uint32_t *minimum,
4470                  unsigned int *errors)
4471 {
4472         isc_result_t result;
4473         isc_result_t answer = ISC_R_SUCCESS;
4474         dns_dbversion_t *version = NULL;
4475         dns_dbnode_t *node;
4476
4477         REQUIRE(db != NULL);
4478         REQUIRE(zone != NULL);
4479
4480         dns_db_currentversion(db, &version);
4481
4482         node = NULL;
4483         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
4484         if (result != ISC_R_SUCCESS) {
4485                 answer = result;
4486                 goto closeversion;
4487         }
4488
4489         if (nscount != NULL || errors != NULL) {
4490                 result = zone_count_ns_rr(zone, db, node, version,
4491                                           nscount, errors, ISC_TRUE);
4492                 if (result != ISC_R_SUCCESS)
4493                         answer = result;
4494         }
4495
4496         if (soacount != NULL || serial != NULL || refresh != NULL
4497             || retry != NULL || expire != NULL || minimum != NULL) {
4498                 result = zone_load_soa_rr(db, node, version, soacount,
4499                                           serial, refresh, retry, expire,
4500                                           minimum);
4501                 if (result != ISC_R_SUCCESS)
4502                         answer = result;
4503         }
4504
4505         dns_db_detachnode(db, &node);
4506  closeversion:
4507         dns_db_closeversion(db, &version, ISC_FALSE);
4508
4509         return (answer);
4510 }
4511
4512 void
4513 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
4514         REQUIRE(DNS_ZONE_VALID(source));
4515         REQUIRE(target != NULL && *target == NULL);
4516         isc_refcount_increment(&source->erefs, NULL);
4517         *target = source;
4518 }
4519
4520 void
4521 dns_zone_detach(dns_zone_t **zonep) {
4522         dns_zone_t *zone;
4523         dns_zone_t *raw = NULL;
4524         dns_zone_t *secure = NULL;
4525         unsigned int refs;
4526         isc_boolean_t free_now = ISC_FALSE;
4527
4528         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4529
4530         zone = *zonep;
4531
4532         isc_refcount_decrement(&zone->erefs, &refs);
4533
4534         if (refs == 0) {
4535                 LOCK_ZONE(zone);
4536                 /*
4537                  * We just detached the last external reference.
4538                  */
4539                 if (zone->task != NULL) {
4540                         /*
4541                          * This zone is being managed.  Post
4542                          * its control event and let it clean
4543                          * up synchronously in the context of
4544                          * its task.
4545                          */
4546                         isc_event_t *ev = &zone->ctlevent;
4547                         isc_task_send(zone->task, &ev);
4548                 } else {
4549                         /*
4550                          * This zone is not being managed; it has
4551                          * no task and can have no outstanding
4552                          * events.  Free it immediately.
4553                          */
4554                         /*
4555                          * Unmanaged zones should not have non-null views;
4556                          * we have no way of detaching from the view here
4557                          * without causing deadlock because this code is called
4558                          * with the view already locked.
4559                          */
4560                         INSIST(zone->view == NULL);
4561                         free_now = ISC_TRUE;
4562                         raw = zone->raw;
4563                         zone->raw = NULL;
4564                         secure = zone->secure;
4565                         zone->secure = NULL;
4566                 }
4567                 UNLOCK_ZONE(zone);
4568         }
4569         *zonep = NULL;
4570         if (free_now) {
4571                 if (raw != NULL)
4572                         dns_zone_detach(&raw);
4573                 if (secure != NULL)
4574                         dns_zone_idetach(&secure);
4575                 zone_free(zone);
4576         }
4577 }
4578
4579 void
4580 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4581         REQUIRE(DNS_ZONE_VALID(source));
4582         REQUIRE(target != NULL && *target == NULL);
4583         LOCK_ZONE(source);
4584         zone_iattach(source, target);
4585         UNLOCK_ZONE(source);
4586 }
4587
4588 static void
4589 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4590
4591         /*
4592          * 'source' locked by caller.
4593          */
4594         REQUIRE(LOCKED_ZONE(source));
4595         REQUIRE(DNS_ZONE_VALID(source));
4596         REQUIRE(target != NULL && *target == NULL);
4597         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
4598         source->irefs++;
4599         INSIST(source->irefs != 0);
4600         *target = source;
4601 }
4602
4603 static void
4604 zone_idetach(dns_zone_t **zonep) {
4605         dns_zone_t *zone;
4606
4607         /*
4608          * 'zone' locked by caller.
4609          */
4610         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4611         zone = *zonep;
4612         REQUIRE(LOCKED_ZONE(*zonep));
4613         *zonep = NULL;
4614
4615         INSIST(zone->irefs > 0);
4616         zone->irefs--;
4617         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4618 }
4619
4620 void
4621 dns_zone_idetach(dns_zone_t **zonep) {
4622         dns_zone_t *zone;
4623         isc_boolean_t free_needed;
4624
4625         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4626         zone = *zonep;
4627         *zonep = NULL;
4628
4629         LOCK_ZONE(zone);
4630         INSIST(zone->irefs > 0);
4631         zone->irefs--;
4632         free_needed = exit_check(zone);
4633         UNLOCK_ZONE(zone);
4634         if (free_needed)
4635                 zone_free(zone);
4636 }
4637
4638 isc_mem_t *
4639 dns_zone_getmctx(dns_zone_t *zone) {
4640         REQUIRE(DNS_ZONE_VALID(zone));
4641
4642         return (zone->mctx);
4643 }
4644
4645 dns_zonemgr_t *
4646 dns_zone_getmgr(dns_zone_t *zone) {
4647         REQUIRE(DNS_ZONE_VALID(zone));
4648
4649         return (zone->zmgr);
4650 }
4651
4652 void
4653 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4654         REQUIRE(DNS_ZONE_VALID(zone));
4655
4656         LOCK_ZONE(zone);
4657         if (value)
4658                 DNS_ZONE_SETFLAG(zone, flags);
4659         else
4660                 DNS_ZONE_CLRFLAG(zone, flags);
4661         UNLOCK_ZONE(zone);
4662 }
4663
4664 void
4665 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4666 {
4667         REQUIRE(DNS_ZONE_VALID(zone));
4668
4669         LOCK_ZONE(zone);
4670         if (value)
4671                 zone->options |= option;
4672         else
4673                 zone->options &= ~option;
4674         UNLOCK_ZONE(zone);
4675 }
4676
4677 unsigned int
4678 dns_zone_getoptions(dns_zone_t *zone) {
4679
4680         REQUIRE(DNS_ZONE_VALID(zone));
4681
4682         return (zone->options);
4683 }
4684
4685 void
4686 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4687 {
4688         REQUIRE(DNS_ZONE_VALID(zone));
4689
4690         LOCK_ZONE(zone);
4691         if (value)
4692                 zone->keyopts |= keyopt;
4693         else
4694                 zone->keyopts &= ~keyopt;
4695         UNLOCK_ZONE(zone);
4696 }
4697
4698 unsigned int
4699 dns_zone_getkeyopts(dns_zone_t *zone) {
4700
4701         REQUIRE(DNS_ZONE_VALID(zone));
4702
4703         return (zone->keyopts);
4704 }
4705
4706 isc_result_t
4707 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4708         REQUIRE(DNS_ZONE_VALID(zone));
4709
4710         LOCK_ZONE(zone);
4711         zone->xfrsource4 = *xfrsource;
4712         UNLOCK_ZONE(zone);
4713
4714         return (ISC_R_SUCCESS);
4715 }
4716
4717 isc_sockaddr_t *
4718 dns_zone_getxfrsource4(dns_zone_t *zone) {
4719         REQUIRE(DNS_ZONE_VALID(zone));
4720         return (&zone->xfrsource4);
4721 }
4722
4723 isc_result_t
4724 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4725         REQUIRE(DNS_ZONE_VALID(zone));
4726
4727         LOCK_ZONE(zone);
4728         zone->xfrsource6 = *xfrsource;
4729         UNLOCK_ZONE(zone);
4730
4731         return (ISC_R_SUCCESS);
4732 }
4733
4734 isc_sockaddr_t *
4735 dns_zone_getxfrsource6(dns_zone_t *zone) {
4736         REQUIRE(DNS_ZONE_VALID(zone));
4737         return (&zone->xfrsource6);
4738 }
4739
4740 isc_result_t
4741 dns_zone_setaltxfrsource4(dns_zone_t *zone,
4742                           const isc_sockaddr_t *altxfrsource)
4743 {
4744         REQUIRE(DNS_ZONE_VALID(zone));
4745
4746         LOCK_ZONE(zone);
4747         zone->altxfrsource4 = *altxfrsource;
4748         UNLOCK_ZONE(zone);
4749
4750         return (ISC_R_SUCCESS);
4751 }
4752
4753 isc_sockaddr_t *
4754 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4755         REQUIRE(DNS_ZONE_VALID(zone));
4756         return (&zone->altxfrsource4);
4757 }
4758
4759 isc_result_t
4760 dns_zone_setaltxfrsource6(dns_zone_t *zone,
4761                           const isc_sockaddr_t *altxfrsource)
4762 {
4763         REQUIRE(DNS_ZONE_VALID(zone));
4764
4765         LOCK_ZONE(zone);
4766         zone->altxfrsource6 = *altxfrsource;
4767         UNLOCK_ZONE(zone);
4768
4769         return (ISC_R_SUCCESS);
4770 }
4771
4772 isc_sockaddr_t *
4773 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4774         REQUIRE(DNS_ZONE_VALID(zone));
4775         return (&zone->altxfrsource6);
4776 }
4777
4778 isc_result_t
4779 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4780         REQUIRE(DNS_ZONE_VALID(zone));
4781
4782         LOCK_ZONE(zone);
4783         zone->notifysrc4 = *notifysrc;
4784         UNLOCK_ZONE(zone);
4785
4786         return (ISC_R_SUCCESS);
4787 }
4788
4789 isc_sockaddr_t *
4790 dns_zone_getnotifysrc4(dns_zone_t *zone) {
4791         REQUIRE(DNS_ZONE_VALID(zone));
4792         return (&zone->notifysrc4);
4793 }
4794
4795 isc_result_t
4796 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4797         REQUIRE(DNS_ZONE_VALID(zone));
4798
4799         LOCK_ZONE(zone);
4800         zone->notifysrc6 = *notifysrc;
4801         UNLOCK_ZONE(zone);
4802
4803         return (ISC_R_SUCCESS);
4804 }
4805
4806 isc_sockaddr_t *
4807 dns_zone_getnotifysrc6(dns_zone_t *zone) {
4808         REQUIRE(DNS_ZONE_VALID(zone));
4809         return (&zone->notifysrc6);
4810 }
4811
4812 static isc_boolean_t
4813 same_addrs(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4814              isc_uint32_t count)
4815 {
4816         unsigned int i;
4817
4818         for (i = 0; i < count; i++)
4819                 if (!isc_sockaddr_equal(&old[i], &new[i]))
4820                         return (ISC_FALSE);
4821         return (ISC_TRUE);
4822 }
4823
4824 static isc_boolean_t
4825 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
4826         unsigned int i;
4827
4828         if (old == NULL && new == NULL)
4829                 return (ISC_TRUE);
4830         if (old == NULL || new == NULL)
4831                 return (ISC_FALSE);
4832
4833         for (i = 0; i < count; i++) {
4834                 if (old[i] == NULL && new[i] == NULL)
4835                         continue;
4836                 if (old[i] == NULL || new[i] == NULL ||
4837                      !dns_name_equal(old[i], new[i]))
4838                         return (ISC_FALSE);
4839         }
4840         return (ISC_TRUE);
4841 }
4842
4843 static void
4844 clear_addresskeylist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
4845                      unsigned int *countp, isc_mem_t *mctx)
4846 {
4847         unsigned int count;
4848         isc_sockaddr_t *addrs;
4849         dns_name_t **keynames;
4850
4851         REQUIRE(countp != NULL && addrsp != NULL && keynamesp != NULL);
4852
4853         count = *countp;
4854         *countp = 0;
4855         addrs = *addrsp;
4856         *addrsp = NULL;
4857         keynames = *keynamesp;
4858         *keynamesp = NULL;
4859
4860         if (addrs != NULL)
4861                 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
4862
4863         if (keynames != NULL) {
4864                 unsigned int i;
4865                 for (i = 0; i < count; i++) {
4866                         if (keynames[i] != NULL) {
4867                                 dns_name_free(keynames[i], mctx);
4868                                 isc_mem_put(mctx, keynames[i],
4869                                             sizeof(dns_name_t));
4870                                 keynames[i] = NULL;
4871                         }
4872                 }
4873                 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
4874         }
4875 }
4876
4877 static isc_result_t
4878 set_addrkeylist(unsigned int count,
4879                 const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
4880                 dns_name_t **names, dns_name_t ***newnamesp,
4881                 isc_mem_t *mctx)
4882 {
4883         isc_result_t result;
4884         isc_sockaddr_t *newaddrs = NULL;
4885         dns_name_t **newnames = NULL;
4886         unsigned int i;
4887
4888         REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
4889         REQUIRE(newnamesp != NULL && *newnamesp == NULL);
4890
4891         newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
4892         if (newaddrs == NULL)
4893                 return (ISC_R_NOMEMORY);
4894         memcpy(newaddrs, addrs, count * sizeof(*newaddrs));
4895
4896         newnames = NULL;
4897         if (names != NULL) {
4898                 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
4899                 if (newnames == NULL) {
4900                         isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
4901                         return (ISC_R_NOMEMORY);
4902                 }
4903                 for (i = 0; i < count; i++)
4904                         newnames[i] = NULL;
4905                 for (i = 0; i < count; i++) {
4906                         if (names[i] != NULL) {
4907                                 newnames[i] = isc_mem_get(mctx,
4908                                                          sizeof(dns_name_t));
4909                                 if (newnames[i] == NULL)
4910                                         goto allocfail;
4911                                 dns_name_init(newnames[i], NULL);
4912                                 result = dns_name_dup(names[i], mctx,
4913                                                       newnames[i]);
4914                                 if (result != ISC_R_SUCCESS) {
4915                                 allocfail:
4916                                         for (i = 0; i < count; i++)
4917                                                 if (newnames[i] != NULL)
4918                                                         dns_name_free(
4919                                                                newnames[i],
4920                                                                mctx);
4921                                         isc_mem_put(mctx, newaddrs,
4922                                                     count * sizeof(*newaddrs));
4923                                         isc_mem_put(mctx, newnames,
4924                                                     count * sizeof(*newnames));
4925                                         return (ISC_R_NOMEMORY);
4926                                 }
4927                         }
4928                 }
4929         }
4930
4931         *newaddrsp = newaddrs;
4932         *newnamesp = newnames;
4933         return (ISC_R_SUCCESS);
4934 }
4935
4936 isc_result_t
4937 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
4938                        isc_uint32_t count)
4939 {
4940         return (dns_zone_setalsonotifywithkeys(zone, notify, NULL, count));
4941 }
4942
4943 isc_result_t
4944 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
4945                                dns_name_t **keynames, isc_uint32_t count)
4946 {
4947         isc_result_t result;
4948         isc_sockaddr_t *newaddrs = NULL;
4949         dns_name_t **newnames = NULL;
4950
4951         REQUIRE(DNS_ZONE_VALID(zone));
4952         REQUIRE(count == 0 || notify != NULL);
4953         if (keynames != NULL)
4954                 REQUIRE(count != 0);
4955
4956         LOCK_ZONE(zone);
4957
4958         if (count == zone->notifycnt &&
4959             same_addrs(zone->notify, notify, count) &&
4960             same_keynames(zone->notifykeynames, keynames, count))
4961                 goto unlock;
4962
4963         clear_addresskeylist(&zone->notify, &zone->notifykeynames,
4964                              &zone->notifycnt, zone->mctx);
4965
4966         if (count == 0)
4967                 goto unlock;
4968
4969         /*
4970          * Set up the notify and notifykey lists
4971          */
4972         result = set_addrkeylist(count, notify, &newaddrs,
4973                                  keynames, &newnames, zone->mctx);
4974         if (result != ISC_R_SUCCESS)
4975                 goto unlock;
4976
4977         /*
4978          * Everything is ok so attach to the zone.
4979          */
4980         zone->notify = newaddrs;
4981         zone->notifykeynames = newnames;
4982         zone->notifycnt = count;
4983  unlock:
4984         UNLOCK_ZONE(zone);
4985         return (ISC_R_SUCCESS);
4986 }
4987
4988 isc_result_t
4989 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
4990                     isc_uint32_t count)
4991 {
4992         isc_result_t result;
4993
4994         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
4995         return (result);
4996 }
4997
4998 isc_result_t
4999 dns_zone_setmasterswithkeys(dns_zone_t *zone,
5000                             const isc_sockaddr_t *masters,
5001                             dns_name_t **keynames,
5002                             isc_uint32_t count)
5003 {
5004         isc_result_t result = ISC_R_SUCCESS;
5005         isc_sockaddr_t *newaddrs = NULL;
5006         dns_name_t **newnames = NULL;
5007         isc_boolean_t *newok;
5008         unsigned int i;
5009
5010         REQUIRE(DNS_ZONE_VALID(zone));
5011         REQUIRE(count == 0 || masters != NULL);
5012         if (keynames != NULL) {
5013                 REQUIRE(count != 0);
5014         }
5015
5016         LOCK_ZONE(zone);
5017         /*
5018          * The refresh code assumes that 'masters' wouldn't change under it.
5019          * If it will change then kill off any current refresh in progress
5020          * and update the masters info.  If it won't change then we can just
5021          * unlock and exit.
5022          */
5023         if (count != zone->masterscnt ||
5024             !same_addrs(zone->masters, masters, count) ||
5025             !same_keynames(zone->masterkeynames, keynames, count)) {
5026                 if (zone->request != NULL)
5027                         dns_request_cancel(zone->request);
5028         } else
5029                 goto unlock;
5030
5031         /*
5032          * This needs to happen before clear_addresskeylist() sets
5033          * zone->masterscnt to 0:
5034          */
5035         if (zone->mastersok != NULL) {
5036                 isc_mem_put(zone->mctx, zone->mastersok,
5037                             zone->masterscnt * sizeof(isc_boolean_t));
5038                 zone->mastersok = NULL;
5039         }
5040         clear_addresskeylist(&zone->masters, &zone->masterkeynames,
5041                              &zone->masterscnt, zone->mctx);
5042         /*
5043          * If count == 0, don't allocate any space for masters, mastersok or
5044          * keynames so internally, those pointers are NULL if count == 0
5045          */
5046         if (count == 0)
5047                 goto unlock;
5048
5049         /*
5050          * mastersok must contain count elements
5051          */
5052         newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
5053         if (newok == NULL) {
5054                 result = ISC_R_NOMEMORY;
5055                 isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
5056                 goto unlock;
5057         };
5058         for (i = 0; i < count; i++)
5059                 newok[i] = ISC_FALSE;
5060
5061         /*
5062          * Now set up the masters and masterkey lists
5063          */
5064         result = set_addrkeylist(count, masters, &newaddrs,
5065                                  keynames, &newnames, zone->mctx);
5066         if (result != ISC_R_SUCCESS) {
5067                 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
5068                 goto unlock;
5069         }
5070
5071         /*
5072          * Everything is ok so attach to the zone.
5073          */
5074         zone->curmaster = 0;
5075         zone->mastersok = newok;
5076         zone->masters = newaddrs;
5077         zone->masterkeynames = newnames;
5078         zone->masterscnt = count;
5079         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
5080
5081  unlock:
5082         UNLOCK_ZONE(zone);
5083         return (result);
5084 }
5085
5086 isc_result_t
5087 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
5088         isc_result_t result = ISC_R_SUCCESS;
5089
5090         REQUIRE(DNS_ZONE_VALID(zone));
5091
5092         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5093         if (zone->db == NULL)
5094                 result = DNS_R_NOTLOADED;
5095         else
5096                 dns_db_attach(zone->db, dpb);
5097         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5098
5099         return (result);
5100 }
5101
5102 void
5103 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
5104         REQUIRE(DNS_ZONE_VALID(zone));
5105         REQUIRE(zone->type == dns_zone_staticstub);
5106
5107         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5108         REQUIRE(zone->db == NULL);
5109         dns_db_attach(db, &zone->db);
5110         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5111 }
5112
5113 /*
5114  * Co-ordinates the starting of routine jobs.
5115  */
5116
5117 void
5118 dns_zone_maintenance(dns_zone_t *zone) {
5119         const char me[] = "dns_zone_maintenance";
5120         isc_time_t now;
5121
5122         REQUIRE(DNS_ZONE_VALID(zone));
5123         ENTER;
5124
5125         LOCK_ZONE(zone);
5126         TIME_NOW(&now);
5127         zone_settimer(zone, &now);
5128         UNLOCK_ZONE(zone);
5129 }
5130
5131 static inline isc_boolean_t
5132 was_dumping(dns_zone_t *zone) {
5133         isc_boolean_t dumping;
5134
5135         REQUIRE(LOCKED_ZONE(zone));
5136
5137         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
5138         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
5139         if (!dumping) {
5140                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
5141                 isc_time_settoepoch(&zone->dumptime);
5142         }
5143         return (dumping);
5144 }
5145
5146 static isc_result_t
5147 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
5148                isc_mem_t *mctx, unsigned int maxkeys,
5149                dst_key_t **keys, unsigned int *nkeys)
5150 {
5151         isc_result_t result;
5152         dns_dbnode_t *node = NULL;
5153         const char *directory = dns_zone_getkeydirectory(zone);
5154
5155         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
5156         result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
5157                                           directory, mctx, maxkeys, keys,
5158                                           nkeys);
5159         if (result == ISC_R_NOTFOUND)
5160                 result = ISC_R_SUCCESS;
5161  failure:
5162         if (node != NULL)
5163                 dns_db_detachnode(db, &node);
5164         return (result);
5165 }
5166
5167 static isc_result_t
5168 offline(dns_db_t *db, dns_dbversion_t *ver, zonediff_t *zonediff,
5169         dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
5170 {
5171         isc_result_t result;
5172
5173         if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
5174                 return (ISC_R_SUCCESS);
5175         result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
5176                                name, ttl, rdata);
5177         if (result != ISC_R_SUCCESS)
5178                 return (result);
5179         rdata->flags |= DNS_RDATA_OFFLINE;
5180         result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
5181                                name, ttl, rdata);
5182         zonediff->offline = ISC_TRUE;
5183         return (result);
5184 }
5185
5186 static void
5187 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
5188 {
5189         unsigned int delta;
5190         char timebuf[80];
5191
5192         zone->key_expiry = when;
5193         if (when <= now) {
5194                 dns_zone_log(zone, ISC_LOG_ERROR,
5195                              "DNSKEY RRSIG(s) have expired");
5196                 isc_time_settoepoch(&zone->keywarntime);
5197         } else if (when < now + 7 * 24 * 3600) {
5198                 isc_time_t t;
5199                 isc_time_set(&t, when, 0);
5200                 isc_time_formattimestamp(&t, timebuf, 80);
5201                 dns_zone_log(zone, ISC_LOG_WARNING,
5202                              "DNSKEY RRSIG(s) will expire within 7 days: %s",
5203                              timebuf);
5204                 delta = when - now;
5205                 delta--;                /* loop prevention */
5206                 delta /= 24 * 3600;     /* to whole days */
5207                 delta *= 24 * 3600;     /* to seconds */
5208                 isc_time_set(&zone->keywarntime, when - delta, 0);
5209         }  else {
5210                 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
5211                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
5212                 dns_zone_log(zone, ISC_LOG_NOTICE,
5213                              "setting keywarntime to %s", timebuf);
5214         }
5215 }
5216
5217 /*
5218  * Helper function to del_sigs(). We don't want to delete RRSIGs that
5219  * have no new key.
5220  */
5221 static isc_boolean_t
5222 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys) {
5223         unsigned int i = 0;
5224
5225         /*
5226          * It's okay to delete a signature if there is an active ZSK
5227          * with the same algorithm
5228          */
5229         for (i = 0; i < nkeys; i++) {
5230                 if (rrsig_ptr->algorithm == dst_key_alg(keys[i]) &&
5231                     (dst_key_isprivate(keys[i])) && !KSK(keys[i]))
5232                         return (ISC_TRUE);
5233         }
5234
5235         /*
5236          * Failing that, it is *not* okay to delete a signature
5237          * if the associated public key is still in the DNSKEY RRset
5238          */
5239         for (i = 0; i < nkeys; i++) {
5240                 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
5241                     (rrsig_ptr->keyid == dst_key_id(keys[i])))
5242                         return (ISC_FALSE);
5243         }
5244
5245         /*
5246          * But if the key is gone, then go ahead.
5247          */
5248         return (ISC_TRUE);
5249 }
5250
5251 /*
5252  * Delete expired RRsigs and any RRsigs we are about to re-sign.
5253  * See also update.c:del_keysigs().
5254  */
5255 static isc_result_t
5256 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5257          dns_rdatatype_t type, zonediff_t *zonediff, dst_key_t **keys,
5258          unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
5259 {
5260         isc_result_t result;
5261         dns_dbnode_t *node = NULL;
5262         dns_rdataset_t rdataset;
5263         unsigned int i;
5264         dns_rdata_rrsig_t rrsig;
5265         isc_boolean_t found, changed;
5266         isc_int64_t warn = 0, maybe = 0;
5267
5268         dns_rdataset_init(&rdataset);
5269
5270         if (type == dns_rdatatype_nsec3)
5271                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5272         else
5273                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
5274         if (result == ISC_R_NOTFOUND)
5275                 return (ISC_R_SUCCESS);
5276         if (result != ISC_R_SUCCESS)
5277                 goto failure;
5278         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
5279                                      (isc_stdtime_t) 0, &rdataset, NULL);
5280         dns_db_detachnode(db, &node);
5281
5282         if (result == ISC_R_NOTFOUND) {
5283                 INSIST(!dns_rdataset_isassociated(&rdataset));
5284                 return (ISC_R_SUCCESS);
5285         }
5286         if (result != ISC_R_SUCCESS) {
5287                 INSIST(!dns_rdataset_isassociated(&rdataset));
5288                 goto failure;
5289         }
5290
5291         changed = ISC_FALSE;
5292         for (result = dns_rdataset_first(&rdataset);
5293              result == ISC_R_SUCCESS;
5294              result = dns_rdataset_next(&rdataset)) {
5295                 dns_rdata_t rdata = DNS_RDATA_INIT;
5296
5297                 dns_rdataset_current(&rdataset, &rdata);
5298                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5299                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5300
5301                 if (type != dns_rdatatype_dnskey) {
5302                         if (delsig_ok(&rrsig, keys, nkeys)) {
5303                                 result = update_one_rr(db, ver, zonediff->diff,
5304                                                DNS_DIFFOP_DELRESIGN, name,
5305                                                rdataset.ttl, &rdata);
5306                                 if (incremental)
5307                                         changed = ISC_TRUE;
5308                                 if (result != ISC_R_SUCCESS)
5309                                         break;
5310                         } else {
5311                                 /*
5312                                  * At this point, we've got an RRSIG,
5313                                  * which is signed by an inactive key.
5314                                  * An administrator needs to provide a new
5315                                  * key/alg, but until that time, we want to
5316                                  * keep the old RRSIG.  Marking the key as
5317                                  * offline will prevent us spinning waiting
5318                                  * for the private part.
5319                                  */
5320                                 if (incremental) {
5321                                         result = offline(db, ver, zonediff,
5322                                                          name, rdataset.ttl,
5323                                                          &rdata);
5324                                         changed = ISC_TRUE;
5325                                         if (result != ISC_R_SUCCESS)
5326                                                 break;
5327                                 }
5328
5329                                 /*
5330                                  * Log the key id and algorithm of
5331                                  * the inactive key with no replacement
5332                                  */
5333                                 if (zone->log_key_expired_timer <= now) {
5334                                         char origin[DNS_NAME_FORMATSIZE];
5335                                         char algbuf[DNS_NAME_FORMATSIZE];
5336                                         dns_name_format(&zone->origin, origin,
5337                                                         sizeof(origin));
5338                                         dns_secalg_format(rrsig.algorithm,
5339                                                           algbuf,
5340                                                           sizeof(algbuf));
5341                                         dns_zone_log(zone, ISC_LOG_WARNING,
5342                                                      "Key %s/%s/%d "
5343                                                      "missing or inactive "
5344                                                      "and has no replacement: "
5345                                                      "retaining signatures.",
5346                                                      origin, algbuf,
5347                                                      rrsig.keyid);
5348                                         zone->log_key_expired_timer = now +
5349                                                                         3600;
5350                                 }
5351                         }
5352                         continue;
5353                 }
5354
5355                 /*
5356                  * RRSIG(DNSKEY) requires special processing.
5357                  */
5358                 found = ISC_FALSE;
5359                 for (i = 0; i < nkeys; i++) {
5360                         if (rrsig.algorithm == dst_key_alg(keys[i]) &&
5361                             rrsig.keyid == dst_key_id(keys[i])) {
5362                                 found = ISC_TRUE;
5363                                 /*
5364                                  * Mark offline RRSIG(DNSKEY).
5365                                  * We want the earliest offline expire time
5366                                  * iff there is a new offline signature.
5367                                  */
5368                                 if (!dst_key_isprivate(keys[i])) {
5369                                         isc_int64_t timeexpire =
5370                                            dns_time64_from32(rrsig.timeexpire);
5371                                         if (warn != 0 && warn > timeexpire)
5372                                                 warn = timeexpire;
5373                                         if (rdata.flags & DNS_RDATA_OFFLINE) {
5374                                                 if (maybe == 0 ||
5375                                                     maybe > timeexpire)
5376                                                         maybe = timeexpire;
5377                                                 break;
5378                                         }
5379                                         if (warn == 0)
5380                                                 warn = maybe;
5381                                         if (warn == 0 || warn > timeexpire)
5382                                                 warn = timeexpire;
5383                                         result = offline(db, ver, zonediff,
5384                                                          name, rdataset.ttl,
5385                                                          &rdata);
5386                                         break;
5387                                 }
5388                                 result = update_one_rr(db, ver, zonediff->diff,
5389                                                        DNS_DIFFOP_DELRESIGN,
5390                                                        name, rdataset.ttl,
5391                                                        &rdata);
5392                                 break;
5393                         }
5394                 }
5395
5396                 /*
5397                  * If there is not a matching DNSKEY then
5398                  * delete the RRSIG.
5399                  */
5400                 if (!found)
5401                         result = update_one_rr(db, ver, zonediff->diff,
5402                                                DNS_DIFFOP_DELRESIGN, name,
5403                                                rdataset.ttl, &rdata);
5404                 if (result != ISC_R_SUCCESS)
5405                         break;
5406         }
5407
5408         if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0)
5409                 dns_db_resigned(db, &rdataset, ver);
5410
5411         dns_rdataset_disassociate(&rdataset);
5412         if (result == ISC_R_NOMORE)
5413                 result = ISC_R_SUCCESS;
5414         if (warn > 0) {
5415 #if defined(STDTIME_ON_32BITS)
5416                 isc_stdtime_t stdwarn = (isc_stdtime_t)warn;
5417                 if (warn == stdwarn)
5418 #endif
5419                         set_key_expiry_warning(zone, (isc_stdtime_t)warn, now);
5420 #if defined(STDTIME_ON_32BITS)
5421                 else
5422                         dns_zone_log(zone, ISC_LOG_ERROR,
5423                                      "key expiry warning time out of range");
5424 #endif
5425         }
5426  failure:
5427         if (node != NULL)
5428                 dns_db_detachnode(db, &node);
5429         return (result);
5430 }
5431
5432 static isc_result_t
5433 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5434          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
5435          unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
5436          isc_stdtime_t expire, isc_boolean_t check_ksk,
5437          isc_boolean_t keyset_kskonly)
5438 {
5439         isc_result_t result;
5440         dns_dbnode_t *node = NULL;
5441         dns_rdataset_t rdataset;
5442         dns_rdata_t sig_rdata = DNS_RDATA_INIT;
5443         unsigned char data[1024]; /* XXX */
5444         isc_buffer_t buffer;
5445         unsigned int i, j;
5446
5447         dns_rdataset_init(&rdataset);
5448         isc_buffer_init(&buffer, data, sizeof(data));
5449
5450         if (type == dns_rdatatype_nsec3)
5451                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5452         else
5453                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
5454         if (result == ISC_R_NOTFOUND)
5455                 return (ISC_R_SUCCESS);
5456         if (result != ISC_R_SUCCESS)
5457                 goto failure;
5458         result = dns_db_findrdataset(db, node, ver, type, 0,
5459                                      (isc_stdtime_t) 0, &rdataset, NULL);
5460         dns_db_detachnode(db, &node);
5461         if (result == ISC_R_NOTFOUND) {
5462                 INSIST(!dns_rdataset_isassociated(&rdataset));
5463                 return (ISC_R_SUCCESS);
5464         }
5465         if (result != ISC_R_SUCCESS) {
5466                 INSIST(!dns_rdataset_isassociated(&rdataset));
5467                 goto failure;
5468         }
5469
5470         for (i = 0; i < nkeys; i++) {
5471                 isc_boolean_t both = ISC_FALSE;
5472
5473                 if (!dst_key_isprivate(keys[i]))
5474                         continue;
5475
5476                 if (check_ksk && !REVOKE(keys[i])) {
5477                         isc_boolean_t have_ksk, have_nonksk;
5478                         if (KSK(keys[i])) {
5479                                 have_ksk = ISC_TRUE;
5480                                 have_nonksk = ISC_FALSE;
5481                         } else {
5482                                 have_ksk = ISC_FALSE;
5483                                 have_nonksk = ISC_TRUE;
5484                         }
5485                         for (j = 0; j < nkeys; j++) {
5486                                 if (j == i || ALG(keys[i]) != ALG(keys[j]))
5487                                         continue;
5488                                 if (REVOKE(keys[j]))
5489                                         continue;
5490                                 if (KSK(keys[j]))
5491                                         have_ksk = ISC_TRUE;
5492                                 else
5493                                         have_nonksk = ISC_TRUE;
5494                                 both = have_ksk && have_nonksk;
5495                                 if (both)
5496                                         break;
5497                         }
5498                 }
5499                 if (both) {
5500                         if (type == dns_rdatatype_dnskey) {
5501                                 if (!KSK(keys[i]) && keyset_kskonly)
5502                                         continue;
5503                         } else if (KSK(keys[i]))
5504                                 continue;
5505                 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
5506                                 continue;
5507
5508                 /* Calculate the signature, creating a RRSIG RDATA. */
5509                 isc_buffer_clear(&buffer);
5510                 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
5511                                       &inception, &expire,
5512                                       mctx, &buffer, &sig_rdata));
5513                 /* Update the database and journal with the RRSIG. */
5514                 /* XXX inefficient - will cause dataset merging */
5515                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
5516                                     name, rdataset.ttl, &sig_rdata));
5517                 dns_rdata_reset(&sig_rdata);
5518                 isc_buffer_init(&buffer, data, sizeof(data));
5519         }
5520
5521  failure:
5522         if (dns_rdataset_isassociated(&rdataset))
5523                 dns_rdataset_disassociate(&rdataset);
5524         if (node != NULL)
5525                 dns_db_detachnode(db, &node);
5526         return (result);
5527 }
5528
5529 static void
5530 zone_resigninc(dns_zone_t *zone) {
5531         const char *me = "zone_resigninc";
5532         dns_db_t *db = NULL;
5533         dns_dbversion_t *version = NULL;
5534         dns_diff_t _sig_diff;
5535         zonediff_t zonediff;
5536         dns_fixedname_t fixed;
5537         dns_name_t *name;
5538         dns_rdataset_t rdataset;
5539         dns_rdatatype_t covers;
5540         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
5541         isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
5542         isc_result_t result;
5543         isc_stdtime_t now, inception, soaexpire, expire, stop;
5544         isc_uint32_t jitter;
5545         unsigned int i;
5546         unsigned int nkeys = 0;
5547         unsigned int resign;
5548
5549         ENTER;
5550
5551         dns_rdataset_init(&rdataset);
5552         dns_fixedname_init(&fixed);
5553         dns_diff_init(zone->mctx, &_sig_diff);
5554         _sig_diff.resign = zone->sigresigninginterval;
5555         zonediff_init(&zonediff, &_sig_diff);
5556
5557         /*
5558          * Zone is frozen or automatic resigning is disabled.
5559          * Pause for 5 minutes.
5560          */
5561         if (zone->update_disabled ||
5562             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
5563         {
5564                 result = ISC_R_FAILURE;
5565                 goto failure;
5566         }
5567
5568         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5569         dns_db_attach(zone->db, &db);
5570         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5571
5572         result = dns_db_newversion(db, &version);
5573         if (result != ISC_R_SUCCESS) {
5574                 dns_zone_log(zone, ISC_LOG_ERROR,
5575                              "zone_resigninc:dns_db_newversion -> %s",
5576                              dns_result_totext(result));
5577                 goto failure;
5578         }
5579
5580         result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
5581                                 zone_keys, &nkeys);
5582         if (result != ISC_R_SUCCESS) {
5583                 dns_zone_log(zone, ISC_LOG_ERROR,
5584                              "zone_resigninc:find_zone_keys -> %s",
5585                              dns_result_totext(result));
5586                 goto failure;
5587         }
5588
5589         isc_stdtime_get(&now);
5590         inception = now - 3600; /* Allow for clock skew. */
5591         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5592         /*
5593          * Spread out signatures over time if they happen to be
5594          * clumped.  We don't do this for each add_sigs() call as
5595          * we still want some clustering to occur.
5596          */
5597         isc_random_get(&jitter);
5598         expire = soaexpire - jitter % 3600;
5599         stop = now + 5;
5600
5601         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5602         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5603
5604         name = dns_fixedname_name(&fixed);
5605         result = dns_db_getsigningtime(db, &rdataset, name);
5606         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
5607                 dns_zone_log(zone, ISC_LOG_ERROR,
5608                              "zone_resigninc:dns_db_getsigningtime -> %s",
5609                              dns_result_totext(result));
5610         }
5611
5612         i = 0;
5613         while (result == ISC_R_SUCCESS) {
5614                 resign = rdataset.resign;
5615                 covers = rdataset.covers;
5616                 dns_rdataset_disassociate(&rdataset);
5617
5618                 /*
5619                  * Stop if we hit the SOA as that means we have walked the
5620                  * entire zone.  The SOA record should always be the most
5621                  * recent signature.
5622                  */
5623                 /* XXXMPA increase number of RRsets signed pre call */
5624                 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
5625                     resign > stop)
5626                         break;
5627
5628                 result = del_sigs(zone, db, version, name, covers, &zonediff,
5629                                   zone_keys, nkeys, now, ISC_TRUE);
5630                 if (result != ISC_R_SUCCESS) {
5631                         dns_zone_log(zone, ISC_LOG_ERROR,
5632                                      "zone_resigninc:del_sigs -> %s",
5633                                      dns_result_totext(result));
5634                         break;
5635                 }
5636
5637                 result = add_sigs(db, version, name, covers, zonediff.diff,
5638                                   zone_keys, nkeys, zone->mctx, inception,
5639                                   expire, check_ksk, keyset_kskonly);
5640                 if (result != ISC_R_SUCCESS) {
5641                         dns_zone_log(zone, ISC_LOG_ERROR,
5642                                      "zone_resigninc:add_sigs -> %s",
5643                                      dns_result_totext(result));
5644                         break;
5645                 }
5646                 result  = dns_db_getsigningtime(db, &rdataset,
5647                                                 dns_fixedname_name(&fixed));
5648                 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
5649                         result = ISC_R_SUCCESS;
5650                         break;
5651                 }
5652                 if (result != ISC_R_SUCCESS)
5653                         dns_zone_log(zone, ISC_LOG_ERROR,
5654                              "zone_resigninc:dns_db_getsigningtime -> %s",
5655                                      dns_result_totext(result));
5656         }
5657
5658         if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
5659                 goto failure;
5660
5661         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5662                           &zonediff, zone_keys, nkeys, now, ISC_TRUE);
5663         if (result != ISC_R_SUCCESS) {
5664                 dns_zone_log(zone, ISC_LOG_ERROR,
5665                              "zone_resigninc:del_sigs -> %s",
5666                              dns_result_totext(result));
5667                 goto failure;
5668         }
5669
5670         /*
5671          * Did we change anything in the zone?
5672          */
5673         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
5674                 /*
5675                  * Commit the changes if any key has been marked as offline.                     */
5676                 if (zonediff.offline)
5677                         dns_db_closeversion(db, &version, ISC_TRUE);
5678                 goto failure;
5679         }
5680
5681         /* Increment SOA serial if we have made changes */
5682         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
5683                                    zone->updatemethod);
5684         if (result != ISC_R_SUCCESS) {
5685                 dns_zone_log(zone, ISC_LOG_ERROR,
5686                              "zone_resigninc:update_soa_serial -> %s",
5687                              dns_result_totext(result));
5688                 goto failure;
5689         }
5690
5691         /*
5692          * Generate maximum life time signatures so that the above loop
5693          * termination is sensible.
5694          */
5695         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5696                           zonediff.diff, zone_keys, nkeys, zone->mctx,
5697                           inception, soaexpire, check_ksk, keyset_kskonly);
5698         if (result != ISC_R_SUCCESS) {
5699                 dns_zone_log(zone, ISC_LOG_ERROR,
5700                              "zone_resigninc:add_sigs -> %s",
5701                              dns_result_totext(result));
5702                 goto failure;
5703         }
5704
5705         /* Write changes to journal file. */
5706         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
5707
5708         /* Everything has succeeded. Commit the changes. */
5709         dns_db_closeversion(db, &version, ISC_TRUE);
5710
5711  failure:
5712         dns_diff_clear(&_sig_diff);
5713         for (i = 0; i < nkeys; i++)
5714                 dst_key_free(&zone_keys[i]);
5715         if (version != NULL) {
5716                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
5717                 dns_db_detach(&db);
5718         } else if (db != NULL)
5719                 dns_db_detach(&db);
5720         if (result == ISC_R_SUCCESS) {
5721                 set_resigntime(zone);
5722                 LOCK_ZONE(zone);
5723                 zone_needdump(zone, DNS_DUMP_DELAY);
5724                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5725                 UNLOCK_ZONE(zone);
5726         } else {
5727                 /*
5728                  * Something failed.  Retry in 5 minutes.
5729                  */
5730                 isc_interval_t ival;
5731                 isc_interval_set(&ival, 300, 0);
5732                 isc_time_nowplusinterval(&zone->resigntime, &ival);
5733         }
5734 }
5735
5736 static isc_result_t
5737 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
5738             dns_name_t *newname, isc_boolean_t bottom)
5739 {
5740         isc_result_t result;
5741         dns_dbiterator_t *dbit = NULL;
5742         dns_rdatasetiter_t *rdsit = NULL;
5743         dns_dbnode_t *node = NULL;
5744
5745         CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
5746         CHECK(dns_dbiterator_seek(dbit, oldname));
5747         do {
5748                 result = dns_dbiterator_next(dbit);
5749                 if (result == ISC_R_NOMORE)
5750                         CHECK(dns_dbiterator_first(dbit));
5751                 CHECK(dns_dbiterator_current(dbit, &node, newname));
5752                 if (bottom && dns_name_issubdomain(newname, oldname) &&
5753                     !dns_name_equal(newname, oldname)) {
5754                         dns_db_detachnode(db, &node);
5755                         continue;
5756                 }
5757                 /*
5758                  * Is this node empty?
5759                  */
5760                 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
5761                 result = dns_rdatasetiter_first(rdsit);
5762                 dns_db_detachnode(db, &node);
5763                 dns_rdatasetiter_destroy(&rdsit);
5764                 if (result != ISC_R_NOMORE)
5765                         break;
5766         } while (1);
5767  failure:
5768         if (node != NULL)
5769                 dns_db_detachnode(db, &node);
5770         if (dbit != NULL)
5771                 dns_dbiterator_destroy(&dbit);
5772         return (result);
5773 }
5774
5775 static isc_boolean_t
5776 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5777                 dns_rdatatype_t type, dst_key_t *key)
5778 {
5779         isc_result_t result;
5780         dns_rdataset_t rdataset;
5781         dns_rdata_t rdata = DNS_RDATA_INIT;
5782         dns_rdata_rrsig_t rrsig;
5783
5784         dns_rdataset_init(&rdataset);
5785         result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
5786                                      type, 0, &rdataset, NULL);
5787         if (result != ISC_R_SUCCESS) {
5788                 INSIST(!dns_rdataset_isassociated(&rdataset));
5789                 return (ISC_FALSE);
5790         }
5791         for (result = dns_rdataset_first(&rdataset);
5792              result == ISC_R_SUCCESS;
5793              result = dns_rdataset_next(&rdataset)) {
5794                 dns_rdataset_current(&rdataset, &rdata);
5795                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5796                 INSIST(result == ISC_R_SUCCESS);
5797                 if (rrsig.algorithm == dst_key_alg(key) &&
5798                     rrsig.keyid == dst_key_id(key)) {
5799                         dns_rdataset_disassociate(&rdataset);
5800                         return (ISC_TRUE);
5801                 }
5802                 dns_rdata_reset(&rdata);
5803         }
5804         dns_rdataset_disassociate(&rdataset);
5805         return (ISC_FALSE);
5806 }
5807
5808 static isc_result_t
5809 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5810          dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
5811          dns_diff_t *diff)
5812 {
5813         dns_fixedname_t fixed;
5814         dns_name_t *next;
5815         dns_rdata_t rdata = DNS_RDATA_INIT;
5816         isc_result_t result;
5817         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
5818
5819         dns_fixedname_init(&fixed);
5820         next = dns_fixedname_name(&fixed);
5821
5822         CHECK(next_active(db, version, name, next, bottom));
5823         CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
5824                                   &rdata));
5825         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
5826                             &rdata));
5827  failure:
5828         return (result);
5829 }
5830
5831 static isc_result_t
5832 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
5833             dns_dbversion_t *version, isc_boolean_t build_nsec3,
5834             isc_boolean_t build_nsec, dst_key_t *key,
5835             isc_stdtime_t inception, isc_stdtime_t expire,
5836             unsigned int minimum, isc_boolean_t is_ksk,
5837             isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
5838             dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
5839 {
5840         isc_result_t result;
5841         dns_rdatasetiter_t *iterator = NULL;
5842         dns_rdataset_t rdataset;
5843         dns_rdata_t rdata = DNS_RDATA_INIT;
5844         isc_buffer_t buffer;
5845         unsigned char data[1024];
5846         isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
5847                       seen_nsec3, seen_ds;
5848         isc_boolean_t bottom;
5849
5850         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5851         if (result != ISC_R_SUCCESS) {
5852                 if (result == ISC_R_NOTFOUND)
5853                         result = ISC_R_SUCCESS;
5854                 return (result);
5855         }
5856
5857         dns_rdataset_init(&rdataset);
5858         isc_buffer_init(&buffer, data, sizeof(data));
5859         seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
5860         seen_nsec3 = seen_ds = ISC_FALSE;
5861         for (result = dns_rdatasetiter_first(iterator);
5862              result == ISC_R_SUCCESS;
5863              result = dns_rdatasetiter_next(iterator)) {
5864                 dns_rdatasetiter_current(iterator, &rdataset);
5865                 if (rdataset.type == dns_rdatatype_soa)
5866                         seen_soa = ISC_TRUE;
5867                 else if (rdataset.type == dns_rdatatype_ns)
5868                         seen_ns = ISC_TRUE;
5869                 else if (rdataset.type == dns_rdatatype_ds)
5870                         seen_ds = ISC_TRUE;
5871                 else if (rdataset.type == dns_rdatatype_dname)
5872                         seen_dname = ISC_TRUE;
5873                 else if (rdataset.type == dns_rdatatype_nsec)
5874                         seen_nsec = ISC_TRUE;
5875                 else if (rdataset.type == dns_rdatatype_nsec3)
5876                         seen_nsec3 = ISC_TRUE;
5877                 if (rdataset.type != dns_rdatatype_rrsig)
5878                         seen_rr = ISC_TRUE;
5879                 dns_rdataset_disassociate(&rdataset);
5880         }
5881         if (result != ISC_R_NOMORE)
5882                 goto failure;
5883         if (seen_ns && !seen_soa)
5884                 *delegation = ISC_TRUE;
5885         /*
5886          * Going from insecure to NSEC3.
5887          * Don't generate NSEC3 records for NSEC3 records.
5888          */
5889         if (build_nsec3 && !seen_nsec3 && seen_rr) {
5890                 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
5891                 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
5892                                           unsecure, diff));
5893                 (*signatures)--;
5894         }
5895         /*
5896          * Going from insecure to NSEC.
5897          * Don't generate NSEC records for NSEC3 records.
5898          */
5899         if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
5900                 /* Build and add NSEC. */
5901                 bottom = (seen_ns && !seen_soa) || seen_dname;
5902                 /*
5903                  * Build a NSEC record except at the origin.
5904                  */
5905                 if (!dns_name_equal(name, dns_db_origin(db))) {
5906                         CHECK(add_nsec(db, version, name, node, minimum,
5907                                        bottom, diff));
5908                         /* Count a NSEC generation as a signature generation. */
5909                         (*signatures)--;
5910                 }
5911         }
5912         result = dns_rdatasetiter_first(iterator);
5913         while (result == ISC_R_SUCCESS) {
5914                 dns_rdatasetiter_current(iterator, &rdataset);
5915                 if (rdataset.type == dns_rdatatype_soa ||
5916                     rdataset.type == dns_rdatatype_rrsig)
5917                         goto next_rdataset;
5918                 if (rdataset.type == dns_rdatatype_dnskey) {
5919                         if (!is_ksk && keyset_kskonly)
5920                                 goto next_rdataset;
5921                 } else if (is_ksk)
5922                         goto next_rdataset;
5923                 if (*delegation &&
5924                     rdataset.type != dns_rdatatype_ds &&
5925                     rdataset.type != dns_rdatatype_nsec)
5926                         goto next_rdataset;
5927                 if (signed_with_key(db, node, version, rdataset.type, key))
5928                         goto next_rdataset;
5929                 /* Calculate the signature, creating a RRSIG RDATA. */
5930                 isc_buffer_clear(&buffer);
5931                 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
5932                                       &expire, mctx, &buffer, &rdata));
5933                 /* Update the database and journal with the RRSIG. */
5934                 /* XXX inefficient - will cause dataset merging */
5935                 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
5936                                     name, rdataset.ttl, &rdata));
5937                 dns_rdata_reset(&rdata);
5938                 (*signatures)--;
5939  next_rdataset:
5940                 dns_rdataset_disassociate(&rdataset);
5941                 result = dns_rdatasetiter_next(iterator);
5942         }
5943         if (result == ISC_R_NOMORE)
5944                 result = ISC_R_SUCCESS;
5945         if (seen_dname)
5946                 *delegation = ISC_TRUE;
5947  failure:
5948         if (dns_rdataset_isassociated(&rdataset))
5949                 dns_rdataset_disassociate(&rdataset);
5950         if (iterator != NULL)
5951                 dns_rdatasetiter_destroy(&iterator);
5952         return (result);
5953 }
5954
5955 /*
5956  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
5957  */
5958 static isc_result_t
5959 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5960              dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
5961 {
5962         isc_result_t result;
5963         dns_rdataset_t rdataset;
5964         dns_dbnode_t *node = NULL;
5965
5966         CHECK(dns_db_getoriginnode(db, &node));
5967         if (update_only) {
5968                 dns_rdataset_init(&rdataset);
5969                 result = dns_db_findrdataset(db, node, version,
5970                                              dns_rdatatype_nsec,
5971                                              dns_rdatatype_none,
5972                                              0, &rdataset, NULL);
5973                 if (dns_rdataset_isassociated(&rdataset))
5974                         dns_rdataset_disassociate(&rdataset);
5975                 if (result == ISC_R_NOTFOUND)
5976                         goto success;
5977                 if (result != ISC_R_SUCCESS)
5978                         goto failure;
5979         }
5980         CHECK(delete_nsec(db, version, node, name, diff));
5981         CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
5982  success:
5983         result = ISC_R_SUCCESS;
5984  failure:
5985         if (node != NULL)
5986                 dns_db_detachnode(db, &node);
5987         return (result);
5988 }
5989
5990 static isc_result_t
5991 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
5992                   dns_dbversion_t *version, isc_boolean_t build_nsec3,
5993                   dns_ttl_t minimum, dns_diff_t *diff)
5994 {
5995         isc_result_t result;
5996         dns_dbnode_t *node = NULL;
5997         dns_rdataset_t rdataset;
5998         dns_rdata_t rdata = DNS_RDATA_INIT;
5999         unsigned char data[5];
6000         isc_boolean_t seen_done = ISC_FALSE;
6001         isc_boolean_t have_rr = ISC_FALSE;
6002
6003         dns_rdataset_init(&rdataset);
6004         result = dns_db_getoriginnode(signing->db, &node);
6005         if (result != ISC_R_SUCCESS)
6006                 goto failure;
6007
6008         result = dns_db_findrdataset(signing->db, node, version,
6009                                      zone->privatetype, dns_rdatatype_none,
6010                                      0, &rdataset, NULL);
6011         if (result == ISC_R_NOTFOUND) {
6012                 INSIST(!dns_rdataset_isassociated(&rdataset));
6013                 result = ISC_R_SUCCESS;
6014                 goto failure;
6015         }
6016         if (result != ISC_R_SUCCESS) {
6017                 INSIST(!dns_rdataset_isassociated(&rdataset));
6018                 goto failure;
6019         }
6020         for (result = dns_rdataset_first(&rdataset);
6021              result == ISC_R_SUCCESS;
6022              result = dns_rdataset_next(&rdataset)) {
6023                 dns_rdataset_current(&rdataset, &rdata);
6024                 /*
6025                  * If we don't match the algorithm or keyid skip the record.
6026                  */
6027                 if (rdata.length != 5 ||
6028                     rdata.data[0] != signing->algorithm ||
6029                     rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
6030                     rdata.data[2] != (signing->keyid & 0xff)) {
6031                         have_rr = ISC_TRUE;
6032                         dns_rdata_reset(&rdata);
6033                         continue;
6034                 }
6035                 /*
6036                  * We have a match.  If we were signing (!signing->delete)
6037                  * and we already have a record indicating that we have
6038                  * finished signing (rdata.data[4] != 0) then keep it.
6039                  * Otherwise it needs to be deleted as we have removed all
6040                  * the signatures (signing->delete), so any record indicating
6041                  * completion is now out of date, or we have finished signing
6042                  * with the new record so we no longer need to remember that
6043                  * we need to sign the zone with the matching key across a
6044                  * nameserver re-start.
6045                  */
6046                 if (!signing->delete && rdata.data[4] != 0) {
6047                         seen_done = ISC_TRUE;
6048                         have_rr = ISC_TRUE;
6049                 } else
6050                         CHECK(update_one_rr(signing->db, version, diff,
6051                                             DNS_DIFFOP_DEL, &zone->origin,
6052                                             rdataset.ttl, &rdata));
6053                 dns_rdata_reset(&rdata);
6054         }
6055         if (result == ISC_R_NOMORE)
6056                 result = ISC_R_SUCCESS;
6057         if (!signing->delete && !seen_done) {
6058                 /*
6059                  * If we were signing then we need to indicate that we have
6060                  * finished signing the zone with this key.  If it is already
6061                  * there we don't need to add it a second time.
6062                  */
6063                 data[0] = signing->algorithm;
6064                 data[1] = (signing->keyid >> 8) & 0xff;
6065                 data[2] = signing->keyid & 0xff;
6066                 data[3] = 0;
6067                 data[4] = 1;
6068                 rdata.length = sizeof(data);
6069                 rdata.data = data;
6070                 rdata.type = zone->privatetype;
6071                 rdata.rdclass = dns_db_class(signing->db);
6072                 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
6073                                     &zone->origin, rdataset.ttl, &rdata));
6074         } else if (!have_rr) {
6075                 dns_name_t *origin = dns_db_origin(signing->db);
6076                 /*
6077                  * Rebuild the NSEC/NSEC3 record for the origin as we no
6078                  * longer have any private records.
6079                  */
6080                 if (build_nsec3)
6081                         CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
6082                                                   minimum, ISC_FALSE, diff));
6083                 CHECK(updatesecure(signing->db, version, origin, minimum,
6084                                    ISC_TRUE, diff));
6085         }
6086
6087  failure:
6088         if (dns_rdataset_isassociated(&rdataset))
6089                 dns_rdataset_disassociate(&rdataset);
6090         if (node != NULL)
6091                 dns_db_detachnode(signing->db, &node);
6092         return (result);
6093 }
6094
6095 /*
6096  * If 'active' is set then we are not done with the chain yet so only
6097  * delete the nsec3param record which indicates a full chain exists
6098  * (flags == 0).
6099  */
6100 static isc_result_t
6101 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
6102                  isc_boolean_t active, dns_rdatatype_t privatetype,
6103                  dns_diff_t *diff)
6104 {
6105         dns_dbnode_t *node = NULL;
6106         dns_name_t *name = dns_db_origin(db);
6107         dns_rdata_t rdata = DNS_RDATA_INIT;
6108         dns_rdataset_t rdataset;
6109         dns_rdata_nsec3param_t nsec3param;
6110         isc_result_t result;
6111         isc_buffer_t buffer;
6112         unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
6113         dns_ttl_t ttl = 0;
6114         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
6115
6116         dns_rdataset_init(&rdataset);
6117
6118         result = dns_db_getoriginnode(db, &node);
6119         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6120         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6121                                      0, 0, &rdataset, NULL);
6122         if (result == ISC_R_NOTFOUND)
6123                 goto try_private;
6124         if (result != ISC_R_SUCCESS)
6125                 goto failure;
6126
6127         /*
6128          * Preserve the existing ttl.
6129          */
6130         ttl = rdataset.ttl;
6131
6132         /*
6133          * Delete all NSEC3PARAM records which match that in nsec3chain.
6134          */
6135         for (result = dns_rdataset_first(&rdataset);
6136              result == ISC_R_SUCCESS;
6137              result = dns_rdataset_next(&rdataset)) {
6138
6139                 dns_rdataset_current(&rdataset, &rdata);
6140                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6141
6142                 if (nsec3param.hash != chain->nsec3param.hash ||
6143                     (active && nsec3param.flags != 0) ||
6144                     nsec3param.iterations != chain->nsec3param.iterations ||
6145                     nsec3param.salt_length != chain->nsec3param.salt_length ||
6146                     memcmp(nsec3param.salt, chain->nsec3param.salt,
6147                            nsec3param.salt_length)) {
6148                         dns_rdata_reset(&rdata);
6149                         continue;
6150                 }
6151
6152                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6153                                     name, rdataset.ttl, &rdata));
6154                 dns_rdata_reset(&rdata);
6155         }
6156         if (result != ISC_R_NOMORE)
6157                 goto failure;
6158
6159         dns_rdataset_disassociate(&rdataset);
6160
6161  try_private:
6162
6163         if (active)
6164                 goto add;
6165
6166         result = dns_nsec_nseconly(db, ver, &nseconly);
6167         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
6168
6169         /*
6170          * Delete all private records which match that in nsec3chain.
6171          */
6172         result = dns_db_findrdataset(db, node, ver, privatetype,
6173                                      0, 0, &rdataset, NULL);
6174         if (result == ISC_R_NOTFOUND)
6175                 goto add;
6176         if (result != ISC_R_SUCCESS)
6177                 goto failure;
6178
6179         for (result = dns_rdataset_first(&rdataset);
6180              result == ISC_R_SUCCESS;
6181              result = dns_rdataset_next(&rdataset)) {
6182                 dns_rdata_t private = DNS_RDATA_INIT;
6183                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
6184
6185                 dns_rdataset_current(&rdataset, &private);
6186                 if (!dns_nsec3param_fromprivate(&private, &rdata,
6187                                                 buf, sizeof(buf)))
6188                         continue;
6189                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6190
6191                 if ((!nsec3ok &&
6192                      (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
6193                     nsec3param.hash != chain->nsec3param.hash ||
6194                     nsec3param.iterations != chain->nsec3param.iterations ||
6195                     nsec3param.salt_length != chain->nsec3param.salt_length ||
6196                     memcmp(nsec3param.salt, chain->nsec3param.salt,
6197                            nsec3param.salt_length)) {
6198                         dns_rdata_reset(&rdata);
6199                         continue;
6200                 }
6201
6202                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6203                                     name, rdataset.ttl, &private));
6204                 dns_rdata_reset(&rdata);
6205         }
6206         if (result != ISC_R_NOMORE)
6207                 goto failure;
6208
6209   add:
6210         if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
6211                 result = ISC_R_SUCCESS;
6212                 goto failure;
6213         }
6214
6215         /*
6216          * Add a NSEC3PARAM record which matches that in nsec3chain but
6217          * with all flags bits cleared.
6218          *
6219          * Note: we do not clear chain->nsec3param.flags as this change
6220          * may be reversed.
6221          */
6222         isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
6223         CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
6224                                    dns_rdatatype_nsec3param,
6225                                    &chain->nsec3param, &buffer));
6226         rdata.data[1] = 0;      /* Clear flag bits. */
6227         CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
6228
6229   failure:
6230         dns_db_detachnode(db, &node);
6231         if (dns_rdataset_isassociated(&rdataset))
6232                 dns_rdataset_disassociate(&rdataset);
6233         return (result);
6234 }
6235
6236 static isc_result_t
6237 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6238             dns_name_t *name, dns_diff_t *diff)
6239 {
6240         dns_rdataset_t rdataset;
6241         isc_result_t result;
6242
6243         dns_rdataset_init(&rdataset);
6244
6245         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6246                                      0, 0, &rdataset, NULL);
6247         if (result == ISC_R_NOTFOUND)
6248                 return (ISC_R_SUCCESS);
6249         if (result != ISC_R_SUCCESS)
6250                 return (result);
6251         for (result = dns_rdataset_first(&rdataset);
6252              result == ISC_R_SUCCESS;
6253              result = dns_rdataset_next(&rdataset)) {
6254                 dns_rdata_t rdata = DNS_RDATA_INIT;
6255
6256                 dns_rdataset_current(&rdataset, &rdata);
6257                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6258                                     rdataset.ttl, &rdata));
6259         }
6260         if (result == ISC_R_NOMORE)
6261                 result = ISC_R_SUCCESS;
6262  failure:
6263         dns_rdataset_disassociate(&rdataset);
6264         return (result);
6265 }
6266
6267 static isc_result_t
6268 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6269                     dns_name_t *name, const dns_rdata_nsec3param_t *param,
6270                     dns_diff_t *diff)
6271 {
6272         dns_rdataset_t rdataset;
6273         dns_rdata_nsec3_t nsec3;
6274         isc_result_t result;
6275
6276         dns_rdataset_init(&rdataset);
6277         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
6278                                      0, 0, &rdataset, NULL);
6279         if (result == ISC_R_NOTFOUND)
6280                 return (ISC_R_SUCCESS);
6281         if (result != ISC_R_SUCCESS)
6282                 return (result);
6283
6284         for (result = dns_rdataset_first(&rdataset);
6285              result == ISC_R_SUCCESS;
6286              result = dns_rdataset_next(&rdataset)) {
6287                 dns_rdata_t rdata = DNS_RDATA_INIT;
6288
6289                 dns_rdataset_current(&rdataset, &rdata);
6290                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
6291                 if (nsec3.hash != param->hash ||
6292                     nsec3.iterations != param->iterations ||
6293                     nsec3.salt_length != param->salt_length ||
6294                     memcmp(nsec3.salt, param->salt, nsec3.salt_length))
6295                         continue;
6296                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6297                                     rdataset.ttl, &rdata));
6298         }
6299         if (result == ISC_R_NOMORE)
6300                 result = ISC_R_SUCCESS;
6301  failure:
6302         dns_rdataset_disassociate(&rdataset);
6303         return (result);
6304 }
6305
6306 static isc_result_t
6307 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
6308                 const dns_rdata_nsec3param_t *param,
6309                 isc_boolean_t *answer)
6310 {
6311         dns_dbnode_t *node = NULL;
6312         dns_rdata_t rdata = DNS_RDATA_INIT;
6313         dns_rdata_nsec3param_t myparam;
6314         dns_rdataset_t rdataset;
6315         isc_result_t result;
6316
6317         *answer = ISC_FALSE;
6318
6319         result = dns_db_getoriginnode(db, &node);
6320         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6321
6322         dns_rdataset_init(&rdataset);
6323
6324         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6325                                      0, 0, &rdataset, NULL);
6326         if (result == ISC_R_SUCCESS) {
6327                 dns_rdataset_disassociate(&rdataset);
6328                 dns_db_detachnode(db, &node);
6329                 return (result);
6330         }
6331         if (result != ISC_R_NOTFOUND) {
6332                 dns_db_detachnode(db, &node);
6333                 return (result);
6334         }
6335
6336         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6337                                      0, 0, &rdataset, NULL);
6338         if (result == ISC_R_NOTFOUND) {
6339                 *answer = ISC_TRUE;
6340                 dns_db_detachnode(db, &node);
6341                 return (ISC_R_SUCCESS);
6342         }
6343         if (result != ISC_R_SUCCESS) {
6344                 dns_db_detachnode(db, &node);
6345                 return (result);
6346         }
6347
6348         for (result = dns_rdataset_first(&rdataset);
6349              result == ISC_R_SUCCESS;
6350              result = dns_rdataset_next(&rdataset)) {
6351                 dns_rdataset_current(&rdataset, &rdata);
6352                 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
6353                 dns_rdata_reset(&rdata);
6354                 /*
6355                  * Ignore any NSEC3PARAM removals.
6356                  */
6357                 if (NSEC3REMOVE(myparam.flags))
6358                         continue;
6359                 /*
6360                  * Ignore the chain that we are in the process of deleting.
6361                  */
6362                 if (myparam.hash == param->hash &&
6363                     myparam.iterations == param->iterations &&
6364                     myparam.salt_length == param->salt_length &&
6365                     !memcmp(myparam.salt, param->salt, myparam.salt_length))
6366                         continue;
6367                 /*
6368                  * Found an active NSEC3 chain.
6369                  */
6370                 break;
6371         }
6372         if (result == ISC_R_NOMORE) {
6373                 *answer = ISC_TRUE;
6374                 result = ISC_R_SUCCESS;
6375         }
6376
6377  failure:
6378         if (dns_rdataset_isassociated(&rdataset))
6379                 dns_rdataset_disassociate(&rdataset);
6380         dns_db_detachnode(db, &node);
6381         return (result);
6382 }
6383
6384 static isc_result_t
6385 update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
6386             dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
6387             isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
6388             isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
6389             zonediff_t *zonediff)
6390 {
6391         dns_difftuple_t *tuple;
6392         isc_result_t result;
6393
6394         for (tuple = ISC_LIST_HEAD(diff->tuples);
6395              tuple != NULL;
6396              tuple = ISC_LIST_HEAD(diff->tuples)) {
6397                 result = del_sigs(zone, db, version, &tuple->name,
6398                                   tuple->rdata.type, zonediff,
6399                                   zone_keys, nkeys, now, ISC_FALSE);
6400                 if (result != ISC_R_SUCCESS) {
6401                         dns_zone_log(zone, ISC_LOG_ERROR,
6402                                      "update_sigs:del_sigs -> %s",
6403                                      dns_result_totext(result));
6404                         return (result);
6405                 }
6406                 result = add_sigs(db, version, &tuple->name,
6407                                   tuple->rdata.type, zonediff->diff,
6408                                   zone_keys, nkeys, zone->mctx, inception,
6409                                   expire, check_ksk, keyset_kskonly);
6410                 if (result != ISC_R_SUCCESS) {
6411                         dns_zone_log(zone, ISC_LOG_ERROR,
6412                                      "update_sigs:add_sigs -> %s",
6413                                      dns_result_totext(result));
6414                         return (result);
6415                 }
6416
6417                 do {
6418                         dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
6419                         while (next != NULL &&
6420                                (tuple->rdata.type != next->rdata.type ||
6421                                 !dns_name_equal(&tuple->name, &next->name)))
6422                                 next = ISC_LIST_NEXT(next, link);
6423                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
6424                         dns_diff_appendminimal(zonediff->diff, &tuple);
6425                         INSIST(tuple == NULL);
6426                         tuple = next;
6427                 } while (tuple != NULL);
6428         }
6429         return (ISC_R_SUCCESS);
6430 }
6431
6432 /*
6433  * Incrementally build and sign a new NSEC3 chain using the parameters
6434  * requested.
6435  */
6436 static void
6437 zone_nsec3chain(dns_zone_t *zone) {
6438         const char *me = "zone_nsec3chain";
6439         dns_db_t *db = NULL;
6440         dns_dbnode_t *node = NULL;
6441         dns_dbversion_t *version = NULL;
6442         dns_diff_t _sig_diff;
6443         dns_diff_t nsec_diff;
6444         dns_diff_t nsec3_diff;
6445         dns_diff_t param_diff;
6446         zonediff_t zonediff;
6447         dns_fixedname_t fixed;
6448         dns_fixedname_t nextfixed;
6449         dns_name_t *name, *nextname;
6450         dns_rdataset_t rdataset;
6451         dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
6452         dns_nsec3chainlist_t cleanup;
6453         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6454         isc_int32_t signatures;
6455         isc_boolean_t check_ksk, keyset_kskonly;
6456         isc_boolean_t delegation;
6457         isc_boolean_t first;
6458         isc_result_t result;
6459         isc_stdtime_t now, inception, soaexpire, expire;
6460         isc_uint32_t jitter;
6461         unsigned int i;
6462         unsigned int nkeys = 0;
6463         isc_uint32_t nodes;
6464         isc_boolean_t unsecure = ISC_FALSE;
6465         isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
6466         isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
6467         dns_rdatasetiter_t *iterator = NULL;
6468         isc_boolean_t buildnsecchain;
6469         isc_boolean_t updatensec = ISC_FALSE;
6470         dns_rdatatype_t privatetype = zone->privatetype;
6471
6472         ENTER;
6473
6474         dns_rdataset_init(&rdataset);
6475         dns_fixedname_init(&fixed);
6476         name = dns_fixedname_name(&fixed);
6477         dns_fixedname_init(&nextfixed);
6478         nextname = dns_fixedname_name(&nextfixed);
6479         dns_diff_init(zone->mctx, &param_diff);
6480         dns_diff_init(zone->mctx, &nsec3_diff);
6481         dns_diff_init(zone->mctx, &nsec_diff);
6482         dns_diff_init(zone->mctx, &_sig_diff);
6483         _sig_diff.resign = zone->sigresigninginterval;
6484         zonediff_init(&zonediff, &_sig_diff);
6485         ISC_LIST_INIT(cleanup);
6486
6487         /*
6488          * Updates are disabled.  Pause for 5 minutes.
6489          */
6490         if (zone->update_disabled) {
6491                 result = ISC_R_FAILURE;
6492                 goto failure;
6493         }
6494
6495         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6496         dns_db_attach(zone->db, &db);
6497         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6498
6499         result = dns_db_newversion(db, &version);
6500         if (result != ISC_R_SUCCESS) {
6501                 dns_zone_log(zone, ISC_LOG_ERROR,
6502                              "zone_nsec3chain:dns_db_newversion -> %s",
6503                              dns_result_totext(result));
6504                 goto failure;
6505         }
6506
6507         result = find_zone_keys(zone, db, version, zone->mctx,
6508                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
6509         if (result != ISC_R_SUCCESS) {
6510                 dns_zone_log(zone, ISC_LOG_ERROR,
6511                              "zone_nsec3chain:find_zone_keys -> %s",
6512                              dns_result_totext(result));
6513                 goto failure;
6514         }
6515
6516         isc_stdtime_get(&now);
6517         inception = now - 3600; /* Allow for clock skew. */
6518         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6519
6520         /*
6521          * Spread out signatures over time if they happen to be
6522          * clumped.  We don't do this for each add_sigs() call as
6523          * we still want some clustering to occur.
6524          */
6525         isc_random_get(&jitter);
6526         expire = soaexpire - jitter % 3600;
6527
6528         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6529         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6530
6531         /*
6532          * We keep pulling nodes off each iterator in turn until
6533          * we have no more nodes to pull off or we reach the limits
6534          * for this quantum.
6535          */
6536         nodes = zone->nodes;
6537         signatures = zone->signatures;
6538         LOCK_ZONE(zone);
6539         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6540         UNLOCK_ZONE(zone);
6541         first = ISC_TRUE;
6542
6543         if (nsec3chain != NULL)
6544                 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6545         /*
6546          * Generate new NSEC3 chains first.
6547          */
6548         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6549                 LOCK_ZONE(zone);
6550                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6551
6552                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6553                 if (nsec3chain->done || nsec3chain->db != zone->db) {
6554                         ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
6555                         ISC_LIST_APPEND(cleanup, nsec3chain, link);
6556                 }
6557                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6558                 UNLOCK_ZONE(zone);
6559                 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
6560                         goto next_addchain;
6561
6562                 /*
6563                  * Possible future db.
6564                  */
6565                 if (nsec3chain->db != db) {
6566                         goto next_addchain;
6567                 }
6568
6569                 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
6570                         goto next_addchain;
6571
6572                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6573
6574                 if (nsec3chain->delete_nsec) {
6575                         delegation = ISC_FALSE;
6576                         dns_dbiterator_pause(nsec3chain->dbiterator);
6577                         CHECK(delete_nsec(db, version, node, name, &nsec_diff));
6578                         goto next_addnode;
6579                 }
6580                 /*
6581                  * On the first pass we need to check if the current node
6582                  * has not been obscured.
6583                  */
6584                 delegation = ISC_FALSE;
6585                 unsecure = ISC_FALSE;
6586                 if (first) {
6587                         dns_fixedname_t ffound;
6588                         dns_name_t *found;
6589                         dns_fixedname_init(&ffound);
6590                         found = dns_fixedname_name(&ffound);
6591                         result = dns_db_find(db, name, version,
6592                                              dns_rdatatype_soa,
6593                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6594                                              NULL, NULL);
6595                         if ((result == DNS_R_DELEGATION ||
6596                             result == DNS_R_DNAME) &&
6597                             !dns_name_equal(name, found)) {
6598                                 /*
6599                                  * Remember the obscuring name so that
6600                                  * we skip all obscured names.
6601                                  */
6602                                 dns_name_copy(found, name, NULL);
6603                                 delegation = ISC_TRUE;
6604                                 goto next_addnode;
6605                         }
6606                 }
6607
6608                 /*
6609                  * Check to see if this is a bottom of zone node.
6610                  */
6611                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6612                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
6613                         goto next_addnode;
6614                 if (result != ISC_R_SUCCESS)
6615                         goto failure;
6616
6617                 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
6618                         ISC_FALSE;
6619                 for (result = dns_rdatasetiter_first(iterator);
6620                      result == ISC_R_SUCCESS;
6621                      result = dns_rdatasetiter_next(iterator)) {
6622                         dns_rdatasetiter_current(iterator, &rdataset);
6623                         INSIST(rdataset.type != dns_rdatatype_nsec3);
6624                         if (rdataset.type == dns_rdatatype_soa)
6625                                 seen_soa = ISC_TRUE;
6626                         else if (rdataset.type == dns_rdatatype_ns)
6627                                 seen_ns = ISC_TRUE;
6628                         else if (rdataset.type == dns_rdatatype_dname)
6629                                 seen_dname = ISC_TRUE;
6630                         else if (rdataset.type == dns_rdatatype_ds)
6631                                 seen_ds = ISC_TRUE;
6632                         else if (rdataset.type == dns_rdatatype_nsec)
6633                                 seen_nsec = ISC_TRUE;
6634                         dns_rdataset_disassociate(&rdataset);
6635                 }
6636                 dns_rdatasetiter_destroy(&iterator);
6637                 /*
6638                  * Is there a NSEC chain than needs to be cleaned up?
6639                  */
6640                 if (seen_nsec)
6641                         nsec3chain->seen_nsec = ISC_TRUE;
6642                 if (seen_ns && !seen_soa && !seen_ds)
6643                         unsecure = ISC_TRUE;
6644                 if ((seen_ns && !seen_soa) || seen_dname)
6645                         delegation = ISC_TRUE;
6646
6647                 /*
6648                  * Process one node.
6649                  */
6650                 dns_dbiterator_pause(nsec3chain->dbiterator);
6651                 result = dns_nsec3_addnsec3(db, version, name,
6652                                             &nsec3chain->nsec3param,
6653                                             zone->minimum, unsecure,
6654                                             &nsec3_diff);
6655                 if (result != ISC_R_SUCCESS) {
6656                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6657                                      "dns_nsec3_addnsec3 -> %s",
6658                                      dns_result_totext(result));
6659                         goto failure;
6660                 }
6661
6662                 /*
6663                  * Treat each call to dns_nsec3_addnsec3() as if it's cost is
6664                  * two signatures.  Additionally there will, in general, be
6665                  * two signature generated below.
6666                  *
6667                  * If we are only changing the optout flag the cost is half
6668                  * that of the cost of generating a completely new chain.
6669                  */
6670                 signatures -= 4;
6671
6672                 /*
6673                  * Go onto next node.
6674                  */
6675  next_addnode:
6676                 first = ISC_FALSE;
6677                 dns_db_detachnode(db, &node);
6678                 do {
6679                         result = dns_dbiterator_next(nsec3chain->dbiterator);
6680
6681                         if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
6682                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6683                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6684                                                        ISC_FALSE, privatetype,
6685                                                        &param_diff));
6686                                 LOCK_ZONE(zone);
6687                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6688                                                 link);
6689                                 UNLOCK_ZONE(zone);
6690                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6691                                 goto next_addchain;
6692                         }
6693                         if (result == ISC_R_NOMORE) {
6694                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6695                                 if (nsec3chain->seen_nsec) {
6696                                         CHECK(fixup_nsec3param(db, version,
6697                                                                nsec3chain,
6698                                                                ISC_TRUE,
6699                                                                privatetype,
6700                                                                &param_diff));
6701                                         nsec3chain->delete_nsec = ISC_TRUE;
6702                                         goto same_addchain;
6703                                 }
6704                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6705                                                        ISC_FALSE, privatetype,
6706                                                        &param_diff));
6707                                 LOCK_ZONE(zone);
6708                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6709                                                 link);
6710                                 UNLOCK_ZONE(zone);
6711                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6712                                 goto next_addchain;
6713                         } else if (result != ISC_R_SUCCESS) {
6714                                 dns_zone_log(zone, ISC_LOG_ERROR,
6715                                              "zone_nsec3chain:"
6716                                              "dns_dbiterator_next -> %s",
6717                                              dns_result_totext(result));
6718                                 goto failure;
6719                         } else if (delegation) {
6720                                 dns_dbiterator_current(nsec3chain->dbiterator,
6721                                                        &node, nextname);
6722                                 dns_db_detachnode(db, &node);
6723                                 if (!dns_name_issubdomain(nextname, name))
6724                                         break;
6725                         } else
6726                                 break;
6727                 } while (1);
6728                 continue;
6729
6730  same_addchain:
6731                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6732                 first = ISC_TRUE;
6733                 continue;
6734
6735  next_addchain:
6736                 dns_dbiterator_pause(nsec3chain->dbiterator);
6737                 nsec3chain = nextnsec3chain;
6738                 first = ISC_TRUE;
6739                 if (nsec3chain != NULL)
6740                         nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6741         }
6742
6743         /*
6744          * Process removals.
6745          */
6746         LOCK_ZONE(zone);
6747         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6748         UNLOCK_ZONE(zone);
6749         first = ISC_TRUE;
6750         buildnsecchain = ISC_FALSE;
6751         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6752                 LOCK_ZONE(zone);
6753                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6754                 UNLOCK_ZONE(zone);
6755
6756                 if (nsec3chain->db != db)
6757                         goto next_removechain;
6758
6759                 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
6760                         goto next_removechain;
6761
6762                 /*
6763                  * Work out if we need to build a NSEC chain as a consequence
6764                  * of removing this NSEC3 chain.
6765                  */
6766                 if (first && !updatensec &&
6767                     (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
6768                 {
6769                         result = need_nsec_chain(db, version,
6770                                                  &nsec3chain->nsec3param,
6771                                                  &buildnsecchain);
6772                         if (result != ISC_R_SUCCESS) {
6773                                 dns_zone_log(zone, ISC_LOG_ERROR,
6774                                              "zone_nsec3chain:"
6775                                              "need_nsec_chain -> %s",
6776                                              dns_result_totext(result));
6777                                 goto failure;
6778                         }
6779                 }
6780
6781                 if (first)
6782                         dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
6783                                      "buildnsecchain = %u\n", buildnsecchain);
6784
6785                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6786                 delegation = ISC_FALSE;
6787
6788                 if (!buildnsecchain) {
6789                         /*
6790                          * Delete the NSECPARAM record that matches this chain.
6791                          */
6792                         if (first) {
6793                                 result = fixup_nsec3param(db, version,
6794                                                           nsec3chain,
6795                                                           ISC_TRUE, privatetype,
6796                                                           &param_diff);
6797                                 if (result != ISC_R_SUCCESS) {
6798                                         dns_zone_log(zone, ISC_LOG_ERROR,
6799                                                      "zone_nsec3chain:"
6800                                                      "fixup_nsec3param -> %s",
6801                                                      dns_result_totext(result));
6802                                         goto failure;
6803                                 }
6804                         }
6805
6806                         /*
6807                          *  Delete the NSEC3 records.
6808                          */
6809                         result = deletematchingnsec3(db, version, node, name,
6810                                                      &nsec3chain->nsec3param,
6811                                                      &nsec3_diff);
6812                         if (result != ISC_R_SUCCESS) {
6813                                 dns_zone_log(zone, ISC_LOG_ERROR,
6814                                              "zone_nsec3chain:"
6815                                              "deletematchingnsec3 -> %s",
6816                                              dns_result_totext(result));
6817                                 goto failure;
6818                         }
6819                         goto next_removenode;
6820                 }
6821
6822                 if (first) {
6823                         dns_fixedname_t ffound;
6824                         dns_name_t *found;
6825                         dns_fixedname_init(&ffound);
6826                         found = dns_fixedname_name(&ffound);
6827                         result = dns_db_find(db, name, version,
6828                                              dns_rdatatype_soa,
6829                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6830                                              NULL, NULL);
6831                         if ((result == DNS_R_DELEGATION ||
6832                              result == DNS_R_DNAME) &&
6833                             !dns_name_equal(name, found)) {
6834                                 /*
6835                                  * Remember the obscuring name so that
6836                                  * we skip all obscured names.
6837                                  */
6838                                 dns_name_copy(found, name, NULL);
6839                                 delegation = ISC_TRUE;
6840                                 goto next_removenode;
6841                         }
6842                 }
6843
6844                 /*
6845                  * Check to see if this is a bottom of zone node.
6846                  */
6847                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6848                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
6849                         goto next_removenode;
6850                 if (result != ISC_R_SUCCESS)
6851                         goto failure;
6852
6853                 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
6854                         seen_rr = ISC_FALSE;
6855                 for (result = dns_rdatasetiter_first(iterator);
6856                      result == ISC_R_SUCCESS;
6857                      result = dns_rdatasetiter_next(iterator)) {
6858                         dns_rdatasetiter_current(iterator, &rdataset);
6859                         if (rdataset.type == dns_rdatatype_soa)
6860                                 seen_soa = ISC_TRUE;
6861                         else if (rdataset.type == dns_rdatatype_ns)
6862                                 seen_ns = ISC_TRUE;
6863                         else if (rdataset.type == dns_rdatatype_dname)
6864                                 seen_dname = ISC_TRUE;
6865                         else if (rdataset.type == dns_rdatatype_nsec)
6866                                 seen_nsec = ISC_TRUE;
6867                         else if (rdataset.type == dns_rdatatype_nsec3)
6868                                 seen_nsec3 = ISC_TRUE;
6869                         if (rdataset.type != dns_rdatatype_rrsig)
6870                                 seen_rr = ISC_TRUE;
6871                         dns_rdataset_disassociate(&rdataset);
6872                 }
6873                 dns_rdatasetiter_destroy(&iterator);
6874
6875                 if (!seen_rr || seen_nsec3 || seen_nsec)
6876                         goto next_removenode;
6877                 if ((seen_ns && !seen_soa) || seen_dname)
6878                         delegation = ISC_TRUE;
6879
6880                 /*
6881                  * Add a NSEC record except at the origin.
6882                  */
6883                 if (!dns_name_equal(name, dns_db_origin(db))) {
6884                         dns_dbiterator_pause(nsec3chain->dbiterator);
6885                         CHECK(add_nsec(db, version, name, node, zone->minimum,
6886                                        delegation, &nsec_diff));
6887                 }
6888
6889  next_removenode:
6890                 first = ISC_FALSE;
6891                 dns_db_detachnode(db, &node);
6892                 do {
6893                         result = dns_dbiterator_next(nsec3chain->dbiterator);
6894                         if (result == ISC_R_NOMORE && buildnsecchain) {
6895                                 /*
6896                                  * The NSEC chain should now be built.
6897                                  * We can now remove the NSEC3 chain.
6898                                  */
6899                                 updatensec = ISC_TRUE;
6900                                 goto same_removechain;
6901                         }
6902                         if (result == ISC_R_NOMORE) {
6903                                 LOCK_ZONE(zone);
6904                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6905                                                 link);
6906                                 UNLOCK_ZONE(zone);
6907                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6908                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6909                                 result = fixup_nsec3param(db, version,
6910                                                           nsec3chain, ISC_FALSE,
6911                                                           privatetype,
6912                                                           &param_diff);
6913                                 if (result != ISC_R_SUCCESS) {
6914                                         dns_zone_log(zone, ISC_LOG_ERROR,
6915                                                      "zone_nsec3chain:"
6916                                                      "fixup_nsec3param -> %s",
6917                                                      dns_result_totext(result));
6918                                         goto failure;
6919                                 }
6920                                 goto next_removechain;
6921                         } else if (result != ISC_R_SUCCESS) {
6922                                 dns_zone_log(zone, ISC_LOG_ERROR,
6923                                              "zone_nsec3chain:"
6924                                              "dns_dbiterator_next -> %s",
6925                                              dns_result_totext(result));
6926                                 goto failure;
6927                         } else if (delegation) {
6928                                 dns_dbiterator_current(nsec3chain->dbiterator,
6929                                                        &node, nextname);
6930                                 dns_db_detachnode(db, &node);
6931                                 if (!dns_name_issubdomain(nextname, name))
6932                                         break;
6933                         } else
6934                                 break;
6935                 } while (1);
6936                 continue;
6937
6938  same_removechain:
6939                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6940                 buildnsecchain = ISC_FALSE;
6941                 first = ISC_TRUE;
6942                 continue;
6943
6944  next_removechain:
6945                 dns_dbiterator_pause(nsec3chain->dbiterator);
6946                 nsec3chain = nextnsec3chain;
6947                 first = ISC_TRUE;
6948         }
6949
6950         /*
6951          * We may need to update the NSEC/NSEC3 records for the zone apex.
6952          */
6953         if (!ISC_LIST_EMPTY(param_diff.tuples)) {
6954                 isc_boolean_t rebuild_nsec = ISC_FALSE,
6955                               rebuild_nsec3 = ISC_FALSE;
6956                 result = dns_db_getoriginnode(db, &node);
6957                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6958                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6959                 if (result != ISC_R_SUCCESS) {
6960                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6961                                      "dns_db_allrdatasets -> %s",
6962                                      dns_result_totext(result));
6963                         goto failure;
6964                 }
6965                 for (result = dns_rdatasetiter_first(iterator);
6966                      result == ISC_R_SUCCESS;
6967                      result = dns_rdatasetiter_next(iterator)) {
6968                         dns_rdatasetiter_current(iterator, &rdataset);
6969                         if (rdataset.type == dns_rdatatype_nsec)
6970                                 rebuild_nsec = ISC_TRUE;
6971                         if (rdataset.type == dns_rdatatype_nsec3param)
6972                                 rebuild_nsec3 = ISC_TRUE;
6973                         dns_rdataset_disassociate(&rdataset);
6974                 }
6975                 dns_rdatasetiter_destroy(&iterator);
6976                 dns_db_detachnode(db, &node);
6977
6978                 if (rebuild_nsec) {
6979                         if (nsec3chain != NULL)
6980                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6981
6982                         result = updatesecure(db, version, &zone->origin,
6983                                               zone->minimum, ISC_TRUE,
6984                                               &nsec_diff);
6985                         if (result != ISC_R_SUCCESS) {
6986                                 dns_zone_log(zone, ISC_LOG_ERROR,
6987                                              "zone_nsec3chain:"
6988                                              "updatesecure -> %s",
6989                                              dns_result_totext(result));
6990                                 goto failure;
6991                         }
6992                 }
6993
6994                 if (rebuild_nsec3) {
6995                         if (nsec3chain != NULL)
6996                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6997
6998                         result = dns_nsec3_addnsec3s(db, version,
6999                                                      dns_db_origin(db),
7000                                                      zone->minimum, ISC_FALSE,
7001                                                      &nsec3_diff);
7002                         if (result != ISC_R_SUCCESS) {
7003                                 dns_zone_log(zone, ISC_LOG_ERROR,
7004                                              "zone_nsec3chain:"
7005                                              "dns_nsec3_addnsec3s -> %s",
7006                                              dns_result_totext(result));
7007                                 goto failure;
7008                         }
7009                 }
7010         }
7011
7012         if (nsec3chain != NULL)
7013                 dns_dbiterator_pause(nsec3chain->dbiterator);
7014
7015         /*
7016          * Add / update signatures for the NSEC3 records.
7017          */
7018         if (nsec3chain != NULL)
7019                 dns_dbiterator_pause(nsec3chain->dbiterator);
7020         result = update_sigs(&nsec3_diff, db, version, zone_keys,
7021                              nkeys, zone, inception, expire, now,
7022                              check_ksk, keyset_kskonly, &zonediff);
7023         if (result != ISC_R_SUCCESS) {
7024                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7025                              "update_sigs -> %s", dns_result_totext(result));
7026                 goto failure;
7027         }
7028
7029         /*
7030          * We have changed the NSEC3PARAM or private RRsets
7031          * above so we need to update the signatures.
7032          */
7033         result = update_sigs(&param_diff, db, version, zone_keys,
7034                              nkeys, zone, inception, expire, now,
7035                              check_ksk, keyset_kskonly, &zonediff);
7036         if (result != ISC_R_SUCCESS) {
7037                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7038                              "update_sigs -> %s", dns_result_totext(result));
7039                 goto failure;
7040         }
7041
7042         if (updatensec) {
7043                 result = updatesecure(db, version, &zone->origin,
7044                                       zone->minimum, ISC_FALSE, &nsec_diff);
7045                 if (result != ISC_R_SUCCESS) {
7046                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7047                                      "updatesecure -> %s",
7048                                      dns_result_totext(result));
7049                         goto failure;
7050                 }
7051         }
7052
7053         result = update_sigs(&nsec_diff, db, version, zone_keys,
7054                              nkeys, zone, inception, expire, now,
7055                              check_ksk, keyset_kskonly, &zonediff);
7056         if (result != ISC_R_SUCCESS) {
7057                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7058                              "update_sigs -> %s", dns_result_totext(result));
7059                 goto failure;
7060         }
7061
7062         /*
7063          * If we made no effective changes to the zone then we can just
7064          * cleanup otherwise we need to increment the serial.
7065          */
7066         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7067                 /*
7068                  * No need to call dns_db_closeversion() here as it is
7069                  * called with commit = ISC_TRUE below.
7070                  */
7071                 goto done;
7072         }
7073
7074         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7075                           &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7076         if (result != ISC_R_SUCCESS) {
7077                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7078                              "del_sigs -> %s", dns_result_totext(result));
7079                 goto failure;
7080         }
7081
7082         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7083                                    zone->updatemethod);
7084         if (result != ISC_R_SUCCESS) {
7085                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7086                              "update_soa_serial -> %s",
7087                              dns_result_totext(result));
7088                 goto failure;
7089         }
7090
7091         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7092                           zonediff.diff, zone_keys, nkeys, zone->mctx,
7093                           inception, soaexpire, check_ksk, keyset_kskonly);
7094         if (result != ISC_R_SUCCESS) {
7095                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7096                              "add_sigs -> %s", dns_result_totext(result));
7097                 goto failure;
7098         }
7099
7100         /* Write changes to journal file. */
7101         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
7102
7103         LOCK_ZONE(zone);
7104         zone_needdump(zone, DNS_DUMP_DELAY);
7105         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7106         UNLOCK_ZONE(zone);
7107
7108  done:
7109         /*
7110          * Pause all iterators so that dns_db_closeversion() can succeed.
7111          */
7112         LOCK_ZONE(zone);
7113         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7114              nsec3chain != NULL;
7115              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7116                 dns_dbiterator_pause(nsec3chain->dbiterator);
7117         UNLOCK_ZONE(zone);
7118
7119         /*
7120          * Everything has succeeded. Commit the changes.
7121          * Unconditionally commit as zonediff.offline not checked above.
7122          */
7123         dns_db_closeversion(db, &version, ISC_TRUE);
7124
7125         /*
7126          * Everything succeeded so we can clean these up now.
7127          */
7128         nsec3chain = ISC_LIST_HEAD(cleanup);
7129         while (nsec3chain != NULL) {
7130                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7131                 dns_db_detach(&nsec3chain->db);
7132                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
7133                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7134                 nsec3chain = ISC_LIST_HEAD(cleanup);
7135         }
7136
7137         set_resigntime(zone);
7138
7139  failure:
7140         if (result != ISC_R_SUCCESS)
7141                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
7142                              dns_result_totext(result));
7143         /*
7144          * On error roll back the current nsec3chain.
7145          */
7146         if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
7147                 if (nsec3chain->done) {
7148                         dns_db_detach(&nsec3chain->db);
7149                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
7150                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7151                 } else {
7152                         result = dns_dbiterator_first(nsec3chain->dbiterator);
7153                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7154                         dns_dbiterator_pause(nsec3chain->dbiterator);
7155                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7156                 }
7157         }
7158
7159         /*
7160          * Rollback the cleanup list.
7161          */
7162         nsec3chain = ISC_LIST_TAIL(cleanup);
7163         while (nsec3chain != NULL) {
7164                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7165                 if (nsec3chain->done) {
7166                         dns_db_detach(&nsec3chain->db);
7167                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
7168                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7169                 } else {
7170                         LOCK_ZONE(zone);
7171                         ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
7172                         UNLOCK_ZONE(zone);
7173                         result = dns_dbiterator_first(nsec3chain->dbiterator);
7174                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7175                         dns_dbiterator_pause(nsec3chain->dbiterator);
7176                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7177                 }
7178                 nsec3chain = ISC_LIST_TAIL(cleanup);
7179         }
7180
7181         LOCK_ZONE(zone);
7182         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7183              nsec3chain != NULL;
7184              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7185                 dns_dbiterator_pause(nsec3chain->dbiterator);
7186         UNLOCK_ZONE(zone);
7187
7188         dns_diff_clear(&param_diff);
7189         dns_diff_clear(&nsec3_diff);
7190         dns_diff_clear(&nsec_diff);
7191         dns_diff_clear(&_sig_diff);
7192
7193         if (iterator != NULL)
7194                 dns_rdatasetiter_destroy(&iterator);
7195
7196         for (i = 0; i < nkeys; i++)
7197                 dst_key_free(&zone_keys[i]);
7198
7199         if (node != NULL)
7200                 dns_db_detachnode(db, &node);
7201         if (version != NULL) {
7202                 dns_db_closeversion(db, &version, ISC_FALSE);
7203                 dns_db_detach(&db);
7204         } else if (db != NULL)
7205                 dns_db_detach(&db);
7206
7207         LOCK_ZONE(zone);
7208         if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
7209                 isc_interval_t i;
7210                 if (zone->update_disabled || result != ISC_R_SUCCESS)
7211                         isc_interval_set(&i, 60, 0);            /* 1 minute */
7212                 else
7213                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
7214                 isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
7215         } else
7216                 isc_time_settoepoch(&zone->nsec3chaintime);
7217         UNLOCK_ZONE(zone);
7218 }
7219
7220 static isc_result_t
7221 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7222         dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
7223         isc_uint16_t keyid, dns_diff_t *diff)
7224 {
7225         dns_rdata_rrsig_t rrsig;
7226         dns_rdataset_t rdataset;
7227         dns_rdatasetiter_t *iterator = NULL;
7228         isc_result_t result;
7229
7230         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7231         if (result != ISC_R_SUCCESS) {
7232                 if (result == ISC_R_NOTFOUND)
7233                         result = ISC_R_SUCCESS;
7234                 return (result);
7235         }
7236
7237         dns_rdataset_init(&rdataset);
7238         for (result = dns_rdatasetiter_first(iterator);
7239              result == ISC_R_SUCCESS;
7240              result = dns_rdatasetiter_next(iterator)) {
7241                 dns_rdatasetiter_current(iterator, &rdataset);
7242                 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
7243                         for (result = dns_rdataset_first(&rdataset);
7244                              result == ISC_R_SUCCESS;
7245                              result = dns_rdataset_next(&rdataset)) {
7246                                 dns_rdata_t rdata = DNS_RDATA_INIT;
7247                                 dns_rdataset_current(&rdataset, &rdata);
7248                                 CHECK(update_one_rr(db, version, diff,
7249                                                     DNS_DIFFOP_DEL, name,
7250                                                     rdataset.ttl, &rdata));
7251                         }
7252                         if (result != ISC_R_NOMORE)
7253                                 goto failure;
7254                         dns_rdataset_disassociate(&rdataset);
7255                         continue;
7256                 }
7257                 if (rdataset.type != dns_rdatatype_rrsig) {
7258                         dns_rdataset_disassociate(&rdataset);
7259                         continue;
7260                 }
7261                 for (result = dns_rdataset_first(&rdataset);
7262                      result == ISC_R_SUCCESS;
7263                      result = dns_rdataset_next(&rdataset)) {
7264                         dns_rdata_t rdata = DNS_RDATA_INIT;
7265                         dns_rdataset_current(&rdataset, &rdata);
7266                         CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
7267                         if (rrsig.algorithm != algorithm ||
7268                             rrsig.keyid != keyid)
7269                                 continue;
7270                         CHECK(update_one_rr(db, version, diff,
7271                                             DNS_DIFFOP_DELRESIGN, name,
7272                                             rdataset.ttl, &rdata));
7273                 }
7274                 dns_rdataset_disassociate(&rdataset);
7275                 if (result != ISC_R_NOMORE)
7276                         break;
7277         }
7278         if (result == ISC_R_NOMORE)
7279                 result = ISC_R_SUCCESS;
7280  failure:
7281         if (dns_rdataset_isassociated(&rdataset))
7282                 dns_rdataset_disassociate(&rdataset);
7283         dns_rdatasetiter_destroy(&iterator);
7284         return (result);
7285 }
7286
7287 /*
7288  * Incrementally sign the zone using the keys requested.
7289  * Builds the NSEC chain if required.
7290  */
7291 static void
7292 zone_sign(dns_zone_t *zone) {
7293         const char *me = "zone_sign";
7294         dns_db_t *db = NULL;
7295         dns_dbnode_t *node = NULL;
7296         dns_dbversion_t *version = NULL;
7297         dns_diff_t _sig_diff;
7298         dns_diff_t post_diff;
7299         zonediff_t zonediff;
7300         dns_fixedname_t fixed;
7301         dns_fixedname_t nextfixed;
7302         dns_name_t *name, *nextname;
7303         dns_rdataset_t rdataset;
7304         dns_signing_t *signing, *nextsigning;
7305         dns_signinglist_t cleanup;
7306         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7307         isc_int32_t signatures;
7308         isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
7309         isc_boolean_t commit = ISC_FALSE;
7310         isc_boolean_t delegation;
7311         isc_boolean_t build_nsec = ISC_FALSE;
7312         isc_boolean_t build_nsec3 = ISC_FALSE;
7313         isc_boolean_t first;
7314         isc_result_t result;
7315         isc_stdtime_t now, inception, soaexpire, expire;
7316         isc_uint32_t jitter;
7317         unsigned int i, j;
7318         unsigned int nkeys = 0;
7319         isc_uint32_t nodes;
7320
7321         ENTER;
7322
7323         dns_rdataset_init(&rdataset);
7324         dns_fixedname_init(&fixed);
7325         name = dns_fixedname_name(&fixed);
7326         dns_fixedname_init(&nextfixed);
7327         nextname = dns_fixedname_name(&nextfixed);
7328         dns_diff_init(zone->mctx, &_sig_diff);
7329         _sig_diff.resign = zone->sigresigninginterval;
7330         dns_diff_init(zone->mctx, &post_diff);
7331         zonediff_init(&zonediff, &_sig_diff);
7332         ISC_LIST_INIT(cleanup);
7333
7334         /*
7335          * Updates are disabled.  Pause for 5 minutes.
7336          */
7337         if (zone->update_disabled) {
7338                 result = ISC_R_FAILURE;
7339                 goto failure;
7340         }
7341
7342         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7343         dns_db_attach(zone->db, &db);
7344         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7345
7346         result = dns_db_newversion(db, &version);
7347         if (result != ISC_R_SUCCESS) {
7348                 dns_zone_log(zone, ISC_LOG_ERROR,
7349                              "zone_sign:dns_db_newversion -> %s",
7350                              dns_result_totext(result));
7351                 goto failure;
7352         }
7353
7354         result = find_zone_keys(zone, db, version, zone->mctx,
7355                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7356         if (result != ISC_R_SUCCESS) {
7357                 dns_zone_log(zone, ISC_LOG_ERROR,
7358                              "zone_sign:find_zone_keys -> %s",
7359                              dns_result_totext(result));
7360                 goto failure;
7361         }
7362
7363         isc_stdtime_get(&now);
7364         inception = now - 3600; /* Allow for clock skew. */
7365         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
7366
7367         /*
7368          * Spread out signatures over time if they happen to be
7369          * clumped.  We don't do this for each add_sigs() call as
7370          * we still want some clustering to occur.
7371          */
7372         isc_random_get(&jitter);
7373         expire = soaexpire - jitter % 3600;
7374
7375         /*
7376          * We keep pulling nodes off each iterator in turn until
7377          * we have no more nodes to pull off or we reach the limits
7378          * for this quantum.
7379          */
7380         nodes = zone->nodes;
7381         signatures = zone->signatures;
7382         signing = ISC_LIST_HEAD(zone->signing);
7383         first = ISC_TRUE;
7384
7385         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7386         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7387
7388         /* Determine which type of chain to build */
7389         CHECK(dns_private_chains(db, version, zone->privatetype,
7390                                  &build_nsec, &build_nsec3));
7391
7392         /* If neither chain is found, default to NSEC */
7393         if (!build_nsec && !build_nsec3)
7394                 build_nsec = ISC_TRUE;
7395
7396         while (signing != NULL && nodes-- > 0 && signatures > 0) {
7397                 nextsigning = ISC_LIST_NEXT(signing, link);
7398
7399                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7400                 if (signing->done || signing->db != zone->db) {
7401                         /*
7402                          * The zone has been reloaded.  We will have
7403                          * created new signings as part of the reload
7404                          * process so we can destroy this one.
7405                          */
7406                         ISC_LIST_UNLINK(zone->signing, signing, link);
7407                         ISC_LIST_APPEND(cleanup, signing, link);
7408                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7409                         goto next_signing;
7410                 }
7411                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7412
7413                 if (signing->db != db)
7414                         goto next_signing;
7415
7416                 delegation = ISC_FALSE;
7417
7418                 if (first && signing->delete) {
7419                         /*
7420                          * Remove the key we are deleting from consideration.
7421                          */
7422                         for (i = 0, j = 0; i < nkeys; i++) {
7423                                 /*
7424                                  * Find the key we want to remove.
7425                                  */
7426                                 if (ALG(zone_keys[i]) == signing->algorithm &&
7427                                     dst_key_id(zone_keys[i]) == signing->keyid)
7428                                 {
7429                                         if (KSK(zone_keys[i]))
7430                                                 dst_key_free(&zone_keys[i]);
7431                                         continue;
7432                                 }
7433                                 zone_keys[j] = zone_keys[i];
7434                                 j++;
7435                         }
7436                         nkeys = j;
7437                 }
7438
7439                 dns_dbiterator_current(signing->dbiterator, &node, name);
7440
7441                 if (signing->delete) {
7442                         dns_dbiterator_pause(signing->dbiterator);
7443                         CHECK(del_sig(db, version, name, node, nkeys,
7444                                       signing->algorithm, signing->keyid,
7445                                       zonediff.diff));
7446                 }
7447
7448                 /*
7449                  * On the first pass we need to check if the current node
7450                  * has not been obscured.
7451                  */
7452                 if (first) {
7453                         dns_fixedname_t ffound;
7454                         dns_name_t *found;
7455                         dns_fixedname_init(&ffound);
7456                         found = dns_fixedname_name(&ffound);
7457                         result = dns_db_find(db, name, version,
7458                                              dns_rdatatype_soa,
7459                                              DNS_DBFIND_NOWILD, 0, NULL, found,
7460                                              NULL, NULL);
7461                         if ((result == DNS_R_DELEGATION ||
7462                             result == DNS_R_DNAME) &&
7463                             !dns_name_equal(name, found)) {
7464                                 /*
7465                                  * Remember the obscuring name so that
7466                                  * we skip all obscured names.
7467                                  */
7468                                 dns_name_copy(found, name, NULL);
7469                                 delegation = ISC_TRUE;
7470                                 goto next_node;
7471                         }
7472                 }
7473
7474                 /*
7475                  * Process one node.
7476                  */
7477                 dns_dbiterator_pause(signing->dbiterator);
7478                 for (i = 0; i < nkeys; i++) {
7479                         isc_boolean_t both = ISC_FALSE;
7480
7481                         /*
7482                          * Find the keys we want to sign with.
7483                          */
7484                         if (!dst_key_isprivate(zone_keys[i]))
7485                                 continue;
7486
7487                         /*
7488                          * When adding look for the specific key.
7489                          */
7490                         if (!signing->delete &&
7491                             (dst_key_alg(zone_keys[i]) != signing->algorithm ||
7492                              dst_key_id(zone_keys[i]) != signing->keyid))
7493                                 continue;
7494
7495                         /*
7496                          * When deleting make sure we are properly signed
7497                          * with the algorithm that was being removed.
7498                          */
7499                         if (signing->delete &&
7500                             ALG(zone_keys[i]) != signing->algorithm)
7501                                 continue;
7502
7503                         /*
7504                          * Do we do KSK processing?
7505                          */
7506                         if (check_ksk && !REVOKE(zone_keys[i])) {
7507                                 isc_boolean_t have_ksk, have_nonksk;
7508                                 if (KSK(zone_keys[i])) {
7509                                         have_ksk = ISC_TRUE;
7510                                         have_nonksk = ISC_FALSE;
7511                                 } else {
7512                                         have_ksk = ISC_FALSE;
7513                                         have_nonksk = ISC_TRUE;
7514                                 }
7515                                 for (j = 0; j < nkeys; j++) {
7516                                         if (j == i ||
7517                                             ALG(zone_keys[i]) !=
7518                                             ALG(zone_keys[j]))
7519                                                 continue;
7520                                         if (REVOKE(zone_keys[j]))
7521                                                 continue;
7522                                         if (KSK(zone_keys[j]))
7523                                                 have_ksk = ISC_TRUE;
7524                                         else
7525                                                 have_nonksk = ISC_TRUE;
7526                                         both = have_ksk && have_nonksk;
7527                                         if (both)
7528                                                 break;
7529                                 }
7530                         }
7531                         if (both || REVOKE(zone_keys[i]))
7532                                 is_ksk = KSK(zone_keys[i]);
7533                         else
7534                                 is_ksk = ISC_FALSE;
7535
7536                         CHECK(sign_a_node(db, name, node, version, build_nsec3,
7537                                           build_nsec, zone_keys[i], inception,
7538                                           expire, zone->minimum, is_ksk,
7539                                           ISC_TF(both && keyset_kskonly),
7540                                           &delegation, zonediff.diff,
7541                                           &signatures, zone->mctx));
7542                         /*
7543                          * If we are adding we are done.  Look for other keys
7544                          * of the same algorithm if deleting.
7545                          */
7546                         if (!signing->delete)
7547                                 break;
7548                 }
7549
7550                 /*
7551                  * Go onto next node.
7552                  */
7553  next_node:
7554                 first = ISC_FALSE;
7555                 dns_db_detachnode(db, &node);
7556                 do {
7557                         result = dns_dbiterator_next(signing->dbiterator);
7558                         if (result == ISC_R_NOMORE) {
7559                                 ISC_LIST_UNLINK(zone->signing, signing, link);
7560                                 ISC_LIST_APPEND(cleanup, signing, link);
7561                                 dns_dbiterator_pause(signing->dbiterator);
7562                                 if (nkeys != 0 && build_nsec) {
7563                                         /*
7564                                          * We have finished regenerating the
7565                                          * zone with a zone signing key.
7566                                          * The NSEC chain is now complete and
7567                                          * there is a full set of signatures
7568                                          * for the zone.  We can now clear the
7569                                          * OPT bit from the NSEC record.
7570                                          */
7571                                         result = updatesecure(db, version,
7572                                                               &zone->origin,
7573                                                               zone->minimum,
7574                                                               ISC_FALSE,
7575                                                               &post_diff);
7576                                         if (result != ISC_R_SUCCESS) {
7577                                                 dns_zone_log(zone,
7578                                                              ISC_LOG_ERROR,
7579                                                     "updatesecure -> %s",
7580                                                     dns_result_totext(result));
7581                                                 goto failure;
7582                                         }
7583                                 }
7584                                 result = updatesignwithkey(zone, signing,
7585                                                            version,
7586                                                            build_nsec3,
7587                                                            zone->minimum,
7588                                                            &post_diff);
7589                                 if (result != ISC_R_SUCCESS) {
7590                                         dns_zone_log(zone, ISC_LOG_ERROR,
7591                                                      "updatesignwithkey -> %s",
7592                                                      dns_result_totext(result));
7593                                         goto failure;
7594                                 }
7595                                 build_nsec = ISC_FALSE;
7596                                 goto next_signing;
7597                         } else if (result != ISC_R_SUCCESS) {
7598                                 dns_zone_log(zone, ISC_LOG_ERROR,
7599                                         "zone_sign:dns_dbiterator_next -> %s",
7600                                              dns_result_totext(result));
7601                                 goto failure;
7602                         } else if (delegation) {
7603                                 dns_dbiterator_current(signing->dbiterator,
7604                                                        &node, nextname);
7605                                 dns_db_detachnode(db, &node);
7606                                 if (!dns_name_issubdomain(nextname, name))
7607                                         break;
7608                         } else
7609                                 break;
7610                 } while (1);
7611                 continue;
7612
7613  next_signing:
7614                 dns_dbiterator_pause(signing->dbiterator);
7615                 signing = nextsigning;
7616                 first = ISC_TRUE;
7617         }
7618
7619         if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
7620                 result = update_sigs(&post_diff, db, version, zone_keys,
7621                                      nkeys, zone, inception, expire, now,
7622                                      check_ksk, keyset_kskonly, &zonediff);
7623                 if (result != ISC_R_SUCCESS) {
7624                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
7625                                      "update_sigs -> %s",
7626                                      dns_result_totext(result));
7627                         goto failure;
7628                 }
7629         }
7630
7631         /*
7632          * Have we changed anything?
7633          */
7634         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7635                 if (zonediff.offline)
7636                         commit = ISC_TRUE;
7637                 result = ISC_R_SUCCESS;
7638                 goto pauseall;
7639         }
7640
7641         commit = ISC_TRUE;
7642
7643         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7644                           &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7645         if (result != ISC_R_SUCCESS) {
7646                 dns_zone_log(zone, ISC_LOG_ERROR,
7647                              "zone_sign:del_sigs -> %s",
7648                              dns_result_totext(result));
7649                 goto failure;
7650         }
7651
7652         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7653                                    zone->updatemethod);
7654         if (result != ISC_R_SUCCESS) {
7655                 dns_zone_log(zone, ISC_LOG_ERROR,
7656                              "zone_sign:update_soa_serial -> %s",
7657                              dns_result_totext(result));
7658                 goto failure;
7659         }
7660
7661         /*
7662          * Generate maximum life time signatures so that the above loop
7663          * termination is sensible.
7664          */
7665         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7666                           zonediff.diff, zone_keys, nkeys, zone->mctx,
7667                           inception, soaexpire, check_ksk, keyset_kskonly);
7668         if (result != ISC_R_SUCCESS) {
7669                 dns_zone_log(zone, ISC_LOG_ERROR,
7670                              "zone_sign:add_sigs -> %s",
7671                              dns_result_totext(result));
7672                 goto failure;
7673         }
7674
7675         /*
7676          * Write changes to journal file.
7677          */
7678         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
7679
7680  pauseall:
7681         /*
7682          * Pause all iterators so that dns_db_closeversion() can succeed.
7683          */
7684         for (signing = ISC_LIST_HEAD(zone->signing);
7685              signing != NULL;
7686              signing = ISC_LIST_NEXT(signing, link))
7687                 dns_dbiterator_pause(signing->dbiterator);
7688
7689         for (signing = ISC_LIST_HEAD(cleanup);
7690              signing != NULL;
7691              signing = ISC_LIST_NEXT(signing, link))
7692                 dns_dbiterator_pause(signing->dbiterator);
7693
7694         /*
7695          * Everything has succeeded. Commit the changes.
7696          */
7697         dns_db_closeversion(db, &version, commit);
7698
7699         /*
7700          * Everything succeeded so we can clean these up now.
7701          */
7702         signing = ISC_LIST_HEAD(cleanup);
7703         while (signing != NULL) {
7704                 ISC_LIST_UNLINK(cleanup, signing, link);
7705                 dns_db_detach(&signing->db);
7706                 dns_dbiterator_destroy(&signing->dbiterator);
7707                 isc_mem_put(zone->mctx, signing, sizeof *signing);
7708                 signing = ISC_LIST_HEAD(cleanup);
7709         }
7710
7711         set_resigntime(zone);
7712
7713         if (commit) {
7714                 LOCK_ZONE(zone);
7715                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7716                 zone_needdump(zone, DNS_DUMP_DELAY);
7717                 UNLOCK_ZONE(zone);
7718         }
7719
7720  failure:
7721         /*
7722          * Rollback the cleanup list.
7723          */
7724         signing = ISC_LIST_HEAD(cleanup);
7725         while (signing != NULL) {
7726                 ISC_LIST_UNLINK(cleanup, signing, link);
7727                 ISC_LIST_PREPEND(zone->signing, signing, link);
7728                 dns_dbiterator_first(signing->dbiterator);
7729                 dns_dbiterator_pause(signing->dbiterator);
7730                 signing = ISC_LIST_HEAD(cleanup);
7731         }
7732
7733         for (signing = ISC_LIST_HEAD(zone->signing);
7734              signing != NULL;
7735              signing = ISC_LIST_NEXT(signing, link))
7736                 dns_dbiterator_pause(signing->dbiterator);
7737
7738         dns_diff_clear(&_sig_diff);
7739
7740         for (i = 0; i < nkeys; i++)
7741                 dst_key_free(&zone_keys[i]);
7742
7743         if (node != NULL)
7744                 dns_db_detachnode(db, &node);
7745
7746         if (version != NULL) {
7747                 dns_db_closeversion(db, &version, ISC_FALSE);
7748                 dns_db_detach(&db);
7749         } else if (db != NULL)
7750                 dns_db_detach(&db);
7751
7752         if (ISC_LIST_HEAD(zone->signing) != NULL) {
7753                 isc_interval_t i;
7754                 if (zone->update_disabled || result != ISC_R_SUCCESS)
7755                         isc_interval_set(&i, 60, 0);            /* 1 minute */
7756                 else
7757                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
7758                 isc_time_nowplusinterval(&zone->signingtime, &i);
7759         } else
7760                 isc_time_settoepoch(&zone->signingtime);
7761 }
7762
7763 static void
7764 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
7765               unsigned char *data, int size) {
7766         dns_rdata_dnskey_t dnskey;
7767         dns_rdata_keydata_t keydata;
7768         isc_buffer_t buf;
7769         isc_result_t result;
7770
7771         dns_rdata_reset(target);
7772         isc_buffer_init(&buf, data, size);
7773
7774         switch (rr->type) {
7775             case dns_rdatatype_dnskey:
7776                 result = dns_rdata_tostruct(rr, &dnskey, NULL);
7777                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7778                 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
7779                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7780                                      &dnskey, &buf);
7781                 break;
7782             case dns_rdatatype_keydata:
7783                 result = dns_rdata_tostruct(rr, &keydata, NULL);
7784                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7785                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
7786                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7787                                      &dnskey, &buf);
7788                 break;
7789             default:
7790                 INSIST(0);
7791         }
7792 }
7793
7794 /*
7795  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
7796  * a KEYDATA rdataset from the key zone.
7797  *
7798  * 'rr' contains either a DNSKEY record, or a KEYDATA record
7799  *
7800  * After normalizing keys to the same format (DNSKEY, with revoke bit
7801  * cleared), return ISC_TRUE if a key that matches 'rr' is found in
7802  * 'rdset', or ISC_FALSE if not.
7803  */
7804
7805 static isc_boolean_t
7806 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
7807         unsigned char data1[4096], data2[4096];
7808         dns_rdata_t rdata, rdata1, rdata2;
7809         isc_result_t result;
7810
7811         dns_rdata_init(&rdata);
7812         dns_rdata_init(&rdata1);
7813         dns_rdata_init(&rdata2);
7814
7815         normalize_key(rr, &rdata1, data1, sizeof(data1));
7816
7817         for (result = dns_rdataset_first(rdset);
7818              result == ISC_R_SUCCESS;
7819              result = dns_rdataset_next(rdset)) {
7820                 dns_rdata_reset(&rdata);
7821                 dns_rdataset_current(rdset, &rdata);
7822                 normalize_key(&rdata, &rdata2, data2, sizeof(data2));
7823                 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
7824                         return (ISC_TRUE);
7825         }
7826
7827         return (ISC_FALSE);
7828 }
7829
7830 /*
7831  * Calculate the refresh interval for a keydata zone, per
7832  * RFC5011: MAX(1 hr,
7833  *              MIN(15 days,
7834  *                  1/2 * OrigTTL,
7835  *                  1/2 * RRSigExpirationInterval))
7836  * or for retries: MAX(1 hr,
7837  *                     MIN(1 day,
7838  *                         1/10 * OrigTTL,
7839  *                         1/10 * RRSigExpirationInterval))
7840  */
7841 static inline isc_stdtime_t
7842 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
7843         isc_result_t result;
7844         isc_uint32_t t;
7845         dns_rdataset_t *rdset;
7846         dns_rdata_t sigrr = DNS_RDATA_INIT;
7847         dns_rdata_sig_t sig;
7848         isc_stdtime_t now;
7849
7850         isc_stdtime_get(&now);
7851
7852         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7853                 rdset = &kfetch->dnskeysigset;
7854         else
7855                 return (now + HOUR);
7856
7857         result = dns_rdataset_first(rdset);
7858         if (result != ISC_R_SUCCESS)
7859                 return (now + HOUR);
7860
7861         dns_rdataset_current(rdset, &sigrr);
7862         result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7863         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7864
7865         if (!retry) {
7866                 t = sig.originalttl / 2;
7867
7868                 if (isc_serial_gt(sig.timeexpire, now)) {
7869                         isc_uint32_t exp = (sig.timeexpire - now) / 2;
7870                         if (t > exp)
7871                                 t = exp;
7872                 }
7873
7874                 if (t > (15*DAY))
7875                         t = (15*DAY);
7876
7877                 if (t < HOUR)
7878                         t = HOUR;
7879         } else {
7880                 t = sig.originalttl / 10;
7881
7882                 if (isc_serial_gt(sig.timeexpire, now)) {
7883                         isc_uint32_t exp = (sig.timeexpire - now) / 10;
7884                         if (t > exp)
7885                                 t = exp;
7886                 }
7887
7888                 if (t > DAY)
7889                         t = DAY;
7890
7891                 if (t < HOUR)
7892                         t = HOUR;
7893         }
7894
7895         return (now + t);
7896 }
7897
7898 /*
7899  * This routine is called when no changes are needed in a KEYDATA
7900  * record except to simply update the refresh timer.  Caller should
7901  * hold zone lock.
7902  */
7903 static isc_result_t
7904 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
7905 {
7906         isc_result_t result;
7907         isc_buffer_t keyb;
7908         unsigned char key_buf[4096];
7909         dns_rdata_t rdata = DNS_RDATA_INIT;
7910         dns_rdata_keydata_t keydata;
7911         dns_name_t *name;
7912         dns_zone_t *zone = kfetch->zone;
7913         isc_stdtime_t now;
7914
7915         name = dns_fixedname_name(&kfetch->name);
7916         isc_stdtime_get(&now);
7917
7918         for (result = dns_rdataset_first(&kfetch->keydataset);
7919              result == ISC_R_SUCCESS;
7920              result = dns_rdataset_next(&kfetch->keydataset)) {
7921                 dns_rdata_reset(&rdata);
7922                 dns_rdataset_current(&kfetch->keydataset, &rdata);
7923
7924                 /* Delete old version */
7925                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
7926                                     name, 0, &rdata));
7927
7928                 /* Update refresh timer */
7929                 CHECK(dns_rdata_tostruct(&rdata, &keydata, NULL));
7930                 keydata.refresh = refresh_time(kfetch, ISC_TRUE);
7931                 set_refreshkeytimer(zone, &keydata, now);
7932
7933                 dns_rdata_reset(&rdata);
7934                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7935                 CHECK(dns_rdata_fromstruct(&rdata,
7936                                            zone->rdclass, dns_rdatatype_keydata,
7937                                            &keydata, &keyb));
7938
7939                 /* Insert updated version */
7940                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
7941                                     name, 0, &rdata));
7942         }
7943         result = ISC_R_SUCCESS;
7944   failure:
7945         return (result);
7946 }
7947
7948 /*
7949  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
7950  */
7951 static isc_boolean_t
7952 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
7953         isc_result_t result;
7954         dns_name_t *keyname;
7955         isc_mem_t *mctx;
7956         dns_rdata_t sigrr = DNS_RDATA_INIT;
7957         dns_rdata_t rr = DNS_RDATA_INIT;
7958         dns_rdata_rrsig_t sig;
7959         dns_rdata_dnskey_t dnskey;
7960         dst_key_t *dstkey = NULL;
7961         unsigned char key_buf[4096];
7962         isc_buffer_t keyb;
7963         isc_boolean_t answer = ISC_FALSE;
7964
7965         REQUIRE(kfetch != NULL && keydata != NULL);
7966         REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
7967
7968         keyname = dns_fixedname_name(&kfetch->name);
7969         mctx = kfetch->zone->view->mctx;
7970
7971         /* Generate a key from keydata */
7972         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7973         dns_keydata_todnskey(keydata, &dnskey, NULL);
7974         dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
7975                                      &dnskey, &keyb);
7976         result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
7977         if (result != ISC_R_SUCCESS)
7978                 return (ISC_FALSE);
7979
7980         /* See if that key generated any of the signatures */
7981         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7982              result == ISC_R_SUCCESS;
7983              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7984                 dns_fixedname_t fixed;
7985                 dns_fixedname_init(&fixed);
7986
7987                 dns_rdata_reset(&sigrr);
7988                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7989                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7990                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7991
7992                 if (dst_key_alg(dstkey) == sig.algorithm &&
7993                     (dst_key_id(dstkey) == sig.keyid ||
7994                      dst_key_rid(dstkey) == sig.keyid)) {
7995                         result = dns_dnssec_verify2(keyname,
7996                                             &kfetch->dnskeyset,
7997                                             dstkey, ISC_FALSE, mctx, &sigrr,
7998                                             dns_fixedname_name(&fixed));
7999
8000                         dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
8001                                      "Confirm revoked DNSKEY is self-signed: "
8002                                      "%s", dns_result_totext(result));
8003
8004                         if (result == ISC_R_SUCCESS) {
8005                                 answer = ISC_TRUE;
8006                                 break;
8007                         }
8008                 }
8009         }
8010
8011         dst_key_free(&dstkey);
8012         return (answer);
8013 }
8014
8015 /*
8016  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
8017  * anchors are being managed; scan the keyset, and update the key zone and the
8018  * local trust anchors according to RFC5011.
8019  */
8020 static void
8021 keyfetch_done(isc_task_t *task, isc_event_t *event) {
8022         isc_result_t result, eresult;
8023         dns_fetchevent_t *devent;
8024         dns_keyfetch_t *kfetch;
8025         dns_zone_t *zone;
8026         isc_mem_t *mctx = NULL;
8027         dns_keytable_t *secroots = NULL;
8028         dns_dbversion_t *ver = NULL;
8029         dns_diff_t diff;
8030         isc_boolean_t alldone = ISC_FALSE;
8031         isc_boolean_t commit = ISC_FALSE;
8032         dns_name_t *keyname;
8033         dns_rdata_t sigrr = DNS_RDATA_INIT;
8034         dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
8035         dns_rdata_t keydatarr = DNS_RDATA_INIT;
8036         dns_rdata_rrsig_t sig;
8037         dns_rdata_dnskey_t dnskey;
8038         dns_rdata_keydata_t keydata;
8039         isc_boolean_t initializing;
8040         char namebuf[DNS_NAME_FORMATSIZE];
8041         unsigned char key_buf[4096];
8042         isc_buffer_t keyb;
8043         dst_key_t *dstkey;
8044         isc_stdtime_t now;
8045         int pending = 0;
8046         isc_boolean_t secure;
8047         isc_boolean_t free_needed;
8048
8049         UNUSED(task);
8050         INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
8051         INSIST(event->ev_arg != NULL);
8052
8053         kfetch = event->ev_arg;
8054         zone = kfetch->zone;
8055         isc_mem_attach(zone->mctx, &mctx);
8056         keyname = dns_fixedname_name(&kfetch->name);
8057
8058         devent = (dns_fetchevent_t *) event;
8059         eresult = devent->result;
8060
8061         /* Free resources which are not of interest */
8062         if (devent->node != NULL)
8063                 dns_db_detachnode(devent->db, &devent->node);
8064         if (devent->db != NULL)
8065                 dns_db_detach(&devent->db);
8066         isc_event_free(&event);
8067         dns_resolver_destroyfetch(&kfetch->fetch);
8068
8069         LOCK_ZONE(zone);
8070         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
8071                 goto cleanup;
8072
8073         isc_stdtime_get(&now);
8074         dns_name_format(keyname, namebuf, sizeof(namebuf));
8075
8076         result = dns_view_getsecroots(zone->view, &secroots);
8077         INSIST(result == ISC_R_SUCCESS);
8078
8079         dns_diff_init(mctx, &diff);
8080         diff.resign = zone->sigresigninginterval;
8081
8082         CHECK(dns_db_newversion(kfetch->db, &ver));
8083
8084         zone->refreshkeycount--;
8085         alldone = ISC_TF(zone->refreshkeycount == 0);
8086
8087         if (alldone)
8088                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8089
8090         /* Fetch failed */
8091         if (eresult != ISC_R_SUCCESS ||
8092             !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
8093                 dns_zone_log(zone, ISC_LOG_WARNING,
8094                              "Unable to fetch DNSKEY set "
8095                              "'%s': %s", namebuf, dns_result_totext(eresult));
8096                 CHECK(minimal_update(kfetch, ver, &diff));
8097                 goto done;
8098         }
8099
8100         /* No RRSIGs found */
8101         if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
8102                 dns_zone_log(zone, ISC_LOG_WARNING,
8103                              "No DNSKEY RRSIGs found for "
8104                              "'%s': %s", namebuf, dns_result_totext(eresult));
8105                 CHECK(minimal_update(kfetch, ver, &diff));
8106                 goto done;
8107         }
8108
8109         /*
8110          * Validate the dnskeyset against the current trusted keys.
8111          */
8112         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8113              result == ISC_R_SUCCESS;
8114              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
8115                 dns_keynode_t *keynode = NULL;
8116
8117                 dns_rdata_reset(&sigrr);
8118                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8119                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8120                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8121
8122                 result = dns_keytable_find(secroots, keyname, &keynode);
8123                 while (result == ISC_R_SUCCESS) {
8124                         dns_keynode_t *nextnode = NULL;
8125                         dns_fixedname_t fixed;
8126                         dns_fixedname_init(&fixed);
8127
8128                         dstkey = dns_keynode_key(keynode);
8129                         if (dstkey == NULL) /* fail_secure() was called */
8130                                 break;
8131
8132                         if (dst_key_alg(dstkey) == sig.algorithm &&
8133                             dst_key_id(dstkey) == sig.keyid) {
8134                                 result = dns_dnssec_verify2(keyname,
8135                                                     &kfetch->dnskeyset,
8136                                                     dstkey, ISC_FALSE,
8137                                                     zone->view->mctx, &sigrr,
8138                                                     dns_fixedname_name(&fixed));
8139
8140                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
8141                                              "Verifying DNSKEY set for zone "
8142                                              "'%s': %s", namebuf,
8143                                              dns_result_totext(result));
8144
8145                                 if (result == ISC_R_SUCCESS) {
8146                                         kfetch->dnskeyset.trust =
8147                                                 dns_trust_secure;
8148                                         kfetch->dnskeysigset.trust =
8149                                                 dns_trust_secure;
8150                                         dns_keytable_detachkeynode(secroots,
8151                                                                    &keynode);
8152                                         break;
8153                                 }
8154                         }
8155
8156                         result = dns_keytable_nextkeynode(secroots,
8157                                                           keynode, &nextnode);
8158                         dns_keytable_detachkeynode(secroots, &keynode);
8159                         keynode = nextnode;
8160                 }
8161
8162                 if (kfetch->dnskeyset.trust == dns_trust_secure)
8163                         break;
8164         }
8165
8166         /*
8167          * If we were not able to verify the answer using the current
8168          * trusted keys then all we can do is look at any revoked keys.
8169          */
8170         secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
8171
8172         /*
8173          * First scan keydataset to find keys that are not in dnskeyset
8174          *   - Missing keys which are not scheduled for removal,
8175          *     log a warning
8176          *   - Missing keys which are scheduled for removal and
8177          *     the remove hold-down timer has completed should
8178          *     be removed from the key zone
8179          *   - Missing keys whose acceptance timers have not yet
8180          *     completed, log a warning and reset the acceptance
8181          *     timer to 30 days in the future
8182          *   - All keys not being removed have their refresh timers
8183          *     updated
8184          */
8185         initializing = ISC_TRUE;
8186         for (result = dns_rdataset_first(&kfetch->keydataset);
8187              result == ISC_R_SUCCESS;
8188              result = dns_rdataset_next(&kfetch->keydataset)) {
8189                 dns_rdata_reset(&keydatarr);
8190                 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8191                 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8192                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8193
8194                 /*
8195                  * If any keydata record has a nonzero add holddown, then
8196                  * there was a pre-existing trust anchor for this domain;
8197                  * that means we are *not* initializing it and shouldn't
8198                  * automatically trust all the keys we find at the zone apex.
8199                  */
8200                 initializing = initializing && ISC_TF(keydata.addhd == 0);
8201
8202                 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
8203                         isc_boolean_t deletekey = ISC_FALSE;
8204
8205                         if (!secure) {
8206                                 if (now > keydata.removehd)
8207                                         deletekey = ISC_TRUE;
8208                         } else if (now < keydata.addhd) {
8209                                 dns_zone_log(zone, ISC_LOG_WARNING,
8210                                              "Pending key unexpectedly missing "
8211                                              "from %s; restarting acceptance "
8212                                              "timer", namebuf);
8213                                 keydata.addhd = now + MONTH;
8214                                 keydata.refresh = refresh_time(kfetch,
8215                                                                ISC_FALSE);
8216                         } else if (keydata.addhd == 0) {
8217                                 keydata.addhd = now;
8218                         } else if (keydata.removehd == 0) {
8219                                 dns_zone_log(zone, ISC_LOG_WARNING,
8220                                              "Active key unexpectedly missing "
8221                                              "from %s", namebuf);
8222                                 keydata.refresh = now + HOUR;
8223                         } else if (now > keydata.removehd) {
8224                                 deletekey = ISC_TRUE;
8225                         } else {
8226                                 keydata.refresh = refresh_time(kfetch,
8227                                                                ISC_FALSE);
8228                         }
8229
8230                         if  (secure || deletekey) {
8231                                 /* Delete old version */
8232                                 CHECK(update_one_rr(kfetch->db, ver, &diff,
8233                                                     DNS_DIFFOP_DEL, keyname, 0,
8234                                                     &keydatarr));
8235                         }
8236
8237                         if (!secure || deletekey)
8238                                 continue;
8239
8240                         dns_rdata_reset(&keydatarr);
8241                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8242                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8243                                              dns_rdatatype_keydata,
8244                                              &keydata, &keyb);
8245
8246                         /* Insert updated version */
8247                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8248                                             DNS_DIFFOP_ADD, keyname, 0,
8249                                             &keydatarr));
8250
8251                         set_refreshkeytimer(zone, &keydata, now);
8252                 }
8253         }
8254
8255         /*
8256          * Next scan dnskeyset:
8257          *   - If new keys are found (i.e., lacking a match in keydataset)
8258          *     add them to the key zone and set the acceptance timer
8259          *     to 30 days in the future (or to immediately if we've
8260          *     determined that we're initializing the zone for the
8261          *     first time)
8262          *   - Previously-known keys that have been revoked
8263          *     must be scheduled for removal from the key zone (or,
8264          *     if they hadn't been accepted as trust anchors yet
8265          *     anyway, removed at once)
8266          *   - Previously-known unrevoked keys whose acceptance timers
8267          *     have completed are promoted to trust anchors
8268          *   - All keys not being removed have their refresh
8269          *     timers updated
8270          */
8271         for (result = dns_rdataset_first(&kfetch->dnskeyset);
8272              result == ISC_R_SUCCESS;
8273              result = dns_rdataset_next(&kfetch->dnskeyset)) {
8274                 isc_boolean_t revoked = ISC_FALSE;
8275                 isc_boolean_t newkey = ISC_FALSE;
8276                 isc_boolean_t updatekey = ISC_FALSE;
8277                 isc_boolean_t deletekey = ISC_FALSE;
8278                 isc_boolean_t trustkey = ISC_FALSE;
8279
8280                 dns_rdata_reset(&dnskeyrr);
8281                 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
8282                 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8283                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8284
8285                 /* Skip ZSK's */
8286                 if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
8287                         continue;
8288
8289                 revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
8290
8291                 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
8292                         dns_rdata_reset(&keydatarr);
8293                         dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8294                         result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8295                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8296
8297                         if (revoked && revocable(kfetch, &keydata)) {
8298                                 if (keydata.addhd > now) {
8299                                         /*
8300                                          * Key wasn't trusted yet, and now
8301                                          * it's been revoked?  Just remove it
8302                                          */
8303                                         deletekey = ISC_TRUE;
8304                                 } else if (keydata.removehd == 0) {
8305                                         /* Remove from secroots */
8306                                         dns_view_untrust(zone->view, keyname,
8307                                                          &dnskey, mctx);
8308
8309                                         /* If initializing, delete now */
8310                                         if (keydata.addhd == 0)
8311                                                 deletekey = ISC_TRUE;
8312                                         else
8313                                                 keydata.removehd = now + MONTH;
8314                                 } else if (keydata.removehd < now) {
8315                                         /* Scheduled for removal */
8316                                         deletekey = ISC_TRUE;
8317                                 }
8318                         } else if (revoked) {
8319                                 if (secure && keydata.removehd == 0) {
8320                                         dns_zone_log(zone, ISC_LOG_WARNING,
8321                                                      "Active key for zone "
8322                                                      "'%s' is revoked but "
8323                                                      "did not self-sign; "
8324                                                          "ignoring.", namebuf);
8325                                                 continue;
8326                                 }
8327                         } else if (secure) {
8328                                 if (keydata.removehd != 0) {
8329                                         /*
8330                                          * Key isn't revoked--but it
8331                                          * seems it used to be.
8332                                          * Remove it now and add it
8333                                          * back as if it were a fresh key.
8334                                          */
8335                                         deletekey = ISC_TRUE;
8336                                         newkey = ISC_TRUE;
8337                                 } else if (keydata.addhd > now)
8338                                         pending++;
8339                                 else if (keydata.addhd == 0)
8340                                         keydata.addhd = now;
8341
8342                                 if (keydata.addhd <= now)
8343                                         trustkey = ISC_TRUE;
8344                         }
8345
8346                         if (!deletekey && !newkey)
8347                                 updatekey = ISC_TRUE;
8348                 } else if (secure) {
8349                         /*
8350                          * Key wasn't in the key zone but it's
8351                          * revoked now anyway, so just skip it
8352                          */
8353                         if (revoked)
8354                                 continue;
8355
8356                         /* Key wasn't in the key zone: add it */
8357                         newkey = ISC_TRUE;
8358
8359                         if (initializing) {
8360                                 dns_keytag_t tag = 0;
8361                                 CHECK(compute_tag(keyname, &dnskey,
8362                                                   mctx, &tag));
8363                                 dns_zone_log(zone, ISC_LOG_WARNING,
8364                                              "Initializing automatic trust "
8365                                              "anchor management for zone '%s'; "
8366                                              "DNSKEY ID %d is now trusted, "
8367                                              "waiving the normal 30-day "
8368                                              "waiting period.",
8369                                              namebuf, tag);
8370                                 trustkey = ISC_TRUE;
8371                         }
8372                 }
8373
8374                 /* Delete old version */
8375                 if (deletekey || !newkey)
8376                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8377                                             DNS_DIFFOP_DEL, keyname, 0,
8378                                             &keydatarr));
8379
8380                 if (updatekey) {
8381                         /* Set refresh timer */
8382                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8383                         dns_rdata_reset(&keydatarr);
8384                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8385                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8386                                              dns_rdatatype_keydata,
8387                                              &keydata, &keyb);
8388
8389                         /* Insert updated version */
8390                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8391                                             DNS_DIFFOP_ADD, keyname, 0,
8392                                             &keydatarr));
8393                 } else if (newkey) {
8394                         /* Convert DNSKEY to KEYDATA */
8395                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8396                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8397                         dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
8398                                                NULL);
8399                         keydata.addhd = initializing ? now : now + MONTH;
8400                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8401                         dns_rdata_reset(&keydatarr);
8402                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8403                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8404                                              dns_rdatatype_keydata,
8405                                              &keydata, &keyb);
8406
8407                         /* Insert into key zone */
8408                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8409                                             DNS_DIFFOP_ADD, keyname, 0,
8410                                             &keydatarr));
8411                 }
8412
8413                 if (trustkey) {
8414                         /* Trust this key. */
8415                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8416                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8417                         trust_key(zone, keyname, &dnskey, mctx);
8418                 }
8419
8420                 if (!deletekey)
8421                         set_refreshkeytimer(zone, &keydata, now);
8422         }
8423
8424         /*
8425          * RFC5011 says, "A trust point that has all of its trust anchors
8426          * revoked is considered deleted and is treated as if the trust
8427          * point was never configured."  But if someone revoked their
8428          * active key before the standby was trusted, that would mean the
8429          * zone would suddenly be nonsecured.  We avoid this by checking to
8430          * see if there's pending keydata.  If so, we put a null key in
8431          * the security roots; then all queries to the zone will fail.
8432          */
8433         if (pending != 0)
8434                 fail_secure(zone, keyname);
8435
8436  done:
8437
8438         if (!ISC_LIST_EMPTY(diff.tuples)) {
8439                 /* Write changes to journal file. */
8440                 CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
8441                                         zone->updatemethod));
8442                 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
8443                 commit = ISC_TRUE;
8444
8445                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8446                 zone_needdump(zone, 30);
8447         }
8448
8449   failure:
8450
8451         dns_diff_clear(&diff);
8452         if (ver != NULL)
8453                 dns_db_closeversion(kfetch->db, &ver, commit);
8454
8455  cleanup:
8456         dns_db_detach(&kfetch->db);
8457
8458         INSIST(zone->irefs > 0);
8459         zone->irefs--;
8460         kfetch->zone = NULL;
8461
8462         if (dns_rdataset_isassociated(&kfetch->keydataset))
8463                 dns_rdataset_disassociate(&kfetch->keydataset);
8464         if (dns_rdataset_isassociated(&kfetch->dnskeyset))
8465                 dns_rdataset_disassociate(&kfetch->dnskeyset);
8466         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8467                 dns_rdataset_disassociate(&kfetch->dnskeysigset);
8468
8469         dns_name_free(keyname, mctx);
8470         isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
8471         isc_mem_detach(&mctx);
8472
8473         if (secroots != NULL)
8474                 dns_keytable_detach(&secroots);
8475
8476         free_needed = exit_check(zone);
8477         UNLOCK_ZONE(zone);
8478         if (free_needed)
8479                 zone_free(zone);
8480 }
8481
8482 /*
8483  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
8484  * records from the zone apex.
8485  */
8486 static void
8487 zone_refreshkeys(dns_zone_t *zone) {
8488         const char me[] = "zone_refreshkeys";
8489         isc_result_t result;
8490         dns_rriterator_t rrit;
8491         dns_db_t *db = NULL;
8492         dns_dbversion_t *ver = NULL;
8493         dns_diff_t diff;
8494         dns_rdata_t rdata = DNS_RDATA_INIT;
8495         dns_rdata_keydata_t kd;
8496         isc_stdtime_t now;
8497         isc_boolean_t commit = ISC_FALSE;
8498         isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
8499
8500         ENTER;
8501         REQUIRE(zone->db != NULL);
8502
8503         isc_stdtime_get(&now);
8504
8505         LOCK_ZONE(zone);
8506         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
8507                 isc_time_settoepoch(&zone->refreshkeytime);
8508                 UNLOCK_ZONE(zone);
8509                 return;
8510         }
8511
8512         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8513         dns_db_attach(zone->db, &db);
8514         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8515
8516         dns_diff_init(zone->mctx, &diff);
8517
8518         CHECK(dns_db_newversion(db, &ver));
8519
8520         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
8521
8522         dns_rriterator_init(&rrit, db, ver, 0);
8523         for (result = dns_rriterator_first(&rrit);
8524              result == ISC_R_SUCCESS;
8525              result = dns_rriterator_nextrrset(&rrit)) {
8526                 isc_stdtime_t timer = 0xffffffff;
8527                 dns_name_t *name = NULL, *kname = NULL;
8528                 dns_rdataset_t *kdset = NULL;
8529                 dns_keyfetch_t *kfetch;
8530                 isc_uint32_t ttl;
8531
8532                 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
8533                 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
8534                     !dns_rdataset_isassociated(kdset))
8535                         continue;
8536
8537                 /*
8538                  * Scan the stored keys looking for ones that need
8539                  * removal or refreshing
8540                  */
8541                 for (result = dns_rdataset_first(kdset);
8542                      result == ISC_R_SUCCESS;
8543                      result = dns_rdataset_next(kdset)) {
8544                         dns_rdata_reset(&rdata);
8545                         dns_rdataset_current(kdset, &rdata);
8546                         result = dns_rdata_tostruct(&rdata, &kd, NULL);
8547                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8548
8549                         /* Removal timer expired? */
8550                         if (kd.removehd != 0 && kd.removehd < now) {
8551                                 CHECK(update_one_rr(db, ver, &diff,
8552                                                     DNS_DIFFOP_DEL, name, ttl,
8553                                                     &rdata));
8554                                 continue;
8555                         }
8556
8557                         /* Acceptance timer expired? */
8558                         if (kd.addhd != 0 && kd.addhd < now)
8559                                 timer = kd.addhd;
8560
8561                         /* Or do we just need to refresh the keyset? */
8562                         if (timer > kd.refresh)
8563                                 timer = kd.refresh;
8564                 }
8565
8566                 if (timer > now)
8567                         continue;
8568
8569                 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
8570                 if (kfetch == NULL) {
8571                         fetch_err = ISC_TRUE;
8572                         goto failure;
8573                 }
8574
8575                 zone->refreshkeycount++;
8576                 kfetch->zone = zone;
8577                 zone->irefs++;
8578                 INSIST(zone->irefs != 0);
8579                 dns_fixedname_init(&kfetch->name);
8580                 kname = dns_fixedname_name(&kfetch->name);
8581                 dns_name_dup(name, zone->mctx, kname);
8582                 dns_rdataset_init(&kfetch->dnskeyset);
8583                 dns_rdataset_init(&kfetch->dnskeysigset);
8584                 dns_rdataset_init(&kfetch->keydataset);
8585                 dns_rdataset_clone(kdset, &kfetch->keydataset);
8586                 kfetch->db = NULL;
8587                 dns_db_attach(db, &kfetch->db);
8588                 kfetch->fetch = NULL;
8589
8590                 result = dns_resolver_createfetch(zone->view->resolver,
8591                                                   kname, dns_rdatatype_dnskey,
8592                                                   NULL, NULL, NULL,
8593                                                   DNS_FETCHOPT_NOVALIDATE,
8594                                                   zone->task,
8595                                                   keyfetch_done, kfetch,
8596                                                   &kfetch->dnskeyset,
8597                                                   &kfetch->dnskeysigset,
8598                                                   &kfetch->fetch);
8599                 if (result == ISC_R_SUCCESS)
8600                         fetching = ISC_TRUE;
8601                 else {
8602                         zone->refreshkeycount--;
8603                         zone->irefs--;
8604                         dns_db_detach(&kfetch->db);
8605                         dns_rdataset_disassociate(&kfetch->keydataset);
8606                         dns_name_free(kname, zone->mctx);
8607                         isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
8608                         dns_zone_log(zone, ISC_LOG_WARNING,
8609                                      "Failed to create fetch for "
8610                                      "DNSKEY update");
8611                         fetch_err = ISC_TRUE;
8612                 }
8613         }
8614         if (!ISC_LIST_EMPTY(diff.tuples)) {
8615                 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
8616                                         zone->updatemethod));
8617                 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
8618                 commit = ISC_TRUE;
8619                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8620                 zone_needdump(zone, 30);
8621         }
8622
8623   failure:
8624         if (fetch_err) {
8625                 /*
8626                  * Error during a key fetch; retry in an hour.
8627                  */
8628                 isc_time_t timenow, timethen;
8629                 char timebuf[80];
8630
8631                 TIME_NOW(&timenow);
8632                 DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
8633                 zone->refreshkeytime = timethen;
8634                 zone_settimer(zone, &timenow);
8635
8636                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
8637                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
8638                              timebuf);
8639
8640                 if (!fetching)
8641                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8642         }
8643
8644         UNLOCK_ZONE(zone);
8645
8646         dns_diff_clear(&diff);
8647         if (ver != NULL) {
8648                 dns_rriterator_destroy(&rrit);
8649                 dns_db_closeversion(db, &ver, commit);
8650         }
8651         dns_db_detach(&db);
8652 }
8653
8654 static void
8655 zone_maintenance(dns_zone_t *zone) {
8656         const char me[] = "zone_maintenance";
8657         isc_time_t now;
8658         isc_result_t result;
8659         isc_boolean_t dumping;
8660
8661         REQUIRE(DNS_ZONE_VALID(zone));
8662         ENTER;
8663
8664         /*
8665          * Are we pending load/reload?
8666          */
8667         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
8668                 return;
8669
8670         /*
8671          * Configuring the view of this zone may have
8672          * failed, for example because the config file
8673          * had a syntax error.  In that case, the view
8674          * adb or resolver will be NULL, and we had better not try
8675          * to do further maintenance on it.
8676          */
8677         if (zone->view == NULL || zone->view->adb == NULL)
8678                 return;
8679
8680         TIME_NOW(&now);
8681
8682         /*
8683          * Expire check.
8684          */
8685         switch (zone->type) {
8686         case dns_zone_redirect:
8687                 if (zone->masters == NULL)
8688                         break;
8689         case dns_zone_slave:
8690         case dns_zone_stub:
8691                 LOCK_ZONE(zone);
8692                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
8693                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8694                         zone_expire(zone);
8695                         zone->refreshtime = now;
8696                 }
8697                 UNLOCK_ZONE(zone);
8698                 break;
8699         default:
8700                 break;
8701         }
8702
8703         /*
8704          * Up to date check.
8705          */
8706         switch (zone->type) {
8707         case dns_zone_redirect:
8708                 if (zone->masters == NULL)
8709                         break;
8710         case dns_zone_slave:
8711         case dns_zone_stub:
8712                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8713                     isc_time_compare(&now, &zone->refreshtime) >= 0)
8714                         dns_zone_refresh(zone);
8715                 break;
8716         default:
8717                 break;
8718         }
8719
8720         /*
8721          * Slaves send notifies before backing up to disk, masters after.
8722          */
8723         if (zone->type == dns_zone_slave &&
8724             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8725             isc_time_compare(&now, &zone->notifytime) >= 0)
8726                 zone_notify(zone, &now);
8727
8728         /*
8729          * Do we need to consolidate the backing store?
8730          */
8731         switch (zone->type) {
8732         case dns_zone_master:
8733         case dns_zone_slave:
8734         case dns_zone_key:
8735         case dns_zone_redirect:
8736         case dns_zone_stub:
8737                 LOCK_ZONE(zone);
8738                 if (zone->masterfile != NULL &&
8739                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
8740                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8741                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
8742                         dumping = was_dumping(zone);
8743                 } else
8744                         dumping = ISC_TRUE;
8745                 UNLOCK_ZONE(zone);
8746                 if (!dumping) {
8747                         result = zone_dump(zone, ISC_TRUE); /* task locked */
8748                         if (result != ISC_R_SUCCESS)
8749                                 dns_zone_log(zone, ISC_LOG_WARNING,
8750                                              "dump failed: %s",
8751                                              dns_result_totext(result));
8752                 }
8753                 break;
8754         default:
8755                 break;
8756         }
8757
8758         /*
8759          * Master/redirect zones send notifies now, if needed
8760          */
8761         switch (zone->type) {
8762         case dns_zone_master:
8763         case dns_zone_redirect:
8764                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
8765                     isc_time_compare(&now, &zone->notifytime) >= 0)
8766                         zone_notify(zone, &now);
8767         default:
8768                 break;
8769         }
8770
8771         /*
8772          * Do we need to refresh keys?
8773          */
8774         switch (zone->type) {
8775         case dns_zone_key:
8776                 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
8777                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8778                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
8779                                 zone_refreshkeys(zone);
8780                         }
8781                 }
8782                 break;
8783         case dns_zone_master:
8784                 if (!isc_time_isepoch(&zone->refreshkeytime) &&
8785                     isc_time_compare(&now, &zone->refreshkeytime) >= 0)
8786                         zone_rekey(zone);
8787         default:
8788                 break;
8789         }
8790
8791         switch (zone->type) {
8792         case dns_zone_master:
8793         case dns_zone_redirect:
8794         case dns_zone_slave:
8795                 /*
8796                  * Do we need to sign/resign some RRsets?
8797                  */
8798                 if (!isc_time_isepoch(&zone->signingtime) &&
8799                     isc_time_compare(&now, &zone->signingtime) >= 0)
8800                         zone_sign(zone);
8801                 else if (!isc_time_isepoch(&zone->resigntime) &&
8802                     isc_time_compare(&now, &zone->resigntime) >= 0)
8803                         zone_resigninc(zone);
8804                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
8805                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
8806                         zone_nsec3chain(zone);
8807                 /*
8808                  * Do we need to issue a key expiry warning?
8809                  */
8810                 if (!isc_time_isepoch(&zone->keywarntime) &&
8811                     isc_time_compare(&now, &zone->keywarntime) >= 0)
8812                         set_key_expiry_warning(zone, zone->key_expiry,
8813                                                isc_time_seconds(&now));
8814                 break;
8815
8816         default:
8817                 break;
8818         }
8819         zone_settimer(zone, &now);
8820 }
8821
8822 void
8823 dns_zone_markdirty(dns_zone_t *zone) {
8824         isc_uint32_t serial;
8825         isc_result_t result = ISC_R_SUCCESS;
8826
8827         LOCK_ZONE(zone);
8828         if (zone->type == dns_zone_master) {
8829                 if (inline_raw(zone)) {
8830                         unsigned int soacount;
8831
8832                         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8833                         if (zone->db != NULL) {
8834                                 result = zone_get_from_db(zone, zone->db, NULL,
8835                                                           &soacount, &serial,
8836                                                           NULL, NULL, NULL,
8837                                                           NULL, NULL);
8838                         } else
8839                                 result = DNS_R_NOTLOADED;
8840                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8841                         if (result == ISC_R_SUCCESS && soacount > 0U)
8842                                 zone_send_secureserial(zone, ISC_FALSE, serial);
8843                 }
8844
8845                 /* XXXMPA make separate call back */
8846                 if (result == ISC_R_SUCCESS)
8847                         set_resigntime(zone);
8848         }
8849         zone_needdump(zone, DNS_DUMP_DELAY);
8850         UNLOCK_ZONE(zone);
8851 }
8852
8853 void
8854 dns_zone_expire(dns_zone_t *zone) {
8855         REQUIRE(DNS_ZONE_VALID(zone));
8856
8857         LOCK_ZONE(zone);
8858         zone_expire(zone);
8859         UNLOCK_ZONE(zone);
8860 }
8861
8862 static void
8863 zone_expire(dns_zone_t *zone) {
8864         /*
8865          * 'zone' locked by caller.
8866          */
8867
8868         REQUIRE(LOCKED_ZONE(zone));
8869
8870         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
8871
8872         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
8873         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
8874         zone->retry = DNS_ZONE_DEFAULTRETRY;
8875         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
8876         zone_unload(zone);
8877 }
8878
8879 void
8880 dns_zone_refresh(dns_zone_t *zone) {
8881         isc_interval_t i;
8882         isc_uint32_t oldflags;
8883         unsigned int j;
8884         isc_result_t result;
8885
8886         REQUIRE(DNS_ZONE_VALID(zone));
8887
8888         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
8889                 return;
8890
8891         /*
8892          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
8893          * in progress at a time.
8894          */
8895
8896         LOCK_ZONE(zone);
8897         oldflags = zone->flags;
8898         if (zone->masterscnt == 0) {
8899                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
8900                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
8901                         dns_zone_log(zone, ISC_LOG_ERROR,
8902                                      "cannot refresh: no masters");
8903                 goto unlock;
8904         }
8905         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
8906         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
8907         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
8908         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
8909                 goto unlock;
8910
8911         /*
8912          * Set the next refresh time as if refresh check has failed.
8913          * Setting this to the retry time will do that.  XXXMLG
8914          * If we are successful it will be reset using zone->refresh.
8915          */
8916         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
8917                          0);
8918         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
8919         if (result != ISC_R_SUCCESS)
8920                 dns_zone_log(zone, ISC_LOG_WARNING,
8921                              "isc_time_nowplusinterval() failed: %s",
8922                              dns_result_totext(result));
8923
8924         /*
8925          * When lacking user-specified timer values from the SOA,
8926          * do exponential backoff of the retry time up to a
8927          * maximum of six hours.
8928          */
8929         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
8930                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
8931
8932         zone->curmaster = 0;
8933         for (j = 0; j < zone->masterscnt; j++)
8934                 zone->mastersok[j] = ISC_FALSE;
8935         /* initiate soa query */
8936         queue_soa_query(zone);
8937  unlock:
8938         UNLOCK_ZONE(zone);
8939 }
8940
8941 isc_result_t
8942 dns_zone_flush(dns_zone_t *zone) {
8943         isc_result_t result = ISC_R_SUCCESS;
8944         isc_boolean_t dumping;
8945
8946         REQUIRE(DNS_ZONE_VALID(zone));
8947
8948         LOCK_ZONE(zone);
8949         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
8950         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8951             zone->masterfile != NULL) {
8952                 result = ISC_R_ALREADYRUNNING;
8953                 dumping = was_dumping(zone);
8954         } else
8955                 dumping = ISC_TRUE;
8956         UNLOCK_ZONE(zone);
8957         if (!dumping)
8958                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
8959         return (result);
8960 }
8961
8962 isc_result_t
8963 dns_zone_dump(dns_zone_t *zone) {
8964         isc_result_t result = ISC_R_ALREADYRUNNING;
8965         isc_boolean_t dumping;
8966
8967         REQUIRE(DNS_ZONE_VALID(zone));
8968
8969         LOCK_ZONE(zone);
8970         dumping = was_dumping(zone);
8971         UNLOCK_ZONE(zone);
8972         if (!dumping)
8973                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
8974         return (result);
8975 }
8976
8977 static void
8978 zone_needdump(dns_zone_t *zone, unsigned int delay) {
8979         const char me[] = "zone_needdump";
8980         isc_time_t dumptime;
8981         isc_time_t now;
8982
8983         /*
8984          * 'zone' locked by caller
8985          */
8986
8987         REQUIRE(DNS_ZONE_VALID(zone));
8988         REQUIRE(LOCKED_ZONE(zone));
8989         ENTER;
8990
8991         /*
8992          * Do we have a place to dump to and are we loaded?
8993          */
8994         if (zone->masterfile == NULL ||
8995             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
8996                 return;
8997
8998         TIME_NOW(&now);
8999         /* add some noise */
9000         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
9001
9002         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9003         if (isc_time_isepoch(&zone->dumptime) ||
9004             isc_time_compare(&zone->dumptime, &dumptime) > 0)
9005                 zone->dumptime = dumptime;
9006         if (zone->task != NULL)
9007                 zone_settimer(zone, &now);
9008 }
9009
9010 static void
9011 dump_done(void *arg, isc_result_t result) {
9012         const char me[] = "dump_done";
9013         dns_zone_t *zone = arg;
9014         dns_db_t *db;
9015         dns_dbversion_t *version;
9016         isc_boolean_t again = ISC_FALSE;
9017         isc_boolean_t compact = ISC_FALSE;
9018         isc_uint32_t serial;
9019         isc_result_t tresult;
9020
9021         REQUIRE(DNS_ZONE_VALID(zone));
9022
9023         ENTER;
9024
9025         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
9026             zone->journalsize != -1) {
9027
9028                 /*
9029                  * We don't own these, zone->dctx must stay valid.
9030                  */
9031                 db = dns_dumpctx_db(zone->dctx);
9032                 version = dns_dumpctx_version(zone->dctx);
9033
9034                 tresult = dns_db_getsoaserial(db, version, &serial);
9035                 /*
9036                  * If there is a secure version of this zone
9037                  * use its serial if it is less than ours.
9038                  */
9039                 if (tresult == ISC_R_SUCCESS && inline_raw(zone) &&
9040                     zone->secure->db != NULL)
9041                 {
9042                         isc_uint32_t sserial;
9043                         isc_result_t mresult;
9044
9045                         mresult = dns_db_getsoaserial(zone->secure->db,
9046                                                       NULL, &sserial);
9047                         if (mresult == ISC_R_SUCCESS &&
9048                             isc_serial_lt(sserial, serial))
9049                                 serial = sserial;
9050                 }
9051                 /*
9052                  * Note: we are task locked here so we can test
9053                  * zone->xfr safely.
9054                  */
9055                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
9056                         tresult = dns_journal_compact(zone->mctx,
9057                                                       zone->journal,
9058                                                       serial,
9059                                                       zone->journalsize);
9060                         switch (tresult) {
9061                         case ISC_R_SUCCESS:
9062                         case ISC_R_NOSPACE:
9063                         case ISC_R_NOTFOUND:
9064                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9065                                              "dns_journal_compact: %s",
9066                                              dns_result_totext(tresult));
9067                                 break;
9068                         default:
9069                                 dns_zone_log(zone, ISC_LOG_ERROR,
9070                                              "dns_journal_compact failed: %s",
9071                                              dns_result_totext(tresult));
9072                                 break;
9073                         }
9074                 } else if (tresult == ISC_R_SUCCESS) {
9075                         compact = ISC_TRUE;
9076                         zone->compact_serial = serial;
9077                 }
9078         }
9079
9080         LOCK_ZONE(zone);
9081         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9082         if (compact)
9083                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
9084         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
9085                 /*
9086                  * Try again in a short while.
9087                  */
9088                 zone_needdump(zone, DNS_DUMP_DELAY);
9089         } else if (result == ISC_R_SUCCESS &&
9090                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9091                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9092                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9093                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9094                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9095                 isc_time_settoepoch(&zone->dumptime);
9096                 again = ISC_TRUE;
9097         } else if (result == ISC_R_SUCCESS)
9098                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9099
9100         if (zone->dctx != NULL)
9101                 dns_dumpctx_detach(&zone->dctx);
9102         zonemgr_putio(&zone->writeio);
9103         UNLOCK_ZONE(zone);
9104         if (again)
9105                 (void)zone_dump(zone, ISC_FALSE);
9106         dns_zone_idetach(&zone);
9107 }
9108
9109 static isc_result_t
9110 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
9111         const char me[] = "zone_dump";
9112         isc_result_t result;
9113         dns_dbversion_t *version = NULL;
9114         isc_boolean_t again;
9115         dns_db_t *db = NULL;
9116         char *masterfile = NULL;
9117         dns_masterformat_t masterformat = dns_masterformat_none;
9118
9119 /*
9120  * 'compact' MUST only be set if we are task locked.
9121  */
9122
9123         REQUIRE(DNS_ZONE_VALID(zone));
9124         ENTER;
9125
9126  redo:
9127         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9128         if (zone->db != NULL)
9129                 dns_db_attach(zone->db, &db);
9130         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9131         LOCK_ZONE(zone);
9132         if (zone->masterfile != NULL) {
9133                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
9134                 masterformat = zone->masterformat;
9135         }
9136         UNLOCK_ZONE(zone);
9137         if (db == NULL) {
9138                 result = DNS_R_NOTLOADED;
9139                 goto fail;
9140         }
9141         if (masterfile == NULL) {
9142                 result = DNS_R_NOMASTERFILE;
9143                 goto fail;
9144         }
9145
9146         if (compact && zone->type != dns_zone_stub) {
9147                 dns_zone_t *dummy = NULL;
9148                 LOCK_ZONE(zone);
9149                 zone_iattach(zone, &dummy);
9150                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
9151                                        zone_gotwritehandle, zone,
9152                                        &zone->writeio);
9153                 if (result != ISC_R_SUCCESS)
9154                         zone_idetach(&dummy);
9155                 else
9156                         result = DNS_R_CONTINUE;
9157                 UNLOCK_ZONE(zone);
9158         } else {
9159                 dns_masterrawheader_t rawdata;
9160                 dns_db_currentversion(db, &version);
9161                 dns_master_initrawheader(&rawdata);
9162                 if (inline_secure(zone))
9163                         get_raw_serial(zone->raw, &rawdata);
9164                 result = dns_master_dump3(zone->mctx, db, version,
9165                                           &dns_master_style_default,
9166                                           masterfile, masterformat,
9167                                           &rawdata);
9168                 dns_db_closeversion(db, &version, ISC_FALSE);
9169         }
9170  fail:
9171         if (db != NULL)
9172                 dns_db_detach(&db);
9173         if (masterfile != NULL)
9174                 isc_mem_free(zone->mctx, masterfile);
9175         masterfile = NULL;
9176
9177         if (result == DNS_R_CONTINUE)
9178                 return (ISC_R_SUCCESS); /* XXXMPA */
9179
9180         again = ISC_FALSE;
9181         LOCK_ZONE(zone);
9182         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9183         if (result != ISC_R_SUCCESS) {
9184                 /*
9185                  * Try again in a short while.
9186                  */
9187                 zone_needdump(zone, DNS_DUMP_DELAY);
9188         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9189                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9190                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9191                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9192                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9193                 isc_time_settoepoch(&zone->dumptime);
9194                 again = ISC_TRUE;
9195         } else
9196                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9197         UNLOCK_ZONE(zone);
9198         if (again)
9199                 goto redo;
9200
9201         return (result);
9202 }
9203
9204 static isc_result_t
9205 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
9206              dns_masterformat_t format, const isc_uint32_t rawversion)
9207 {
9208         isc_result_t result;
9209         dns_dbversion_t *version = NULL;
9210         dns_db_t *db = NULL;
9211         dns_masterrawheader_t rawdata;
9212
9213         REQUIRE(DNS_ZONE_VALID(zone));
9214
9215         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9216         if (zone->db != NULL)
9217                 dns_db_attach(zone->db, &db);
9218         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9219         if (db == NULL)
9220                 return (DNS_R_NOTLOADED);
9221
9222         dns_db_currentversion(db, &version);
9223         dns_master_initrawheader(&rawdata);
9224         if (rawversion == 0)
9225                 rawdata.flags |= DNS_MASTERRAW_COMPAT;
9226         else if (inline_secure(zone))
9227                 get_raw_serial(zone->raw, &rawdata);
9228         else if (zone->sourceserialset) {
9229                 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
9230                 rawdata.sourceserial = zone->sourceserial;
9231         }
9232         result = dns_master_dumptostream3(zone->mctx, db, version, style,
9233                                           format, &rawdata, fd);
9234         dns_db_closeversion(db, &version, ISC_FALSE);
9235         dns_db_detach(&db);
9236         return (result);
9237 }
9238
9239 isc_result_t
9240 dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9241                        const dns_master_style_t *style,
9242                        const isc_uint32_t rawversion)
9243 {
9244         return (dumptostream(zone, fd, style, format, rawversion));
9245 }
9246
9247 isc_result_t
9248 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9249                        const dns_master_style_t *style) {
9250         return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
9251 }
9252
9253 isc_result_t
9254 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
9255         return (dumptostream(zone, fd, &dns_master_style_default,
9256                              dns_masterformat_text, 0));
9257 }
9258
9259 isc_result_t
9260 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
9261         return (dumptostream(zone, fd, &dns_master_style_full,
9262                              dns_masterformat_text, 0));
9263 }
9264
9265 void
9266 dns_zone_unload(dns_zone_t *zone) {
9267         REQUIRE(DNS_ZONE_VALID(zone));
9268
9269         LOCK_ZONE(zone);
9270         zone_unload(zone);
9271         UNLOCK_ZONE(zone);
9272 }
9273
9274 static void
9275 notify_cancel(dns_zone_t *zone) {
9276         dns_notify_t *notify;
9277
9278         /*
9279          * 'zone' locked by caller.
9280          */
9281
9282         REQUIRE(LOCKED_ZONE(zone));
9283
9284         for (notify = ISC_LIST_HEAD(zone->notifies);
9285              notify != NULL;
9286              notify = ISC_LIST_NEXT(notify, link)) {
9287                 if (notify->find != NULL)
9288                         dns_adb_cancelfind(notify->find);
9289                 if (notify->request != NULL)
9290                         dns_request_cancel(notify->request);
9291         }
9292 }
9293
9294 static void
9295 forward_cancel(dns_zone_t *zone) {
9296         dns_forward_t *forward;
9297
9298         /*
9299          * 'zone' locked by caller.
9300          */
9301
9302         REQUIRE(LOCKED_ZONE(zone));
9303
9304         for (forward = ISC_LIST_HEAD(zone->forwards);
9305              forward != NULL;
9306              forward = ISC_LIST_NEXT(forward, link)) {
9307                 if (forward->request != NULL)
9308                         dns_request_cancel(forward->request);
9309         }
9310 }
9311
9312 static void
9313 zone_unload(dns_zone_t *zone) {
9314
9315         /*
9316          * 'zone' locked by caller.
9317          */
9318
9319         REQUIRE(LOCKED_ZONE(zone));
9320
9321         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
9322             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9323                 if (zone->writeio != NULL)
9324                         zonemgr_cancelio(zone->writeio);
9325
9326                 if (zone->dctx != NULL)
9327                         dns_dumpctx_cancel(zone->dctx);
9328         }
9329         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9330         zone_detachdb(zone);
9331         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9332         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
9333         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9334 }
9335
9336 void
9337 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9338         REQUIRE(DNS_ZONE_VALID(zone));
9339         REQUIRE(val > 0);
9340
9341         zone->minrefresh = val;
9342 }
9343
9344 void
9345 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9346         REQUIRE(DNS_ZONE_VALID(zone));
9347         REQUIRE(val > 0);
9348
9349         zone->maxrefresh = val;
9350 }
9351
9352 void
9353 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
9354         REQUIRE(DNS_ZONE_VALID(zone));
9355         REQUIRE(val > 0);
9356
9357         zone->minretry = val;
9358 }
9359
9360 void
9361 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
9362         REQUIRE(DNS_ZONE_VALID(zone));
9363         REQUIRE(val > 0);
9364
9365         zone->maxretry = val;
9366 }
9367
9368 static isc_boolean_t
9369 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
9370         dns_notify_t *notify;
9371
9372         for (notify = ISC_LIST_HEAD(zone->notifies);
9373              notify != NULL;
9374              notify = ISC_LIST_NEXT(notify, link)) {
9375                 if (notify->request != NULL)
9376                         continue;
9377                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
9378                     dns_name_equal(name, &notify->ns))
9379                         return (ISC_TRUE);
9380                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
9381                         return (ISC_TRUE);
9382         }
9383         return (ISC_FALSE);
9384 }
9385
9386 static isc_boolean_t
9387 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
9388         dns_tsigkey_t *key = NULL;
9389         isc_sockaddr_t src;
9390         isc_sockaddr_t any;
9391         isc_boolean_t isself;
9392         isc_netaddr_t dstaddr;
9393         isc_result_t result;
9394
9395         if (zone->view == NULL || zone->isself == NULL)
9396                 return (ISC_FALSE);
9397
9398         switch (isc_sockaddr_pf(dst)) {
9399         case PF_INET:
9400                 src = zone->notifysrc4;
9401                 isc_sockaddr_any(&any);
9402                 break;
9403         case PF_INET6:
9404                 src = zone->notifysrc6;
9405                 isc_sockaddr_any6(&any);
9406                 break;
9407         default:
9408                 return (ISC_FALSE);
9409         }
9410
9411         /*
9412          * When sending from any the kernel will assign a source address
9413          * that matches the destination address.
9414          */
9415         if (isc_sockaddr_eqaddr(&any, &src))
9416                 src = *dst;
9417
9418         isc_netaddr_fromsockaddr(&dstaddr, dst);
9419         result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
9420         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
9421                 return (ISC_FALSE);
9422         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
9423                                 zone->isselfarg);
9424         if (key != NULL)
9425                 dns_tsigkey_detach(&key);
9426         return (isself);
9427 }
9428
9429 static void
9430 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
9431         isc_mem_t *mctx;
9432
9433         /*
9434          * Caller holds zone lock.
9435          */
9436         REQUIRE(DNS_NOTIFY_VALID(notify));
9437
9438         if (notify->zone != NULL) {
9439                 if (!locked)
9440                         LOCK_ZONE(notify->zone);
9441                 REQUIRE(LOCKED_ZONE(notify->zone));
9442                 if (ISC_LINK_LINKED(notify, link))
9443                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
9444                 if (!locked)
9445                         UNLOCK_ZONE(notify->zone);
9446                 if (locked)
9447                         zone_idetach(&notify->zone);
9448                 else
9449                         dns_zone_idetach(&notify->zone);
9450         }
9451         if (notify->find != NULL)
9452                 dns_adb_destroyfind(&notify->find);
9453         if (notify->request != NULL)
9454                 dns_request_destroy(&notify->request);
9455         if (dns_name_dynamic(&notify->ns))
9456                 dns_name_free(&notify->ns, notify->mctx);
9457         if (notify->key != NULL)
9458                 dns_tsigkey_detach(&notify->key);
9459         mctx = notify->mctx;
9460         isc_mem_put(notify->mctx, notify, sizeof(*notify));
9461         isc_mem_detach(&mctx);
9462 }
9463
9464 static isc_result_t
9465 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
9466         dns_notify_t *notify;
9467
9468         REQUIRE(notifyp != NULL && *notifyp == NULL);
9469
9470         notify = isc_mem_get(mctx, sizeof(*notify));
9471         if (notify == NULL)
9472                 return (ISC_R_NOMEMORY);
9473
9474         notify->mctx = NULL;
9475         isc_mem_attach(mctx, &notify->mctx);
9476         notify->flags = flags;
9477         notify->zone = NULL;
9478         notify->find = NULL;
9479         notify->request = NULL;
9480         notify->key = NULL;
9481         isc_sockaddr_any(&notify->dst);
9482         dns_name_init(&notify->ns, NULL);
9483         ISC_LINK_INIT(notify, link);
9484         notify->magic = NOTIFY_MAGIC;
9485         *notifyp = notify;
9486         return (ISC_R_SUCCESS);
9487 }
9488
9489 /*
9490  * XXXAG should check for DNS_ZONEFLG_EXITING
9491  */
9492 static void
9493 process_adb_event(isc_task_t *task, isc_event_t *ev) {
9494         dns_notify_t *notify;
9495         isc_eventtype_t result;
9496
9497         UNUSED(task);
9498
9499         notify = ev->ev_arg;
9500         REQUIRE(DNS_NOTIFY_VALID(notify));
9501         INSIST(task == notify->zone->task);
9502         result = ev->ev_type;
9503         isc_event_free(&ev);
9504         if (result == DNS_EVENT_ADBMOREADDRESSES) {
9505                 dns_adb_destroyfind(&notify->find);
9506                 notify_find_address(notify);
9507                 return;
9508         }
9509         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
9510                 LOCK_ZONE(notify->zone);
9511                 notify_send(notify);
9512                 UNLOCK_ZONE(notify->zone);
9513         }
9514         notify_destroy(notify, ISC_FALSE);
9515 }
9516
9517 static void
9518 notify_find_address(dns_notify_t *notify) {
9519         isc_result_t result;
9520         unsigned int options;
9521
9522         REQUIRE(DNS_NOTIFY_VALID(notify));
9523         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
9524                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
9525
9526         if (notify->zone->view->adb == NULL)
9527                 goto destroy;
9528
9529         result = dns_adb_createfind(notify->zone->view->adb,
9530                                     notify->zone->task,
9531                                     process_adb_event, notify,
9532                                     &notify->ns, dns_rootname, 0,
9533                                     options, 0, NULL,
9534                                     notify->zone->view->dstport,
9535                                     &notify->find);
9536
9537         /* Something failed? */
9538         if (result != ISC_R_SUCCESS)
9539                 goto destroy;
9540
9541         /* More addresses pending? */
9542         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
9543                 return;
9544
9545         /* We have as many addresses as we can get. */
9546         LOCK_ZONE(notify->zone);
9547         notify_send(notify);
9548         UNLOCK_ZONE(notify->zone);
9549
9550  destroy:
9551         notify_destroy(notify, ISC_FALSE);
9552 }
9553
9554
9555 static isc_result_t
9556 notify_send_queue(dns_notify_t *notify) {
9557         isc_event_t *e;
9558         isc_result_t result;
9559
9560         e = isc_event_allocate(notify->mctx, NULL,
9561                                DNS_EVENT_NOTIFYSENDTOADDR,
9562                                notify_send_toaddr,
9563                                notify, sizeof(isc_event_t));
9564         if (e == NULL)
9565                 return (ISC_R_NOMEMORY);
9566         e->ev_arg = notify;
9567         e->ev_sender = NULL;
9568         result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
9569                                          notify->zone->task, &e);
9570         if (result != ISC_R_SUCCESS)
9571                 isc_event_free(&e);
9572         return (result);
9573 }
9574
9575 static void
9576 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
9577         dns_notify_t *notify;
9578         isc_result_t result;
9579         dns_message_t *message = NULL;
9580         isc_netaddr_t dstip;
9581         dns_tsigkey_t *key = NULL;
9582         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9583         isc_sockaddr_t src;
9584         int timeout;
9585         isc_boolean_t have_notifysource = ISC_FALSE;
9586
9587         notify = event->ev_arg;
9588         REQUIRE(DNS_NOTIFY_VALID(notify));
9589
9590         UNUSED(task);
9591
9592         LOCK_ZONE(notify->zone);
9593
9594         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
9595                 result = ISC_R_CANCELED;
9596                 goto cleanup;
9597         }
9598
9599         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
9600             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
9601             notify->zone->view->requestmgr == NULL ||
9602             notify->zone->db == NULL) {
9603                 result = ISC_R_CANCELED;
9604                 goto cleanup;
9605         }
9606
9607         /*
9608          * The raw IPv4 address should also exist.  Don't send to the
9609          * mapped form.
9610          */
9611         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
9612             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
9613                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9614                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
9615                            "notify: ignoring IPv6 mapped IPV4 address: %s",
9616                            addrbuf);
9617                 result = ISC_R_CANCELED;
9618                 goto cleanup;
9619         }
9620
9621         result = notify_createmessage(notify->zone, notify->flags, &message);
9622         if (result != ISC_R_SUCCESS)
9623                 goto cleanup;
9624
9625         if (notify->key != NULL) {
9626                 /* Transfer ownership of key */
9627                 key = notify->key;
9628                 notify->key = NULL;
9629         } else {
9630                 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
9631                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9632                 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
9633                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9634                         notify_log(notify->zone, ISC_LOG_ERROR,
9635                                    "NOTIFY to %s not sent. "
9636                                    "Peer TSIG key lookup failure.", addrbuf);
9637                         goto cleanup_message;
9638                 }
9639         }
9640
9641         /* XXX: should we log the tsig key too? */
9642         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
9643                    addrbuf);
9644         if (notify->zone->view->peers != NULL) {
9645                 dns_peer_t *peer = NULL;
9646                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
9647                                                  &dstip, &peer);
9648                 if (result == ISC_R_SUCCESS) {
9649                         result = dns_peer_getnotifysource(peer, &src);
9650                         if (result == ISC_R_SUCCESS)
9651                                 have_notifysource = ISC_TRUE;
9652                 }
9653         }
9654         switch (isc_sockaddr_pf(&notify->dst)) {
9655         case PF_INET:
9656                 if (!have_notifysource)
9657                         src = notify->zone->notifysrc4;
9658                 break;
9659         case PF_INET6:
9660                 if (!have_notifysource)
9661                         src = notify->zone->notifysrc6;
9662                 break;
9663         default:
9664                 result = ISC_R_NOTIMPLEMENTED;
9665                 goto cleanup_key;
9666         }
9667         timeout = 15;
9668         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
9669                 timeout = 30;
9670         result = dns_request_createvia2(notify->zone->view->requestmgr,
9671                                         message, &src, &notify->dst, 0, key,
9672                                         timeout * 3, timeout,
9673                                         notify->zone->task, notify_done,
9674                                         notify, &notify->request);
9675         if (result == ISC_R_SUCCESS) {
9676                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
9677                         inc_stats(notify->zone,
9678                                   dns_zonestatscounter_notifyoutv4);
9679                 } else {
9680                         inc_stats(notify->zone,
9681                                   dns_zonestatscounter_notifyoutv6);
9682                 }
9683         }
9684
9685  cleanup_key:
9686         if (key != NULL)
9687                 dns_tsigkey_detach(&key);
9688  cleanup_message:
9689         dns_message_destroy(&message);
9690  cleanup:
9691         UNLOCK_ZONE(notify->zone);
9692         isc_event_free(&event);
9693         if (result != ISC_R_SUCCESS)
9694                 notify_destroy(notify, ISC_FALSE);
9695 }
9696
9697 static void
9698 notify_send(dns_notify_t *notify) {
9699         dns_adbaddrinfo_t *ai;
9700         isc_sockaddr_t dst;
9701         isc_result_t result;
9702         dns_notify_t *new = NULL;
9703
9704         /*
9705          * Zone lock held by caller.
9706          */
9707         REQUIRE(DNS_NOTIFY_VALID(notify));
9708         REQUIRE(LOCKED_ZONE(notify->zone));
9709
9710         for (ai = ISC_LIST_HEAD(notify->find->list);
9711              ai != NULL;
9712              ai = ISC_LIST_NEXT(ai, publink)) {
9713                 dst = ai->sockaddr;
9714                 if (notify_isqueued(notify->zone, NULL, &dst))
9715                         continue;
9716                 if (notify_isself(notify->zone, &dst))
9717                         continue;
9718                 new = NULL;
9719                 result = notify_create(notify->mctx,
9720                                        (notify->flags & DNS_NOTIFY_NOSOA),
9721                                        &new);
9722                 if (result != ISC_R_SUCCESS)
9723                         goto cleanup;
9724                 zone_iattach(notify->zone, &new->zone);
9725                 ISC_LIST_APPEND(new->zone->notifies, new, link);
9726                 new->dst = dst;
9727                 result = notify_send_queue(new);
9728                 if (result != ISC_R_SUCCESS)
9729                         goto cleanup;
9730                 new = NULL;
9731         }
9732
9733  cleanup:
9734         if (new != NULL)
9735                 notify_destroy(new, ISC_TRUE);
9736 }
9737
9738 void
9739 dns_zone_notify(dns_zone_t *zone) {
9740         isc_time_t now;
9741
9742         REQUIRE(DNS_ZONE_VALID(zone));
9743
9744         LOCK_ZONE(zone);
9745         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9746
9747         TIME_NOW(&now);
9748         zone_settimer(zone, &now);
9749         UNLOCK_ZONE(zone);
9750 }
9751
9752 static void
9753 zone_notify(dns_zone_t *zone, isc_time_t *now) {
9754         dns_dbnode_t *node = NULL;
9755         dns_db_t *zonedb = NULL;
9756         dns_dbversion_t *version = NULL;
9757         dns_name_t *origin = NULL;
9758         dns_name_t master;
9759         dns_rdata_ns_t ns;
9760         dns_rdata_soa_t soa;
9761         isc_uint32_t serial;
9762         dns_rdata_t rdata = DNS_RDATA_INIT;
9763         dns_rdataset_t nsrdset;
9764         dns_rdataset_t soardset;
9765         isc_result_t result;
9766         dns_notify_t *notify = NULL;
9767         unsigned int i;
9768         isc_sockaddr_t dst;
9769         isc_boolean_t isqueued;
9770         dns_notifytype_t notifytype;
9771         unsigned int flags = 0;
9772         isc_boolean_t loggednotify = ISC_FALSE;
9773
9774         REQUIRE(DNS_ZONE_VALID(zone));
9775
9776         LOCK_ZONE(zone);
9777         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9778         notifytype = zone->notifytype;
9779         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
9780         UNLOCK_ZONE(zone);
9781
9782         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
9783                 return;
9784
9785         if (notifytype == dns_notifytype_no)
9786                 return;
9787
9788         if (notifytype == dns_notifytype_masteronly &&
9789             zone->type != dns_zone_master)
9790                 return;
9791
9792         origin = &zone->origin;
9793
9794         /*
9795          * If the zone is dialup we are done as we don't want to send
9796          * the current soa so as to force a refresh query.
9797          */
9798         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
9799                 flags |= DNS_NOTIFY_NOSOA;
9800
9801         /*
9802          * Get SOA RRset.
9803          */
9804         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9805         if (zone->db != NULL)
9806                 dns_db_attach(zone->db, &zonedb);
9807         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9808         if (zonedb == NULL)
9809                 return;
9810         dns_db_currentversion(zonedb, &version);
9811         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
9812         if (result != ISC_R_SUCCESS)
9813                 goto cleanup1;
9814
9815         dns_rdataset_init(&soardset);
9816         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
9817                                      dns_rdatatype_none, 0, &soardset, NULL);
9818         if (result != ISC_R_SUCCESS)
9819                 goto cleanup2;
9820
9821         /*
9822          * Find serial and master server's name.
9823          */
9824         dns_name_init(&master, NULL);
9825         result = dns_rdataset_first(&soardset);
9826         if (result != ISC_R_SUCCESS)
9827                 goto cleanup3;
9828         dns_rdataset_current(&soardset, &rdata);
9829         result = dns_rdata_tostruct(&rdata, &soa, NULL);
9830         RUNTIME_CHECK(result == ISC_R_SUCCESS);
9831         dns_rdata_reset(&rdata);
9832         result = dns_name_dup(&soa.origin, zone->mctx, &master);
9833         serial = soa.serial;
9834         dns_rdataset_disassociate(&soardset);
9835         if (result != ISC_R_SUCCESS)
9836                 goto cleanup3;
9837
9838         /*
9839          * Enqueue notify requests for 'also-notify' servers.
9840          */
9841         LOCK_ZONE(zone);
9842         for (i = 0; i < zone->notifycnt; i++) {
9843                 dns_tsigkey_t *key = NULL;
9844
9845                 dst = zone->notify[i];
9846                 if (notify_isqueued(zone, NULL, &dst))
9847                         continue;
9848
9849                 result = notify_create(zone->mctx, flags, &notify);
9850                 if (result != ISC_R_SUCCESS)
9851                         continue;
9852
9853                 zone_iattach(zone, &notify->zone);
9854                 notify->dst = dst;
9855
9856                 if ((zone->notifykeynames != NULL) &&
9857                     (zone->notifykeynames[i] != NULL)) {
9858                         dns_view_t *view = dns_zone_getview(zone);
9859                         dns_name_t *keyname = zone->notifykeynames[i];
9860                         result = dns_view_gettsig(view, keyname, &key);
9861                         if (result == ISC_R_SUCCESS) {
9862                                 notify->key = key;
9863                                 key = NULL;
9864                         }
9865                 }
9866
9867                 ISC_LIST_APPEND(zone->notifies, notify, link);
9868                 result = notify_send_queue(notify);
9869                 if (result != ISC_R_SUCCESS)
9870                         notify_destroy(notify, ISC_TRUE);
9871                 if (!loggednotify) {
9872                         notify_log(zone, ISC_LOG_INFO,
9873                                    "sending notifies (serial %u)",
9874                                    serial);
9875                         loggednotify = ISC_TRUE;
9876                 }
9877                 notify = NULL;
9878         }
9879         UNLOCK_ZONE(zone);
9880
9881         if (notifytype == dns_notifytype_explicit)
9882                 goto cleanup3;
9883
9884         /*
9885          * Process NS RRset to generate notifies.
9886          */
9887
9888         dns_rdataset_init(&nsrdset);
9889         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
9890                                      dns_rdatatype_none, 0, &nsrdset, NULL);
9891         if (result != ISC_R_SUCCESS)
9892                 goto cleanup3;
9893
9894         result = dns_rdataset_first(&nsrdset);
9895         while (result == ISC_R_SUCCESS) {
9896                 dns_rdataset_current(&nsrdset, &rdata);
9897                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
9898                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9899                 dns_rdata_reset(&rdata);
9900                 /*
9901                  * Don't notify the master server unless explicitly
9902                  * configured to do so.
9903                  */
9904                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
9905                     dns_name_compare(&master, &ns.name) == 0) {
9906                         result = dns_rdataset_next(&nsrdset);
9907                         continue;
9908                 }
9909
9910                 if (!loggednotify) {
9911                         notify_log(zone, ISC_LOG_INFO,
9912                                    "sending notifies (serial %u)",
9913                                    serial);
9914                         loggednotify = ISC_TRUE;
9915                 }
9916
9917                 LOCK_ZONE(zone);
9918                 isqueued = notify_isqueued(zone, &ns.name, NULL);
9919                 UNLOCK_ZONE(zone);
9920                 if (isqueued) {
9921                         result = dns_rdataset_next(&nsrdset);
9922                         continue;
9923                 }
9924                 result = notify_create(zone->mctx, flags, &notify);
9925                 if (result != ISC_R_SUCCESS)
9926                         continue;
9927                 dns_zone_iattach(zone, &notify->zone);
9928                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
9929                 if (result != ISC_R_SUCCESS) {
9930                         LOCK_ZONE(zone);
9931                         notify_destroy(notify, ISC_TRUE);
9932                         UNLOCK_ZONE(zone);
9933                         continue;
9934                 }
9935                 LOCK_ZONE(zone);
9936                 ISC_LIST_APPEND(zone->notifies, notify, link);
9937                 UNLOCK_ZONE(zone);
9938                 notify_find_address(notify);
9939                 notify = NULL;
9940                 result = dns_rdataset_next(&nsrdset);
9941         }
9942         dns_rdataset_disassociate(&nsrdset);
9943
9944  cleanup3:
9945         if (dns_name_dynamic(&master))
9946                 dns_name_free(&master, zone->mctx);
9947  cleanup2:
9948         dns_db_detachnode(zonedb, &node);
9949  cleanup1:
9950         dns_db_closeversion(zonedb, &version, ISC_FALSE);
9951         dns_db_detach(&zonedb);
9952 }
9953
9954 /***
9955  *** Private
9956  ***/
9957
9958 static inline isc_result_t
9959 save_nsrrset(dns_message_t *message, dns_name_t *name,
9960              dns_db_t *db, dns_dbversion_t *version)
9961 {
9962         dns_rdataset_t *nsrdataset = NULL;
9963         dns_rdataset_t *rdataset = NULL;
9964         dns_dbnode_t *node = NULL;
9965         dns_rdata_ns_t ns;
9966         isc_result_t result;
9967         dns_rdata_t rdata = DNS_RDATA_INIT;
9968
9969         /*
9970          * Extract NS RRset from message.
9971          */
9972         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
9973                                       dns_rdatatype_ns, dns_rdatatype_none,
9974                                       NULL, &nsrdataset);
9975         if (result != ISC_R_SUCCESS)
9976                 goto fail;
9977
9978         /*
9979          * Add NS rdataset.
9980          */
9981         result = dns_db_findnode(db, name, ISC_TRUE, &node);
9982         if (result != ISC_R_SUCCESS)
9983                 goto fail;
9984         result = dns_db_addrdataset(db, node, version, 0,
9985                                     nsrdataset, 0, NULL);
9986         dns_db_detachnode(db, &node);
9987         if (result != ISC_R_SUCCESS)
9988                 goto fail;
9989         /*
9990          * Add glue rdatasets.
9991          */
9992         for (result = dns_rdataset_first(nsrdataset);
9993              result == ISC_R_SUCCESS;
9994              result = dns_rdataset_next(nsrdataset)) {
9995                 dns_rdataset_current(nsrdataset, &rdata);
9996                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
9997                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9998                 dns_rdata_reset(&rdata);
9999                 if (!dns_name_issubdomain(&ns.name, name))
10000                         continue;
10001                 rdataset = NULL;
10002                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10003                                               &ns.name, dns_rdatatype_aaaa,
10004                                               dns_rdatatype_none, NULL,
10005                                               &rdataset);
10006                 if (result == ISC_R_SUCCESS) {
10007                         result = dns_db_findnode(db, &ns.name,
10008                                                  ISC_TRUE, &node);
10009                         if (result != ISC_R_SUCCESS)
10010                                 goto fail;
10011                         result = dns_db_addrdataset(db, node, version, 0,
10012                                                     rdataset, 0, NULL);
10013                         dns_db_detachnode(db, &node);
10014                         if (result != ISC_R_SUCCESS)
10015                                 goto fail;
10016                 }
10017                 rdataset = NULL;
10018                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10019                                               &ns.name, dns_rdatatype_a,
10020                                               dns_rdatatype_none, NULL,
10021                                               &rdataset);
10022                 if (result == ISC_R_SUCCESS) {
10023                         result = dns_db_findnode(db, &ns.name,
10024                                                  ISC_TRUE, &node);
10025                         if (result != ISC_R_SUCCESS)
10026                                 goto fail;
10027                         result = dns_db_addrdataset(db, node, version, 0,
10028                                                     rdataset, 0, NULL);
10029                         dns_db_detachnode(db, &node);
10030                         if (result != ISC_R_SUCCESS)
10031                                 goto fail;
10032                 }
10033         }
10034         if (result != ISC_R_NOMORE)
10035                 goto fail;
10036
10037         return (ISC_R_SUCCESS);
10038
10039 fail:
10040         return (result);
10041 }
10042
10043 static void
10044 stub_callback(isc_task_t *task, isc_event_t *event) {
10045         const char me[] = "stub_callback";
10046         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10047         dns_stub_t *stub = NULL;
10048         dns_message_t *msg = NULL;
10049         dns_zone_t *zone = NULL;
10050         char master[ISC_SOCKADDR_FORMATSIZE];
10051         char source[ISC_SOCKADDR_FORMATSIZE];
10052         isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
10053         isc_result_t result;
10054         isc_time_t now;
10055         isc_boolean_t exiting = ISC_FALSE;
10056         isc_interval_t i;
10057         unsigned int j, soacount;
10058
10059         stub = revent->ev_arg;
10060         INSIST(DNS_STUB_VALID(stub));
10061
10062         UNUSED(task);
10063
10064         zone = stub->zone;
10065
10066         ENTER;
10067
10068         TIME_NOW(&now);
10069
10070         LOCK_ZONE(zone);
10071
10072         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10073                 zone_debuglog(zone, me, 1, "exiting");
10074                 exiting = ISC_TRUE;
10075                 goto next_master;
10076         }
10077
10078         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10079         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10080
10081         if (revent->result != ISC_R_SUCCESS) {
10082                 if (revent->result == ISC_R_TIMEDOUT &&
10083                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10084                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10085                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10086                                      "refreshing stub: timeout retrying "
10087                                      " without EDNS master %s (source %s)",
10088                                      master, source);
10089                         goto same_master;
10090                 }
10091                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
10092                                            &zone->sourceaddr, &now);
10093                 dns_zone_log(zone, ISC_LOG_INFO,
10094                              "could not refresh stub from master %s"
10095                              " (source %s): %s", master, source,
10096                              dns_result_totext(revent->result));
10097                 goto next_master;
10098         }
10099
10100         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10101         if (result != ISC_R_SUCCESS)
10102                 goto next_master;
10103
10104         result = dns_request_getresponse(revent->request, msg, 0);
10105         if (result != ISC_R_SUCCESS)
10106                 goto next_master;
10107
10108         /*
10109          * Unexpected rcode.
10110          */
10111         if (msg->rcode != dns_rcode_noerror) {
10112                 char rcode[128];
10113                 isc_buffer_t rb;
10114
10115                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10116                 (void)dns_rcode_totext(msg->rcode, &rb);
10117
10118                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10119                     (msg->rcode == dns_rcode_servfail ||
10120                      msg->rcode == dns_rcode_notimp ||
10121                      msg->rcode == dns_rcode_formerr)) {
10122                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10123                                      "refreshing stub: rcode (%.*s) retrying "
10124                                      "without EDNS master %s (source %s)",
10125                                      (int)rb.used, rcode, master, source);
10126                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10127                         goto same_master;
10128                 }
10129
10130                 dns_zone_log(zone, ISC_LOG_INFO,
10131                              "refreshing stub: "
10132                              "unexpected rcode (%.*s) from %s (source %s)",
10133                              (int)rb.used, rcode, master, source);
10134                 goto next_master;
10135         }
10136
10137         /*
10138          * We need complete messages.
10139          */
10140         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10141                 if (dns_request_usedtcp(revent->request)) {
10142                         dns_zone_log(zone, ISC_LOG_INFO,
10143                                      "refreshing stub: truncated TCP "
10144                                      "response from master %s (source %s)",
10145                                      master, source);
10146                         goto next_master;
10147                 }
10148                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10149                 goto same_master;
10150         }
10151
10152         /*
10153          * If non-auth log and next master.
10154          */
10155         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10156                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10157                              "non-authoritative answer from "
10158                              "master %s (source %s)", master, source);
10159                 goto next_master;
10160         }
10161
10162         /*
10163          * Sanity checks.
10164          */
10165         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10166         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
10167
10168         if (cnamecnt != 0) {
10169                 dns_zone_log(zone, ISC_LOG_INFO,
10170                              "refreshing stub: unexpected CNAME response "
10171                              "from master %s (source %s)", master, source);
10172                 goto next_master;
10173         }
10174
10175         if (nscnt == 0) {
10176                 dns_zone_log(zone, ISC_LOG_INFO,
10177                              "refreshing stub: no NS records in response "
10178                              "from master %s (source %s)", master, source);
10179                 goto next_master;
10180         }
10181
10182         /*
10183          * Save answer.
10184          */
10185         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
10186         if (result != ISC_R_SUCCESS) {
10187                 dns_zone_log(zone, ISC_LOG_INFO,
10188                              "refreshing stub: unable to save NS records "
10189                              "from master %s (source %s)", master, source);
10190                 goto next_master;
10191         }
10192
10193         /*
10194          * Tidy up.
10195          */
10196         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
10197         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
10198         if (zone->db == NULL)
10199                 zone_attachdb(zone, stub->db);
10200         result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
10201                                   &refresh, &retry, &expire, NULL, NULL);
10202         if (result == ISC_R_SUCCESS && soacount > 0U) {
10203                 zone->refresh = RANGE(refresh, zone->minrefresh,
10204                                       zone->maxrefresh);
10205                 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
10206                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
10207                                      DNS_MAX_EXPIRE);
10208                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10209         }
10210         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
10211         dns_db_detach(&stub->db);
10212
10213         dns_message_destroy(&msg);
10214         isc_event_free(&event);
10215         dns_request_destroy(&zone->request);
10216
10217         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10218         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10219         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10220         isc_interval_set(&i, zone->expire, 0);
10221         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10222
10223         if (zone->masterfile != NULL)
10224                 zone_needdump(zone, 0);
10225
10226         zone_settimer(zone, &now);
10227         goto free_stub;
10228
10229  next_master:
10230         if (stub->version != NULL)
10231                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
10232         if (stub->db != NULL)
10233                 dns_db_detach(&stub->db);
10234         if (msg != NULL)
10235                 dns_message_destroy(&msg);
10236         isc_event_free(&event);
10237         dns_request_destroy(&zone->request);
10238         /*
10239          * Skip to next failed / untried master.
10240          */
10241         do {
10242                 zone->curmaster++;
10243         } while (zone->curmaster < zone->masterscnt &&
10244                  zone->mastersok[zone->curmaster]);
10245         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10246         if (exiting || zone->curmaster >= zone->masterscnt) {
10247                 isc_boolean_t done = ISC_TRUE;
10248                 if (!exiting &&
10249                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10250                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10251                         /*
10252                          * Did we get a good answer from all the masters?
10253                          */
10254                         for (j = 0; j < zone->masterscnt; j++)
10255                                 if (zone->mastersok[j] == ISC_FALSE) {
10256                                         done = ISC_FALSE;
10257                                         break;
10258                                 }
10259                 } else
10260                         done = ISC_TRUE;
10261                 if (!done) {
10262                         zone->curmaster = 0;
10263                         /*
10264                          * Find the next failed master.
10265                          */
10266                         while (zone->curmaster < zone->masterscnt &&
10267                                zone->mastersok[zone->curmaster])
10268                                 zone->curmaster++;
10269                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10270                 } else {
10271                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10272
10273                         zone_settimer(zone, &now);
10274                         goto free_stub;
10275                 }
10276         }
10277         queue_soa_query(zone);
10278         goto free_stub;
10279
10280  same_master:
10281         if (msg != NULL)
10282                 dns_message_destroy(&msg);
10283         isc_event_free(&event);
10284         dns_request_destroy(&zone->request);
10285         ns_query(zone, NULL, stub);
10286         UNLOCK_ZONE(zone);
10287         goto done;
10288
10289  free_stub:
10290         UNLOCK_ZONE(zone);
10291         stub->magic = 0;
10292         dns_zone_idetach(&stub->zone);
10293         INSIST(stub->db == NULL);
10294         INSIST(stub->version == NULL);
10295         isc_mem_put(stub->mctx, stub, sizeof(*stub));
10296
10297  done:
10298         INSIST(event == NULL);
10299         return;
10300 }
10301
10302 /*
10303  * An SOA query has finished (successfully or not).
10304  */
10305 static void
10306 refresh_callback(isc_task_t *task, isc_event_t *event) {
10307         const char me[] = "refresh_callback";
10308         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10309         dns_zone_t *zone;
10310         dns_message_t *msg = NULL;
10311         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
10312         isc_time_t now;
10313         char master[ISC_SOCKADDR_FORMATSIZE];
10314         char source[ISC_SOCKADDR_FORMATSIZE];
10315         dns_rdataset_t *rdataset = NULL;
10316         dns_rdata_t rdata = DNS_RDATA_INIT;
10317         dns_rdata_soa_t soa;
10318         isc_result_t result;
10319         isc_uint32_t serial, oldserial = 0;
10320         unsigned int j;
10321         isc_boolean_t do_queue_xfrin = ISC_FALSE;
10322
10323         zone = revent->ev_arg;
10324         INSIST(DNS_ZONE_VALID(zone));
10325
10326         UNUSED(task);
10327
10328         ENTER;
10329
10330         TIME_NOW(&now);
10331
10332         LOCK_ZONE(zone);
10333
10334         /*
10335          * if timeout log and next master;
10336          */
10337
10338         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10339         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10340
10341         if (revent->result != ISC_R_SUCCESS) {
10342                 if (revent->result == ISC_R_TIMEDOUT &&
10343                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10344                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10345                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10346                                      "refresh: timeout retrying without EDNS "
10347                                      "master %s (source %s)", master, source);
10348                         goto same_master;
10349                 }
10350                 if (revent->result == ISC_R_TIMEDOUT &&
10351                     !dns_request_usedtcp(revent->request)) {
10352                         dns_zone_log(zone, ISC_LOG_INFO,
10353                                      "refresh: retry limit for "
10354                                      "master %s exceeded (source %s)",
10355                                      master, source);
10356                         /* Try with slave with TCP. */
10357                         if ((zone->type == dns_zone_slave ||
10358                              zone->type == dns_zone_redirect) &&
10359                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
10360                                 if (!dns_zonemgr_unreachable(zone->zmgr,
10361                                                              &zone->masteraddr,
10362                                                              &zone->sourceaddr,
10363                                                              &now))
10364                                 {
10365                                         DNS_ZONE_SETFLAG(zone,
10366                                                      DNS_ZONEFLG_SOABEFOREAXFR);
10367                                         goto tcp_transfer;
10368                                 }
10369                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10370                                              "refresh: skipped tcp fallback "
10371                                              "as master %s (source %s) is "
10372                                              "unreachable (cached)",
10373                                               master, source);
10374                         }
10375                 } else
10376                         dns_zone_log(zone, ISC_LOG_INFO,
10377                                      "refresh: failure trying master "
10378                                      "%s (source %s): %s", master, source,
10379                                      dns_result_totext(revent->result));
10380                 goto next_master;
10381         }
10382
10383         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10384         if (result != ISC_R_SUCCESS)
10385                 goto next_master;
10386         result = dns_request_getresponse(revent->request, msg, 0);
10387         if (result != ISC_R_SUCCESS) {
10388                 dns_zone_log(zone, ISC_LOG_INFO,
10389                              "refresh: failure trying master "
10390                              "%s (source %s): %s", master, source,
10391                              dns_result_totext(result));
10392                 goto next_master;
10393         }
10394
10395         /*
10396          * Unexpected rcode.
10397          */
10398         if (msg->rcode != dns_rcode_noerror) {
10399                 char rcode[128];
10400                 isc_buffer_t rb;
10401
10402                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10403                 (void)dns_rcode_totext(msg->rcode, &rb);
10404
10405                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10406                     (msg->rcode == dns_rcode_servfail ||
10407                      msg->rcode == dns_rcode_notimp ||
10408                      msg->rcode == dns_rcode_formerr)) {
10409                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10410                                      "refresh: rcode (%.*s) retrying without "
10411                                      "EDNS master %s (source %s)",
10412                                      (int)rb.used, rcode, master, source);
10413                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10414                         goto same_master;
10415                 }
10416                 dns_zone_log(zone, ISC_LOG_INFO,
10417                              "refresh: unexpected rcode (%.*s) from "
10418                              "master %s (source %s)", (int)rb.used, rcode,
10419                              master, source);
10420                 /*
10421                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
10422                  */
10423                 if (msg->rcode == dns_rcode_refused &&
10424                     (zone->type == dns_zone_slave ||
10425                      zone->type == dns_zone_redirect))
10426                         goto tcp_transfer;
10427                 goto next_master;
10428         }
10429
10430         /*
10431          * If truncated punt to zone transfer which will query again.
10432          */
10433         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10434                 if (zone->type == dns_zone_slave ||
10435                     zone->type == dns_zone_redirect) {
10436                         dns_zone_log(zone, ISC_LOG_INFO,
10437                                      "refresh: truncated UDP answer, "
10438                                      "initiating TCP zone xfer "
10439                                      "for master %s (source %s)",
10440                                      master, source);
10441                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
10442                         goto tcp_transfer;
10443                 } else {
10444                         INSIST(zone->type == dns_zone_stub);
10445                         if (dns_request_usedtcp(revent->request)) {
10446                                 dns_zone_log(zone, ISC_LOG_INFO,
10447                                              "refresh: truncated TCP response "
10448                                              "from master %s (source %s)",
10449                                              master, source);
10450                                 goto next_master;
10451                         }
10452                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10453                         goto same_master;
10454                 }
10455         }
10456
10457         /*
10458          * if non-auth log and next master;
10459          */
10460         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10461                 dns_zone_log(zone, ISC_LOG_INFO,
10462                              "refresh: non-authoritative answer from "
10463                              "master %s (source %s)", master, source);
10464                 goto next_master;
10465         }
10466
10467         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10468         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
10469         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
10470         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
10471                                  dns_rdatatype_soa);
10472
10473         /*
10474          * There should not be a CNAME record at top of zone.
10475          */
10476         if (cnamecnt != 0) {
10477                 dns_zone_log(zone, ISC_LOG_INFO,
10478                              "refresh: CNAME at top of zone "
10479                              "in master %s (source %s)", master, source);
10480                 goto next_master;
10481         }
10482
10483         /*
10484          * if referral log and next master;
10485          */
10486         if (soacnt == 0 && soacount == 0 && nscount != 0) {
10487                 dns_zone_log(zone, ISC_LOG_INFO,
10488                              "refresh: referral response "
10489                              "from master %s (source %s)", master, source);
10490                 goto next_master;
10491         }
10492
10493         /*
10494          * if nodata log and next master;
10495          */
10496         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
10497                 dns_zone_log(zone, ISC_LOG_INFO,
10498                              "refresh: NODATA response "
10499                              "from master %s (source %s)", master, source);
10500                 goto next_master;
10501         }
10502
10503         /*
10504          * Only one soa at top of zone.
10505          */
10506         if (soacnt != 1) {
10507                 dns_zone_log(zone, ISC_LOG_INFO,
10508                              "refresh: answer SOA count (%d) != 1 "
10509                              "from master %s (source %s)",
10510                              soacnt, master, source);
10511                 goto next_master;
10512         }
10513
10514         /*
10515          * Extract serial
10516          */
10517         rdataset = NULL;
10518         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
10519                                       dns_rdatatype_soa, dns_rdatatype_none,
10520                                       NULL, &rdataset);
10521         if (result != ISC_R_SUCCESS) {
10522                 dns_zone_log(zone, ISC_LOG_INFO,
10523                              "refresh: unable to get SOA record "
10524                              "from master %s (source %s)", master, source);
10525                 goto next_master;
10526         }
10527
10528         result = dns_rdataset_first(rdataset);
10529         if (result != ISC_R_SUCCESS) {
10530                 dns_zone_log(zone, ISC_LOG_INFO,
10531                              "refresh: dns_rdataset_first() failed");
10532                 goto next_master;
10533         }
10534
10535         dns_rdataset_current(rdataset, &rdata);
10536         result = dns_rdata_tostruct(&rdata, &soa, NULL);
10537         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10538
10539         serial = soa.serial;
10540         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10541                 unsigned int soacount;
10542                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
10543                                           &oldserial, NULL, NULL, NULL, NULL,
10544                                           NULL);
10545                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10546                 RUNTIME_CHECK(soacount > 0U);
10547                 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
10548                               serial, oldserial);
10549         } else
10550                 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
10551                               serial);
10552
10553         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
10554             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
10555             isc_serial_gt(serial, oldserial)) {
10556                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
10557                                             &zone->sourceaddr, &now))
10558                 {
10559                         dns_zone_log(zone, ISC_LOG_INFO,
10560                                      "refresh: skipping %s as master %s "
10561                                      "(source %s) is unreachable (cached)",
10562                                      (zone->type == dns_zone_slave ||
10563                                       zone->type == dns_zone_redirect) ?
10564                                      "zone transfer" : "NS query",
10565                                      master, source);
10566                         goto next_master;
10567                 }
10568  tcp_transfer:
10569                 isc_event_free(&event);
10570                 dns_request_destroy(&zone->request);
10571                 if (zone->type == dns_zone_slave ||
10572                     zone->type == dns_zone_redirect) {
10573                         do_queue_xfrin = ISC_TRUE;
10574                 } else {
10575                         INSIST(zone->type == dns_zone_stub);
10576                         ns_query(zone, rdataset, NULL);
10577                 }
10578                 if (msg != NULL)
10579                         dns_message_destroy(&msg);
10580         } else if (isc_serial_eq(soa.serial, oldserial)) {
10581                 if (zone->masterfile != NULL) {
10582                         result = ISC_R_FAILURE;
10583                         if (zone->journal != NULL)
10584                                 result = isc_file_settime(zone->journal, &now);
10585                         if (result == ISC_R_SUCCESS &&
10586                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10587                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10588                                 result = isc_file_settime(zone->masterfile,
10589                                                           &now);
10590                         } else if (result != ISC_R_SUCCESS)
10591                                 result = isc_file_settime(zone->masterfile,
10592                                                           &now);
10593                         /* Someone removed the file from underneath us! */
10594                         if (result == ISC_R_FILENOTFOUND) {
10595                                 zone_needdump(zone, DNS_DUMP_DELAY);
10596                         } else if (result != ISC_R_SUCCESS)
10597                                 dns_zone_log(zone, ISC_LOG_ERROR,
10598                                              "refresh: could not set file "
10599                                              "modification time of '%s': %s",
10600                                              zone->masterfile,
10601                                              dns_result_totext(result));
10602                 }
10603                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10604                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10605                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10606                 goto next_master;
10607         } else {
10608                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
10609                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
10610                                      "received from master %s < ours (%u)",
10611                                      soa.serial, master, oldserial);
10612                 else
10613                         zone_debuglog(zone, me, 1, "ahead");
10614                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10615                 goto next_master;
10616         }
10617         if (msg != NULL)
10618                 dns_message_destroy(&msg);
10619         goto detach;
10620
10621  next_master:
10622         if (msg != NULL)
10623                 dns_message_destroy(&msg);
10624         isc_event_free(&event);
10625         dns_request_destroy(&zone->request);
10626         /*
10627          * Skip to next failed / untried master.
10628          */
10629         do {
10630                 zone->curmaster++;
10631         } while (zone->curmaster < zone->masterscnt &&
10632                  zone->mastersok[zone->curmaster]);
10633         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10634         if (zone->curmaster >= zone->masterscnt) {
10635                 isc_boolean_t done = ISC_TRUE;
10636                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10637                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10638                         /*
10639                          * Did we get a good answer from all the masters?
10640                          */
10641                         for (j = 0; j < zone->masterscnt; j++)
10642                                 if (zone->mastersok[j] == ISC_FALSE) {
10643                                         done = ISC_FALSE;
10644                                         break;
10645                                 }
10646                 } else
10647                         done = ISC_TRUE;
10648                 if (!done) {
10649                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10650                         zone->curmaster = 0;
10651                         /*
10652                          * Find the next failed master.
10653                          */
10654                         while (zone->curmaster < zone->masterscnt &&
10655                                zone->mastersok[zone->curmaster])
10656                                 zone->curmaster++;
10657                         goto requeue;
10658                 }
10659                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10660                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
10661                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10662                         zone->refreshtime = now;
10663                 }
10664                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10665                 zone_settimer(zone, &now);
10666                 goto detach;
10667         }
10668
10669  requeue:
10670         queue_soa_query(zone);
10671         goto detach;
10672
10673  same_master:
10674         if (msg != NULL)
10675                 dns_message_destroy(&msg);
10676         isc_event_free(&event);
10677         dns_request_destroy(&zone->request);
10678         queue_soa_query(zone);
10679
10680  detach:
10681         UNLOCK_ZONE(zone);
10682         if (do_queue_xfrin)
10683                 queue_xfrin(zone);
10684         dns_zone_idetach(&zone);
10685         return;
10686 }
10687
10688 static void
10689 queue_soa_query(dns_zone_t *zone) {
10690         const char me[] = "queue_soa_query";
10691         isc_event_t *e;
10692         dns_zone_t *dummy = NULL;
10693         isc_result_t result;
10694
10695         ENTER;
10696         /*
10697          * Locked by caller
10698          */
10699         REQUIRE(LOCKED_ZONE(zone));
10700
10701         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10702                 cancel_refresh(zone);
10703                 return;
10704         }
10705
10706         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
10707                                soa_query, zone, sizeof(isc_event_t));
10708         if (e == NULL) {
10709                 cancel_refresh(zone);
10710                 return;
10711         }
10712
10713         /*
10714          * Attach so that we won't clean up
10715          * until the event is delivered.
10716          */
10717         zone_iattach(zone, &dummy);
10718
10719         e->ev_arg = zone;
10720         e->ev_sender = NULL;
10721         result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
10722         if (result != ISC_R_SUCCESS) {
10723                 zone_idetach(&dummy);
10724                 isc_event_free(&e);
10725                 cancel_refresh(zone);
10726         }
10727 }
10728
10729 static inline isc_result_t
10730 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
10731              dns_message_t **messagep)
10732 {
10733         dns_message_t *message = NULL;
10734         dns_name_t *qname = NULL;
10735         dns_rdataset_t *qrdataset = NULL;
10736         isc_result_t result;
10737
10738         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10739                                     &message);
10740         if (result != ISC_R_SUCCESS)
10741                 goto cleanup;
10742
10743         message->opcode = dns_opcode_query;
10744         message->rdclass = zone->rdclass;
10745
10746         result = dns_message_gettempname(message, &qname);
10747         if (result != ISC_R_SUCCESS)
10748                 goto cleanup;
10749
10750         result = dns_message_gettemprdataset(message, &qrdataset);
10751         if (result != ISC_R_SUCCESS)
10752                 goto cleanup;
10753
10754         /*
10755          * Make question.
10756          */
10757         dns_name_init(qname, NULL);
10758         dns_name_clone(&zone->origin, qname);
10759         dns_rdataset_init(qrdataset);
10760         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
10761         ISC_LIST_APPEND(qname->list, qrdataset, link);
10762         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
10763
10764         *messagep = message;
10765         return (ISC_R_SUCCESS);
10766
10767  cleanup:
10768         if (qname != NULL)
10769                 dns_message_puttempname(message, &qname);
10770         if (qrdataset != NULL)
10771                 dns_message_puttemprdataset(message, &qrdataset);
10772         if (message != NULL)
10773                 dns_message_destroy(&message);
10774         return (result);
10775 }
10776
10777 static isc_result_t
10778 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
10779         dns_rdataset_t *rdataset = NULL;
10780         dns_rdatalist_t *rdatalist = NULL;
10781         dns_rdata_t *rdata = NULL;
10782         isc_result_t result;
10783
10784         result = dns_message_gettemprdatalist(message, &rdatalist);
10785         if (result != ISC_R_SUCCESS)
10786                 goto cleanup;
10787         result = dns_message_gettemprdata(message, &rdata);
10788         if (result != ISC_R_SUCCESS)
10789                 goto cleanup;
10790         result = dns_message_gettemprdataset(message, &rdataset);
10791         if (result != ISC_R_SUCCESS)
10792                 goto cleanup;
10793         dns_rdataset_init(rdataset);
10794
10795         rdatalist->type = dns_rdatatype_opt;
10796         rdatalist->covers = 0;
10797
10798         /*
10799          * Set Maximum UDP buffer size.
10800          */
10801         rdatalist->rdclass = udpsize;
10802
10803         /*
10804          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
10805          */
10806         rdatalist->ttl = 0;
10807
10808         /* Set EDNS options if applicable */
10809         if (reqnsid) {
10810                 unsigned char data[4];
10811                 isc_buffer_t buf;
10812
10813                 isc_buffer_init(&buf, data, sizeof(data));
10814                 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
10815                 isc_buffer_putuint16(&buf, 0);
10816                 rdata->data = data;
10817                 rdata->length = sizeof(data);
10818         } else {
10819                 rdata->data = NULL;
10820                 rdata->length = 0;
10821         }
10822
10823         rdata->rdclass = rdatalist->rdclass;
10824         rdata->type = rdatalist->type;
10825         rdata->flags = 0;
10826
10827         ISC_LIST_INIT(rdatalist->rdata);
10828         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
10829         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
10830                       == ISC_R_SUCCESS);
10831
10832         return (dns_message_setopt(message, rdataset));
10833
10834  cleanup:
10835         if (rdatalist != NULL)
10836                 dns_message_puttemprdatalist(message, &rdatalist);
10837         if (rdataset != NULL)
10838                 dns_message_puttemprdataset(message, &rdataset);
10839         if (rdata != NULL)
10840                 dns_message_puttemprdata(message, &rdata);
10841
10842         return (result);
10843 }
10844
10845 static void
10846 soa_query(isc_task_t *task, isc_event_t *event) {
10847         const char me[] = "soa_query";
10848         isc_result_t result = ISC_R_FAILURE;
10849         dns_message_t *message = NULL;
10850         dns_zone_t *zone = event->ev_arg;
10851         dns_zone_t *dummy = NULL;
10852         isc_netaddr_t masterip;
10853         dns_tsigkey_t *key = NULL;
10854         isc_uint32_t options;
10855         isc_boolean_t cancel = ISC_TRUE;
10856         int timeout;
10857         isc_boolean_t have_xfrsource, reqnsid;
10858         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10859
10860         REQUIRE(DNS_ZONE_VALID(zone));
10861
10862         UNUSED(task);
10863
10864         ENTER;
10865
10866         LOCK_ZONE(zone);
10867         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
10868             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
10869             zone->view->requestmgr == NULL) {
10870                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10871                         cancel = ISC_FALSE;
10872                 goto cleanup;
10873         }
10874
10875         /*
10876          * XXX Optimisation: Create message when zone is setup and reuse.
10877          */
10878         result = create_query(zone, dns_rdatatype_soa, &message);
10879         if (result != ISC_R_SUCCESS)
10880                 goto cleanup;
10881
10882  again:
10883         INSIST(zone->masterscnt > 0);
10884         INSIST(zone->curmaster < zone->masterscnt);
10885
10886         zone->masteraddr = zone->masters[zone->curmaster];
10887
10888         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10889         /*
10890          * First, look for a tsig key in the master statement, then
10891          * try for a server key.
10892          */
10893         if ((zone->masterkeynames != NULL) &&
10894             (zone->masterkeynames[zone->curmaster] != NULL)) {
10895                 dns_view_t *view = dns_zone_getview(zone);
10896                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10897                 result = dns_view_gettsig(view, keyname, &key);
10898                 if (result != ISC_R_SUCCESS) {
10899                         char namebuf[DNS_NAME_FORMATSIZE];
10900                         dns_name_format(keyname, namebuf, sizeof(namebuf));
10901                         dns_zone_log(zone, ISC_LOG_ERROR,
10902                                      "unable to find key: %s", namebuf);
10903                         goto skip_master;
10904                 }
10905         }
10906         if (key == NULL) {
10907                 result = dns_view_getpeertsig(zone->view, &masterip, &key);
10908                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
10909                         char addrbuf[ISC_NETADDR_FORMATSIZE];
10910                         isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
10911                         dns_zone_log(zone, ISC_LOG_ERROR,
10912                                      "unable to find TSIG key for %s", addrbuf);
10913                         goto skip_master;
10914                 }
10915         }
10916
10917         have_xfrsource = ISC_FALSE;
10918         reqnsid = zone->view->requestnsid;
10919         if (zone->view->peers != NULL) {
10920                 dns_peer_t *peer = NULL;
10921                 isc_boolean_t edns;
10922                 result = dns_peerlist_peerbyaddr(zone->view->peers,
10923                                                  &masterip, &peer);
10924                 if (result == ISC_R_SUCCESS) {
10925                         result = dns_peer_getsupportedns(peer, &edns);
10926                         if (result == ISC_R_SUCCESS && !edns)
10927                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10928                         result = dns_peer_gettransfersource(peer,
10929                                                             &zone->sourceaddr);
10930                         if (result == ISC_R_SUCCESS)
10931                                 have_xfrsource = ISC_TRUE;
10932                         if (zone->view->resolver != NULL)
10933                                 udpsize =
10934                                   dns_resolver_getudpsize(zone->view->resolver);
10935                         (void)dns_peer_getudpsize(peer, &udpsize);
10936                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
10937                 }
10938         }
10939
10940         switch (isc_sockaddr_pf(&zone->masteraddr)) {
10941         case PF_INET:
10942                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10943                         if (isc_sockaddr_equal(&zone->altxfrsource4,
10944                                                &zone->xfrsource4))
10945                                 goto skip_master;
10946                         zone->sourceaddr = zone->altxfrsource4;
10947                 } else if (!have_xfrsource)
10948                         zone->sourceaddr = zone->xfrsource4;
10949                 break;
10950         case PF_INET6:
10951                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10952                         if (isc_sockaddr_equal(&zone->altxfrsource6,
10953                                                &zone->xfrsource6))
10954                                 goto skip_master;
10955                         zone->sourceaddr = zone->altxfrsource6;
10956                 } else if (!have_xfrsource)
10957                         zone->sourceaddr = zone->xfrsource6;
10958                 break;
10959         default:
10960                 result = ISC_R_NOTIMPLEMENTED;
10961                 goto cleanup;
10962         }
10963
10964         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
10965                   DNS_REQUESTOPT_TCP : 0;
10966
10967         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10968                 result = add_opt(message, udpsize, reqnsid);
10969                 if (result != ISC_R_SUCCESS)
10970                         zone_debuglog(zone, me, 1,
10971                                       "unable to add opt record: %s",
10972                                       dns_result_totext(result));
10973         }
10974
10975         zone_iattach(zone, &dummy);
10976         timeout = 15;
10977         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10978                 timeout = 30;
10979         result = dns_request_createvia2(zone->view->requestmgr, message,
10980                                         &zone->sourceaddr, &zone->masteraddr,
10981                                         options, key, timeout * 3, timeout,
10982                                         zone->task, refresh_callback, zone,
10983                                         &zone->request);
10984         if (result != ISC_R_SUCCESS) {
10985                 zone_idetach(&dummy);
10986                 zone_debuglog(zone, me, 1,
10987                               "dns_request_createvia2() failed: %s",
10988                               dns_result_totext(result));
10989                 goto cleanup;
10990         } else {
10991                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
10992                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
10993                 else
10994                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
10995         }
10996         cancel = ISC_FALSE;
10997
10998  cleanup:
10999         if (key != NULL)
11000                 dns_tsigkey_detach(&key);
11001         if (result != ISC_R_SUCCESS)
11002                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11003         if (message != NULL)
11004                 dns_message_destroy(&message);
11005         if (cancel)
11006                 cancel_refresh(zone);
11007         isc_event_free(&event);
11008         UNLOCK_ZONE(zone);
11009         dns_zone_idetach(&zone);
11010         return;
11011
11012  skip_master:
11013         if (key != NULL)
11014                 dns_tsigkey_detach(&key);
11015         /*
11016          * Skip to next failed / untried master.
11017          */
11018         do {
11019                 zone->curmaster++;
11020         } while (zone->curmaster < zone->masterscnt &&
11021                  zone->mastersok[zone->curmaster]);
11022         if (zone->curmaster < zone->masterscnt)
11023                 goto again;
11024         zone->curmaster = 0;
11025         goto cleanup;
11026 }
11027
11028 static void
11029 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
11030         const char me[] = "ns_query";
11031         isc_result_t result;
11032         dns_message_t *message = NULL;
11033         isc_netaddr_t masterip;
11034         dns_tsigkey_t *key = NULL;
11035         dns_dbnode_t *node = NULL;
11036         int timeout;
11037         isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
11038         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11039
11040         REQUIRE(DNS_ZONE_VALID(zone));
11041         REQUIRE(LOCKED_ZONE(zone));
11042         REQUIRE((soardataset != NULL && stub == NULL) ||
11043                 (soardataset == NULL && stub != NULL));
11044         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
11045
11046         ENTER;
11047
11048         if (stub == NULL) {
11049                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
11050                 if (stub == NULL)
11051                         goto cleanup;
11052                 stub->magic = STUB_MAGIC;
11053                 stub->mctx = zone->mctx;
11054                 stub->zone = NULL;
11055                 stub->db = NULL;
11056                 stub->version = NULL;
11057
11058                 /*
11059                  * Attach so that the zone won't disappear from under us.
11060                  */
11061                 zone_iattach(zone, &stub->zone);
11062
11063                 /*
11064                  * If a db exists we will update it, otherwise we create a
11065                  * new one and attach it to the zone once we have the NS
11066                  * RRset and glue.
11067                  */
11068                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11069                 if (zone->db != NULL) {
11070                         dns_db_attach(zone->db, &stub->db);
11071                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11072                 } else {
11073                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11074
11075                         INSIST(zone->db_argc >= 1);
11076                         result = dns_db_create(zone->mctx, zone->db_argv[0],
11077                                                &zone->origin, dns_dbtype_stub,
11078                                                zone->rdclass,
11079                                                zone->db_argc - 1,
11080                                                zone->db_argv + 1,
11081                                                &stub->db);
11082                         if (result != ISC_R_SUCCESS) {
11083                                 dns_zone_log(zone, ISC_LOG_ERROR,
11084                                              "refreshing stub: "
11085                                              "could not create "
11086                                              "database: %s",
11087                                              dns_result_totext(result));
11088                                 goto cleanup;
11089                         }
11090                         dns_db_settask(stub->db, zone->task);
11091                 }
11092
11093                 result = dns_db_newversion(stub->db, &stub->version);
11094                 if (result != ISC_R_SUCCESS) {
11095                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11096                                      "dns_db_newversion() failed: %s",
11097                                      dns_result_totext(result));
11098                         goto cleanup;
11099                 }
11100
11101                 /*
11102                  * Update SOA record.
11103                  */
11104                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
11105                                          &node);
11106                 if (result != ISC_R_SUCCESS) {
11107                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11108                                      "dns_db_findnode() failed: %s",
11109                                      dns_result_totext(result));
11110                         goto cleanup;
11111                 }
11112
11113                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
11114                                             soardataset, 0, NULL);
11115                 dns_db_detachnode(stub->db, &node);
11116                 if (result != ISC_R_SUCCESS) {
11117                         dns_zone_log(zone, ISC_LOG_INFO,
11118                                      "refreshing stub: "
11119                                      "dns_db_addrdataset() failed: %s",
11120                                      dns_result_totext(result));
11121                         goto cleanup;
11122                 }
11123         }
11124
11125         /*
11126          * XXX Optimisation: Create message when zone is setup and reuse.
11127          */
11128         result = create_query(zone, dns_rdatatype_ns, &message);
11129         INSIST(result == ISC_R_SUCCESS);
11130
11131         INSIST(zone->masterscnt > 0);
11132         INSIST(zone->curmaster < zone->masterscnt);
11133         zone->masteraddr = zone->masters[zone->curmaster];
11134
11135         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11136         /*
11137          * First, look for a tsig key in the master statement, then
11138          * try for a server key.
11139          */
11140         if ((zone->masterkeynames != NULL) &&
11141             (zone->masterkeynames[zone->curmaster] != NULL)) {
11142                 dns_view_t *view = dns_zone_getview(zone);
11143                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11144                 result = dns_view_gettsig(view, keyname, &key);
11145                 if (result != ISC_R_SUCCESS) {
11146                         char namebuf[DNS_NAME_FORMATSIZE];
11147                         dns_name_format(keyname, namebuf, sizeof(namebuf));
11148                         dns_zone_log(zone, ISC_LOG_ERROR,
11149                                      "unable to find key: %s", namebuf);
11150                 }
11151         }
11152         if (key == NULL)
11153                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
11154
11155         reqnsid = zone->view->requestnsid;
11156         if (zone->view->peers != NULL) {
11157                 dns_peer_t *peer = NULL;
11158                 isc_boolean_t edns;
11159                 result = dns_peerlist_peerbyaddr(zone->view->peers,
11160                                                  &masterip, &peer);
11161                 if (result == ISC_R_SUCCESS) {
11162                         result = dns_peer_getsupportedns(peer, &edns);
11163                         if (result == ISC_R_SUCCESS && !edns)
11164                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11165                         result = dns_peer_gettransfersource(peer,
11166                                                             &zone->sourceaddr);
11167                         if (result == ISC_R_SUCCESS)
11168                                 have_xfrsource = ISC_TRUE;
11169                         if (zone->view->resolver != NULL)
11170                                 udpsize =
11171                                   dns_resolver_getudpsize(zone->view->resolver);
11172                         (void)dns_peer_getudpsize(peer, &udpsize);
11173                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
11174                 }
11175
11176         }
11177         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11178                 result = add_opt(message, udpsize, reqnsid);
11179                 if (result != ISC_R_SUCCESS)
11180                         zone_debuglog(zone, me, 1,
11181                                       "unable to add opt record: %s",
11182                                       dns_result_totext(result));
11183         }
11184
11185         /*
11186          * Always use TCP so that we shouldn't truncate in additional section.
11187          */
11188         switch (isc_sockaddr_pf(&zone->masteraddr)) {
11189         case PF_INET:
11190                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11191                         zone->sourceaddr = zone->altxfrsource4;
11192                 else if (!have_xfrsource)
11193                         zone->sourceaddr = zone->xfrsource4;
11194                 break;
11195         case PF_INET6:
11196                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11197                         zone->sourceaddr = zone->altxfrsource6;
11198                 else if (!have_xfrsource)
11199                         zone->sourceaddr = zone->xfrsource6;
11200                 break;
11201         default:
11202                 result = ISC_R_NOTIMPLEMENTED;
11203                 POST(result);
11204                 goto cleanup;
11205         }
11206         timeout = 15;
11207         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11208                 timeout = 30;
11209         result = dns_request_createvia2(zone->view->requestmgr, message,
11210                                         &zone->sourceaddr, &zone->masteraddr,
11211                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
11212                                         timeout, zone->task, stub_callback,
11213                                         stub, &zone->request);
11214         if (result != ISC_R_SUCCESS) {
11215                 zone_debuglog(zone, me, 1,
11216                               "dns_request_createvia() failed: %s",
11217                               dns_result_totext(result));
11218                 goto cleanup;
11219         }
11220         dns_message_destroy(&message);
11221         goto unlock;
11222
11223  cleanup:
11224         cancel_refresh(zone);
11225         if (stub != NULL) {
11226                 stub->magic = 0;
11227                 if (stub->version != NULL)
11228                         dns_db_closeversion(stub->db, &stub->version,
11229                                             ISC_FALSE);
11230                 if (stub->db != NULL)
11231                         dns_db_detach(&stub->db);
11232                 if (stub->zone != NULL)
11233                         zone_idetach(&stub->zone);
11234                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
11235         }
11236         if (message != NULL)
11237                 dns_message_destroy(&message);
11238  unlock:
11239         if (key != NULL)
11240                 dns_tsigkey_detach(&key);
11241         return;
11242 }
11243
11244 /*
11245  * Handle the control event.  Note that although this event causes the zone
11246  * to shut down, it is not a shutdown event in the sense of the task library.
11247  */
11248 static void
11249 zone_shutdown(isc_task_t *task, isc_event_t *event) {
11250         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
11251         isc_boolean_t free_needed, linked = ISC_FALSE;
11252         dns_zone_t *raw = NULL, *secure = NULL;
11253
11254         UNUSED(task);
11255         REQUIRE(DNS_ZONE_VALID(zone));
11256         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
11257         INSIST(isc_refcount_current(&zone->erefs) == 0);
11258
11259         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
11260
11261         /*
11262          * Stop things being restarted after we cancel them below.
11263          */
11264         LOCK_ZONE(zone);
11265         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
11266         UNLOCK_ZONE(zone);
11267
11268         /*
11269          * If we were waiting for xfrin quota, step out of
11270          * the queue.
11271          * If there's no zone manager, we can't be waiting for the
11272          * xfrin quota
11273          */
11274         if (zone->zmgr != NULL) {
11275                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11276                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
11277                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
11278                                         statelink);
11279                         linked = ISC_TRUE;
11280                         zone->statelist = NULL;
11281                 }
11282                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11283         }
11284
11285         /*
11286          * In task context, no locking required.  See zone_xfrdone().
11287          */
11288         if (zone->xfr != NULL)
11289                 dns_xfrin_shutdown(zone->xfr);
11290
11291         LOCK_ZONE(zone);
11292         if (linked) {
11293                 INSIST(zone->irefs > 0);
11294                 zone->irefs--;
11295         }
11296         if (zone->request != NULL) {
11297                 dns_request_cancel(zone->request);
11298         }
11299
11300         if (zone->readio != NULL)
11301                 zonemgr_cancelio(zone->readio);
11302
11303         if (zone->lctx != NULL)
11304                 dns_loadctx_cancel(zone->lctx);
11305
11306         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11307             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11308                 if (zone->writeio != NULL)
11309                         zonemgr_cancelio(zone->writeio);
11310
11311                 if (zone->dctx != NULL)
11312                         dns_dumpctx_cancel(zone->dctx);
11313         }
11314
11315         notify_cancel(zone);
11316
11317         forward_cancel(zone);
11318
11319         if (zone->timer != NULL) {
11320                 isc_timer_detach(&zone->timer);
11321                 INSIST(zone->irefs > 0);
11322                 zone->irefs--;
11323         }
11324
11325         if (zone->view != NULL)
11326                 dns_view_weakdetach(&zone->view);
11327
11328         /*
11329          * We have now canceled everything set the flag to allow exit_check()
11330          * to succeed.  We must not unlock between setting this flag and
11331          * calling exit_check().
11332          */
11333         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
11334         free_needed = exit_check(zone);
11335         if (inline_secure(zone)) {
11336                 raw = zone->raw;
11337                 zone->raw = NULL;
11338         }
11339         if (inline_raw(zone)) {
11340                 secure = zone->secure;
11341                 zone->secure = NULL;
11342         }
11343         UNLOCK_ZONE(zone);
11344         if (raw != NULL)
11345                 dns_zone_detach(&raw);
11346         if (secure != NULL)
11347                 dns_zone_idetach(&secure);
11348         if (free_needed)
11349                 zone_free(zone);
11350 }
11351
11352 static void
11353 zone_timer(isc_task_t *task, isc_event_t *event) {
11354         const char me[] = "zone_timer";
11355         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
11356
11357         UNUSED(task);
11358         REQUIRE(DNS_ZONE_VALID(zone));
11359
11360         ENTER;
11361
11362         zone_maintenance(zone);
11363
11364         isc_event_free(&event);
11365 }
11366
11367 static void
11368 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
11369         const char me[] = "zone_settimer";
11370         isc_time_t next;
11371         isc_result_t result;
11372
11373         ENTER;
11374         REQUIRE(DNS_ZONE_VALID(zone));
11375         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11376                 return;
11377
11378         isc_time_settoepoch(&next);
11379
11380         switch (zone->type) {
11381         case dns_zone_redirect:
11382                 if (zone->masters != NULL)
11383                         goto treat_as_slave;
11384                 /* FALLTHROUGH */
11385
11386         case dns_zone_master:
11387                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
11388                         next = zone->notifytime;
11389                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11390                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11391                         INSIST(!isc_time_isepoch(&zone->dumptime));
11392                         if (isc_time_isepoch(&next) ||
11393                             isc_time_compare(&zone->dumptime, &next) < 0)
11394                                 next = zone->dumptime;
11395                 }
11396                 if (zone->type == dns_zone_redirect)
11397                         break;
11398                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
11399                     !isc_time_isepoch(&zone->refreshkeytime)) {
11400                         if (isc_time_isepoch(&next) ||
11401                             isc_time_compare(&zone->refreshkeytime, &next) < 0)
11402                                 next = zone->refreshkeytime;
11403                 }
11404                 if (!isc_time_isepoch(&zone->resigntime)) {
11405                         if (isc_time_isepoch(&next) ||
11406                             isc_time_compare(&zone->resigntime, &next) < 0)
11407                                 next = zone->resigntime;
11408                 }
11409                 if (!isc_time_isepoch(&zone->keywarntime)) {
11410                         if (isc_time_isepoch(&next) ||
11411                             isc_time_compare(&zone->keywarntime, &next) < 0)
11412                                 next = zone->keywarntime;
11413                 }
11414                 if (!isc_time_isepoch(&zone->signingtime)) {
11415                         if (isc_time_isepoch(&next) ||
11416                             isc_time_compare(&zone->signingtime, &next) < 0)
11417                                 next = zone->signingtime;
11418                 }
11419                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
11420                         if (isc_time_isepoch(&next) ||
11421                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
11422                                 next = zone->nsec3chaintime;
11423                 }
11424                 break;
11425
11426         case dns_zone_slave:
11427         treat_as_slave:
11428                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
11429                         next = zone->notifytime;
11430                 /* FALLTHROUGH */
11431
11432         case dns_zone_stub:
11433                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
11434                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
11435                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
11436                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
11437                         INSIST(!isc_time_isepoch(&zone->refreshtime));
11438                         if (isc_time_isepoch(&next) ||
11439                             isc_time_compare(&zone->refreshtime, &next) < 0)
11440                                 next = zone->refreshtime;
11441                 }
11442                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
11443                         INSIST(!isc_time_isepoch(&zone->expiretime));
11444                         if (isc_time_isepoch(&next) ||
11445                             isc_time_compare(&zone->expiretime, &next) < 0)
11446                                 next = zone->expiretime;
11447                 }
11448                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11449                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11450                         INSIST(!isc_time_isepoch(&zone->dumptime));
11451                         if (isc_time_isepoch(&next) ||
11452                             isc_time_compare(&zone->dumptime, &next) < 0)
11453                                 next = zone->dumptime;
11454                 }
11455                 break;
11456
11457         case dns_zone_key:
11458                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11459                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11460                         INSIST(!isc_time_isepoch(&zone->dumptime));
11461                         if (isc_time_isepoch(&next) ||
11462                             isc_time_compare(&zone->dumptime, &next) < 0)
11463                                 next = zone->dumptime;
11464                 }
11465                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
11466                         if (isc_time_isepoch(&next) ||
11467                             (!isc_time_isepoch(&zone->refreshkeytime) &&
11468                             isc_time_compare(&zone->refreshkeytime, &next) < 0))
11469                                 next = zone->refreshkeytime;
11470                 }
11471                 break;
11472
11473         default:
11474                 break;
11475         }
11476
11477         if (isc_time_isepoch(&next)) {
11478                 zone_debuglog(zone, me, 10, "settimer inactive");
11479                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
11480                                           NULL, NULL, ISC_TRUE);
11481                 if (result != ISC_R_SUCCESS)
11482                         dns_zone_log(zone, ISC_LOG_ERROR,
11483                                      "could not deactivate zone timer: %s",
11484                                      isc_result_totext(result));
11485         } else {
11486                 if (isc_time_compare(&next, now) <= 0)
11487                         next = *now;
11488                 result = isc_timer_reset(zone->timer, isc_timertype_once,
11489                                          &next, NULL, ISC_TRUE);
11490                 if (result != ISC_R_SUCCESS)
11491                         dns_zone_log(zone, ISC_LOG_ERROR,
11492                                      "could not reset zone timer: %s",
11493                                      isc_result_totext(result));
11494         }
11495 }
11496
11497 static void
11498 cancel_refresh(dns_zone_t *zone) {
11499         const char me[] = "cancel_refresh";
11500         isc_time_t now;
11501
11502         /*
11503          * 'zone' locked by caller.
11504          */
11505
11506         REQUIRE(DNS_ZONE_VALID(zone));
11507         REQUIRE(LOCKED_ZONE(zone));
11508
11509         ENTER;
11510
11511         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11512         TIME_NOW(&now);
11513         zone_settimer(zone, &now);
11514 }
11515
11516 static isc_result_t
11517 notify_createmessage(dns_zone_t *zone, unsigned int flags,
11518                      dns_message_t **messagep)
11519 {
11520         dns_db_t *zonedb = NULL;
11521         dns_dbnode_t *node = NULL;
11522         dns_dbversion_t *version = NULL;
11523         dns_message_t *message = NULL;
11524         dns_rdataset_t rdataset;
11525         dns_rdata_t rdata = DNS_RDATA_INIT;
11526
11527         dns_name_t *tempname = NULL;
11528         dns_rdata_t *temprdata = NULL;
11529         dns_rdatalist_t *temprdatalist = NULL;
11530         dns_rdataset_t *temprdataset = NULL;
11531
11532         isc_result_t result;
11533         isc_region_t r;
11534         isc_buffer_t *b = NULL;
11535
11536         REQUIRE(DNS_ZONE_VALID(zone));
11537         REQUIRE(messagep != NULL && *messagep == NULL);
11538
11539         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11540                                     &message);
11541         if (result != ISC_R_SUCCESS)
11542                 return (result);
11543
11544         message->opcode = dns_opcode_notify;
11545         message->flags |= DNS_MESSAGEFLAG_AA;
11546         message->rdclass = zone->rdclass;
11547
11548         result = dns_message_gettempname(message, &tempname);
11549         if (result != ISC_R_SUCCESS)
11550                 goto cleanup;
11551
11552         result = dns_message_gettemprdataset(message, &temprdataset);
11553         if (result != ISC_R_SUCCESS)
11554                 goto cleanup;
11555
11556         /*
11557          * Make question.
11558          */
11559         dns_name_init(tempname, NULL);
11560         dns_name_clone(&zone->origin, tempname);
11561         dns_rdataset_init(temprdataset);
11562         dns_rdataset_makequestion(temprdataset, zone->rdclass,
11563                                   dns_rdatatype_soa);
11564         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11565         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
11566         tempname = NULL;
11567         temprdataset = NULL;
11568
11569         if ((flags & DNS_NOTIFY_NOSOA) != 0)
11570                 goto done;
11571
11572         result = dns_message_gettempname(message, &tempname);
11573         if (result != ISC_R_SUCCESS)
11574                 goto soa_cleanup;
11575         result = dns_message_gettemprdata(message, &temprdata);
11576         if (result != ISC_R_SUCCESS)
11577                 goto soa_cleanup;
11578         result = dns_message_gettemprdataset(message, &temprdataset);
11579         if (result != ISC_R_SUCCESS)
11580                 goto soa_cleanup;
11581         result = dns_message_gettemprdatalist(message, &temprdatalist);
11582         if (result != ISC_R_SUCCESS)
11583                 goto soa_cleanup;
11584
11585         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11586         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
11587         dns_db_attach(zone->db, &zonedb);
11588         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11589
11590         dns_name_init(tempname, NULL);
11591         dns_name_clone(&zone->origin, tempname);
11592         dns_db_currentversion(zonedb, &version);
11593         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
11594         if (result != ISC_R_SUCCESS)
11595                 goto soa_cleanup;
11596
11597         dns_rdataset_init(&rdataset);
11598         result = dns_db_findrdataset(zonedb, node, version,
11599                                      dns_rdatatype_soa,
11600                                      dns_rdatatype_none, 0, &rdataset,
11601                                      NULL);
11602         if (result != ISC_R_SUCCESS)
11603                 goto soa_cleanup;
11604         result = dns_rdataset_first(&rdataset);
11605         if (result != ISC_R_SUCCESS)
11606                 goto soa_cleanup;
11607         dns_rdataset_current(&rdataset, &rdata);
11608         dns_rdata_toregion(&rdata, &r);
11609         result = isc_buffer_allocate(zone->mctx, &b, r.length);
11610         if (result != ISC_R_SUCCESS)
11611                 goto soa_cleanup;
11612         isc_buffer_putmem(b, r.base, r.length);
11613         isc_buffer_usedregion(b, &r);
11614         dns_rdata_init(temprdata);
11615         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
11616         dns_message_takebuffer(message, &b);
11617         result = dns_rdataset_next(&rdataset);
11618         dns_rdataset_disassociate(&rdataset);
11619         if (result != ISC_R_NOMORE)
11620                 goto soa_cleanup;
11621         temprdatalist->rdclass = rdata.rdclass;
11622         temprdatalist->type = rdata.type;
11623         temprdatalist->covers = 0;
11624         temprdatalist->ttl = rdataset.ttl;
11625         ISC_LIST_INIT(temprdatalist->rdata);
11626         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
11627
11628         dns_rdataset_init(temprdataset);
11629         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
11630         if (result != ISC_R_SUCCESS)
11631                 goto soa_cleanup;
11632
11633         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11634         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
11635         temprdatalist = NULL;
11636         temprdataset = NULL;
11637         temprdata = NULL;
11638         tempname = NULL;
11639
11640  soa_cleanup:
11641         if (node != NULL)
11642                 dns_db_detachnode(zonedb, &node);
11643         if (version != NULL)
11644                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
11645         if (zonedb != NULL)
11646                 dns_db_detach(&zonedb);
11647         if (tempname != NULL)
11648                 dns_message_puttempname(message, &tempname);
11649         if (temprdata != NULL)
11650                 dns_message_puttemprdata(message, &temprdata);
11651         if (temprdataset != NULL)
11652                 dns_message_puttemprdataset(message, &temprdataset);
11653         if (temprdatalist != NULL)
11654                 dns_message_puttemprdatalist(message, &temprdatalist);
11655
11656  done:
11657         *messagep = message;
11658         return (ISC_R_SUCCESS);
11659
11660  cleanup:
11661         if (tempname != NULL)
11662                 dns_message_puttempname(message, &tempname);
11663         if (temprdataset != NULL)
11664                 dns_message_puttemprdataset(message, &temprdataset);
11665         dns_message_destroy(&message);
11666         return (result);
11667 }
11668
11669 isc_result_t
11670 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
11671                        dns_message_t *msg)
11672 {
11673         unsigned int i;
11674         dns_rdata_soa_t soa;
11675         dns_rdataset_t *rdataset = NULL;
11676         dns_rdata_t rdata = DNS_RDATA_INIT;
11677         isc_result_t result;
11678         char fromtext[ISC_SOCKADDR_FORMATSIZE];
11679         int match = 0;
11680         isc_netaddr_t netaddr;
11681         isc_sockaddr_t local, remote;
11682
11683         REQUIRE(DNS_ZONE_VALID(zone));
11684
11685         /*
11686          * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
11687          * ROLLOVER.
11688          *
11689          * SOA: RFC1996
11690          * Check that 'from' is a valid notify source, (zone->masters).
11691          *      Return DNS_R_REFUSED if not.
11692          *
11693          * If the notify message contains a serial number check it
11694          * against the zones serial and return if <= current serial
11695          *
11696          * If a refresh check is progress, if so just record the
11697          * fact we received a NOTIFY and from where and return.
11698          * We will perform a new refresh check when the current one
11699          * completes. Return ISC_R_SUCCESS.
11700          *
11701          * Otherwise initiate a refresh check using 'from' as the
11702          * first address to check.  Return ISC_R_SUCCESS.
11703          */
11704
11705         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
11706
11707         /*
11708          * Notify messages are processed by the raw zone.
11709          */
11710         LOCK_ZONE(zone);
11711         if (inline_secure(zone)) {
11712                 result = dns_zone_notifyreceive(zone->raw, from, msg);
11713                 UNLOCK_ZONE(zone);
11714                 return (result);
11715         }
11716         /*
11717          *  We only handle NOTIFY (SOA) at the present.
11718          */
11719         if (isc_sockaddr_pf(from) == PF_INET)
11720                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
11721         else
11722                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
11723         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
11724             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
11725                                  dns_rdatatype_soa, dns_rdatatype_none,
11726                                  NULL, NULL) != ISC_R_SUCCESS) {
11727                 UNLOCK_ZONE(zone);
11728                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
11729                         dns_zone_log(zone, ISC_LOG_NOTICE,
11730                                      "NOTIFY with no "
11731                                      "question section from: %s", fromtext);
11732                         return (DNS_R_FORMERR);
11733                 }
11734                 dns_zone_log(zone, ISC_LOG_NOTICE,
11735                              "NOTIFY zone does not match");
11736                 return (DNS_R_NOTIMP);
11737         }
11738
11739         /*
11740          * If we are a master zone just succeed.
11741          */
11742         if (zone->type == dns_zone_master) {
11743                 UNLOCK_ZONE(zone);
11744                 return (ISC_R_SUCCESS);
11745         }
11746
11747         isc_netaddr_fromsockaddr(&netaddr, from);
11748         for (i = 0; i < zone->masterscnt; i++) {
11749                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
11750                         break;
11751                 if (zone->view->aclenv.match_mapped &&
11752                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
11753                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
11754                         isc_netaddr_t na1, na2;
11755                         isc_netaddr_fromv4mapped(&na1, &netaddr);
11756                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
11757                         if (isc_netaddr_equal(&na1, &na2))
11758                                 break;
11759                 }
11760         }
11761
11762         /*
11763          * Accept notify requests from non masters if they are on
11764          * 'zone->notify_acl'.
11765          */
11766         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
11767             dns_acl_match(&netaddr, NULL, zone->notify_acl,
11768                           &zone->view->aclenv,
11769                           &match, NULL) == ISC_R_SUCCESS &&
11770             match > 0)
11771         {
11772                 /* Accept notify. */
11773         } else if (i >= zone->masterscnt) {
11774                 UNLOCK_ZONE(zone);
11775                 dns_zone_log(zone, ISC_LOG_INFO,
11776                              "refused notify from non-master: %s", fromtext);
11777                 inc_stats(zone, dns_zonestatscounter_notifyrej);
11778                 return (DNS_R_REFUSED);
11779         }
11780
11781         /*
11782          * If the zone is loaded and there are answers check the serial
11783          * to see if we need to do a refresh.  Do not worry about this
11784          * check if we are a dialup zone as we use the notify request
11785          * to trigger a refresh check.
11786          */
11787         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
11788             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11789             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
11790                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
11791                                               &zone->origin,
11792                                               dns_rdatatype_soa,
11793                                               dns_rdatatype_none, NULL,
11794                                               &rdataset);
11795                 if (result == ISC_R_SUCCESS)
11796                         result = dns_rdataset_first(rdataset);
11797                 if (result == ISC_R_SUCCESS) {
11798                         isc_uint32_t serial = 0, oldserial;
11799                         unsigned int soacount;
11800
11801                         dns_rdataset_current(rdataset, &rdata);
11802                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
11803                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11804                         serial = soa.serial;
11805                         /*
11806                          * The following should safely be performed without DB
11807                          * lock and succeed in this context.
11808                          */
11809                         result = zone_get_from_db(zone, zone->db, NULL,
11810                                                   &soacount, &oldserial, NULL,
11811                                                   NULL, NULL, NULL, NULL);
11812                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11813                         RUNTIME_CHECK(soacount > 0U);
11814                         if (isc_serial_le(serial, oldserial)) {
11815                                 dns_zone_log(zone,
11816                                              ISC_LOG_INFO,
11817                                              "notify from %s: "
11818                                              "zone is up to date",
11819                                              fromtext);
11820                                 UNLOCK_ZONE(zone);
11821                                 return (ISC_R_SUCCESS);
11822                         }
11823                 }
11824         }
11825
11826         /*
11827          * If we got this far and there was a refresh in progress just
11828          * let it complete.  Record where we got the notify from so we
11829          * can perform a refresh check when the current one completes
11830          */
11831         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
11832                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11833                 zone->notifyfrom = *from;
11834                 UNLOCK_ZONE(zone);
11835                 dns_zone_log(zone, ISC_LOG_INFO,
11836                              "notify from %s: refresh in progress, "
11837                              "refresh check queued",
11838                              fromtext);
11839                 return (ISC_R_SUCCESS);
11840         }
11841         zone->notifyfrom = *from;
11842         local = zone->masteraddr;
11843         remote = zone->sourceaddr;
11844         UNLOCK_ZONE(zone);
11845         dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
11846         dns_zone_refresh(zone);
11847         return (ISC_R_SUCCESS);
11848 }
11849
11850 void
11851 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
11852
11853         REQUIRE(DNS_ZONE_VALID(zone));
11854
11855         LOCK_ZONE(zone);
11856         if (zone->notify_acl != NULL)
11857                 dns_acl_detach(&zone->notify_acl);
11858         dns_acl_attach(acl, &zone->notify_acl);
11859         UNLOCK_ZONE(zone);
11860 }
11861
11862 void
11863 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
11864
11865         REQUIRE(DNS_ZONE_VALID(zone));
11866
11867         LOCK_ZONE(zone);
11868         if (zone->query_acl != NULL)
11869                 dns_acl_detach(&zone->query_acl);
11870         dns_acl_attach(acl, &zone->query_acl);
11871         UNLOCK_ZONE(zone);
11872 }
11873
11874 void
11875 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
11876
11877         REQUIRE(DNS_ZONE_VALID(zone));
11878
11879         LOCK_ZONE(zone);
11880         if (zone->queryon_acl != NULL)
11881                 dns_acl_detach(&zone->queryon_acl);
11882         dns_acl_attach(acl, &zone->queryon_acl);
11883         UNLOCK_ZONE(zone);
11884 }
11885
11886 void
11887 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
11888
11889         REQUIRE(DNS_ZONE_VALID(zone));
11890
11891         LOCK_ZONE(zone);
11892         if (zone->update_acl != NULL)
11893                 dns_acl_detach(&zone->update_acl);
11894         dns_acl_attach(acl, &zone->update_acl);
11895         UNLOCK_ZONE(zone);
11896 }
11897
11898 void
11899 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
11900
11901         REQUIRE(DNS_ZONE_VALID(zone));
11902
11903         LOCK_ZONE(zone);
11904         if (zone->forward_acl != NULL)
11905                 dns_acl_detach(&zone->forward_acl);
11906         dns_acl_attach(acl, &zone->forward_acl);
11907         UNLOCK_ZONE(zone);
11908 }
11909
11910 void
11911 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
11912
11913         REQUIRE(DNS_ZONE_VALID(zone));
11914
11915         LOCK_ZONE(zone);
11916         if (zone->xfr_acl != NULL)
11917                 dns_acl_detach(&zone->xfr_acl);
11918         dns_acl_attach(acl, &zone->xfr_acl);
11919         UNLOCK_ZONE(zone);
11920 }
11921
11922 dns_acl_t *
11923 dns_zone_getnotifyacl(dns_zone_t *zone) {
11924
11925         REQUIRE(DNS_ZONE_VALID(zone));
11926
11927         return (zone->notify_acl);
11928 }
11929
11930 dns_acl_t *
11931 dns_zone_getqueryacl(dns_zone_t *zone) {
11932
11933         REQUIRE(DNS_ZONE_VALID(zone));
11934
11935         return (zone->query_acl);
11936 }
11937
11938 dns_acl_t *
11939 dns_zone_getqueryonacl(dns_zone_t *zone) {
11940
11941         REQUIRE(DNS_ZONE_VALID(zone));
11942
11943         return (zone->queryon_acl);
11944 }
11945
11946 dns_acl_t *
11947 dns_zone_getupdateacl(dns_zone_t *zone) {
11948
11949         REQUIRE(DNS_ZONE_VALID(zone));
11950
11951         return (zone->update_acl);
11952 }
11953
11954 dns_acl_t *
11955 dns_zone_getforwardacl(dns_zone_t *zone) {
11956
11957         REQUIRE(DNS_ZONE_VALID(zone));
11958
11959         return (zone->forward_acl);
11960 }
11961
11962 dns_acl_t *
11963 dns_zone_getxfracl(dns_zone_t *zone) {
11964
11965         REQUIRE(DNS_ZONE_VALID(zone));
11966
11967         return (zone->xfr_acl);
11968 }
11969
11970 void
11971 dns_zone_clearupdateacl(dns_zone_t *zone) {
11972
11973         REQUIRE(DNS_ZONE_VALID(zone));
11974
11975         LOCK_ZONE(zone);
11976         if (zone->update_acl != NULL)
11977                 dns_acl_detach(&zone->update_acl);
11978         UNLOCK_ZONE(zone);
11979 }
11980
11981 void
11982 dns_zone_clearforwardacl(dns_zone_t *zone) {
11983
11984         REQUIRE(DNS_ZONE_VALID(zone));
11985
11986         LOCK_ZONE(zone);
11987         if (zone->forward_acl != NULL)
11988                 dns_acl_detach(&zone->forward_acl);
11989         UNLOCK_ZONE(zone);
11990 }
11991
11992 void
11993 dns_zone_clearnotifyacl(dns_zone_t *zone) {
11994
11995         REQUIRE(DNS_ZONE_VALID(zone));
11996
11997         LOCK_ZONE(zone);
11998         if (zone->notify_acl != NULL)
11999                 dns_acl_detach(&zone->notify_acl);
12000         UNLOCK_ZONE(zone);
12001 }
12002
12003 void
12004 dns_zone_clearqueryacl(dns_zone_t *zone) {
12005
12006         REQUIRE(DNS_ZONE_VALID(zone));
12007
12008         LOCK_ZONE(zone);
12009         if (zone->query_acl != NULL)
12010                 dns_acl_detach(&zone->query_acl);
12011         UNLOCK_ZONE(zone);
12012 }
12013
12014 void
12015 dns_zone_clearqueryonacl(dns_zone_t *zone) {
12016
12017         REQUIRE(DNS_ZONE_VALID(zone));
12018
12019         LOCK_ZONE(zone);
12020         if (zone->queryon_acl != NULL)
12021                 dns_acl_detach(&zone->queryon_acl);
12022         UNLOCK_ZONE(zone);
12023 }
12024
12025 void
12026 dns_zone_clearxfracl(dns_zone_t *zone) {
12027
12028         REQUIRE(DNS_ZONE_VALID(zone));
12029
12030         LOCK_ZONE(zone);
12031         if (zone->xfr_acl != NULL)
12032                 dns_acl_detach(&zone->xfr_acl);
12033         UNLOCK_ZONE(zone);
12034 }
12035
12036 isc_boolean_t
12037 dns_zone_getupdatedisabled(dns_zone_t *zone) {
12038         REQUIRE(DNS_ZONE_VALID(zone));
12039         return (zone->update_disabled);
12040
12041 }
12042
12043 void
12044 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
12045         REQUIRE(DNS_ZONE_VALID(zone));
12046         zone->update_disabled = state;
12047 }
12048
12049 isc_boolean_t
12050 dns_zone_getzeronosoattl(dns_zone_t *zone) {
12051         REQUIRE(DNS_ZONE_VALID(zone));
12052         return (zone->zero_no_soa_ttl);
12053
12054 }
12055
12056 void
12057 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
12058         REQUIRE(DNS_ZONE_VALID(zone));
12059         zone->zero_no_soa_ttl = state;
12060 }
12061
12062 void
12063 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
12064
12065         REQUIRE(DNS_ZONE_VALID(zone));
12066
12067         zone->check_names = severity;
12068 }
12069
12070 dns_severity_t
12071 dns_zone_getchecknames(dns_zone_t *zone) {
12072
12073         REQUIRE(DNS_ZONE_VALID(zone));
12074
12075         return (zone->check_names);
12076 }
12077
12078 void
12079 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
12080
12081         REQUIRE(DNS_ZONE_VALID(zone));
12082
12083         zone->journalsize = size;
12084 }
12085
12086 isc_int32_t
12087 dns_zone_getjournalsize(dns_zone_t *zone) {
12088
12089         REQUIRE(DNS_ZONE_VALID(zone));
12090
12091         return (zone->journalsize);
12092 }
12093
12094 static void
12095 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
12096         isc_result_t result = ISC_R_FAILURE;
12097         isc_buffer_t buffer;
12098
12099         REQUIRE(buf != NULL);
12100         REQUIRE(length > 1U);
12101
12102         /*
12103          * Leave space for terminating '\0'.
12104          */
12105         isc_buffer_init(&buffer, buf, length - 1);
12106         if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
12107                 if (dns_name_dynamic(&zone->origin))
12108                         result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12109                 if (result != ISC_R_SUCCESS &&
12110                     isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12111                         isc_buffer_putstr(&buffer, "<UNKNOWN>");
12112
12113                 if (isc_buffer_availablelength(&buffer) > 0)
12114                         isc_buffer_putstr(&buffer, "/");
12115                 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
12116         }
12117
12118         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
12119             strcmp(zone->view->name, "_default") != 0 &&
12120             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
12121                 isc_buffer_putstr(&buffer, "/");
12122                 isc_buffer_putstr(&buffer, zone->view->name);
12123         }
12124         if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
12125                 isc_buffer_putstr(&buffer, " (signed)");
12126         if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
12127                 isc_buffer_putstr(&buffer, " (unsigned)");
12128
12129         buf[isc_buffer_usedlength(&buffer)] = '\0';
12130 }
12131
12132 static void
12133 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
12134         isc_result_t result = ISC_R_FAILURE;
12135         isc_buffer_t buffer;
12136
12137         REQUIRE(buf != NULL);
12138         REQUIRE(length > 1U);
12139
12140         /*
12141          * Leave space for terminating '\0'.
12142          */
12143         isc_buffer_init(&buffer, buf, length - 1);
12144         if (dns_name_dynamic(&zone->origin))
12145                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12146         if (result != ISC_R_SUCCESS &&
12147             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12148                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
12149
12150         buf[isc_buffer_usedlength(&buffer)] = '\0';
12151 }
12152
12153 static void
12154 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
12155         isc_buffer_t buffer;
12156
12157         REQUIRE(buf != NULL);
12158         REQUIRE(length > 1U);
12159
12160         /*
12161          * Leave space for terminating '\0'.
12162          */
12163         isc_buffer_init(&buffer, buf, length - 1);
12164         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
12165
12166         buf[isc_buffer_usedlength(&buffer)] = '\0';
12167 }
12168
12169 static void
12170 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
12171         isc_buffer_t buffer;
12172
12173         REQUIRE(buf != NULL);
12174         REQUIRE(length > 1U);
12175
12176
12177         /*
12178          * Leave space for terminating '\0'.
12179          */
12180         isc_buffer_init(&buffer, buf, length - 1);
12181
12182         if (zone->view == NULL) {
12183                 isc_buffer_putstr(&buffer, "_none");
12184         } else if (strlen(zone->view->name)
12185                    < isc_buffer_availablelength(&buffer)) {
12186                 isc_buffer_putstr(&buffer, zone->view->name);
12187         } else {
12188                 isc_buffer_putstr(&buffer, "_toolong");
12189         }
12190
12191         buf[isc_buffer_usedlength(&buffer)] = '\0';
12192 }
12193
12194 void
12195 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
12196         REQUIRE(DNS_ZONE_VALID(zone));
12197         REQUIRE(buf != NULL);
12198         zone_namerd_tostr(zone, buf, length);
12199 }
12200
12201 static void
12202 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12203         va_list ap;
12204         char message[4096];
12205
12206         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12207                 return;
12208
12209         va_start(ap, fmt);
12210         vsnprintf(message, sizeof(message), fmt, ap);
12211         va_end(ap);
12212         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
12213                       level, "zone %s: %s", zone->strnamerd, message);
12214 }
12215
12216 void
12217 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
12218               int level, const char *fmt, ...) {
12219         va_list ap;
12220         char message[4096];
12221
12222         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12223                 return;
12224
12225         va_start(ap, fmt);
12226         vsnprintf(message, sizeof(message), fmt, ap);
12227         va_end(ap);
12228         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
12229                       level, "%s%s: %s", (zone->type == dns_zone_key) ?
12230                       "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12231                       "redirect-zone" : "zone ", zone->strnamerd, message);
12232 }
12233
12234 void
12235 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12236         va_list ap;
12237         char message[4096];
12238
12239         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12240                 return;
12241
12242         va_start(ap, fmt);
12243         vsnprintf(message, sizeof(message), fmt, ap);
12244         va_end(ap);
12245         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12246                       level, "%s%s: %s", (zone->type == dns_zone_key) ?
12247                       "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12248                       "redirect-zone" : "zone ", zone->strnamerd, message);
12249 }
12250
12251 static void
12252 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
12253               const char *fmt, ...)
12254 {
12255         va_list ap;
12256         char message[4096];
12257         int level = ISC_LOG_DEBUG(debuglevel);
12258         const char *zstr;
12259
12260         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12261                 return;
12262
12263         va_start(ap, fmt);
12264         vsnprintf(message, sizeof(message), fmt, ap);
12265         va_end(ap);
12266
12267         switch (zone->type) {
12268         case dns_zone_key:
12269                 zstr = "managed-keys-zone";
12270                 break;
12271         case dns_zone_redirect:
12272                 zstr = "redirect-zone";
12273                 break;
12274         default:
12275                 zstr = "zone";
12276         }
12277
12278         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12279                       level, "%s: %s %s: %s", me, zstr, zone->strnamerd,
12280                       message);
12281 }
12282
12283 static int
12284 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
12285 {
12286         isc_result_t result;
12287         dns_name_t *name;
12288         dns_rdataset_t *curr;
12289         int count = 0;
12290
12291         result = dns_message_firstname(msg, section);
12292         while (result == ISC_R_SUCCESS) {
12293                 name = NULL;
12294                 dns_message_currentname(msg, section, &name);
12295
12296                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
12297                      curr = ISC_LIST_PREV(curr, link)) {
12298                         if (curr->type == type)
12299                                 count++;
12300                 }
12301                 result = dns_message_nextname(msg, section);
12302         }
12303
12304         return (count);
12305 }
12306
12307 void
12308 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
12309         REQUIRE(DNS_ZONE_VALID(zone));
12310
12311         zone->maxxfrin = maxxfrin;
12312 }
12313
12314 isc_uint32_t
12315 dns_zone_getmaxxfrin(dns_zone_t *zone) {
12316         REQUIRE(DNS_ZONE_VALID(zone));
12317
12318         return (zone->maxxfrin);
12319 }
12320
12321 void
12322 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
12323         REQUIRE(DNS_ZONE_VALID(zone));
12324         zone->maxxfrout = maxxfrout;
12325 }
12326
12327 isc_uint32_t
12328 dns_zone_getmaxxfrout(dns_zone_t *zone) {
12329         REQUIRE(DNS_ZONE_VALID(zone));
12330
12331         return (zone->maxxfrout);
12332 }
12333
12334 dns_zonetype_t
12335 dns_zone_gettype(dns_zone_t *zone) {
12336         REQUIRE(DNS_ZONE_VALID(zone));
12337
12338         return (zone->type);
12339 }
12340
12341 dns_name_t *
12342 dns_zone_getorigin(dns_zone_t *zone) {
12343         REQUIRE(DNS_ZONE_VALID(zone));
12344
12345         return (&zone->origin);
12346 }
12347
12348 void
12349 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
12350         REQUIRE(DNS_ZONE_VALID(zone));
12351
12352         LOCK_ZONE(zone);
12353         if (zone->task != NULL)
12354                 isc_task_detach(&zone->task);
12355         isc_task_attach(task, &zone->task);
12356         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12357         if (zone->db != NULL)
12358                 dns_db_settask(zone->db, zone->task);
12359         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12360         UNLOCK_ZONE(zone);
12361 }
12362
12363 void
12364 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
12365         REQUIRE(DNS_ZONE_VALID(zone));
12366         isc_task_attach(zone->task, target);
12367 }
12368
12369 void
12370 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
12371         REQUIRE(DNS_ZONE_VALID(zone));
12372
12373         if (idlein == 0)
12374                 idlein = DNS_DEFAULT_IDLEIN;
12375         zone->idlein = idlein;
12376 }
12377
12378 isc_uint32_t
12379 dns_zone_getidlein(dns_zone_t *zone) {
12380         REQUIRE(DNS_ZONE_VALID(zone));
12381
12382         return (zone->idlein);
12383 }
12384
12385 void
12386 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
12387         REQUIRE(DNS_ZONE_VALID(zone));
12388
12389         zone->idleout = idleout;
12390 }
12391
12392 isc_uint32_t
12393 dns_zone_getidleout(dns_zone_t *zone) {
12394         REQUIRE(DNS_ZONE_VALID(zone));
12395
12396         return (zone->idleout);
12397 }
12398
12399 static void
12400 notify_done(isc_task_t *task, isc_event_t *event) {
12401         dns_requestevent_t *revent = (dns_requestevent_t *)event;
12402         dns_notify_t *notify;
12403         isc_result_t result;
12404         dns_message_t *message = NULL;
12405         isc_buffer_t buf;
12406         char rcode[128];
12407         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12408
12409         UNUSED(task);
12410
12411         notify = event->ev_arg;
12412         REQUIRE(DNS_NOTIFY_VALID(notify));
12413         INSIST(task == notify->zone->task);
12414
12415         isc_buffer_init(&buf, rcode, sizeof(rcode));
12416         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12417
12418         result = revent->result;
12419         if (result == ISC_R_SUCCESS)
12420                 result = dns_message_create(notify->zone->mctx,
12421                                             DNS_MESSAGE_INTENTPARSE, &message);
12422         if (result == ISC_R_SUCCESS)
12423                 result = dns_request_getresponse(revent->request, message,
12424                                         DNS_MESSAGEPARSE_PRESERVEORDER);
12425         if (result == ISC_R_SUCCESS)
12426                 result = dns_rcode_totext(message->rcode, &buf);
12427         if (result == ISC_R_SUCCESS)
12428                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12429                            "notify response from %s: %.*s",
12430                            addrbuf, (int)buf.used, rcode);
12431         else
12432                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
12433                            "notify to %s failed: %s", addrbuf,
12434                            dns_result_totext(result));
12435
12436         /*
12437          * Old bind's return formerr if they see a soa record.  Retry w/o
12438          * the soa if we see a formerr and had sent a SOA.
12439          */
12440         isc_event_free(&event);
12441         if (message != NULL && message->rcode == dns_rcode_formerr &&
12442             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
12443                 notify->flags |= DNS_NOTIFY_NOSOA;
12444                 dns_request_destroy(&notify->request);
12445                 result = notify_send_queue(notify);
12446                 if (result != ISC_R_SUCCESS)
12447                         notify_destroy(notify, ISC_FALSE);
12448         } else {
12449                 if (result == ISC_R_TIMEDOUT)
12450                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
12451                                    "notify to %s: retries exceeded", addrbuf);
12452                 notify_destroy(notify, ISC_FALSE);
12453         }
12454         if (message != NULL)
12455                 dns_message_destroy(&message);
12456 }
12457
12458 struct secure_event {
12459         isc_event_t e;
12460         dns_db_t *db;
12461         isc_uint32_t serial;
12462 };
12463
12464 static void
12465 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
12466         UNUSED(arg);
12467         dns_zone_log(zone, level, "%s", message);
12468 }
12469
12470 static isc_result_t
12471 sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal,
12472                     isc_uint32_t start, isc_uint32_t end,
12473                     dns_difftuple_t **soatuplep, dns_diff_t *diff)
12474 {
12475         isc_result_t result;
12476         dns_difftuple_t *tuple = NULL;
12477         dns_diffop_t op = DNS_DIFFOP_ADD;
12478         int n_soa = 0;
12479
12480         REQUIRE(soatuplep != NULL);
12481
12482         if (start == end)
12483                 return (DNS_R_UNCHANGED);
12484
12485         CHECK(dns_journal_iter_init(journal, start, end));
12486         for (result = dns_journal_first_rr(journal);
12487              result == ISC_R_SUCCESS;
12488              result = dns_journal_next_rr(journal))
12489         {
12490                 dns_name_t *name = NULL;
12491                 isc_uint32_t ttl;
12492                 dns_rdata_t *rdata = NULL;
12493                 dns_journal_current_rr(journal, &name, &ttl, &rdata);
12494
12495                 if (rdata->type == dns_rdatatype_soa) {
12496                         n_soa++;
12497                         if (n_soa == 2) {
12498                                 /*
12499                                  * Save the latest raw SOA record.
12500                                  */
12501                                 if (*soatuplep != NULL)
12502                                         dns_difftuple_free(soatuplep);
12503                                 CHECK(dns_difftuple_create(diff->mctx,
12504                                                            DNS_DIFFOP_ADD,
12505                                                            name, ttl, rdata,
12506                                                            soatuplep));
12507                         }
12508                         if (n_soa == 3)
12509                                 n_soa = 1;
12510                         continue;
12511                 }
12512
12513                 /* Sanity. */
12514                 if (n_soa == 0) {
12515                         dns_zone_log(zone->raw, ISC_LOG_ERROR,
12516                                      "corrupt journal file: '%s'\n",
12517                                      zone->raw->journal);
12518                         return (ISC_R_FAILURE);
12519                 }
12520
12521                 if (zone->privatetype != 0 &&
12522                     rdata->type == zone->privatetype)
12523                         continue;
12524
12525                 if (rdata->type == dns_rdatatype_nsec ||
12526                     rdata->type == dns_rdatatype_rrsig ||
12527                     rdata->type == dns_rdatatype_nsec3 ||
12528                     rdata->type == dns_rdatatype_dnskey ||
12529                     rdata->type == dns_rdatatype_nsec3param)
12530                         continue;
12531
12532                 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
12533
12534                 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
12535                                            &tuple));
12536                 dns_diff_appendminimal(diff, &tuple);
12537         }
12538         if (result == ISC_R_NOMORE)
12539                 result = ISC_R_SUCCESS;
12540
12541  failure:
12542         return(result);
12543 }
12544
12545 static isc_result_t
12546 sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb,
12547                dns_dbversion_t *secver, dns_difftuple_t **soatuple,
12548                dns_diff_t *diff)
12549 {
12550         isc_result_t result;
12551         dns_db_t *rawdb = NULL;
12552         dns_dbversion_t *rawver = NULL;
12553         dns_difftuple_t *tuple = NULL, *next;
12554         dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
12555         dns_rdata_soa_t oldsoa, newsoa;
12556
12557         REQUIRE(DNS_ZONE_VALID(seczone));
12558         REQUIRE(inline_secure(seczone));
12559         REQUIRE(soatuple != NULL && *soatuple == NULL);
12560
12561         if (!seczone->sourceserialset)
12562                 return (DNS_R_UNCHANGED);
12563
12564         dns_db_attach(seczone->raw->db, &rawdb);
12565         dns_db_currentversion(rawdb, &rawver);
12566         result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
12567         dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
12568         dns_db_detach(&rawdb);
12569
12570         if (result != ISC_R_SUCCESS)
12571                 return (result);
12572
12573         for (tuple = ISC_LIST_HEAD(diff->tuples);
12574              tuple != NULL;
12575              tuple = next)
12576         {
12577                 next = ISC_LIST_NEXT(tuple, link);
12578                 if (tuple->rdata.type == dns_rdatatype_nsec ||
12579                     tuple->rdata.type == dns_rdatatype_rrsig ||
12580                     tuple->rdata.type == dns_rdatatype_dnskey ||
12581                     tuple->rdata.type == dns_rdatatype_nsec3 ||
12582                     tuple->rdata.type == dns_rdatatype_nsec3param)
12583                 {
12584                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
12585                         dns_difftuple_free(&tuple);
12586                         continue;
12587                 }
12588                 if (tuple->rdata.type == dns_rdatatype_soa) {
12589                         if (tuple->op == DNS_DIFFOP_DEL) {
12590                                 INSIST(oldtuple == NULL);
12591                                 oldtuple = tuple;
12592                         }
12593                         if (tuple->op == DNS_DIFFOP_ADD) {
12594                                 INSIST(newtuple == NULL);
12595                                 newtuple = tuple;
12596                         }
12597                 }
12598         }
12599
12600         if (oldtuple != NULL && newtuple != NULL) {
12601
12602                 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
12603                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12604
12605                 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
12606                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12607
12608                 /*
12609                  * If the SOA records are the same except for the serial
12610                  * remove them from the diff.
12611                  */
12612                 if (oldsoa.refresh == newsoa.refresh &&
12613                     oldsoa.retry == newsoa.retry &&
12614                     oldsoa.minimum == newsoa.minimum &&
12615                     oldsoa.expire == newsoa.expire &&
12616                     dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
12617                     dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
12618                         ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12619                         dns_difftuple_free(&oldtuple);
12620                         ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12621                         dns_difftuple_free(&newtuple);
12622                 }
12623         }
12624
12625         if (ISC_LIST_EMPTY(diff->tuples))
12626                 return (DNS_R_UNCHANGED);
12627
12628         /*
12629          * If there are still SOA records in the diff they can now be removed
12630          * saving the new SOA record.
12631          */
12632         if (oldtuple != NULL) {
12633                 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12634                 dns_difftuple_free(&oldtuple);
12635         }
12636
12637         if (newtuple != NULL) {
12638                 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12639                 *soatuple = newtuple;
12640         }
12641
12642         return (ISC_R_SUCCESS);
12643 }
12644
12645 static void
12646 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
12647         isc_result_t result;
12648         dns_journal_t *rjournal = NULL;
12649         isc_uint32_t start, end;
12650         dns_zone_t *zone;
12651         dns_db_t *db = NULL;
12652         dns_dbversion_t *newver = NULL, *oldver = NULL;
12653         dns_diff_t diff;
12654         dns_difftuple_t *tuple = NULL, *soatuple = NULL;
12655         dns_update_log_t log = { update_log_cb, NULL };
12656         isc_time_t timenow;
12657
12658         zone = event->ev_arg;
12659         end = ((struct secure_event *)event)->serial;
12660         isc_event_free(&event);
12661
12662         LOCK_ZONE(zone);
12663
12664         dns_diff_init(zone->mctx, &diff);
12665
12666         UNUSED(task);
12667
12668         /*
12669          * zone->db may be NULL if the load from disk failed.
12670          */
12671         if (zone->db == NULL || !inline_secure(zone)) {
12672                 result = ISC_R_FAILURE;
12673                 goto failure;
12674         }
12675
12676         /*
12677          * We first attempt to sync the raw zone to the secure zone
12678          * by using the raw zone's journal, applying all the deltas
12679          * from the latest source-serial of the secure zone up to
12680          * the current serial number of the raw zone.
12681          *
12682          * If that fails, then we'll fall back to a direct comparison
12683          * between raw and secure zones.
12684          */
12685         result = dns_journal_open(zone->raw->mctx, zone->raw->journal,
12686                                   DNS_JOURNAL_WRITE, &rjournal);
12687         if (result != ISC_R_SUCCESS)
12688                 goto failure;
12689         else {
12690                 dns_journal_t *sjournal = NULL;
12691
12692                 result = dns_journal_open(zone->mctx, zone->journal,
12693                                           DNS_JOURNAL_READ, &sjournal);
12694                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
12695                         goto failure;
12696
12697                 if (!dns_journal_get_sourceserial(rjournal, &start)) {
12698                         start = dns_journal_first_serial(rjournal);
12699                         dns_journal_set_sourceserial(rjournal, start);
12700                 }
12701                 if (sjournal != NULL) {
12702                         isc_uint32_t serial;
12703                         /*
12704                          * We read the secure journal first, if that exists
12705                          * use its value provided it is greater that from the
12706                          * raw journal.
12707                          */
12708                         if (dns_journal_get_sourceserial(sjournal, &serial)) {
12709                                 if (isc_serial_gt(serial, start))
12710                                         start = serial;
12711                         }
12712                         dns_journal_destroy(&sjournal);
12713                 }
12714         }
12715
12716         dns_db_attach(zone->db, &db);
12717         dns_db_currentversion(db, &oldver);
12718         CHECK(dns_db_newversion(db, &newver));
12719
12720         /*
12721          * Try to apply diffs from the raw zone's journal to the secure
12722          * zone.  If that fails, we recover by syncing up the databases
12723          * directly.
12724          */
12725         result = sync_secure_journal(zone, rjournal, start, end,
12726                                      &soatuple, &diff);
12727         if (result == DNS_R_UNCHANGED)
12728                 goto failure;
12729         else if (result != ISC_R_SUCCESS)
12730                 CHECK(sync_secure_db(zone, db, oldver, &soatuple, &diff));
12731
12732         CHECK(dns_diff_apply(&diff, db, newver));
12733
12734         if (soatuple != NULL) {
12735                 isc_uint32_t oldserial, newserial, desired;
12736
12737                 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
12738                                             DNS_DIFFOP_DEL, &tuple));
12739                 oldserial = dns_soa_getserial(&tuple->rdata);
12740                 newserial = desired = dns_soa_getserial(&soatuple->rdata);
12741                 if (!isc_serial_gt(newserial, oldserial)) {
12742                         newserial = oldserial + 1;
12743                         if (newserial == 0)
12744                                 newserial++;
12745                         dns_soa_setserial(newserial, &soatuple->rdata);
12746                 }
12747                 CHECK(do_one_tuple(&tuple, db, newver, &diff));
12748                 CHECK(do_one_tuple(&soatuple, db, newver, &diff));
12749                 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
12750                              newserial, desired);
12751         } else
12752                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
12753                                         zone->updatemethod));
12754
12755         CHECK(dns_update_signatures(&log, zone, db, oldver, newver,
12756                                     &diff, zone->sigvalidityinterval));
12757
12758         CHECK(zone_journal(zone, &diff, &end, "receive_secure_serial"));
12759
12760         dns_journal_set_sourceserial(rjournal, end);
12761         dns_journal_commit(rjournal);
12762
12763         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12764
12765         zone->sourceserial = end;
12766         zone->sourceserialset = ISC_TRUE;
12767         zone_needdump(zone, DNS_DUMP_DELAY);
12768
12769         TIME_NOW(&timenow);
12770         zone_settimer(zone, &timenow);
12771
12772         dns_db_closeversion(db, &oldver, ISC_FALSE);
12773         dns_db_closeversion(db, &newver, ISC_TRUE);
12774
12775  failure:
12776         UNLOCK_ZONE(zone);
12777         if (result != ISC_R_SUCCESS)
12778                 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
12779                              dns_result_totext(result));
12780         if (tuple != NULL)
12781                 dns_difftuple_free(&tuple);
12782         if (soatuple != NULL)
12783                 dns_difftuple_free(&soatuple);
12784         if (db != NULL) {
12785                 if (oldver != NULL)
12786                         dns_db_closeversion(db, &oldver, ISC_FALSE);
12787                 if (newver != NULL)
12788                         dns_db_closeversion(db, &newver, ISC_FALSE);
12789                 dns_db_detach(&db);
12790         }
12791         if (rjournal != NULL)
12792                 dns_journal_destroy(&rjournal);
12793         dns_diff_clear(&diff);
12794         dns_zone_idetach(&zone);
12795 }
12796
12797 static isc_result_t
12798 zone_send_secureserial(dns_zone_t *zone, isc_boolean_t locked,
12799                        isc_uint32_t serial)
12800 {
12801         isc_event_t *e;
12802         dns_zone_t *dummy = NULL;
12803
12804         e = isc_event_allocate(zone->secure->mctx, zone,
12805                                DNS_EVENT_ZONESECURESERIAL,
12806                                receive_secure_serial, zone->secure,
12807                                sizeof(struct secure_event));
12808         if (e == NULL)
12809                 return (ISC_R_NOMEMORY);
12810         ((struct secure_event *)e)->serial = serial;
12811         if (locked)
12812                 zone_iattach(zone->secure, &dummy);
12813         else
12814                 dns_zone_iattach(zone->secure, &dummy);
12815         isc_task_send(zone->secure->task, &e);
12816
12817         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
12818         return (ISC_R_SUCCESS);
12819 }
12820
12821 static isc_result_t
12822 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
12823                dns_rdataset_t *rdataset, isc_uint32_t oldserial)
12824 {
12825         dns_rdata_soa_t soa;
12826         dns_rdata_t rdata = DNS_RDATA_INIT;
12827         dns_rdatalist_t temprdatalist;
12828         dns_rdataset_t temprdataset;
12829         isc_buffer_t b;
12830         isc_result_t result;
12831         unsigned char buf[DNS_SOA_BUFFERSIZE];
12832
12833         result = dns_rdataset_first(rdataset);
12834         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12835         dns_rdataset_current(rdataset, &rdata);
12836         result = dns_rdata_tostruct(&rdata, &soa, NULL);
12837         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12838
12839         if (isc_serial_gt(soa.serial, oldserial))
12840                 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
12841                                            NULL));
12842         /*
12843          * Always bump the serial.
12844          */
12845         oldserial++;
12846         if (oldserial == 0)
12847                 oldserial++;
12848         soa.serial = oldserial;
12849
12850         /*
12851          * Construct a replacement rdataset.
12852          */
12853         dns_rdata_reset(&rdata);
12854         isc_buffer_init(&b, buf, sizeof(buf));
12855         result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
12856                                       dns_rdatatype_soa, &soa, &b);
12857         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12858         temprdatalist.rdclass = rdata.rdclass;
12859         temprdatalist.type = rdata.type;
12860         temprdatalist.covers = 0;
12861         temprdatalist.ttl = rdataset->ttl;
12862         ISC_LIST_INIT(temprdatalist.rdata);
12863         ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
12864
12865         dns_rdataset_init(&temprdataset);
12866         result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
12867         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12868         return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
12869                                    0, NULL));
12870 }
12871
12872 static void
12873 receive_secure_db(isc_task_t *task, isc_event_t *event) {
12874         isc_result_t result;
12875         dns_zone_t *zone;
12876         dns_db_t *rawdb, *db = NULL;
12877         dns_dbnode_t *rawnode = NULL, *node = NULL;
12878         dns_fixedname_t fname;
12879         dns_name_t *name;
12880         dns_dbiterator_t *dbiterator = NULL;
12881         dns_rdatasetiter_t *rdsit = NULL;
12882         dns_rdataset_t rdataset;
12883         dns_dbversion_t *version = NULL;
12884         isc_time_t loadtime;
12885         unsigned int oldserial = 0;
12886         isc_boolean_t have_oldserial = ISC_FALSE;
12887
12888         UNUSED(task);
12889
12890         zone = event->ev_arg;
12891         rawdb = ((struct secure_event *)event)->db;
12892         isc_event_free(&event);
12893
12894         REQUIRE(inline_secure(zone));
12895
12896         dns_fixedname_init(&fname);
12897         name = dns_fixedname_name(&fname);
12898         dns_rdataset_init(&rdataset);
12899
12900         TIME_NOW(&loadtime);
12901         if (zone->db != NULL) {
12902                 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
12903                 if (result == ISC_R_SUCCESS)
12904                         have_oldserial = ISC_TRUE;
12905         }
12906
12907         result = dns_db_create(zone->mctx, zone->db_argv[0],
12908                                &zone->origin, dns_dbtype_zone, zone->rdclass,
12909                                zone->db_argc - 1, zone->db_argv + 1, &db);
12910         if (result != ISC_R_SUCCESS)
12911                 goto failure;
12912
12913         result = dns_db_newversion(db, &version);
12914         if (result != ISC_R_SUCCESS)
12915                 goto failure;
12916
12917         result = dns_db_createiterator(rawdb, 0, &dbiterator);
12918         if (result != ISC_R_SUCCESS)
12919                 goto failure;
12920
12921         for (result = dns_dbiterator_first(dbiterator);
12922              result == ISC_R_SUCCESS;
12923              result = dns_dbiterator_next(dbiterator)) {
12924                 result = dns_dbiterator_current(dbiterator, &rawnode, name);
12925                 if (result != ISC_R_SUCCESS)
12926                         continue;
12927
12928                 result = dns_db_findnode(db, name, ISC_TRUE, &node);
12929                 if (result != ISC_R_SUCCESS)
12930                         goto failure;
12931
12932                 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
12933                 if (result != ISC_R_SUCCESS)
12934                         goto failure;
12935
12936                 for (result = dns_rdatasetiter_first(rdsit);
12937                      result == ISC_R_SUCCESS;
12938                      result = dns_rdatasetiter_next(rdsit)) {
12939                         dns_rdatasetiter_current(rdsit, &rdataset);
12940                         if (rdataset.type == dns_rdatatype_nsec ||
12941                             rdataset.type == dns_rdatatype_rrsig ||
12942                             rdataset.type == dns_rdatatype_nsec3 ||
12943                             rdataset.type == dns_rdatatype_dnskey ||
12944                             rdataset.type == dns_rdatatype_nsec3param) {
12945                                 dns_rdataset_disassociate(&rdataset);
12946                                 continue;
12947                         }
12948                         if (rdataset.type == dns_rdatatype_soa &&
12949                             have_oldserial) {
12950                                 result = checkandaddsoa(db, node, version,
12951                                                         &rdataset, oldserial);
12952                         } else
12953                                 result = dns_db_addrdataset(db, node, version,
12954                                                             0, &rdataset, 0,
12955                                                             NULL);
12956                         if (result != ISC_R_SUCCESS)
12957                                 goto failure;
12958
12959                         dns_rdataset_disassociate(&rdataset);
12960                 }
12961                 dns_rdatasetiter_destroy(&rdsit);
12962                 dns_db_detachnode(rawdb, &rawnode);
12963                 dns_db_detachnode(db, &node);
12964         }
12965
12966         dns_db_closeversion(db, &version, ISC_TRUE);
12967         /*
12968          * Lock hierarchy: zmgr, zone, raw.
12969          */
12970         LOCK_ZONE(zone);
12971         if (inline_secure(zone))
12972                 LOCK_ZONE(zone->raw);
12973         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12974         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
12975         zone_needdump(zone, 0); /* XXXMPA */
12976         if (inline_secure(zone))
12977                 UNLOCK_ZONE(zone->raw);
12978         UNLOCK_ZONE(zone);
12979
12980  failure:
12981         if (result != ISC_R_SUCCESS)
12982                 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
12983                              dns_result_totext(result));
12984
12985         if (dns_rdataset_isassociated(&rdataset))
12986                 dns_rdataset_disassociate(&rdataset);
12987         if (db != NULL) {
12988                 if (node != NULL)
12989                         dns_db_detachnode(db, &node);
12990                 dns_db_detach(&db);
12991         }
12992         if (rawnode != NULL)
12993                 dns_db_detachnode(rawdb, &rawnode);
12994         dns_db_detach(&rawdb);
12995         if (dbiterator != NULL)
12996                 dns_dbiterator_destroy(&dbiterator);
12997         dns_zone_idetach(&zone);
12998 }
12999
13000 static isc_result_t
13001 zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked, dns_db_t *db) {
13002         isc_event_t *e;
13003         dns_db_t *dummy = NULL;
13004         dns_zone_t *secure = NULL;
13005
13006         e = isc_event_allocate(zone->secure->mctx, zone,
13007                                DNS_EVENT_ZONESECUREDB,
13008                                receive_secure_db, zone->secure,
13009                                sizeof(struct secure_event));
13010         if (e == NULL)
13011                 return (ISC_R_NOMEMORY);
13012         dns_db_attach(db, &dummy);
13013         ((struct secure_event *)e)->db = dummy;
13014         if (locked)
13015                 zone_iattach(zone->secure, &secure);
13016         else
13017                 dns_zone_iattach(zone->secure, &secure);
13018
13019         isc_task_send(zone->secure->task, &e);
13020         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
13021         return (ISC_R_SUCCESS);
13022 }
13023
13024 isc_result_t
13025 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13026         isc_result_t result;
13027
13028         REQUIRE(DNS_ZONE_VALID(zone));
13029         LOCK_ZONE(zone);
13030         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13031         result = zone_replacedb(zone, db, dump);
13032         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13033         UNLOCK_ZONE(zone);
13034         return (result);
13035 }
13036
13037 static isc_result_t
13038 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13039         dns_dbversion_t *ver;
13040         isc_result_t result;
13041         unsigned int soacount = 0;
13042         unsigned int nscount = 0;
13043
13044         /*
13045          * 'zone' and 'zonedb' locked by caller.
13046          */
13047         REQUIRE(DNS_ZONE_VALID(zone));
13048         REQUIRE(LOCKED_ZONE(zone));
13049
13050         result = zone_get_from_db(zone, db, &nscount, &soacount,
13051                                   NULL, NULL, NULL, NULL, NULL, NULL);
13052         if (result == ISC_R_SUCCESS) {
13053                 if (soacount != 1) {
13054                         dns_zone_log(zone, ISC_LOG_ERROR,
13055                                      "has %d SOA records", soacount);
13056                         result = DNS_R_BADZONE;
13057                 }
13058                 if (nscount == 0 && zone->type != dns_zone_key) {
13059                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
13060                         result = DNS_R_BADZONE;
13061                 }
13062                 if (result != ISC_R_SUCCESS)
13063                         return (result);
13064         } else {
13065                 dns_zone_log(zone, ISC_LOG_ERROR,
13066                             "retrieving SOA and NS records failed: %s",
13067                             dns_result_totext(result));
13068                 return (result);
13069         }
13070
13071         result = check_nsec3param(zone, db);
13072         if (result != ISC_R_SUCCESS)
13073                 return (result);
13074
13075         ver = NULL;
13076         dns_db_currentversion(db, &ver);
13077
13078         /*
13079          * The initial version of a slave zone is always dumped;
13080          * subsequent versions may be journaled instead if this
13081          * is enabled in the configuration.
13082          */
13083         if (zone->db != NULL && zone->journal != NULL &&
13084             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
13085             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
13086         {
13087                 isc_uint32_t serial, oldserial;
13088                 unsigned int soacount;
13089
13090                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
13091
13092                 result = dns_db_getsoaserial(db, ver, &serial);
13093                 if (result != ISC_R_SUCCESS) {
13094                         dns_zone_log(zone, ISC_LOG_ERROR,
13095                                      "ixfr-from-differences: unable to get "
13096                                      "new serial");
13097                         goto fail;
13098                 }
13099
13100                 /*
13101                  * This is checked in zone_postload() for master zones.
13102                  */
13103                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
13104                                           &oldserial, NULL, NULL, NULL, NULL,
13105                                           NULL);
13106                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13107                 RUNTIME_CHECK(soacount > 0U);
13108                 if ((zone->type == dns_zone_slave ||
13109                      (zone->type == dns_zone_redirect &&
13110                       zone->masters != NULL))
13111                     && !isc_serial_gt(serial, oldserial)) {
13112                         isc_uint32_t serialmin, serialmax;
13113                         serialmin = (oldserial + 1) & 0xffffffffU;
13114                         serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
13115                         dns_zone_log(zone, ISC_LOG_ERROR,
13116                                      "ixfr-from-differences: failed: "
13117                                      "new serial (%u) out of range [%u - %u]",
13118                                      serial, serialmin, serialmax);
13119                         result = ISC_R_RANGE;
13120                         goto fail;
13121                 }
13122
13123                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
13124                                      zone->journal);
13125                 if (result != ISC_R_SUCCESS)
13126                         goto fail;
13127                 if (dump)
13128                         zone_needdump(zone, DNS_DUMP_DELAY);
13129                 else if (zone->journalsize != -1) {
13130                         result = dns_journal_compact(zone->mctx, zone->journal,
13131                                                      serial, zone->journalsize);
13132                         switch (result) {
13133                         case ISC_R_SUCCESS:
13134                         case ISC_R_NOSPACE:
13135                         case ISC_R_NOTFOUND:
13136                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
13137                                              "dns_journal_compact: %s",
13138                                              dns_result_totext(result));
13139                                 break;
13140                         default:
13141                                 dns_zone_log(zone, ISC_LOG_ERROR,
13142                                              "dns_journal_compact failed: %s",
13143                                              dns_result_totext(result));
13144                                 break;
13145                         }
13146                 }
13147                 if (zone->type == dns_zone_master && inline_raw(zone))
13148                         zone_send_secureserial(zone, ISC_FALSE, serial);
13149         } else {
13150                 if (dump && zone->masterfile != NULL) {
13151                         /*
13152                          * If DNS_ZONEFLG_FORCEXFER was set we don't want
13153                          * to keep the old masterfile.
13154                          */
13155                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
13156                             remove(zone->masterfile) < 0 && errno != ENOENT) {
13157                                 char strbuf[ISC_STRERRORSIZE];
13158                                 isc__strerror(errno, strbuf, sizeof(strbuf));
13159                                 isc_log_write(dns_lctx,
13160                                               DNS_LOGCATEGORY_GENERAL,
13161                                               DNS_LOGMODULE_ZONE,
13162                                               ISC_LOG_WARNING,
13163                                               "unable to remove masterfile "
13164                                               "'%s': '%s'",
13165                                               zone->masterfile, strbuf);
13166                         }
13167                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
13168                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
13169                         else
13170                                 zone_needdump(zone, 0);
13171                 }
13172                 if (dump && zone->journal != NULL) {
13173                         /*
13174                          * The in-memory database just changed, and
13175                          * because 'dump' is set, it didn't change by
13176                          * being loaded from disk.  Also, we have not
13177                          * journaled diffs for this change.
13178                          * Therefore, the on-disk journal is missing
13179                          * the deltas for this change.  Since it can
13180                          * no longer be used to bring the zone
13181                          * up-to-date, it is useless and should be
13182                          * removed.
13183                          */
13184                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13185                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13186                                       "removing journal file");
13187                         if (remove(zone->journal) < 0 && errno != ENOENT) {
13188                                 char strbuf[ISC_STRERRORSIZE];
13189                                 isc__strerror(errno, strbuf, sizeof(strbuf));
13190                                 isc_log_write(dns_lctx,
13191                                               DNS_LOGCATEGORY_GENERAL,
13192                                               DNS_LOGMODULE_ZONE,
13193                                               ISC_LOG_WARNING,
13194                                               "unable to remove journal "
13195                                               "'%s': '%s'",
13196                                               zone->journal, strbuf);
13197                         }
13198                 }
13199
13200                 if (inline_raw(zone))
13201                         zone_send_securedb(zone, ISC_FALSE, db);
13202         }
13203
13204         dns_db_closeversion(db, &ver, ISC_FALSE);
13205
13206         dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
13207
13208         if (zone->db != NULL)
13209                 zone_detachdb(zone);
13210         zone_attachdb(zone, db);
13211         dns_db_settask(zone->db, zone->task);
13212         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
13213         return (ISC_R_SUCCESS);
13214
13215  fail:
13216         dns_db_closeversion(db, &ver, ISC_FALSE);
13217         return (result);
13218 }
13219
13220 /* The caller must hold the dblock as a writer. */
13221 static inline void
13222 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
13223         REQUIRE(zone->db == NULL && db != NULL);
13224
13225         dns_db_attach(db, &zone->db);
13226         if (zone->acache != NULL) {
13227                 isc_result_t result;
13228                 result = dns_acache_setdb(zone->acache, db);
13229                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
13230                         UNEXPECTED_ERROR(__FILE__, __LINE__,
13231                                          "dns_acache_setdb() failed: %s",
13232                                          isc_result_totext(result));
13233                 }
13234         }
13235 }
13236
13237 /* The caller must hold the dblock as a writer. */
13238 static inline void
13239 zone_detachdb(dns_zone_t *zone) {
13240         REQUIRE(zone->db != NULL);
13241
13242         if (zone->acache != NULL)
13243                 (void)dns_acache_putdb(zone->acache, zone->db);
13244         dns_db_detach(&zone->db);
13245 }
13246
13247 static void
13248 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
13249         isc_time_t now;
13250         isc_boolean_t again = ISC_FALSE;
13251         unsigned int soacount;
13252         unsigned int nscount;
13253         isc_uint32_t serial, refresh, retry, expire, minimum;
13254         isc_result_t xfrresult = result;
13255         isc_boolean_t free_needed;
13256
13257         REQUIRE(DNS_ZONE_VALID(zone));
13258
13259         dns_zone_log(zone, ISC_LOG_DEBUG(1),
13260                      "zone transfer finished: %s", dns_result_totext(result));
13261
13262         LOCK_ZONE(zone);
13263         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
13264         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13265         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
13266
13267         TIME_NOW(&now);
13268         switch (result) {
13269         case ISC_R_SUCCESS:
13270                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13271                 /*FALLTHROUGH*/
13272         case DNS_R_UPTODATE:
13273                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13274                 /*
13275                  * Has the zone expired underneath us?
13276                  */
13277                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13278                 if (zone->db == NULL) {
13279                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13280                         goto same_master;
13281                 }
13282
13283                 /*
13284                  * Update the zone structure's data from the actual
13285                  * SOA received.
13286                  */
13287                 nscount = 0;
13288                 soacount = 0;
13289                 INSIST(zone->db != NULL);
13290                 result = zone_get_from_db(zone, zone->db, &nscount,
13291                                           &soacount, &serial, &refresh,
13292                                           &retry, &expire, &minimum, NULL);
13293                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13294                 if (result == ISC_R_SUCCESS) {
13295                         if (soacount != 1)
13296                                 dns_zone_log(zone, ISC_LOG_ERROR,
13297                                              "transferred zone "
13298                                              "has %d SOA record%s", soacount,
13299                                              (soacount != 0) ? "s" : "");
13300                         if (nscount == 0) {
13301                                 dns_zone_log(zone, ISC_LOG_ERROR,
13302                                              "transferred zone "
13303                                              "has no NS records");
13304                                 if (DNS_ZONE_FLAG(zone,
13305                                                   DNS_ZONEFLG_HAVETIMERS)) {
13306                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
13307                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
13308                                 }
13309                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13310                                 zone_unload(zone);
13311                                 goto next_master;
13312                         }
13313                         zone->refresh = RANGE(refresh, zone->minrefresh,
13314                                               zone->maxrefresh);
13315                         zone->retry = RANGE(retry, zone->minretry,
13316                                             zone->maxretry);
13317                         zone->expire = RANGE(expire,
13318                                              zone->refresh + zone->retry,
13319                                              DNS_MAX_EXPIRE);
13320                         zone->minimum = minimum;
13321                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13322                 }
13323
13324                 /*
13325                  * Set our next update/expire times.
13326                  */
13327                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
13328                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13329                         zone->refreshtime = now;
13330                         DNS_ZONE_TIME_ADD(&now, zone->expire,
13331                                           &zone->expiretime);
13332                 } else {
13333                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
13334                                             &zone->refreshtime);
13335                         DNS_ZONE_TIME_ADD(&now, zone->expire,
13336                                           &zone->expiretime);
13337                 }
13338                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
13339                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
13340                         if (zone->tsigkey != NULL) {
13341                                 char namebuf[DNS_NAME_FORMATSIZE];
13342                                 dns_name_format(&zone->tsigkey->name, namebuf,
13343                                                 sizeof(namebuf));
13344                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
13345                                          namebuf);
13346                         } else
13347                                 buf[0] = '\0';
13348                         dns_zone_log(zone, ISC_LOG_INFO,
13349                                      "transferred serial %u%s",
13350                                      serial, buf);
13351                         if (inline_raw(zone))
13352                                 zone_send_secureserial(zone, ISC_FALSE, serial);
13353                 }
13354
13355                 /*
13356                  * This is not necessary if we just performed a AXFR
13357                  * however it is necessary for an IXFR / UPTODATE and
13358                  * won't hurt with an AXFR.
13359                  */
13360                 if (zone->masterfile != NULL || zone->journal != NULL) {
13361                         unsigned int delay = DNS_DUMP_DELAY;
13362
13363                         result = ISC_R_FAILURE;
13364                         if (zone->journal != NULL)
13365                                 result = isc_file_settime(zone->journal, &now);
13366                         if (result != ISC_R_SUCCESS &&
13367                             zone->masterfile != NULL)
13368                                 result = isc_file_settime(zone->masterfile,
13369                                                           &now);
13370
13371                         if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
13372                             result == ISC_R_FILENOTFOUND)
13373                                 delay = 0;
13374
13375                         if ((result == ISC_R_SUCCESS ||
13376                             result == ISC_R_FILENOTFOUND) &&
13377                             zone->masterfile != NULL)
13378                                 zone_needdump(zone, delay);
13379                         else if (result != ISC_R_SUCCESS)
13380                                 dns_zone_log(zone, ISC_LOG_ERROR,
13381                                              "transfer: could not set file "
13382                                              "modification time of '%s': %s",
13383                                              zone->masterfile,
13384                                              dns_result_totext(result));
13385                 }
13386                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
13387                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
13388                 break;
13389
13390         case DNS_R_BADIXFR:
13391                 /* Force retry with AXFR. */
13392                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
13393                 goto same_master;
13394
13395         default:
13396         next_master:
13397                 /*
13398                  * Skip to next failed / untried master.
13399                  */
13400                 do {
13401                         zone->curmaster++;
13402                 } while (zone->curmaster < zone->masterscnt &&
13403                          zone->mastersok[zone->curmaster]);
13404                 /* FALLTHROUGH */
13405         same_master:
13406                 if (zone->curmaster >= zone->masterscnt) {
13407                         zone->curmaster = 0;
13408                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13409                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13410                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
13411                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13412                                 while (zone->curmaster < zone->masterscnt &&
13413                                        zone->mastersok[zone->curmaster])
13414                                         zone->curmaster++;
13415                                 again = ISC_TRUE;
13416                         } else
13417                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13418                 } else {
13419                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
13420                         again = ISC_TRUE;
13421                 }
13422                 inc_stats(zone, dns_zonestatscounter_xfrfail);
13423                 break;
13424         }
13425         zone_settimer(zone, &now);
13426
13427         /*
13428          * If creating the transfer object failed, zone->xfr is NULL.
13429          * Otherwise, we are called as the done callback of a zone
13430          * transfer object that just entered its shutting-down
13431          * state.  Since we are no longer responsible for shutting
13432          * it down, we can detach our reference.
13433          */
13434         if (zone->xfr != NULL)
13435                 dns_xfrin_detach(&zone->xfr);
13436
13437         if (zone->tsigkey != NULL)
13438                 dns_tsigkey_detach(&zone->tsigkey);
13439
13440         /*
13441          * Handle any deferred journal compaction.
13442          */
13443         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
13444                 result = dns_journal_compact(zone->mctx, zone->journal,
13445                                              zone->compact_serial,
13446                                              zone->journalsize);
13447                 switch (result) {
13448                 case ISC_R_SUCCESS:
13449                 case ISC_R_NOSPACE:
13450                 case ISC_R_NOTFOUND:
13451                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
13452                                      "dns_journal_compact: %s",
13453                                      dns_result_totext(result));
13454                         break;
13455                 default:
13456                         dns_zone_log(zone, ISC_LOG_ERROR,
13457                                      "dns_journal_compact failed: %s",
13458                                      dns_result_totext(result));
13459                         break;
13460                 }
13461                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
13462         }
13463
13464         /*
13465          * This transfer finishing freed up a transfer quota slot.
13466          * Let any other zones waiting for quota have it.
13467          */
13468         UNLOCK_ZONE(zone);
13469         RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13470         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
13471         zone->statelist = NULL;
13472         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
13473         RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13474         LOCK_ZONE(zone);
13475
13476         /*
13477          * Retry with a different server if necessary.
13478          */
13479         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
13480                 queue_soa_query(zone);
13481
13482         INSIST(zone->irefs > 0);
13483         zone->irefs--;
13484         free_needed = exit_check(zone);
13485         UNLOCK_ZONE(zone);
13486         if (free_needed)
13487                 zone_free(zone);
13488 }
13489
13490 static void
13491 zone_loaddone(void *arg, isc_result_t result) {
13492         static char me[] = "zone_loaddone";
13493         dns_load_t *load = arg;
13494         dns_zone_t *zone;
13495         isc_result_t tresult;
13496
13497         REQUIRE(DNS_LOAD_VALID(load));
13498         zone = load->zone;
13499
13500         ENTER;
13501
13502         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
13503         if (tresult != ISC_R_SUCCESS &&
13504             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
13505                 result = tresult;
13506
13507         /*
13508          * Lock hierarchy: zmgr, zone, raw.
13509          */
13510         LOCK_ZONE(zone);
13511         if (inline_secure(zone))
13512                 LOCK_ZONE(zone->raw);
13513         (void)zone_postload(zone, load->db, load->loadtime, result);
13514         zonemgr_putio(&zone->readio);
13515         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
13516         zone_idetach(&load->callbacks.zone);
13517         /*
13518          * Leave the zone frozen if the reload fails.
13519          */
13520         if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
13521              DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
13522                 zone->update_disabled = ISC_FALSE;
13523         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
13524         if (inline_secure(zone))
13525                 UNLOCK_ZONE(zone->raw);
13526         UNLOCK_ZONE(zone);
13527
13528         load->magic = 0;
13529         dns_db_detach(&load->db);
13530         if (load->zone->lctx != NULL)
13531                 dns_loadctx_detach(&load->zone->lctx);
13532         dns_zone_idetach(&load->zone);
13533         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
13534 }
13535
13536 void
13537 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
13538         REQUIRE(DNS_ZONE_VALID(zone));
13539         REQUIRE(table != NULL);
13540         REQUIRE(*table == NULL);
13541
13542         LOCK_ZONE(zone);
13543         if (zone->ssutable != NULL)
13544                 dns_ssutable_attach(zone->ssutable, table);
13545         UNLOCK_ZONE(zone);
13546 }
13547
13548 void
13549 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
13550         REQUIRE(DNS_ZONE_VALID(zone));
13551
13552         LOCK_ZONE(zone);
13553         if (zone->ssutable != NULL)
13554                 dns_ssutable_detach(&zone->ssutable);
13555         if (table != NULL)
13556                 dns_ssutable_attach(table, &zone->ssutable);
13557         UNLOCK_ZONE(zone);
13558 }
13559
13560 void
13561 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
13562         REQUIRE(DNS_ZONE_VALID(zone));
13563
13564         zone->sigvalidityinterval = interval;
13565 }
13566
13567 isc_uint32_t
13568 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
13569         REQUIRE(DNS_ZONE_VALID(zone));
13570
13571         return (zone->sigvalidityinterval);
13572 }
13573
13574 void
13575 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
13576         REQUIRE(DNS_ZONE_VALID(zone));
13577
13578         zone->sigresigninginterval = interval;
13579 }
13580
13581 isc_uint32_t
13582 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
13583         REQUIRE(DNS_ZONE_VALID(zone));
13584
13585         return (zone->sigresigninginterval);
13586 }
13587
13588 static void
13589 queue_xfrin(dns_zone_t *zone) {
13590         const char me[] = "queue_xfrin";
13591         isc_result_t result;
13592         dns_zonemgr_t *zmgr = zone->zmgr;
13593
13594         ENTER;
13595
13596         INSIST(zone->statelist == NULL);
13597
13598         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13599         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
13600         LOCK_ZONE(zone);
13601         zone->irefs++;
13602         UNLOCK_ZONE(zone);
13603         zone->statelist = &zmgr->waiting_for_xfrin;
13604         result = zmgr_start_xfrin_ifquota(zmgr, zone);
13605         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13606
13607         if (result == ISC_R_QUOTA) {
13608                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
13609                               "zone transfer deferred due to quota");
13610         } else if (result != ISC_R_SUCCESS) {
13611                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
13612                               "starting zone transfer: %s",
13613                               isc_result_totext(result));
13614         }
13615 }
13616
13617 /*
13618  * This event callback is called when a zone has received
13619  * any necessary zone transfer quota.  This is the time
13620  * to go ahead and start the transfer.
13621  */
13622 static void
13623 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
13624         isc_result_t result = ISC_R_SUCCESS;
13625         dns_peer_t *peer = NULL;
13626         char master[ISC_SOCKADDR_FORMATSIZE];
13627         char source[ISC_SOCKADDR_FORMATSIZE];
13628         dns_rdatatype_t xfrtype;
13629         dns_zone_t *zone = event->ev_arg;
13630         isc_netaddr_t masterip;
13631         isc_sockaddr_t sourceaddr;
13632         isc_sockaddr_t masteraddr;
13633         isc_time_t now;
13634         const char *soa_before = "";
13635
13636         UNUSED(task);
13637
13638         INSIST(task == zone->task);
13639
13640         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13641                 result = ISC_R_CANCELED;
13642                 goto cleanup;
13643         }
13644
13645         TIME_NOW(&now);
13646
13647         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13648         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
13649                                     &zone->sourceaddr, &now))
13650         {
13651                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13652                 dns_zone_log(zone, ISC_LOG_INFO,
13653                              "got_transfer_quota: skipping zone transfer as "
13654                              "master %s (source %s) is unreachable (cached)",
13655                              master, source);
13656                 result = ISC_R_CANCELED;
13657                 goto cleanup;
13658         }
13659
13660         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
13661         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
13662
13663         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
13664                 soa_before = "SOA before ";
13665         /*
13666          * Decide whether we should request IXFR or AXFR.
13667          */
13668         if (zone->db == NULL) {
13669                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13670                              "no database exists yet, requesting AXFR of "
13671                              "initial version from %s", master);
13672                 xfrtype = dns_rdatatype_axfr;
13673         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
13674                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13675                              "forced reload, requesting AXFR of "
13676                              "initial version from %s", master);
13677                 xfrtype = dns_rdatatype_axfr;
13678         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
13679                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13680                              "retrying with AXFR from %s due to "
13681                              "previous IXFR failure", master);
13682                 xfrtype = dns_rdatatype_axfr;
13683                 LOCK_ZONE(zone);
13684                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
13685                 UNLOCK_ZONE(zone);
13686         } else {
13687                 isc_boolean_t use_ixfr = ISC_TRUE;
13688                 if (peer != NULL)
13689                         result = dns_peer_getrequestixfr(peer, &use_ixfr);
13690                 if (peer == NULL || result != ISC_R_SUCCESS)
13691                         use_ixfr = zone->requestixfr;
13692                 if (use_ixfr == ISC_FALSE) {
13693                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
13694                                      "IXFR disabled, requesting %sAXFR from %s",
13695                                      soa_before, master);
13696                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
13697                                 xfrtype = dns_rdatatype_soa;
13698                         else
13699                                 xfrtype = dns_rdatatype_axfr;
13700                 } else {
13701                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
13702                                      "requesting IXFR from %s", master);
13703                         xfrtype = dns_rdatatype_ixfr;
13704                 }
13705         }
13706
13707         /*
13708          * Determine if we should attempt to sign the request with TSIG.
13709          */
13710         result = ISC_R_NOTFOUND;
13711         /*
13712          * First, look for a tsig key in the master statement, then
13713          * try for a server key.
13714          */
13715         if ((zone->masterkeynames != NULL) &&
13716             (zone->masterkeynames[zone->curmaster] != NULL)) {
13717                 dns_view_t *view = dns_zone_getview(zone);
13718                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
13719                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
13720         }
13721         if (zone->tsigkey == NULL)
13722                 result = dns_view_getpeertsig(zone->view, &masterip,
13723                                               &zone->tsigkey);
13724
13725         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
13726                 dns_zone_log(zone, ISC_LOG_ERROR,
13727                              "could not get TSIG key for zone transfer: %s",
13728                              isc_result_totext(result));
13729         }
13730
13731         LOCK_ZONE(zone);
13732         masteraddr = zone->masteraddr;
13733         sourceaddr = zone->sourceaddr;
13734         UNLOCK_ZONE(zone);
13735         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
13736         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
13737                                    zone->tsigkey, zone->mctx,
13738                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
13739                                    zone->task, zone_xfrdone, &zone->xfr);
13740         if (result == ISC_R_SUCCESS) {
13741                 LOCK_ZONE(zone);
13742                 if (xfrtype == dns_rdatatype_axfr) {
13743                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
13744                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
13745                         else
13746                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
13747                 } else if (xfrtype == dns_rdatatype_ixfr) {
13748                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
13749                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
13750                         else
13751                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
13752                 }
13753                 UNLOCK_ZONE(zone);
13754         }
13755  cleanup:
13756         /*
13757          * Any failure in this function is handled like a failed
13758          * zone transfer.  This ensures that we get removed from
13759          * zmgr->xfrin_in_progress.
13760          */
13761         if (result != ISC_R_SUCCESS)
13762                 zone_xfrdone(zone, result);
13763
13764         isc_event_free(&event);
13765 }
13766
13767 /*
13768  * Update forwarding support.
13769  */
13770
13771 static void
13772 forward_destroy(dns_forward_t *forward) {
13773
13774         forward->magic = 0;
13775         if (forward->request != NULL)
13776                 dns_request_destroy(&forward->request);
13777         if (forward->msgbuf != NULL)
13778                 isc_buffer_free(&forward->msgbuf);
13779         if (forward->zone != NULL) {
13780                 LOCK(&forward->zone->lock);
13781                 if (ISC_LINK_LINKED(forward, link))
13782                         ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
13783                 UNLOCK(&forward->zone->lock);
13784                 dns_zone_idetach(&forward->zone);
13785         }
13786         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
13787 }
13788
13789 static isc_result_t
13790 sendtomaster(dns_forward_t *forward) {
13791         isc_result_t result;
13792         isc_sockaddr_t src;
13793
13794         LOCK_ZONE(forward->zone);
13795
13796         if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
13797                 UNLOCK_ZONE(forward->zone);
13798                 return (ISC_R_CANCELED);
13799         }
13800
13801         if (forward->which >= forward->zone->masterscnt) {
13802                 UNLOCK_ZONE(forward->zone);
13803                 return (ISC_R_NOMORE);
13804         }
13805
13806         forward->addr = forward->zone->masters[forward->which];
13807         /*
13808          * Always use TCP regardless of whether the original update
13809          * used TCP.
13810          * XXX The timeout may but a bit small if we are far down a
13811          * transfer graph and the master has to try several masters.
13812          */
13813         switch (isc_sockaddr_pf(&forward->addr)) {
13814         case PF_INET:
13815                 src = forward->zone->xfrsource4;
13816                 break;
13817         case PF_INET6:
13818                 src = forward->zone->xfrsource6;
13819                 break;
13820         default:
13821                 result = ISC_R_NOTIMPLEMENTED;
13822                 goto unlock;
13823         }
13824         result = dns_request_createraw(forward->zone->view->requestmgr,
13825                                        forward->msgbuf,
13826                                        &src, &forward->addr,
13827                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
13828                                        forward->zone->task,
13829                                        forward_callback, forward,
13830                                        &forward->request);
13831         if (result == ISC_R_SUCCESS) {
13832                 if (!ISC_LINK_LINKED(forward, link))
13833                         ISC_LIST_APPEND(forward->zone->forwards, forward, link);
13834         }
13835
13836  unlock:
13837         UNLOCK_ZONE(forward->zone);
13838         return (result);
13839 }
13840
13841 static void
13842 forward_callback(isc_task_t *task, isc_event_t *event) {
13843         const char me[] = "forward_callback";
13844         dns_requestevent_t *revent = (dns_requestevent_t *)event;
13845         dns_message_t *msg = NULL;
13846         char master[ISC_SOCKADDR_FORMATSIZE];
13847         isc_result_t result;
13848         dns_forward_t *forward;
13849         dns_zone_t *zone;
13850
13851         UNUSED(task);
13852
13853         forward = revent->ev_arg;
13854         INSIST(DNS_FORWARD_VALID(forward));
13855         zone = forward->zone;
13856         INSIST(DNS_ZONE_VALID(zone));
13857
13858         ENTER;
13859
13860         isc_sockaddr_format(&forward->addr, master, sizeof(master));
13861
13862         if (revent->result != ISC_R_SUCCESS) {
13863                 dns_zone_log(zone, ISC_LOG_INFO,
13864                              "could not forward dynamic update to %s: %s",
13865                              master, dns_result_totext(revent->result));
13866                 goto next_master;
13867         }
13868
13869         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13870         if (result != ISC_R_SUCCESS)
13871                 goto next_master;
13872
13873         result = dns_request_getresponse(revent->request, msg,
13874                                          DNS_MESSAGEPARSE_PRESERVEORDER |
13875                                          DNS_MESSAGEPARSE_CLONEBUFFER);
13876         if (result != ISC_R_SUCCESS)
13877                 goto next_master;
13878
13879         switch (msg->rcode) {
13880         /*
13881          * Pass these rcodes back to client.
13882          */
13883         case dns_rcode_noerror:
13884         case dns_rcode_yxdomain:
13885         case dns_rcode_yxrrset:
13886         case dns_rcode_nxrrset:
13887         case dns_rcode_refused:
13888         case dns_rcode_nxdomain:
13889                 break;
13890
13891         /* These should not occur if the masters/zone are valid. */
13892         case dns_rcode_notzone:
13893         case dns_rcode_notauth: {
13894                 char rcode[128];
13895                 isc_buffer_t rb;
13896
13897                 isc_buffer_init(&rb, rcode, sizeof(rcode));
13898                 (void)dns_rcode_totext(msg->rcode, &rb);
13899                 dns_zone_log(zone, ISC_LOG_WARNING,
13900                              "forwarding dynamic update: "
13901                              "unexpected response: master %s returned: %.*s",
13902                              master, (int)rb.used, rcode);
13903                 goto next_master;
13904         }
13905
13906         /* Try another server for these rcodes. */
13907         case dns_rcode_formerr:
13908         case dns_rcode_servfail:
13909         case dns_rcode_notimp:
13910         case dns_rcode_badvers:
13911         default:
13912                 goto next_master;
13913         }
13914
13915         /* call callback */
13916         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
13917         msg = NULL;
13918         dns_request_destroy(&forward->request);
13919         forward_destroy(forward);
13920         isc_event_free(&event);
13921         return;
13922
13923  next_master:
13924         if (msg != NULL)
13925                 dns_message_destroy(&msg);
13926         isc_event_free(&event);
13927         forward->which++;
13928         dns_request_destroy(&forward->request);
13929         result = sendtomaster(forward);
13930         if (result != ISC_R_SUCCESS) {
13931                 /* call callback */
13932                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
13933                              "exhausted dynamic update forwarder list");
13934                 (forward->callback)(forward->callback_arg, result, NULL);
13935                 forward_destroy(forward);
13936         }
13937 }
13938
13939 isc_result_t
13940 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
13941                        dns_updatecallback_t callback, void *callback_arg)
13942 {
13943         dns_forward_t *forward;
13944         isc_result_t result;
13945         isc_region_t *mr;
13946
13947         REQUIRE(DNS_ZONE_VALID(zone));
13948         REQUIRE(msg != NULL);
13949         REQUIRE(callback != NULL);
13950
13951         forward = isc_mem_get(zone->mctx, sizeof(*forward));
13952         if (forward == NULL)
13953                 return (ISC_R_NOMEMORY);
13954
13955         forward->request = NULL;
13956         forward->zone = NULL;
13957         forward->msgbuf = NULL;
13958         forward->which = 0;
13959         forward->mctx = 0;
13960         forward->callback = callback;
13961         forward->callback_arg = callback_arg;
13962         ISC_LINK_INIT(forward, link);
13963         forward->magic = FORWARD_MAGIC;
13964
13965         mr = dns_message_getrawmessage(msg);
13966         if (mr == NULL) {
13967                 result = ISC_R_UNEXPECTEDEND;
13968                 goto cleanup;
13969         }
13970
13971         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
13972         if (result != ISC_R_SUCCESS)
13973                 goto cleanup;
13974         result = isc_buffer_copyregion(forward->msgbuf, mr);
13975         if (result != ISC_R_SUCCESS)
13976                 goto cleanup;
13977
13978         isc_mem_attach(zone->mctx, &forward->mctx);
13979         dns_zone_iattach(zone, &forward->zone);
13980         result = sendtomaster(forward);
13981
13982  cleanup:
13983         if (result != ISC_R_SUCCESS) {
13984                 forward_destroy(forward);
13985         }
13986         return (result);
13987 }
13988
13989 isc_result_t
13990 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
13991         REQUIRE(DNS_ZONE_VALID(zone));
13992         REQUIRE(next != NULL && *next == NULL);
13993
13994         *next = ISC_LIST_NEXT(zone, link);
13995         if (*next == NULL)
13996                 return (ISC_R_NOMORE);
13997         else
13998                 return (ISC_R_SUCCESS);
13999 }
14000
14001 isc_result_t
14002 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
14003         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14004         REQUIRE(first != NULL && *first == NULL);
14005
14006         *first = ISC_LIST_HEAD(zmgr->zones);
14007         if (*first == NULL)
14008                 return (ISC_R_NOMORE);
14009         else
14010                 return (ISC_R_SUCCESS);
14011 }
14012
14013 /***
14014  ***    Zone manager.
14015  ***/
14016
14017 isc_result_t
14018 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
14019                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
14020                    dns_zonemgr_t **zmgrp)
14021 {
14022         dns_zonemgr_t *zmgr;
14023         isc_result_t result;
14024         isc_interval_t interval;
14025
14026         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
14027         if (zmgr == NULL)
14028                 return (ISC_R_NOMEMORY);
14029         zmgr->mctx = NULL;
14030         zmgr->refs = 1;
14031         isc_mem_attach(mctx, &zmgr->mctx);
14032         zmgr->taskmgr = taskmgr;
14033         zmgr->timermgr = timermgr;
14034         zmgr->socketmgr = socketmgr;
14035         zmgr->zonetasks = NULL;
14036         zmgr->loadtasks = NULL;
14037         zmgr->mctxpool = NULL;
14038         zmgr->task = NULL;
14039         zmgr->rl = NULL;
14040         ISC_LIST_INIT(zmgr->zones);
14041         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
14042         ISC_LIST_INIT(zmgr->xfrin_in_progress);
14043         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
14044         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
14045         if (result != ISC_R_SUCCESS)
14046                 goto free_mem;
14047
14048         zmgr->transfersin = 10;
14049         zmgr->transfersperns = 2;
14050
14051         /* Unreachable lock. */
14052         result = isc_rwlock_init(&zmgr->urlock, 0, 0);
14053         if (result != ISC_R_SUCCESS)
14054                 goto free_rwlock;
14055
14056         /* Create a single task for queueing of SOA queries. */
14057         result = isc_task_create(taskmgr, 1, &zmgr->task);
14058         if (result != ISC_R_SUCCESS)
14059                 goto free_urlock;
14060
14061         isc_task_setname(zmgr->task, "zmgr", zmgr);
14062         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14063                                         &zmgr->rl);
14064         if (result != ISC_R_SUCCESS)
14065                 goto free_task;
14066
14067         /* default to 20 refresh queries / notifies per second. */
14068         isc_interval_set(&interval, 0, 1000000000/2);
14069         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
14070         RUNTIME_CHECK(result == ISC_R_SUCCESS);
14071         isc_ratelimiter_setpertic(zmgr->rl, 10);
14072
14073         zmgr->iolimit = 1;
14074         zmgr->ioactive = 0;
14075         ISC_LIST_INIT(zmgr->high);
14076         ISC_LIST_INIT(zmgr->low);
14077
14078         result = isc_mutex_init(&zmgr->iolock);
14079         if (result != ISC_R_SUCCESS)
14080                 goto free_rl;
14081
14082         zmgr->magic = ZONEMGR_MAGIC;
14083
14084         *zmgrp = zmgr;
14085         return (ISC_R_SUCCESS);
14086
14087 #if 0
14088  free_iolock:
14089         DESTROYLOCK(&zmgr->iolock);
14090 #endif
14091  free_rl:
14092         isc_ratelimiter_detach(&zmgr->rl);
14093  free_task:
14094         isc_task_detach(&zmgr->task);
14095  free_urlock:
14096         isc_rwlock_destroy(&zmgr->urlock);
14097  free_rwlock:
14098         isc_rwlock_destroy(&zmgr->rwlock);
14099  free_mem:
14100         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14101         isc_mem_detach(&mctx);
14102         return (result);
14103 }
14104
14105 isc_result_t
14106 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
14107         isc_result_t result;
14108         isc_mem_t *mctx = NULL;
14109         dns_zone_t *zone = NULL;
14110         void *item;
14111
14112         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14113         REQUIRE(zonep != NULL && *zonep == NULL);
14114
14115         if (zmgr->mctxpool == NULL)
14116                 return (ISC_R_FAILURE);
14117
14118         item = isc_pool_get(zmgr->mctxpool);
14119         if (item == NULL)
14120                 return (ISC_R_FAILURE);
14121
14122         isc_mem_attach((isc_mem_t *) item, &mctx);
14123         result = dns_zone_create(&zone, mctx);
14124         isc_mem_detach(&mctx);
14125
14126         if (result == ISC_R_SUCCESS)
14127                 *zonep = zone;
14128
14129         return (result);
14130 }
14131
14132 isc_result_t
14133 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14134         isc_result_t result;
14135
14136         REQUIRE(DNS_ZONE_VALID(zone));
14137         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14138
14139         if (zmgr->zonetasks == NULL)
14140                 return (ISC_R_FAILURE);
14141
14142         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14143         LOCK_ZONE(zone);
14144         REQUIRE(zone->task == NULL);
14145         REQUIRE(zone->timer == NULL);
14146         REQUIRE(zone->zmgr == NULL);
14147
14148         isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
14149         isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
14150
14151         /*
14152          * Set the task name.  The tag will arbitrarily point to one
14153          * of the zones sharing the task (in practice, the one
14154          * to be managed last).
14155          */
14156         isc_task_setname(zone->task, "zone", zone);
14157         isc_task_setname(zone->loadtask, "loadzone", zone);
14158
14159         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
14160                                   NULL, NULL,
14161                                   zone->task, zone_timer, zone,
14162                                   &zone->timer);
14163
14164         if (result != ISC_R_SUCCESS)
14165                 goto cleanup_tasks;
14166
14167         /*
14168          * The timer "holds" a iref.
14169          */
14170         zone->irefs++;
14171         INSIST(zone->irefs != 0);
14172
14173         ISC_LIST_APPEND(zmgr->zones, zone, link);
14174         zone->zmgr = zmgr;
14175         zmgr->refs++;
14176
14177         goto unlock;
14178
14179  cleanup_tasks:
14180         isc_task_detach(&zone->loadtask);
14181         isc_task_detach(&zone->task);
14182
14183  unlock:
14184         UNLOCK_ZONE(zone);
14185         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14186         return (result);
14187 }
14188
14189 void
14190 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14191         isc_boolean_t free_now = ISC_FALSE;
14192
14193         REQUIRE(DNS_ZONE_VALID(zone));
14194         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14195         REQUIRE(zone->zmgr == zmgr);
14196
14197         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14198         LOCK_ZONE(zone);
14199
14200         ISC_LIST_UNLINK(zmgr->zones, zone, link);
14201         zone->zmgr = NULL;
14202         zmgr->refs--;
14203         if (zmgr->refs == 0)
14204                 free_now = ISC_TRUE;
14205
14206         UNLOCK_ZONE(zone);
14207         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14208
14209         if (free_now)
14210                 zonemgr_free(zmgr);
14211         ENSURE(zone->zmgr == NULL);
14212 }
14213
14214 void
14215 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
14216         REQUIRE(DNS_ZONEMGR_VALID(source));
14217         REQUIRE(target != NULL && *target == NULL);
14218
14219         RWLOCK(&source->rwlock, isc_rwlocktype_write);
14220         REQUIRE(source->refs > 0);
14221         source->refs++;
14222         INSIST(source->refs > 0);
14223         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
14224         *target = source;
14225 }
14226
14227 void
14228 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
14229         dns_zonemgr_t *zmgr;
14230         isc_boolean_t free_now = ISC_FALSE;
14231
14232         REQUIRE(zmgrp != NULL);
14233         zmgr = *zmgrp;
14234         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14235
14236         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14237         zmgr->refs--;
14238         if (zmgr->refs == 0)
14239                 free_now = ISC_TRUE;
14240         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14241
14242         if (free_now)
14243                 zonemgr_free(zmgr);
14244         *zmgrp = NULL;
14245 }
14246
14247 isc_result_t
14248 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
14249         dns_zone_t *p;
14250
14251         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14252
14253         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14254         for (p = ISC_LIST_HEAD(zmgr->zones);
14255              p != NULL;
14256              p = ISC_LIST_NEXT(p, link))
14257         {
14258                 dns_zone_maintenance(p);
14259         }
14260         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14261
14262         /*
14263          * Recent configuration changes may have increased the
14264          * amount of available transfers quota.  Make sure any
14265          * transfers currently blocked on quota get started if
14266          * possible.
14267          */
14268         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14269         zmgr_resume_xfrs(zmgr, ISC_TRUE);
14270         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14271         return (ISC_R_SUCCESS);
14272 }
14273
14274 void
14275 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
14276
14277         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14278
14279         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14280         zmgr_resume_xfrs(zmgr, ISC_TRUE);
14281         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14282 }
14283
14284 void
14285 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
14286         dns_zone_t *zone;
14287
14288         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14289
14290         isc_ratelimiter_shutdown(zmgr->rl);
14291
14292         if (zmgr->task != NULL)
14293                 isc_task_destroy(&zmgr->task);
14294         if (zmgr->zonetasks != NULL)
14295                 isc_taskpool_destroy(&zmgr->zonetasks);
14296         if (zmgr->loadtasks != NULL)
14297                 isc_taskpool_destroy(&zmgr->loadtasks);
14298         if (zmgr->mctxpool != NULL)
14299                 isc_pool_destroy(&zmgr->mctxpool);
14300
14301         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14302         for (zone = ISC_LIST_HEAD(zmgr->zones);
14303              zone != NULL;
14304              zone = ISC_LIST_NEXT(zone, link))
14305         {
14306                 LOCK_ZONE(zone);
14307                 forward_cancel(zone);
14308                 UNLOCK_ZONE(zone);
14309         }
14310         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
14311 }
14312
14313 static isc_result_t
14314 mctxinit(void **target, void *arg) {
14315         isc_result_t result;
14316         isc_mem_t *mctx = NULL;
14317
14318         UNUSED(arg);
14319
14320         REQUIRE(target != NULL && *target == NULL);
14321
14322         result = isc_mem_create(0, 0, &mctx);
14323         if (result != ISC_R_SUCCESS)
14324                 return (result);
14325         isc_mem_setname(mctx, "zonemgr-pool", NULL);
14326
14327         *target = mctx;
14328         return (ISC_R_SUCCESS);
14329 }
14330
14331 static void
14332 mctxfree(void **target) {
14333         isc_mem_t *mctx = *(isc_mem_t **) target;
14334         isc_mem_detach(&mctx);
14335         *target = NULL;
14336 }
14337
14338 #define ZONES_PER_TASK 100
14339 #define ZONES_PER_MCTX 1000
14340
14341 isc_result_t
14342 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
14343         isc_result_t result;
14344         int ntasks = num_zones / ZONES_PER_TASK;
14345         int nmctx = num_zones / ZONES_PER_MCTX;
14346         isc_taskpool_t *pool = NULL;
14347         isc_pool_t *mctxpool = NULL;
14348
14349         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14350
14351         /*
14352          * For anything fewer than 1000 zones we use 10 tasks in
14353          * the task pools.  More than that, and we'll scale at one
14354          * task per 100 zones.  Similarly, for anything smaller than
14355          * 2000 zones we use 2 memory contexts, then scale at 1:1000.
14356          */
14357         if (ntasks < 10)
14358                 ntasks = 10;
14359         if (nmctx < 2)
14360                 nmctx = 2;
14361
14362         /* Create or resize the zone task pools. */
14363         if (zmgr->zonetasks == NULL)
14364                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
14365                                              ntasks, 2, &pool);
14366         else
14367                 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
14368
14369         if (result == ISC_R_SUCCESS)
14370                 zmgr->zonetasks = pool;
14371
14372         pool = NULL;
14373         if (zmgr->loadtasks == NULL)
14374                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
14375                                              ntasks, 2, &pool);
14376         else
14377                 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
14378
14379         if (result == ISC_R_SUCCESS)
14380                 zmgr->loadtasks = pool;
14381
14382 #ifdef BIND9
14383         /*
14384          * We always set all tasks in the zone-load task pool to
14385          * privileged.  This prevents other tasks in the system from
14386          * running while the server task manager is in privileged
14387          * mode.
14388          *
14389          * NOTE: If we start using task privileges for any other
14390          * part of the system than zone tasks, then this will need to be
14391          * revisted.  In that case we'd want to turn on privileges for
14392          * zone tasks only when we were loading, and turn them off the
14393          * rest of the time.  For now, however, it's okay to just
14394          * set it and forget it.
14395          */
14396         isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
14397 #endif
14398
14399         /* Create or resize the zone memory context pool. */
14400         if (zmgr->mctxpool == NULL)
14401                 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
14402                                          mctxinit, NULL, &mctxpool);
14403         else
14404                 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
14405
14406         if (result == ISC_R_SUCCESS)
14407                 zmgr->mctxpool = mctxpool;
14408
14409         return (result);
14410 }
14411
14412 static void
14413 zonemgr_free(dns_zonemgr_t *zmgr) {
14414         isc_mem_t *mctx;
14415
14416         INSIST(zmgr->refs == 0);
14417         INSIST(ISC_LIST_EMPTY(zmgr->zones));
14418
14419         zmgr->magic = 0;
14420
14421         DESTROYLOCK(&zmgr->iolock);
14422         isc_ratelimiter_detach(&zmgr->rl);
14423
14424         isc_rwlock_destroy(&zmgr->urlock);
14425         isc_rwlock_destroy(&zmgr->rwlock);
14426         mctx = zmgr->mctx;
14427         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14428         isc_mem_detach(&mctx);
14429 }
14430
14431 void
14432 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
14433         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14434
14435         zmgr->transfersin = value;
14436 }
14437
14438 isc_uint32_t
14439 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
14440         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14441
14442         return (zmgr->transfersin);
14443 }
14444
14445 void
14446 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
14447         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14448
14449         zmgr->transfersperns = value;
14450 }
14451
14452 isc_uint32_t
14453 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
14454         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14455
14456         return (zmgr->transfersperns);
14457 }
14458
14459 /*
14460  * Try to start a new incoming zone transfer to fill a quota
14461  * slot that was just vacated.
14462  *
14463  * Requires:
14464  *      The zone manager is locked by the caller.
14465  */
14466 static void
14467 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
14468         dns_zone_t *zone;
14469         dns_zone_t *next;
14470
14471         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
14472              zone != NULL;
14473              zone = next)
14474         {
14475                 isc_result_t result;
14476                 next = ISC_LIST_NEXT(zone, statelink);
14477                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
14478                 if (result == ISC_R_SUCCESS) {
14479                         if (multi)
14480                                 continue;
14481                         /*
14482                          * We successfully filled the slot.  We're done.
14483                          */
14484                         break;
14485                 } else if (result == ISC_R_QUOTA) {
14486                         /*
14487                          * Not enough quota.  This is probably the per-server
14488                          * quota, because we usually get called when a unit of
14489                          * global quota has just been freed.  Try the next
14490                          * zone, it may succeed if it uses another master.
14491                          */
14492                         continue;
14493                 } else {
14494                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
14495                                      "starting zone transfer: %s",
14496                                      isc_result_totext(result));
14497                         break;
14498                 }
14499         }
14500 }
14501
14502 /*
14503  * Try to start an incoming zone transfer for 'zone', quota permitting.
14504  *
14505  * Requires:
14506  *      The zone manager is locked by the caller.
14507  *
14508  * Returns:
14509  *      ISC_R_SUCCESS   There was enough quota and we attempted to
14510  *                      start a transfer.  zone_xfrdone() has been or will
14511  *                      be called.
14512  *      ISC_R_QUOTA     Not enough quota.
14513  *      Others          Failure.
14514  */
14515 static isc_result_t
14516 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14517         dns_peer_t *peer = NULL;
14518         isc_netaddr_t masterip;
14519         isc_uint32_t nxfrsin, nxfrsperns;
14520         dns_zone_t *x;
14521         isc_uint32_t maxtransfersin, maxtransfersperns;
14522         isc_event_t *e;
14523
14524         /*
14525          * If we are exiting just pretend we got quota so the zone will
14526          * be cleaned up in the zone's task context.
14527          */
14528         LOCK_ZONE(zone);
14529         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14530                 UNLOCK_ZONE(zone);
14531                 goto gotquota;
14532         }
14533
14534         /*
14535          * Find any configured information about the server we'd
14536          * like to transfer this zone from.
14537          */
14538         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14539         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
14540         UNLOCK_ZONE(zone);
14541
14542         /*
14543          * Determine the total maximum number of simultaneous
14544          * transfers allowed, and the maximum for this specific
14545          * master.
14546          */
14547         maxtransfersin = zmgr->transfersin;
14548         maxtransfersperns = zmgr->transfersperns;
14549         if (peer != NULL)
14550                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
14551
14552         /*
14553          * Count the total number of transfers that are in progress,
14554          * and the number of transfers in progress from this master.
14555          * We linearly scan a list of all transfers; if this turns
14556          * out to be too slow, we could hash on the master address.
14557          */
14558         nxfrsin = nxfrsperns = 0;
14559         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
14560              x != NULL;
14561              x = ISC_LIST_NEXT(x, statelink))
14562         {
14563                 isc_netaddr_t xip;
14564
14565                 LOCK_ZONE(x);
14566                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
14567                 UNLOCK_ZONE(x);
14568
14569                 nxfrsin++;
14570                 if (isc_netaddr_equal(&xip, &masterip))
14571                         nxfrsperns++;
14572         }
14573
14574         /* Enforce quota. */
14575         if (nxfrsin >= maxtransfersin)
14576                 return (ISC_R_QUOTA);
14577
14578         if (nxfrsperns >= maxtransfersperns)
14579                 return (ISC_R_QUOTA);
14580
14581  gotquota:
14582         /*
14583          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
14584          * list and send it an event to let it start the actual transfer in the
14585          * context of its own task.
14586          */
14587         e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
14588                                got_transfer_quota, zone, sizeof(isc_event_t));
14589         if (e == NULL)
14590                 return (ISC_R_NOMEMORY);
14591
14592         LOCK_ZONE(zone);
14593         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
14594         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
14595         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
14596         zone->statelist = &zmgr->xfrin_in_progress;
14597         isc_task_send(zone->task, &e);
14598         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
14599         UNLOCK_ZONE(zone);
14600
14601         return (ISC_R_SUCCESS);
14602 }
14603
14604 void
14605 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
14606
14607         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14608         REQUIRE(iolimit > 0);
14609
14610         zmgr->iolimit = iolimit;
14611 }
14612
14613 isc_uint32_t
14614 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
14615
14616         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14617
14618         return (zmgr->iolimit);
14619 }
14620
14621 /*
14622  * Get permission to request a file handle from the OS.
14623  * An event will be sent to action when one is available.
14624  * There are two queues available (high and low), the high
14625  * queue will be serviced before the low one.
14626  *
14627  * zonemgr_putio() must be called after the event is delivered to
14628  * 'action'.
14629  */
14630
14631 static isc_result_t
14632 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
14633               isc_task_t *task, isc_taskaction_t action, void *arg,
14634               dns_io_t **iop)
14635 {
14636         dns_io_t *io;
14637         isc_boolean_t queue;
14638
14639         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14640         REQUIRE(iop != NULL && *iop == NULL);
14641
14642         io = isc_mem_get(zmgr->mctx, sizeof(*io));
14643         if (io == NULL)
14644                 return (ISC_R_NOMEMORY);
14645
14646         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
14647                                        action, arg, sizeof(*io->event));
14648         if (io->event == NULL) {
14649                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
14650                 return (ISC_R_NOMEMORY);
14651         }
14652
14653         io->zmgr = zmgr;
14654         io->high = high;
14655         io->task = NULL;
14656         isc_task_attach(task, &io->task);
14657         ISC_LINK_INIT(io, link);
14658         io->magic = IO_MAGIC;
14659
14660         LOCK(&zmgr->iolock);
14661         zmgr->ioactive++;
14662         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
14663         if (queue) {
14664                 if (io->high)
14665                         ISC_LIST_APPEND(zmgr->high, io, link);
14666                 else
14667                         ISC_LIST_APPEND(zmgr->low, io, link);
14668         }
14669         UNLOCK(&zmgr->iolock);
14670         *iop = io;
14671
14672         if (!queue)
14673                 isc_task_send(io->task, &io->event);
14674         return (ISC_R_SUCCESS);
14675 }
14676
14677 static void
14678 zonemgr_putio(dns_io_t **iop) {
14679         dns_io_t *io;
14680         dns_io_t *next;
14681         dns_zonemgr_t *zmgr;
14682
14683         REQUIRE(iop != NULL);
14684         io = *iop;
14685         REQUIRE(DNS_IO_VALID(io));
14686
14687         *iop = NULL;
14688
14689         INSIST(!ISC_LINK_LINKED(io, link));
14690         INSIST(io->event == NULL);
14691
14692         zmgr = io->zmgr;
14693         isc_task_detach(&io->task);
14694         io->magic = 0;
14695         isc_mem_put(zmgr->mctx, io, sizeof(*io));
14696
14697         LOCK(&zmgr->iolock);
14698         INSIST(zmgr->ioactive > 0);
14699         zmgr->ioactive--;
14700         next = HEAD(zmgr->high);
14701         if (next == NULL)
14702                 next = HEAD(zmgr->low);
14703         if (next != NULL) {
14704                 if (next->high)
14705                         ISC_LIST_UNLINK(zmgr->high, next, link);
14706                 else
14707                         ISC_LIST_UNLINK(zmgr->low, next, link);
14708                 INSIST(next->event != NULL);
14709         }
14710         UNLOCK(&zmgr->iolock);
14711         if (next != NULL)
14712                 isc_task_send(next->task, &next->event);
14713 }
14714
14715 static void
14716 zonemgr_cancelio(dns_io_t *io) {
14717         isc_boolean_t send_event = ISC_FALSE;
14718
14719         REQUIRE(DNS_IO_VALID(io));
14720
14721         /*
14722          * If we are queued to be run then dequeue.
14723          */
14724         LOCK(&io->zmgr->iolock);
14725         if (ISC_LINK_LINKED(io, link)) {
14726                 if (io->high)
14727                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
14728                 else
14729                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
14730
14731                 send_event = ISC_TRUE;
14732                 INSIST(io->event != NULL);
14733         }
14734         UNLOCK(&io->zmgr->iolock);
14735         if (send_event) {
14736                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
14737                 isc_task_send(io->task, &io->event);
14738         }
14739 }
14740
14741 static void
14742 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
14743         char *buf;
14744         int buflen;
14745         isc_result_t result;
14746
14747         buflen = strlen(path) + strlen(templat) + 2;
14748
14749         buf = isc_mem_get(zone->mctx, buflen);
14750         if (buf == NULL)
14751                 return;
14752
14753         result = isc_file_template(path, templat, buf, buflen);
14754         if (result != ISC_R_SUCCESS)
14755                 goto cleanup;
14756
14757         result = isc_file_renameunique(path, buf);
14758         if (result != ISC_R_SUCCESS)
14759                 goto cleanup;
14760
14761         dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
14762                      "renaming file to '%s' for failure analysis and "
14763                      "retransferring.", path, buf);
14764
14765  cleanup:
14766         isc_mem_put(zone->mctx, buf, buflen);
14767 }
14768
14769 #if 0
14770 /* Hook for ondestroy notification from a database. */
14771
14772 static void
14773 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
14774         dns_db_t *db = event->sender;
14775         UNUSED(task);
14776
14777         isc_event_free(&event);
14778
14779         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14780                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
14781                       "database (%p) destroyed", (void*) db);
14782 }
14783 #endif
14784
14785 void
14786 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
14787         isc_interval_t interval;
14788         isc_uint32_t s, ns;
14789         isc_uint32_t pertic;
14790         isc_result_t result;
14791
14792         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14793
14794         if (value == 0)
14795                 value = 1;
14796
14797         if (value == 1) {
14798                 s = 1;
14799                 ns = 0;
14800                 pertic = 1;
14801         } else if (value <= 10) {
14802                 s = 0;
14803                 ns = 1000000000 / value;
14804                 pertic = 1;
14805         } else {
14806                 s = 0;
14807                 ns = (1000000000 / value) * 10;
14808                 pertic = 10;
14809         }
14810
14811         isc_interval_set(&interval, s, ns);
14812         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
14813         RUNTIME_CHECK(result == ISC_R_SUCCESS);
14814         isc_ratelimiter_setpertic(zmgr->rl, pertic);
14815
14816         zmgr->serialqueryrate = value;
14817 }
14818
14819 unsigned int
14820 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
14821         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14822
14823         return (zmgr->serialqueryrate);
14824 }
14825
14826 isc_boolean_t
14827 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
14828                         isc_sockaddr_t *local, isc_time_t *now)
14829 {
14830         unsigned int i;
14831         isc_rwlocktype_t locktype;
14832         isc_result_t result;
14833         isc_uint32_t seconds = isc_time_seconds(now);
14834
14835         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14836
14837         locktype = isc_rwlocktype_read;
14838         RWLOCK(&zmgr->urlock, locktype);
14839         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
14840                 if (zmgr->unreachable[i].expire >= seconds &&
14841                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
14842                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
14843                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
14844                         if (result == ISC_R_SUCCESS) {
14845                                 locktype = isc_rwlocktype_write;
14846                                 zmgr->unreachable[i].last = seconds;
14847                         }
14848                         break;
14849                 }
14850         }
14851         RWUNLOCK(&zmgr->urlock, locktype);
14852         return (ISC_TF(i < UNREACH_CHACHE_SIZE));
14853 }
14854
14855 void
14856 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
14857                            isc_sockaddr_t *local)
14858 {
14859         unsigned int i;
14860         isc_rwlocktype_t locktype;
14861         isc_result_t result;
14862
14863         char master[ISC_SOCKADDR_FORMATSIZE];
14864         char source[ISC_SOCKADDR_FORMATSIZE];
14865
14866         isc_sockaddr_format(remote, master, sizeof(master));
14867         isc_sockaddr_format(local, source, sizeof(source));
14868
14869         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14870
14871         locktype = isc_rwlocktype_read;
14872         RWLOCK(&zmgr->urlock, locktype);
14873         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
14874                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
14875                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
14876                         if (zmgr->unreachable[i].expire == 0)
14877                                 break;
14878                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
14879                         if (result == ISC_R_SUCCESS) {
14880                                 locktype = isc_rwlocktype_write;
14881                                 zmgr->unreachable[i].expire = 0;
14882                                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14883                                               DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
14884                                               "master %s (source %s) deleted "
14885                                               "from unreachable cache",
14886                                               master, source);
14887                         }
14888                         break;
14889                 }
14890         }
14891         RWUNLOCK(&zmgr->urlock, locktype);
14892 }
14893
14894 void
14895 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
14896                            isc_sockaddr_t *local, isc_time_t *now)
14897 {
14898         isc_uint32_t seconds = isc_time_seconds(now);
14899         isc_uint32_t last = seconds;
14900         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
14901
14902         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14903
14904         RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
14905         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
14906                 /* Existing entry? */
14907                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
14908                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
14909                         break;
14910                 /* Empty slot? */
14911                 if (zmgr->unreachable[i].expire < seconds)
14912                         slot = i;
14913                 /* Least recently used slot? */
14914                 if (zmgr->unreachable[i].last < last) {
14915                         last = zmgr->unreachable[i].last;
14916                         oldest = i;
14917                 }
14918         }
14919         if (i < UNREACH_CHACHE_SIZE) {
14920                 /*
14921                  * Found a existing entry.  Update the expire timer and
14922                  * last usage timestamps.
14923                  */
14924                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
14925                 zmgr->unreachable[i].last = seconds;
14926         } else if (slot != UNREACH_CHACHE_SIZE) {
14927                 /*
14928                  * Found a empty slot. Add a new entry to the cache.
14929                  */
14930                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
14931                 zmgr->unreachable[slot].last = seconds;
14932                 zmgr->unreachable[slot].remote = *remote;
14933                 zmgr->unreachable[slot].local = *local;
14934         } else {
14935                 /*
14936                  * Replace the least recently used entry in the cache.
14937                  */
14938                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
14939                 zmgr->unreachable[oldest].last = seconds;
14940                 zmgr->unreachable[oldest].remote = *remote;
14941                 zmgr->unreachable[oldest].local = *local;
14942         }
14943         RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
14944 }
14945
14946 void
14947 dns_zone_forcereload(dns_zone_t *zone) {
14948         REQUIRE(DNS_ZONE_VALID(zone));
14949
14950         if (zone->type == dns_zone_master ||
14951             (zone->type == dns_zone_redirect && zone->masters == NULL))
14952                 return;
14953
14954         LOCK_ZONE(zone);
14955         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
14956         UNLOCK_ZONE(zone);
14957         dns_zone_refresh(zone);
14958 }
14959
14960 isc_boolean_t
14961 dns_zone_isforced(dns_zone_t *zone) {
14962         REQUIRE(DNS_ZONE_VALID(zone));
14963
14964         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
14965 }
14966
14967 isc_result_t
14968 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
14969         /*
14970          * This function is obsoleted.
14971          */
14972         UNUSED(zone);
14973         UNUSED(on);
14974         return (ISC_R_NOTIMPLEMENTED);
14975 }
14976
14977 isc_uint64_t *
14978 dns_zone_getstatscounters(dns_zone_t *zone) {
14979         /*
14980          * This function is obsoleted.
14981          */
14982         UNUSED(zone);
14983         return (NULL);
14984 }
14985
14986 void
14987 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
14988         REQUIRE(DNS_ZONE_VALID(zone));
14989         REQUIRE(zone->stats == NULL);
14990
14991         LOCK_ZONE(zone);
14992         zone->stats = NULL;
14993         isc_stats_attach(stats, &zone->stats);
14994         UNLOCK_ZONE(zone);
14995 }
14996
14997 void
14998 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
14999
15000         REQUIRE(DNS_ZONE_VALID(zone));
15001
15002         LOCK_ZONE(zone);
15003         if (zone->requeststats_on && stats == NULL)
15004                 zone->requeststats_on = ISC_FALSE;
15005         else if (!zone->requeststats_on && stats != NULL) {
15006                 if (zone->requeststats == NULL) {
15007                         isc_stats_attach(stats, &zone->requeststats);
15008                         zone->requeststats_on = ISC_TRUE;
15009                 }
15010         }
15011         UNLOCK_ZONE(zone);
15012 }
15013
15014 #ifdef NEWSTATS
15015 void
15016 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
15017
15018         REQUIRE(DNS_ZONE_VALID(zone));
15019
15020         LOCK_ZONE(zone);
15021         if (zone->requeststats_on && stats != NULL) {
15022                 if (zone->rcvquerystats == NULL) {
15023                         dns_stats_attach(stats, &zone->rcvquerystats);
15024                         zone->requeststats_on = ISC_TRUE;
15025                 }
15026         }
15027         UNLOCK_ZONE(zone);
15028 }
15029 #endif
15030
15031 isc_stats_t *
15032 dns_zone_getrequeststats(dns_zone_t *zone) {
15033         /*
15034          * We don't lock zone for efficiency reason.  This is not catastrophic
15035          * because requeststats must always be valid when requeststats_on is
15036          * true.
15037          * Some counters may be incremented while requeststats_on is becoming
15038          * false, or some cannot be incremented just after the statistics are
15039          * installed, but it shouldn't matter much in practice.
15040          */
15041         if (zone->requeststats_on)
15042                 return (zone->requeststats);
15043         else
15044                 return (NULL);
15045 }
15046
15047 #ifdef NEWSTATS
15048 /*
15049  * Return the received query stats bucket
15050  * see note from dns_zone_getrequeststats()
15051  */
15052 dns_stats_t *
15053 dns_zone_getrcvquerystats(dns_zone_t *zone) {
15054         if (zone->requeststats_on)
15055                 return (zone->rcvquerystats);
15056         else
15057                 return (NULL);
15058 }
15059 #endif
15060
15061 void
15062 dns_zone_dialup(dns_zone_t *zone) {
15063
15064         REQUIRE(DNS_ZONE_VALID(zone));
15065
15066         zone_debuglog(zone, "dns_zone_dialup", 3,
15067                       "notify = %d, refresh = %d",
15068                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
15069                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
15070
15071         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
15072                 dns_zone_notify(zone);
15073         if (zone->type != dns_zone_master && zone->masters != NULL &&
15074             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
15075                 dns_zone_refresh(zone);
15076 }
15077
15078 void
15079 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
15080         REQUIRE(DNS_ZONE_VALID(zone));
15081
15082         LOCK_ZONE(zone);
15083         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
15084                          DNS_ZONEFLG_DIALREFRESH |
15085                          DNS_ZONEFLG_NOREFRESH);
15086         switch (dialup) {
15087         case dns_dialuptype_no:
15088                 break;
15089         case dns_dialuptype_yes:
15090                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
15091                                  DNS_ZONEFLG_DIALREFRESH |
15092                                  DNS_ZONEFLG_NOREFRESH));
15093                 break;
15094         case dns_dialuptype_notify:
15095                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15096                 break;
15097         case dns_dialuptype_notifypassive:
15098                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15099                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15100                 break;
15101         case dns_dialuptype_refresh:
15102                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
15103                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15104                 break;
15105         case dns_dialuptype_passive:
15106                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15107                 break;
15108         default:
15109                 INSIST(0);
15110         }
15111         UNLOCK_ZONE(zone);
15112 }
15113
15114 isc_result_t
15115 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
15116         isc_result_t result = ISC_R_SUCCESS;
15117
15118         REQUIRE(DNS_ZONE_VALID(zone));
15119
15120         LOCK_ZONE(zone);
15121         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
15122         UNLOCK_ZONE(zone);
15123
15124         return (result);
15125 }
15126
15127 const char *
15128 dns_zone_getkeydirectory(dns_zone_t *zone) {
15129         REQUIRE(DNS_ZONE_VALID(zone));
15130
15131         return (zone->keydirectory);
15132 }
15133
15134 unsigned int
15135 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
15136         dns_zone_t *zone;
15137         unsigned int count = 0;
15138
15139         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15140
15141         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15142         switch (state) {
15143         case DNS_ZONESTATE_XFERRUNNING:
15144                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15145                      zone != NULL;
15146                      zone = ISC_LIST_NEXT(zone, statelink))
15147                         count++;
15148                 break;
15149         case DNS_ZONESTATE_XFERDEFERRED:
15150                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
15151                      zone != NULL;
15152                      zone = ISC_LIST_NEXT(zone, statelink))
15153                         count++;
15154                 break;
15155         case DNS_ZONESTATE_SOAQUERY:
15156                 for (zone = ISC_LIST_HEAD(zmgr->zones);
15157                      zone != NULL;
15158                      zone = ISC_LIST_NEXT(zone, link))
15159                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
15160                                 count++;
15161                 break;
15162         case DNS_ZONESTATE_ANY:
15163                 for (zone = ISC_LIST_HEAD(zmgr->zones);
15164                      zone != NULL;
15165                      zone = ISC_LIST_NEXT(zone, link)) {
15166                         dns_view_t *view = zone->view;
15167                         if (view != NULL && strcmp(view->name, "_bind") == 0)
15168                                 continue;
15169                         count++;
15170                 }
15171                 break;
15172         default:
15173                 INSIST(0);
15174         }
15175
15176         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15177
15178         return (count);
15179 }
15180
15181 isc_result_t
15182 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
15183         isc_boolean_t ok = ISC_TRUE;
15184         isc_boolean_t fail = ISC_FALSE;
15185         char namebuf[DNS_NAME_FORMATSIZE];
15186         char namebuf2[DNS_NAME_FORMATSIZE];
15187         char typebuf[DNS_RDATATYPE_FORMATSIZE];
15188         int level = ISC_LOG_WARNING;
15189         dns_name_t bad;
15190
15191         REQUIRE(DNS_ZONE_VALID(zone));
15192
15193         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
15194                 return (ISC_R_SUCCESS);
15195
15196         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
15197                 level = ISC_LOG_ERROR;
15198                 fail = ISC_TRUE;
15199         }
15200
15201         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
15202         if (!ok) {
15203                 dns_name_format(name, namebuf, sizeof(namebuf));
15204                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
15205                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
15206                              dns_result_totext(DNS_R_BADOWNERNAME));
15207                 if (fail)
15208                         return (DNS_R_BADOWNERNAME);
15209         }
15210
15211         dns_name_init(&bad, NULL);
15212         ok = dns_rdata_checknames(rdata, name, &bad);
15213         if (!ok) {
15214                 dns_name_format(name, namebuf, sizeof(namebuf));
15215                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
15216                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
15217                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
15218                              namebuf2, dns_result_totext(DNS_R_BADNAME));
15219                 if (fail)
15220                         return (DNS_R_BADNAME);
15221         }
15222
15223         return (ISC_R_SUCCESS);
15224 }
15225
15226 void
15227 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
15228         REQUIRE(DNS_ZONE_VALID(zone));
15229         zone->checkmx = checkmx;
15230 }
15231
15232 void
15233 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
15234         REQUIRE(DNS_ZONE_VALID(zone));
15235         zone->checksrv = checksrv;
15236 }
15237
15238 void
15239 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
15240         REQUIRE(DNS_ZONE_VALID(zone));
15241         zone->checkns = checkns;
15242 }
15243
15244 void
15245 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
15246         REQUIRE(DNS_ZONE_VALID(zone));
15247
15248         LOCK_ZONE(zone);
15249         zone->isself = isself;
15250         zone->isselfarg = arg;
15251         UNLOCK_ZONE(zone);
15252 }
15253
15254 void
15255 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
15256         REQUIRE(DNS_ZONE_VALID(zone));
15257
15258         LOCK_ZONE(zone);
15259         zone->notifydelay = delay;
15260         UNLOCK_ZONE(zone);
15261 }
15262
15263 isc_uint32_t
15264 dns_zone_getnotifydelay(dns_zone_t *zone) {
15265         REQUIRE(DNS_ZONE_VALID(zone));
15266
15267         return (zone->notifydelay);
15268 }
15269
15270 isc_result_t
15271 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
15272                      isc_uint16_t keyid, isc_boolean_t delete)
15273 {
15274         isc_result_t result;
15275         REQUIRE(DNS_ZONE_VALID(zone));
15276
15277         dns_zone_log(zone, ISC_LOG_NOTICE,
15278                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
15279                      algorithm, keyid);
15280         LOCK_ZONE(zone);
15281         result = zone_signwithkey(zone, algorithm, keyid, delete);
15282         UNLOCK_ZONE(zone);
15283
15284         return (result);
15285 }
15286
15287 static const char *hex = "0123456789ABCDEF";
15288
15289 isc_result_t
15290 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
15291         isc_result_t result;
15292         char salt[255*2+1];
15293         unsigned int i, j;
15294
15295         REQUIRE(DNS_ZONE_VALID(zone));
15296
15297         if (nsec3param->salt_length != 0) {
15298                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
15299                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
15300                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
15301                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
15302                 }
15303                 salt[j] = '\0';
15304         } else
15305                 strcpy(salt, "-");
15306         dns_zone_log(zone, ISC_LOG_NOTICE,
15307                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
15308                      nsec3param->hash, nsec3param->iterations,
15309                      salt);
15310         LOCK_ZONE(zone);
15311         result = zone_addnsec3chain(zone, nsec3param);
15312         UNLOCK_ZONE(zone);
15313
15314         return (result);
15315 }
15316
15317 void
15318 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
15319         REQUIRE(DNS_ZONE_VALID(zone));
15320
15321         if (nodes == 0)
15322                 nodes = 1;
15323         zone->nodes = nodes;
15324 }
15325
15326 void
15327 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
15328         REQUIRE(DNS_ZONE_VALID(zone));
15329
15330         /*
15331          * We treat signatures as a signed value so explicitly
15332          * limit its range here.
15333          */
15334         if (signatures > ISC_INT32_MAX)
15335                 signatures = ISC_INT32_MAX;
15336         else if (signatures == 0)
15337                 signatures = 1;
15338         zone->signatures = signatures;
15339 }
15340
15341 void
15342 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
15343         REQUIRE(DNS_ZONE_VALID(zone));
15344         zone->privatetype = type;
15345 }
15346
15347 dns_rdatatype_t
15348 dns_zone_getprivatetype(dns_zone_t *zone) {
15349         REQUIRE(DNS_ZONE_VALID(zone));
15350         return (zone->privatetype);
15351 }
15352
15353 static isc_result_t
15354 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
15355                  isc_boolean_t delete)
15356 {
15357         dns_signing_t *signing;
15358         dns_signing_t *current;
15359         isc_result_t result = ISC_R_SUCCESS;
15360         isc_time_t now;
15361
15362         signing = isc_mem_get(zone->mctx, sizeof *signing);
15363         if (signing == NULL)
15364                 return (ISC_R_NOMEMORY);
15365
15366         signing->magic = 0;
15367         signing->db  = NULL;
15368         signing->dbiterator = NULL;
15369         signing->algorithm = algorithm;
15370         signing->keyid = keyid;
15371         signing->delete = delete;
15372         signing->done = ISC_FALSE;
15373
15374         TIME_NOW(&now);
15375
15376         for (current = ISC_LIST_HEAD(zone->signing);
15377              current != NULL;
15378              current = ISC_LIST_NEXT(current, link)) {
15379                 if (current->db == zone->db &&
15380                     current->algorithm == signing->algorithm &&
15381                     current->keyid == signing->keyid) {
15382                         if (current->delete != signing->delete)
15383                                 current->done = ISC_TRUE;
15384                         else
15385                                 goto cleanup;
15386                 }
15387         }
15388
15389         if (zone->db != NULL) {
15390                 dns_db_attach(zone->db, &signing->db);
15391                 result = dns_db_createiterator(signing->db, 0,
15392                                                &signing->dbiterator);
15393
15394                 if (result == ISC_R_SUCCESS)
15395                         result = dns_dbiterator_first(signing->dbiterator);
15396                 if (result == ISC_R_SUCCESS) {
15397                         dns_dbiterator_pause(signing->dbiterator);
15398                         ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
15399                         signing = NULL;
15400                         if (isc_time_isepoch(&zone->signingtime)) {
15401                                 zone->signingtime = now;
15402                                 if (zone->task != NULL)
15403                                         zone_settimer(zone, &now);
15404                         }
15405                 }
15406         } else
15407                 result = ISC_R_NOTFOUND;
15408
15409  cleanup:
15410         if (signing != NULL) {
15411                 if (signing->db != NULL)
15412                         dns_db_detach(&signing->db);
15413                 if (signing->dbiterator != NULL)
15414                         dns_dbiterator_destroy(&signing->dbiterator);
15415                 isc_mem_put(zone->mctx, signing, sizeof *signing);
15416         }
15417         return (result);
15418 }
15419
15420 static void
15421 logmsg(const char *format, ...) {
15422         va_list args;
15423         va_start(args, format);
15424         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
15425                        ISC_LOG_DEBUG(1), format, args);
15426         va_end(args);
15427 }
15428
15429 static void
15430 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
15431         dns_dnsseckey_t *key;
15432         while (!ISC_LIST_EMPTY(*list)) {
15433                 key = ISC_LIST_HEAD(*list);
15434                 ISC_LIST_UNLINK(*list, key, link);
15435                 dns_dnsseckey_destroy(mctx, &key);
15436         }
15437 }
15438
15439 /* Called once; *timep should be set to the current time. */
15440 static isc_result_t
15441 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
15442         isc_result_t result;
15443         isc_stdtime_t now, then = 0, event;
15444         int i;
15445
15446         now = *timep;
15447
15448         for (i = 0; i <= DST_MAX_TIMES; i++) {
15449                 result = dst_key_gettime(key, i, &event);
15450                 if (result == ISC_R_SUCCESS && event > now &&
15451                     (then == 0 || event < then))
15452                         then = event;
15453         }
15454
15455         if (then != 0) {
15456                 *timep = then;
15457                 return (ISC_R_SUCCESS);
15458         }
15459
15460         return (ISC_R_NOTFOUND);
15461 }
15462
15463 static isc_result_t
15464 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
15465           const dns_rdata_t *rdata, isc_boolean_t *flag)
15466 {
15467         dns_rdataset_t rdataset;
15468         dns_dbnode_t *node = NULL;
15469         isc_result_t result;
15470
15471         dns_rdataset_init(&rdataset);
15472         if (rdata->type == dns_rdatatype_nsec3)
15473                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
15474         else
15475                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
15476         result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
15477                                      (isc_stdtime_t) 0, &rdataset, NULL);
15478         if (result == ISC_R_NOTFOUND) {
15479                 *flag = ISC_FALSE;
15480                 result = ISC_R_SUCCESS;
15481                 goto failure;
15482         }
15483
15484         for (result = dns_rdataset_first(&rdataset);
15485              result == ISC_R_SUCCESS;
15486              result = dns_rdataset_next(&rdataset)) {
15487                 dns_rdata_t myrdata = DNS_RDATA_INIT;
15488                 dns_rdataset_current(&rdataset, &myrdata);
15489                 if (!dns_rdata_compare(&myrdata, rdata))
15490                         break;
15491         }
15492         dns_rdataset_disassociate(&rdataset);
15493         if (result == ISC_R_SUCCESS) {
15494                 *flag = ISC_TRUE;
15495         } else if (result == ISC_R_NOMORE) {
15496                 *flag = ISC_FALSE;
15497                 result = ISC_R_SUCCESS;
15498         }
15499
15500  failure:
15501         if (node != NULL)
15502                 dns_db_detachnode(db, &node);
15503         return (result);
15504 }
15505
15506 /*
15507  * Add records to signal the state of signing or of key removal.
15508  */
15509 static isc_result_t
15510 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
15511                     dns_dbversion_t *ver, dns_diff_t *diff,
15512                     isc_boolean_t sign_all)
15513 {
15514         dns_difftuple_t *tuple, *newtuple = NULL;
15515         dns_rdata_dnskey_t dnskey;
15516         dns_rdata_t rdata = DNS_RDATA_INIT;
15517         isc_boolean_t flag;
15518         isc_region_t r;
15519         isc_result_t result = ISC_R_SUCCESS;
15520         isc_uint16_t keyid;
15521         unsigned char buf[5];
15522         dns_name_t *name = dns_db_origin(db);
15523
15524         for (tuple = ISC_LIST_HEAD(diff->tuples);
15525              tuple != NULL;
15526              tuple = ISC_LIST_NEXT(tuple, link)) {
15527                 if (tuple->rdata.type != dns_rdatatype_dnskey)
15528                         continue;
15529
15530                 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
15531                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15532                 if ((dnskey.flags &
15533                      (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
15534                          != DNS_KEYOWNER_ZONE)
15535                         continue;
15536
15537                 dns_rdata_toregion(&tuple->rdata, &r);
15538
15539                 keyid = dst_region_computeid(&r, dnskey.algorithm);
15540
15541                 buf[0] = dnskey.algorithm;
15542                 buf[1] = (keyid & 0xff00) >> 8;
15543                 buf[2] = (keyid & 0xff);
15544                 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
15545                 buf[4] = 0;
15546                 rdata.data = buf;
15547                 rdata.length = sizeof(buf);
15548                 rdata.type = privatetype;
15549                 rdata.rdclass = tuple->rdata.rdclass;
15550
15551                 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
15552                         CHECK(rr_exists(db, ver, name, &rdata, &flag));
15553                         if (flag)
15554                                 continue;
15555                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
15556                                                    name, 0, &rdata, &newtuple));
15557                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
15558                         INSIST(newtuple == NULL);
15559                 }
15560
15561                 /*
15562                  * Remove any record which says this operation has already
15563                  * completed.
15564                  */
15565                 buf[4] = 1;
15566                 CHECK(rr_exists(db, ver, name, &rdata, &flag));
15567                 if (flag) {
15568                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
15569                                                    name, 0, &rdata, &newtuple));
15570                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
15571                         INSIST(newtuple == NULL);
15572                 }
15573         }
15574  failure:
15575         return (result);
15576 }
15577
15578 static isc_result_t
15579 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
15580           dns_diff_t *diff, zonediff_t *zonediff)
15581 {
15582         isc_result_t result;
15583         isc_stdtime_t now, inception, soaexpire;
15584         isc_boolean_t check_ksk, keyset_kskonly;
15585         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
15586         unsigned int nkeys = 0, i;
15587         dns_difftuple_t *tuple;
15588
15589         result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
15590                                 zone_keys, &nkeys);
15591         if (result != ISC_R_SUCCESS) {
15592                 dns_zone_log(zone, ISC_LOG_ERROR,
15593                              "sign_apex:find_zone_keys -> %s",
15594                              dns_result_totext(result));
15595                 return (result);
15596         }
15597
15598         isc_stdtime_get(&now);
15599         inception = now - 3600; /* Allow for clock skew. */
15600         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
15601
15602         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
15603         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
15604
15605         /*
15606          * See if update_sigs will update DNSKEY signature and if not
15607          * cause them to sign so that so that newly activated keys
15608          * are used.
15609          */
15610         for (tuple = ISC_LIST_HEAD(diff->tuples);
15611              tuple != NULL;
15612              tuple = ISC_LIST_NEXT(tuple, link)) {
15613                 if (tuple->rdata.type == dns_rdatatype_dnskey &&
15614                     dns_name_equal(&tuple->name, &zone->origin))
15615                         break;
15616         }
15617
15618         if (tuple == NULL) {
15619                 result = del_sigs(zone, db, ver, &zone->origin,
15620                                   dns_rdatatype_dnskey, zonediff,
15621                                   zone_keys, nkeys, now, ISC_FALSE);
15622                 if (result != ISC_R_SUCCESS) {
15623                         dns_zone_log(zone, ISC_LOG_ERROR,
15624                                      "sign_apex:del_sigs -> %s",
15625                                      dns_result_totext(result));
15626                         goto failure;
15627                 }
15628                 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
15629                                   zonediff->diff, zone_keys, nkeys, zone->mctx,
15630                                   inception, soaexpire, check_ksk,
15631                                   keyset_kskonly);
15632                 if (result != ISC_R_SUCCESS) {
15633                         dns_zone_log(zone, ISC_LOG_ERROR,
15634                                      "sign_apex:add_sigs -> %s",
15635                                      dns_result_totext(result));
15636                         goto failure;
15637                 }
15638         }
15639
15640         result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
15641                              inception, soaexpire, now, check_ksk,
15642                              keyset_kskonly, zonediff);
15643
15644         if (result != ISC_R_SUCCESS) {
15645                 dns_zone_log(zone, ISC_LOG_ERROR,
15646                              "sign_apex:update_sigs -> %s",
15647                              dns_result_totext(result));
15648                 goto failure;
15649         }
15650
15651  failure:
15652         for (i = 0; i < nkeys; i++)
15653                 dst_key_free(&zone_keys[i]);
15654         return (result);
15655 }
15656
15657 /*
15658  * Prevent the zone entering a inconsistent state where
15659  * NSEC only DNSKEYs are present with NSEC3 chains.
15660  * See update.c:check_dnssec()
15661  */
15662 static isc_boolean_t
15663 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
15664             dns_diff_t *diff)
15665 {
15666         isc_result_t result;
15667         dns_difftuple_t *tuple;
15668         isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
15669         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
15670
15671         /* Scan the tuples for an NSEC-only DNSKEY */
15672         for (tuple = ISC_LIST_HEAD(diff->tuples);
15673              tuple != NULL;
15674              tuple = ISC_LIST_NEXT(tuple, link)) {
15675                 isc_uint8_t alg;
15676                 if (tuple->rdata.type != dns_rdatatype_dnskey ||
15677                     tuple->op != DNS_DIFFOP_ADD)
15678                         continue;
15679
15680                 alg = tuple->rdata.data[3];
15681                 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
15682                     alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
15683                         nseconly = ISC_TRUE;
15684                         break;
15685                 }
15686         }
15687
15688         /* Check existing DB for NSEC-only DNSKEY */
15689         if (!nseconly) {
15690                 result = dns_nsec_nseconly(db, ver, &nseconly);
15691                 if (result == ISC_R_NOTFOUND)
15692                         result = ISC_R_SUCCESS;
15693                 CHECK(result);
15694         }
15695
15696         /* Check existing DB for NSEC3 */
15697         if (!nsec3)
15698                 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
15699                                         privatetype, &nsec3));
15700
15701         /* Refuse to allow NSEC3 with NSEC-only keys */
15702         if (nseconly && nsec3) {
15703                 dns_zone_log(zone, ISC_LOG_ERROR,
15704                            "NSEC only DNSKEYs and NSEC3 chains not allowed");
15705                 goto failure;
15706         }
15707
15708         return (ISC_TRUE);
15709
15710  failure:
15711         return (ISC_FALSE);
15712 }
15713
15714 static isc_result_t
15715 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
15716                  dns_diff_t *diff)
15717 {
15718         isc_result_t result;
15719         dns_dbnode_t *node = NULL;
15720         dns_rdataset_t rdataset;
15721
15722         dns_rdataset_init(&rdataset);
15723         CHECK(dns_db_getoriginnode(db, &node));
15724
15725         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
15726                                      dns_rdatatype_none, 0, &rdataset, NULL);
15727         if (dns_rdataset_isassociated(&rdataset))
15728                 dns_rdataset_disassociate(&rdataset);
15729         if (result != ISC_R_NOTFOUND)
15730                 goto failure;
15731
15732         result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
15733
15734  failure:
15735         if (node != NULL)
15736                 dns_db_detachnode(db, &node);
15737         return (result);
15738 }
15739
15740 /*
15741  * Given an RRSIG rdataset and an algorithm, determine whether there
15742  * are any signatures using that algorithm.
15743  */
15744 static isc_boolean_t
15745 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
15746         dns_rdata_t rdata = DNS_RDATA_INIT;
15747         dns_rdata_rrsig_t rrsig;
15748         isc_result_t result;
15749
15750         REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
15751         if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
15752                 return (ISC_FALSE);
15753         }
15754
15755         for (result = dns_rdataset_first(rdataset);
15756              result == ISC_R_SUCCESS;
15757              result = dns_rdataset_next(rdataset))
15758         {
15759                 dns_rdataset_current(rdataset, &rdata);
15760                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
15761                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15762                 dns_rdata_reset(&rdata);
15763                 if (rrsig.algorithm == alg)
15764                         return (ISC_TRUE);
15765         }
15766
15767         return (ISC_FALSE);
15768 }
15769
15770 static isc_result_t
15771 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
15772            dns_diff_t *diff)
15773 {
15774         dns_name_t *origin;
15775         isc_boolean_t build_nsec3;
15776         isc_result_t result;
15777
15778         origin = dns_db_origin(db);
15779         CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
15780                                  &build_nsec3));
15781         if (build_nsec3)
15782                 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
15783                                            ISC_FALSE, zone->privatetype, diff));
15784         CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
15785
15786  failure:
15787         return (result);
15788 }
15789
15790 static void
15791 zone_rekey(dns_zone_t *zone) {
15792         isc_result_t result;
15793         dns_db_t *db = NULL;
15794         dns_dbnode_t *node = NULL;
15795         dns_dbversion_t *ver = NULL;
15796         dns_rdataset_t soaset, soasigs, keyset, keysigs;
15797         dns_dnsseckeylist_t dnskeys, keys, rmkeys;
15798         dns_dnsseckey_t *key;
15799         dns_diff_t diff, _sig_diff;
15800         zonediff_t zonediff;
15801         isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
15802         isc_boolean_t newalg = ISC_FALSE;
15803         isc_boolean_t fullsign;
15804         dns_ttl_t ttl = 3600;
15805         const char *dir;
15806         isc_mem_t *mctx;
15807         isc_stdtime_t now;
15808         isc_time_t timenow;
15809         isc_interval_t ival;
15810         char timebuf[80];
15811
15812         REQUIRE(DNS_ZONE_VALID(zone));
15813
15814         ISC_LIST_INIT(dnskeys);
15815         ISC_LIST_INIT(keys);
15816         ISC_LIST_INIT(rmkeys);
15817         dns_rdataset_init(&soaset);
15818         dns_rdataset_init(&soasigs);
15819         dns_rdataset_init(&keyset);
15820         dns_rdataset_init(&keysigs);
15821         dir = dns_zone_getkeydirectory(zone);
15822         mctx = zone->mctx;
15823         dns_diff_init(mctx, &diff);
15824         dns_diff_init(mctx, &_sig_diff);
15825         _sig_diff.resign = zone->sigresigninginterval;
15826         zonediff_init(&zonediff, &_sig_diff);
15827
15828         CHECK(dns_zone_getdb(zone, &db));
15829         CHECK(dns_db_newversion(db, &ver));
15830         CHECK(dns_db_getoriginnode(db, &node));
15831
15832         TIME_NOW(&timenow);
15833         now = isc_time_seconds(&timenow);
15834
15835         dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
15836
15837         /* Get the SOA record's TTL */
15838         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
15839                                   dns_rdatatype_none, 0, &soaset, &soasigs));
15840         ttl = soaset.ttl;
15841         dns_rdataset_disassociate(&soaset);
15842
15843         /* Get the DNSKEY rdataset */
15844         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
15845                                      dns_rdatatype_none, 0, &keyset, &keysigs);
15846         if (result == ISC_R_SUCCESS) {
15847                 ttl = keyset.ttl;
15848                 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
15849                                                      mctx, &keyset,
15850                                                      &keysigs, &soasigs,
15851                                                      ISC_FALSE, ISC_FALSE,
15852                                                      &dnskeys));
15853         } else if (result != ISC_R_NOTFOUND)
15854                 goto failure;
15855
15856         /*
15857          * True when called from "rndc sign".  Indicates the zone should be
15858          * fully signed now.
15859          */
15860         fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
15861
15862         result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
15863         if (result == ISC_R_SUCCESS) {
15864                 isc_boolean_t check_ksk;
15865                 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
15866
15867                 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
15868                                                &zone->origin, ttl, &diff,
15869                                                ISC_TF(!check_ksk),
15870                                                mctx, logmsg);
15871
15872                 /* Keys couldn't be updated for some reason;
15873                  * try again later. */
15874                 if (result != ISC_R_SUCCESS) {
15875                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
15876                                      "couldn't update zone keys: %s",
15877                                      isc_result_totext(result));
15878                         goto failure;
15879                 }
15880
15881                 /*
15882                  * See if any pre-existing keys have newly become active;
15883                  * also, see if any new key is for a new algorithm, as in that
15884                  * event, we need to sign the zone fully.  (If there's a new
15885                  * key, but it's for an already-existing algorithm, then
15886                  * the zone signing can be handled incrementally.)
15887                  */
15888                 for (key = ISC_LIST_HEAD(dnskeys);
15889                      key != NULL;
15890                      key = ISC_LIST_NEXT(key, link)) {
15891                         if (!key->first_sign)
15892                                 continue;
15893
15894                         newactive = ISC_TRUE;
15895
15896                         if (!dns_rdataset_isassociated(&keysigs)) {
15897                                 newalg = ISC_TRUE;
15898                                 break;
15899                         }
15900
15901                         if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
15902                                 /*
15903                                  * This isn't a new algorithm; clear
15904                                  * first_sign so we won't sign the
15905                                  * whole zone with this key later
15906                                  */
15907                                 key->first_sign = ISC_FALSE;
15908                         } else {
15909                                 newalg = ISC_TRUE;
15910                                 break;
15911                         }
15912                 }
15913
15914                 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
15915                     dnskey_sane(zone, db, ver, &diff)) {
15916                         CHECK(dns_diff_apply(&diff, db, ver));
15917                         CHECK(clean_nsec3param(zone, db, ver, &diff));
15918                         CHECK(add_signing_records(db, zone->privatetype,
15919                                                   ver, &diff,
15920                                                   ISC_TF(newalg || fullsign)));
15921                         CHECK(update_soa_serial(db, ver, &diff, mctx,
15922                                                 zone->updatemethod));
15923                         CHECK(add_chains(zone, db, ver, &diff));
15924                         CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
15925                         CHECK(zone_journal(zone, zonediff.diff, NULL,
15926                                            "zone_rekey"));
15927                         commit = ISC_TRUE;
15928                 }
15929         }
15930
15931         dns_db_closeversion(db, &ver, ISC_TRUE);
15932
15933         if (commit) {
15934                 dns_difftuple_t *tuple;
15935
15936                 LOCK_ZONE(zone);
15937                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
15938
15939                 zone_needdump(zone, DNS_DUMP_DELAY);
15940
15941                 zone_settimer(zone, &timenow);
15942
15943                 /* Remove any signatures from removed keys.  */
15944                 if (!ISC_LIST_EMPTY(rmkeys)) {
15945                         for (key = ISC_LIST_HEAD(rmkeys);
15946                              key != NULL;
15947                              key = ISC_LIST_NEXT(key, link)) {
15948                                 result = zone_signwithkey(zone,
15949                                                           dst_key_alg(key->key),
15950                                                           dst_key_id(key->key),
15951                                                           ISC_TRUE);
15952                                 if (result != ISC_R_SUCCESS) {
15953                                         dns_zone_log(zone, ISC_LOG_ERROR,
15954                                              "zone_signwithkey failed: %s",
15955                                              dns_result_totext(result));
15956                                 }
15957                         }
15958                 }
15959
15960                 if (fullsign) {
15961                         /*
15962                          * "rndc sign" was called, so we now sign the zone
15963                          * with all active keys, whether they're new or not.
15964                          */
15965                         for (key = ISC_LIST_HEAD(dnskeys);
15966                              key != NULL;
15967                              key = ISC_LIST_NEXT(key, link)) {
15968                                 if (!key->force_sign && !key->hint_sign)
15969                                         continue;
15970
15971                                 result = zone_signwithkey(zone,
15972                                                           dst_key_alg(key->key),
15973                                                           dst_key_id(key->key),
15974                                                           ISC_FALSE);
15975                                 if (result != ISC_R_SUCCESS) {
15976                                         dns_zone_log(zone, ISC_LOG_ERROR,
15977                                              "zone_signwithkey failed: %s",
15978                                              dns_result_totext(result));
15979                                 }
15980                         }
15981                 } else if (newalg) {
15982                         /*
15983                          * We haven't been told to sign fully, but a new
15984                          * algorithm was added to the DNSKEY.  We sign
15985                          * the full zone, but only with newly active
15986                          * keys.
15987                          */
15988                         for (key = ISC_LIST_HEAD(dnskeys);
15989                              key != NULL;
15990                              key = ISC_LIST_NEXT(key, link)) {
15991                                 if (!key->first_sign)
15992                                         continue;
15993
15994                                 result = zone_signwithkey(zone,
15995                                                           dst_key_alg(key->key),
15996                                                           dst_key_id(key->key),
15997                                                           ISC_FALSE);
15998                                 if (result != ISC_R_SUCCESS) {
15999                                         dns_zone_log(zone, ISC_LOG_ERROR,
16000                                              "zone_signwithkey failed: %s",
16001                                              dns_result_totext(result));
16002                                 }
16003                         }
16004                 }
16005
16006                 /*
16007                  * Clear fullsign flag, if it was set, so we don't do
16008                  * another full signing next time
16009                  */
16010                 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
16011
16012                 /*
16013                  * Cause the zone to add/delete NSEC3 chains for the
16014                  * deferred NSEC3PARAM changes.
16015                  */
16016                 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
16017                      tuple != NULL;
16018                      tuple = ISC_LIST_NEXT(tuple, link)) {
16019                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16020                         dns_rdata_t rdata = DNS_RDATA_INIT;
16021                         dns_rdata_nsec3param_t nsec3param;
16022
16023                         if (tuple->rdata.type != zone->privatetype ||
16024                             tuple->op != DNS_DIFFOP_ADD)
16025                                 continue;
16026
16027                         if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
16028                                                         buf, sizeof(buf)))
16029                                 continue;
16030                         result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
16031                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
16032                         if (nsec3param.flags == 0)
16033                                 continue;
16034
16035                         result = zone_addnsec3chain(zone, &nsec3param);
16036                         if (result != ISC_R_SUCCESS) {
16037                                 dns_zone_log(zone, ISC_LOG_ERROR,
16038                                              "zone_addnsec3chain failed: %s",
16039                                              dns_result_totext(result));
16040                         }
16041                 }
16042
16043                 /*
16044                  * Activate any NSEC3 chain updates that may have
16045                  * been scheduled before this rekey.
16046                  */
16047                 if (fullsign || newalg)
16048                         resume_addnsec3chain(zone);
16049
16050                 /*
16051                  * Schedule the next resigning event
16052                  */
16053                 set_resigntime(zone);
16054                 UNLOCK_ZONE(zone);
16055         }
16056
16057         isc_time_settoepoch(&zone->refreshkeytime);
16058
16059         /*
16060          * If we're doing key maintenance, set the key refresh timer to
16061          * the next scheduled key event or to 'dnssec-loadkeys-interval'
16062          * seconds in the future, whichever is sooner.
16063          */
16064         if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
16065                 isc_time_t timethen;
16066                 isc_stdtime_t then;
16067
16068                 LOCK_ZONE(zone);
16069                 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
16070                                   &timethen);
16071                 zone->refreshkeytime = timethen;
16072                 UNLOCK_ZONE(zone);
16073
16074                 for (key = ISC_LIST_HEAD(dnskeys);
16075                      key != NULL;
16076                      key = ISC_LIST_NEXT(key, link)) {
16077                         then = now;
16078                         result = next_keyevent(key->key, &then);
16079                         if (result != ISC_R_SUCCESS)
16080                                 continue;
16081
16082                         DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
16083                         LOCK_ZONE(zone);
16084                         if (isc_time_compare(&timethen,
16085                                              &zone->refreshkeytime) < 0) {
16086                                 zone->refreshkeytime = timethen;
16087                         }
16088                         UNLOCK_ZONE(zone);
16089                 }
16090
16091                 zone_settimer(zone, &timenow);
16092
16093                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
16094                 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
16095         }
16096
16097  done:
16098         dns_diff_clear(&diff);
16099         dns_diff_clear(&_sig_diff);
16100
16101         clear_keylist(&dnskeys, mctx);
16102         clear_keylist(&keys, mctx);
16103         clear_keylist(&rmkeys, mctx);
16104
16105         if (ver != NULL)
16106                 dns_db_closeversion(db, &ver, ISC_FALSE);
16107         if (dns_rdataset_isassociated(&keyset))
16108                 dns_rdataset_disassociate(&keyset);
16109         if (dns_rdataset_isassociated(&keysigs))
16110                 dns_rdataset_disassociate(&keysigs);
16111         if (dns_rdataset_isassociated(&soasigs))
16112                 dns_rdataset_disassociate(&soasigs);
16113         if (node != NULL)
16114                 dns_db_detachnode(db, &node);
16115         if (db != NULL)
16116                 dns_db_detach(&db);
16117         return;
16118
16119  failure:
16120         /*
16121          * Something went wrong; try again in ten minutes or
16122          * after a key refresh interval, whichever is shorter.
16123          */
16124         isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
16125         isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
16126         goto done;
16127 }
16128
16129 void
16130 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
16131         isc_time_t now;
16132
16133         if (zone->type == dns_zone_master && zone->task != NULL) {
16134                 LOCK_ZONE(zone);
16135
16136                 if (fullsign)
16137                         zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
16138
16139                 TIME_NOW(&now);
16140                 zone->refreshkeytime = now;
16141                 zone_settimer(zone, &now);
16142
16143                 UNLOCK_ZONE(zone);
16144         }
16145 }
16146
16147 isc_result_t
16148 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
16149                  unsigned int *errors)
16150 {
16151         isc_result_t result;
16152         dns_dbnode_t *node = NULL;
16153
16154         REQUIRE(DNS_ZONE_VALID(zone));
16155         REQUIRE(errors != NULL);
16156
16157         result = dns_db_getoriginnode(db, &node);
16158         if (result != ISC_R_SUCCESS)
16159                 return (result);
16160         result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
16161                                   ISC_FALSE);
16162         dns_db_detachnode(db, &node);
16163         return (result);
16164 }
16165
16166 void
16167 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
16168         REQUIRE(DNS_ZONE_VALID(zone));
16169         LOCK_ZONE(zone);
16170         zone->added = added;
16171         UNLOCK_ZONE(zone);
16172 }
16173
16174 isc_boolean_t
16175 dns_zone_getadded(dns_zone_t *zone) {
16176         REQUIRE(DNS_ZONE_VALID(zone));
16177         return (zone->added);
16178 }
16179
16180 isc_result_t
16181 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
16182 {
16183         isc_time_t loadtime;
16184         isc_result_t result;
16185
16186         TIME_NOW(&loadtime);
16187
16188         /*
16189          * Lock hierarchy: zmgr, zone, raw.
16190          */
16191         LOCK_ZONE(zone);
16192         if (inline_secure(zone))
16193                 LOCK_ZONE(zone->raw);
16194         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
16195         if (inline_secure(zone))
16196                 UNLOCK_ZONE(zone->raw);
16197         UNLOCK_ZONE(zone);
16198         return result;
16199 }
16200
16201 isc_result_t
16202 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
16203         REQUIRE(DNS_ZONE_VALID(zone));
16204         if (interval == 0)
16205                 return (ISC_R_RANGE);
16206         /* Maximum value: 24 hours (3600 minutes) */
16207         if (interval > (24 * 60))
16208                 interval = (24 * 60);
16209         /* Multiply by 60 for seconds */
16210         zone->refreshkeyinterval = interval * 60;
16211         return (ISC_R_SUCCESS);
16212 }
16213
16214 void
16215 dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) {
16216         REQUIRE(DNS_ZONE_VALID(zone));
16217         zone->requestixfr = flag;
16218 }
16219
16220 isc_boolean_t
16221 dns_zone_getrequestixfr(dns_zone_t *zone) {
16222         REQUIRE(DNS_ZONE_VALID(zone));
16223         return (zone->requestixfr);
16224 }
16225
16226 void
16227 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
16228         REQUIRE(DNS_ZONE_VALID(zone));
16229         zone->updatemethod = method;
16230 }
16231
16232 dns_updatemethod_t
16233 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
16234         REQUIRE(DNS_ZONE_VALID(zone));
16235         return(zone->updatemethod);
16236 }
16237
16238 /*
16239  * Lock hierarchy: zmgr, zone, raw.
16240  */
16241 isc_result_t
16242 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
16243         isc_result_t result;
16244         dns_zonemgr_t *zmgr;
16245
16246         REQUIRE(DNS_ZONE_VALID(zone));
16247         REQUIRE(zone->zmgr != NULL);
16248         REQUIRE(zone->task != NULL);
16249         REQUIRE(zone->loadtask != NULL);
16250         REQUIRE(zone->raw == NULL);
16251
16252         REQUIRE(DNS_ZONE_VALID(raw));
16253         REQUIRE(raw->zmgr == NULL);
16254         REQUIRE(raw->task == NULL);
16255         REQUIRE(raw->loadtask == NULL);
16256         REQUIRE(raw->secure == NULL);
16257
16258         /*
16259          * Lock hierarchy: zmgr, zone, raw.
16260          */
16261         zmgr = zone->zmgr;
16262         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16263         LOCK_ZONE(zone);
16264         LOCK_ZONE(raw);
16265
16266         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
16267                                   NULL, NULL, zone->task, zone_timer, raw,
16268                                   &raw->timer);
16269         if (result != ISC_R_SUCCESS)
16270                 goto unlock;
16271
16272         /*
16273          * The timer "holds" a iref.
16274          */
16275         raw->irefs++;
16276         INSIST(raw->irefs != 0);
16277
16278
16279         /* dns_zone_attach(raw, &zone->raw); */
16280         isc_refcount_increment(&raw->erefs, NULL);
16281         zone->raw = raw;
16282
16283         /* dns_zone_iattach(zone,  &raw->secure); */
16284         zone_iattach(zone, &raw->secure);
16285
16286         isc_task_attach(zone->task, &raw->task);
16287         isc_task_attach(zone->loadtask, &raw->loadtask);
16288
16289         ISC_LIST_APPEND(zmgr->zones, raw, link);
16290         raw->zmgr = zmgr;
16291         zmgr->refs++;
16292
16293  unlock:
16294         UNLOCK_ZONE(raw);
16295         UNLOCK_ZONE(zone);
16296         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16297         return (result);
16298 }
16299
16300 void
16301 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
16302         REQUIRE(DNS_ZONE_VALID(zone));
16303         REQUIRE(raw != NULL && *raw == NULL);
16304
16305         LOCK(&zone->lock);
16306         if (zone->raw != NULL)
16307                 dns_zone_attach(zone->raw, raw);
16308         UNLOCK(&zone->lock);
16309 }
16310
16311 struct keydone {
16312         isc_event_t event;
16313         isc_boolean_t all;
16314         unsigned char data[5];
16315 };
16316
16317 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
16318
16319 static void
16320 keydone(isc_task_t *task, isc_event_t *event) {
16321         const char *me = "keydone";
16322         isc_boolean_t commit = ISC_FALSE;
16323         isc_result_t result;
16324         dns_rdata_t rdata = DNS_RDATA_INIT;
16325         dns_dbversion_t *oldver = NULL, *newver = NULL;
16326         dns_zone_t *zone;
16327         dns_db_t *db = NULL;
16328         dns_dbnode_t *node = NULL;
16329         dns_rdataset_t rdataset;
16330         dns_diff_t diff;
16331         struct keydone *keydone = (struct keydone *)event;
16332         dns_update_log_t log = { update_log_cb, NULL };
16333         isc_boolean_t clear_pending = ISC_FALSE;
16334
16335         UNUSED(task);
16336
16337         zone = event->ev_arg;
16338         INSIST(DNS_ZONE_VALID(zone));
16339
16340         ENTER;
16341
16342         dns_rdataset_init(&rdataset);
16343         dns_diff_init(zone->mctx, &diff);
16344
16345         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16346         if (zone->db != NULL) {
16347                 dns_db_attach(zone->db, &db);
16348                 dns_db_currentversion(db, &oldver);
16349                 result = dns_db_newversion(db, &newver);
16350                 if (result != ISC_R_SUCCESS) {
16351                         dns_zone_log(zone, ISC_LOG_ERROR,
16352                                      "keydone:dns_db_newversion -> %s",
16353                                      dns_result_totext(result));
16354                         goto failure;
16355                 }
16356         }
16357         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16358         if (db == NULL)
16359                 goto failure;
16360
16361         result = dns_db_getoriginnode(db, &node);
16362         if (result != ISC_R_SUCCESS)
16363                 goto failure;
16364
16365         result = dns_db_findrdataset(db, node, newver, zone->privatetype,
16366                                      dns_rdatatype_none, 0, &rdataset, NULL);
16367         if (result == ISC_R_NOTFOUND) {
16368                 INSIST(!dns_rdataset_isassociated(&rdataset));
16369                 goto failure;
16370         }
16371         if (result != ISC_R_SUCCESS) {
16372                 INSIST(!dns_rdataset_isassociated(&rdataset));
16373                 goto failure;
16374         }
16375
16376         for (result = dns_rdataset_first(&rdataset);
16377              result == ISC_R_SUCCESS;
16378              result = dns_rdataset_next(&rdataset)) {
16379                 isc_boolean_t found = ISC_FALSE;
16380
16381                 dns_rdataset_current(&rdataset, &rdata);
16382
16383                 if (keydone->all) {
16384                         if (rdata.length == 5 && rdata.data[0] != 0 &&
16385                                rdata.data[3] == 0 && rdata.data[4] == 1)
16386                                 found = ISC_TRUE;
16387                         else if (rdata.data[0] == 0 &&
16388                                  (rdata.data[2] & PENDINGFLAGS) != 0) {
16389                                 found = ISC_TRUE;
16390                                 clear_pending = ISC_TRUE;
16391                         }
16392                 } else if (rdata.length == 5 &&
16393                            memcmp(rdata.data, keydone->data, 5) == 0)
16394                         found = ISC_TRUE;
16395
16396                 if (found)
16397                         CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
16398                                             &zone->origin, rdataset.ttl,
16399                                             &rdata));
16400                 dns_rdata_reset(&rdata);
16401         }
16402
16403         if (!ISC_LIST_EMPTY(diff.tuples)) {
16404                 /* Write changes to journal file. */
16405                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
16406                                         zone->updatemethod));
16407
16408                 result = dns_update_signatures(&log, zone, db,
16409                                                oldver, newver, &diff,
16410                                                zone->sigvalidityinterval);
16411                 if (!clear_pending)
16412                         CHECK(result);
16413
16414                 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
16415                 commit = ISC_TRUE;
16416
16417                 LOCK_ZONE(zone);
16418                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
16419                 zone_needdump(zone, 30);
16420                 UNLOCK_ZONE(zone);
16421         }
16422
16423  failure:
16424         if (dns_rdataset_isassociated(&rdataset))
16425                 dns_rdataset_disassociate(&rdataset);
16426         if (db != NULL) {
16427                 if (node != NULL)
16428                         dns_db_detachnode(db, &node);
16429                 if (oldver != NULL)
16430                         dns_db_closeversion(db, &oldver, ISC_FALSE);
16431                 if (newver != NULL)
16432                         dns_db_closeversion(db, &newver, commit);
16433                 dns_db_detach(&db);
16434         }
16435         dns_diff_clear(&diff);
16436         isc_event_free(&event);
16437         dns_zone_idetach(&zone);
16438 }
16439
16440 isc_result_t
16441 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
16442         isc_result_t result = ISC_R_SUCCESS;
16443         isc_event_t *e;
16444         isc_buffer_t b;
16445         dns_zone_t *dummy = NULL;
16446         struct keydone *kd;
16447
16448         REQUIRE(DNS_ZONE_VALID(zone));
16449
16450         LOCK_ZONE(zone);
16451
16452         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
16453                                zone, sizeof(struct keydone));
16454         if (e == NULL) {
16455                 result = ISC_R_NOMEMORY;
16456                 goto failure;
16457         }
16458
16459         kd = (struct keydone *) e;
16460         if (strcasecmp(keystr, "all") == 0)
16461                 kd->all = ISC_TRUE;
16462         else {
16463                 isc_textregion_t r;
16464                 char *algstr;
16465                 dns_keytag_t keyid;
16466                 dns_secalg_t alg;
16467                 size_t n;
16468
16469                 kd->all = ISC_FALSE;
16470
16471                 n = sscanf(keystr, "%hd/", &keyid);
16472                 if (n == 0U)
16473                         CHECK(ISC_R_FAILURE);
16474
16475                 algstr = strchr(keystr, '/');
16476                 if (algstr != NULL)
16477                         algstr++;
16478                 else
16479                         CHECK(ISC_R_FAILURE);
16480
16481                 n = sscanf(algstr, "%hhd", &alg);
16482                 if (n == 0U) {
16483                         DE_CONST(algstr, r.base);
16484                         r.length = strlen(algstr);
16485                         CHECK(dns_secalg_fromtext(&alg, &r));
16486                 }
16487
16488                 /* construct a private-type rdata */
16489                 isc_buffer_init(&b, kd->data, sizeof(kd->data));
16490                 isc_buffer_putuint8(&b, alg);
16491                 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
16492                 isc_buffer_putuint8(&b, (keyid & 0xff));
16493                 isc_buffer_putuint8(&b, 0);
16494                 isc_buffer_putuint8(&b, 1);
16495         }
16496
16497         zone_iattach(zone, &dummy);
16498         isc_task_send(zone->task, &e);
16499
16500  failure:
16501         if (e != NULL)
16502                 isc_event_free(&e);
16503         UNLOCK_ZONE(zone);
16504         return (result);
16505 }
16506
16507 struct nsec3param {
16508         isc_event_t event;
16509         unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
16510         unsigned int length;
16511         isc_boolean_t nsec;
16512         isc_boolean_t replace;
16513 };
16514
16515 static void
16516 setnsec3param(isc_task_t *task, isc_event_t *event) {
16517         const char *me = "setnsec3param";
16518         isc_boolean_t commit = ISC_FALSE;
16519         isc_result_t result;
16520         dns_dbversion_t *oldver = NULL, *newver = NULL;
16521         dns_zone_t *zone;
16522         dns_db_t *db = NULL;
16523         dns_dbnode_t *node = NULL;
16524         dns_rdataset_t prdataset, nrdataset;
16525         dns_diff_t diff;
16526         struct nsec3param *np = (struct nsec3param *)event;
16527         dns_update_log_t log = { update_log_cb, NULL };
16528         dns_rdata_t rdata;
16529         isc_boolean_t nseconly;
16530         isc_boolean_t exists = ISC_FALSE;
16531
16532         UNUSED(task);
16533
16534         zone = event->ev_arg;
16535         INSIST(DNS_ZONE_VALID(zone));
16536
16537         ENTER;
16538
16539         dns_rdataset_init(&prdataset);
16540         dns_rdataset_init(&nrdataset);
16541         dns_diff_init(zone->mctx, &diff);
16542
16543         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16544         if (zone->db != NULL) {
16545                 dns_db_attach(zone->db, &db);
16546                 dns_db_currentversion(db, &oldver);
16547                 result = dns_db_newversion(db, &newver);
16548                 if (result != ISC_R_SUCCESS) {
16549                         dns_zone_log(zone, ISC_LOG_ERROR,
16550                                      "setnsec3param:dns_db_newversion -> %s",
16551                                      dns_result_totext(result));
16552                         goto failure;
16553                 }
16554         }
16555         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16556         if (db == NULL)
16557                 goto failure;
16558
16559         CHECK(dns_db_getoriginnode(db, &node));
16560
16561         /*
16562          * Does a private-type record already exist for this chain?
16563          */
16564         result = dns_db_findrdataset(db, node, newver, zone->privatetype,
16565                                      dns_rdatatype_none, 0, &prdataset, NULL);
16566         if (result == ISC_R_SUCCESS) {
16567                 for (result = dns_rdataset_first(&prdataset);
16568                      result == ISC_R_SUCCESS;
16569                      result = dns_rdataset_next(&prdataset)) {
16570                         dns_rdata_init(&rdata);
16571                         dns_rdataset_current(&prdataset, &rdata);
16572
16573                         if (np->length == rdata.length &&
16574                             memcmp(rdata.data, np->data, np->length) == 0) {
16575                                 exists = ISC_TRUE;
16576                                 break;
16577                         }
16578                 }
16579         } else if (result != ISC_R_NOTFOUND) {
16580                 INSIST(!dns_rdataset_isassociated(&prdataset));
16581                 goto failure;
16582         }
16583
16584         /*
16585          * Does the chain already exist?
16586          */
16587         result = dns_db_findrdataset(db, node, newver,
16588                                      dns_rdatatype_nsec3param,
16589                                      dns_rdatatype_none, 0, &nrdataset, NULL);
16590         if (result == ISC_R_SUCCESS) {
16591                 for (result = dns_rdataset_first(&nrdataset);
16592                      result == ISC_R_SUCCESS;
16593                      result = dns_rdataset_next(&nrdataset)) {
16594                         dns_rdata_init(&rdata);
16595                         dns_rdataset_current(&nrdataset, &rdata);
16596
16597                         if (np->length == (rdata.length + 1) &&
16598                             memcmp(rdata.data, np->data + 1,
16599                                    np->length - 1) == 0)
16600                         {
16601                                 exists = ISC_TRUE;
16602                                 break;
16603                         }
16604                 }
16605         } else if (result != ISC_R_NOTFOUND) {
16606                 INSIST(!dns_rdataset_isassociated(&nrdataset));
16607                 goto failure;
16608         }
16609
16610
16611         /*
16612          * We need to remove any existing NSEC3 chains.
16613          */
16614         if (!exists && np->replace && (np->length != 0 || np->nsec))
16615                 CHECK(dns_nsec3param_deletechains(db, newver, zone,
16616                                                   !np->nsec, &diff));
16617
16618         if (!exists && np->length != 0) {
16619                 /*
16620                  * We're creating an NSEC3 chain.
16621                  *
16622                  * If the zone is not currently capable of supporting
16623                  * an NSEC3 chain, add the INITIAL flag, so these
16624                  * parameters can be used later when NSEC3 becomes
16625                  * available.
16626                  */
16627                 dns_rdata_init(&rdata);
16628
16629                 np->data[2] |= DNS_NSEC3FLAG_CREATE;
16630                 result = dns_nsec_nseconly(db, newver, &nseconly);
16631                 if (result == ISC_R_NOTFOUND || nseconly)
16632                         np->data[2] |= DNS_NSEC3FLAG_INITIAL;
16633
16634                 rdata.length = np->length;
16635                 rdata.data = np->data;
16636                 rdata.type = zone->privatetype;
16637                 rdata.rdclass = zone->rdclass;
16638                 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
16639                                     &zone->origin, 0, &rdata));
16640         }
16641
16642         if (!ISC_LIST_EMPTY(diff.tuples)) {
16643                 /* Write changes to journal file. */
16644                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
16645                                         zone->updatemethod));
16646                 result = dns_update_signatures(&log, zone, db,
16647                                                oldver, newver, &diff,
16648                                                zone->sigvalidityinterval);
16649                 if (result != ISC_R_NOTFOUND)
16650                         CHECK(result);
16651                 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
16652                 commit = ISC_TRUE;
16653
16654                 LOCK_ZONE(zone);
16655                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
16656                 zone_needdump(zone, 30);
16657                 UNLOCK_ZONE(zone);
16658         }
16659
16660  failure:
16661         if (dns_rdataset_isassociated(&prdataset))
16662                 dns_rdataset_disassociate(&prdataset);
16663         if (dns_rdataset_isassociated(&nrdataset))
16664                 dns_rdataset_disassociate(&nrdataset);
16665         if (node != NULL)
16666                 dns_db_detachnode(db, &node);
16667         if (oldver != NULL)
16668                 dns_db_closeversion(db, &oldver, ISC_FALSE);
16669         if (newver != NULL)
16670                 dns_db_closeversion(db, &newver, commit);
16671         if (db != NULL)
16672                 dns_db_detach(&db);
16673         if (commit)
16674                 resume_addnsec3chain(zone);
16675         dns_diff_clear(&diff);
16676         isc_event_free(&event);
16677         dns_zone_idetach(&zone);
16678 }
16679
16680 isc_result_t
16681 dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
16682                        isc_uint16_t iter, isc_uint8_t saltlen,
16683                        unsigned char *salt, isc_boolean_t replace)
16684 {
16685         isc_result_t result = ISC_R_SUCCESS;
16686         dns_rdata_nsec3param_t param;
16687         dns_rdata_t nrdata = DNS_RDATA_INIT;
16688         dns_rdata_t prdata = DNS_RDATA_INIT;
16689         unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
16690         struct nsec3param *np;
16691         dns_zone_t *dummy = NULL;
16692         isc_buffer_t b;
16693         isc_event_t *e;
16694
16695         REQUIRE(DNS_ZONE_VALID(zone));
16696         REQUIRE(salt != NULL);
16697
16698         LOCK_ZONE(zone);
16699
16700         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
16701                                setnsec3param, zone, sizeof(struct nsec3param));
16702         if (e == NULL) {
16703                 result = ISC_R_NOMEMORY;
16704                 goto failure;
16705         }
16706
16707         np = (struct nsec3param *) e;
16708         np->replace = replace;
16709         if (hash == 0) {
16710                 np->length = 0;
16711                 np->nsec = ISC_TRUE;
16712         } else {
16713                 param.common.rdclass = zone->rdclass;
16714                 param.common.rdtype = dns_rdatatype_nsec3param;
16715                 ISC_LINK_INIT(&param.common, link);
16716                 param.mctx = NULL;
16717                 param.hash = hash;
16718                 param.flags = flags;
16719                 param.iterations = iter;
16720                 param.salt_length = saltlen;
16721                 param.salt = salt;
16722                 isc_buffer_init(&b, nbuf, sizeof(nbuf));
16723                 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
16724                                            dns_rdatatype_nsec3param,
16725                                            &param, &b));
16726                 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
16727                                          np->data, sizeof(np->data));
16728                 np->length = prdata.length;
16729         }
16730
16731         zone_iattach(zone, &dummy);
16732         isc_task_send(zone->task, &e);
16733
16734  failure:
16735         if (e != NULL)
16736                 isc_event_free(&e);
16737         UNLOCK_ZONE(zone);
16738         return (result);
16739 }
16740
16741 void
16742 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
16743         REQUIRE(DNS_ZONE_VALID(zone));
16744
16745         zone->statlevel = level;
16746 }
16747
16748 dns_zonestat_level_t
16749 dns_zone_getstatlevel(dns_zone_t *zone) {
16750         REQUIRE(DNS_ZONE_VALID(zone));
16751
16752         return (zone->statlevel);
16753 }