]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/lib/dns/zone.c
Update BIND to 9.9.8
[FreeBSD/stable/9.git] / contrib / bind9 / lib / dns / zone.c
1 /*
2  * Copyright (C) 2004-2015  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 /*! \file */
19
20 #include <config.h>
21 #include <errno.h>
22
23 #include <isc/file.h>
24 #include <isc/hex.h>
25 #include <isc/mutex.h>
26 #include <isc/pool.h>
27 #include <isc/print.h>
28 #include <isc/random.h>
29 #include <isc/ratelimiter.h>
30 #include <isc/refcount.h>
31 #include <isc/rwlock.h>
32 #include <isc/serial.h>
33 #include <isc/stats.h>
34 #include <isc/stdtime.h>
35 #include <isc/strerror.h>
36 #include <isc/string.h>
37 #include <isc/taskpool.h>
38 #include <isc/thread.h>
39 #include <isc/timer.h>
40 #include <isc/util.h>
41
42 #include <dns/acache.h>
43 #include <dns/acl.h>
44 #include <dns/adb.h>
45 #include <dns/callbacks.h>
46 #include <dns/db.h>
47 #include <dns/dbiterator.h>
48 #include <dns/dnssec.h>
49 #include <dns/ds.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 #define TRYLOCK_ZONE(result, z) \
166         do { \
167               result = isc_mutex_trylock(&(z)->lock); \
168               if (result == ISC_R_SUCCESS) {  \
169                      INSIST((z)->locked == ISC_FALSE); \
170                      (z)->locked = ISC_TRUE; \
171               } \
172         } while (0)
173 #else
174 #define LOCK_ZONE(z) LOCK(&(z)->lock)
175 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
176 #define LOCKED_ZONE(z) ISC_TRUE
177 #define TRYLOCK_ZONE(result, z) \
178         do { result = isc_mutex_trylock(&(z)->lock); } while (0)
179 #endif
180
181 #ifdef ISC_RWLOCK_USEATOMIC
182 #define ZONEDB_INITLOCK(l)      isc_rwlock_init((l), 0, 0)
183 #define ZONEDB_DESTROYLOCK(l)   isc_rwlock_destroy(l)
184 #define ZONEDB_LOCK(l, t)       RWLOCK((l), (t))
185 #define ZONEDB_UNLOCK(l, t)     RWUNLOCK((l), (t))
186 #else
187 #define ZONEDB_INITLOCK(l)      isc_mutex_init(l)
188 #define ZONEDB_DESTROYLOCK(l)   DESTROYLOCK(l)
189 #define ZONEDB_LOCK(l, t)       LOCK(l)
190 #define ZONEDB_UNLOCK(l, t)     UNLOCK(l)
191 #endif
192
193 struct dns_zone {
194         /* Unlocked */
195         unsigned int            magic;
196         isc_mutex_t             lock;
197 #ifdef DNS_ZONE_CHECKLOCK
198         isc_boolean_t           locked;
199 #endif
200         isc_mem_t               *mctx;
201         isc_refcount_t          erefs;
202
203 #ifdef ISC_RWLOCK_USEATOMIC
204         isc_rwlock_t            dblock;
205 #else
206         isc_mutex_t             dblock;
207 #endif
208         dns_db_t                *db;            /* Locked by dblock */
209
210         /* Locked */
211         dns_zonemgr_t           *zmgr;
212         ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
213         isc_timer_t             *timer;
214         unsigned int            irefs;
215         dns_name_t              origin;
216         char                    *masterfile;
217         dns_masterformat_t      masterformat;
218         char                    *journal;
219         isc_int32_t             journalsize;
220         dns_rdataclass_t        rdclass;
221         dns_zonetype_t          type;
222         unsigned int            flags;
223         unsigned int            options;
224         unsigned int            db_argc;
225         char                    **db_argv;
226         isc_time_t              expiretime;
227         isc_time_t              refreshtime;
228         isc_time_t              dumptime;
229         isc_time_t              loadtime;
230         isc_time_t              notifytime;
231         isc_time_t              resigntime;
232         isc_time_t              keywarntime;
233         isc_time_t              signingtime;
234         isc_time_t              nsec3chaintime;
235         isc_time_t              refreshkeytime;
236         isc_uint32_t            refreshkeyinterval;
237         isc_uint32_t            refreshkeycount;
238         isc_uint32_t            refresh;
239         isc_uint32_t            retry;
240         isc_uint32_t            expire;
241         isc_uint32_t            minimum;
242         isc_stdtime_t           key_expiry;
243         isc_stdtime_t           log_key_expired_timer;
244         char                    *keydirectory;
245
246         isc_uint32_t            maxrefresh;
247         isc_uint32_t            minrefresh;
248         isc_uint32_t            maxretry;
249         isc_uint32_t            minretry;
250
251         isc_sockaddr_t          *masters;
252         dns_name_t              **masterkeynames;
253         isc_boolean_t           *mastersok;
254         unsigned int            masterscnt;
255         unsigned int            curmaster;
256         isc_sockaddr_t          masteraddr;
257         dns_notifytype_t        notifytype;
258         isc_sockaddr_t          *notify;
259         dns_name_t              **notifykeynames;
260         unsigned int            notifycnt;
261         isc_sockaddr_t          notifyfrom;
262         isc_task_t              *task;
263         isc_task_t              *loadtask;
264         isc_sockaddr_t          notifysrc4;
265         isc_sockaddr_t          notifysrc6;
266         isc_sockaddr_t          xfrsource4;
267         isc_sockaddr_t          xfrsource6;
268         isc_sockaddr_t          altxfrsource4;
269         isc_sockaddr_t          altxfrsource6;
270         isc_sockaddr_t          sourceaddr;
271         dns_xfrin_ctx_t         *xfr;           /* task locked */
272         dns_tsigkey_t           *tsigkey;       /* key used for xfr */
273         /* Access Control Lists */
274         dns_acl_t               *update_acl;
275         dns_acl_t               *forward_acl;
276         dns_acl_t               *notify_acl;
277         dns_acl_t               *query_acl;
278         dns_acl_t               *queryon_acl;
279         dns_acl_t               *xfr_acl;
280         isc_boolean_t           update_disabled;
281         isc_boolean_t           zero_no_soa_ttl;
282         dns_severity_t          check_names;
283         ISC_LIST(dns_notify_t)  notifies;
284         dns_request_t           *request;
285         dns_loadctx_t           *lctx;
286         dns_io_t                *readio;
287         dns_dumpctx_t           *dctx;
288         dns_io_t                *writeio;
289         isc_uint32_t            maxxfrin;
290         isc_uint32_t            maxxfrout;
291         isc_uint32_t            idlein;
292         isc_uint32_t            idleout;
293         isc_event_t             ctlevent;
294         dns_ssutable_t          *ssutable;
295         isc_uint32_t            sigvalidityinterval;
296         isc_uint32_t            sigresigninginterval;
297         dns_view_t              *view;
298         dns_acache_t            *acache;
299         dns_checkmxfunc_t       checkmx;
300         dns_checksrvfunc_t      checksrv;
301         dns_checknsfunc_t       checkns;
302         /*%
303          * Zones in certain states such as "waiting for zone transfer"
304          * or "zone transfer in progress" are kept on per-state linked lists
305          * in the zone manager using the 'statelink' field.  The 'statelist'
306          * field points at the list the zone is currently on.  It the zone
307          * is not on any such list, statelist is NULL.
308          */
309         ISC_LINK(dns_zone_t)    statelink;
310         dns_zonelist_t          *statelist;
311         /*%
312          * Statistics counters about zone management.
313          */
314         isc_stats_t             *stats;
315         /*%
316          * Optional per-zone statistics counters.  Counted outside of this
317          * module.
318          */
319         dns_zonestat_level_t    statlevel;
320         isc_boolean_t           requeststats_on;
321         isc_stats_t             *requeststats;
322         dns_stats_t             *rcvquerystats;
323         isc_uint32_t            notifydelay;
324         dns_isselffunc_t        isself;
325         void                    *isselfarg;
326
327         char *                  strnamerd;
328         char *                  strname;
329         char *                  strrdclass;
330         char *                  strviewname;
331
332         /*%
333          * Serial number for deferred journal compaction.
334          */
335         isc_uint32_t            compact_serial;
336         /*%
337          * Keys that are signing the zone for the first time.
338          */
339         dns_signinglist_t       signing;
340         dns_nsec3chainlist_t    nsec3chain;
341         /*%
342          * Signing / re-signing quantum stopping parameters.
343          */
344         isc_uint32_t            signatures;
345         isc_uint32_t            nodes;
346         dns_rdatatype_t         privatetype;
347
348         /*%
349          * Autosigning/key-maintenance options
350          */
351         isc_uint32_t            keyopts;
352
353         /*%
354          * True if added by "rndc addzone"
355          */
356         isc_boolean_t           added;
357
358         /*%
359          * whether this is a response policy zone
360          */
361         isc_boolean_t           is_rpz;
362
363         /*%
364          * Serial number update method.
365          */
366         dns_updatemethod_t      updatemethod;
367
368         /*%
369          * whether ixfr is requested
370          */
371         isc_boolean_t           requestixfr;
372
373         /*%
374          * Outstanding forwarded UPDATE requests.
375          */
376         dns_forwardlist_t       forwards;
377
378         dns_zone_t              *raw;
379         dns_zone_t              *secure;
380
381         isc_boolean_t           sourceserialset;
382         isc_uint32_t            sourceserial;
383
384         /*%
385          * maximum zone ttl
386          */
387         dns_ttl_t               maxttl;
388
389         /*
390          * Inline zone signing state.
391          */
392         dns_diff_t              rss_diff;
393         isc_eventlist_t         rss_events;
394         dns_dbversion_t         *rss_newver;
395         dns_dbversion_t         *rss_oldver;
396         dns_db_t                *rss_db;
397         dns_zone_t              *rss_raw;
398         isc_event_t             *rss_event;
399         dns_update_state_t      *rss_state;
400 };
401
402 typedef struct {
403         dns_diff_t      *diff;
404         isc_boolean_t   offline;
405 } zonediff_t;
406
407 #define zonediff_init(z, d) \
408         do { \
409                 zonediff_t *_z = (z); \
410                 (_z)->diff = (d); \
411                 (_z)->offline = ISC_FALSE; \
412         } while (0)
413
414 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
415 #define DNS_ZONE_SETFLAG(z,f) do { \
416                 INSIST(LOCKED_ZONE(z)); \
417                 (z)->flags |= (f); \
418                 } while (0)
419 #define DNS_ZONE_CLRFLAG(z,f) do { \
420                 INSIST(LOCKED_ZONE(z)); \
421                 (z)->flags &= ~(f); \
422                 } while (0)
423         /* XXX MPA these may need to go back into zone.h */
424 #define DNS_ZONEFLG_REFRESH     0x00000001U     /*%< refresh check in progress */
425 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /*%< zone need consolidation */
426 #define DNS_ZONEFLG_USEVC       0x00000004U     /*%< use tcp for refresh query */
427 #define DNS_ZONEFLG_DUMPING     0x00000008U     /*%< a dump is in progress */
428 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /*%< $INCLUDE in zone file */
429 #define DNS_ZONEFLG_LOADED      0x00000020U     /*%< database has loaded */
430 #define DNS_ZONEFLG_EXITING     0x00000040U     /*%< zone is being destroyed */
431 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /*%< zone has expired */
432 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /*%< refresh check needed */
433 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /*%< zone contents are
434                                                  * uptodate */
435 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /*%< need to send out notify
436                                                  * messages */
437 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /*%< generate a journal diff on
438                                                  * reload */
439 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /*%< an attempt to refresh a
440                                                  * zone with no masters
441                                                  * occurred */
442 #define DNS_ZONEFLG_LOADING     0x00002000U     /*%< load from disk in progress*/
443 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /*%< timer values have been set
444                                                  * from SOA (if not set, we
445                                                  * are still using
446                                                  * default timer values) */
447 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
448 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
449 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
450 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
451 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
452 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /*%< IXFR failed, force AXFR */
453 #define DNS_ZONEFLG_FLUSH       0x00200000U
454 #define DNS_ZONEFLG_NOEDNS      0x00400000U
455 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
456 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
457 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
458 #define DNS_ZONEFLG_REFRESHING  0x04000000U     /*%< Refreshing keydata */
459 #define DNS_ZONEFLG_THAW        0x08000000U
460 #define DNS_ZONEFLG_LOADPENDING 0x10000000U     /*%< Loading scheduled */
461 #define DNS_ZONEFLG_NODELAY     0x20000000U
462 #define DNS_ZONEFLG_SENDSECURE  0x40000000U
463 #define DNS_ZONEFLG_NEEDSTARTUPNOTIFY 0x80000000U /*%< need to send out notify
464                                                    *   due to the zone just
465                                                    *   being loaded for the
466                                                    *   first time.  */
467
468 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
469 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
470
471 /* Flags for zone_load() */
472 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
473 #define DNS_ZONELOADFLAG_THAW   0x00000002U     /* Thaw the zone on successful
474                                                    load. */
475
476 #define UNREACH_CHACHE_SIZE     10U
477 #define UNREACH_HOLD_TIME       600     /* 10 minutes */
478
479 #define CHECK(op) \
480         do { result = (op); \
481                 if (result != ISC_R_SUCCESS) goto failure; \
482         } while (0)
483
484 struct dns_unreachable {
485         isc_sockaddr_t  remote;
486         isc_sockaddr_t  local;
487         isc_uint32_t    expire;
488         isc_uint32_t    last;
489         isc_uint32_t    count;
490 };
491
492 struct dns_zonemgr {
493         unsigned int            magic;
494         isc_mem_t *             mctx;
495         int                     refs;           /* Locked by rwlock */
496         isc_taskmgr_t *         taskmgr;
497         isc_timermgr_t *        timermgr;
498         isc_socketmgr_t *       socketmgr;
499         isc_taskpool_t *        zonetasks;
500         isc_taskpool_t *        loadtasks;
501         isc_task_t *            task;
502         isc_pool_t *            mctxpool;
503         isc_ratelimiter_t *     notifyrl;
504         isc_ratelimiter_t *     refreshrl;
505         isc_ratelimiter_t *     startupnotifyrl;
506         isc_ratelimiter_t *     startuprefreshrl;
507         isc_rwlock_t            rwlock;
508         isc_mutex_t             iolock;
509         isc_rwlock_t            urlock;
510
511         /* Locked by rwlock. */
512         dns_zonelist_t          zones;
513         dns_zonelist_t          waiting_for_xfrin;
514         dns_zonelist_t          xfrin_in_progress;
515
516         /* Configuration data. */
517         isc_uint32_t            transfersin;
518         isc_uint32_t            transfersperns;
519         unsigned int            notifyrate;
520         unsigned int            startupnotifyrate;
521         unsigned int            serialqueryrate;
522         unsigned int            startupserialqueryrate;
523
524         /* Locked by iolock */
525         isc_uint32_t            iolimit;
526         isc_uint32_t            ioactive;
527         dns_iolist_t            high;
528         dns_iolist_t            low;
529
530         /* Locked by urlock. */
531         /* LRU cache */
532         struct dns_unreachable  unreachable[UNREACH_CHACHE_SIZE];
533 };
534
535 /*%
536  * Hold notify state.
537  */
538 struct dns_notify {
539         unsigned int            magic;
540         unsigned int            flags;
541         isc_mem_t               *mctx;
542         dns_zone_t              *zone;
543         dns_adbfind_t           *find;
544         dns_request_t           *request;
545         dns_name_t              ns;
546         isc_sockaddr_t          dst;
547         dns_tsigkey_t           *key;
548         ISC_LINK(dns_notify_t)  link;
549         isc_event_t             *event;
550 };
551
552 #define DNS_NOTIFY_NOSOA        0x0001U
553 #define DNS_NOTIFY_STARTUP      0x0002U
554
555 /*%
556  *      dns_stub holds state while performing a 'stub' transfer.
557  *      'db' is the zone's 'db' or a new one if this is the initial
558  *      transfer.
559  */
560
561 struct dns_stub {
562         unsigned int            magic;
563         isc_mem_t               *mctx;
564         dns_zone_t              *zone;
565         dns_db_t                *db;
566         dns_dbversion_t         *version;
567 };
568
569 /*%
570  *      Hold load state.
571  */
572 struct dns_load {
573         unsigned int            magic;
574         isc_mem_t               *mctx;
575         dns_zone_t              *zone;
576         dns_db_t                *db;
577         isc_time_t              loadtime;
578         dns_rdatacallbacks_t    callbacks;
579 };
580
581 /*%
582  *      Hold forward state.
583  */
584 struct dns_forward {
585         unsigned int            magic;
586         isc_mem_t               *mctx;
587         dns_zone_t              *zone;
588         isc_buffer_t            *msgbuf;
589         dns_request_t           *request;
590         isc_uint32_t            which;
591         isc_sockaddr_t          addr;
592         dns_updatecallback_t    callback;
593         void                    *callback_arg;
594         unsigned int            options;
595         ISC_LINK(dns_forward_t) link;
596 };
597
598 /*%
599  *      Hold IO request state.
600  */
601 struct dns_io {
602         unsigned int    magic;
603         dns_zonemgr_t   *zmgr;
604         isc_boolean_t   high;
605         isc_task_t      *task;
606         ISC_LINK(dns_io_t) link;
607         isc_event_t     *event;
608 };
609
610 /*%
611  *      Hold state for when we are signing a zone with a new
612  *      DNSKEY as result of an update.
613  */
614 struct dns_signing {
615         unsigned int            magic;
616         dns_db_t                *db;
617         dns_dbiterator_t        *dbiterator;
618         dns_secalg_t            algorithm;
619         isc_uint16_t            keyid;
620         isc_boolean_t           delete;
621         isc_boolean_t           done;
622         ISC_LINK(dns_signing_t) link;
623 };
624
625 struct dns_nsec3chain {
626         unsigned int                    magic;
627         dns_db_t                        *db;
628         dns_dbiterator_t                *dbiterator;
629         dns_rdata_nsec3param_t          nsec3param;
630         unsigned char                   salt[255];
631         isc_boolean_t                   done;
632         isc_boolean_t                   seen_nsec;
633         isc_boolean_t                   delete_nsec;
634         isc_boolean_t                   save_delete_nsec;
635         ISC_LINK(dns_nsec3chain_t)      link;
636 };
637 /*%<
638  * 'dbiterator' contains a iterator for the database.  If we are creating
639  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
640  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
641  * iterated.
642  *
643  * 'nsec3param' contains the parameters of the NSEC3 chain being created
644  * or removed.
645  *
646  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
647  *
648  * 'seen_nsec' will be set to true if, while iterating the zone to create a
649  * NSEC3 chain, a NSEC record is seen.
650  *
651  * 'delete_nsec' will be set to true if, at the completion of the creation
652  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
653  * are in the process of deleting the NSEC chain.
654  *
655  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
656  * so it can be recovered in the event of a error.
657  */
658
659 struct dns_keyfetch {
660         dns_fixedname_t name;
661         dns_rdataset_t keydataset;
662         dns_rdataset_t dnskeyset;
663         dns_rdataset_t dnskeysigset;
664         dns_zone_t *zone;
665         dns_db_t *db;
666         dns_fetch_t *fetch;
667 };
668
669 /*%
670  * Hold state for an asynchronous load
671  */
672 struct dns_asyncload {
673         dns_zone_t *zone;
674         dns_zt_zoneloaded_t loaded;
675         void *loaded_arg;
676 };
677
678 #define HOUR 3600
679 #define DAY (24*HOUR)
680 #define MONTH (30*DAY)
681
682 /*
683  * These can be overridden by the -T mkeytimers option on the command
684  * line, so that we can test with shorter periods than specified in
685  * RFC 5011.
686  */
687 unsigned int dns_zone_mkey_hour = HOUR;
688 unsigned int dns_zone_mkey_day = DAY;
689 unsigned int dns_zone_mkey_month = MONTH;
690
691 #define SEND_BUFFER_SIZE 2048
692
693 static void zone_settimer(dns_zone_t *, isc_time_t *);
694 static void cancel_refresh(dns_zone_t *);
695 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
696                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
697 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
698      ISC_FORMAT_PRINTF(3, 4);
699 static void queue_xfrin(dns_zone_t *zone);
700 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
701                                   dns_diff_t *diff, dns_diffop_t op,
702                                   dns_name_t *name, dns_ttl_t ttl,
703                                   dns_rdata_t *rdata);
704 static void zone_unload(dns_zone_t *zone);
705 static void zone_expire(dns_zone_t *zone);
706 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
707 static void zone_idetach(dns_zone_t **zonep);
708 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
709                                    isc_boolean_t dump);
710 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
711 static inline void zone_detachdb(dns_zone_t *zone);
712 static isc_result_t default_journal(dns_zone_t *zone);
713 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
714 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
715                                   isc_time_t loadtime, isc_result_t result);
716 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
717 static void zone_shutdown(isc_task_t *, isc_event_t *);
718 static void zone_loaddone(void *arg, isc_result_t result);
719 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
720                                    isc_time_t loadtime);
721 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
722 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
723 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
724 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
725 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
726                                            isc_uint32_t serial);
727
728 #if 0
729 /* ondestroy example */
730 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
731 #endif
732
733 static void refresh_callback(isc_task_t *, isc_event_t *);
734 static void stub_callback(isc_task_t *, isc_event_t *);
735 static void queue_soa_query(dns_zone_t *zone);
736 static void soa_query(isc_task_t *, isc_event_t *);
737 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
738                      dns_stub_t *stub);
739 static int message_count(dns_message_t *msg, dns_section_t section,
740                          dns_rdatatype_t type);
741 static void notify_cancel(dns_zone_t *zone);
742 static void notify_find_address(dns_notify_t *notify);
743 static void notify_send(dns_notify_t *notify);
744 static isc_result_t notify_createmessage(dns_zone_t *zone,
745                                          unsigned int flags,
746                                          dns_message_t **messagep);
747 static void notify_done(isc_task_t *task, isc_event_t *event);
748 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
749 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
750 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
751 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
752                                              dns_zone_t *zone);
753 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
754 static void zonemgr_free(dns_zonemgr_t *zmgr);
755 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
756                                   isc_task_t *task, isc_taskaction_t action,
757                                   void *arg, dns_io_t **iop);
758 static void zonemgr_putio(dns_io_t **iop);
759 static void zonemgr_cancelio(dns_io_t *io);
760
761 static isc_result_t
762 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
763                  unsigned int *soacount, isc_uint32_t *serial,
764                  isc_uint32_t *refresh, isc_uint32_t *retry,
765                  isc_uint32_t *expire, isc_uint32_t *minimum,
766                  unsigned int *errors);
767
768 static void zone_freedbargs(dns_zone_t *zone);
769 static void forward_callback(isc_task_t *task, isc_event_t *event);
770 static void zone_saveunique(dns_zone_t *zone, const char *path,
771                             const char *templat);
772 static void zone_maintenance(dns_zone_t *zone);
773 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
774 static void dump_done(void *arg, isc_result_t result);
775 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
776                                      isc_uint16_t keyid, isc_boolean_t delete);
777 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
778                                 dns_dbnode_t *node, dns_name_t *name,
779                                 dns_diff_t *diff);
780 static void zone_rekey(dns_zone_t *zone);
781 static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
782 static void setrl(isc_ratelimiter_t *rl, unsigned int *rate,
783                   unsigned int value);
784
785 #define ENTER zone_debuglog(zone, me, 1, "enter")
786
787 static const unsigned int dbargc_default = 1;
788 static const char *dbargv_default[] = { "rbt" };
789
790 #define DNS_ZONE_JITTER_ADD(a, b, c) \
791         do { \
792                 isc_interval_t _i; \
793                 isc_uint32_t _j; \
794                 _j = isc_random_jitter((b), (b)/4); \
795                 isc_interval_set(&_i, _j, 0); \
796                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
797                         dns_zone_log(zone, ISC_LOG_WARNING, \
798                                      "epoch approaching: upgrade required: " \
799                                      "now + %s failed", #b); \
800                         isc_interval_set(&_i, _j/2, 0); \
801                         (void)isc_time_add((a), &_i, (c)); \
802                 } \
803         } while (0)
804
805 #define DNS_ZONE_TIME_ADD(a, b, c) \
806         do { \
807                 isc_interval_t _i; \
808                 isc_interval_set(&_i, (b), 0); \
809                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
810                         dns_zone_log(zone, ISC_LOG_WARNING, \
811                                      "epoch approaching: upgrade required: " \
812                                      "now + %s failed", #b); \
813                         isc_interval_set(&_i, (b)/2, 0); \
814                         (void)isc_time_add((a), &_i, (c)); \
815                 } \
816         } while (0)
817
818 typedef struct nsec3param nsec3param_t;
819 struct nsec3param {
820         unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
821         unsigned int length;
822         isc_boolean_t nsec;
823         isc_boolean_t replace;
824         ISC_LINK(nsec3param_t)  link;
825 };
826 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
827 struct np3event {
828         isc_event_t event;
829         nsec3param_t params;
830 };
831
832 /*%
833  * Increment resolver-related statistics counters.  Zone must be locked.
834  */
835 static inline void
836 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
837         if (zone->stats != NULL)
838                 isc_stats_increment(zone->stats, counter);
839 }
840
841 /***
842  ***    Public functions.
843  ***/
844
845 isc_result_t
846 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
847         isc_result_t result;
848         dns_zone_t *zone;
849         isc_time_t now;
850
851         REQUIRE(zonep != NULL && *zonep == NULL);
852         REQUIRE(mctx != NULL);
853
854         TIME_NOW(&now);
855         zone = isc_mem_get(mctx, sizeof(*zone));
856         if (zone == NULL)
857                 return (ISC_R_NOMEMORY);
858
859         zone->mctx = NULL;
860         isc_mem_attach(mctx, &zone->mctx);
861
862         result = isc_mutex_init(&zone->lock);
863         if (result != ISC_R_SUCCESS)
864                 goto free_zone;
865
866         result = ZONEDB_INITLOCK(&zone->dblock);
867         if (result != ISC_R_SUCCESS)
868                 goto free_mutex;
869
870         /* XXX MPA check that all elements are initialised */
871 #ifdef DNS_ZONE_CHECKLOCK
872         zone->locked = ISC_FALSE;
873 #endif
874         zone->db = NULL;
875         zone->zmgr = NULL;
876         ISC_LINK_INIT(zone, link);
877         result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
878         if (result != ISC_R_SUCCESS)
879                 goto free_dblock;
880         zone->irefs = 0;
881         dns_name_init(&zone->origin, NULL);
882         zone->strnamerd = NULL;
883         zone->strname = NULL;
884         zone->strrdclass = NULL;
885         zone->strviewname = NULL;
886         zone->masterfile = NULL;
887         zone->masterformat = dns_masterformat_none;
888         zone->keydirectory = NULL;
889         zone->journalsize = -1;
890         zone->journal = NULL;
891         zone->rdclass = dns_rdataclass_none;
892         zone->type = dns_zone_none;
893         zone->flags = 0;
894         zone->options = 0;
895         zone->keyopts = 0;
896         zone->db_argc = 0;
897         zone->db_argv = NULL;
898         isc_time_settoepoch(&zone->expiretime);
899         isc_time_settoepoch(&zone->refreshtime);
900         isc_time_settoepoch(&zone->dumptime);
901         isc_time_settoepoch(&zone->loadtime);
902         zone->notifytime = now;
903         isc_time_settoepoch(&zone->resigntime);
904         isc_time_settoepoch(&zone->keywarntime);
905         isc_time_settoepoch(&zone->signingtime);
906         isc_time_settoepoch(&zone->nsec3chaintime);
907         isc_time_settoepoch(&zone->refreshkeytime);
908         zone->refreshkeyinterval = 0;
909         zone->refreshkeycount = 0;
910         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
911         zone->retry = DNS_ZONE_DEFAULTRETRY;
912         zone->expire = 0;
913         zone->minimum = 0;
914         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
915         zone->minrefresh = DNS_ZONE_MINREFRESH;
916         zone->maxretry = DNS_ZONE_MAXRETRY;
917         zone->minretry = DNS_ZONE_MINRETRY;
918         zone->masters = NULL;
919         zone->masterkeynames = NULL;
920         zone->mastersok = NULL;
921         zone->masterscnt = 0;
922         zone->curmaster = 0;
923         zone->notify = NULL;
924         zone->notifykeynames = NULL;
925         zone->notifytype = dns_notifytype_yes;
926         zone->notifycnt = 0;
927         zone->task = NULL;
928         zone->loadtask = NULL;
929         zone->update_acl = NULL;
930         zone->forward_acl = NULL;
931         zone->notify_acl = NULL;
932         zone->query_acl = NULL;
933         zone->queryon_acl = NULL;
934         zone->xfr_acl = NULL;
935         zone->update_disabled = ISC_FALSE;
936         zone->zero_no_soa_ttl = ISC_TRUE;
937         zone->check_names = dns_severity_ignore;
938         zone->request = NULL;
939         zone->lctx = NULL;
940         zone->readio = NULL;
941         zone->dctx = NULL;
942         zone->writeio = NULL;
943         zone->timer = NULL;
944         zone->idlein = DNS_DEFAULT_IDLEIN;
945         zone->idleout = DNS_DEFAULT_IDLEOUT;
946         zone->log_key_expired_timer = 0;
947         ISC_LIST_INIT(zone->notifies);
948         isc_sockaddr_any(&zone->notifysrc4);
949         isc_sockaddr_any6(&zone->notifysrc6);
950         isc_sockaddr_any(&zone->xfrsource4);
951         isc_sockaddr_any6(&zone->xfrsource6);
952         isc_sockaddr_any(&zone->altxfrsource4);
953         isc_sockaddr_any6(&zone->altxfrsource6);
954         zone->xfr = NULL;
955         zone->tsigkey = NULL;
956         zone->maxxfrin = MAX_XFER_TIME;
957         zone->maxxfrout = MAX_XFER_TIME;
958         zone->ssutable = NULL;
959         zone->sigvalidityinterval = 30 * 24 * 3600;
960         zone->sigresigninginterval = 7 * 24 * 3600;
961         zone->view = NULL;
962         zone->acache = NULL;
963         zone->checkmx = NULL;
964         zone->checksrv = NULL;
965         zone->checkns = NULL;
966         ISC_LINK_INIT(zone, statelink);
967         zone->statelist = NULL;
968         zone->stats = NULL;
969         zone->requeststats_on = ISC_FALSE;
970         zone->statlevel = dns_zonestat_none;
971         zone->requeststats = NULL;
972         zone->rcvquerystats = NULL;
973         zone->notifydelay = 5;
974         zone->isself = NULL;
975         zone->isselfarg = NULL;
976         ISC_LIST_INIT(zone->signing);
977         ISC_LIST_INIT(zone->nsec3chain);
978         zone->signatures = 10;
979         zone->nodes = 100;
980         zone->privatetype = (dns_rdatatype_t)0xffffU;
981         zone->added = ISC_FALSE;
982         zone->is_rpz = ISC_FALSE;
983         ISC_LIST_INIT(zone->forwards);
984         zone->raw = NULL;
985         zone->secure = NULL;
986         zone->sourceserial = 0;
987         zone->sourceserialset = ISC_FALSE;
988         ISC_LIST_INIT(zone->rss_events);
989         zone->rss_db = NULL;
990         zone->rss_raw = NULL;
991         zone->rss_newver = NULL;
992         zone->rss_oldver = NULL;
993         zone->rss_event = NULL;
994         zone->rss_state = NULL;
995         zone->updatemethod = dns_updatemethod_increment;
996
997         zone->magic = ZONE_MAGIC;
998
999         /* Must be after magic is set. */
1000         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1001         if (result != ISC_R_SUCCESS)
1002                 goto free_erefs;
1003
1004         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1005                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
1006                        NULL, NULL);
1007         *zonep = zone;
1008         return (ISC_R_SUCCESS);
1009
1010  free_erefs:
1011         isc_refcount_decrement(&zone->erefs, NULL);
1012         isc_refcount_destroy(&zone->erefs);
1013
1014  free_dblock:
1015         ZONEDB_DESTROYLOCK(&zone->dblock);
1016
1017  free_mutex:
1018         DESTROYLOCK(&zone->lock);
1019
1020  free_zone:
1021         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1022         return (result);
1023 }
1024
1025 /*
1026  * Free a zone.  Because we require that there be no more
1027  * outstanding events or references, no locking is necessary.
1028  */
1029 static void
1030 zone_free(dns_zone_t *zone) {
1031         isc_mem_t *mctx = NULL;
1032         dns_signing_t *signing;
1033         dns_nsec3chain_t *nsec3chain;
1034
1035         REQUIRE(DNS_ZONE_VALID(zone));
1036         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
1037         REQUIRE(zone->irefs == 0);
1038         REQUIRE(!LOCKED_ZONE(zone));
1039         REQUIRE(zone->timer == NULL);
1040         REQUIRE(zone->zmgr == NULL);
1041
1042         /*
1043          * Managed objects.  Order is important.
1044          */
1045         if (zone->request != NULL)
1046                 dns_request_destroy(&zone->request); /* XXXMPA */
1047         INSIST(zone->readio == NULL);
1048         INSIST(zone->statelist == NULL);
1049         INSIST(zone->writeio == NULL);
1050
1051         if (zone->task != NULL)
1052                 isc_task_detach(&zone->task);
1053         if (zone->loadtask != NULL)
1054                 isc_task_detach(&zone->loadtask);
1055
1056         /* Unmanaged objects */
1057         for (signing = ISC_LIST_HEAD(zone->signing);
1058              signing != NULL;
1059              signing = ISC_LIST_HEAD(zone->signing)) {
1060                 ISC_LIST_UNLINK(zone->signing, signing, link);
1061                 dns_db_detach(&signing->db);
1062                 dns_dbiterator_destroy(&signing->dbiterator);
1063                 isc_mem_put(zone->mctx, signing, sizeof *signing);
1064         }
1065         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
1066              nsec3chain != NULL;
1067              nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
1068                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1069                 dns_db_detach(&nsec3chain->db);
1070                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1071                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1072         }
1073         if (zone->masterfile != NULL)
1074                 isc_mem_free(zone->mctx, zone->masterfile);
1075         zone->masterfile = NULL;
1076         if (zone->keydirectory != NULL)
1077                 isc_mem_free(zone->mctx, zone->keydirectory);
1078         zone->keydirectory = NULL;
1079         zone->journalsize = -1;
1080         if (zone->journal != NULL)
1081                 isc_mem_free(zone->mctx, zone->journal);
1082         zone->journal = NULL;
1083         if (zone->stats != NULL)
1084                 isc_stats_detach(&zone->stats);
1085         if (zone->requeststats != NULL)
1086                 isc_stats_detach(&zone->requeststats);
1087         if(zone->rcvquerystats != NULL )
1088                 dns_stats_detach(&zone->rcvquerystats);
1089         if (zone->db != NULL)
1090                 zone_detachdb(zone);
1091         if (zone->acache != NULL)
1092                 dns_acache_detach(&zone->acache);
1093         zone_freedbargs(zone);
1094         RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
1095                       == ISC_R_SUCCESS);
1096         RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
1097                       == ISC_R_SUCCESS);
1098         zone->check_names = dns_severity_ignore;
1099         if (zone->update_acl != NULL)
1100                 dns_acl_detach(&zone->update_acl);
1101         if (zone->forward_acl != NULL)
1102                 dns_acl_detach(&zone->forward_acl);
1103         if (zone->notify_acl != NULL)
1104                 dns_acl_detach(&zone->notify_acl);
1105         if (zone->query_acl != NULL)
1106                 dns_acl_detach(&zone->query_acl);
1107         if (zone->queryon_acl != NULL)
1108                 dns_acl_detach(&zone->queryon_acl);
1109         if (zone->xfr_acl != NULL)
1110                 dns_acl_detach(&zone->xfr_acl);
1111         if (dns_name_dynamic(&zone->origin))
1112                 dns_name_free(&zone->origin, zone->mctx);
1113         if (zone->strnamerd != NULL)
1114                 isc_mem_free(zone->mctx, zone->strnamerd);
1115         if (zone->strname != NULL)
1116                 isc_mem_free(zone->mctx, zone->strname);
1117         if (zone->strrdclass != NULL)
1118                 isc_mem_free(zone->mctx, zone->strrdclass);
1119         if (zone->strviewname != NULL)
1120                 isc_mem_free(zone->mctx, zone->strviewname);
1121         if (zone->ssutable != NULL)
1122                 dns_ssutable_detach(&zone->ssutable);
1123
1124         /* last stuff */
1125         ZONEDB_DESTROYLOCK(&zone->dblock);
1126         DESTROYLOCK(&zone->lock);
1127         isc_refcount_destroy(&zone->erefs);
1128         zone->magic = 0;
1129         mctx = zone->mctx;
1130         isc_mem_put(mctx, zone, sizeof(*zone));
1131         isc_mem_detach(&mctx);
1132 }
1133
1134 /*
1135  * Returns ISC_TRUE iff this the signed side of an inline-signing zone.
1136  * Caller should hold zone lock.
1137  */
1138 static inline isc_boolean_t
1139 inline_secure(dns_zone_t *zone) {
1140         REQUIRE(DNS_ZONE_VALID(zone));
1141         if (zone->raw != NULL)
1142                 return (ISC_TRUE);
1143         return (ISC_FALSE);
1144 }
1145
1146 /*
1147  * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone
1148  * Caller should hold zone lock.
1149  */
1150 static inline isc_boolean_t
1151 inline_raw(dns_zone_t *zone) {
1152         REQUIRE(DNS_ZONE_VALID(zone));
1153         if (zone->secure != NULL)
1154                 return (ISC_TRUE);
1155         return (ISC_FALSE);
1156 }
1157
1158 /*
1159  *      Single shot.
1160  */
1161 void
1162 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1163         char namebuf[1024];
1164
1165         REQUIRE(DNS_ZONE_VALID(zone));
1166         REQUIRE(rdclass != dns_rdataclass_none);
1167
1168         /*
1169          * Test and set.
1170          */
1171         LOCK_ZONE(zone);
1172         REQUIRE(zone->rdclass == dns_rdataclass_none ||
1173                 zone->rdclass == rdclass);
1174         zone->rdclass = rdclass;
1175
1176         if (zone->strnamerd != NULL)
1177                 isc_mem_free(zone->mctx, zone->strnamerd);
1178         if (zone->strrdclass != NULL)
1179                 isc_mem_free(zone->mctx, zone->strrdclass);
1180
1181         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1182         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1183         zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1184         zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1185
1186         if (inline_secure(zone))
1187                 dns_zone_setclass(zone->raw, rdclass);
1188         UNLOCK_ZONE(zone);
1189 }
1190
1191 dns_rdataclass_t
1192 dns_zone_getclass(dns_zone_t *zone) {
1193         REQUIRE(DNS_ZONE_VALID(zone));
1194
1195         return (zone->rdclass);
1196 }
1197
1198 void
1199 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1200         REQUIRE(DNS_ZONE_VALID(zone));
1201
1202         LOCK_ZONE(zone);
1203         zone->notifytype = notifytype;
1204         UNLOCK_ZONE(zone);
1205 }
1206
1207 isc_result_t
1208 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1209         isc_result_t result;
1210         unsigned int soacount;
1211
1212         REQUIRE(DNS_ZONE_VALID(zone));
1213         REQUIRE(serialp != NULL);
1214
1215         LOCK_ZONE(zone);
1216         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1217         if (zone->db != NULL) {
1218                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1219                                           serialp, NULL, NULL, NULL, NULL,
1220                                           NULL);
1221                 if (result == ISC_R_SUCCESS && soacount == 0)
1222                         result = ISC_R_FAILURE;
1223         } else
1224                 result = DNS_R_NOTLOADED;
1225         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1226         UNLOCK_ZONE(zone);
1227
1228         return (result);
1229 }
1230
1231 isc_uint32_t
1232 dns_zone_getserial(dns_zone_t *zone) {
1233         isc_result_t result;
1234         isc_uint32_t serial;
1235
1236         result = dns_zone_getserial2(zone, &serial);
1237         if (result != ISC_R_SUCCESS)
1238                 serial = 0; /* XXX: not really correct, but no other choice */
1239
1240         return (serial);
1241 }
1242
1243 /*
1244  *      Single shot.
1245  */
1246 void
1247 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1248         char namebuf[1024];
1249
1250         REQUIRE(DNS_ZONE_VALID(zone));
1251         REQUIRE(type != dns_zone_none);
1252
1253         /*
1254          * Test and set.
1255          */
1256         LOCK_ZONE(zone);
1257         REQUIRE(zone->type == dns_zone_none || zone->type == type);
1258         zone->type = type;
1259
1260         if (zone->strnamerd != NULL)
1261                 isc_mem_free(zone->mctx, zone->strnamerd);
1262
1263         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1264         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1265         UNLOCK_ZONE(zone);
1266 }
1267
1268 static void
1269 zone_freedbargs(dns_zone_t *zone) {
1270         unsigned int i;
1271
1272         /* Free the old database argument list. */
1273         if (zone->db_argv != NULL) {
1274                 for (i = 0; i < zone->db_argc; i++)
1275                         isc_mem_free(zone->mctx, zone->db_argv[i]);
1276                 isc_mem_put(zone->mctx, zone->db_argv,
1277                             zone->db_argc * sizeof(*zone->db_argv));
1278         }
1279         zone->db_argc = 0;
1280         zone->db_argv = NULL;
1281 }
1282
1283 isc_result_t
1284 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1285         size_t size = 0;
1286         unsigned int i;
1287         isc_result_t result = ISC_R_SUCCESS;
1288         void *mem;
1289         char **tmp, *tmp2;
1290
1291         REQUIRE(DNS_ZONE_VALID(zone));
1292         REQUIRE(argv != NULL && *argv == NULL);
1293
1294         LOCK_ZONE(zone);
1295         size = (zone->db_argc + 1) * sizeof(char *);
1296         for (i = 0; i < zone->db_argc; i++)
1297                 size += strlen(zone->db_argv[i]) + 1;
1298         mem = isc_mem_allocate(mctx, size);
1299         if (mem != NULL) {
1300                 tmp = mem;
1301                 tmp2 = mem;
1302                 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1303                 for (i = 0; i < zone->db_argc; i++) {
1304                         *tmp++ = tmp2;
1305                         strcpy(tmp2, zone->db_argv[i]);
1306                         tmp2 += strlen(tmp2) + 1;
1307                 }
1308                 *tmp = NULL;
1309         } else
1310                 result = ISC_R_NOMEMORY;
1311         UNLOCK_ZONE(zone);
1312         *argv = mem;
1313         return (result);
1314 }
1315
1316 isc_result_t
1317 dns_zone_setdbtype(dns_zone_t *zone,
1318                    unsigned int dbargc, const char * const *dbargv) {
1319         isc_result_t result = ISC_R_SUCCESS;
1320         char **new = NULL;
1321         unsigned int i;
1322
1323         REQUIRE(DNS_ZONE_VALID(zone));
1324         REQUIRE(dbargc >= 1);
1325         REQUIRE(dbargv != NULL);
1326
1327         LOCK_ZONE(zone);
1328
1329         /* Set up a new database argument list. */
1330         new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1331         if (new == NULL)
1332                 goto nomem;
1333         for (i = 0; i < dbargc; i++)
1334                 new[i] = NULL;
1335         for (i = 0; i < dbargc; i++) {
1336                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1337                 if (new[i] == NULL)
1338                         goto nomem;
1339         }
1340
1341         /* Free the old list. */
1342         zone_freedbargs(zone);
1343
1344         zone->db_argc = dbargc;
1345         zone->db_argv = new;
1346         result = ISC_R_SUCCESS;
1347         goto unlock;
1348
1349  nomem:
1350         if (new != NULL) {
1351                 for (i = 0; i < dbargc; i++)
1352                         if (new[i] != NULL)
1353                                 isc_mem_free(zone->mctx, new[i]);
1354                 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1355         }
1356         result = ISC_R_NOMEMORY;
1357
1358  unlock:
1359         UNLOCK_ZONE(zone);
1360         return (result);
1361 }
1362
1363 void
1364 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1365         char namebuf[1024];
1366         REQUIRE(DNS_ZONE_VALID(zone));
1367
1368         LOCK_ZONE(zone);
1369         if (zone->view != NULL)
1370                 dns_view_weakdetach(&zone->view);
1371         dns_view_weakattach(view, &zone->view);
1372
1373         if (zone->strviewname != NULL)
1374                 isc_mem_free(zone->mctx, zone->strviewname);
1375         if (zone->strnamerd != NULL)
1376                 isc_mem_free(zone->mctx, zone->strnamerd);
1377
1378         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1379         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1380         zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1381         zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1382
1383         if (inline_secure(zone))
1384                 dns_zone_setview(zone->raw, view);
1385
1386         UNLOCK_ZONE(zone);
1387 }
1388
1389 dns_view_t *
1390 dns_zone_getview(dns_zone_t *zone) {
1391         REQUIRE(DNS_ZONE_VALID(zone));
1392
1393         return (zone->view);
1394 }
1395
1396
1397 isc_result_t
1398 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1399         isc_result_t result;
1400         char namebuf[1024];
1401
1402         REQUIRE(DNS_ZONE_VALID(zone));
1403         REQUIRE(origin != NULL);
1404
1405         LOCK_ZONE(zone);
1406         if (dns_name_dynamic(&zone->origin)) {
1407                 dns_name_free(&zone->origin, zone->mctx);
1408                 dns_name_init(&zone->origin, NULL);
1409         }
1410         result = dns_name_dup(origin, zone->mctx, &zone->origin);
1411
1412         if (zone->strnamerd != NULL)
1413                 isc_mem_free(zone->mctx, zone->strnamerd);
1414         if (zone->strname != NULL)
1415                 isc_mem_free(zone->mctx, zone->strname);
1416
1417         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1418         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1419         zone_name_tostr(zone, namebuf, sizeof namebuf);
1420         zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1421
1422         if (result == ISC_R_SUCCESS && inline_secure(zone))
1423                 result = dns_zone_setorigin(zone->raw, origin);
1424         UNLOCK_ZONE(zone);
1425         return (result);
1426 }
1427
1428 void
1429 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1430         REQUIRE(DNS_ZONE_VALID(zone));
1431         REQUIRE(acache != NULL);
1432
1433         LOCK_ZONE(zone);
1434         if (zone->acache != NULL)
1435                 dns_acache_detach(&zone->acache);
1436         dns_acache_attach(acache, &zone->acache);
1437         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1438         if (zone->db != NULL) {
1439                 isc_result_t result;
1440
1441                 /*
1442                  * If the zone reuses an existing DB, the DB needs to be
1443                  * set in the acache explicitly.  We can safely ignore the
1444                  * case where the DB is already set.  If other error happens,
1445                  * the acache will not work effectively.
1446                  */
1447                 result = dns_acache_setdb(acache, zone->db);
1448                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1449                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1450                                          "dns_acache_setdb() failed: %s",
1451                                          isc_result_totext(result));
1452                 }
1453         }
1454         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1455         UNLOCK_ZONE(zone);
1456 }
1457
1458 static isc_result_t
1459 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1460         char *copy;
1461
1462         if (value != NULL) {
1463                 copy = isc_mem_strdup(zone->mctx, value);
1464                 if (copy == NULL)
1465                         return (ISC_R_NOMEMORY);
1466         } else {
1467                 copy = NULL;
1468         }
1469
1470         if (*field != NULL)
1471                 isc_mem_free(zone->mctx, *field);
1472
1473         *field = copy;
1474         return (ISC_R_SUCCESS);
1475 }
1476
1477 isc_result_t
1478 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1479         return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1480 }
1481
1482 isc_result_t
1483 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1484                   dns_masterformat_t format) {
1485         isc_result_t result = ISC_R_SUCCESS;
1486
1487         REQUIRE(DNS_ZONE_VALID(zone));
1488
1489         LOCK_ZONE(zone);
1490         result = dns_zone_setstring(zone, &zone->masterfile, file);
1491         if (result == ISC_R_SUCCESS) {
1492                 zone->masterformat = format;
1493                 result = default_journal(zone);
1494         }
1495         UNLOCK_ZONE(zone);
1496
1497         return (result);
1498 }
1499
1500 const char *
1501 dns_zone_getfile(dns_zone_t *zone) {
1502         REQUIRE(DNS_ZONE_VALID(zone));
1503
1504         return (zone->masterfile);
1505 }
1506
1507 static isc_result_t
1508 default_journal(dns_zone_t *zone) {
1509         isc_result_t result;
1510         char *journal;
1511
1512         REQUIRE(DNS_ZONE_VALID(zone));
1513         REQUIRE(LOCKED_ZONE(zone));
1514
1515         if (zone->masterfile != NULL) {
1516                 /* Calculate string length including '\0'. */
1517                 int len = strlen(zone->masterfile) + sizeof(".jnl");
1518                 journal = isc_mem_allocate(zone->mctx, len);
1519                 if (journal == NULL)
1520                         return (ISC_R_NOMEMORY);
1521                 strcpy(journal, zone->masterfile);
1522                 strcat(journal, ".jnl");
1523         } else {
1524                 journal = NULL;
1525         }
1526         result = dns_zone_setstring(zone, &zone->journal, journal);
1527         if (journal != NULL)
1528                 isc_mem_free(zone->mctx, journal);
1529         return (result);
1530 }
1531
1532 isc_result_t
1533 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1534         isc_result_t result = ISC_R_SUCCESS;
1535
1536         REQUIRE(DNS_ZONE_VALID(zone));
1537
1538         LOCK_ZONE(zone);
1539         result = dns_zone_setstring(zone, &zone->journal, journal);
1540         UNLOCK_ZONE(zone);
1541
1542         return (result);
1543 }
1544
1545 char *
1546 dns_zone_getjournal(dns_zone_t *zone) {
1547         REQUIRE(DNS_ZONE_VALID(zone));
1548
1549         return (zone->journal);
1550 }
1551
1552 /*
1553  * Return true iff the zone is "dynamic", in the sense that the zone's
1554  * master file (if any) is written by the server, rather than being
1555  * updated manually and read by the server.
1556  *
1557  * This is true for slave zones, stub zones, key zones, and zones that
1558  * allow dynamic updates either by having an update policy ("ssutable")
1559  * or an "allow-update" ACL with a value other than exactly "{ none; }".
1560  */
1561 isc_boolean_t
1562 dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) {
1563         REQUIRE(DNS_ZONE_VALID(zone));
1564
1565         if (zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1566             zone->type == dns_zone_key ||
1567             (zone->type == dns_zone_redirect && zone->masters != NULL))
1568                 return (ISC_TRUE);
1569
1570         /* If !ignore_freeze, we need check whether updates are disabled.  */
1571         if (zone->type == dns_zone_master &&
1572             (!zone->update_disabled || ignore_freeze) &&
1573             ((zone->ssutable != NULL) ||
1574              (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1575                 return (ISC_TRUE);
1576
1577         return (ISC_FALSE);
1578
1579 }
1580
1581 /*
1582  * Set the response policy index and information for a zone.
1583  */
1584 isc_result_t
1585 dns_zone_rpz_enable(dns_zone_t *zone) {
1586         /*
1587          * Only RBTDB zones can be used for response policy zones,
1588          * because only they have the code to load the create the summary data.
1589          * Only zones that are loaded instead of mmap()ed create the
1590          * summary data and so can be policy zones.
1591          */
1592         if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1593             strcmp(zone->db_argv[0], "rbt64") != 0)
1594                 return (ISC_R_NOTIMPLEMENTED);
1595
1596         zone->is_rpz = ISC_TRUE;
1597
1598         return (ISC_R_SUCCESS);
1599 }
1600
1601 isc_boolean_t
1602 dns_zone_get_rpz(dns_zone_t *zone) {
1603         return (zone->is_rpz);
1604 }
1605
1606 /*
1607  * If a zone is a response policy zone, mark its new database.
1608  */
1609 isc_result_t
1610 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1611 #ifdef BIND9
1612         if (zone->is_rpz)
1613                 return (dns_db_rpz_enabled(db, NULL));
1614 #endif
1615         return (ISC_R_SUCCESS);
1616 }
1617
1618 static isc_result_t
1619 zone_load(dns_zone_t *zone, unsigned int flags, isc_boolean_t locked) {
1620         isc_result_t result;
1621         isc_time_t now;
1622         isc_time_t loadtime, filetime;
1623         dns_db_t *db = NULL;
1624         isc_boolean_t rbt, hasraw;
1625
1626         REQUIRE(DNS_ZONE_VALID(zone));
1627
1628         if (!locked)
1629                 LOCK_ZONE(zone);
1630         hasraw = inline_secure(zone);
1631         if (hasraw) {
1632                 result = zone_load(zone->raw, flags, ISC_FALSE);
1633                 if (result != ISC_R_SUCCESS) {
1634                         if (!locked)
1635                                 UNLOCK_ZONE(zone);
1636                         return(result);
1637                 }
1638                 LOCK_ZONE(zone->raw);
1639         }
1640
1641         TIME_NOW(&now);
1642
1643         INSIST(zone->type != dns_zone_none);
1644
1645         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1646                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1647                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1648                 result = DNS_R_CONTINUE;
1649                 goto cleanup;
1650         }
1651
1652         INSIST(zone->db_argc >= 1);
1653
1654         rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1655               strcmp(zone->db_argv[0], "rbt64") == 0;
1656
1657         if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1658                 /*
1659                  * The zone has no master file configured.
1660                  */
1661                 result = ISC_R_SUCCESS;
1662                 goto cleanup;
1663         }
1664
1665         if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) {
1666                 /*
1667                  * This is a slave, stub, or dynamically updated
1668                  * zone being reloaded.  Do nothing - the database
1669                  * we already have is guaranteed to be up-to-date.
1670                  */
1671                 if (zone->type == dns_zone_master)
1672                         result = DNS_R_DYNAMIC;
1673                 else
1674                         result = ISC_R_SUCCESS;
1675                 goto cleanup;
1676         }
1677
1678         /*
1679          * Store the current time before the zone is loaded, so that if the
1680          * file changes between the time of the load and the time that
1681          * zone->loadtime is set, then the file will still be reloaded
1682          * the next time dns_zone_load is called.
1683          */
1684         TIME_NOW(&loadtime);
1685
1686         /*
1687          * Don't do the load if the file that stores the zone is older
1688          * than the last time the zone was loaded.  If the zone has not
1689          * been loaded yet, zone->loadtime will be the epoch.
1690          */
1691         if (zone->masterfile != NULL) {
1692                 /*
1693                  * The file is already loaded.  If we are just doing a
1694                  * "rndc reconfig", we are done.
1695                  */
1696                 if (!isc_time_isepoch(&zone->loadtime) &&
1697                     (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1698                         result = ISC_R_SUCCESS;
1699                         goto cleanup;
1700                 }
1701
1702                 result = isc_file_getmodtime(zone->masterfile, &filetime);
1703                 if (result == ISC_R_SUCCESS) {
1704                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1705                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1706                             isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1707                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1708                                              "skipping load: master file "
1709                                              "older than last load");
1710                                 result = DNS_R_UPTODATE;
1711                                 goto cleanup;
1712                         }
1713                         loadtime = filetime;
1714                 }
1715         }
1716
1717         /*
1718          * Built in zones (with the exception of empty zones) don't need
1719          * to be reloaded.
1720          */
1721         if (zone->type == dns_zone_master &&
1722             strcmp(zone->db_argv[0], "_builtin") == 0 &&
1723             (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1724             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1725                 result = ISC_R_SUCCESS;
1726                 goto cleanup;
1727         }
1728
1729         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1730              (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
1731             rbt) {
1732                 if (zone->masterfile == NULL ||
1733                     !isc_file_exists(zone->masterfile)) {
1734                         if (zone->masterfile != NULL) {
1735                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1736                                              "no master file");
1737                         }
1738                         zone->refreshtime = now;
1739                         if (zone->task != NULL)
1740                                 zone_settimer(zone, &now);
1741                         result = ISC_R_SUCCESS;
1742                         goto cleanup;
1743                 }
1744         }
1745
1746         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1747
1748         result = dns_db_create(zone->mctx, zone->db_argv[0],
1749                                &zone->origin, (zone->type == dns_zone_stub) ?
1750                                dns_dbtype_stub : dns_dbtype_zone,
1751                                zone->rdclass,
1752                                zone->db_argc - 1, zone->db_argv + 1,
1753                                &db);
1754
1755         if (result != ISC_R_SUCCESS) {
1756                 dns_zone_log(zone, ISC_LOG_ERROR,
1757                              "loading zone: creating database: %s",
1758                              isc_result_totext(result));
1759                 goto cleanup;
1760         }
1761         dns_db_settask(db, zone->task);
1762
1763         if (! dns_db_ispersistent(db)) {
1764                 if (zone->masterfile != NULL) {
1765                         result = zone_startload(db, zone, loadtime);
1766                 } else {
1767                         result = DNS_R_NOMASTERFILE;
1768                         if (zone->type == dns_zone_master ||
1769                             (zone->type == dns_zone_redirect &&
1770                              zone->masters == NULL)) {
1771                                 dns_zone_log(zone, ISC_LOG_ERROR,
1772                                              "loading zone: "
1773                                              "no master file configured");
1774                                 goto cleanup;
1775                         }
1776                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1777                                      "no master file configured: continuing");
1778                 }
1779         }
1780
1781         if (result == DNS_R_CONTINUE) {
1782                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1783                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1784                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1785                 goto cleanup;
1786         }
1787
1788         result = zone_postload(zone, db, loadtime, result);
1789
1790  cleanup:
1791         if (hasraw)
1792                 UNLOCK_ZONE(zone->raw);
1793         if (!locked)
1794                 UNLOCK_ZONE(zone);
1795         if (db != NULL)
1796                 dns_db_detach(&db);
1797         return (result);
1798 }
1799
1800 isc_result_t
1801 dns_zone_load(dns_zone_t *zone) {
1802         return (zone_load(zone, 0, ISC_FALSE));
1803 }
1804
1805 isc_result_t
1806 dns_zone_loadnew(dns_zone_t *zone) {
1807         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT, ISC_FALSE));
1808 }
1809
1810 static void
1811 zone_asyncload(isc_task_t *task, isc_event_t *event) {
1812         dns_asyncload_t *asl = event->ev_arg;
1813         dns_zone_t *zone = asl->zone;
1814         isc_result_t result = ISC_R_SUCCESS;
1815         isc_boolean_t load_pending;
1816
1817         UNUSED(task);
1818
1819         REQUIRE(DNS_ZONE_VALID(zone));
1820
1821         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1822                 result = ISC_R_CANCELED;
1823         isc_event_free(&event);
1824
1825         if (result == ISC_R_CANCELED)
1826                 goto cleanup;
1827
1828         /* Make sure load is still pending */
1829         LOCK_ZONE(zone);
1830         load_pending = ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
1831
1832         if (!load_pending) {
1833                 UNLOCK_ZONE(zone);
1834                 goto cleanup;
1835         }
1836
1837         zone_load(zone, 0, ISC_TRUE);
1838
1839         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1840         UNLOCK_ZONE(zone);
1841
1842         /* Inform the zone table we've finished loading */
1843         if (asl->loaded != NULL)
1844                 (asl->loaded)(asl->loaded_arg, zone, task);
1845
1846  cleanup:
1847         isc_mem_put(zone->mctx, asl, sizeof (*asl));
1848         dns_zone_idetach(&zone);
1849 }
1850
1851 isc_result_t
1852 dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
1853         isc_event_t *e;
1854         dns_asyncload_t *asl = NULL;
1855         isc_result_t result = ISC_R_SUCCESS;
1856
1857         REQUIRE(DNS_ZONE_VALID(zone));
1858
1859         if (zone->zmgr == NULL)
1860                 return (ISC_R_FAILURE);
1861
1862         /* If we already have a load pending, stop now */
1863         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
1864                 return (ISC_R_ALREADYRUNNING);
1865
1866         asl = isc_mem_get(zone->mctx, sizeof (*asl));
1867         if (asl == NULL)
1868                 CHECK(ISC_R_NOMEMORY);
1869
1870         asl->zone = NULL;
1871         asl->loaded = done;
1872         asl->loaded_arg = arg;
1873
1874         e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
1875                                DNS_EVENT_ZONELOAD,
1876                                zone_asyncload, asl,
1877                                sizeof(isc_event_t));
1878         if (e == NULL)
1879                 CHECK(ISC_R_NOMEMORY);
1880
1881         LOCK_ZONE(zone);
1882         zone_iattach(zone, &asl->zone);
1883         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
1884         isc_task_send(zone->loadtask, &e);
1885         UNLOCK_ZONE(zone);
1886
1887         return (ISC_R_SUCCESS);
1888
1889   failure:
1890         if (asl != NULL)
1891                 isc_mem_put(zone->mctx, asl, sizeof (*asl));
1892         return (result);
1893 }
1894
1895 isc_boolean_t
1896 dns__zone_loadpending(dns_zone_t *zone) {
1897         REQUIRE(DNS_ZONE_VALID(zone));
1898
1899         return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)));
1900 }
1901
1902 isc_result_t
1903 dns_zone_loadandthaw(dns_zone_t *zone) {
1904         isc_result_t result;
1905
1906         if (inline_raw(zone))
1907                 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW,
1908                                    ISC_FALSE);
1909         else
1910                 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, ISC_FALSE);
1911
1912         switch (result) {
1913         case DNS_R_CONTINUE:
1914                 /* Deferred thaw. */
1915                 break;
1916         case DNS_R_UPTODATE:
1917         case ISC_R_SUCCESS:
1918         case DNS_R_SEENINCLUDE:
1919                 zone->update_disabled = ISC_FALSE;
1920                 break;
1921         case DNS_R_NOMASTERFILE:
1922                 zone->update_disabled = ISC_FALSE;
1923                 break;
1924         default:
1925                 /* Error, remain in disabled state. */
1926                 break;
1927         }
1928         return (result);
1929 }
1930
1931 static unsigned int
1932 get_master_options(dns_zone_t *zone) {
1933         unsigned int options;
1934
1935         options = DNS_MASTER_ZONE;
1936         if (zone->type == dns_zone_slave ||
1937             (zone->type == dns_zone_redirect && zone->masters == NULL))
1938                 options |= DNS_MASTER_SLAVE;
1939         if (zone->type == dns_zone_key)
1940                 options |= DNS_MASTER_KEY;
1941         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1942                 options |= DNS_MASTER_CHECKNS;
1943         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1944                 options |= DNS_MASTER_FATALNS;
1945         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1946                 options |= DNS_MASTER_CHECKNAMES;
1947         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1948                 options |= DNS_MASTER_CHECKNAMESFAIL;
1949         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1950                 options |= DNS_MASTER_CHECKMX;
1951         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1952                 options |= DNS_MASTER_CHECKMXFAIL;
1953         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1954                 options |= DNS_MASTER_CHECKWILDCARD;
1955         if (inline_secure(zone) || (zone->type == dns_zone_master &&
1956             ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1957               zone->ssutable != NULL)))
1958                 options |= DNS_MASTER_RESIGN;
1959         return (options);
1960 }
1961
1962 static void
1963 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1964         dns_load_t *load = event->ev_arg;
1965         isc_result_t result = ISC_R_SUCCESS;
1966         unsigned int options;
1967
1968         REQUIRE(DNS_LOAD_VALID(load));
1969
1970         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1971                 result = ISC_R_CANCELED;
1972         isc_event_free(&event);
1973         if (result == ISC_R_CANCELED)
1974                 goto fail;
1975
1976         options = get_master_options(load->zone);
1977
1978         result = dns_master_loadfileinc3(load->zone->masterfile,
1979                                          dns_db_origin(load->db),
1980                                          dns_db_origin(load->db),
1981                                          load->zone->rdclass, options, 0,
1982                                          &load->callbacks, task,
1983                                          zone_loaddone, load,
1984                                          &load->zone->lctx, load->zone->mctx,
1985                                          load->zone->masterformat);
1986         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1987             result != DNS_R_SEENINCLUDE)
1988                 goto fail;
1989         return;
1990
1991  fail:
1992         zone_loaddone(load, result);
1993 }
1994
1995 static void
1996 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
1997         isc_result_t result;
1998         unsigned int soacount;
1999
2000         LOCK(&raw->lock);
2001         if (raw->db != NULL) {
2002                 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
2003                                           &rawdata->sourceserial,
2004                                           NULL, NULL, NULL, NULL,
2005                                           NULL);
2006                 if (result == ISC_R_SUCCESS && soacount > 0U)
2007                         rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2008         }
2009         UNLOCK(&raw->lock);
2010 }
2011
2012 static void
2013 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2014         const char me[] = "zone_gotwritehandle";
2015         dns_zone_t *zone = event->ev_arg;
2016         isc_result_t result = ISC_R_SUCCESS;
2017         dns_dbversion_t *version = NULL;
2018         dns_masterrawheader_t rawdata;
2019
2020         REQUIRE(DNS_ZONE_VALID(zone));
2021         INSIST(task == zone->task);
2022         ENTER;
2023
2024         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2025                 result = ISC_R_CANCELED;
2026         isc_event_free(&event);
2027         if (result == ISC_R_CANCELED)
2028                 goto fail;
2029
2030         LOCK_ZONE(zone);
2031         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2032         if (zone->db != NULL) {
2033                 const dns_master_style_t *output_style;
2034
2035                 dns_db_currentversion(zone->db, &version);
2036                 dns_master_initrawheader(&rawdata);
2037                 if (inline_secure(zone))
2038                         get_raw_serial(zone->raw, &rawdata);
2039                 if (zone->type == dns_zone_key)
2040                         output_style = &dns_master_style_keyzone;
2041                 else
2042                         output_style = &dns_master_style_default;
2043                 result = dns_master_dumpinc3(zone->mctx, zone->db, version,
2044                                              output_style, zone->masterfile,
2045                                              zone->task, dump_done, zone,                                                    &zone->dctx, zone->masterformat,
2046                                              &rawdata);
2047                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2048         } else
2049                 result = ISC_R_CANCELED;
2050         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2051         UNLOCK_ZONE(zone);
2052         if (result != DNS_R_CONTINUE)
2053                 goto fail;
2054         return;
2055
2056  fail:
2057         dump_done(zone, result);
2058 }
2059
2060 /*
2061  * Save the raw serial number for inline-signing zones.
2062  * (XXX: Other information from the header will be used
2063  * for other purposes in the future, but for now this is
2064  * all we're interested in.)
2065  */
2066 static void
2067 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2068         if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
2069                 return;
2070
2071         zone->sourceserial = header->sourceserial;
2072         zone->sourceserialset = ISC_TRUE;
2073 }
2074
2075 void
2076 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2077         if (zone == NULL)
2078                 return;
2079
2080         LOCK_ZONE(zone);
2081         zone_setrawdata(zone, header);
2082         UNLOCK_ZONE(zone);
2083 }
2084
2085 static isc_result_t
2086 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2087         dns_load_t *load;
2088         isc_result_t result;
2089         isc_result_t tresult;
2090         unsigned int options;
2091
2092         result = dns_zone_rpz_enable_db(zone, db);
2093         if (result != ISC_R_SUCCESS)
2094                 return (result);
2095         options = get_master_options(zone);
2096         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
2097                 options |= DNS_MASTER_MANYERRORS;
2098
2099         if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2100                 load = isc_mem_get(zone->mctx, sizeof(*load));
2101                 if (load == NULL)
2102                         return (ISC_R_NOMEMORY);
2103
2104                 load->mctx = NULL;
2105                 load->zone = NULL;
2106                 load->db = NULL;
2107                 load->loadtime = loadtime;
2108                 load->magic = LOAD_MAGIC;
2109
2110                 isc_mem_attach(zone->mctx, &load->mctx);
2111                 zone_iattach(zone, &load->zone);
2112                 dns_db_attach(db, &load->db);
2113                 dns_rdatacallbacks_init(&load->callbacks);
2114                 load->callbacks.rawdata = zone_setrawdata;
2115                 zone_iattach(zone, &load->callbacks.zone);
2116                 result = dns_db_beginload(db, &load->callbacks.add,
2117                                           &load->callbacks.add_private);
2118                 if (result != ISC_R_SUCCESS)
2119                         goto cleanup;
2120                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask,
2121                                        zone_gotreadhandle, load,
2122                                        &zone->readio);
2123                 if (result != ISC_R_SUCCESS) {
2124                         /*
2125                          * We can't report multiple errors so ignore
2126                          * the result of dns_db_endload().
2127                          */
2128                         (void)dns_db_endload(load->db,
2129                                              &load->callbacks.add_private);
2130                         goto cleanup;
2131                 } else
2132                         result = DNS_R_CONTINUE;
2133         } else {
2134                 dns_rdatacallbacks_t callbacks;
2135
2136                 dns_rdatacallbacks_init(&callbacks);
2137                 callbacks.rawdata = zone_setrawdata;
2138                 zone_iattach(zone, &callbacks.zone);
2139                 result = dns_db_beginload(db, &callbacks.add,
2140                                           &callbacks.add_private);
2141                 if (result != ISC_R_SUCCESS) {
2142                         zone_idetach(&callbacks.zone);
2143                         return (result);
2144                 }
2145                 result = dns_master_loadfile3(zone->masterfile,
2146                                               &zone->origin, &zone->origin,
2147                                               zone->rdclass, options, 0,
2148                                               &callbacks, zone->mctx,
2149                                               zone->masterformat);
2150                 tresult = dns_db_endload(db, &callbacks.add_private);
2151                 if (result == ISC_R_SUCCESS)
2152                         result = tresult;
2153                 zone_idetach(&callbacks.zone);
2154         }
2155
2156         return (result);
2157
2158  cleanup:
2159         load->magic = 0;
2160         dns_db_detach(&load->db);
2161         zone_idetach(&load->zone);
2162         zone_idetach(&load->callbacks.zone);
2163         isc_mem_detach(&load->mctx);
2164         isc_mem_put(zone->mctx, load, sizeof(*load));
2165         return (result);
2166 }
2167
2168 static isc_boolean_t
2169 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2170               dns_name_t *owner)
2171 {
2172         isc_result_t result;
2173         char ownerbuf[DNS_NAME_FORMATSIZE];
2174         char namebuf[DNS_NAME_FORMATSIZE];
2175         char altbuf[DNS_NAME_FORMATSIZE];
2176         dns_fixedname_t fixed;
2177         dns_name_t *foundname;
2178         int level;
2179
2180         /*
2181          * "." means the services does not exist.
2182          */
2183         if (dns_name_equal(name, dns_rootname))
2184                 return (ISC_TRUE);
2185
2186         /*
2187          * Outside of zone.
2188          */
2189         if (!dns_name_issubdomain(name, &zone->origin)) {
2190                 if (zone->checkmx != NULL)
2191                         return ((zone->checkmx)(zone, name, owner));
2192                 return (ISC_TRUE);
2193         }
2194
2195         if (zone->type == dns_zone_master)
2196                 level = ISC_LOG_ERROR;
2197         else
2198                 level = ISC_LOG_WARNING;
2199
2200         dns_fixedname_init(&fixed);
2201         foundname = dns_fixedname_name(&fixed);
2202
2203         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2204                              0, 0, NULL, foundname, NULL, NULL);
2205         if (result == ISC_R_SUCCESS)
2206                 return (ISC_TRUE);
2207
2208         if (result == DNS_R_NXRRSET) {
2209                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2210                                      0, 0, NULL, foundname, NULL, NULL);
2211                 if (result == ISC_R_SUCCESS)
2212                         return (ISC_TRUE);
2213         }
2214
2215         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2216         dns_name_format(name, namebuf, sizeof namebuf);
2217         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2218             result == DNS_R_EMPTYNAME) {
2219                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2220                         level = ISC_LOG_WARNING;
2221                 dns_zone_log(zone, level,
2222                              "%s/MX '%s' has no address records (A or AAAA)",
2223                              ownerbuf, namebuf);
2224                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2225         }
2226
2227         if (result == DNS_R_CNAME) {
2228                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2229                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2230                         level = ISC_LOG_WARNING;
2231                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2232                         dns_zone_log(zone, level,
2233                                      "%s/MX '%s' is a CNAME (illegal)",
2234                                      ownerbuf, namebuf);
2235                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2236         }
2237
2238         if (result == DNS_R_DNAME) {
2239                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2240                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2241                         level = ISC_LOG_WARNING;
2242                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2243                         dns_name_format(foundname, altbuf, sizeof altbuf);
2244                         dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2245                                      " '%s' (illegal)", ownerbuf, namebuf,
2246                                      altbuf);
2247                 }
2248                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2249         }
2250
2251         if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2252                 return ((zone->checkmx)(zone, name, owner));
2253
2254         return (ISC_TRUE);
2255 }
2256
2257 static isc_boolean_t
2258 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2259                dns_name_t *owner)
2260 {
2261         isc_result_t result;
2262         char ownerbuf[DNS_NAME_FORMATSIZE];
2263         char namebuf[DNS_NAME_FORMATSIZE];
2264         char altbuf[DNS_NAME_FORMATSIZE];
2265         dns_fixedname_t fixed;
2266         dns_name_t *foundname;
2267         int level;
2268
2269         /*
2270          * "." means the services does not exist.
2271          */
2272         if (dns_name_equal(name, dns_rootname))
2273                 return (ISC_TRUE);
2274
2275         /*
2276          * Outside of zone.
2277          */
2278         if (!dns_name_issubdomain(name, &zone->origin)) {
2279                 if (zone->checksrv != NULL)
2280                         return ((zone->checksrv)(zone, name, owner));
2281                 return (ISC_TRUE);
2282         }
2283
2284         if (zone->type == dns_zone_master)
2285                 level = ISC_LOG_ERROR;
2286         else
2287                 level = ISC_LOG_WARNING;
2288
2289         dns_fixedname_init(&fixed);
2290         foundname = dns_fixedname_name(&fixed);
2291
2292         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2293                              0, 0, NULL, foundname, NULL, NULL);
2294         if (result == ISC_R_SUCCESS)
2295                 return (ISC_TRUE);
2296
2297         if (result == DNS_R_NXRRSET) {
2298                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2299                                      0, 0, NULL, foundname, NULL, NULL);
2300                 if (result == ISC_R_SUCCESS)
2301                         return (ISC_TRUE);
2302         }
2303
2304         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2305         dns_name_format(name, namebuf, sizeof namebuf);
2306         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2307             result == DNS_R_EMPTYNAME) {
2308                 dns_zone_log(zone, level,
2309                              "%s/SRV '%s' has no address records (A or AAAA)",
2310                              ownerbuf, namebuf);
2311                 /* XXX950 make fatal for 9.5.0. */
2312                 return (ISC_TRUE);
2313         }
2314
2315         if (result == DNS_R_CNAME) {
2316                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2317                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2318                         level = ISC_LOG_WARNING;
2319                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2320                         dns_zone_log(zone, level,
2321                                      "%s/SRV '%s' is a CNAME (illegal)",
2322                                      ownerbuf, namebuf);
2323                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2324         }
2325
2326         if (result == DNS_R_DNAME) {
2327                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2328                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2329                         level = ISC_LOG_WARNING;
2330                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2331                         dns_name_format(foundname, altbuf, sizeof altbuf);
2332                         dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2333                                      "DNAME '%s' (illegal)", ownerbuf, namebuf,
2334                                      altbuf);
2335                 }
2336                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2337         }
2338
2339         if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2340                 return ((zone->checksrv)(zone, name, owner));
2341
2342         return (ISC_TRUE);
2343 }
2344
2345 static isc_boolean_t
2346 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2347                 dns_name_t *owner)
2348 {
2349         isc_boolean_t answer = ISC_TRUE;
2350         isc_result_t result, tresult;
2351         char ownerbuf[DNS_NAME_FORMATSIZE];
2352         char namebuf[DNS_NAME_FORMATSIZE];
2353         char altbuf[DNS_NAME_FORMATSIZE];
2354         dns_fixedname_t fixed;
2355         dns_name_t *foundname;
2356         dns_rdataset_t a;
2357         dns_rdataset_t aaaa;
2358         int level;
2359
2360         /*
2361          * Outside of zone.
2362          */
2363         if (!dns_name_issubdomain(name, &zone->origin)) {
2364                 if (zone->checkns != NULL)
2365                         return ((zone->checkns)(zone, name, owner, NULL, NULL));
2366                 return (ISC_TRUE);
2367         }
2368
2369         if (zone->type == dns_zone_master)
2370                 level = ISC_LOG_ERROR;
2371         else
2372                 level = ISC_LOG_WARNING;
2373
2374         dns_fixedname_init(&fixed);
2375         foundname = dns_fixedname_name(&fixed);
2376         dns_rdataset_init(&a);
2377         dns_rdataset_init(&aaaa);
2378
2379         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2380                              DNS_DBFIND_GLUEOK, 0, NULL,
2381                              foundname, &a, NULL);
2382
2383         if (result == ISC_R_SUCCESS) {
2384                 dns_rdataset_disassociate(&a);
2385                 return (ISC_TRUE);
2386         } else if (result == DNS_R_DELEGATION)
2387                 dns_rdataset_disassociate(&a);
2388
2389         if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2390             result == DNS_R_GLUE) {
2391                 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2392                                      DNS_DBFIND_GLUEOK, 0, NULL,
2393                                      foundname, &aaaa, NULL);
2394                 if (tresult == ISC_R_SUCCESS) {
2395                         if (dns_rdataset_isassociated(&a))
2396                                 dns_rdataset_disassociate(&a);
2397                         dns_rdataset_disassociate(&aaaa);
2398                         return (ISC_TRUE);
2399                 }
2400                 if (tresult == DNS_R_DELEGATION)
2401                         dns_rdataset_disassociate(&aaaa);
2402                 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2403                         /*
2404                          * Check glue against child zone.
2405                          */
2406                         if (zone->checkns != NULL)
2407                                 answer = (zone->checkns)(zone, name, owner,
2408                                                          &a, &aaaa);
2409                         if (dns_rdataset_isassociated(&a))
2410                                 dns_rdataset_disassociate(&a);
2411                         if (dns_rdataset_isassociated(&aaaa))
2412                                 dns_rdataset_disassociate(&aaaa);
2413                         return (answer);
2414                 }
2415         }
2416
2417         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2418         dns_name_format(name, namebuf, sizeof namebuf);
2419         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2420             result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2421                 const char *what;
2422                 isc_boolean_t required = ISC_FALSE;
2423                 if (dns_name_issubdomain(name, owner)) {
2424                         what = "REQUIRED GLUE ";
2425                         required = ISC_TRUE;
2426                  } else if (result == DNS_R_DELEGATION)
2427                         what = "SIBLING GLUE ";
2428                 else
2429                         what = "";
2430
2431                 if (result != DNS_R_DELEGATION || required ||
2432                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2433                         dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2434                                      "address records (A or AAAA)",
2435                                      ownerbuf, namebuf, what);
2436                         /*
2437                          * Log missing address record.
2438                          */
2439                         if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2440                                 (void)(zone->checkns)(zone, name, owner,
2441                                                       &a, &aaaa);
2442                         /* XXX950 make fatal for 9.5.0. */
2443                         /* answer = ISC_FALSE; */
2444                 }
2445         } else if (result == DNS_R_CNAME) {
2446                 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2447                              ownerbuf, namebuf);
2448                 /* XXX950 make fatal for 9.5.0. */
2449                 /* answer = ISC_FALSE; */
2450         } else if (result == DNS_R_DNAME) {
2451                 dns_name_format(foundname, altbuf, sizeof altbuf);
2452                 dns_zone_log(zone, level,
2453                              "%s/NS '%s' is below a DNAME '%s' (illegal)",
2454                              ownerbuf, namebuf, altbuf);
2455                 /* XXX950 make fatal for 9.5.0. */
2456                 /* answer = ISC_FALSE; */
2457         }
2458
2459         if (dns_rdataset_isassociated(&a))
2460                 dns_rdataset_disassociate(&a);
2461         if (dns_rdataset_isassociated(&aaaa))
2462                 dns_rdataset_disassociate(&aaaa);
2463         return (answer);
2464 }
2465
2466 static isc_boolean_t
2467 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2468                      dns_rdataset_t *rdataset)
2469 {
2470         dns_rdataset_t tmprdataset;
2471         isc_result_t result;
2472         isc_boolean_t answer = ISC_TRUE;
2473         isc_boolean_t format = ISC_TRUE;
2474         int level = ISC_LOG_WARNING;
2475         char ownerbuf[DNS_NAME_FORMATSIZE];
2476         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2477         unsigned int count1 = 0;
2478
2479         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2480                 level = ISC_LOG_ERROR;
2481
2482         dns_rdataset_init(&tmprdataset);
2483         for (result = dns_rdataset_first(rdataset);
2484              result == ISC_R_SUCCESS;
2485              result = dns_rdataset_next(rdataset)) {
2486                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2487                 unsigned int count2 = 0;
2488
2489                 count1++;
2490                 dns_rdataset_current(rdataset, &rdata1);
2491                 dns_rdataset_clone(rdataset, &tmprdataset);
2492                 for (result = dns_rdataset_first(&tmprdataset);
2493                      result == ISC_R_SUCCESS;
2494                      result = dns_rdataset_next(&tmprdataset)) {
2495                         dns_rdata_t rdata2 = DNS_RDATA_INIT;
2496                         count2++;
2497                         if (count1 >= count2)
2498                                 continue;
2499                         dns_rdataset_current(&tmprdataset, &rdata2);
2500                         if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2501                                 if (format) {
2502                                         dns_name_format(owner, ownerbuf,
2503                                                         sizeof ownerbuf);
2504                                         dns_rdatatype_format(rdata1.type,
2505                                                              typebuf,
2506                                                              sizeof(typebuf));
2507                                         format = ISC_FALSE;
2508                                 }
2509                                 dns_zone_log(zone, level, "%s/%s has "
2510                                              "semantically identical records",
2511                                              ownerbuf, typebuf);
2512                                 if (level == ISC_LOG_ERROR)
2513                                         answer = ISC_FALSE;
2514                                 break;
2515                         }
2516                 }
2517                 dns_rdataset_disassociate(&tmprdataset);
2518                 if (!format)
2519                         break;
2520         }
2521         return (answer);
2522 }
2523
2524 static isc_boolean_t
2525 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2526         dns_dbiterator_t *dbiterator = NULL;
2527         dns_dbnode_t *node = NULL;
2528         dns_fixedname_t fixed;
2529         dns_name_t *name;
2530         dns_rdataset_t rdataset;
2531         dns_rdatasetiter_t *rdsit = NULL;
2532         isc_boolean_t ok = ISC_TRUE;
2533         isc_result_t result;
2534
2535         dns_fixedname_init(&fixed);
2536         name = dns_fixedname_name(&fixed);
2537         dns_rdataset_init(&rdataset);
2538
2539         result = dns_db_createiterator(db, 0, &dbiterator);
2540         if (result != ISC_R_SUCCESS)
2541                 return (ISC_TRUE);
2542
2543         for (result = dns_dbiterator_first(dbiterator);
2544              result == ISC_R_SUCCESS;
2545              result = dns_dbiterator_next(dbiterator)) {
2546                 result = dns_dbiterator_current(dbiterator, &node, name);
2547                 if (result != ISC_R_SUCCESS)
2548                         continue;
2549
2550                 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2551                 if (result != ISC_R_SUCCESS)
2552                         continue;
2553
2554                 for (result = dns_rdatasetiter_first(rdsit);
2555                      result == ISC_R_SUCCESS;
2556                      result = dns_rdatasetiter_next(rdsit)) {
2557                         dns_rdatasetiter_current(rdsit, &rdataset);
2558                         if (!zone_rrset_check_dup(zone, name, &rdataset))
2559                                 ok = ISC_FALSE;
2560                         dns_rdataset_disassociate(&rdataset);
2561                 }
2562                 dns_rdatasetiter_destroy(&rdsit);
2563                 dns_db_detachnode(db, &node);
2564         }
2565
2566         if (node != NULL)
2567                 dns_db_detachnode(db, &node);
2568         dns_dbiterator_destroy(&dbiterator);
2569
2570         return (ok);
2571 }
2572
2573 static isc_boolean_t
2574 isspf(const dns_rdata_t *rdata) {
2575         char buf[1024];
2576         const unsigned char *data = rdata->data;
2577         unsigned int rdl = rdata->length, i = 0, tl, len;
2578
2579         while (rdl > 0U) {
2580                 len = tl = *data;
2581                 ++data;
2582                 --rdl;
2583                 INSIST(tl <= rdl);
2584                 if (len > sizeof(buf) - i - 1)
2585                         len = sizeof(buf) - i - 1;
2586                 memmove(buf + i, data, len);
2587                 i += len;
2588                 data += tl;
2589                 rdl -= tl;
2590         }
2591
2592         if (i < 6U)
2593                 return(ISC_FALSE);
2594
2595         buf[i] = 0;
2596         if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
2597                 return (ISC_TRUE);
2598         return (ISC_FALSE);
2599 }
2600
2601 static isc_boolean_t
2602 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2603         dns_dbiterator_t *dbiterator = NULL;
2604         dns_dbnode_t *node = NULL;
2605         dns_rdataset_t rdataset;
2606         dns_fixedname_t fixed;
2607         dns_fixedname_t fixedbottom;
2608         dns_rdata_mx_t mx;
2609         dns_rdata_ns_t ns;
2610         dns_rdata_in_srv_t srv;
2611         dns_rdata_t rdata;
2612         dns_name_t *name;
2613         dns_name_t *bottom;
2614         isc_result_t result;
2615         isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
2616
2617         dns_fixedname_init(&fixed);
2618         name = dns_fixedname_name(&fixed);
2619         dns_fixedname_init(&fixedbottom);
2620         bottom = dns_fixedname_name(&fixedbottom);
2621         dns_rdataset_init(&rdataset);
2622         dns_rdata_init(&rdata);
2623
2624         result = dns_db_createiterator(db, 0, &dbiterator);
2625         if (result != ISC_R_SUCCESS)
2626                 return (ISC_TRUE);
2627
2628         result = dns_dbiterator_first(dbiterator);
2629         while (result == ISC_R_SUCCESS) {
2630                 result = dns_dbiterator_current(dbiterator, &node, name);
2631                 if (result != ISC_R_SUCCESS)
2632                         goto cleanup;
2633
2634                 /*
2635                  * Is this name visible in the zone?
2636                  */
2637                 if (!dns_name_issubdomain(name, &zone->origin) ||
2638                     (dns_name_countlabels(bottom) > 0 &&
2639                      dns_name_issubdomain(name, bottom)))
2640                         goto next;
2641
2642                 /*
2643                  * Don't check the NS records at the origin.
2644                  */
2645                 if (dns_name_equal(name, &zone->origin))
2646                         goto checkmx;
2647
2648                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2649                                              0, 0, &rdataset, NULL);
2650                 if (result != ISC_R_SUCCESS)
2651                         goto checkmx;
2652                 /*
2653                  * Remember bottom of zone.
2654                  */
2655                 dns_name_copy(name, bottom, NULL);
2656
2657                 result = dns_rdataset_first(&rdataset);
2658                 while (result == ISC_R_SUCCESS) {
2659                         dns_rdataset_current(&rdataset, &rdata);
2660                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
2661                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2662                         if (!zone_check_glue(zone, db, &ns.name, name))
2663                                 ok = ISC_FALSE;
2664                         dns_rdata_reset(&rdata);
2665                         result = dns_rdataset_next(&rdataset);
2666                 }
2667                 dns_rdataset_disassociate(&rdataset);
2668                 goto next;
2669
2670  checkmx:
2671                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2672                                              0, 0, &rdataset, NULL);
2673                 if (result != ISC_R_SUCCESS)
2674                         goto checksrv;
2675                 result = dns_rdataset_first(&rdataset);
2676                 while (result == ISC_R_SUCCESS) {
2677                         dns_rdataset_current(&rdataset, &rdata);
2678                         result = dns_rdata_tostruct(&rdata, &mx, NULL);
2679                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2680                         if (!zone_check_mx(zone, db, &mx.mx, name))
2681                                 ok = ISC_FALSE;
2682                         dns_rdata_reset(&rdata);
2683                         result = dns_rdataset_next(&rdataset);
2684                 }
2685                 dns_rdataset_disassociate(&rdataset);
2686
2687  checksrv:
2688                 if (zone->rdclass != dns_rdataclass_in)
2689                         goto next;
2690                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2691                                              0, 0, &rdataset, NULL);
2692                 if (result != ISC_R_SUCCESS)
2693                         goto checkspf;
2694                 result = dns_rdataset_first(&rdataset);
2695                 while (result == ISC_R_SUCCESS) {
2696                         dns_rdataset_current(&rdataset, &rdata);
2697                         result = dns_rdata_tostruct(&rdata, &srv, NULL);
2698                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2699                         if (!zone_check_srv(zone, db, &srv.target, name))
2700                                 ok = ISC_FALSE;
2701                         dns_rdata_reset(&rdata);
2702                         result = dns_rdataset_next(&rdataset);
2703                 }
2704                 dns_rdataset_disassociate(&rdataset);
2705
2706  checkspf:
2707                 /*
2708                  * Check if there is a type SPF record without an
2709                  * SPF-formatted type TXT record also being present.
2710                  */
2711                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
2712                         goto next;
2713                 if (zone->rdclass != dns_rdataclass_in)
2714                         goto next;
2715                 have_spf = have_txt = ISC_FALSE;
2716                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
2717                                              0, 0, &rdataset, NULL);
2718                 if (result == ISC_R_SUCCESS) {
2719                         dns_rdataset_disassociate(&rdataset);
2720                         have_spf = ISC_TRUE;
2721                 }
2722                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
2723                                              0, 0, &rdataset, NULL);
2724                 if (result != ISC_R_SUCCESS)
2725                         goto notxt;
2726                 result = dns_rdataset_first(&rdataset);
2727                 while (result == ISC_R_SUCCESS) {
2728                         dns_rdataset_current(&rdataset, &rdata);
2729                         have_txt = isspf(&rdata);
2730                         dns_rdata_reset(&rdata);
2731                         if (have_txt)
2732                                 break;
2733                         result = dns_rdataset_next(&rdataset);
2734                 }
2735                 dns_rdataset_disassociate(&rdataset);
2736
2737  notxt:
2738                 if (have_spf && !have_txt) {
2739                         char namebuf[DNS_NAME_FORMATSIZE];
2740
2741                         dns_name_format(name, namebuf, sizeof(namebuf));
2742                         dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
2743                                      "SPF record but no SPF TXT record found, "
2744                                      "add matching type TXT record", namebuf);
2745                 }
2746
2747  next:
2748                 dns_db_detachnode(db, &node);
2749                 result = dns_dbiterator_next(dbiterator);
2750         }
2751
2752  cleanup:
2753         if (node != NULL)
2754                 dns_db_detachnode(db, &node);
2755         dns_dbiterator_destroy(&dbiterator);
2756
2757         return (ok);
2758 }
2759
2760 /*
2761  * OpenSSL verification of RSA keys with exponent 3 is known to be
2762  * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
2763  * if they are in use.
2764  */
2765 static void
2766 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2767         dns_dbnode_t *node = NULL;
2768         dns_dbversion_t *version = NULL;
2769         dns_rdata_dnskey_t dnskey;
2770         dns_rdata_t rdata = DNS_RDATA_INIT;
2771         dns_rdataset_t rdataset;
2772         isc_result_t result;
2773         isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2774         const char *algorithm;
2775
2776         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2777         if (result != ISC_R_SUCCESS)
2778                 goto cleanup;
2779
2780         dns_db_currentversion(db, &version);
2781         dns_rdataset_init(&rdataset);
2782         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2783                                      dns_rdatatype_none, 0, &rdataset, NULL);
2784         if (result != ISC_R_SUCCESS)
2785                 goto cleanup;
2786
2787         for (result = dns_rdataset_first(&rdataset);
2788              result == ISC_R_SUCCESS;
2789              result = dns_rdataset_next(&rdataset))
2790         {
2791                 dns_rdataset_current(&rdataset, &rdata);
2792                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2793                 INSIST(result == ISC_R_SUCCESS);
2794
2795                 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2796                      dnskey.algorithm == DST_ALG_RSAMD5) &&
2797                      dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2798                      dnskey.data[1] == 3)
2799                 {
2800                         if (dnskey.algorithm == DST_ALG_RSASHA1) {
2801                                 logit = !foundrsa;
2802                                 foundrsa = ISC_TRUE;
2803                                 algorithm = "RSASHA1";
2804                         } else {
2805                                 logit = !foundmd5;
2806                                 foundmd5 = ISC_TRUE;
2807                                 algorithm = "RSAMD5";
2808                         }
2809                         if (logit)
2810                                 dns_zone_log(zone, ISC_LOG_WARNING,
2811                                              "weak %s (%u) key found "
2812                                              "(exponent=3)", algorithm,
2813                                              dnskey.algorithm);
2814                         if (foundrsa && foundmd5)
2815                                 break;
2816                 }
2817                 dns_rdata_reset(&rdata);
2818         }
2819         dns_rdataset_disassociate(&rdataset);
2820
2821  cleanup:
2822         if (node != NULL)
2823                 dns_db_detachnode(db, &node);
2824         if (version != NULL)
2825                 dns_db_closeversion(db, &version, ISC_FALSE);
2826 }
2827
2828 static void
2829 resume_signingwithkey(dns_zone_t *zone) {
2830         dns_dbnode_t *node = NULL;
2831         dns_dbversion_t *version = NULL;
2832         dns_rdata_t rdata = DNS_RDATA_INIT;
2833         dns_rdataset_t rdataset;
2834         isc_result_t result;
2835         dns_db_t *db = NULL;
2836
2837         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2838         if (zone->db != NULL)
2839                 dns_db_attach(zone->db, &db);
2840         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2841         if (db == NULL)
2842                 goto cleanup;
2843
2844         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2845         if (result != ISC_R_SUCCESS)
2846                 goto cleanup;
2847
2848         dns_db_currentversion(db, &version);
2849         dns_rdataset_init(&rdataset);
2850         result = dns_db_findrdataset(db, node, version,
2851                                      zone->privatetype,
2852                                      dns_rdatatype_none, 0,
2853                                      &rdataset, NULL);
2854         if (result != ISC_R_SUCCESS) {
2855                 INSIST(!dns_rdataset_isassociated(&rdataset));
2856                 goto cleanup;
2857         }
2858
2859         for (result = dns_rdataset_first(&rdataset);
2860              result == ISC_R_SUCCESS;
2861              result = dns_rdataset_next(&rdataset))
2862         {
2863                 dns_rdataset_current(&rdataset, &rdata);
2864                 if (rdata.length != 5 ||
2865                     rdata.data[0] == 0 || rdata.data[4] != 0) {
2866                         dns_rdata_reset(&rdata);
2867                         continue;
2868                 }
2869
2870                 result = zone_signwithkey(zone, rdata.data[0],
2871                                           (rdata.data[1] << 8) | rdata.data[2],
2872                                           ISC_TF(rdata.data[3]));
2873                 if (result != ISC_R_SUCCESS) {
2874                         dns_zone_log(zone, ISC_LOG_ERROR,
2875                                      "zone_signwithkey failed: %s",
2876                                      dns_result_totext(result));
2877                 }
2878                 dns_rdata_reset(&rdata);
2879         }
2880         dns_rdataset_disassociate(&rdataset);
2881
2882  cleanup:
2883         if (db != NULL) {
2884                 if (node != NULL)
2885                         dns_db_detachnode(db, &node);
2886                 if (version != NULL)
2887                         dns_db_closeversion(db, &version, ISC_FALSE);
2888                 dns_db_detach(&db);
2889         }
2890 }
2891
2892 static isc_result_t
2893 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2894         dns_nsec3chain_t *nsec3chain, *current;
2895         dns_dbversion_t *version = NULL;
2896         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
2897         isc_result_t result;
2898         isc_time_t now;
2899         unsigned int options = 0;
2900         char saltbuf[255*2+1];
2901         char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
2902         dns_db_t *db = NULL;
2903         int i;
2904
2905         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2906         if (zone->db != NULL)
2907                 dns_db_attach(zone->db, &db);
2908         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2909
2910         if (db == NULL) {
2911                 result = ISC_R_SUCCESS;
2912                 goto cleanup;
2913         }
2914
2915         dns_db_currentversion(db, &version);
2916         result = dns_nsec_nseconly(db, version, &nseconly);
2917         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
2918         dns_db_closeversion(db, &version, ISC_FALSE);
2919         if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
2920                 result = ISC_R_SUCCESS;
2921                 goto cleanup;
2922         }
2923
2924         nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2925         if (nsec3chain == NULL) {
2926                 result = ISC_R_NOMEMORY;
2927                 goto cleanup;
2928         }
2929
2930         nsec3chain->magic = 0;
2931         nsec3chain->done = ISC_FALSE;
2932         nsec3chain->db = NULL;
2933         nsec3chain->dbiterator = NULL;
2934         nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2935         nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2936         nsec3chain->nsec3param.hash = nsec3param->hash;
2937         nsec3chain->nsec3param.iterations = nsec3param->iterations;
2938         nsec3chain->nsec3param.flags = nsec3param->flags;
2939         nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2940         memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2941         nsec3chain->nsec3param.salt = nsec3chain->salt;
2942         nsec3chain->seen_nsec = ISC_FALSE;
2943         nsec3chain->delete_nsec = ISC_FALSE;
2944         nsec3chain->save_delete_nsec = ISC_FALSE;
2945
2946         if (nsec3param->flags == 0)
2947                 strlcpy(flags, "NONE", sizeof(flags));
2948         else {
2949                 flags[0] = '\0';
2950                 if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2951                         strlcat(flags, "REMOVE", sizeof(flags));
2952                 if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) {
2953                         if (flags[0] == '\0')
2954                                 strlcpy(flags, "INITIAL", sizeof(flags));
2955                         else
2956                                 strlcat(flags, "|INITIAL", sizeof(flags));
2957                 }
2958                 if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2959                         if (flags[0] == '\0')
2960                                 strlcpy(flags, "CREATE", sizeof(flags));
2961                         else
2962                                 strlcat(flags, "|CREATE", sizeof(flags));
2963                 }
2964                 if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2965                         if (flags[0] == '\0')
2966                                 strlcpy(flags, "NONSEC", sizeof(flags));
2967                         else
2968                                 strlcat(flags, "|NONSEC", sizeof(flags));
2969                 }
2970                 if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2971                         if (flags[0] == '\0')
2972                                 strlcpy(flags, "OPTOUT", sizeof(flags));
2973                         else
2974                                 strlcat(flags, "|OPTOUT", sizeof(flags));
2975                 }
2976         }
2977         if (nsec3param->salt_length == 0)
2978                 strlcpy(saltbuf, "-", sizeof(saltbuf));
2979         else
2980                 for (i = 0; i < nsec3param->salt_length; i++)
2981                         sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2982         dns_zone_log(zone, ISC_LOG_INFO,
2983                      "zone_addnsec3chain(%u,%s,%u,%s)",
2984                       nsec3param->hash, flags, nsec3param->iterations,
2985                       saltbuf);
2986
2987         for (current = ISC_LIST_HEAD(zone->nsec3chain);
2988              current != NULL;
2989              current = ISC_LIST_NEXT(current, link)) {
2990                 if (current->db == db &&
2991                     current->nsec3param.hash == nsec3param->hash &&
2992                     current->nsec3param.iterations == nsec3param->iterations &&
2993                     current->nsec3param.salt_length == nsec3param->salt_length
2994                     && !memcmp(current->nsec3param.salt, nsec3param->salt,
2995                                nsec3param->salt_length))
2996                         current->done = ISC_TRUE;
2997         }
2998
2999         dns_db_attach(db, &nsec3chain->db);
3000         if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
3001                 options = DNS_DB_NONSEC3;
3002         result = dns_db_createiterator(nsec3chain->db, options,
3003                                        &nsec3chain->dbiterator);
3004         if (result == ISC_R_SUCCESS)
3005                 dns_dbiterator_first(nsec3chain->dbiterator);
3006         if (result == ISC_R_SUCCESS) {
3007                 dns_dbiterator_pause(nsec3chain->dbiterator);
3008                 ISC_LIST_INITANDAPPEND(zone->nsec3chain,
3009                                        nsec3chain, link);
3010                 nsec3chain = NULL;
3011                 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3012                         TIME_NOW(&now);
3013                         zone->nsec3chaintime = now;
3014                         if (zone->task != NULL)
3015                                 zone_settimer(zone, &now);
3016                 }
3017         }
3018
3019         if (nsec3chain != NULL) {
3020                 if (nsec3chain->db != NULL)
3021                         dns_db_detach(&nsec3chain->db);
3022                 if (nsec3chain->dbiterator != NULL)
3023                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
3024                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3025         }
3026
3027  cleanup:
3028         if (db != NULL)
3029                 dns_db_detach(&db);
3030         return (result);
3031 }
3032
3033 static void
3034 resume_addnsec3chain(dns_zone_t *zone) {
3035         dns_dbnode_t *node = NULL;
3036         dns_dbversion_t *version = NULL;
3037         dns_rdataset_t rdataset;
3038         isc_result_t result;
3039         dns_rdata_nsec3param_t nsec3param;
3040         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
3041         dns_db_t *db = NULL;
3042
3043         if (zone->privatetype == 0)
3044                 return;
3045
3046         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3047         if (zone->db != NULL)
3048                 dns_db_attach(zone->db, &db);
3049         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3050         if (db == NULL)
3051                 goto cleanup;
3052
3053         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3054         if (result != ISC_R_SUCCESS)
3055                 goto cleanup;
3056
3057         dns_db_currentversion(db, &version);
3058
3059         result = dns_nsec_nseconly(db, version, &nseconly);
3060         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3061
3062         dns_rdataset_init(&rdataset);
3063         result = dns_db_findrdataset(db, node, version,
3064                                      zone->privatetype, dns_rdatatype_none,
3065                                      0, &rdataset, NULL);
3066         if (result != ISC_R_SUCCESS) {
3067                 INSIST(!dns_rdataset_isassociated(&rdataset));
3068                 goto cleanup;
3069         }
3070
3071         for (result = dns_rdataset_first(&rdataset);
3072              result == ISC_R_SUCCESS;
3073              result = dns_rdataset_next(&rdataset))
3074         {
3075                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3076                 dns_rdata_t rdata = DNS_RDATA_INIT;
3077                 dns_rdata_t private = DNS_RDATA_INIT;
3078
3079                 dns_rdataset_current(&rdataset, &private);
3080                 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3081                                                 sizeof(buf)))
3082                         continue;
3083                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3084                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3085                 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3086                     ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3087                 {
3088                         result = zone_addnsec3chain(zone, &nsec3param);
3089                         if (result != ISC_R_SUCCESS) {
3090                                 dns_zone_log(zone, ISC_LOG_ERROR,
3091                                              "zone_addnsec3chain failed: %s",
3092                                              dns_result_totext(result));
3093                         }
3094                 }
3095         }
3096         dns_rdataset_disassociate(&rdataset);
3097  cleanup:
3098         if (db != NULL) {
3099                 if (node != NULL)
3100                         dns_db_detachnode(db, &node);
3101                 if (version != NULL)
3102                         dns_db_closeversion(db, &version, ISC_FALSE);
3103                 dns_db_detach(&db);
3104         }
3105 }
3106
3107 static void
3108 set_resigntime(dns_zone_t *zone) {
3109         dns_rdataset_t rdataset;
3110         dns_fixedname_t fixed;
3111         unsigned int resign;
3112         isc_result_t result;
3113         isc_uint32_t nanosecs;
3114         dns_db_t *db = NULL;
3115
3116         dns_rdataset_init(&rdataset);
3117         dns_fixedname_init(&fixed);
3118
3119         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3120         if (zone->db != NULL)
3121                 dns_db_attach(zone->db, &db);
3122         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3123         if (db == NULL) {
3124                 isc_time_settoepoch(&zone->resigntime);
3125                 return;
3126         }
3127
3128         result = dns_db_getsigningtime(db, &rdataset,
3129                                        dns_fixedname_name(&fixed));
3130         if (result != ISC_R_SUCCESS) {
3131                 isc_time_settoepoch(&zone->resigntime);
3132                 goto cleanup;
3133         }
3134
3135         resign = rdataset.resign - zone->sigresigninginterval;
3136         dns_rdataset_disassociate(&rdataset);
3137         isc_random_get(&nanosecs);
3138         nanosecs %= 1000000000;
3139         isc_time_set(&zone->resigntime, resign, nanosecs);
3140  cleanup:
3141         dns_db_detach(&db);
3142         return;
3143 }
3144
3145 static isc_result_t
3146 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3147         dns_dbnode_t *node = NULL;
3148         dns_rdataset_t rdataset;
3149         dns_dbversion_t *version = NULL;
3150         dns_rdata_nsec3param_t nsec3param;
3151         isc_boolean_t ok = ISC_FALSE;
3152         isc_result_t result;
3153         dns_rdata_t rdata = DNS_RDATA_INIT;
3154         isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
3155                                 dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE;
3156
3157         dns_rdataset_init(&rdataset);
3158         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3159         if (result != ISC_R_SUCCESS) {
3160                 dns_zone_log(zone, ISC_LOG_ERROR,
3161                              "nsec3param lookup failure: %s",
3162                              dns_result_totext(result));
3163                 return (result);
3164         }
3165         dns_db_currentversion(db, &version);
3166
3167         result = dns_db_findrdataset(db, node, version,
3168                                      dns_rdatatype_nsec3param,
3169                                      dns_rdatatype_none, 0, &rdataset, NULL);
3170         if (result == ISC_R_NOTFOUND) {
3171                 INSIST(!dns_rdataset_isassociated(&rdataset));
3172                 result = ISC_R_SUCCESS;
3173                 goto cleanup;
3174         }
3175         if (result != ISC_R_SUCCESS) {
3176                 INSIST(!dns_rdataset_isassociated(&rdataset));
3177                 dns_zone_log(zone, ISC_LOG_ERROR,
3178                              "nsec3param lookup failure: %s",
3179                              dns_result_totext(result));
3180                 goto cleanup;
3181         }
3182
3183         /*
3184          * For dynamic zones we must support every algorithm so we can
3185          * regenerate all the NSEC3 chains.
3186          * For non-dynamic zones we only need to find a supported algorithm.
3187          */
3188         for (result = dns_rdataset_first(&rdataset);
3189              result == ISC_R_SUCCESS;
3190              result = dns_rdataset_next(&rdataset))
3191         {
3192                 dns_rdataset_current(&rdataset, &rdata);
3193                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3194                 dns_rdata_reset(&rdata);
3195                 INSIST(result == ISC_R_SUCCESS);
3196                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3197                     nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3198                 {
3199                         dns_zone_log(zone, ISC_LOG_WARNING,
3200                              "nsec3 test \"unknown\" hash algorithm found: %u",
3201                                      nsec3param.hash);
3202                         ok = ISC_TRUE;
3203                 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3204                         if (dynamic) {
3205                                 dns_zone_log(zone, ISC_LOG_ERROR,
3206                                              "unsupported nsec3 hash algorithm"
3207                                              " in dynamic zone: %u",
3208                                              nsec3param.hash);
3209                                 result = DNS_R_BADZONE;
3210                                 /* Stop second error message. */
3211                                 ok = ISC_TRUE;
3212                                 break;
3213                         } else
3214                                 dns_zone_log(zone, ISC_LOG_WARNING,
3215                                      "unsupported nsec3 hash algorithm: %u",
3216                                              nsec3param.hash);
3217                 } else
3218                         ok = ISC_TRUE;
3219         }
3220         if (result == ISC_R_NOMORE)
3221                 result = ISC_R_SUCCESS;
3222
3223         if (!ok) {
3224                 result = DNS_R_BADZONE;
3225                 dns_zone_log(zone, ISC_LOG_ERROR,
3226                              "no supported nsec3 hash algorithm");
3227         }
3228
3229  cleanup:
3230         if (dns_rdataset_isassociated(&rdataset))
3231                 dns_rdataset_disassociate(&rdataset);
3232         dns_db_closeversion(db, &version, ISC_FALSE);
3233         dns_db_detachnode(db, &node);
3234         return (result);
3235 }
3236
3237 /*
3238  * Set the timer for refreshing the key zone to the soonest future time
3239  * of the set (current timer, keydata->refresh, keydata->addhd,
3240  * keydata->removehd).
3241  */
3242 static void
3243 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3244                     isc_stdtime_t now, isc_boolean_t force)
3245 {
3246         const char me[] = "set_refreshkeytimer";
3247         isc_stdtime_t then;
3248         isc_time_t timenow, timethen;
3249         char timebuf[80];
3250
3251         ENTER;
3252         then = key->refresh;
3253         if (force)
3254                 then = now;
3255         if (key->addhd > now && key->addhd < then)
3256                 then = key->addhd;
3257         if (key->removehd > now && key->removehd < then)
3258                 then = key->removehd;
3259
3260         TIME_NOW(&timenow);
3261         if (then > now)
3262                 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
3263         else
3264                 timethen = timenow;
3265         if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
3266             isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
3267                 zone->refreshkeytime = timethen;
3268
3269         isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
3270         dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
3271         zone_settimer(zone, &timenow);
3272 }
3273
3274 /*
3275  * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3276  * If the key zone is changed, set '*changed' to ISC_TRUE.
3277  */
3278 static isc_result_t
3279 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3280                dns_diff_t *diff, dns_keytable_t *keytable,
3281                dns_keynode_t **keynodep, isc_boolean_t *changed)
3282 {
3283         const char me[] = "create_keydata";
3284         isc_result_t result = ISC_R_SUCCESS;
3285         isc_buffer_t keyb, dstb;
3286         unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3287         dns_rdata_keydata_t keydata;
3288         dns_rdata_dnskey_t dnskey;
3289         dns_rdata_t rdata = DNS_RDATA_INIT;
3290         dns_keynode_t *keynode;
3291         isc_stdtime_t now;
3292         isc_region_t r;
3293         dst_key_t *key;
3294
3295         REQUIRE(keynodep != NULL);
3296         keynode = *keynodep;
3297
3298         ENTER;
3299         isc_stdtime_get(&now);
3300
3301         /* Loop in case there's more than one key. */
3302         while (result == ISC_R_SUCCESS) {
3303                 dns_keynode_t *nextnode = NULL;
3304
3305                 key = dns_keynode_key(keynode);
3306                 if (key == NULL)
3307                         goto skip;
3308
3309                 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3310                 CHECK(dst_key_todns(key, &dstb));
3311
3312                 /* Convert DST key to DNSKEY. */
3313                 dns_rdata_reset(&rdata);
3314                 isc_buffer_usedregion(&dstb, &r);
3315                 dns_rdata_fromregion(&rdata, dst_key_class(key),
3316                                      dns_rdatatype_dnskey, &r);
3317
3318                 /* DSTKEY to KEYDATA. */
3319                 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3320                 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3321                                              NULL));
3322
3323                 /* KEYDATA to rdata. */
3324                 dns_rdata_reset(&rdata);
3325                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3326                 CHECK(dns_rdata_fromstruct(&rdata,
3327                                            zone->rdclass, dns_rdatatype_keydata,
3328                                            &keydata, &keyb));
3329
3330                 /* Add rdata to zone. */
3331                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3332                                     dst_key_name(key), 0, &rdata));
3333                 *changed = ISC_TRUE;
3334
3335                 /* Refresh new keys from the zone apex as soon as possible. */
3336                 set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
3337
3338  skip:
3339                 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3340                 if (result != ISC_R_NOTFOUND) {
3341                         dns_keytable_detachkeynode(keytable, &keynode);
3342                         keynode = nextnode;
3343                 }
3344         }
3345
3346         if (keynode != NULL)
3347                 dns_keytable_detachkeynode(keytable, &keynode);
3348         *keynodep = NULL;
3349
3350         return (ISC_R_SUCCESS);
3351
3352   failure:
3353         return (result);
3354 }
3355
3356 /*
3357  * Remove from the key zone all the KEYDATA records found in rdataset.
3358  */
3359 static isc_result_t
3360 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3361                dns_name_t *name, dns_rdataset_t *rdataset)
3362 {
3363         dns_rdata_t rdata = DNS_RDATA_INIT;
3364         isc_result_t result, uresult;
3365
3366         for (result = dns_rdataset_first(rdataset);
3367              result == ISC_R_SUCCESS;
3368              result = dns_rdataset_next(rdataset)) {
3369                 dns_rdata_reset(&rdata);
3370                 dns_rdataset_current(rdataset, &rdata);
3371                 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3372                                         name, 0, &rdata);
3373                 if (uresult != ISC_R_SUCCESS)
3374                         return (uresult);
3375         }
3376         if (result == ISC_R_NOMORE)
3377                 result = ISC_R_SUCCESS;
3378         return (result);
3379 }
3380
3381 /*
3382  * Compute the DNSSEC key ID for a DNSKEY record.
3383  */
3384 static isc_result_t
3385 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3386             dns_keytag_t *tag)
3387 {
3388         isc_result_t result;
3389         dns_rdata_t rdata = DNS_RDATA_INIT;
3390         unsigned char data[4096];
3391         isc_buffer_t buffer;
3392         dst_key_t *dstkey = NULL;
3393
3394         isc_buffer_init(&buffer, data, sizeof(data));
3395         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3396                              dns_rdatatype_dnskey, dnskey, &buffer);
3397
3398         result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3399         if (result == ISC_R_SUCCESS)
3400                 *tag = dst_key_id(dstkey);
3401         dst_key_free(&dstkey);
3402
3403         return (result);
3404 }
3405
3406 /*
3407  * Add key to the security roots.
3408  */
3409 static void
3410 trust_key(dns_zone_t *zone, dns_name_t *keyname,
3411           dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
3412         isc_result_t result;
3413         dns_rdata_t rdata = DNS_RDATA_INIT;
3414         unsigned char data[4096];
3415         isc_buffer_t buffer;
3416         dns_keytable_t *sr = NULL;
3417         dst_key_t *dstkey = NULL;
3418
3419         /* Convert dnskey to DST key. */
3420         isc_buffer_init(&buffer, data, sizeof(data));
3421         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3422                              dns_rdatatype_dnskey, dnskey, &buffer);
3423
3424         result = dns_view_getsecroots(zone->view, &sr);
3425         if (result != ISC_R_SUCCESS)
3426                 goto failure;
3427
3428         CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
3429         CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
3430         dns_keytable_detach(&sr);
3431
3432   failure:
3433         if (dstkey != NULL)
3434                 dst_key_free(&dstkey);
3435         if (sr != NULL)
3436                 dns_keytable_detach(&sr);
3437         return;
3438 }
3439
3440 /*
3441  * Add a null key to the security roots for so that all queries
3442  * to the zone will fail.
3443  */
3444 static void
3445 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
3446         isc_result_t result;
3447         dns_keytable_t *sr = NULL;
3448
3449         result = dns_view_getsecroots(zone->view, &sr);
3450         if (result == ISC_R_SUCCESS) {
3451                 dns_keytable_marksecure(sr, keyname);
3452                 dns_keytable_detach(&sr);
3453         }
3454 }
3455
3456 /*
3457  * Scan a set of KEYDATA records from the key zone.  The ones that are
3458  * valid (i.e., the add holddown timer has expired) become trusted keys.
3459  */
3460 static void
3461 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
3462         isc_result_t result;
3463         dns_rdata_t rdata = DNS_RDATA_INIT;
3464         dns_rdata_keydata_t keydata;
3465         dns_rdata_dnskey_t dnskey;
3466         isc_mem_t *mctx = zone->mctx;
3467         int trusted = 0, revoked = 0, pending = 0;
3468         isc_stdtime_t now;
3469         dns_keytable_t *sr = NULL;
3470
3471         isc_stdtime_get(&now);
3472
3473         result = dns_view_getsecroots(zone->view, &sr);
3474         if (result == ISC_R_SUCCESS) {
3475                 dns_keytable_delete(sr, name);
3476                 dns_keytable_detach(&sr);
3477         }
3478
3479         /* Now insert all the accepted trust anchors from this keydata set. */
3480         for (result = dns_rdataset_first(rdataset);
3481              result == ISC_R_SUCCESS;
3482              result = dns_rdataset_next(rdataset)) {
3483                 dns_rdata_reset(&rdata);
3484                 dns_rdataset_current(rdataset, &rdata);
3485
3486                 /* Convert rdata to keydata. */
3487                 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
3488                 if (result == ISC_R_UNEXPECTEDEND)
3489                         continue;
3490                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3491
3492                 /* Set the key refresh timer to force a fast refresh. */
3493                 set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
3494
3495                 /* If the removal timer is nonzero, this key was revoked. */
3496                 if (keydata.removehd != 0) {
3497                         revoked++;
3498                         continue;
3499                 }
3500
3501                 /*
3502                  * If the add timer is still pending, this key is not
3503                  * trusted yet.
3504                  */
3505                 if (now < keydata.addhd) {
3506                         pending++;
3507                         continue;
3508                 }
3509
3510                 /* Convert keydata to dnskey. */
3511                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
3512
3513                 /* Add to keytables. */
3514                 trusted++;
3515                 trust_key(zone, name, &dnskey, mctx);
3516         }
3517
3518         if (trusted == 0 && pending != 0) {
3519                 char namebuf[DNS_NAME_FORMATSIZE];
3520                 dns_name_format(name, namebuf, sizeof namebuf);
3521                 dns_zone_log(zone, ISC_LOG_ERROR,
3522                              "No valid trust anchors for '%s'!", namebuf);
3523                 dns_zone_log(zone, ISC_LOG_ERROR,
3524                              "%d key(s) revoked, %d still pending",
3525                              revoked, pending);
3526                 dns_zone_log(zone, ISC_LOG_ERROR,
3527                              "All queries to '%s' will fail", namebuf);
3528                 fail_secure(zone, name);
3529         }
3530 }
3531
3532 static isc_result_t
3533 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3534              dns_diff_t *diff)
3535 {
3536         dns_diff_t temp_diff;
3537         isc_result_t result;
3538
3539         /*
3540          * Create a singleton diff.
3541          */
3542         dns_diff_init(diff->mctx, &temp_diff);
3543         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3544
3545         /*
3546          * Apply it to the database.
3547          */
3548         result = dns_diff_apply(&temp_diff, db, ver);
3549         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3550         if (result != ISC_R_SUCCESS) {
3551                 dns_difftuple_free(tuple);
3552                 return (result);
3553         }
3554
3555         /*
3556          * Merge it into the current pending journal entry.
3557          */
3558         dns_diff_appendminimal(diff, tuple);
3559
3560         /*
3561          * Do not clear temp_diff.
3562          */
3563         return (ISC_R_SUCCESS);
3564 }
3565
3566 static isc_result_t
3567 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3568               dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3569               dns_rdata_t *rdata)
3570 {
3571         dns_difftuple_t *tuple = NULL;
3572         isc_result_t result;
3573         result = dns_difftuple_create(diff->mctx, op,
3574                                       name, ttl, rdata, &tuple);
3575         if (result != ISC_R_SUCCESS)
3576                 return (result);
3577         return (do_one_tuple(&tuple, db, ver, diff));
3578 }
3579
3580 static isc_result_t
3581 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3582                   isc_mem_t *mctx, dns_updatemethod_t method) {
3583         dns_difftuple_t *deltuple = NULL;
3584         dns_difftuple_t *addtuple = NULL;
3585         isc_uint32_t serial;
3586         isc_result_t result;
3587
3588         CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3589         CHECK(dns_difftuple_copy(deltuple, &addtuple));
3590         addtuple->op = DNS_DIFFOP_ADD;
3591
3592         serial = dns_soa_getserial(&addtuple->rdata);
3593         serial = dns_update_soaserial(serial, method);
3594         dns_soa_setserial(serial, &addtuple->rdata);
3595         CHECK(do_one_tuple(&deltuple, db, ver, diff));
3596         CHECK(do_one_tuple(&addtuple, db, ver, diff));
3597         result = ISC_R_SUCCESS;
3598
3599         failure:
3600         if (addtuple != NULL)
3601                 dns_difftuple_free(&addtuple);
3602         if (deltuple != NULL)
3603                 dns_difftuple_free(&deltuple);
3604         return (result);
3605 }
3606
3607 /*
3608  * Write all transactions in 'diff' to the zone journal file.
3609  */
3610 static isc_result_t
3611 zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial,
3612              const char *caller)
3613 {
3614         const char me[] = "zone_journal";
3615         const char *journalfile;
3616         isc_result_t result = ISC_R_SUCCESS;
3617         dns_journal_t *journal = NULL;
3618         unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
3619
3620         ENTER;
3621         journalfile = dns_zone_getjournal(zone);
3622         if (journalfile != NULL) {
3623                 result = dns_journal_open(zone->mctx, journalfile, mode,
3624                                           &journal);
3625                 if (result != ISC_R_SUCCESS) {
3626                         dns_zone_log(zone, ISC_LOG_ERROR,
3627                                      "%s:dns_journal_open -> %s",
3628                                      caller, dns_result_totext(result));
3629                         return (result);
3630                 }
3631
3632                 if (sourceserial != NULL)
3633                         dns_journal_set_sourceserial(journal, *sourceserial);
3634
3635                 result = dns_journal_write_transaction(journal, diff);
3636                 if (result != ISC_R_SUCCESS) {
3637                         dns_zone_log(zone, ISC_LOG_ERROR,
3638                                      "%s:dns_journal_write_transaction -> %s",
3639                                      caller, dns_result_totext(result));
3640                 }
3641                 dns_journal_destroy(&journal);
3642         }
3643
3644         return (result);
3645 }
3646
3647 /*
3648  * Create an SOA record for a newly-created zone
3649  */
3650 static isc_result_t
3651 add_soa(dns_zone_t *zone, dns_db_t *db) {
3652         isc_result_t result;
3653         dns_rdata_t rdata = DNS_RDATA_INIT;
3654         unsigned char buf[DNS_SOA_BUFFERSIZE];
3655         dns_dbversion_t *ver = NULL;
3656         dns_diff_t diff;
3657
3658         dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3659
3660         dns_diff_init(zone->mctx, &diff);
3661         result = dns_db_newversion(db, &ver);
3662         if (result != ISC_R_SUCCESS) {
3663                 dns_zone_log(zone, ISC_LOG_ERROR,
3664                              "add_soa:dns_db_newversion -> %s",
3665                              dns_result_totext(result));
3666                 goto failure;
3667         }
3668
3669         /* Build SOA record */
3670         result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3671                                     0, 0, 0, 0, 0, buf, &rdata);
3672         if (result != ISC_R_SUCCESS) {
3673                 dns_zone_log(zone, ISC_LOG_ERROR,
3674                              "add_soa:dns_soa_buildrdata -> %s",
3675                              dns_result_totext(result));
3676                 goto failure;
3677         }
3678
3679         result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3680                                &zone->origin, 0, &rdata);
3681
3682 failure:
3683         dns_diff_clear(&diff);
3684         if (ver != NULL)
3685                 dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3686
3687         INSIST(ver == NULL);
3688
3689         return (result);
3690 }
3691
3692 /*
3693  * Synchronize the set of initializing keys found in managed-keys {}
3694  * statements with the set of trust anchors found in the managed-keys.bind
3695  * zone.  If a domain is no longer named in managed-keys, delete all keys
3696  * from that domain from the key zone.  If a domain is mentioned in in
3697  * managed-keys but there are no references to it in the key zone, load
3698  * the key zone with the initializing key(s) for that domain.
3699  */
3700 static isc_result_t
3701 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3702         isc_result_t result = ISC_R_SUCCESS;
3703         isc_boolean_t changed = ISC_FALSE;
3704         isc_boolean_t commit = ISC_FALSE;
3705         dns_rbtnodechain_t chain;
3706         dns_fixedname_t fn;
3707         dns_name_t foundname, *origin;
3708         dns_keynode_t *keynode = NULL;
3709         dns_view_t *view = zone->view;
3710         dns_keytable_t *sr = NULL;
3711         dns_dbversion_t *ver = NULL;
3712         dns_diff_t diff;
3713         dns_rriterator_t rrit;
3714
3715         dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3716
3717         dns_name_init(&foundname, NULL);
3718         dns_fixedname_init(&fn);
3719         origin = dns_fixedname_name(&fn);
3720
3721         dns_diff_init(zone->mctx, &diff);
3722
3723         CHECK(dns_view_getsecroots(view, &sr));
3724
3725         result = dns_db_newversion(db, &ver);
3726         if (result != ISC_R_SUCCESS) {
3727                 dns_zone_log(zone, ISC_LOG_ERROR,
3728                              "sync_keyzone:dns_db_newversion -> %s",
3729                              dns_result_totext(result));
3730                 goto failure;
3731         }
3732
3733         /*
3734          * Walk the zone DB.  If we find any keys whose names are no longer
3735          * in managed-keys (or *are* in trusted-keys, meaning they are
3736          * permanent and not RFC5011-maintained), delete them from the
3737          * zone.  Otherwise call load_secroots(), which loads keys into
3738          * secroots as appropriate.
3739          */
3740         dns_rriterator_init(&rrit, db, ver, 0);
3741         for (result = dns_rriterator_first(&rrit);
3742              result == ISC_R_SUCCESS;
3743              result = dns_rriterator_nextrrset(&rrit)) {
3744                 dns_rdataset_t *rdataset = NULL;
3745                 dns_name_t *rrname = NULL;
3746                 isc_uint32_t ttl;
3747
3748                 dns_rriterator_current(&rrit, &rrname, &ttl,
3749                                        &rdataset, NULL);
3750                 if (!dns_rdataset_isassociated(rdataset)) {
3751                         dns_rriterator_destroy(&rrit);
3752                         goto failure;
3753                 }
3754
3755                 if (rdataset->type != dns_rdatatype_keydata)
3756                         continue;
3757
3758                 result = dns_keytable_find(sr, rrname, &keynode);
3759                 if ((result != ISC_R_SUCCESS &&
3760                      result != DNS_R_PARTIALMATCH) ||
3761                     dns_keynode_managed(keynode) == ISC_FALSE)
3762                 {
3763                         CHECK(delete_keydata(db, ver, &diff,
3764                                              rrname, rdataset));
3765                         changed = ISC_TRUE;
3766                 } else {
3767                         load_secroots(zone, rrname, rdataset);
3768                 }
3769
3770                 if (keynode != NULL)
3771                         dns_keytable_detachkeynode(sr, &keynode);
3772         }
3773         dns_rriterator_destroy(&rrit);
3774
3775         /*
3776          * Now walk secroots to find any managed keys that aren't
3777          * in the zone.  If we find any, we add them to the zone.
3778          */
3779         RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3780         dns_rbtnodechain_init(&chain, zone->mctx);
3781         result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3782         if (result == ISC_R_NOTFOUND)
3783                 result = ISC_R_NOMORE;
3784         while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3785                 dns_rbtnode_t *rbtnode = NULL;
3786
3787                 dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3788                 if (rbtnode->data == NULL)
3789                         goto skip;
3790
3791                 dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3792                 if (dns_keynode_managed(keynode)) {
3793                         dns_fixedname_t fname;
3794                         dns_name_t *keyname;
3795                         dst_key_t *key;
3796
3797                         key = dns_keynode_key(keynode);
3798                         dns_fixedname_init(&fname);
3799
3800                         if (key == NULL)   /* fail_secure() was called. */
3801                                 goto skip;
3802
3803                         keyname = dst_key_name(key);
3804                         result = dns_db_find(db, keyname, ver,
3805                                              dns_rdatatype_keydata,
3806                                              DNS_DBFIND_NOWILD, 0, NULL,
3807                                              dns_fixedname_name(&fname),
3808                                              NULL, NULL);
3809                         if (result != ISC_R_SUCCESS)
3810                                 result = create_keydata(zone, db, ver, &diff,
3811                                                         sr, &keynode, &changed);
3812                         if (result != ISC_R_SUCCESS)
3813                                 break;
3814                 }
3815   skip:
3816                 result = dns_rbtnodechain_next(&chain, &foundname, origin);
3817                 if (keynode != NULL)
3818                         dns_keytable_detachkeynode(sr, &keynode);
3819         }
3820         RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3821
3822         if (result == ISC_R_NOMORE)
3823                 result = ISC_R_SUCCESS;
3824
3825         if (changed) {
3826                 /* Write changes to journal file. */
3827                 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
3828                                         zone->updatemethod));
3829                 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
3830
3831                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3832                 zone_needdump(zone, 30);
3833                 commit = ISC_TRUE;
3834         }
3835
3836  failure:
3837         if (result != ISC_R_SUCCESS &&
3838             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
3839                 dns_zone_log(zone, ISC_LOG_ERROR,
3840                              "unable to synchronize managed keys: %s",
3841                              dns_result_totext(result));
3842                 isc_time_settoepoch(&zone->refreshkeytime);
3843         }
3844         if (keynode != NULL)
3845                 dns_keytable_detachkeynode(sr, &keynode);
3846         if (sr != NULL)
3847                 dns_keytable_detach(&sr);
3848         if (ver != NULL)
3849                 dns_db_closeversion(db, &ver, commit);
3850         dns_diff_clear(&diff);
3851
3852         INSIST(ver == NULL);
3853
3854         return (result);
3855 }
3856
3857 isc_result_t
3858 dns_zone_synckeyzone(dns_zone_t *zone) {
3859         isc_result_t result;
3860         dns_db_t *db = NULL;
3861
3862         if (zone->type != dns_zone_key)
3863                 return (DNS_R_BADZONE);
3864
3865         CHECK(dns_zone_getdb(zone, &db));
3866
3867         LOCK_ZONE(zone);
3868         result = sync_keyzone(zone, db);
3869         UNLOCK_ZONE(zone);
3870
3871  failure:
3872         if (db != NULL)
3873                 dns_db_detach(&db);
3874         return (result);
3875 }
3876
3877 static void
3878 maybe_send_secure(dns_zone_t *zone) {
3879         isc_result_t result;
3880
3881         /*
3882          * We've finished loading, or else failed to load, an inline-signing
3883          * 'secure' zone.  We now need information about the status of the
3884          * 'raw' zone.  If we failed to load, then we need it to send a
3885          * copy of its database; if we succeeded, we need it to send its
3886          * serial number so that we can sync with it.  If it has not yet
3887          * loaded, we set a flag so that it will send the necessary
3888          * information when it has finished loading.
3889          */
3890         if (zone->raw->db != NULL) {
3891                 if (zone->db != NULL) {
3892                         isc_uint32_t serial;
3893                         unsigned int soacount;
3894
3895                         result = zone_get_from_db(zone->raw, zone->raw->db,
3896                                                   NULL, &soacount, &serial, NULL,
3897                                                   NULL, NULL, NULL, NULL);
3898                         if (result == ISC_R_SUCCESS && soacount > 0U)
3899                                 zone_send_secureserial(zone->raw, serial);
3900                 } else
3901                         zone_send_securedb(zone->raw, zone->raw->db);
3902
3903         } else
3904                 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
3905 }
3906
3907 static isc_boolean_t
3908 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
3909         isc_result_t result;
3910         isc_boolean_t answer = ISC_FALSE;
3911         dns_diff_t diff;
3912
3913         dns_diff_init(mctx, &diff);
3914         result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
3915         if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
3916                 answer = ISC_TRUE;
3917         dns_diff_clear(&diff);
3918         return (answer);
3919 }
3920
3921 /*
3922  * The zone is presumed to be locked.
3923  * If this is a inline_raw zone the secure version is also locked.
3924  */
3925 static isc_result_t
3926 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3927               isc_result_t result)
3928 {
3929         unsigned int soacount = 0;
3930         unsigned int nscount = 0;
3931         unsigned int errors = 0;
3932         isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3933         isc_time_t now;
3934         isc_boolean_t needdump = ISC_FALSE;
3935         isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3936         isc_boolean_t nomaster = ISC_FALSE;
3937         unsigned int options;
3938
3939         INSIST(LOCKED_ZONE(zone));
3940         if (inline_raw(zone))
3941                 INSIST(LOCKED_ZONE(zone->secure));
3942
3943         TIME_NOW(&now);
3944
3945         /*
3946          * Initiate zone transfer?  We may need a error code that
3947          * indicates that the "permanent" form does not exist.
3948          * XXX better error feedback to log.
3949          */
3950         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3951                 if (zone->type == dns_zone_slave ||
3952                     zone->type == dns_zone_stub ||
3953                     (zone->type == dns_zone_redirect &&
3954                      zone->masters == NULL)) {
3955                         if (result == ISC_R_FILENOTFOUND)
3956                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3957                                              "no master file");
3958                         else if (result != DNS_R_NOMASTERFILE)
3959                                 dns_zone_log(zone, ISC_LOG_ERROR,
3960                                              "loading from master file %s "
3961                                              "failed: %s",
3962                                              zone->masterfile,
3963                                              dns_result_totext(result));
3964                 } else if (zone->type == dns_zone_master &&
3965                            inline_secure(zone) && result == ISC_R_FILENOTFOUND)
3966                 {
3967                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
3968                                      "no master file, requesting db");
3969                         maybe_send_secure(zone);
3970                 } else {
3971                         int level = ISC_LOG_ERROR;
3972                         if (zone->type == dns_zone_key &&
3973                             result == ISC_R_FILENOTFOUND)
3974                                 level = ISC_LOG_DEBUG(1);
3975                         dns_zone_log(zone, level,
3976                                      "loading from master file %s failed: %s",
3977                                      zone->masterfile,
3978                                      dns_result_totext(result));
3979                         nomaster = ISC_TRUE;
3980                 }
3981
3982                 if (zone->type != dns_zone_key)
3983                         goto cleanup;
3984         }
3985
3986         dns_zone_log(zone, ISC_LOG_DEBUG(2),
3987                      "number of nodes in database: %u",
3988                      dns_db_nodecount(db));
3989
3990         if (result == DNS_R_SEENINCLUDE)
3991                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3992         else
3993                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3994
3995         /*
3996          * If there's no master file for a key zone, then the zone is new:
3997          * create an SOA record.  (We do this now, instead of later, so that
3998          * if there happens to be a journal file, we can roll forward from
3999          * a sane starting point.)
4000          */
4001         if (nomaster && zone->type == dns_zone_key) {
4002                 result = add_soa(zone, db);
4003                 if (result != ISC_R_SUCCESS)
4004                         goto cleanup;
4005         }
4006
4007         /*
4008          * Apply update log, if any, on initial load.
4009          */
4010         if (zone->journal != NULL &&
4011             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4012             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4013         {
4014                 if (zone->type == dns_zone_master &&
4015                     (zone->update_acl != NULL || zone->ssutable != NULL))
4016                         options = DNS_JOURNALOPT_RESIGN;
4017                 else
4018                         options = 0;
4019                 result = dns_journal_rollforward2(zone->mctx, db, options,
4020                                                   0, zone->journal);
4021                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
4022                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
4023                     result != ISC_R_RANGE) {
4024                         dns_zone_log(zone, ISC_LOG_ERROR,
4025                                      "journal rollforward failed: %s",
4026                                      dns_result_totext(result));
4027                         goto cleanup;
4028
4029
4030                 }
4031                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
4032                         dns_zone_log(zone, ISC_LOG_ERROR,
4033                                      "journal rollforward failed: "
4034                                      "journal out of sync with zone");
4035                         goto cleanup;
4036                 }
4037                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
4038                              "journal rollforward completed "
4039                              "successfully: %s",
4040                              dns_result_totext(result));
4041                 if (result == ISC_R_SUCCESS)
4042                         needdump = ISC_TRUE;
4043         }
4044
4045         /*
4046          * Obtain ns, soa and cname counts for top of zone.
4047          */
4048         INSIST(db != NULL);
4049         result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
4050                                   &refresh, &retry, &expire, &minimum,
4051                                   &errors);
4052         if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4053                 dns_zone_log(zone, ISC_LOG_ERROR,
4054                              "could not find NS and/or SOA records");
4055         }
4056
4057         /*
4058          * Check to make sure the journal is up to date, and remove the
4059          * journal file if it isn't, as we wouldn't be able to apply
4060          * updates otherwise.
4061          */
4062         if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) &&
4063             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
4064                 isc_uint32_t jserial;
4065                 dns_journal_t *journal = NULL;
4066
4067                 result = dns_journal_open(zone->mctx, zone->journal,
4068                                           DNS_JOURNAL_READ, &journal);
4069                 if (result == ISC_R_SUCCESS) {
4070                         jserial = dns_journal_last_serial(journal);
4071                         dns_journal_destroy(&journal);
4072                 } else {
4073                         jserial = serial;
4074                         result = ISC_R_SUCCESS;
4075                 }
4076
4077                 if (jserial != serial) {
4078                         dns_zone_log(zone, ISC_LOG_INFO,
4079                                      "journal file is out of date: "
4080                                      "removing journal file");
4081                         if (remove(zone->journal) < 0 && errno != ENOENT) {
4082                                 char strbuf[ISC_STRERRORSIZE];
4083                                 isc__strerror(errno, strbuf, sizeof(strbuf));
4084                                 isc_log_write(dns_lctx,
4085                                               DNS_LOGCATEGORY_GENERAL,
4086                                               DNS_LOGMODULE_ZONE,
4087                                               ISC_LOG_WARNING,
4088                                               "unable to remove journal "
4089                                               "'%s': '%s'",
4090                                               zone->journal, strbuf);
4091                         }
4092                 }
4093         }
4094
4095         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
4096
4097         /*
4098          * Master / Slave / Stub zones require both NS and SOA records at
4099          * the top of the zone.
4100          */
4101
4102         switch (zone->type) {
4103         case dns_zone_dlz:
4104         case dns_zone_master:
4105         case dns_zone_slave:
4106         case dns_zone_stub:
4107         case dns_zone_redirect:
4108                 if (soacount != 1) {
4109                         dns_zone_log(zone, ISC_LOG_ERROR,
4110                                      "has %d SOA records", soacount);
4111                         result = DNS_R_BADZONE;
4112                 }
4113                 if (nscount == 0) {
4114                         dns_zone_log(zone, ISC_LOG_ERROR,
4115                                      "has no NS records");
4116                         result = DNS_R_BADZONE;
4117                 }
4118                 if (result != ISC_R_SUCCESS)
4119                         goto cleanup;
4120                 if (zone->type == dns_zone_master && errors != 0) {
4121                         result = DNS_R_BADZONE;
4122                         goto cleanup;
4123                 }
4124                 if (zone->type != dns_zone_stub &&
4125                     zone->type != dns_zone_redirect) {
4126                         result = check_nsec3param(zone, db);
4127                         if (result != ISC_R_SUCCESS)
4128                                 goto cleanup;
4129                 }
4130                 if (zone->type == dns_zone_master &&
4131                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4132                     !integrity_checks(zone, db)) {
4133                         result = DNS_R_BADZONE;
4134                         goto cleanup;
4135                 }
4136                 if (zone->type == dns_zone_master &&
4137                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4138                     !zone_check_dup(zone, db)) {
4139                         result = DNS_R_BADZONE;
4140                         goto cleanup;
4141                 }
4142
4143                 if (zone->db != NULL) {
4144                         unsigned int oldsoacount;
4145
4146                         /*
4147                          * This is checked in zone_replacedb() for slave zones
4148                          * as they don't reload from disk.
4149                          */
4150                         result = zone_get_from_db(zone, zone->db, NULL,
4151                                                   &oldsoacount, &oldserial,
4152                                                   NULL, NULL, NULL, NULL,
4153                                                   NULL);
4154                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4155                         RUNTIME_CHECK(soacount > 0U);
4156                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4157                             !isc_serial_gt(serial, oldserial)) {
4158                                 isc_uint32_t serialmin, serialmax;
4159
4160                                 INSIST(zone->type == dns_zone_master);
4161
4162                                 if (serial == oldserial &&
4163                                     zone_unchanged(zone->db, db, zone->mctx)) {
4164                                         dns_zone_log(zone, ISC_LOG_INFO,
4165                                                      "ixfr-from-differences: "
4166                                                      "unchanged");
4167                                         return(ISC_R_SUCCESS);
4168                                 }
4169
4170                                 serialmin = (oldserial + 1) & 0xffffffffU;
4171                                 serialmax = (oldserial + 0x7fffffffU) &
4172                                              0xffffffffU;
4173                                 dns_zone_log(zone, ISC_LOG_ERROR,
4174                                              "ixfr-from-differences: "
4175                                              "new serial (%u) out of range "
4176                                              "[%u - %u]", serial, serialmin,
4177                                              serialmax);
4178                                 result = DNS_R_BADZONE;
4179                                 goto cleanup;
4180                         } else if (!isc_serial_ge(serial, oldserial))
4181                                 dns_zone_log(zone, ISC_LOG_ERROR,
4182                                              "zone serial (%u/%u) has gone "
4183                                              "backwards", serial, oldserial);
4184                         else if (serial == oldserial && !hasinclude &&
4185                                  strcmp(zone->db_argv[0], "_builtin") != 0)
4186                                 dns_zone_log(zone, ISC_LOG_ERROR,
4187                                              "zone serial (%u) unchanged. "
4188                                              "zone may fail to transfer "
4189                                              "to slaves.", serial);
4190                 }
4191
4192                 if (zone->type == dns_zone_master &&
4193                     (zone->update_acl != NULL || zone->ssutable != NULL) &&
4194                     zone->sigresigninginterval < (3 * refresh) &&
4195                     dns_db_issecure(db))
4196                 {
4197                         dns_zone_log(zone, ISC_LOG_WARNING,
4198                                      "sig-re-signing-interval less than "
4199                                      "3 * refresh.");
4200                 }
4201
4202                 zone->refresh = RANGE(refresh,
4203                                       zone->minrefresh, zone->maxrefresh);
4204                 zone->retry = RANGE(retry,
4205                                     zone->minretry, zone->maxretry);
4206                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
4207                                      DNS_MAX_EXPIRE);
4208                 zone->minimum = minimum;
4209                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4210
4211                 if (zone->type == dns_zone_slave ||
4212                     zone->type == dns_zone_stub ||
4213                     (zone->type == dns_zone_redirect &&
4214                      zone->masters != NULL)) {
4215                         isc_time_t t;
4216                         isc_uint32_t delay;
4217
4218                         result = isc_file_getmodtime(zone->journal, &t);
4219                         if (result != ISC_R_SUCCESS)
4220                                 result = isc_file_getmodtime(zone->masterfile,
4221                                                              &t);
4222                         if (result == ISC_R_SUCCESS)
4223                                 DNS_ZONE_TIME_ADD(&t, zone->expire,
4224                                                   &zone->expiretime);
4225                         else
4226                                 DNS_ZONE_TIME_ADD(&now, zone->retry,
4227                                                   &zone->expiretime);
4228
4229                         delay = isc_random_jitter(zone->retry,
4230                                                   (zone->retry * 3) / 4);
4231                         DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
4232                         if (isc_time_compare(&zone->refreshtime,
4233                                              &zone->expiretime) >= 0)
4234                                 zone->refreshtime = now;
4235                 }
4236
4237                 break;
4238
4239         case dns_zone_key:
4240                 result = sync_keyzone(zone, db);
4241                 if (result != ISC_R_SUCCESS)
4242                         goto cleanup;
4243                 break;
4244
4245         default:
4246                 UNEXPECTED_ERROR(__FILE__, __LINE__,
4247                                  "unexpected zone type %d", zone->type);
4248                 result = ISC_R_UNEXPECTED;
4249                 goto cleanup;
4250         }
4251
4252         /*
4253          * Check for weak DNSKEY's.
4254          */
4255         if (zone->type == dns_zone_master)
4256                 zone_check_dnskeys(zone, db);
4257
4258         /*
4259          * Schedule DNSSEC key refresh.
4260          */
4261         if (zone->type == dns_zone_master &&
4262             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
4263                 zone->refreshkeytime = now;
4264
4265 #if 0
4266         /* destroy notification example. */
4267         {
4268                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
4269                                                     DNS_EVENT_DBDESTROYED,
4270                                                     dns_zonemgr_dbdestroyed,
4271                                                     zone,
4272                                                     sizeof(isc_event_t));
4273                 dns_db_ondestroy(db, zone->task, &e);
4274         }
4275 #endif
4276
4277         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4278         if (zone->db != NULL) {
4279                 result = zone_replacedb(zone, db, ISC_FALSE);
4280                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4281                 if (result != ISC_R_SUCCESS)
4282                         goto cleanup;
4283         } else {
4284                 zone_attachdb(zone, db);
4285                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4286                 DNS_ZONE_SETFLAG(zone,
4287                                  DNS_ZONEFLG_LOADED|
4288                                  DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
4289                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
4290                     inline_raw(zone))
4291                 {
4292                         if (zone->secure->db == NULL)
4293                                 zone_send_securedb(zone, db);
4294                         else
4295                                 zone_send_secureserial(zone, serial);
4296                 }
4297         }
4298
4299         /*
4300          * Finished loading inline-signing zone; need to get status
4301          * from the raw side now.
4302          */
4303         if (zone->type == dns_zone_master && inline_secure(zone))
4304                 maybe_send_secure(zone);
4305
4306
4307         result = ISC_R_SUCCESS;
4308
4309         if (needdump) {
4310                 if (zone->type == dns_zone_key)
4311                         zone_needdump(zone, 30);
4312                 else
4313                         zone_needdump(zone, DNS_DUMP_DELAY);
4314         }
4315
4316         if (zone->task != NULL) {
4317                 if (zone->type == dns_zone_master) {
4318                         set_resigntime(zone);
4319                         resume_signingwithkey(zone);
4320                         resume_addnsec3chain(zone);
4321                 }
4322
4323                 if (zone->type == dns_zone_master &&
4324                     !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4325                     dns_zone_isdynamic(zone, ISC_FALSE) &&
4326                     dns_db_issecure(db)) {
4327                         dns_name_t *name;
4328                         dns_fixedname_t fixed;
4329                         dns_rdataset_t next;
4330
4331                         dns_rdataset_init(&next);
4332                         dns_fixedname_init(&fixed);
4333                         name = dns_fixedname_name(&fixed);
4334
4335                         result = dns_db_getsigningtime(db, &next, name);
4336                         if (result == ISC_R_SUCCESS) {
4337                                 isc_stdtime_t timenow;
4338                                 char namebuf[DNS_NAME_FORMATSIZE];
4339                                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4340
4341                                 isc_stdtime_get(&timenow);
4342                                 dns_name_format(name, namebuf, sizeof(namebuf));
4343                                 dns_rdatatype_format(next.covers,
4344                                                      typebuf, sizeof(typebuf));
4345                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
4346                                              "next resign: %s/%s in %d seconds",
4347                                              namebuf, typebuf,
4348                                              next.resign - timenow -
4349                                              zone->sigresigninginterval);
4350                                 dns_rdataset_disassociate(&next);
4351                         } else
4352                                 dns_zone_log(zone, ISC_LOG_WARNING,
4353                                              "signed dynamic zone has no "
4354                                              "resign event scheduled");
4355                 }
4356
4357                 zone_settimer(zone, &now);
4358         }
4359
4360         if (! dns_db_ispersistent(db))
4361                 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
4362                              dns_db_issecure(db) ? " (DNSSEC signed)" : "");
4363
4364         zone->loadtime = loadtime;
4365         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
4366         return (result);
4367
4368  cleanup:
4369         if (zone->type == dns_zone_slave ||
4370             zone->type == dns_zone_stub ||
4371             zone->type == dns_zone_key ||
4372             (zone->type == dns_zone_redirect && zone->masters != NULL)) {
4373                 if (result != ISC_R_NOMEMORY) {
4374                         if (zone->journal != NULL)
4375                                 zone_saveunique(zone, zone->journal,
4376                                                 "jn-XXXXXXXX");
4377                         if (zone->masterfile != NULL)
4378                                 zone_saveunique(zone, zone->masterfile,
4379                                                 "db-XXXXXXXX");
4380                 }
4381
4382                 /* Mark the zone for immediate refresh. */
4383                 zone->refreshtime = now;
4384                 if (zone->task != NULL)
4385                         zone_settimer(zone, &now);
4386                 result = ISC_R_SUCCESS;
4387         } else if (zone->type == dns_zone_master ||
4388                    zone->type == dns_zone_redirect) {
4389                 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND))
4390                         dns_zone_log(zone, ISC_LOG_ERROR,
4391                                      "not loaded due to errors.");
4392                 else if (zone->type == dns_zone_master)
4393                         result = ISC_R_SUCCESS;
4394         }
4395
4396         return (result);
4397 }
4398
4399 static isc_boolean_t
4400 exit_check(dns_zone_t *zone) {
4401         REQUIRE(LOCKED_ZONE(zone));
4402
4403         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
4404                 /*
4405                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
4406                  */
4407                 INSIST(isc_refcount_current(&zone->erefs) == 0);
4408                 return (ISC_TRUE);
4409         }
4410         return (ISC_FALSE);
4411 }
4412
4413 static isc_boolean_t
4414 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
4415               dns_name_t *name, isc_boolean_t logit)
4416 {
4417         isc_result_t result;
4418         char namebuf[DNS_NAME_FORMATSIZE];
4419         char altbuf[DNS_NAME_FORMATSIZE];
4420         dns_fixedname_t fixed;
4421         dns_name_t *foundname;
4422         int level;
4423
4424         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
4425                 return (ISC_TRUE);
4426
4427         if (zone->type == dns_zone_master)
4428                 level = ISC_LOG_ERROR;
4429         else
4430                 level = ISC_LOG_WARNING;
4431
4432         dns_fixedname_init(&fixed);
4433         foundname = dns_fixedname_name(&fixed);
4434
4435         result = dns_db_find(db, name, version, dns_rdatatype_a,
4436                              0, 0, NULL, foundname, NULL, NULL);
4437         if (result == ISC_R_SUCCESS)
4438                 return (ISC_TRUE);
4439
4440         if (result == DNS_R_NXRRSET) {
4441                 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
4442                                      0, 0, NULL, foundname, NULL, NULL);
4443                 if (result == ISC_R_SUCCESS)
4444                         return (ISC_TRUE);
4445         }
4446
4447         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
4448             result == DNS_R_EMPTYNAME) {
4449                 if (logit) {
4450                         dns_name_format(name, namebuf, sizeof namebuf);
4451                         dns_zone_log(zone, level, "NS '%s' has no address "
4452                                      "records (A or AAAA)", namebuf);
4453                 }
4454                 return (ISC_FALSE);
4455         }
4456
4457         if (result == DNS_R_CNAME) {
4458                 if (logit) {
4459                         dns_name_format(name, namebuf, sizeof namebuf);
4460                         dns_zone_log(zone, level, "NS '%s' is a CNAME "
4461                                      "(illegal)", namebuf);
4462                 }
4463                 return (ISC_FALSE);
4464         }
4465
4466         if (result == DNS_R_DNAME) {
4467                 if (logit) {
4468                         dns_name_format(name, namebuf, sizeof namebuf);
4469                         dns_name_format(foundname, altbuf, sizeof altbuf);
4470                         dns_zone_log(zone, level, "NS '%s' is below a DNAME "
4471                                      "'%s' (illegal)", namebuf, altbuf);
4472                 }
4473                 return (ISC_FALSE);
4474         }
4475
4476         return (ISC_TRUE);
4477 }
4478
4479 static isc_result_t
4480 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
4481                  dns_dbversion_t *version, unsigned int *nscount,
4482                  unsigned int *errors, isc_boolean_t logit)
4483 {
4484         isc_result_t result;
4485         unsigned int count = 0;
4486         unsigned int ecount = 0;
4487         dns_rdataset_t rdataset;
4488         dns_rdata_t rdata;
4489         dns_rdata_ns_t ns;
4490
4491         dns_rdataset_init(&rdataset);
4492         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
4493                                      dns_rdatatype_none, 0, &rdataset, NULL);
4494         if (result == ISC_R_NOTFOUND) {
4495                 INSIST(!dns_rdataset_isassociated(&rdataset));
4496                 goto success;
4497         }
4498         if (result != ISC_R_SUCCESS) {
4499                 INSIST(!dns_rdataset_isassociated(&rdataset));
4500                 goto invalidate_rdataset;
4501         }
4502
4503         result = dns_rdataset_first(&rdataset);
4504         while (result == ISC_R_SUCCESS) {
4505                 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
4506                     (zone->type == dns_zone_master ||
4507                      zone->type == dns_zone_slave)) {
4508                         dns_rdata_init(&rdata);
4509                         dns_rdataset_current(&rdataset, &rdata);
4510                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
4511                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4512                         if (dns_name_issubdomain(&ns.name, &zone->origin) &&
4513                             !zone_check_ns(zone, db, version, &ns.name, logit))
4514                                 ecount++;
4515                 }
4516                 count++;
4517                 result = dns_rdataset_next(&rdataset);
4518         }
4519         dns_rdataset_disassociate(&rdataset);
4520
4521  success:
4522         if (nscount != NULL)
4523                 *nscount = count;
4524         if (errors != NULL)
4525                 *errors = ecount;
4526
4527         result = ISC_R_SUCCESS;
4528
4529  invalidate_rdataset:
4530         dns_rdataset_invalidate(&rdataset);
4531
4532         return (result);
4533 }
4534
4535 static isc_result_t
4536 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
4537                  unsigned int *soacount,
4538                  isc_uint32_t *serial, isc_uint32_t *refresh,
4539                  isc_uint32_t *retry, isc_uint32_t *expire,
4540                  isc_uint32_t *minimum)
4541 {
4542         isc_result_t result;
4543         unsigned int count;
4544         dns_rdataset_t rdataset;
4545         dns_rdata_t rdata = DNS_RDATA_INIT;
4546         dns_rdata_soa_t soa;
4547
4548         dns_rdataset_init(&rdataset);
4549         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
4550                                      dns_rdatatype_none, 0, &rdataset, NULL);
4551         if (result == ISC_R_NOTFOUND) {
4552                 INSIST(!dns_rdataset_isassociated(&rdataset));
4553                 if (soacount != NULL)
4554                         *soacount = 0;
4555                 if (serial != NULL)
4556                         *serial = 0;
4557                 if (refresh != NULL)
4558                         *refresh = 0;
4559                 if (retry != NULL)
4560                         *retry = 0;
4561                 if (expire != NULL)
4562                         *expire = 0;
4563                 if (minimum != NULL)
4564                         *minimum = 0;
4565                 result = ISC_R_SUCCESS;
4566                 goto invalidate_rdataset;
4567         }
4568         if (result != ISC_R_SUCCESS) {
4569                 INSIST(!dns_rdataset_isassociated(&rdataset));
4570                 goto invalidate_rdataset;
4571         }
4572
4573         count = 0;
4574         result = dns_rdataset_first(&rdataset);
4575         while (result == ISC_R_SUCCESS) {
4576                 dns_rdata_init(&rdata);
4577                 dns_rdataset_current(&rdataset, &rdata);
4578                 count++;
4579                 if (count == 1) {
4580                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
4581                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4582                 }
4583
4584                 result = dns_rdataset_next(&rdataset);
4585                 dns_rdata_reset(&rdata);
4586         }
4587         dns_rdataset_disassociate(&rdataset);
4588
4589         if (soacount != NULL)
4590                 *soacount = count;
4591
4592         if (count > 0) {
4593                 if (serial != NULL)
4594                         *serial = soa.serial;
4595                 if (refresh != NULL)
4596                         *refresh = soa.refresh;
4597                 if (retry != NULL)
4598                         *retry = soa.retry;
4599                 if (expire != NULL)
4600                         *expire = soa.expire;
4601                 if (minimum != NULL)
4602                         *minimum = soa.minimum;
4603         } else {
4604                 if (soacount != NULL)
4605                         *soacount = 0;
4606                 if (serial != NULL)
4607                         *serial = 0;
4608                 if (refresh != NULL)
4609                         *refresh = 0;
4610                 if (retry != NULL)
4611                         *retry = 0;
4612                 if (expire != NULL)
4613                         *expire = 0;
4614                 if (minimum != NULL)
4615                         *minimum = 0;
4616         }
4617
4618         result = ISC_R_SUCCESS;
4619
4620  invalidate_rdataset:
4621         dns_rdataset_invalidate(&rdataset);
4622
4623         return (result);
4624 }
4625
4626 /*
4627  * zone must be locked.
4628  */
4629 static isc_result_t
4630 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
4631                  unsigned int *soacount, isc_uint32_t *serial,
4632                  isc_uint32_t *refresh, isc_uint32_t *retry,
4633                  isc_uint32_t *expire, isc_uint32_t *minimum,
4634                  unsigned int *errors)
4635 {
4636         isc_result_t result;
4637         isc_result_t answer = ISC_R_SUCCESS;
4638         dns_dbversion_t *version = NULL;
4639         dns_dbnode_t *node;
4640
4641         REQUIRE(db != NULL);
4642         REQUIRE(zone != NULL);
4643
4644         dns_db_currentversion(db, &version);
4645
4646         if (nscount != NULL)
4647                 *nscount = 0;
4648         if (soacount != NULL)
4649                 *soacount = 0;
4650         if (serial != NULL)
4651                 *serial = 0;
4652         if (refresh != NULL)
4653                 *refresh = 0;
4654         if (retry != NULL)
4655                 *retry = 0;
4656         if (expire != NULL)
4657                 *expire = 0;
4658         if (errors != NULL)
4659                 *errors = 0;
4660
4661         node = NULL;
4662         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
4663         if (result != ISC_R_SUCCESS) {
4664                 answer = result;
4665                 goto closeversion;
4666         }
4667
4668         if (nscount != NULL || errors != NULL) {
4669                 result = zone_count_ns_rr(zone, db, node, version,
4670                                           nscount, errors, ISC_TRUE);
4671                 if (result != ISC_R_SUCCESS)
4672                         answer = result;
4673         }
4674
4675         if (soacount != NULL || serial != NULL || refresh != NULL
4676             || retry != NULL || expire != NULL || minimum != NULL) {
4677                 result = zone_load_soa_rr(db, node, version, soacount,
4678                                           serial, refresh, retry, expire,
4679                                           minimum);
4680                 if (result != ISC_R_SUCCESS)
4681                         answer = result;
4682         }
4683
4684         dns_db_detachnode(db, &node);
4685  closeversion:
4686         dns_db_closeversion(db, &version, ISC_FALSE);
4687
4688         return (answer);
4689 }
4690
4691 void
4692 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
4693         REQUIRE(DNS_ZONE_VALID(source));
4694         REQUIRE(target != NULL && *target == NULL);
4695         isc_refcount_increment(&source->erefs, NULL);
4696         *target = source;
4697 }
4698
4699 void
4700 dns_zone_detach(dns_zone_t **zonep) {
4701         dns_zone_t *zone;
4702         dns_zone_t *raw = NULL;
4703         dns_zone_t *secure = NULL;
4704         unsigned int refs;
4705         isc_boolean_t free_now = ISC_FALSE;
4706
4707         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4708
4709         zone = *zonep;
4710
4711         isc_refcount_decrement(&zone->erefs, &refs);
4712
4713         if (refs == 0) {
4714                 LOCK_ZONE(zone);
4715                 /*
4716                  * We just detached the last external reference.
4717                  */
4718                 if (zone->task != NULL) {
4719                         /*
4720                          * This zone is being managed.  Post
4721                          * its control event and let it clean
4722                          * up synchronously in the context of
4723                          * its task.
4724                          */
4725                         isc_event_t *ev = &zone->ctlevent;
4726                         isc_task_send(zone->task, &ev);
4727                 } else {
4728                         /*
4729                          * This zone is not being managed; it has
4730                          * no task and can have no outstanding
4731                          * events.  Free it immediately.
4732                          */
4733                         /*
4734                          * Unmanaged zones should not have non-null views;
4735                          * we have no way of detaching from the view here
4736                          * without causing deadlock because this code is called
4737                          * with the view already locked.
4738                          */
4739                         INSIST(zone->view == NULL);
4740                         free_now = ISC_TRUE;
4741                         raw = zone->raw;
4742                         zone->raw = NULL;
4743                         secure = zone->secure;
4744                         zone->secure = NULL;
4745                 }
4746                 UNLOCK_ZONE(zone);
4747         }
4748         *zonep = NULL;
4749         if (free_now) {
4750                 if (raw != NULL)
4751                         dns_zone_detach(&raw);
4752                 if (secure != NULL)
4753                         dns_zone_idetach(&secure);
4754                 zone_free(zone);
4755         }
4756 }
4757
4758 void
4759 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4760         REQUIRE(DNS_ZONE_VALID(source));
4761         REQUIRE(target != NULL && *target == NULL);
4762         LOCK_ZONE(source);
4763         zone_iattach(source, target);
4764         UNLOCK_ZONE(source);
4765 }
4766
4767 static void
4768 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
4769
4770         /*
4771          * 'source' locked by caller.
4772          */
4773         REQUIRE(LOCKED_ZONE(source));
4774         REQUIRE(DNS_ZONE_VALID(source));
4775         REQUIRE(target != NULL && *target == NULL);
4776         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
4777         source->irefs++;
4778         INSIST(source->irefs != 0);
4779         *target = source;
4780 }
4781
4782 static void
4783 zone_idetach(dns_zone_t **zonep) {
4784         dns_zone_t *zone;
4785
4786         /*
4787          * 'zone' locked by caller.
4788          */
4789         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4790         zone = *zonep;
4791         REQUIRE(LOCKED_ZONE(*zonep));
4792         *zonep = NULL;
4793
4794         INSIST(zone->irefs > 0);
4795         zone->irefs--;
4796         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4797 }
4798
4799 void
4800 dns_zone_idetach(dns_zone_t **zonep) {
4801         dns_zone_t *zone;
4802         isc_boolean_t free_needed;
4803
4804         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4805         zone = *zonep;
4806         *zonep = NULL;
4807
4808         LOCK_ZONE(zone);
4809         INSIST(zone->irefs > 0);
4810         zone->irefs--;
4811         free_needed = exit_check(zone);
4812         UNLOCK_ZONE(zone);
4813         if (free_needed)
4814                 zone_free(zone);
4815 }
4816
4817 isc_mem_t *
4818 dns_zone_getmctx(dns_zone_t *zone) {
4819         REQUIRE(DNS_ZONE_VALID(zone));
4820
4821         return (zone->mctx);
4822 }
4823
4824 dns_zonemgr_t *
4825 dns_zone_getmgr(dns_zone_t *zone) {
4826         REQUIRE(DNS_ZONE_VALID(zone));
4827
4828         return (zone->zmgr);
4829 }
4830
4831 void
4832 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4833         REQUIRE(DNS_ZONE_VALID(zone));
4834
4835         LOCK_ZONE(zone);
4836         if (value)
4837                 DNS_ZONE_SETFLAG(zone, flags);
4838         else
4839                 DNS_ZONE_CLRFLAG(zone, flags);
4840         UNLOCK_ZONE(zone);
4841 }
4842
4843 void
4844 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4845 {
4846         REQUIRE(DNS_ZONE_VALID(zone));
4847
4848         LOCK_ZONE(zone);
4849         if (value)
4850                 zone->options |= option;
4851         else
4852                 zone->options &= ~option;
4853         UNLOCK_ZONE(zone);
4854 }
4855
4856 unsigned int
4857 dns_zone_getoptions(dns_zone_t *zone) {
4858
4859         REQUIRE(DNS_ZONE_VALID(zone));
4860
4861         return (zone->options);
4862 }
4863
4864 void
4865 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4866 {
4867         REQUIRE(DNS_ZONE_VALID(zone));
4868
4869         LOCK_ZONE(zone);
4870         if (value)
4871                 zone->keyopts |= keyopt;
4872         else
4873                 zone->keyopts &= ~keyopt;
4874         UNLOCK_ZONE(zone);
4875 }
4876
4877 unsigned int
4878 dns_zone_getkeyopts(dns_zone_t *zone) {
4879
4880         REQUIRE(DNS_ZONE_VALID(zone));
4881
4882         return (zone->keyopts);
4883 }
4884
4885 isc_result_t
4886 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4887         REQUIRE(DNS_ZONE_VALID(zone));
4888
4889         LOCK_ZONE(zone);
4890         zone->xfrsource4 = *xfrsource;
4891         UNLOCK_ZONE(zone);
4892
4893         return (ISC_R_SUCCESS);
4894 }
4895
4896 isc_sockaddr_t *
4897 dns_zone_getxfrsource4(dns_zone_t *zone) {
4898         REQUIRE(DNS_ZONE_VALID(zone));
4899         return (&zone->xfrsource4);
4900 }
4901
4902 isc_result_t
4903 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4904         REQUIRE(DNS_ZONE_VALID(zone));
4905
4906         LOCK_ZONE(zone);
4907         zone->xfrsource6 = *xfrsource;
4908         UNLOCK_ZONE(zone);
4909
4910         return (ISC_R_SUCCESS);
4911 }
4912
4913 isc_sockaddr_t *
4914 dns_zone_getxfrsource6(dns_zone_t *zone) {
4915         REQUIRE(DNS_ZONE_VALID(zone));
4916         return (&zone->xfrsource6);
4917 }
4918
4919 isc_result_t
4920 dns_zone_setaltxfrsource4(dns_zone_t *zone,
4921                           const isc_sockaddr_t *altxfrsource)
4922 {
4923         REQUIRE(DNS_ZONE_VALID(zone));
4924
4925         LOCK_ZONE(zone);
4926         zone->altxfrsource4 = *altxfrsource;
4927         UNLOCK_ZONE(zone);
4928
4929         return (ISC_R_SUCCESS);
4930 }
4931
4932 isc_sockaddr_t *
4933 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4934         REQUIRE(DNS_ZONE_VALID(zone));
4935         return (&zone->altxfrsource4);
4936 }
4937
4938 isc_result_t
4939 dns_zone_setaltxfrsource6(dns_zone_t *zone,
4940                           const isc_sockaddr_t *altxfrsource)
4941 {
4942         REQUIRE(DNS_ZONE_VALID(zone));
4943
4944         LOCK_ZONE(zone);
4945         zone->altxfrsource6 = *altxfrsource;
4946         UNLOCK_ZONE(zone);
4947
4948         return (ISC_R_SUCCESS);
4949 }
4950
4951 isc_sockaddr_t *
4952 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4953         REQUIRE(DNS_ZONE_VALID(zone));
4954         return (&zone->altxfrsource6);
4955 }
4956
4957 isc_result_t
4958 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4959         REQUIRE(DNS_ZONE_VALID(zone));
4960
4961         LOCK_ZONE(zone);
4962         zone->notifysrc4 = *notifysrc;
4963         UNLOCK_ZONE(zone);
4964
4965         return (ISC_R_SUCCESS);
4966 }
4967
4968 isc_sockaddr_t *
4969 dns_zone_getnotifysrc4(dns_zone_t *zone) {
4970         REQUIRE(DNS_ZONE_VALID(zone));
4971         return (&zone->notifysrc4);
4972 }
4973
4974 isc_result_t
4975 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4976         REQUIRE(DNS_ZONE_VALID(zone));
4977
4978         LOCK_ZONE(zone);
4979         zone->notifysrc6 = *notifysrc;
4980         UNLOCK_ZONE(zone);
4981
4982         return (ISC_R_SUCCESS);
4983 }
4984
4985 isc_sockaddr_t *
4986 dns_zone_getnotifysrc6(dns_zone_t *zone) {
4987         REQUIRE(DNS_ZONE_VALID(zone));
4988         return (&zone->notifysrc6);
4989 }
4990
4991 static isc_boolean_t
4992 same_addrs(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4993              isc_uint32_t count)
4994 {
4995         unsigned int i;
4996
4997         for (i = 0; i < count; i++)
4998                 if (!isc_sockaddr_equal(&old[i], &new[i]))
4999                         return (ISC_FALSE);
5000         return (ISC_TRUE);
5001 }
5002
5003 static isc_boolean_t
5004 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
5005         unsigned int i;
5006
5007         if (old == NULL && new == NULL)
5008                 return (ISC_TRUE);
5009         if (old == NULL || new == NULL)
5010                 return (ISC_FALSE);
5011
5012         for (i = 0; i < count; i++) {
5013                 if (old[i] == NULL && new[i] == NULL)
5014                         continue;
5015                 if (old[i] == NULL || new[i] == NULL ||
5016                      !dns_name_equal(old[i], new[i]))
5017                         return (ISC_FALSE);
5018         }
5019         return (ISC_TRUE);
5020 }
5021
5022 static void
5023 clear_addresskeylist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
5024                      unsigned int *countp, isc_mem_t *mctx)
5025 {
5026         unsigned int count;
5027         isc_sockaddr_t *addrs;
5028         dns_name_t **keynames;
5029
5030         REQUIRE(countp != NULL && addrsp != NULL && keynamesp != NULL);
5031
5032         count = *countp;
5033         *countp = 0;
5034         addrs = *addrsp;
5035         *addrsp = NULL;
5036         keynames = *keynamesp;
5037         *keynamesp = NULL;
5038
5039         if (addrs != NULL)
5040                 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
5041
5042         if (keynames != NULL) {
5043                 unsigned int i;
5044                 for (i = 0; i < count; i++) {
5045                         if (keynames[i] != NULL) {
5046                                 dns_name_free(keynames[i], mctx);
5047                                 isc_mem_put(mctx, keynames[i],
5048                                             sizeof(dns_name_t));
5049                                 keynames[i] = NULL;
5050                         }
5051                 }
5052                 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
5053         }
5054 }
5055
5056 static isc_result_t
5057 set_addrkeylist(unsigned int count,
5058                 const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
5059                 dns_name_t **names, dns_name_t ***newnamesp,
5060                 isc_mem_t *mctx)
5061 {
5062         isc_result_t result;
5063         isc_sockaddr_t *newaddrs = NULL;
5064         dns_name_t **newnames = NULL;
5065         unsigned int i;
5066
5067         REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
5068         REQUIRE(newnamesp != NULL && *newnamesp == NULL);
5069
5070         newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
5071         if (newaddrs == NULL)
5072                 return (ISC_R_NOMEMORY);
5073         memmove(newaddrs, addrs, count * sizeof(*newaddrs));
5074
5075         newnames = NULL;
5076         if (names != NULL) {
5077                 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
5078                 if (newnames == NULL) {
5079                         isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5080                         return (ISC_R_NOMEMORY);
5081                 }
5082                 for (i = 0; i < count; i++)
5083                         newnames[i] = NULL;
5084                 for (i = 0; i < count; i++) {
5085                         if (names[i] != NULL) {
5086                                 newnames[i] = isc_mem_get(mctx,
5087                                                          sizeof(dns_name_t));
5088                                 if (newnames[i] == NULL)
5089                                         goto allocfail;
5090                                 dns_name_init(newnames[i], NULL);
5091                                 result = dns_name_dup(names[i], mctx,
5092                                                       newnames[i]);
5093                                 if (result != ISC_R_SUCCESS) {
5094                                 allocfail:
5095                                         for (i = 0; i < count; i++)
5096                                                 if (newnames[i] != NULL)
5097                                                         dns_name_free(
5098                                                                newnames[i],
5099                                                                mctx);
5100                                         isc_mem_put(mctx, newaddrs,
5101                                                     count * sizeof(*newaddrs));
5102                                         isc_mem_put(mctx, newnames,
5103                                                     count * sizeof(*newnames));
5104                                         return (ISC_R_NOMEMORY);
5105                                 }
5106                         }
5107                 }
5108         }
5109
5110         *newaddrsp = newaddrs;
5111         *newnamesp = newnames;
5112         return (ISC_R_SUCCESS);
5113 }
5114
5115 isc_result_t
5116 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
5117                        isc_uint32_t count)
5118 {
5119         return (dns_zone_setalsonotifywithkeys(zone, notify, NULL, count));
5120 }
5121
5122 isc_result_t
5123 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5124                                dns_name_t **keynames, isc_uint32_t count)
5125 {
5126         isc_result_t result;
5127         isc_sockaddr_t *newaddrs = NULL;
5128         dns_name_t **newnames = NULL;
5129
5130         REQUIRE(DNS_ZONE_VALID(zone));
5131         REQUIRE(count == 0 || notify != NULL);
5132         if (keynames != NULL)
5133                 REQUIRE(count != 0);
5134
5135         LOCK_ZONE(zone);
5136
5137         if (count == zone->notifycnt &&
5138             same_addrs(zone->notify, notify, count) &&
5139             same_keynames(zone->notifykeynames, keynames, count))
5140                 goto unlock;
5141
5142         clear_addresskeylist(&zone->notify, &zone->notifykeynames,
5143                              &zone->notifycnt, zone->mctx);
5144
5145         if (count == 0)
5146                 goto unlock;
5147
5148         /*
5149          * Set up the notify and notifykey lists
5150          */
5151         result = set_addrkeylist(count, notify, &newaddrs,
5152                                  keynames, &newnames, zone->mctx);
5153         if (result != ISC_R_SUCCESS)
5154                 goto unlock;
5155
5156         /*
5157          * Everything is ok so attach to the zone.
5158          */
5159         zone->notify = newaddrs;
5160         zone->notifykeynames = newnames;
5161         zone->notifycnt = count;
5162  unlock:
5163         UNLOCK_ZONE(zone);
5164         return (ISC_R_SUCCESS);
5165 }
5166
5167 isc_result_t
5168 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
5169                     isc_uint32_t count)
5170 {
5171         isc_result_t result;
5172
5173         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
5174         return (result);
5175 }
5176
5177 isc_result_t
5178 dns_zone_setmasterswithkeys(dns_zone_t *zone,
5179                             const isc_sockaddr_t *masters,
5180                             dns_name_t **keynames,
5181                             isc_uint32_t count)
5182 {
5183         isc_result_t result = ISC_R_SUCCESS;
5184         isc_sockaddr_t *newaddrs = NULL;
5185         dns_name_t **newnames = NULL;
5186         isc_boolean_t *newok;
5187         unsigned int i;
5188
5189         REQUIRE(DNS_ZONE_VALID(zone));
5190         REQUIRE(count == 0 || masters != NULL);
5191         if (keynames != NULL) {
5192                 REQUIRE(count != 0);
5193         }
5194
5195         LOCK_ZONE(zone);
5196         /*
5197          * The refresh code assumes that 'masters' wouldn't change under it.
5198          * If it will change then kill off any current refresh in progress
5199          * and update the masters info.  If it won't change then we can just
5200          * unlock and exit.
5201          */
5202         if (count != zone->masterscnt ||
5203             !same_addrs(zone->masters, masters, count) ||
5204             !same_keynames(zone->masterkeynames, keynames, count)) {
5205                 if (zone->request != NULL)
5206                         dns_request_cancel(zone->request);
5207         } else
5208                 goto unlock;
5209
5210         /*
5211          * This needs to happen before clear_addresskeylist() sets
5212          * zone->masterscnt to 0:
5213          */
5214         if (zone->mastersok != NULL) {
5215                 isc_mem_put(zone->mctx, zone->mastersok,
5216                             zone->masterscnt * sizeof(isc_boolean_t));
5217                 zone->mastersok = NULL;
5218         }
5219         clear_addresskeylist(&zone->masters, &zone->masterkeynames,
5220                              &zone->masterscnt, zone->mctx);
5221         /*
5222          * If count == 0, don't allocate any space for masters, mastersok or
5223          * keynames so internally, those pointers are NULL if count == 0
5224          */
5225         if (count == 0)
5226                 goto unlock;
5227
5228         /*
5229          * mastersok must contain count elements
5230          */
5231         newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
5232         if (newok == NULL) {
5233                 result = ISC_R_NOMEMORY;
5234                 isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
5235                 goto unlock;
5236         };
5237         for (i = 0; i < count; i++)
5238                 newok[i] = ISC_FALSE;
5239
5240         /*
5241          * Now set up the masters and masterkey lists
5242          */
5243         result = set_addrkeylist(count, masters, &newaddrs,
5244                                  keynames, &newnames, zone->mctx);
5245         if (result != ISC_R_SUCCESS) {
5246                 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
5247                 goto unlock;
5248         }
5249
5250         /*
5251          * Everything is ok so attach to the zone.
5252          */
5253         zone->curmaster = 0;
5254         zone->mastersok = newok;
5255         zone->masters = newaddrs;
5256         zone->masterkeynames = newnames;
5257         zone->masterscnt = count;
5258         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
5259
5260  unlock:
5261         UNLOCK_ZONE(zone);
5262         return (result);
5263 }
5264
5265 isc_result_t
5266 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
5267         isc_result_t result = ISC_R_SUCCESS;
5268
5269         REQUIRE(DNS_ZONE_VALID(zone));
5270
5271         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5272         if (zone->db == NULL)
5273                 result = DNS_R_NOTLOADED;
5274         else
5275                 dns_db_attach(zone->db, dpb);
5276         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5277
5278         return (result);
5279 }
5280
5281 void
5282 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
5283         REQUIRE(DNS_ZONE_VALID(zone));
5284         REQUIRE(zone->type == dns_zone_staticstub);
5285
5286         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5287         REQUIRE(zone->db == NULL);
5288         dns_db_attach(db, &zone->db);
5289         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5290 }
5291
5292 /*
5293  * Co-ordinates the starting of routine jobs.
5294  */
5295
5296 void
5297 dns_zone_maintenance(dns_zone_t *zone) {
5298         const char me[] = "dns_zone_maintenance";
5299         isc_time_t now;
5300
5301         REQUIRE(DNS_ZONE_VALID(zone));
5302         ENTER;
5303
5304         LOCK_ZONE(zone);
5305         TIME_NOW(&now);
5306         zone_settimer(zone, &now);
5307         UNLOCK_ZONE(zone);
5308 }
5309
5310 static inline isc_boolean_t
5311 was_dumping(dns_zone_t *zone) {
5312         isc_boolean_t dumping;
5313
5314         REQUIRE(LOCKED_ZONE(zone));
5315
5316         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
5317         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
5318         if (!dumping) {
5319                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
5320                 isc_time_settoepoch(&zone->dumptime);
5321         }
5322         return (dumping);
5323 }
5324
5325 static isc_result_t
5326 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
5327                isc_mem_t *mctx, unsigned int maxkeys,
5328                dst_key_t **keys, unsigned int *nkeys)
5329 {
5330         isc_result_t result;
5331         dns_dbnode_t *node = NULL;
5332         const char *directory = dns_zone_getkeydirectory(zone);
5333
5334         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
5335         memset(keys, 0, sizeof(*keys) * maxkeys);
5336         result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
5337                                           directory, mctx, maxkeys, keys,
5338                                           nkeys);
5339         if (result == ISC_R_NOTFOUND)
5340                 result = ISC_R_SUCCESS;
5341  failure:
5342         if (node != NULL)
5343                 dns_db_detachnode(db, &node);
5344         return (result);
5345 }
5346
5347 static isc_result_t
5348 offline(dns_db_t *db, dns_dbversion_t *ver, zonediff_t *zonediff,
5349         dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
5350 {
5351         isc_result_t result;
5352
5353         if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
5354                 return (ISC_R_SUCCESS);
5355         result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
5356                                name, ttl, rdata);
5357         if (result != ISC_R_SUCCESS)
5358                 return (result);
5359         rdata->flags |= DNS_RDATA_OFFLINE;
5360         result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
5361                                name, ttl, rdata);
5362         zonediff->offline = ISC_TRUE;
5363         return (result);
5364 }
5365
5366 static void
5367 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
5368 {
5369         unsigned int delta;
5370         char timebuf[80];
5371
5372         zone->key_expiry = when;
5373         if (when <= now) {
5374                 dns_zone_log(zone, ISC_LOG_ERROR,
5375                              "DNSKEY RRSIG(s) have expired");
5376                 isc_time_settoepoch(&zone->keywarntime);
5377         } else if (when < now + 7 * 24 * 3600) {
5378                 isc_time_t t;
5379                 isc_time_set(&t, when, 0);
5380                 isc_time_formattimestamp(&t, timebuf, 80);
5381                 dns_zone_log(zone, ISC_LOG_WARNING,
5382                              "DNSKEY RRSIG(s) will expire within 7 days: %s",
5383                              timebuf);
5384                 delta = when - now;
5385                 delta--;                /* loop prevention */
5386                 delta /= 24 * 3600;     /* to whole days */
5387                 delta *= 24 * 3600;     /* to seconds */
5388                 isc_time_set(&zone->keywarntime, when - delta, 0);
5389         }  else {
5390                 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
5391                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
5392                 dns_zone_log(zone, ISC_LOG_NOTICE,
5393                              "setting keywarntime to %s", timebuf);
5394         }
5395 }
5396
5397 /*
5398  * Helper function to del_sigs(). We don't want to delete RRSIGs that
5399  * have no new key.
5400  */
5401 static isc_boolean_t
5402 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
5403           isc_boolean_t *warn)
5404 {
5405         unsigned int i = 0;
5406         isc_boolean_t have_ksk = ISC_FALSE, have_zsk = ISC_FALSE;
5407         isc_boolean_t have_pksk = ISC_FALSE, have_pzsk = ISC_FALSE;
5408
5409         for (i = 0; i < nkeys; i++) {
5410                 if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
5411                         continue;
5412                 if (dst_key_isprivate(keys[i])) {
5413                         if (KSK(keys[i]))
5414                                 have_ksk = have_pksk = ISC_TRUE;
5415                         else
5416                                 have_zsk = have_pzsk = ISC_TRUE;
5417                 } else {
5418                         if (KSK(keys[i]))
5419                                 have_ksk = ISC_TRUE;
5420                         else
5421                                 have_zsk = ISC_TRUE;
5422                 }
5423         }
5424
5425         if (have_zsk && have_ksk && !have_pzsk)
5426                 *warn = ISC_TRUE;
5427
5428         /*
5429          * It's okay to delete a signature if there is an active key
5430          * with the same algorithm to replace it.
5431          */
5432         if (have_pksk || have_pzsk)
5433                 return (ISC_TRUE);
5434
5435         /*
5436          * Failing that, it is *not* okay to delete a signature
5437          * if the associated public key is still in the DNSKEY RRset
5438          */
5439         for (i = 0; i < nkeys; i++) {
5440                 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
5441                     (rrsig_ptr->keyid == dst_key_id(keys[i])))
5442                         return (ISC_FALSE);
5443         }
5444
5445         /*
5446          * But if the key is gone, then go ahead.
5447          */
5448         return (ISC_TRUE);
5449 }
5450
5451 /*
5452  * Delete expired RRsigs and any RRsigs we are about to re-sign.
5453  * See also update.c:del_keysigs().
5454  */
5455 static isc_result_t
5456 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5457          dns_rdatatype_t type, zonediff_t *zonediff, dst_key_t **keys,
5458          unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
5459 {
5460         isc_result_t result;
5461         dns_dbnode_t *node = NULL;
5462         dns_rdataset_t rdataset;
5463         unsigned int i;
5464         dns_rdata_rrsig_t rrsig;
5465         isc_boolean_t found;
5466         isc_int64_t timewarn = 0, timemaybe = 0;
5467
5468         dns_rdataset_init(&rdataset);
5469
5470         if (type == dns_rdatatype_nsec3)
5471                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5472         else
5473                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
5474         if (result == ISC_R_NOTFOUND)
5475                 return (ISC_R_SUCCESS);
5476         if (result != ISC_R_SUCCESS)
5477                 goto failure;
5478         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
5479                                      (isc_stdtime_t) 0, &rdataset, NULL);
5480         dns_db_detachnode(db, &node);
5481
5482         if (result == ISC_R_NOTFOUND) {
5483                 INSIST(!dns_rdataset_isassociated(&rdataset));
5484                 return (ISC_R_SUCCESS);
5485         }
5486         if (result != ISC_R_SUCCESS) {
5487                 INSIST(!dns_rdataset_isassociated(&rdataset));
5488                 goto failure;
5489         }
5490
5491         for (result = dns_rdataset_first(&rdataset);
5492              result == ISC_R_SUCCESS;
5493              result = dns_rdataset_next(&rdataset)) {
5494                 dns_rdata_t rdata = DNS_RDATA_INIT;
5495
5496                 dns_rdataset_current(&rdataset, &rdata);
5497                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5498                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5499
5500                 if (type != dns_rdatatype_dnskey) {
5501                         isc_boolean_t warn = ISC_FALSE, deleted = ISC_FALSE;
5502                         if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
5503                                 result = update_one_rr(db, ver, zonediff->diff,
5504                                                DNS_DIFFOP_DELRESIGN, name,
5505                                                rdataset.ttl, &rdata);
5506                                 if (result != ISC_R_SUCCESS)
5507                                         break;
5508                                 deleted = ISC_TRUE;
5509                         }
5510                         if (warn) {
5511                                 /*
5512                                  * At this point, we've got an RRSIG,
5513                                  * which is signed by an inactive key.
5514                                  * An administrator needs to provide a new
5515                                  * key/alg, but until that time, we want to
5516                                  * keep the old RRSIG.  Marking the key as
5517                                  * offline will prevent us spinning waiting
5518                                  * for the private part.
5519                                  */
5520                                 if (incremental && !deleted) {
5521                                         result = offline(db, ver, zonediff,
5522                                                          name, rdataset.ttl,
5523                                                          &rdata);
5524                                         if (result != ISC_R_SUCCESS)
5525                                                 break;
5526                                 }
5527
5528                                 /*
5529                                  * Log the key id and algorithm of
5530                                  * the inactive key with no replacement
5531                                  */
5532                                 if (zone->log_key_expired_timer <= now) {
5533                                         char origin[DNS_NAME_FORMATSIZE];
5534                                         char algbuf[DNS_NAME_FORMATSIZE];
5535                                         dns_name_format(&zone->origin, origin,
5536                                                         sizeof(origin));
5537                                         dns_secalg_format(rrsig.algorithm,
5538                                                           algbuf,
5539                                                           sizeof(algbuf));
5540                                         dns_zone_log(zone, ISC_LOG_WARNING,
5541                                                      "Key %s/%s/%d "
5542                                                      "missing or inactive "
5543                                                      "and has no replacement: "
5544                                                      "retaining signatures.",
5545                                                      origin, algbuf,
5546                                                      rrsig.keyid);
5547                                         zone->log_key_expired_timer = now +
5548                                                                         3600;
5549                                 }
5550                         }
5551                         continue;
5552                 }
5553
5554                 /*
5555                  * RRSIG(DNSKEY) requires special processing.
5556                  */
5557                 found = ISC_FALSE;
5558                 for (i = 0; i < nkeys; i++) {
5559                         if (rrsig.algorithm == dst_key_alg(keys[i]) &&
5560                             rrsig.keyid == dst_key_id(keys[i])) {
5561                                 found = ISC_TRUE;
5562                                 /*
5563                                  * Mark offline RRSIG(DNSKEY).
5564                                  * We want the earliest offline expire time
5565                                  * iff there is a new offline signature.
5566                                  */
5567                                 if (!dst_key_inactive(keys[i]) &&
5568                                     !dst_key_isprivate(keys[i]))
5569                                 {
5570                                         isc_int64_t timeexpire =
5571                                            dns_time64_from32(rrsig.timeexpire);
5572                                         if (timewarn != 0 &&
5573                                             timewarn > timeexpire)
5574                                                 timewarn = timeexpire;
5575                                         if (rdata.flags & DNS_RDATA_OFFLINE) {
5576                                                 if (timemaybe == 0 ||
5577                                                     timemaybe > timeexpire)
5578                                                         timemaybe = timeexpire;
5579                                                 break;
5580                                         }
5581                                         if (timewarn == 0)
5582                                                 timewarn = timemaybe;
5583                                         if (timewarn == 0 ||
5584                                             timewarn > timeexpire)
5585                                                 timewarn = timeexpire;
5586                                         result = offline(db, ver, zonediff,
5587                                                          name, rdataset.ttl,
5588                                                          &rdata);
5589                                         break;
5590                                 }
5591                                 result = update_one_rr(db, ver, zonediff->diff,
5592                                                        DNS_DIFFOP_DELRESIGN,
5593                                                        name, rdataset.ttl,
5594                                                        &rdata);
5595                                 break;
5596                         }
5597                 }
5598
5599                 /*
5600                  * If there is not a matching DNSKEY then
5601                  * delete the RRSIG.
5602                  */
5603                 if (!found)
5604                         result = update_one_rr(db, ver, zonediff->diff,
5605                                                DNS_DIFFOP_DELRESIGN, name,
5606                                                rdataset.ttl, &rdata);
5607                 if (result != ISC_R_SUCCESS)
5608                         break;
5609         }
5610
5611         dns_rdataset_disassociate(&rdataset);
5612         if (result == ISC_R_NOMORE)
5613                 result = ISC_R_SUCCESS;
5614         if (timewarn > 0) {
5615 #if defined(STDTIME_ON_32BITS)
5616                 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
5617                 if (timewarn == stdwarn)
5618 #endif
5619                         set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
5620                                                now);
5621 #if defined(STDTIME_ON_32BITS)
5622                 else
5623                         dns_zone_log(zone, ISC_LOG_ERROR,
5624                                      "key expiry warning time out of range");
5625 #endif
5626         }
5627  failure:
5628         if (node != NULL)
5629                 dns_db_detachnode(db, &node);
5630         return (result);
5631 }
5632
5633 static isc_result_t
5634 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5635          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
5636          unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
5637          isc_stdtime_t expire, isc_boolean_t check_ksk,
5638          isc_boolean_t keyset_kskonly)
5639 {
5640         isc_result_t result;
5641         dns_dbnode_t *node = NULL;
5642         dns_rdataset_t rdataset;
5643         dns_rdata_t sig_rdata = DNS_RDATA_INIT;
5644         unsigned char data[1024]; /* XXX */
5645         isc_buffer_t buffer;
5646         unsigned int i, j;
5647
5648         dns_rdataset_init(&rdataset);
5649         isc_buffer_init(&buffer, data, sizeof(data));
5650
5651         if (type == dns_rdatatype_nsec3)
5652                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5653         else
5654                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
5655         if (result == ISC_R_NOTFOUND)
5656                 return (ISC_R_SUCCESS);
5657         if (result != ISC_R_SUCCESS)
5658                 goto failure;
5659         result = dns_db_findrdataset(db, node, ver, type, 0,
5660                                      (isc_stdtime_t) 0, &rdataset, NULL);
5661         dns_db_detachnode(db, &node);
5662         if (result == ISC_R_NOTFOUND) {
5663                 INSIST(!dns_rdataset_isassociated(&rdataset));
5664                 return (ISC_R_SUCCESS);
5665         }
5666         if (result != ISC_R_SUCCESS) {
5667                 INSIST(!dns_rdataset_isassociated(&rdataset));
5668                 goto failure;
5669         }
5670
5671         for (i = 0; i < nkeys; i++) {
5672                 isc_boolean_t both = ISC_FALSE;
5673
5674                 if (!dst_key_isprivate(keys[i]))
5675                         continue;
5676
5677                 if (check_ksk && !REVOKE(keys[i])) {
5678                         isc_boolean_t have_ksk, have_nonksk;
5679                         if (KSK(keys[i])) {
5680                                 have_ksk = ISC_TRUE;
5681                                 have_nonksk = ISC_FALSE;
5682                         } else {
5683                                 have_ksk = ISC_FALSE;
5684                                 have_nonksk = ISC_TRUE;
5685                         }
5686                         for (j = 0; j < nkeys; j++) {
5687                                 if (j == i || ALG(keys[i]) != ALG(keys[j]))
5688                                         continue;
5689                                 if (REVOKE(keys[j]))
5690                                         continue;
5691                                 if (KSK(keys[j]))
5692                                         have_ksk = ISC_TRUE;
5693                                 else
5694                                         have_nonksk = ISC_TRUE;
5695                                 both = have_ksk && have_nonksk;
5696                                 if (both)
5697                                         break;
5698                         }
5699                 }
5700                 if (both) {
5701                         if (type == dns_rdatatype_dnskey) {
5702                                 if (!KSK(keys[i]) && keyset_kskonly)
5703                                         continue;
5704                         } else if (KSK(keys[i]))
5705                                 continue;
5706                 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
5707                                 continue;
5708
5709                 /* Calculate the signature, creating a RRSIG RDATA. */
5710                 isc_buffer_clear(&buffer);
5711                 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
5712                                       &inception, &expire,
5713                                       mctx, &buffer, &sig_rdata));
5714                 /* Update the database and journal with the RRSIG. */
5715                 /* XXX inefficient - will cause dataset merging */
5716                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
5717                                     name, rdataset.ttl, &sig_rdata));
5718                 dns_rdata_reset(&sig_rdata);
5719                 isc_buffer_init(&buffer, data, sizeof(data));
5720         }
5721
5722  failure:
5723         if (dns_rdataset_isassociated(&rdataset))
5724                 dns_rdataset_disassociate(&rdataset);
5725         if (node != NULL)
5726                 dns_db_detachnode(db, &node);
5727         return (result);
5728 }
5729
5730 static void
5731 zone_resigninc(dns_zone_t *zone) {
5732         const char *me = "zone_resigninc";
5733         dns_db_t *db = NULL;
5734         dns_dbversion_t *version = NULL;
5735         dns_diff_t _sig_diff;
5736         zonediff_t zonediff;
5737         dns_fixedname_t fixed;
5738         dns_name_t *name;
5739         dns_rdataset_t rdataset;
5740         dns_rdatatype_t covers;
5741         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
5742         isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
5743         isc_result_t result;
5744         isc_stdtime_t now, inception, soaexpire, expire, stop;
5745         isc_uint32_t jitter;
5746         unsigned int i;
5747         unsigned int nkeys = 0;
5748         unsigned int resign;
5749
5750         ENTER;
5751
5752         dns_rdataset_init(&rdataset);
5753         dns_fixedname_init(&fixed);
5754         dns_diff_init(zone->mctx, &_sig_diff);
5755         zonediff_init(&zonediff, &_sig_diff);
5756
5757         /*
5758          * Zone is frozen or automatic resigning is disabled.
5759          * Pause for 5 minutes.
5760          */
5761         if (zone->update_disabled ||
5762             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
5763         {
5764                 result = ISC_R_FAILURE;
5765                 goto failure;
5766         }
5767
5768         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5769         dns_db_attach(zone->db, &db);
5770         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5771
5772         result = dns_db_newversion(db, &version);
5773         if (result != ISC_R_SUCCESS) {
5774                 dns_zone_log(zone, ISC_LOG_ERROR,
5775                              "zone_resigninc:dns_db_newversion -> %s",
5776                              dns_result_totext(result));
5777                 goto failure;
5778         }
5779
5780         result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
5781                                 zone_keys, &nkeys);
5782         if (result != ISC_R_SUCCESS) {
5783                 dns_zone_log(zone, ISC_LOG_ERROR,
5784                              "zone_resigninc:find_zone_keys -> %s",
5785                              dns_result_totext(result));
5786                 goto failure;
5787         }
5788
5789         isc_stdtime_get(&now);
5790         inception = now - 3600; /* Allow for clock skew. */
5791         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5792         /*
5793          * Spread out signatures over time if they happen to be
5794          * clumped.  We don't do this for each add_sigs() call as
5795          * we still want some clustering to occur.
5796          */
5797         isc_random_get(&jitter);
5798         expire = soaexpire - jitter % 3600;
5799         stop = now + 5;
5800
5801         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5802         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5803
5804         name = dns_fixedname_name(&fixed);
5805         result = dns_db_getsigningtime(db, &rdataset, name);
5806         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
5807                 dns_zone_log(zone, ISC_LOG_ERROR,
5808                              "zone_resigninc:dns_db_getsigningtime -> %s",
5809                              dns_result_totext(result));
5810         }
5811
5812         i = 0;
5813         while (result == ISC_R_SUCCESS) {
5814                 resign = rdataset.resign - zone->sigresigninginterval;
5815                 covers = rdataset.covers;
5816                 dns_rdataset_disassociate(&rdataset);
5817
5818                 /*
5819                  * Stop if we hit the SOA as that means we have walked the
5820                  * entire zone.  The SOA record should always be the most
5821                  * recent signature.
5822                  */
5823                 /* XXXMPA increase number of RRsets signed pre call */
5824                 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
5825                     resign > stop)
5826                         break;
5827
5828                 result = del_sigs(zone, db, version, name, covers, &zonediff,
5829                                   zone_keys, nkeys, now, ISC_TRUE);
5830                 if (result != ISC_R_SUCCESS) {
5831                         dns_zone_log(zone, ISC_LOG_ERROR,
5832                                      "zone_resigninc:del_sigs -> %s",
5833                                      dns_result_totext(result));
5834                         break;
5835                 }
5836
5837                 result = add_sigs(db, version, name, covers, zonediff.diff,
5838                                   zone_keys, nkeys, zone->mctx, inception,
5839                                   expire, check_ksk, keyset_kskonly);
5840                 if (result != ISC_R_SUCCESS) {
5841                         dns_zone_log(zone, ISC_LOG_ERROR,
5842                                      "zone_resigninc:add_sigs -> %s",
5843                                      dns_result_totext(result));
5844                         break;
5845                 }
5846                 result  = dns_db_getsigningtime(db, &rdataset, name);
5847                 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
5848                         result = ISC_R_SUCCESS;
5849                         break;
5850                 }
5851                 if (result != ISC_R_SUCCESS)
5852                         dns_zone_log(zone, ISC_LOG_ERROR,
5853                              "zone_resigninc:dns_db_getsigningtime -> %s",
5854                                      dns_result_totext(result));
5855         }
5856
5857         if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
5858                 goto failure;
5859
5860         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5861                           &zonediff, zone_keys, nkeys, now, ISC_TRUE);
5862         if (result != ISC_R_SUCCESS) {
5863                 dns_zone_log(zone, ISC_LOG_ERROR,
5864                              "zone_resigninc:del_sigs -> %s",
5865                              dns_result_totext(result));
5866                 goto failure;
5867         }
5868
5869         /*
5870          * Did we change anything in the zone?
5871          */
5872         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
5873                 /*
5874                  * Commit the changes if any key has been marked as offline.                     */
5875                 if (zonediff.offline)
5876                         dns_db_closeversion(db, &version, ISC_TRUE);
5877                 goto failure;
5878         }
5879
5880         /* Increment SOA serial if we have made changes */
5881         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
5882                                    zone->updatemethod);
5883         if (result != ISC_R_SUCCESS) {
5884                 dns_zone_log(zone, ISC_LOG_ERROR,
5885                              "zone_resigninc:update_soa_serial -> %s",
5886                              dns_result_totext(result));
5887                 goto failure;
5888         }
5889
5890         /*
5891          * Generate maximum life time signatures so that the above loop
5892          * termination is sensible.
5893          */
5894         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5895                           zonediff.diff, zone_keys, nkeys, zone->mctx,
5896                           inception, soaexpire, check_ksk, keyset_kskonly);
5897         if (result != ISC_R_SUCCESS) {
5898                 dns_zone_log(zone, ISC_LOG_ERROR,
5899                              "zone_resigninc:add_sigs -> %s",
5900                              dns_result_totext(result));
5901                 goto failure;
5902         }
5903
5904         /* Write changes to journal file. */
5905         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
5906
5907         /* Everything has succeeded. Commit the changes. */
5908         dns_db_closeversion(db, &version, ISC_TRUE);
5909
5910  failure:
5911         dns_diff_clear(&_sig_diff);
5912         for (i = 0; i < nkeys; i++)
5913                 dst_key_free(&zone_keys[i]);
5914         if (version != NULL) {
5915                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
5916                 dns_db_detach(&db);
5917         } else if (db != NULL)
5918                 dns_db_detach(&db);
5919         if (result == ISC_R_SUCCESS) {
5920                 set_resigntime(zone);
5921                 LOCK_ZONE(zone);
5922                 zone_needdump(zone, DNS_DUMP_DELAY);
5923                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5924                 UNLOCK_ZONE(zone);
5925         } else {
5926                 /*
5927                  * Something failed.  Retry in 5 minutes.
5928                  */
5929                 isc_interval_t ival;
5930                 isc_interval_set(&ival, 300, 0);
5931                 isc_time_nowplusinterval(&zone->resigntime, &ival);
5932         }
5933
5934         INSIST(version == NULL);
5935 }
5936
5937 static isc_result_t
5938 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
5939             dns_name_t *newname, isc_boolean_t bottom)
5940 {
5941         isc_result_t result;
5942         dns_dbiterator_t *dbit = NULL;
5943         dns_rdatasetiter_t *rdsit = NULL;
5944         dns_dbnode_t *node = NULL;
5945
5946         CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
5947         CHECK(dns_dbiterator_seek(dbit, oldname));
5948         do {
5949                 result = dns_dbiterator_next(dbit);
5950                 if (result == ISC_R_NOMORE)
5951                         CHECK(dns_dbiterator_first(dbit));
5952                 CHECK(dns_dbiterator_current(dbit, &node, newname));
5953                 if (bottom && dns_name_issubdomain(newname, oldname) &&
5954                     !dns_name_equal(newname, oldname)) {
5955                         dns_db_detachnode(db, &node);
5956                         continue;
5957                 }
5958                 /*
5959                  * Is this node empty?
5960                  */
5961                 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
5962                 result = dns_rdatasetiter_first(rdsit);
5963                 dns_db_detachnode(db, &node);
5964                 dns_rdatasetiter_destroy(&rdsit);
5965                 if (result != ISC_R_NOMORE)
5966                         break;
5967         } while (1);
5968  failure:
5969         if (node != NULL)
5970                 dns_db_detachnode(db, &node);
5971         if (dbit != NULL)
5972                 dns_dbiterator_destroy(&dbit);
5973         return (result);
5974 }
5975
5976 static isc_boolean_t
5977 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5978                 dns_rdatatype_t type, dst_key_t *key)
5979 {
5980         isc_result_t result;
5981         dns_rdataset_t rdataset;
5982         dns_rdata_t rdata = DNS_RDATA_INIT;
5983         dns_rdata_rrsig_t rrsig;
5984
5985         dns_rdataset_init(&rdataset);
5986         result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
5987                                      type, 0, &rdataset, NULL);
5988         if (result != ISC_R_SUCCESS) {
5989                 INSIST(!dns_rdataset_isassociated(&rdataset));
5990                 return (ISC_FALSE);
5991         }
5992         for (result = dns_rdataset_first(&rdataset);
5993              result == ISC_R_SUCCESS;
5994              result = dns_rdataset_next(&rdataset)) {
5995                 dns_rdataset_current(&rdataset, &rdata);
5996                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5997                 INSIST(result == ISC_R_SUCCESS);
5998                 if (rrsig.algorithm == dst_key_alg(key) &&
5999                     rrsig.keyid == dst_key_id(key)) {
6000                         dns_rdataset_disassociate(&rdataset);
6001                         return (ISC_TRUE);
6002                 }
6003                 dns_rdata_reset(&rdata);
6004         }
6005         dns_rdataset_disassociate(&rdataset);
6006         return (ISC_FALSE);
6007 }
6008
6009 static isc_result_t
6010 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6011          dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
6012          dns_diff_t *diff)
6013 {
6014         dns_fixedname_t fixed;
6015         dns_name_t *next;
6016         dns_rdata_t rdata = DNS_RDATA_INIT;
6017         isc_result_t result;
6018         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
6019
6020         dns_fixedname_init(&fixed);
6021         next = dns_fixedname_name(&fixed);
6022
6023         CHECK(next_active(db, version, name, next, bottom));
6024         CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
6025                                   &rdata));
6026         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
6027                             &rdata));
6028  failure:
6029         return (result);
6030 }
6031
6032 static isc_result_t
6033 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
6034             dns_dbversion_t *version, isc_boolean_t build_nsec3,
6035             isc_boolean_t build_nsec, dst_key_t *key,
6036             isc_stdtime_t inception, isc_stdtime_t expire,
6037             unsigned int minimum, isc_boolean_t is_ksk,
6038             isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
6039             dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
6040 {
6041         isc_result_t result;
6042         dns_rdatasetiter_t *iterator = NULL;
6043         dns_rdataset_t rdataset;
6044         dns_rdata_t rdata = DNS_RDATA_INIT;
6045         isc_buffer_t buffer;
6046         unsigned char data[1024];
6047         isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
6048                       seen_nsec3, seen_ds;
6049         isc_boolean_t bottom;
6050
6051         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6052         if (result != ISC_R_SUCCESS) {
6053                 if (result == ISC_R_NOTFOUND)
6054                         result = ISC_R_SUCCESS;
6055                 return (result);
6056         }
6057
6058         dns_rdataset_init(&rdataset);
6059         isc_buffer_init(&buffer, data, sizeof(data));
6060         seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
6061         seen_nsec3 = seen_ds = ISC_FALSE;
6062         for (result = dns_rdatasetiter_first(iterator);
6063              result == ISC_R_SUCCESS;
6064              result = dns_rdatasetiter_next(iterator)) {
6065                 dns_rdatasetiter_current(iterator, &rdataset);
6066                 if (rdataset.type == dns_rdatatype_soa)
6067                         seen_soa = ISC_TRUE;
6068                 else if (rdataset.type == dns_rdatatype_ns)
6069                         seen_ns = ISC_TRUE;
6070                 else if (rdataset.type == dns_rdatatype_ds)
6071                         seen_ds = ISC_TRUE;
6072                 else if (rdataset.type == dns_rdatatype_dname)
6073                         seen_dname = ISC_TRUE;
6074                 else if (rdataset.type == dns_rdatatype_nsec)
6075                         seen_nsec = ISC_TRUE;
6076                 else if (rdataset.type == dns_rdatatype_nsec3)
6077                         seen_nsec3 = ISC_TRUE;
6078                 if (rdataset.type != dns_rdatatype_rrsig)
6079                         seen_rr = ISC_TRUE;
6080                 dns_rdataset_disassociate(&rdataset);
6081         }
6082         if (result != ISC_R_NOMORE)
6083                 goto failure;
6084         if (seen_ns && !seen_soa)
6085                 *delegation = ISC_TRUE;
6086         /*
6087          * Going from insecure to NSEC3.
6088          * Don't generate NSEC3 records for NSEC3 records.
6089          */
6090         if (build_nsec3 && !seen_nsec3 && seen_rr) {
6091                 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
6092                 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
6093                                           unsecure, diff));
6094                 (*signatures)--;
6095         }
6096         /*
6097          * Going from insecure to NSEC.
6098          * Don't generate NSEC records for NSEC3 records.
6099          */
6100         if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
6101                 /* Build and add NSEC. */
6102                 bottom = (seen_ns && !seen_soa) || seen_dname;
6103                 /*
6104                  * Build a NSEC record except at the origin.
6105                  */
6106                 if (!dns_name_equal(name, dns_db_origin(db))) {
6107                         CHECK(add_nsec(db, version, name, node, minimum,
6108                                        bottom, diff));
6109                         /* Count a NSEC generation as a signature generation. */
6110                         (*signatures)--;
6111                 }
6112         }
6113         result = dns_rdatasetiter_first(iterator);
6114         while (result == ISC_R_SUCCESS) {
6115                 dns_rdatasetiter_current(iterator, &rdataset);
6116                 if (rdataset.type == dns_rdatatype_soa ||
6117                     rdataset.type == dns_rdatatype_rrsig)
6118                         goto next_rdataset;
6119                 if (rdataset.type == dns_rdatatype_dnskey) {
6120                         if (!is_ksk && keyset_kskonly)
6121                                 goto next_rdataset;
6122                 } else if (is_ksk) {
6123                         /*
6124                          * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
6125                          */
6126                         if (rdataset.type != dns_rdatatype_cds &&
6127                             rdataset.type != dns_rdatatype_cdnskey)
6128                                 goto next_rdataset;
6129                 }
6130                 if (*delegation &&
6131                     rdataset.type != dns_rdatatype_ds &&
6132                     rdataset.type != dns_rdatatype_nsec)
6133                         goto next_rdataset;
6134                 if (signed_with_key(db, node, version, rdataset.type, key))
6135                         goto next_rdataset;
6136                 /* Calculate the signature, creating a RRSIG RDATA. */
6137                 isc_buffer_clear(&buffer);
6138                 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
6139                                       &expire, mctx, &buffer, &rdata));
6140                 /* Update the database and journal with the RRSIG. */
6141                 /* XXX inefficient - will cause dataset merging */
6142                 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
6143                                     name, rdataset.ttl, &rdata));
6144                 dns_rdata_reset(&rdata);
6145                 (*signatures)--;
6146  next_rdataset:
6147                 dns_rdataset_disassociate(&rdataset);
6148                 result = dns_rdatasetiter_next(iterator);
6149         }
6150         if (result == ISC_R_NOMORE)
6151                 result = ISC_R_SUCCESS;
6152         if (seen_dname)
6153                 *delegation = ISC_TRUE;
6154  failure:
6155         if (dns_rdataset_isassociated(&rdataset))
6156                 dns_rdataset_disassociate(&rdataset);
6157         if (iterator != NULL)
6158                 dns_rdatasetiter_destroy(&iterator);
6159         return (result);
6160 }
6161
6162 /*
6163  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
6164  */
6165 static isc_result_t
6166 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6167              dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
6168 {
6169         isc_result_t result;
6170         dns_rdataset_t rdataset;
6171         dns_dbnode_t *node = NULL;
6172
6173         CHECK(dns_db_getoriginnode(db, &node));
6174         if (update_only) {
6175                 dns_rdataset_init(&rdataset);
6176                 result = dns_db_findrdataset(db, node, version,
6177                                              dns_rdatatype_nsec,
6178                                              dns_rdatatype_none,
6179                                              0, &rdataset, NULL);
6180                 if (dns_rdataset_isassociated(&rdataset))
6181                         dns_rdataset_disassociate(&rdataset);
6182                 if (result == ISC_R_NOTFOUND)
6183                         goto success;
6184                 if (result != ISC_R_SUCCESS)
6185                         goto failure;
6186         }
6187         CHECK(delete_nsec(db, version, node, name, diff));
6188         CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
6189  success:
6190         result = ISC_R_SUCCESS;
6191  failure:
6192         if (node != NULL)
6193                 dns_db_detachnode(db, &node);
6194         return (result);
6195 }
6196
6197 static isc_result_t
6198 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
6199                   dns_dbversion_t *version, isc_boolean_t build_nsec3,
6200                   dns_ttl_t minimum, dns_diff_t *diff)
6201 {
6202         isc_result_t result;
6203         dns_dbnode_t *node = NULL;
6204         dns_rdataset_t rdataset;
6205         dns_rdata_t rdata = DNS_RDATA_INIT;
6206         unsigned char data[5];
6207         isc_boolean_t seen_done = ISC_FALSE;
6208         isc_boolean_t have_rr = ISC_FALSE;
6209
6210         dns_rdataset_init(&rdataset);
6211         result = dns_db_getoriginnode(signing->db, &node);
6212         if (result != ISC_R_SUCCESS)
6213                 goto failure;
6214
6215         result = dns_db_findrdataset(signing->db, node, version,
6216                                      zone->privatetype, dns_rdatatype_none,
6217                                      0, &rdataset, NULL);
6218         if (result == ISC_R_NOTFOUND) {
6219                 INSIST(!dns_rdataset_isassociated(&rdataset));
6220                 result = ISC_R_SUCCESS;
6221                 goto failure;
6222         }
6223         if (result != ISC_R_SUCCESS) {
6224                 INSIST(!dns_rdataset_isassociated(&rdataset));
6225                 goto failure;
6226         }
6227         for (result = dns_rdataset_first(&rdataset);
6228              result == ISC_R_SUCCESS;
6229              result = dns_rdataset_next(&rdataset)) {
6230                 dns_rdataset_current(&rdataset, &rdata);
6231                 /*
6232                  * If we don't match the algorithm or keyid skip the record.
6233                  */
6234                 if (rdata.length != 5 ||
6235                     rdata.data[0] != signing->algorithm ||
6236                     rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
6237                     rdata.data[2] != (signing->keyid & 0xff)) {
6238                         have_rr = ISC_TRUE;
6239                         dns_rdata_reset(&rdata);
6240                         continue;
6241                 }
6242                 /*
6243                  * We have a match.  If we were signing (!signing->delete)
6244                  * and we already have a record indicating that we have
6245                  * finished signing (rdata.data[4] != 0) then keep it.
6246                  * Otherwise it needs to be deleted as we have removed all
6247                  * the signatures (signing->delete), so any record indicating
6248                  * completion is now out of date, or we have finished signing
6249                  * with the new record so we no longer need to remember that
6250                  * we need to sign the zone with the matching key across a
6251                  * nameserver re-start.
6252                  */
6253                 if (!signing->delete && rdata.data[4] != 0) {
6254                         seen_done = ISC_TRUE;
6255                         have_rr = ISC_TRUE;
6256                 } else
6257                         CHECK(update_one_rr(signing->db, version, diff,
6258                                             DNS_DIFFOP_DEL, &zone->origin,
6259                                             rdataset.ttl, &rdata));
6260                 dns_rdata_reset(&rdata);
6261         }
6262         if (result == ISC_R_NOMORE)
6263                 result = ISC_R_SUCCESS;
6264         if (!signing->delete && !seen_done) {
6265                 /*
6266                  * If we were signing then we need to indicate that we have
6267                  * finished signing the zone with this key.  If it is already
6268                  * there we don't need to add it a second time.
6269                  */
6270                 data[0] = signing->algorithm;
6271                 data[1] = (signing->keyid >> 8) & 0xff;
6272                 data[2] = signing->keyid & 0xff;
6273                 data[3] = 0;
6274                 data[4] = 1;
6275                 rdata.length = sizeof(data);
6276                 rdata.data = data;
6277                 rdata.type = zone->privatetype;
6278                 rdata.rdclass = dns_db_class(signing->db);
6279                 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
6280                                     &zone->origin, rdataset.ttl, &rdata));
6281         } else if (!have_rr) {
6282                 dns_name_t *origin = dns_db_origin(signing->db);
6283                 /*
6284                  * Rebuild the NSEC/NSEC3 record for the origin as we no
6285                  * longer have any private records.
6286                  */
6287                 if (build_nsec3)
6288                         CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
6289                                                   minimum, ISC_FALSE, diff));
6290                 CHECK(updatesecure(signing->db, version, origin, minimum,
6291                                    ISC_TRUE, diff));
6292         }
6293
6294  failure:
6295         if (dns_rdataset_isassociated(&rdataset))
6296                 dns_rdataset_disassociate(&rdataset);
6297         if (node != NULL)
6298                 dns_db_detachnode(signing->db, &node);
6299         return (result);
6300 }
6301
6302 /*
6303  * If 'active' is set then we are not done with the chain yet so only
6304  * delete the nsec3param record which indicates a full chain exists
6305  * (flags == 0).
6306  */
6307 static isc_result_t
6308 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
6309                  isc_boolean_t active, dns_rdatatype_t privatetype,
6310                  dns_diff_t *diff)
6311 {
6312         dns_dbnode_t *node = NULL;
6313         dns_name_t *name = dns_db_origin(db);
6314         dns_rdata_t rdata = DNS_RDATA_INIT;
6315         dns_rdataset_t rdataset;
6316         dns_rdata_nsec3param_t nsec3param;
6317         isc_result_t result;
6318         isc_buffer_t buffer;
6319         unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
6320         dns_ttl_t ttl = 0;
6321         isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
6322
6323         dns_rdataset_init(&rdataset);
6324
6325         result = dns_db_getoriginnode(db, &node);
6326         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6327         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6328                                      0, 0, &rdataset, NULL);
6329         if (result == ISC_R_NOTFOUND)
6330                 goto try_private;
6331         if (result != ISC_R_SUCCESS)
6332                 goto failure;
6333
6334         /*
6335          * Preserve the existing ttl.
6336          */
6337         ttl = rdataset.ttl;
6338
6339         /*
6340          * Delete all NSEC3PARAM records which match that in nsec3chain.
6341          */
6342         for (result = dns_rdataset_first(&rdataset);
6343              result == ISC_R_SUCCESS;
6344              result = dns_rdataset_next(&rdataset)) {
6345
6346                 dns_rdataset_current(&rdataset, &rdata);
6347                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6348
6349                 if (nsec3param.hash != chain->nsec3param.hash ||
6350                     (active && nsec3param.flags != 0) ||
6351                     nsec3param.iterations != chain->nsec3param.iterations ||
6352                     nsec3param.salt_length != chain->nsec3param.salt_length ||
6353                     memcmp(nsec3param.salt, chain->nsec3param.salt,
6354                            nsec3param.salt_length)) {
6355                         dns_rdata_reset(&rdata);
6356                         continue;
6357                 }
6358
6359                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6360                                     name, rdataset.ttl, &rdata));
6361                 dns_rdata_reset(&rdata);
6362         }
6363         if (result != ISC_R_NOMORE)
6364                 goto failure;
6365
6366         dns_rdataset_disassociate(&rdataset);
6367
6368  try_private:
6369
6370         if (active)
6371                 goto add;
6372
6373         result = dns_nsec_nseconly(db, ver, &nseconly);
6374         nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
6375
6376         /*
6377          * Delete all private records which match that in nsec3chain.
6378          */
6379         result = dns_db_findrdataset(db, node, ver, privatetype,
6380                                      0, 0, &rdataset, NULL);
6381         if (result == ISC_R_NOTFOUND)
6382                 goto add;
6383         if (result != ISC_R_SUCCESS)
6384                 goto failure;
6385
6386         for (result = dns_rdataset_first(&rdataset);
6387              result == ISC_R_SUCCESS;
6388              result = dns_rdataset_next(&rdataset)) {
6389                 dns_rdata_t private = DNS_RDATA_INIT;
6390                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
6391
6392                 dns_rdataset_current(&rdataset, &private);
6393                 if (!dns_nsec3param_fromprivate(&private, &rdata,
6394                                                 buf, sizeof(buf)))
6395                         continue;
6396                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6397
6398                 if ((!nsec3ok &&
6399                      (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
6400                     nsec3param.hash != chain->nsec3param.hash ||
6401                     nsec3param.iterations != chain->nsec3param.iterations ||
6402                     nsec3param.salt_length != chain->nsec3param.salt_length ||
6403                     memcmp(nsec3param.salt, chain->nsec3param.salt,
6404                            nsec3param.salt_length)) {
6405                         dns_rdata_reset(&rdata);
6406                         continue;
6407                 }
6408
6409                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6410                                     name, rdataset.ttl, &private));
6411                 dns_rdata_reset(&rdata);
6412         }
6413         if (result != ISC_R_NOMORE)
6414                 goto failure;
6415
6416   add:
6417         if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
6418                 result = ISC_R_SUCCESS;
6419                 goto failure;
6420         }
6421
6422         /*
6423          * Add a NSEC3PARAM record which matches that in nsec3chain but
6424          * with all flags bits cleared.
6425          *
6426          * Note: we do not clear chain->nsec3param.flags as this change
6427          * may be reversed.
6428          */
6429         isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
6430         CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
6431                                    dns_rdatatype_nsec3param,
6432                                    &chain->nsec3param, &buffer));
6433         rdata.data[1] = 0;      /* Clear flag bits. */
6434         CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
6435
6436   failure:
6437         dns_db_detachnode(db, &node);
6438         if (dns_rdataset_isassociated(&rdataset))
6439                 dns_rdataset_disassociate(&rdataset);
6440         return (result);
6441 }
6442
6443 static isc_result_t
6444 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6445             dns_name_t *name, dns_diff_t *diff)
6446 {
6447         dns_rdataset_t rdataset;
6448         isc_result_t result;
6449
6450         dns_rdataset_init(&rdataset);
6451
6452         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6453                                      0, 0, &rdataset, NULL);
6454         if (result == ISC_R_NOTFOUND)
6455                 return (ISC_R_SUCCESS);
6456         if (result != ISC_R_SUCCESS)
6457                 return (result);
6458         for (result = dns_rdataset_first(&rdataset);
6459              result == ISC_R_SUCCESS;
6460              result = dns_rdataset_next(&rdataset)) {
6461                 dns_rdata_t rdata = DNS_RDATA_INIT;
6462
6463                 dns_rdataset_current(&rdataset, &rdata);
6464                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6465                                     rdataset.ttl, &rdata));
6466         }
6467         if (result == ISC_R_NOMORE)
6468                 result = ISC_R_SUCCESS;
6469  failure:
6470         dns_rdataset_disassociate(&rdataset);
6471         return (result);
6472 }
6473
6474 static isc_result_t
6475 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6476                     dns_name_t *name, const dns_rdata_nsec3param_t *param,
6477                     dns_diff_t *diff)
6478 {
6479         dns_rdataset_t rdataset;
6480         dns_rdata_nsec3_t nsec3;
6481         isc_result_t result;
6482
6483         dns_rdataset_init(&rdataset);
6484         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
6485                                      0, 0, &rdataset, NULL);
6486         if (result == ISC_R_NOTFOUND)
6487                 return (ISC_R_SUCCESS);
6488         if (result != ISC_R_SUCCESS)
6489                 return (result);
6490
6491         for (result = dns_rdataset_first(&rdataset);
6492              result == ISC_R_SUCCESS;
6493              result = dns_rdataset_next(&rdataset)) {
6494                 dns_rdata_t rdata = DNS_RDATA_INIT;
6495
6496                 dns_rdataset_current(&rdataset, &rdata);
6497                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
6498                 if (nsec3.hash != param->hash ||
6499                     nsec3.iterations != param->iterations ||
6500                     nsec3.salt_length != param->salt_length ||
6501                     memcmp(nsec3.salt, param->salt, nsec3.salt_length))
6502                         continue;
6503                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6504                                     rdataset.ttl, &rdata));
6505         }
6506         if (result == ISC_R_NOMORE)
6507                 result = ISC_R_SUCCESS;
6508  failure:
6509         dns_rdataset_disassociate(&rdataset);
6510         return (result);
6511 }
6512
6513 static isc_result_t
6514 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
6515                 const dns_rdata_nsec3param_t *param,
6516                 isc_boolean_t *answer)
6517 {
6518         dns_dbnode_t *node = NULL;
6519         dns_rdata_t rdata = DNS_RDATA_INIT;
6520         dns_rdata_nsec3param_t myparam;
6521         dns_rdataset_t rdataset;
6522         isc_result_t result;
6523
6524         *answer = ISC_FALSE;
6525
6526         result = dns_db_getoriginnode(db, &node);
6527         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6528
6529         dns_rdataset_init(&rdataset);
6530
6531         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6532                                      0, 0, &rdataset, NULL);
6533         if (result == ISC_R_SUCCESS) {
6534                 dns_rdataset_disassociate(&rdataset);
6535                 dns_db_detachnode(db, &node);
6536                 return (result);
6537         }
6538         if (result != ISC_R_NOTFOUND) {
6539                 dns_db_detachnode(db, &node);
6540                 return (result);
6541         }
6542
6543         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6544                                      0, 0, &rdataset, NULL);
6545         if (result == ISC_R_NOTFOUND) {
6546                 *answer = ISC_TRUE;
6547                 dns_db_detachnode(db, &node);
6548                 return (ISC_R_SUCCESS);
6549         }
6550         if (result != ISC_R_SUCCESS) {
6551                 dns_db_detachnode(db, &node);
6552                 return (result);
6553         }
6554
6555         for (result = dns_rdataset_first(&rdataset);
6556              result == ISC_R_SUCCESS;
6557              result = dns_rdataset_next(&rdataset)) {
6558                 dns_rdataset_current(&rdataset, &rdata);
6559                 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
6560                 dns_rdata_reset(&rdata);
6561                 /*
6562                  * Ignore any NSEC3PARAM removals.
6563                  */
6564                 if (NSEC3REMOVE(myparam.flags))
6565                         continue;
6566                 /*
6567                  * Ignore the chain that we are in the process of deleting.
6568                  */
6569                 if (myparam.hash == param->hash &&
6570                     myparam.iterations == param->iterations &&
6571                     myparam.salt_length == param->salt_length &&
6572                     !memcmp(myparam.salt, param->salt, myparam.salt_length))
6573                         continue;
6574                 /*
6575                  * Found an active NSEC3 chain.
6576                  */
6577                 break;
6578         }
6579         if (result == ISC_R_NOMORE) {
6580                 *answer = ISC_TRUE;
6581                 result = ISC_R_SUCCESS;
6582         }
6583
6584  failure:
6585         if (dns_rdataset_isassociated(&rdataset))
6586                 dns_rdataset_disassociate(&rdataset);
6587         dns_db_detachnode(db, &node);
6588         return (result);
6589 }
6590
6591 static isc_result_t
6592 update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
6593             dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
6594             isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
6595             isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
6596             zonediff_t *zonediff)
6597 {
6598         dns_difftuple_t *tuple;
6599         isc_result_t result;
6600
6601         for (tuple = ISC_LIST_HEAD(diff->tuples);
6602              tuple != NULL;
6603              tuple = ISC_LIST_HEAD(diff->tuples)) {
6604                 result = del_sigs(zone, db, version, &tuple->name,
6605                                   tuple->rdata.type, zonediff,
6606                                   zone_keys, nkeys, now, ISC_FALSE);
6607                 if (result != ISC_R_SUCCESS) {
6608                         dns_zone_log(zone, ISC_LOG_ERROR,
6609                                      "update_sigs:del_sigs -> %s",
6610                                      dns_result_totext(result));
6611                         return (result);
6612                 }
6613                 result = add_sigs(db, version, &tuple->name,
6614                                   tuple->rdata.type, zonediff->diff,
6615                                   zone_keys, nkeys, zone->mctx, inception,
6616                                   expire, check_ksk, keyset_kskonly);
6617                 if (result != ISC_R_SUCCESS) {
6618                         dns_zone_log(zone, ISC_LOG_ERROR,
6619                                      "update_sigs:add_sigs -> %s",
6620                                      dns_result_totext(result));
6621                         return (result);
6622                 }
6623
6624                 do {
6625                         dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
6626                         while (next != NULL &&
6627                                (tuple->rdata.type != next->rdata.type ||
6628                                 !dns_name_equal(&tuple->name, &next->name)))
6629                                 next = ISC_LIST_NEXT(next, link);
6630                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
6631                         dns_diff_appendminimal(zonediff->diff, &tuple);
6632                         INSIST(tuple == NULL);
6633                         tuple = next;
6634                 } while (tuple != NULL);
6635         }
6636         return (ISC_R_SUCCESS);
6637 }
6638
6639 /*
6640  * Incrementally build and sign a new NSEC3 chain using the parameters
6641  * requested.
6642  */
6643 static void
6644 zone_nsec3chain(dns_zone_t *zone) {
6645         const char *me = "zone_nsec3chain";
6646         dns_db_t *db = NULL;
6647         dns_dbnode_t *node = NULL;
6648         dns_dbversion_t *version = NULL;
6649         dns_diff_t _sig_diff;
6650         dns_diff_t nsec_diff;
6651         dns_diff_t nsec3_diff;
6652         dns_diff_t param_diff;
6653         zonediff_t zonediff;
6654         dns_fixedname_t fixed;
6655         dns_fixedname_t nextfixed;
6656         dns_name_t *name, *nextname;
6657         dns_rdataset_t rdataset;
6658         dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
6659         dns_nsec3chainlist_t cleanup;
6660         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6661         isc_int32_t signatures;
6662         isc_boolean_t check_ksk, keyset_kskonly;
6663         isc_boolean_t delegation;
6664         isc_boolean_t first;
6665         isc_result_t result;
6666         isc_stdtime_t now, inception, soaexpire, expire;
6667         isc_uint32_t jitter;
6668         unsigned int i;
6669         unsigned int nkeys = 0;
6670         isc_uint32_t nodes;
6671         isc_boolean_t unsecure = ISC_FALSE;
6672         isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
6673         isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
6674         dns_rdatasetiter_t *iterator = NULL;
6675         isc_boolean_t buildnsecchain;
6676         isc_boolean_t updatensec = ISC_FALSE;
6677         dns_rdatatype_t privatetype = zone->privatetype;
6678
6679         ENTER;
6680
6681         dns_rdataset_init(&rdataset);
6682         dns_fixedname_init(&fixed);
6683         name = dns_fixedname_name(&fixed);
6684         dns_fixedname_init(&nextfixed);
6685         nextname = dns_fixedname_name(&nextfixed);
6686         dns_diff_init(zone->mctx, &param_diff);
6687         dns_diff_init(zone->mctx, &nsec3_diff);
6688         dns_diff_init(zone->mctx, &nsec_diff);
6689         dns_diff_init(zone->mctx, &_sig_diff);
6690         zonediff_init(&zonediff, &_sig_diff);
6691         ISC_LIST_INIT(cleanup);
6692
6693         /*
6694          * Updates are disabled.  Pause for 5 minutes.
6695          */
6696         if (zone->update_disabled) {
6697                 result = ISC_R_FAILURE;
6698                 goto failure;
6699         }
6700
6701         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6702         dns_db_attach(zone->db, &db);
6703         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6704
6705         result = dns_db_newversion(db, &version);
6706         if (result != ISC_R_SUCCESS) {
6707                 dns_zone_log(zone, ISC_LOG_ERROR,
6708                              "zone_nsec3chain:dns_db_newversion -> %s",
6709                              dns_result_totext(result));
6710                 goto failure;
6711         }
6712
6713         result = find_zone_keys(zone, db, version, zone->mctx,
6714                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
6715         if (result != ISC_R_SUCCESS) {
6716                 dns_zone_log(zone, ISC_LOG_ERROR,
6717                              "zone_nsec3chain:find_zone_keys -> %s",
6718                              dns_result_totext(result));
6719                 goto failure;
6720         }
6721
6722         isc_stdtime_get(&now);
6723         inception = now - 3600; /* Allow for clock skew. */
6724         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6725
6726         /*
6727          * Spread out signatures over time if they happen to be
6728          * clumped.  We don't do this for each add_sigs() call as
6729          * we still want some clustering to occur.
6730          */
6731         isc_random_get(&jitter);
6732         expire = soaexpire - jitter % 3600;
6733
6734         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6735         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6736
6737         /*
6738          * We keep pulling nodes off each iterator in turn until
6739          * we have no more nodes to pull off or we reach the limits
6740          * for this quantum.
6741          */
6742         nodes = zone->nodes;
6743         signatures = zone->signatures;
6744         LOCK_ZONE(zone);
6745         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6746         UNLOCK_ZONE(zone);
6747         first = ISC_TRUE;
6748
6749         if (nsec3chain != NULL)
6750                 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6751         /*
6752          * Generate new NSEC3 chains first.
6753          */
6754         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6755                 LOCK_ZONE(zone);
6756                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6757
6758                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6759                 if (nsec3chain->done || nsec3chain->db != zone->db) {
6760                         ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
6761                         ISC_LIST_APPEND(cleanup, nsec3chain, link);
6762                 }
6763                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6764                 UNLOCK_ZONE(zone);
6765                 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
6766                         goto next_addchain;
6767
6768                 /*
6769                  * Possible future db.
6770                  */
6771                 if (nsec3chain->db != db) {
6772                         goto next_addchain;
6773                 }
6774
6775                 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
6776                         goto next_addchain;
6777
6778                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6779
6780                 if (nsec3chain->delete_nsec) {
6781                         delegation = ISC_FALSE;
6782                         dns_dbiterator_pause(nsec3chain->dbiterator);
6783                         CHECK(delete_nsec(db, version, node, name, &nsec_diff));
6784                         goto next_addnode;
6785                 }
6786                 /*
6787                  * On the first pass we need to check if the current node
6788                  * has not been obscured.
6789                  */
6790                 delegation = ISC_FALSE;
6791                 unsecure = ISC_FALSE;
6792                 if (first) {
6793                         dns_fixedname_t ffound;
6794                         dns_name_t *found;
6795                         dns_fixedname_init(&ffound);
6796                         found = dns_fixedname_name(&ffound);
6797                         result = dns_db_find(db, name, version,
6798                                              dns_rdatatype_soa,
6799                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6800                                              NULL, NULL);
6801                         if ((result == DNS_R_DELEGATION ||
6802                             result == DNS_R_DNAME) &&
6803                             !dns_name_equal(name, found)) {
6804                                 /*
6805                                  * Remember the obscuring name so that
6806                                  * we skip all obscured names.
6807                                  */
6808                                 dns_name_copy(found, name, NULL);
6809                                 delegation = ISC_TRUE;
6810                                 goto next_addnode;
6811                         }
6812                 }
6813
6814                 /*
6815                  * Check to see if this is a bottom of zone node.
6816                  */
6817                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6818                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
6819                         goto next_addnode;
6820                 if (result != ISC_R_SUCCESS)
6821                         goto failure;
6822
6823                 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
6824                         ISC_FALSE;
6825                 for (result = dns_rdatasetiter_first(iterator);
6826                      result == ISC_R_SUCCESS;
6827                      result = dns_rdatasetiter_next(iterator)) {
6828                         dns_rdatasetiter_current(iterator, &rdataset);
6829                         INSIST(rdataset.type != dns_rdatatype_nsec3);
6830                         if (rdataset.type == dns_rdatatype_soa)
6831                                 seen_soa = ISC_TRUE;
6832                         else if (rdataset.type == dns_rdatatype_ns)
6833                                 seen_ns = ISC_TRUE;
6834                         else if (rdataset.type == dns_rdatatype_dname)
6835                                 seen_dname = ISC_TRUE;
6836                         else if (rdataset.type == dns_rdatatype_ds)
6837                                 seen_ds = ISC_TRUE;
6838                         else if (rdataset.type == dns_rdatatype_nsec)
6839                                 seen_nsec = ISC_TRUE;
6840                         dns_rdataset_disassociate(&rdataset);
6841                 }
6842                 dns_rdatasetiter_destroy(&iterator);
6843                 /*
6844                  * Is there a NSEC chain than needs to be cleaned up?
6845                  */
6846                 if (seen_nsec)
6847                         nsec3chain->seen_nsec = ISC_TRUE;
6848                 if (seen_ns && !seen_soa && !seen_ds)
6849                         unsecure = ISC_TRUE;
6850                 if ((seen_ns && !seen_soa) || seen_dname)
6851                         delegation = ISC_TRUE;
6852
6853                 /*
6854                  * Process one node.
6855                  */
6856                 dns_dbiterator_pause(nsec3chain->dbiterator);
6857                 result = dns_nsec3_addnsec3(db, version, name,
6858                                             &nsec3chain->nsec3param,
6859                                             zone->minimum, unsecure,
6860                                             &nsec3_diff);
6861                 if (result != ISC_R_SUCCESS) {
6862                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6863                                      "dns_nsec3_addnsec3 -> %s",
6864                                      dns_result_totext(result));
6865                         goto failure;
6866                 }
6867
6868                 /*
6869                  * Treat each call to dns_nsec3_addnsec3() as if it's cost is
6870                  * two signatures.  Additionally there will, in general, be
6871                  * two signature generated below.
6872                  *
6873                  * If we are only changing the optout flag the cost is half
6874                  * that of the cost of generating a completely new chain.
6875                  */
6876                 signatures -= 4;
6877
6878                 /*
6879                  * Go onto next node.
6880                  */
6881  next_addnode:
6882                 first = ISC_FALSE;
6883                 dns_db_detachnode(db, &node);
6884                 do {
6885                         result = dns_dbiterator_next(nsec3chain->dbiterator);
6886
6887                         if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
6888                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6889                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6890                                                        ISC_FALSE, privatetype,
6891                                                        &param_diff));
6892                                 LOCK_ZONE(zone);
6893                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6894                                                 link);
6895                                 UNLOCK_ZONE(zone);
6896                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6897                                 goto next_addchain;
6898                         }
6899                         if (result == ISC_R_NOMORE) {
6900                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6901                                 if (nsec3chain->seen_nsec) {
6902                                         CHECK(fixup_nsec3param(db, version,
6903                                                                nsec3chain,
6904                                                                ISC_TRUE,
6905                                                                privatetype,
6906                                                                &param_diff));
6907                                         nsec3chain->delete_nsec = ISC_TRUE;
6908                                         goto same_addchain;
6909                                 }
6910                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6911                                                        ISC_FALSE, privatetype,
6912                                                        &param_diff));
6913                                 LOCK_ZONE(zone);
6914                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6915                                                 link);
6916                                 UNLOCK_ZONE(zone);
6917                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6918                                 goto next_addchain;
6919                         } else if (result != ISC_R_SUCCESS) {
6920                                 dns_zone_log(zone, ISC_LOG_ERROR,
6921                                              "zone_nsec3chain:"
6922                                              "dns_dbiterator_next -> %s",
6923                                              dns_result_totext(result));
6924                                 goto failure;
6925                         } else if (delegation) {
6926                                 dns_dbiterator_current(nsec3chain->dbiterator,
6927                                                        &node, nextname);
6928                                 dns_db_detachnode(db, &node);
6929                                 if (!dns_name_issubdomain(nextname, name))
6930                                         break;
6931                         } else
6932                                 break;
6933                 } while (1);
6934                 continue;
6935
6936  same_addchain:
6937                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6938                 first = ISC_TRUE;
6939                 continue;
6940
6941  next_addchain:
6942                 dns_dbiterator_pause(nsec3chain->dbiterator);
6943                 nsec3chain = nextnsec3chain;
6944                 first = ISC_TRUE;
6945                 if (nsec3chain != NULL)
6946                         nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6947         }
6948
6949         /*
6950          * Process removals.
6951          */
6952         LOCK_ZONE(zone);
6953         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6954         UNLOCK_ZONE(zone);
6955         first = ISC_TRUE;
6956         buildnsecchain = ISC_FALSE;
6957         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6958                 LOCK_ZONE(zone);
6959                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6960                 UNLOCK_ZONE(zone);
6961
6962                 if (nsec3chain->db != db)
6963                         goto next_removechain;
6964
6965                 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
6966                         goto next_removechain;
6967
6968                 /*
6969                  * Work out if we need to build a NSEC chain as a consequence
6970                  * of removing this NSEC3 chain.
6971                  */
6972                 if (first && !updatensec &&
6973                     (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
6974                 {
6975                         result = need_nsec_chain(db, version,
6976                                                  &nsec3chain->nsec3param,
6977                                                  &buildnsecchain);
6978                         if (result != ISC_R_SUCCESS) {
6979                                 dns_zone_log(zone, ISC_LOG_ERROR,
6980                                              "zone_nsec3chain:"
6981                                              "need_nsec_chain -> %s",
6982                                              dns_result_totext(result));
6983                                 goto failure;
6984                         }
6985                 }
6986
6987                 if (first)
6988                         dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
6989                                      "buildnsecchain = %u\n", buildnsecchain);
6990
6991                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6992                 delegation = ISC_FALSE;
6993
6994                 if (!buildnsecchain) {
6995                         /*
6996                          * Delete the NSECPARAM record that matches this chain.
6997                          */
6998                         if (first) {
6999                                 result = fixup_nsec3param(db, version,
7000                                                           nsec3chain,
7001                                                           ISC_TRUE, privatetype,
7002                                                           &param_diff);
7003                                 if (result != ISC_R_SUCCESS) {
7004                                         dns_zone_log(zone, ISC_LOG_ERROR,
7005                                                      "zone_nsec3chain:"
7006                                                      "fixup_nsec3param -> %s",
7007                                                      dns_result_totext(result));
7008                                         goto failure;
7009                                 }
7010                         }
7011
7012                         /*
7013                          *  Delete the NSEC3 records.
7014                          */
7015                         result = deletematchingnsec3(db, version, node, name,
7016                                                      &nsec3chain->nsec3param,
7017                                                      &nsec3_diff);
7018                         if (result != ISC_R_SUCCESS) {
7019                                 dns_zone_log(zone, ISC_LOG_ERROR,
7020                                              "zone_nsec3chain:"
7021                                              "deletematchingnsec3 -> %s",
7022                                              dns_result_totext(result));
7023                                 goto failure;
7024                         }
7025                         goto next_removenode;
7026                 }
7027
7028                 if (first) {
7029                         dns_fixedname_t ffound;
7030                         dns_name_t *found;
7031                         dns_fixedname_init(&ffound);
7032                         found = dns_fixedname_name(&ffound);
7033                         result = dns_db_find(db, name, version,
7034                                              dns_rdatatype_soa,
7035                                              DNS_DBFIND_NOWILD, 0, NULL, found,
7036                                              NULL, NULL);
7037                         if ((result == DNS_R_DELEGATION ||
7038                              result == DNS_R_DNAME) &&
7039                             !dns_name_equal(name, found)) {
7040                                 /*
7041                                  * Remember the obscuring name so that
7042                                  * we skip all obscured names.
7043                                  */
7044                                 dns_name_copy(found, name, NULL);
7045                                 delegation = ISC_TRUE;
7046                                 goto next_removenode;
7047                         }
7048                 }
7049
7050                 /*
7051                  * Check to see if this is a bottom of zone node.
7052                  */
7053                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7054                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
7055                         goto next_removenode;
7056                 if (result != ISC_R_SUCCESS)
7057                         goto failure;
7058
7059                 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
7060                         seen_rr = ISC_FALSE;
7061                 for (result = dns_rdatasetiter_first(iterator);
7062                      result == ISC_R_SUCCESS;
7063                      result = dns_rdatasetiter_next(iterator)) {
7064                         dns_rdatasetiter_current(iterator, &rdataset);
7065                         if (rdataset.type == dns_rdatatype_soa)
7066                                 seen_soa = ISC_TRUE;
7067                         else if (rdataset.type == dns_rdatatype_ns)
7068                                 seen_ns = ISC_TRUE;
7069                         else if (rdataset.type == dns_rdatatype_dname)
7070                                 seen_dname = ISC_TRUE;
7071                         else if (rdataset.type == dns_rdatatype_nsec)
7072                                 seen_nsec = ISC_TRUE;
7073                         else if (rdataset.type == dns_rdatatype_nsec3)
7074                                 seen_nsec3 = ISC_TRUE;
7075                         if (rdataset.type != dns_rdatatype_rrsig)
7076                                 seen_rr = ISC_TRUE;
7077                         dns_rdataset_disassociate(&rdataset);
7078                 }
7079                 dns_rdatasetiter_destroy(&iterator);
7080
7081                 if (!seen_rr || seen_nsec3 || seen_nsec)
7082                         goto next_removenode;
7083                 if ((seen_ns && !seen_soa) || seen_dname)
7084                         delegation = ISC_TRUE;
7085
7086                 /*
7087                  * Add a NSEC record except at the origin.
7088                  */
7089                 if (!dns_name_equal(name, dns_db_origin(db))) {
7090                         dns_dbiterator_pause(nsec3chain->dbiterator);
7091                         CHECK(add_nsec(db, version, name, node, zone->minimum,
7092                                        delegation, &nsec_diff));
7093                 }
7094
7095  next_removenode:
7096                 first = ISC_FALSE;
7097                 dns_db_detachnode(db, &node);
7098                 do {
7099                         result = dns_dbiterator_next(nsec3chain->dbiterator);
7100                         if (result == ISC_R_NOMORE && buildnsecchain) {
7101                                 /*
7102                                  * The NSEC chain should now be built.
7103                                  * We can now remove the NSEC3 chain.
7104                                  */
7105                                 updatensec = ISC_TRUE;
7106                                 goto same_removechain;
7107                         }
7108                         if (result == ISC_R_NOMORE) {
7109                                 LOCK_ZONE(zone);
7110                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7111                                                 link);
7112                                 UNLOCK_ZONE(zone);
7113                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7114                                 dns_dbiterator_pause(nsec3chain->dbiterator);
7115                                 result = fixup_nsec3param(db, version,
7116                                                           nsec3chain, ISC_FALSE,
7117                                                           privatetype,
7118                                                           &param_diff);
7119                                 if (result != ISC_R_SUCCESS) {
7120                                         dns_zone_log(zone, ISC_LOG_ERROR,
7121                                                      "zone_nsec3chain:"
7122                                                      "fixup_nsec3param -> %s",
7123                                                      dns_result_totext(result));
7124                                         goto failure;
7125                                 }
7126                                 goto next_removechain;
7127                         } else if (result != ISC_R_SUCCESS) {
7128                                 dns_zone_log(zone, ISC_LOG_ERROR,
7129                                              "zone_nsec3chain:"
7130                                              "dns_dbiterator_next -> %s",
7131                                              dns_result_totext(result));
7132                                 goto failure;
7133                         } else if (delegation) {
7134                                 dns_dbiterator_current(nsec3chain->dbiterator,
7135                                                        &node, nextname);
7136                                 dns_db_detachnode(db, &node);
7137                                 if (!dns_name_issubdomain(nextname, name))
7138                                         break;
7139                         } else
7140                                 break;
7141                 } while (1);
7142                 continue;
7143
7144  same_removechain:
7145                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
7146                 buildnsecchain = ISC_FALSE;
7147                 first = ISC_TRUE;
7148                 continue;
7149
7150  next_removechain:
7151                 dns_dbiterator_pause(nsec3chain->dbiterator);
7152                 nsec3chain = nextnsec3chain;
7153                 first = ISC_TRUE;
7154         }
7155
7156         /*
7157          * We may need to update the NSEC/NSEC3 records for the zone apex.
7158          */
7159         if (!ISC_LIST_EMPTY(param_diff.tuples)) {
7160                 isc_boolean_t rebuild_nsec = ISC_FALSE,
7161                               rebuild_nsec3 = ISC_FALSE;
7162                 result = dns_db_getoriginnode(db, &node);
7163                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7164                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7165                 if (result != ISC_R_SUCCESS) {
7166                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7167                                      "dns_db_allrdatasets -> %s",
7168                                      dns_result_totext(result));
7169                         goto failure;
7170                 }
7171                 for (result = dns_rdatasetiter_first(iterator);
7172                      result == ISC_R_SUCCESS;
7173                      result = dns_rdatasetiter_next(iterator)) {
7174                         dns_rdatasetiter_current(iterator, &rdataset);
7175                         if (rdataset.type == dns_rdatatype_nsec)
7176                                 rebuild_nsec = ISC_TRUE;
7177                         if (rdataset.type == dns_rdatatype_nsec3param)
7178                                 rebuild_nsec3 = ISC_TRUE;
7179                         dns_rdataset_disassociate(&rdataset);
7180                 }
7181                 dns_rdatasetiter_destroy(&iterator);
7182                 dns_db_detachnode(db, &node);
7183
7184                 if (rebuild_nsec) {
7185                         if (nsec3chain != NULL)
7186                                 dns_dbiterator_pause(nsec3chain->dbiterator);
7187
7188                         result = updatesecure(db, version, &zone->origin,
7189                                               zone->minimum, ISC_TRUE,
7190                                               &nsec_diff);
7191                         if (result != ISC_R_SUCCESS) {
7192                                 dns_zone_log(zone, ISC_LOG_ERROR,
7193                                              "zone_nsec3chain:"
7194                                              "updatesecure -> %s",
7195                                              dns_result_totext(result));
7196                                 goto failure;
7197                         }
7198                 }
7199
7200                 if (rebuild_nsec3) {
7201                         if (nsec3chain != NULL)
7202                                 dns_dbiterator_pause(nsec3chain->dbiterator);
7203
7204                         result = dns_nsec3_addnsec3s(db, version,
7205                                                      dns_db_origin(db),
7206                                                      zone->minimum, ISC_FALSE,
7207                                                      &nsec3_diff);
7208                         if (result != ISC_R_SUCCESS) {
7209                                 dns_zone_log(zone, ISC_LOG_ERROR,
7210                                              "zone_nsec3chain:"
7211                                              "dns_nsec3_addnsec3s -> %s",
7212                                              dns_result_totext(result));
7213                                 goto failure;
7214                         }
7215                 }
7216         }
7217
7218         if (nsec3chain != NULL)
7219                 dns_dbiterator_pause(nsec3chain->dbiterator);
7220
7221         /*
7222          * Add / update signatures for the NSEC3 records.
7223          */
7224         if (nsec3chain != NULL)
7225                 dns_dbiterator_pause(nsec3chain->dbiterator);
7226         result = update_sigs(&nsec3_diff, db, version, zone_keys,
7227                              nkeys, zone, inception, expire, now,
7228                              check_ksk, keyset_kskonly, &zonediff);
7229         if (result != ISC_R_SUCCESS) {
7230                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7231                              "update_sigs -> %s", dns_result_totext(result));
7232                 goto failure;
7233         }
7234
7235         /*
7236          * We have changed the NSEC3PARAM or private RRsets
7237          * above so we need to update the signatures.
7238          */
7239         result = update_sigs(&param_diff, db, version, zone_keys,
7240                              nkeys, zone, inception, expire, now,
7241                              check_ksk, keyset_kskonly, &zonediff);
7242         if (result != ISC_R_SUCCESS) {
7243                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7244                              "update_sigs -> %s", dns_result_totext(result));
7245                 goto failure;
7246         }
7247
7248         if (updatensec) {
7249                 result = updatesecure(db, version, &zone->origin,
7250                                       zone->minimum, ISC_FALSE, &nsec_diff);
7251                 if (result != ISC_R_SUCCESS) {
7252                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7253                                      "updatesecure -> %s",
7254                                      dns_result_totext(result));
7255                         goto failure;
7256                 }
7257         }
7258
7259         result = update_sigs(&nsec_diff, db, version, zone_keys,
7260                              nkeys, zone, inception, expire, now,
7261                              check_ksk, keyset_kskonly, &zonediff);
7262         if (result != ISC_R_SUCCESS) {
7263                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7264                              "update_sigs -> %s", dns_result_totext(result));
7265                 goto failure;
7266         }
7267
7268         /*
7269          * If we made no effective changes to the zone then we can just
7270          * cleanup otherwise we need to increment the serial.
7271          */
7272         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7273                 /*
7274                  * No need to call dns_db_closeversion() here as it is
7275                  * called with commit = ISC_TRUE below.
7276                  */
7277                 goto done;
7278         }
7279
7280         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7281                           &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7282         if (result != ISC_R_SUCCESS) {
7283                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7284                              "del_sigs -> %s", dns_result_totext(result));
7285                 goto failure;
7286         }
7287
7288         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7289                                    zone->updatemethod);
7290         if (result != ISC_R_SUCCESS) {
7291                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7292                              "update_soa_serial -> %s",
7293                              dns_result_totext(result));
7294                 goto failure;
7295         }
7296
7297         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7298                           zonediff.diff, zone_keys, nkeys, zone->mctx,
7299                           inception, soaexpire, check_ksk, keyset_kskonly);
7300         if (result != ISC_R_SUCCESS) {
7301                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7302                              "add_sigs -> %s", dns_result_totext(result));
7303                 goto failure;
7304         }
7305
7306         /* Write changes to journal file. */
7307         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
7308
7309         LOCK_ZONE(zone);
7310         zone_needdump(zone, DNS_DUMP_DELAY);
7311         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7312         UNLOCK_ZONE(zone);
7313
7314  done:
7315         /*
7316          * Pause all iterators so that dns_db_closeversion() can succeed.
7317          */
7318         LOCK_ZONE(zone);
7319         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7320              nsec3chain != NULL;
7321              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7322                 dns_dbiterator_pause(nsec3chain->dbiterator);
7323         UNLOCK_ZONE(zone);
7324
7325         /*
7326          * Everything has succeeded. Commit the changes.
7327          * Unconditionally commit as zonediff.offline not checked above.
7328          */
7329         dns_db_closeversion(db, &version, ISC_TRUE);
7330
7331         /*
7332          * Everything succeeded so we can clean these up now.
7333          */
7334         nsec3chain = ISC_LIST_HEAD(cleanup);
7335         while (nsec3chain != NULL) {
7336                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7337                 dns_db_detach(&nsec3chain->db);
7338                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
7339                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7340                 nsec3chain = ISC_LIST_HEAD(cleanup);
7341         }
7342
7343         set_resigntime(zone);
7344
7345  failure:
7346         if (result != ISC_R_SUCCESS)
7347                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
7348                              dns_result_totext(result));
7349         /*
7350          * On error roll back the current nsec3chain.
7351          */
7352         if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
7353                 if (nsec3chain->done) {
7354                         dns_db_detach(&nsec3chain->db);
7355                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
7356                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7357                 } else {
7358                         result = dns_dbiterator_first(nsec3chain->dbiterator);
7359                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7360                         dns_dbiterator_pause(nsec3chain->dbiterator);
7361                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7362                 }
7363         }
7364
7365         /*
7366          * Rollback the cleanup list.
7367          */
7368         nsec3chain = ISC_LIST_TAIL(cleanup);
7369         while (nsec3chain != NULL) {
7370                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7371                 if (nsec3chain->done) {
7372                         dns_db_detach(&nsec3chain->db);
7373                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
7374                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7375                 } else {
7376                         LOCK_ZONE(zone);
7377                         ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
7378                         UNLOCK_ZONE(zone);
7379                         result = dns_dbiterator_first(nsec3chain->dbiterator);
7380                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7381                         dns_dbiterator_pause(nsec3chain->dbiterator);
7382                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7383                 }
7384                 nsec3chain = ISC_LIST_TAIL(cleanup);
7385         }
7386
7387         LOCK_ZONE(zone);
7388         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7389              nsec3chain != NULL;
7390              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7391                 dns_dbiterator_pause(nsec3chain->dbiterator);
7392         UNLOCK_ZONE(zone);
7393
7394         dns_diff_clear(&param_diff);
7395         dns_diff_clear(&nsec3_diff);
7396         dns_diff_clear(&nsec_diff);
7397         dns_diff_clear(&_sig_diff);
7398
7399         if (iterator != NULL)
7400                 dns_rdatasetiter_destroy(&iterator);
7401
7402         for (i = 0; i < nkeys; i++)
7403                 dst_key_free(&zone_keys[i]);
7404
7405         if (node != NULL)
7406                 dns_db_detachnode(db, &node);
7407         if (version != NULL) {
7408                 dns_db_closeversion(db, &version, ISC_FALSE);
7409                 dns_db_detach(&db);
7410         } else if (db != NULL)
7411                 dns_db_detach(&db);
7412
7413         LOCK_ZONE(zone);
7414         if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
7415                 isc_interval_t interval;
7416                 if (zone->update_disabled || result != ISC_R_SUCCESS)
7417                         isc_interval_set(&interval, 60, 0);       /* 1 minute */
7418                 else
7419                         isc_interval_set(&interval, 0, 10000000); /* 10 ms */
7420                 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
7421         } else
7422                 isc_time_settoepoch(&zone->nsec3chaintime);
7423         UNLOCK_ZONE(zone);
7424
7425         INSIST(version == NULL);
7426 }
7427
7428 static isc_result_t
7429 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7430         dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
7431         isc_uint16_t keyid, dns_diff_t *diff)
7432 {
7433         dns_rdata_rrsig_t rrsig;
7434         dns_rdataset_t rdataset;
7435         dns_rdatasetiter_t *iterator = NULL;
7436         isc_result_t result;
7437
7438         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7439         if (result != ISC_R_SUCCESS) {
7440                 if (result == ISC_R_NOTFOUND)
7441                         result = ISC_R_SUCCESS;
7442                 return (result);
7443         }
7444
7445         dns_rdataset_init(&rdataset);
7446         for (result = dns_rdatasetiter_first(iterator);
7447              result == ISC_R_SUCCESS;
7448              result = dns_rdatasetiter_next(iterator)) {
7449                 dns_rdatasetiter_current(iterator, &rdataset);
7450                 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
7451                         for (result = dns_rdataset_first(&rdataset);
7452                              result == ISC_R_SUCCESS;
7453                              result = dns_rdataset_next(&rdataset)) {
7454                                 dns_rdata_t rdata = DNS_RDATA_INIT;
7455                                 dns_rdataset_current(&rdataset, &rdata);
7456                                 CHECK(update_one_rr(db, version, diff,
7457                                                     DNS_DIFFOP_DEL, name,
7458                                                     rdataset.ttl, &rdata));
7459                         }
7460                         if (result != ISC_R_NOMORE)
7461                                 goto failure;
7462                         dns_rdataset_disassociate(&rdataset);
7463                         continue;
7464                 }
7465                 if (rdataset.type != dns_rdatatype_rrsig) {
7466                         dns_rdataset_disassociate(&rdataset);
7467                         continue;
7468                 }
7469                 for (result = dns_rdataset_first(&rdataset);
7470                      result == ISC_R_SUCCESS;
7471                      result = dns_rdataset_next(&rdataset)) {
7472                         dns_rdata_t rdata = DNS_RDATA_INIT;
7473                         dns_rdataset_current(&rdataset, &rdata);
7474                         CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
7475                         if (rrsig.algorithm != algorithm ||
7476                             rrsig.keyid != keyid)
7477                                 continue;
7478                         CHECK(update_one_rr(db, version, diff,
7479                                             DNS_DIFFOP_DELRESIGN, name,
7480                                             rdataset.ttl, &rdata));
7481                 }
7482                 dns_rdataset_disassociate(&rdataset);
7483                 if (result != ISC_R_NOMORE)
7484                         break;
7485         }
7486         if (result == ISC_R_NOMORE)
7487                 result = ISC_R_SUCCESS;
7488  failure:
7489         if (dns_rdataset_isassociated(&rdataset))
7490                 dns_rdataset_disassociate(&rdataset);
7491         dns_rdatasetiter_destroy(&iterator);
7492         return (result);
7493 }
7494
7495 /*
7496  * Incrementally sign the zone using the keys requested.
7497  * Builds the NSEC chain if required.
7498  */
7499 static void
7500 zone_sign(dns_zone_t *zone) {
7501         const char *me = "zone_sign";
7502         dns_db_t *db = NULL;
7503         dns_dbnode_t *node = NULL;
7504         dns_dbversion_t *version = NULL;
7505         dns_diff_t _sig_diff;
7506         dns_diff_t post_diff;
7507         zonediff_t zonediff;
7508         dns_fixedname_t fixed;
7509         dns_fixedname_t nextfixed;
7510         dns_name_t *name, *nextname;
7511         dns_rdataset_t rdataset;
7512         dns_signing_t *signing, *nextsigning;
7513         dns_signinglist_t cleanup;
7514         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7515         isc_int32_t signatures;
7516         isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
7517         isc_boolean_t commit = ISC_FALSE;
7518         isc_boolean_t delegation;
7519         isc_boolean_t build_nsec = ISC_FALSE;
7520         isc_boolean_t build_nsec3 = ISC_FALSE;
7521         isc_boolean_t first;
7522         isc_result_t result;
7523         isc_stdtime_t now, inception, soaexpire, expire;
7524         isc_uint32_t jitter;
7525         unsigned int i, j;
7526         unsigned int nkeys = 0;
7527         isc_uint32_t nodes;
7528
7529         ENTER;
7530
7531         dns_rdataset_init(&rdataset);
7532         dns_fixedname_init(&fixed);
7533         name = dns_fixedname_name(&fixed);
7534         dns_fixedname_init(&nextfixed);
7535         nextname = dns_fixedname_name(&nextfixed);
7536         dns_diff_init(zone->mctx, &_sig_diff);
7537         dns_diff_init(zone->mctx, &post_diff);
7538         zonediff_init(&zonediff, &_sig_diff);
7539         ISC_LIST_INIT(cleanup);
7540
7541         /*
7542          * Updates are disabled.  Pause for 5 minutes.
7543          */
7544         if (zone->update_disabled) {
7545                 result = ISC_R_FAILURE;
7546                 goto failure;
7547         }
7548
7549         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7550         if (zone->db != NULL)
7551                 dns_db_attach(zone->db, &db);
7552         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7553         if (db == NULL) {
7554                 result = ISC_R_FAILURE;
7555                 goto failure;
7556         }
7557
7558         result = dns_db_newversion(db, &version);
7559         if (result != ISC_R_SUCCESS) {
7560                 dns_zone_log(zone, ISC_LOG_ERROR,
7561                              "zone_sign:dns_db_newversion -> %s",
7562                              dns_result_totext(result));
7563                 goto failure;
7564         }
7565
7566         result = find_zone_keys(zone, db, version, zone->mctx,
7567                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7568         if (result != ISC_R_SUCCESS) {
7569                 dns_zone_log(zone, ISC_LOG_ERROR,
7570                              "zone_sign:find_zone_keys -> %s",
7571                              dns_result_totext(result));
7572                 goto failure;
7573         }
7574
7575         isc_stdtime_get(&now);
7576         inception = now - 3600; /* Allow for clock skew. */
7577         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
7578
7579         /*
7580          * Spread out signatures over time if they happen to be
7581          * clumped.  We don't do this for each add_sigs() call as
7582          * we still want some clustering to occur.
7583          */
7584         isc_random_get(&jitter);
7585         expire = soaexpire - jitter % 3600;
7586
7587         /*
7588          * We keep pulling nodes off each iterator in turn until
7589          * we have no more nodes to pull off or we reach the limits
7590          * for this quantum.
7591          */
7592         nodes = zone->nodes;
7593         signatures = zone->signatures;
7594         signing = ISC_LIST_HEAD(zone->signing);
7595         first = ISC_TRUE;
7596
7597         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7598         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7599
7600         /* Determine which type of chain to build */
7601         CHECK(dns_private_chains(db, version, zone->privatetype,
7602                                  &build_nsec, &build_nsec3));
7603
7604         /* If neither chain is found, default to NSEC */
7605         if (!build_nsec && !build_nsec3)
7606                 build_nsec = ISC_TRUE;
7607
7608         while (signing != NULL && nodes-- > 0 && signatures > 0) {
7609                 nextsigning = ISC_LIST_NEXT(signing, link);
7610
7611                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7612                 if (signing->done || signing->db != zone->db) {
7613                         /*
7614                          * The zone has been reloaded.  We will have
7615                          * created new signings as part of the reload
7616                          * process so we can destroy this one.
7617                          */
7618                         ISC_LIST_UNLINK(zone->signing, signing, link);
7619                         ISC_LIST_APPEND(cleanup, signing, link);
7620                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7621                         goto next_signing;
7622                 }
7623                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7624
7625                 if (signing->db != db)
7626                         goto next_signing;
7627
7628                 delegation = ISC_FALSE;
7629
7630                 if (first && signing->delete) {
7631                         /*
7632                          * Remove the key we are deleting from consideration.
7633                          */
7634                         for (i = 0, j = 0; i < nkeys; i++) {
7635                                 /*
7636                                  * Find the key we want to remove.
7637                                  */
7638                                 if (ALG(zone_keys[i]) == signing->algorithm &&
7639                                     dst_key_id(zone_keys[i]) == signing->keyid)
7640                                 {
7641                                         if (KSK(zone_keys[i]))
7642                                                 dst_key_free(&zone_keys[i]);
7643                                         continue;
7644                                 }
7645                                 zone_keys[j] = zone_keys[i];
7646                                 j++;
7647                         }
7648                         nkeys = j;
7649                 }
7650
7651                 dns_dbiterator_current(signing->dbiterator, &node, name);
7652
7653                 if (signing->delete) {
7654                         dns_dbiterator_pause(signing->dbiterator);
7655                         CHECK(del_sig(db, version, name, node, nkeys,
7656                                       signing->algorithm, signing->keyid,
7657                                       zonediff.diff));
7658                 }
7659
7660                 /*
7661                  * On the first pass we need to check if the current node
7662                  * has not been obscured.
7663                  */
7664                 if (first) {
7665                         dns_fixedname_t ffound;
7666                         dns_name_t *found;
7667                         dns_fixedname_init(&ffound);
7668                         found = dns_fixedname_name(&ffound);
7669                         result = dns_db_find(db, name, version,
7670                                              dns_rdatatype_soa,
7671                                              DNS_DBFIND_NOWILD, 0, NULL, found,
7672                                              NULL, NULL);
7673                         if ((result == DNS_R_DELEGATION ||
7674                             result == DNS_R_DNAME) &&
7675                             !dns_name_equal(name, found)) {
7676                                 /*
7677                                  * Remember the obscuring name so that
7678                                  * we skip all obscured names.
7679                                  */
7680                                 dns_name_copy(found, name, NULL);
7681                                 delegation = ISC_TRUE;
7682                                 goto next_node;
7683                         }
7684                 }
7685
7686                 /*
7687                  * Process one node.
7688                  */
7689                 dns_dbiterator_pause(signing->dbiterator);
7690                 for (i = 0; i < nkeys; i++) {
7691                         isc_boolean_t both = ISC_FALSE;
7692
7693                         /*
7694                          * Find the keys we want to sign with.
7695                          */
7696                         if (!dst_key_isprivate(zone_keys[i]))
7697                                 continue;
7698
7699                         /*
7700                          * When adding look for the specific key.
7701                          */
7702                         if (!signing->delete &&
7703                             (dst_key_alg(zone_keys[i]) != signing->algorithm ||
7704                              dst_key_id(zone_keys[i]) != signing->keyid))
7705                                 continue;
7706
7707                         /*
7708                          * When deleting make sure we are properly signed
7709                          * with the algorithm that was being removed.
7710                          */
7711                         if (signing->delete &&
7712                             ALG(zone_keys[i]) != signing->algorithm)
7713                                 continue;
7714
7715                         /*
7716                          * Do we do KSK processing?
7717                          */
7718                         if (check_ksk && !REVOKE(zone_keys[i])) {
7719                                 isc_boolean_t have_ksk, have_nonksk;
7720                                 if (KSK(zone_keys[i])) {
7721                                         have_ksk = ISC_TRUE;
7722                                         have_nonksk = ISC_FALSE;
7723                                 } else {
7724                                         have_ksk = ISC_FALSE;
7725                                         have_nonksk = ISC_TRUE;
7726                                 }
7727                                 for (j = 0; j < nkeys; j++) {
7728                                         if (j == i ||
7729                                             ALG(zone_keys[i]) !=
7730                                             ALG(zone_keys[j]))
7731                                                 continue;
7732                                         if (REVOKE(zone_keys[j]))
7733                                                 continue;
7734                                         if (KSK(zone_keys[j]))
7735                                                 have_ksk = ISC_TRUE;
7736                                         else
7737                                                 have_nonksk = ISC_TRUE;
7738                                         both = have_ksk && have_nonksk;
7739                                         if (both)
7740                                                 break;
7741                                 }
7742                         }
7743                         if (both || REVOKE(zone_keys[i]))
7744                                 is_ksk = KSK(zone_keys[i]);
7745                         else
7746                                 is_ksk = ISC_FALSE;
7747
7748                         CHECK(sign_a_node(db, name, node, version, build_nsec3,
7749                                           build_nsec, zone_keys[i], inception,
7750                                           expire, zone->minimum, is_ksk,
7751                                           ISC_TF(both && keyset_kskonly),
7752                                           &delegation, zonediff.diff,
7753                                           &signatures, zone->mctx));
7754                         /*
7755                          * If we are adding we are done.  Look for other keys
7756                          * of the same algorithm if deleting.
7757                          */
7758                         if (!signing->delete)
7759                                 break;
7760                 }
7761
7762                 /*
7763                  * Go onto next node.
7764                  */
7765  next_node:
7766                 first = ISC_FALSE;
7767                 dns_db_detachnode(db, &node);
7768                 do {
7769                         result = dns_dbiterator_next(signing->dbiterator);
7770                         if (result == ISC_R_NOMORE) {
7771                                 ISC_LIST_UNLINK(zone->signing, signing, link);
7772                                 ISC_LIST_APPEND(cleanup, signing, link);
7773                                 dns_dbiterator_pause(signing->dbiterator);
7774                                 if (nkeys != 0 && build_nsec) {
7775                                         /*
7776                                          * We have finished regenerating the
7777                                          * zone with a zone signing key.
7778                                          * The NSEC chain is now complete and
7779                                          * there is a full set of signatures
7780                                          * for the zone.  We can now clear the
7781                                          * OPT bit from the NSEC record.
7782                                          */
7783                                         result = updatesecure(db, version,
7784                                                               &zone->origin,
7785                                                               zone->minimum,
7786                                                               ISC_FALSE,
7787                                                               &post_diff);
7788                                         if (result != ISC_R_SUCCESS) {
7789                                                 dns_zone_log(zone,
7790                                                              ISC_LOG_ERROR,
7791                                                     "updatesecure -> %s",
7792                                                     dns_result_totext(result));
7793                                                 goto failure;
7794                                         }
7795                                 }
7796                                 result = updatesignwithkey(zone, signing,
7797                                                            version,
7798                                                            build_nsec3,
7799                                                            zone->minimum,
7800                                                            &post_diff);
7801                                 if (result != ISC_R_SUCCESS) {
7802                                         dns_zone_log(zone, ISC_LOG_ERROR,
7803                                                      "updatesignwithkey -> %s",
7804                                                      dns_result_totext(result));
7805                                         goto failure;
7806                                 }
7807                                 build_nsec = ISC_FALSE;
7808                                 goto next_signing;
7809                         } else if (result != ISC_R_SUCCESS) {
7810                                 dns_zone_log(zone, ISC_LOG_ERROR,
7811                                         "zone_sign:dns_dbiterator_next -> %s",
7812                                              dns_result_totext(result));
7813                                 goto failure;
7814                         } else if (delegation) {
7815                                 dns_dbiterator_current(signing->dbiterator,
7816                                                        &node, nextname);
7817                                 dns_db_detachnode(db, &node);
7818                                 if (!dns_name_issubdomain(nextname, name))
7819                                         break;
7820                         } else
7821                                 break;
7822                 } while (1);
7823                 continue;
7824
7825  next_signing:
7826                 dns_dbiterator_pause(signing->dbiterator);
7827                 signing = nextsigning;
7828                 first = ISC_TRUE;
7829         }
7830
7831         if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
7832                 result = update_sigs(&post_diff, db, version, zone_keys,
7833                                      nkeys, zone, inception, expire, now,
7834                                      check_ksk, keyset_kskonly, &zonediff);
7835                 if (result != ISC_R_SUCCESS) {
7836                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
7837                                      "update_sigs -> %s",
7838                                      dns_result_totext(result));
7839                         goto failure;
7840                 }
7841         }
7842
7843         /*
7844          * Have we changed anything?
7845          */
7846         if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7847                 if (zonediff.offline)
7848                         commit = ISC_TRUE;
7849                 result = ISC_R_SUCCESS;
7850                 goto pauseall;
7851         }
7852
7853         commit = ISC_TRUE;
7854
7855         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7856                           &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7857         if (result != ISC_R_SUCCESS) {
7858                 dns_zone_log(zone, ISC_LOG_ERROR,
7859                              "zone_sign:del_sigs -> %s",
7860                              dns_result_totext(result));
7861                 goto failure;
7862         }
7863
7864         result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7865                                    zone->updatemethod);
7866         if (result != ISC_R_SUCCESS) {
7867                 dns_zone_log(zone, ISC_LOG_ERROR,
7868                              "zone_sign:update_soa_serial -> %s",
7869                              dns_result_totext(result));
7870                 goto failure;
7871         }
7872
7873         /*
7874          * Generate maximum life time signatures so that the above loop
7875          * termination is sensible.
7876          */
7877         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7878                           zonediff.diff, zone_keys, nkeys, zone->mctx,
7879                           inception, soaexpire, check_ksk, keyset_kskonly);
7880         if (result != ISC_R_SUCCESS) {
7881                 dns_zone_log(zone, ISC_LOG_ERROR,
7882                              "zone_sign:add_sigs -> %s",
7883                              dns_result_totext(result));
7884                 goto failure;
7885         }
7886
7887         /*
7888          * Write changes to journal file.
7889          */
7890         CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
7891
7892  pauseall:
7893         /*
7894          * Pause all iterators so that dns_db_closeversion() can succeed.
7895          */
7896         for (signing = ISC_LIST_HEAD(zone->signing);
7897              signing != NULL;
7898              signing = ISC_LIST_NEXT(signing, link))
7899                 dns_dbiterator_pause(signing->dbiterator);
7900
7901         for (signing = ISC_LIST_HEAD(cleanup);
7902              signing != NULL;
7903              signing = ISC_LIST_NEXT(signing, link))
7904                 dns_dbiterator_pause(signing->dbiterator);
7905
7906         /*
7907          * Everything has succeeded. Commit the changes.
7908          */
7909         dns_db_closeversion(db, &version, commit);
7910
7911         /*
7912          * Everything succeeded so we can clean these up now.
7913          */
7914         signing = ISC_LIST_HEAD(cleanup);
7915         while (signing != NULL) {
7916                 ISC_LIST_UNLINK(cleanup, signing, link);
7917                 dns_db_detach(&signing->db);
7918                 dns_dbiterator_destroy(&signing->dbiterator);
7919                 isc_mem_put(zone->mctx, signing, sizeof *signing);
7920                 signing = ISC_LIST_HEAD(cleanup);
7921         }
7922
7923         set_resigntime(zone);
7924
7925         if (commit) {
7926                 LOCK_ZONE(zone);
7927                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7928                 zone_needdump(zone, DNS_DUMP_DELAY);
7929                 UNLOCK_ZONE(zone);
7930         }
7931
7932  failure:
7933         /*
7934          * Rollback the cleanup list.
7935          */
7936         signing = ISC_LIST_HEAD(cleanup);
7937         while (signing != NULL) {
7938                 ISC_LIST_UNLINK(cleanup, signing, link);
7939                 ISC_LIST_PREPEND(zone->signing, signing, link);
7940                 dns_dbiterator_first(signing->dbiterator);
7941                 dns_dbiterator_pause(signing->dbiterator);
7942                 signing = ISC_LIST_HEAD(cleanup);
7943         }
7944
7945         for (signing = ISC_LIST_HEAD(zone->signing);
7946              signing != NULL;
7947              signing = ISC_LIST_NEXT(signing, link))
7948                 dns_dbiterator_pause(signing->dbiterator);
7949
7950         dns_diff_clear(&_sig_diff);
7951
7952         for (i = 0; i < nkeys; i++)
7953                 dst_key_free(&zone_keys[i]);
7954
7955         if (node != NULL)
7956                 dns_db_detachnode(db, &node);
7957
7958         if (version != NULL) {
7959                 dns_db_closeversion(db, &version, ISC_FALSE);
7960                 dns_db_detach(&db);
7961         } else if (db != NULL)
7962                 dns_db_detach(&db);
7963
7964         if (ISC_LIST_HEAD(zone->signing) != NULL) {
7965                 isc_interval_t interval;
7966                 if (zone->update_disabled || result != ISC_R_SUCCESS)
7967                         isc_interval_set(&interval, 60, 0);       /* 1 minute */
7968                 else
7969                         isc_interval_set(&interval, 0, 10000000); /* 10 ms */
7970                 isc_time_nowplusinterval(&zone->signingtime, &interval);
7971         } else
7972                 isc_time_settoepoch(&zone->signingtime);
7973
7974         INSIST(version == NULL);
7975 }
7976
7977 static isc_result_t
7978 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
7979               unsigned char *data, int size)
7980 {
7981         dns_rdata_dnskey_t dnskey;
7982         dns_rdata_keydata_t keydata;
7983         isc_buffer_t buf;
7984         isc_result_t result;
7985
7986         dns_rdata_reset(target);
7987         isc_buffer_init(&buf, data, size);
7988
7989         switch (rr->type) {
7990             case dns_rdatatype_dnskey:
7991                 result = dns_rdata_tostruct(rr, &dnskey, NULL);
7992                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7993                 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
7994                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7995                                      &dnskey, &buf);
7996                 break;
7997             case dns_rdatatype_keydata:
7998                 result = dns_rdata_tostruct(rr, &keydata, NULL);
7999                 if (result == ISC_R_UNEXPECTEDEND)
8000                         return (result);
8001                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8002                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
8003                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
8004                                      &dnskey, &buf);
8005                 break;
8006             default:
8007                 INSIST(0);
8008         }
8009         return (ISC_R_SUCCESS);
8010 }
8011
8012 /*
8013  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
8014  * a KEYDATA rdataset from the key zone.
8015  *
8016  * 'rr' contains either a DNSKEY record, or a KEYDATA record
8017  *
8018  * After normalizing keys to the same format (DNSKEY, with revoke bit
8019  * cleared), return ISC_TRUE if a key that matches 'rr' is found in
8020  * 'rdset', or ISC_FALSE if not.
8021  */
8022
8023 static isc_boolean_t
8024 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
8025         unsigned char data1[4096], data2[4096];
8026         dns_rdata_t rdata, rdata1, rdata2;
8027         isc_result_t result;
8028
8029         dns_rdata_init(&rdata);
8030         dns_rdata_init(&rdata1);
8031         dns_rdata_init(&rdata2);
8032
8033         result = normalize_key(rr, &rdata1, data1, sizeof(data1));
8034         if (result != ISC_R_SUCCESS)
8035                 return (ISC_FALSE);
8036
8037         for (result = dns_rdataset_first(rdset);
8038              result == ISC_R_SUCCESS;
8039              result = dns_rdataset_next(rdset)) {
8040                 dns_rdata_reset(&rdata);
8041                 dns_rdataset_current(rdset, &rdata);
8042                 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
8043                 if (result != ISC_R_SUCCESS)
8044                         continue;
8045                 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
8046                         return (ISC_TRUE);
8047         }
8048
8049         return (ISC_FALSE);
8050 }
8051
8052 /*
8053  * Calculate the refresh interval for a keydata zone, per
8054  * RFC5011: MAX(1 hr,
8055  *              MIN(15 days,
8056  *                  1/2 * OrigTTL,
8057  *                  1/2 * RRSigExpirationInterval))
8058  * or for retries: MAX(1 hr,
8059  *                     MIN(1 day,
8060  *                         1/10 * OrigTTL,
8061  *                         1/10 * RRSigExpirationInterval))
8062  */
8063 static inline isc_stdtime_t
8064 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
8065         isc_result_t result;
8066         isc_uint32_t t;
8067         dns_rdataset_t *rdset;
8068         dns_rdata_t sigrr = DNS_RDATA_INIT;
8069         dns_rdata_sig_t sig;
8070         isc_stdtime_t now;
8071
8072         isc_stdtime_get(&now);
8073
8074         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8075                 rdset = &kfetch->dnskeysigset;
8076         else
8077                 return (now + dns_zone_mkey_hour);
8078
8079         result = dns_rdataset_first(rdset);
8080         if (result != ISC_R_SUCCESS)
8081                 return (now + dns_zone_mkey_hour);
8082
8083         dns_rdataset_current(rdset, &sigrr);
8084         result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8085         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8086
8087         if (!retry) {
8088                 t = sig.originalttl / 2;
8089
8090                 if (isc_serial_gt(sig.timeexpire, now)) {
8091                         isc_uint32_t exp = (sig.timeexpire - now) / 2;
8092                         if (t > exp)
8093                                 t = exp;
8094                 }
8095
8096                 if (t > (15 * dns_zone_mkey_day))
8097                         t = (15 * dns_zone_mkey_day);
8098
8099                 if (t < dns_zone_mkey_hour)
8100                         t = dns_zone_mkey_hour;
8101         } else {
8102                 t = sig.originalttl / 10;
8103
8104                 if (isc_serial_gt(sig.timeexpire, now)) {
8105                         isc_uint32_t exp = (sig.timeexpire - now) / 10;
8106                         if (t > exp)
8107                                 t = exp;
8108                 }
8109
8110                 if (t > dns_zone_mkey_day)
8111                         t = dns_zone_mkey_day;
8112
8113                 if (t < dns_zone_mkey_hour)
8114                         t = dns_zone_mkey_hour;
8115         }
8116
8117         return (now + t);
8118 }
8119
8120 /*
8121  * This routine is called when no changes are needed in a KEYDATA
8122  * record except to simply update the refresh timer.  Caller should
8123  * hold zone lock.
8124  */
8125 static isc_result_t
8126 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
8127 {
8128         isc_result_t result;
8129         isc_buffer_t keyb;
8130         unsigned char key_buf[4096];
8131         dns_rdata_t rdata = DNS_RDATA_INIT;
8132         dns_rdata_keydata_t keydata;
8133         dns_name_t *name;
8134         dns_zone_t *zone = kfetch->zone;
8135         isc_stdtime_t now;
8136
8137         name = dns_fixedname_name(&kfetch->name);
8138         isc_stdtime_get(&now);
8139
8140         for (result = dns_rdataset_first(&kfetch->keydataset);
8141              result == ISC_R_SUCCESS;
8142              result = dns_rdataset_next(&kfetch->keydataset)) {
8143                 dns_rdata_reset(&rdata);
8144                 dns_rdataset_current(&kfetch->keydataset, &rdata);
8145
8146                 /* Delete old version */
8147                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
8148                                     name, 0, &rdata));
8149
8150                 /* Update refresh timer */
8151                 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
8152                 if (result == ISC_R_UNEXPECTEDEND)
8153                         continue;
8154                 if (result != ISC_R_SUCCESS)
8155                         goto failure;
8156                 keydata.refresh = refresh_time(kfetch, ISC_TRUE);
8157                 set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
8158
8159                 dns_rdata_reset(&rdata);
8160                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8161                 CHECK(dns_rdata_fromstruct(&rdata,
8162                                            zone->rdclass, dns_rdatatype_keydata,
8163                                            &keydata, &keyb));
8164
8165                 /* Insert updated version */
8166                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
8167                                     name, 0, &rdata));
8168         }
8169         result = ISC_R_SUCCESS;
8170   failure:
8171         return (result);
8172 }
8173
8174 /*
8175  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
8176  */
8177 static isc_boolean_t
8178 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
8179         isc_result_t result;
8180         dns_name_t *keyname;
8181         isc_mem_t *mctx;
8182         dns_rdata_t sigrr = DNS_RDATA_INIT;
8183         dns_rdata_t rr = DNS_RDATA_INIT;
8184         dns_rdata_rrsig_t sig;
8185         dns_rdata_dnskey_t dnskey;
8186         dst_key_t *dstkey = NULL;
8187         unsigned char key_buf[4096];
8188         isc_buffer_t keyb;
8189         isc_boolean_t answer = ISC_FALSE;
8190
8191         REQUIRE(kfetch != NULL && keydata != NULL);
8192         REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
8193
8194         keyname = dns_fixedname_name(&kfetch->name);
8195         mctx = kfetch->zone->view->mctx;
8196
8197         /* Generate a key from keydata */
8198         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8199         dns_keydata_todnskey(keydata, &dnskey, NULL);
8200         dns_rdata_fromstruct(&rr, keydata->common.rdclass,
8201                              dns_rdatatype_dnskey, &dnskey, &keyb);
8202         result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
8203         if (result != ISC_R_SUCCESS)
8204                 return (ISC_FALSE);
8205
8206         /* See if that key generated any of the signatures */
8207         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8208              result == ISC_R_SUCCESS;
8209              result = dns_rdataset_next(&kfetch->dnskeysigset))
8210         {
8211                 dns_fixedname_t fixed;
8212                 dns_fixedname_init(&fixed);
8213
8214                 dns_rdata_reset(&sigrr);
8215                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8216                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8217                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8218
8219                 if (dst_key_alg(dstkey) == sig.algorithm &&
8220                     dst_key_rid(dstkey) == sig.keyid)
8221                 {
8222                         result = dns_dnssec_verify2(keyname,
8223                                             &kfetch->dnskeyset,
8224                                             dstkey, ISC_FALSE, mctx, &sigrr,
8225                                             dns_fixedname_name(&fixed));
8226
8227                         dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
8228                                      "Confirm revoked DNSKEY is self-signed: "
8229                                      "%s", dns_result_totext(result));
8230
8231                         if (result == ISC_R_SUCCESS) {
8232                                 answer = ISC_TRUE;
8233                                 break;
8234                         }
8235                 }
8236         }
8237
8238         dst_key_free(&dstkey);
8239         return (answer);
8240 }
8241
8242 /*
8243  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
8244  * anchors are being managed; scan the keyset, and update the key zone and the
8245  * local trust anchors according to RFC5011.
8246  */
8247 static void
8248 keyfetch_done(isc_task_t *task, isc_event_t *event) {
8249         isc_result_t result, eresult;
8250         dns_fetchevent_t *devent;
8251         dns_keyfetch_t *kfetch;
8252         dns_zone_t *zone;
8253         isc_mem_t *mctx = NULL;
8254         dns_keytable_t *secroots = NULL;
8255         dns_dbversion_t *ver = NULL;
8256         dns_diff_t diff;
8257         isc_boolean_t alldone = ISC_FALSE;
8258         isc_boolean_t commit = ISC_FALSE;
8259         dns_name_t *keyname;
8260         dns_rdata_t sigrr = DNS_RDATA_INIT;
8261         dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
8262         dns_rdata_t keydatarr = DNS_RDATA_INIT;
8263         dns_rdata_rrsig_t sig;
8264         dns_rdata_dnskey_t dnskey;
8265         dns_rdata_keydata_t keydata;
8266         isc_boolean_t initializing;
8267         char namebuf[DNS_NAME_FORMATSIZE];
8268         unsigned char key_buf[4096];
8269         isc_buffer_t keyb;
8270         dst_key_t *dstkey;
8271         isc_stdtime_t now;
8272         int pending = 0;
8273         isc_boolean_t secure;
8274         isc_boolean_t free_needed;
8275
8276         UNUSED(task);
8277         INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
8278         INSIST(event->ev_arg != NULL);
8279
8280         kfetch = event->ev_arg;
8281         zone = kfetch->zone;
8282         isc_mem_attach(zone->mctx, &mctx);
8283         keyname = dns_fixedname_name(&kfetch->name);
8284
8285         devent = (dns_fetchevent_t *) event;
8286         eresult = devent->result;
8287
8288         /* Free resources which are not of interest */
8289         if (devent->node != NULL)
8290                 dns_db_detachnode(devent->db, &devent->node);
8291         if (devent->db != NULL)
8292                 dns_db_detach(&devent->db);
8293         isc_event_free(&event);
8294         dns_resolver_destroyfetch(&kfetch->fetch);
8295
8296         LOCK_ZONE(zone);
8297         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
8298                 goto cleanup;
8299
8300         isc_stdtime_get(&now);
8301         dns_name_format(keyname, namebuf, sizeof(namebuf));
8302
8303         result = dns_view_getsecroots(zone->view, &secroots);
8304         INSIST(result == ISC_R_SUCCESS);
8305
8306         dns_diff_init(mctx, &diff);
8307
8308         CHECK(dns_db_newversion(kfetch->db, &ver));
8309
8310         zone->refreshkeycount--;
8311         alldone = ISC_TF(zone->refreshkeycount == 0);
8312
8313         if (alldone)
8314                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8315
8316         /* Fetch failed */
8317         if (eresult != ISC_R_SUCCESS ||
8318             !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
8319                 dns_zone_log(zone, ISC_LOG_WARNING,
8320                              "Unable to fetch DNSKEY set "
8321                              "'%s': %s", namebuf, dns_result_totext(eresult));
8322                 CHECK(minimal_update(kfetch, ver, &diff));
8323                 goto done;
8324         }
8325
8326         /* No RRSIGs found */
8327         if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
8328                 dns_zone_log(zone, ISC_LOG_WARNING,
8329                              "No DNSKEY RRSIGs found for "
8330                              "'%s': %s", namebuf, dns_result_totext(eresult));
8331                 CHECK(minimal_update(kfetch, ver, &diff));
8332                 goto done;
8333         }
8334
8335         /*
8336          * Clear any cached trust level, as we need to run validation
8337          * over again; trusted keys might have changed.
8338          */
8339         kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
8340
8341         /*
8342          * Validate the dnskeyset against the current trusted keys.
8343          */
8344         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8345              result == ISC_R_SUCCESS;
8346              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
8347                 dns_keynode_t *keynode = NULL;
8348
8349                 dns_rdata_reset(&sigrr);
8350                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8351                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8352                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8353
8354                 result = dns_keytable_find(secroots, keyname, &keynode);
8355                 while (result == ISC_R_SUCCESS) {
8356                         dns_keynode_t *nextnode = NULL;
8357                         dns_fixedname_t fixed;
8358                         dns_fixedname_init(&fixed);
8359
8360                         dstkey = dns_keynode_key(keynode);
8361                         if (dstkey == NULL) /* fail_secure() was called */
8362                                 break;
8363
8364                         if (dst_key_alg(dstkey) == sig.algorithm &&
8365                             dst_key_id(dstkey) == sig.keyid) {
8366                                 result = dns_dnssec_verify2(keyname,
8367                                                     &kfetch->dnskeyset,
8368                                                     dstkey, ISC_FALSE,
8369                                                     zone->view->mctx, &sigrr,
8370                                                     dns_fixedname_name(&fixed));
8371
8372                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
8373                                              "Verifying DNSKEY set for zone "
8374                                              "'%s' using key %d/%d: %s",
8375                                              namebuf, sig.keyid, sig.algorithm,
8376                                              dns_result_totext(result));
8377
8378                                 if (result == ISC_R_SUCCESS) {
8379                                         kfetch->dnskeyset.trust =
8380                                                 dns_trust_secure;
8381                                         kfetch->dnskeysigset.trust =
8382                                                 dns_trust_secure;
8383                                         break;
8384                                 }
8385                         }
8386
8387                         result = dns_keytable_nextkeynode(secroots,
8388                                                           keynode, &nextnode);
8389                         dns_keytable_detachkeynode(secroots, &keynode);
8390                         keynode = nextnode;
8391                 }
8392
8393                 if (keynode != NULL)
8394                         dns_keytable_detachkeynode(secroots, &keynode);
8395
8396                 if (kfetch->dnskeyset.trust == dns_trust_secure)
8397                         break;
8398         }
8399
8400         /*
8401          * If we were not able to verify the answer using the current
8402          * trusted keys then all we can do is look at any revoked keys.
8403          */
8404         secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
8405
8406         /*
8407          * First scan keydataset to find keys that are not in dnskeyset
8408          *   - Missing keys which are not scheduled for removal,
8409          *     log a warning
8410          *   - Missing keys which are scheduled for removal and
8411          *     the remove hold-down timer has completed should
8412          *     be removed from the key zone
8413          *   - Missing keys whose acceptance timers have not yet
8414          *     completed, log a warning and reset the acceptance
8415          *     timer to 30 days in the future
8416          *   - All keys not being removed have their refresh timers
8417          *     updated
8418          */
8419         initializing = ISC_TRUE;
8420         for (result = dns_rdataset_first(&kfetch->keydataset);
8421              result == ISC_R_SUCCESS;
8422              result = dns_rdataset_next(&kfetch->keydataset)) {
8423                 dns_rdata_reset(&keydatarr);
8424                 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8425                 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8426                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8427
8428                 /*
8429                  * If any keydata record has a nonzero add holddown, then
8430                  * there was a pre-existing trust anchor for this domain;
8431                  * that means we are *not* initializing it and shouldn't
8432                  * automatically trust all the keys we find at the zone apex.
8433                  */
8434                 initializing = initializing && ISC_TF(keydata.addhd == 0);
8435
8436                 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
8437                         isc_boolean_t deletekey = ISC_FALSE;
8438
8439                         if (!secure) {
8440                                 if (keydata.removehd != 0 &&
8441                                     keydata.removehd <= now)
8442                                         deletekey = ISC_TRUE;
8443                         } else if (keydata.addhd == 0) {
8444                                 deletekey = ISC_TRUE;
8445                         } else if (keydata.addhd > now) {
8446                                 dns_zone_log(zone, ISC_LOG_WARNING,
8447                                              "Pending key unexpectedly missing "
8448                                              "from %s; restarting acceptance "
8449                                              "timer", namebuf);
8450                                 if (keydata.addhd < now + dns_zone_mkey_month)
8451                                         keydata.addhd =
8452                                                 now + dns_zone_mkey_month;
8453                                 keydata.refresh = refresh_time(kfetch,
8454                                                                ISC_FALSE);
8455                         } else if (keydata.removehd == 0) {
8456                                 dns_zone_log(zone, ISC_LOG_WARNING,
8457                                              "Active key unexpectedly missing "
8458                                              "from %s", namebuf);
8459                                 keydata.refresh = now + dns_zone_mkey_hour;
8460                         } else if (keydata.removehd <= now) {
8461                                 deletekey = ISC_TRUE;
8462                         } else {
8463                                 keydata.refresh = refresh_time(kfetch,
8464                                                                ISC_FALSE);
8465                         }
8466
8467                         if (secure || deletekey) {
8468                                 /* Delete old version */
8469                                 CHECK(update_one_rr(kfetch->db, ver, &diff,
8470                                                     DNS_DIFFOP_DEL, keyname, 0,
8471                                                     &keydatarr));
8472                         }
8473
8474                         if (!secure || deletekey)
8475                                 continue;
8476
8477                         dns_rdata_reset(&keydatarr);
8478                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8479                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8480                                              dns_rdatatype_keydata,
8481                                              &keydata, &keyb);
8482
8483                         /* Insert updated version */
8484                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8485                                             DNS_DIFFOP_ADD, keyname, 0,
8486                                             &keydatarr));
8487
8488                         set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
8489                 }
8490         }
8491
8492         /*
8493          * Next scan dnskeyset:
8494          *   - If new keys are found (i.e., lacking a match in keydataset)
8495          *     add them to the key zone and set the acceptance timer
8496          *     to 30 days in the future (or to immediately if we've
8497          *     determined that we're initializing the zone for the
8498          *     first time)
8499          *   - Previously-known keys that have been revoked
8500          *     must be scheduled for removal from the key zone (or,
8501          *     if they hadn't been accepted as trust anchors yet
8502          *     anyway, removed at once)
8503          *   - Previously-known unrevoked keys whose acceptance timers
8504          *     have completed are promoted to trust anchors
8505          *   - All keys not being removed have their refresh
8506          *     timers updated
8507          */
8508         for (result = dns_rdataset_first(&kfetch->dnskeyset);
8509              result == ISC_R_SUCCESS;
8510              result = dns_rdataset_next(&kfetch->dnskeyset))
8511         {
8512                 isc_boolean_t revoked = ISC_FALSE;
8513                 isc_boolean_t newkey = ISC_FALSE;
8514                 isc_boolean_t updatekey = ISC_FALSE;
8515                 isc_boolean_t deletekey = ISC_FALSE;
8516                 isc_boolean_t trustkey = ISC_FALSE;
8517
8518                 dns_rdata_reset(&dnskeyrr);
8519                 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
8520                 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8521                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8522
8523                 /* Skip ZSK's */
8524                 if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
8525                         continue;
8526
8527                 revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
8528
8529                 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
8530                         dns_rdata_reset(&keydatarr);
8531                         dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8532                         result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8533                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8534
8535                         if (revoked && revocable(kfetch, &keydata)) {
8536                                 if (keydata.addhd > now) {
8537                                         /*
8538                                          * Key wasn't trusted yet, and now
8539                                          * it's been revoked?  Just remove it
8540                                          */
8541                                         deletekey = ISC_TRUE;
8542                                 } else if (keydata.removehd == 0) {
8543                                         /* Remove from secroots */
8544                                         dns_view_untrust(zone->view, keyname,
8545                                                          &dnskey, mctx);
8546
8547                                         /* But ensure there's a null key */
8548                                         fail_secure(zone, keyname);
8549
8550                                         /* If initializing, delete now */
8551                                         if (keydata.addhd == 0)
8552                                                 deletekey = ISC_TRUE;
8553                                         else {
8554                                                 keydata.removehd = now +
8555                                                         dns_zone_mkey_month;
8556                                                 keydata.flags |=
8557                                                         DNS_KEYFLAG_REVOKE;
8558                                         }
8559                                 } else if (keydata.removehd < now) {
8560                                         /* Scheduled for removal */
8561                                         deletekey = ISC_TRUE;
8562                                 }
8563                         } else if (revoked && keydata.removehd == 0) {
8564                                 dns_zone_log(zone, ISC_LOG_WARNING,
8565                                              "Active key for zone "
8566                                              "'%s' is revoked but "
8567                                              "did not self-sign; "
8568                                              "ignoring.", namebuf);
8569                                         continue;
8570                         } else if (secure) {
8571                                 if (keydata.removehd != 0) {
8572                                         /*
8573                                          * Key isn't revoked--but it
8574                                          * seems it used to be.
8575                                          * Remove it now and add it
8576                                          * back as if it were a fresh key,
8577                                          * with a 30 day acceptance timer.
8578                                          */
8579                                         deletekey = ISC_TRUE;
8580                                         newkey = ISC_TRUE;
8581                                         keydata.removehd = 0;
8582                                         keydata.addhd =
8583                                                 now + dns_zone_mkey_month;
8584                                 } else if (keydata.addhd > now)
8585                                         pending++;
8586                                 else if (keydata.addhd == 0)
8587                                         keydata.addhd = now;
8588
8589                                 if (keydata.addhd <= now)
8590                                         trustkey = ISC_TRUE;
8591                         } else if (keydata.addhd > now) {
8592                                 /*
8593                                  * Not secure, and key is pending:
8594                                  * reset the acceptance timer
8595                                  */
8596                                 pending++;
8597                                 keydata.addhd = now + dns_zone_mkey_month;
8598                         }
8599
8600                         if (!deletekey && !newkey)
8601                                 updatekey = ISC_TRUE;
8602                 } else if (secure) {
8603                         /*
8604                          * Key wasn't in the key zone but it's
8605                          * revoked now anyway, so just skip it
8606                          */
8607                         if (revoked)
8608                                 continue;
8609
8610                         /* Key wasn't in the key zone: add it */
8611                         newkey = ISC_TRUE;
8612
8613                         if (initializing) {
8614                                 dns_keytag_t tag = 0;
8615                                 CHECK(compute_tag(keyname, &dnskey,
8616                                                   mctx, &tag));
8617                                 dns_zone_log(zone, ISC_LOG_WARNING,
8618                                              "Initializing automatic trust "
8619                                              "anchor management for zone '%s'; "
8620                                              "DNSKEY ID %d is now trusted, "
8621                                              "waiving the normal 30-day "
8622                                              "waiting period.",
8623                                              namebuf, tag);
8624                                 trustkey = ISC_TRUE;
8625                         }
8626                 } else {
8627                         /*
8628                          * No previously known key, and the key is not
8629                          * secure, so skip it.
8630                          */
8631                         continue;
8632                 }
8633
8634                 /* Delete old version */
8635                 if (deletekey || !newkey)
8636                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8637                                             DNS_DIFFOP_DEL, keyname, 0,
8638                                             &keydatarr));
8639
8640                 if (updatekey) {
8641                         /* Set refresh timer */
8642                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8643                         dns_rdata_reset(&keydatarr);
8644                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8645                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8646                                              dns_rdatatype_keydata,
8647                                              &keydata, &keyb);
8648
8649                         /* Insert updated version */
8650                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8651                                             DNS_DIFFOP_ADD, keyname, 0,
8652                                             &keydatarr));
8653                 } else if (newkey) {
8654                         /* Convert DNSKEY to KEYDATA */
8655                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8656                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8657                         dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
8658                                                NULL);
8659                         keydata.addhd = initializing
8660                                          ? now : now + dns_zone_mkey_month;
8661                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
8662                         dns_rdata_reset(&keydatarr);
8663                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8664                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8665                                              dns_rdatatype_keydata,
8666                                              &keydata, &keyb);
8667
8668                         /* Insert into key zone */
8669                         CHECK(update_one_rr(kfetch->db, ver, &diff,
8670                                             DNS_DIFFOP_ADD, keyname, 0,
8671                                             &keydatarr));
8672                 }
8673
8674                 if (trustkey) {
8675                         /* Trust this key. */
8676                         result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8677                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8678                         trust_key(zone, keyname, &dnskey, mctx);
8679                 }
8680
8681                 if (secure && !deletekey) {
8682                         INSIST(newkey || updatekey);
8683                         set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
8684                 }
8685         }
8686
8687         /*
8688          * RFC5011 says, "A trust point that has all of its trust anchors
8689          * revoked is considered deleted and is treated as if the trust
8690          * point was never configured."  But if someone revoked their
8691          * active key before the standby was trusted, that would mean the
8692          * zone would suddenly be nonsecured.  We avoid this by checking to
8693          * see if there's pending keydata.  If so, we put a null key in
8694          * the security roots; then all queries to the zone will fail.
8695          */
8696         if (pending != 0)
8697                 fail_secure(zone, keyname);
8698
8699  done:
8700
8701         if (!ISC_LIST_EMPTY(diff.tuples)) {
8702                 /* Write changes to journal file. */
8703                 CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
8704                                         zone->updatemethod));
8705                 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
8706                 commit = ISC_TRUE;
8707
8708                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8709                 zone_needdump(zone, 30);
8710         }
8711
8712  failure:
8713
8714         dns_diff_clear(&diff);
8715         if (ver != NULL)
8716                 dns_db_closeversion(kfetch->db, &ver, commit);
8717
8718  cleanup:
8719         dns_db_detach(&kfetch->db);
8720
8721         INSIST(zone->irefs > 0);
8722         zone->irefs--;
8723         kfetch->zone = NULL;
8724
8725         if (dns_rdataset_isassociated(&kfetch->keydataset))
8726                 dns_rdataset_disassociate(&kfetch->keydataset);
8727         if (dns_rdataset_isassociated(&kfetch->dnskeyset))
8728                 dns_rdataset_disassociate(&kfetch->dnskeyset);
8729         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8730                 dns_rdataset_disassociate(&kfetch->dnskeysigset);
8731
8732         dns_name_free(keyname, mctx);
8733         isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
8734         isc_mem_detach(&mctx);
8735
8736         if (secroots != NULL)
8737                 dns_keytable_detach(&secroots);
8738
8739         free_needed = exit_check(zone);
8740         UNLOCK_ZONE(zone);
8741         if (free_needed)
8742                 zone_free(zone);
8743
8744         INSIST(ver == NULL);
8745 }
8746
8747 /*
8748  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
8749  * records from the zone apex.
8750  */
8751 static void
8752 zone_refreshkeys(dns_zone_t *zone) {
8753         const char me[] = "zone_refreshkeys";
8754         isc_result_t result;
8755         dns_rriterator_t rrit;
8756         dns_db_t *db = NULL;
8757         dns_dbversion_t *ver = NULL;
8758         dns_diff_t diff;
8759         dns_rdata_t rdata = DNS_RDATA_INIT;
8760         dns_rdata_keydata_t kd;
8761         isc_stdtime_t now;
8762         isc_boolean_t commit = ISC_FALSE;
8763         isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
8764
8765         ENTER;
8766         REQUIRE(zone->db != NULL);
8767
8768         isc_stdtime_get(&now);
8769
8770         LOCK_ZONE(zone);
8771         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
8772                 isc_time_settoepoch(&zone->refreshkeytime);
8773                 UNLOCK_ZONE(zone);
8774                 return;
8775         }
8776
8777         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8778         dns_db_attach(zone->db, &db);
8779         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8780
8781         dns_diff_init(zone->mctx, &diff);
8782
8783         CHECK(dns_db_newversion(db, &ver));
8784
8785         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
8786
8787         dns_rriterator_init(&rrit, db, ver, 0);
8788         for (result = dns_rriterator_first(&rrit);
8789              result == ISC_R_SUCCESS;
8790              result = dns_rriterator_nextrrset(&rrit)) {
8791                 isc_stdtime_t timer = 0xffffffff;
8792                 dns_name_t *name = NULL, *kname = NULL;
8793                 dns_rdataset_t *kdset = NULL;
8794                 dns_keyfetch_t *kfetch;
8795                 isc_uint32_t ttl;
8796
8797                 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
8798                 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
8799                     !dns_rdataset_isassociated(kdset))
8800                         continue;
8801
8802                 /*
8803                  * Scan the stored keys looking for ones that need
8804                  * removal or refreshing
8805                  */
8806                 for (result = dns_rdataset_first(kdset);
8807                      result == ISC_R_SUCCESS;
8808                      result = dns_rdataset_next(kdset)) {
8809                         dns_rdata_reset(&rdata);
8810                         dns_rdataset_current(kdset, &rdata);
8811                         result = dns_rdata_tostruct(&rdata, &kd, NULL);
8812                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8813
8814                         /* Removal timer expired? */
8815                         if (kd.removehd != 0 && kd.removehd < now) {
8816                                 CHECK(update_one_rr(db, ver, &diff,
8817                                                     DNS_DIFFOP_DEL, name, ttl,
8818                                                     &rdata));
8819                                 continue;
8820                         }
8821
8822                         /* Acceptance timer expired? */
8823                         if (kd.addhd != 0 && kd.addhd < now)
8824                                 timer = kd.addhd;
8825
8826                         /* Or do we just need to refresh the keyset? */
8827                         if (timer > kd.refresh)
8828                                 timer = kd.refresh;
8829                 }
8830
8831                 if (timer > now)
8832                         continue;
8833
8834                 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
8835                 if (kfetch == NULL) {
8836                         fetch_err = ISC_TRUE;
8837                         goto failure;
8838                 }
8839
8840                 zone->refreshkeycount++;
8841                 kfetch->zone = zone;
8842                 zone->irefs++;
8843                 INSIST(zone->irefs != 0);
8844                 dns_fixedname_init(&kfetch->name);
8845                 kname = dns_fixedname_name(&kfetch->name);
8846                 dns_name_dup(name, zone->mctx, kname);
8847                 dns_rdataset_init(&kfetch->dnskeyset);
8848                 dns_rdataset_init(&kfetch->dnskeysigset);
8849                 dns_rdataset_init(&kfetch->keydataset);
8850                 dns_rdataset_clone(kdset, &kfetch->keydataset);
8851                 kfetch->db = NULL;
8852                 dns_db_attach(db, &kfetch->db);
8853                 kfetch->fetch = NULL;
8854
8855                 result = dns_resolver_createfetch(zone->view->resolver,
8856                                                   kname, dns_rdatatype_dnskey,
8857                                                   NULL, NULL, NULL,
8858                                                   DNS_FETCHOPT_NOVALIDATE,
8859                                                   zone->task,
8860                                                   keyfetch_done, kfetch,
8861                                                   &kfetch->dnskeyset,
8862                                                   &kfetch->dnskeysigset,
8863                                                   &kfetch->fetch);
8864                 if (result == ISC_R_SUCCESS)
8865                         fetching = ISC_TRUE;
8866                 else {
8867                         zone->refreshkeycount--;
8868                         zone->irefs--;
8869                         dns_db_detach(&kfetch->db);
8870                         dns_rdataset_disassociate(&kfetch->keydataset);
8871                         dns_name_free(kname, zone->mctx);
8872                         isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
8873                         dns_zone_log(zone, ISC_LOG_WARNING,
8874                                      "Failed to create fetch for "
8875                                      "DNSKEY update");
8876                         fetch_err = ISC_TRUE;
8877                 }
8878         }
8879         if (!ISC_LIST_EMPTY(diff.tuples)) {
8880                 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
8881                                         zone->updatemethod));
8882                 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
8883                 commit = ISC_TRUE;
8884                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
8885                 zone_needdump(zone, 30);
8886         }
8887
8888   failure:
8889         if (fetch_err) {
8890                 /*
8891                  * Error during a key fetch; retry in an hour.
8892                  */
8893                 isc_time_t timenow, timethen;
8894                 char timebuf[80];
8895
8896                 TIME_NOW(&timenow);
8897                 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
8898                 zone->refreshkeytime = timethen;
8899                 zone_settimer(zone, &timenow);
8900
8901                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
8902                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
8903                              timebuf);
8904
8905                 if (!fetching)
8906                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8907         }
8908
8909         UNLOCK_ZONE(zone);
8910
8911         dns_diff_clear(&diff);
8912         if (ver != NULL) {
8913                 dns_rriterator_destroy(&rrit);
8914                 dns_db_closeversion(db, &ver, commit);
8915         }
8916         dns_db_detach(&db);
8917
8918         INSIST(ver == NULL);
8919 }
8920
8921 static void
8922 zone_maintenance(dns_zone_t *zone) {
8923         const char me[] = "zone_maintenance";
8924         isc_time_t now;
8925         isc_result_t result;
8926         isc_boolean_t dumping;
8927
8928         REQUIRE(DNS_ZONE_VALID(zone));
8929         ENTER;
8930
8931         /*
8932          * Are we pending load/reload?
8933          */
8934         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
8935                 return;
8936
8937         /*
8938          * Configuring the view of this zone may have
8939          * failed, for example because the config file
8940          * had a syntax error.  In that case, the view
8941          * adb or resolver will be NULL, and we had better not try
8942          * to do further maintenance on it.
8943          */
8944         if (zone->view == NULL || zone->view->adb == NULL)
8945                 return;
8946
8947         TIME_NOW(&now);
8948
8949         /*
8950          * Expire check.
8951          */
8952         switch (zone->type) {
8953         case dns_zone_redirect:
8954                 if (zone->masters == NULL)
8955                         break;
8956         case dns_zone_slave:
8957         case dns_zone_stub:
8958                 LOCK_ZONE(zone);
8959                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
8960                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8961                         zone_expire(zone);
8962                         zone->refreshtime = now;
8963                 }
8964                 UNLOCK_ZONE(zone);
8965                 break;
8966         default:
8967                 break;
8968         }
8969
8970         /*
8971          * Up to date check.
8972          */
8973         switch (zone->type) {
8974         case dns_zone_redirect:
8975                 if (zone->masters == NULL)
8976                         break;
8977         case dns_zone_slave:
8978         case dns_zone_stub:
8979                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
8980                     isc_time_compare(&now, &zone->refreshtime) >= 0)
8981                         dns_zone_refresh(zone);
8982                 break;
8983         default:
8984                 break;
8985         }
8986
8987         /*
8988          * Slaves send notifies before backing up to disk, masters after.
8989          */
8990         if (zone->type == dns_zone_slave &&
8991             (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
8992              DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
8993             isc_time_compare(&now, &zone->notifytime) >= 0)
8994                 zone_notify(zone, &now);
8995
8996         /*
8997          * Do we need to consolidate the backing store?
8998          */
8999         switch (zone->type) {
9000         case dns_zone_master:
9001         case dns_zone_slave:
9002         case dns_zone_key:
9003         case dns_zone_redirect:
9004         case dns_zone_stub:
9005                 LOCK_ZONE(zone);
9006                 if (zone->masterfile != NULL &&
9007                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
9008                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
9009                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
9010                         dumping = was_dumping(zone);
9011                 } else
9012                         dumping = ISC_TRUE;
9013                 UNLOCK_ZONE(zone);
9014                 if (!dumping) {
9015                         result = zone_dump(zone, ISC_TRUE); /* task locked */
9016                         if (result != ISC_R_SUCCESS)
9017                                 dns_zone_log(zone, ISC_LOG_WARNING,
9018                                              "dump failed: %s",
9019                                              dns_result_totext(result));
9020                 }
9021                 break;
9022         default:
9023                 break;
9024         }
9025
9026         /*
9027          * Master/redirect zones send notifies now, if needed
9028          */
9029         switch (zone->type) {
9030         case dns_zone_master:
9031         case dns_zone_redirect:
9032                 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
9033                      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&&
9034                     isc_time_compare(&now, &zone->notifytime) >= 0)
9035                         zone_notify(zone, &now);
9036         default:
9037                 break;
9038         }
9039
9040         /*
9041          * Do we need to refresh keys?
9042          */
9043         switch (zone->type) {
9044         case dns_zone_key:
9045                 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
9046                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
9047                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
9048                                 zone_refreshkeys(zone);
9049                         }
9050                 }
9051                 break;
9052         case dns_zone_master:
9053                 if (!isc_time_isepoch(&zone->refreshkeytime) &&
9054                     isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
9055                     zone->rss_event == NULL)
9056                         zone_rekey(zone);
9057         default:
9058                 break;
9059         }
9060
9061         switch (zone->type) {
9062         case dns_zone_master:
9063         case dns_zone_redirect:
9064         case dns_zone_slave:
9065                 /*
9066                  * Do we need to sign/resign some RRsets?
9067                  */
9068                 if (zone->rss_event != NULL)
9069                         break;
9070                 if (!isc_time_isepoch(&zone->signingtime) &&
9071                     isc_time_compare(&now, &zone->signingtime) >= 0)
9072                         zone_sign(zone);
9073                 else if (!isc_time_isepoch(&zone->resigntime) &&
9074                     isc_time_compare(&now, &zone->resigntime) >= 0)
9075                         zone_resigninc(zone);
9076                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
9077                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
9078                         zone_nsec3chain(zone);
9079                 /*
9080                  * Do we need to issue a key expiry warning?
9081                  */
9082                 if (!isc_time_isepoch(&zone->keywarntime) &&
9083                     isc_time_compare(&now, &zone->keywarntime) >= 0)
9084                         set_key_expiry_warning(zone, zone->key_expiry,
9085                                                isc_time_seconds(&now));
9086                 break;
9087
9088         default:
9089                 break;
9090         }
9091         zone_settimer(zone, &now);
9092 }
9093
9094 void
9095 dns_zone_markdirty(dns_zone_t *zone) {
9096         isc_uint32_t serial;
9097         isc_result_t result = ISC_R_SUCCESS;
9098         dns_zone_t *secure = NULL;
9099
9100         /*
9101          * Obtaining a lock on the zone->secure (see zone_send_secureserial)
9102          * could result in a deadlock due to a LOR so we will spin if we
9103          * can't obtain the both locks.
9104          */
9105  again:
9106         LOCK_ZONE(zone);
9107         if (zone->type == dns_zone_master) {
9108                 if (inline_raw(zone)) {
9109                         unsigned int soacount;
9110                         secure = zone->secure;
9111                         INSIST(secure != zone);
9112                         TRYLOCK_ZONE(result, secure);
9113                         if (result != ISC_R_SUCCESS) {
9114                                 UNLOCK_ZONE(zone);
9115                                 secure = NULL;
9116 #ifdef ISC_PLATFORM_USETHREADS
9117                                 isc_thread_yield();
9118 #endif
9119                                 goto again;
9120                         }
9121
9122                         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9123                         if (zone->db != NULL) {
9124                                 result = zone_get_from_db(zone, zone->db, NULL,
9125                                                           &soacount, &serial,
9126                                                           NULL, NULL, NULL,
9127                                                           NULL, NULL);
9128                         } else
9129                                 result = DNS_R_NOTLOADED;
9130                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9131                         if (result == ISC_R_SUCCESS && soacount > 0U)
9132                                 zone_send_secureserial(zone, serial);
9133                 }
9134
9135                 /* XXXMPA make separate call back */
9136                 if (result == ISC_R_SUCCESS)
9137                         set_resigntime(zone);
9138         }
9139         if (secure != NULL)
9140                 UNLOCK_ZONE(secure);
9141         zone_needdump(zone, DNS_DUMP_DELAY);
9142         UNLOCK_ZONE(zone);
9143 }
9144
9145 void
9146 dns_zone_expire(dns_zone_t *zone) {
9147         REQUIRE(DNS_ZONE_VALID(zone));
9148
9149         LOCK_ZONE(zone);
9150         zone_expire(zone);
9151         UNLOCK_ZONE(zone);
9152 }
9153
9154 static void
9155 zone_expire(dns_zone_t *zone) {
9156         /*
9157          * 'zone' locked by caller.
9158          */
9159
9160         REQUIRE(LOCKED_ZONE(zone));
9161
9162         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
9163
9164         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
9165         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
9166         zone->retry = DNS_ZONE_DEFAULTRETRY;
9167         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9168         zone_unload(zone);
9169 }
9170
9171 void
9172 dns_zone_refresh(dns_zone_t *zone) {
9173         isc_interval_t i;
9174         isc_uint32_t oldflags;
9175         unsigned int j;
9176         isc_result_t result;
9177
9178         REQUIRE(DNS_ZONE_VALID(zone));
9179
9180         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
9181                 return;
9182
9183         /*
9184          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
9185          * in progress at a time.
9186          */
9187
9188         LOCK_ZONE(zone);
9189         oldflags = zone->flags;
9190         if (zone->masterscnt == 0) {
9191                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
9192                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
9193                         dns_zone_log(zone, ISC_LOG_ERROR,
9194                                      "cannot refresh: no masters");
9195                 goto unlock;
9196         }
9197         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
9198         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9199         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9200         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
9201                 goto unlock;
9202
9203         /*
9204          * Set the next refresh time as if refresh check has failed.
9205          * Setting this to the retry time will do that.  XXXMLG
9206          * If we are successful it will be reset using zone->refresh.
9207          */
9208         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
9209                          0);
9210         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
9211         if (result != ISC_R_SUCCESS)
9212                 dns_zone_log(zone, ISC_LOG_WARNING,
9213                              "isc_time_nowplusinterval() failed: %s",
9214                              dns_result_totext(result));
9215
9216         /*
9217          * When lacking user-specified timer values from the SOA,
9218          * do exponential backoff of the retry time up to a
9219          * maximum of six hours.
9220          */
9221         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
9222                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
9223
9224         zone->curmaster = 0;
9225         for (j = 0; j < zone->masterscnt; j++)
9226                 zone->mastersok[j] = ISC_FALSE;
9227         /* initiate soa query */
9228         queue_soa_query(zone);
9229  unlock:
9230         UNLOCK_ZONE(zone);
9231 }
9232
9233 isc_result_t
9234 dns_zone_flush(dns_zone_t *zone) {
9235         isc_result_t result = ISC_R_SUCCESS;
9236         isc_boolean_t dumping;
9237
9238         REQUIRE(DNS_ZONE_VALID(zone));
9239
9240         LOCK_ZONE(zone);
9241         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
9242         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9243             zone->masterfile != NULL) {
9244                 result = ISC_R_ALREADYRUNNING;
9245                 dumping = was_dumping(zone);
9246         } else
9247                 dumping = ISC_TRUE;
9248         UNLOCK_ZONE(zone);
9249         if (!dumping)
9250                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
9251         return (result);
9252 }
9253
9254 isc_result_t
9255 dns_zone_dump(dns_zone_t *zone) {
9256         isc_result_t result = ISC_R_ALREADYRUNNING;
9257         isc_boolean_t dumping;
9258
9259         REQUIRE(DNS_ZONE_VALID(zone));
9260
9261         LOCK_ZONE(zone);
9262         dumping = was_dumping(zone);
9263         UNLOCK_ZONE(zone);
9264         if (!dumping)
9265                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
9266         return (result);
9267 }
9268
9269 static void
9270 zone_needdump(dns_zone_t *zone, unsigned int delay) {
9271         const char me[] = "zone_needdump";
9272         isc_time_t dumptime;
9273         isc_time_t now;
9274
9275         /*
9276          * 'zone' locked by caller
9277          */
9278
9279         REQUIRE(DNS_ZONE_VALID(zone));
9280         REQUIRE(LOCKED_ZONE(zone));
9281         ENTER;
9282
9283         /*
9284          * Do we have a place to dump to and are we loaded?
9285          */
9286         if (zone->masterfile == NULL ||
9287             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
9288                 return;
9289
9290         TIME_NOW(&now);
9291         /* add some noise */
9292         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
9293
9294         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9295         if (isc_time_isepoch(&zone->dumptime) ||
9296             isc_time_compare(&zone->dumptime, &dumptime) > 0)
9297                 zone->dumptime = dumptime;
9298         if (zone->task != NULL)
9299                 zone_settimer(zone, &now);
9300 }
9301
9302 static void
9303 dump_done(void *arg, isc_result_t result) {
9304         const char me[] = "dump_done";
9305         dns_zone_t *zone = arg;
9306         dns_db_t *db;
9307         dns_dbversion_t *version;
9308         isc_boolean_t again = ISC_FALSE;
9309         isc_boolean_t compact = ISC_FALSE;
9310         isc_uint32_t serial;
9311         isc_result_t tresult;
9312
9313         REQUIRE(DNS_ZONE_VALID(zone));
9314
9315         ENTER;
9316
9317         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
9318             zone->journalsize != -1) {
9319
9320                 /*
9321                  * We don't own these, zone->dctx must stay valid.
9322                  */
9323                 db = dns_dumpctx_db(zone->dctx);
9324                 version = dns_dumpctx_version(zone->dctx);
9325
9326                 tresult = dns_db_getsoaserial(db, version, &serial);
9327                 /*
9328                  * If there is a secure version of this zone
9329                  * use its serial if it is less than ours.
9330                  */
9331                 if (tresult == ISC_R_SUCCESS && inline_raw(zone) &&
9332                     zone->secure->db != NULL)
9333                 {
9334                         isc_uint32_t sserial;
9335                         isc_result_t mresult;
9336
9337                         mresult = dns_db_getsoaserial(zone->secure->db,
9338                                                       NULL, &sserial);
9339                         if (mresult == ISC_R_SUCCESS &&
9340                             isc_serial_lt(sserial, serial))
9341                                 serial = sserial;
9342                 }
9343                 /*
9344                  * Note: we are task locked here so we can test
9345                  * zone->xfr safely.
9346                  */
9347                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
9348                         tresult = dns_journal_compact(zone->mctx,
9349                                                       zone->journal,
9350                                                       serial,
9351                                                       zone->journalsize);
9352                         switch (tresult) {
9353                         case ISC_R_SUCCESS:
9354                         case ISC_R_NOSPACE:
9355                         case ISC_R_NOTFOUND:
9356                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9357                                              "dns_journal_compact: %s",
9358                                              dns_result_totext(tresult));
9359                                 break;
9360                         default:
9361                                 dns_zone_log(zone, ISC_LOG_ERROR,
9362                                              "dns_journal_compact failed: %s",
9363                                              dns_result_totext(tresult));
9364                                 break;
9365                         }
9366                 } else if (tresult == ISC_R_SUCCESS) {
9367                         compact = ISC_TRUE;
9368                         zone->compact_serial = serial;
9369                 }
9370         }
9371
9372         LOCK_ZONE(zone);
9373         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9374         if (compact)
9375                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
9376         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
9377                 /*
9378                  * Try again in a short while.
9379                  */
9380                 zone_needdump(zone, DNS_DUMP_DELAY);
9381         } else if (result == ISC_R_SUCCESS &&
9382                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9383                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9384                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9385                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9386                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9387                 isc_time_settoepoch(&zone->dumptime);
9388                 again = ISC_TRUE;
9389         } else if (result == ISC_R_SUCCESS)
9390                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9391
9392         if (zone->dctx != NULL)
9393                 dns_dumpctx_detach(&zone->dctx);
9394         zonemgr_putio(&zone->writeio);
9395         UNLOCK_ZONE(zone);
9396         if (again)
9397                 (void)zone_dump(zone, ISC_FALSE);
9398         dns_zone_idetach(&zone);
9399 }
9400
9401 static isc_result_t
9402 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
9403         const char me[] = "zone_dump";
9404         isc_result_t result;
9405         dns_dbversion_t *version = NULL;
9406         isc_boolean_t again;
9407         dns_db_t *db = NULL;
9408         char *masterfile = NULL;
9409         dns_masterformat_t masterformat = dns_masterformat_none;
9410
9411 /*
9412  * 'compact' MUST only be set if we are task locked.
9413  */
9414
9415         REQUIRE(DNS_ZONE_VALID(zone));
9416         ENTER;
9417
9418  redo:
9419         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9420         if (zone->db != NULL)
9421                 dns_db_attach(zone->db, &db);
9422         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9423         LOCK_ZONE(zone);
9424         if (zone->masterfile != NULL) {
9425                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
9426                 masterformat = zone->masterformat;
9427         }
9428         UNLOCK_ZONE(zone);
9429         if (db == NULL) {
9430                 result = DNS_R_NOTLOADED;
9431                 goto fail;
9432         }
9433         if (masterfile == NULL) {
9434                 result = DNS_R_NOMASTERFILE;
9435                 goto fail;
9436         }
9437
9438         if (compact && zone->type != dns_zone_stub) {
9439                 dns_zone_t *dummy = NULL;
9440                 LOCK_ZONE(zone);
9441                 zone_iattach(zone, &dummy);
9442                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
9443                                        zone_gotwritehandle, zone,
9444                                        &zone->writeio);
9445                 if (result != ISC_R_SUCCESS)
9446                         zone_idetach(&dummy);
9447                 else
9448                         result = DNS_R_CONTINUE;
9449                 UNLOCK_ZONE(zone);
9450         } else {
9451                 const dns_master_style_t *output_style;
9452
9453                 dns_masterrawheader_t rawdata;
9454                 dns_db_currentversion(db, &version);
9455                 dns_master_initrawheader(&rawdata);
9456                 if (inline_secure(zone))
9457                         get_raw_serial(zone->raw, &rawdata);
9458                 if (zone->type == dns_zone_key)
9459                         output_style = &dns_master_style_keyzone;
9460                 else
9461                         output_style = &dns_master_style_default;
9462                 result = dns_master_dump3(zone->mctx, db, version,
9463                                           output_style, masterfile,
9464                                           masterformat, &rawdata);
9465                 dns_db_closeversion(db, &version, ISC_FALSE);
9466         }
9467  fail:
9468         if (db != NULL)
9469                 dns_db_detach(&db);
9470         if (masterfile != NULL)
9471                 isc_mem_free(zone->mctx, masterfile);
9472         masterfile = NULL;
9473
9474         if (result == DNS_R_CONTINUE)
9475                 return (ISC_R_SUCCESS); /* XXXMPA */
9476
9477         again = ISC_FALSE;
9478         LOCK_ZONE(zone);
9479         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9480         if (result != ISC_R_SUCCESS) {
9481                 /*
9482                  * Try again in a short while.
9483                  */
9484                 zone_needdump(zone, DNS_DUMP_DELAY);
9485         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9486                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9487                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9488                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9489                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9490                 isc_time_settoepoch(&zone->dumptime);
9491                 again = ISC_TRUE;
9492         } else
9493                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9494         UNLOCK_ZONE(zone);
9495         if (again)
9496                 goto redo;
9497
9498         return (result);
9499 }
9500
9501 static isc_result_t
9502 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
9503              dns_masterformat_t format, const isc_uint32_t rawversion)
9504 {
9505         isc_result_t result;
9506         dns_dbversion_t *version = NULL;
9507         dns_db_t *db = NULL;
9508         dns_masterrawheader_t rawdata;
9509
9510         REQUIRE(DNS_ZONE_VALID(zone));
9511
9512         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9513         if (zone->db != NULL)
9514                 dns_db_attach(zone->db, &db);
9515         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9516         if (db == NULL)
9517                 return (DNS_R_NOTLOADED);
9518
9519         dns_db_currentversion(db, &version);
9520         dns_master_initrawheader(&rawdata);
9521         if (rawversion == 0)
9522                 rawdata.flags |= DNS_MASTERRAW_COMPAT;
9523         else if (inline_secure(zone))
9524                 get_raw_serial(zone->raw, &rawdata);
9525         else if (zone->sourceserialset) {
9526                 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
9527                 rawdata.sourceserial = zone->sourceserial;
9528         }
9529         result = dns_master_dumptostream3(zone->mctx, db, version, style,
9530                                           format, &rawdata, fd);
9531         dns_db_closeversion(db, &version, ISC_FALSE);
9532         dns_db_detach(&db);
9533         return (result);
9534 }
9535
9536 isc_result_t
9537 dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9538                        const dns_master_style_t *style,
9539                        const isc_uint32_t rawversion)
9540 {
9541         return (dumptostream(zone, fd, style, format, rawversion));
9542 }
9543
9544 isc_result_t
9545 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9546                        const dns_master_style_t *style) {
9547         return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
9548 }
9549
9550 isc_result_t
9551 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
9552         return (dumptostream(zone, fd, &dns_master_style_default,
9553                              dns_masterformat_text, 0));
9554 }
9555
9556 isc_result_t
9557 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
9558         return (dumptostream(zone, fd, &dns_master_style_full,
9559                              dns_masterformat_text, 0));
9560 }
9561
9562 void
9563 dns_zone_unload(dns_zone_t *zone) {
9564         REQUIRE(DNS_ZONE_VALID(zone));
9565
9566         LOCK_ZONE(zone);
9567         zone_unload(zone);
9568         UNLOCK_ZONE(zone);
9569 }
9570
9571 static void
9572 notify_cancel(dns_zone_t *zone) {
9573         dns_notify_t *notify;
9574
9575         /*
9576          * 'zone' locked by caller.
9577          */
9578
9579         REQUIRE(LOCKED_ZONE(zone));
9580
9581         for (notify = ISC_LIST_HEAD(zone->notifies);
9582              notify != NULL;
9583              notify = ISC_LIST_NEXT(notify, link)) {
9584                 if (notify->find != NULL)
9585                         dns_adb_cancelfind(notify->find);
9586                 if (notify->request != NULL)
9587                         dns_request_cancel(notify->request);
9588         }
9589 }
9590
9591 static void
9592 forward_cancel(dns_zone_t *zone) {
9593         dns_forward_t *forward;
9594
9595         /*
9596          * 'zone' locked by caller.
9597          */
9598
9599         REQUIRE(LOCKED_ZONE(zone));
9600
9601         for (forward = ISC_LIST_HEAD(zone->forwards);
9602              forward != NULL;
9603              forward = ISC_LIST_NEXT(forward, link)) {
9604                 if (forward->request != NULL)
9605                         dns_request_cancel(forward->request);
9606         }
9607 }
9608
9609 static void
9610 zone_unload(dns_zone_t *zone) {
9611         /*
9612          * 'zone' locked by caller.
9613          */
9614
9615         REQUIRE(LOCKED_ZONE(zone));
9616
9617         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
9618             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9619                 if (zone->writeio != NULL)
9620                         zonemgr_cancelio(zone->writeio);
9621
9622                 if (zone->dctx != NULL)
9623                         dns_dumpctx_cancel(zone->dctx);
9624         }
9625         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9626         zone_detachdb(zone);
9627         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9628         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
9629         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9630 }
9631
9632 void
9633 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9634         REQUIRE(DNS_ZONE_VALID(zone));
9635         REQUIRE(val > 0);
9636
9637         zone->minrefresh = val;
9638 }
9639
9640 void
9641 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
9642         REQUIRE(DNS_ZONE_VALID(zone));
9643         REQUIRE(val > 0);
9644
9645         zone->maxrefresh = val;
9646 }
9647
9648 void
9649 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
9650         REQUIRE(DNS_ZONE_VALID(zone));
9651         REQUIRE(val > 0);
9652
9653         zone->minretry = val;
9654 }
9655
9656 void
9657 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
9658         REQUIRE(DNS_ZONE_VALID(zone));
9659         REQUIRE(val > 0);
9660
9661         zone->maxretry = val;
9662 }
9663
9664 static isc_boolean_t
9665 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
9666                 isc_sockaddr_t *addr, dns_tsigkey_t *key)
9667 {
9668         dns_notify_t *notify;
9669         dns_zonemgr_t *zmgr;
9670         isc_result_t result;
9671
9672         for (notify = ISC_LIST_HEAD(zone->notifies);
9673              notify != NULL;
9674              notify = ISC_LIST_NEXT(notify, link)) {
9675                 if (notify->request != NULL)
9676                         continue;
9677                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
9678                     dns_name_equal(name, &notify->ns))
9679                         goto requeue;
9680                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
9681                     notify->key == key)
9682                         goto requeue;
9683         }
9684         return (ISC_FALSE);
9685
9686 requeue:
9687         /*
9688          * If we are enqueued on the startup ratelimiter and this is
9689          * not a startup notify, re-enqueue on the normal notify
9690          * ratelimiter.
9691          */
9692         if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
9693             (notify->flags & DNS_NOTIFY_STARTUP) != 0) {
9694                 zmgr = notify->zone->zmgr;
9695                 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
9696                                                  notify->event);
9697                 if (result != ISC_R_SUCCESS)
9698                         return (ISC_TRUE);
9699
9700                 notify->flags &= ~DNS_NOTIFY_STARTUP;
9701                 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
9702                                                  notify->zone->task,
9703                                                  &notify->event);
9704                 if (result != ISC_R_SUCCESS) {
9705                         isc_event_free(&notify->event);
9706                         return (ISC_FALSE);
9707                 }
9708         }
9709
9710         return (ISC_TRUE);
9711 }
9712
9713 static isc_boolean_t
9714 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
9715         dns_tsigkey_t *key = NULL;
9716         isc_sockaddr_t src;
9717         isc_sockaddr_t any;
9718         isc_boolean_t isself;
9719         isc_netaddr_t dstaddr;
9720         isc_result_t result;
9721
9722         if (zone->view == NULL || zone->isself == NULL)
9723                 return (ISC_FALSE);
9724
9725         switch (isc_sockaddr_pf(dst)) {
9726         case PF_INET:
9727                 src = zone->notifysrc4;
9728                 isc_sockaddr_any(&any);
9729                 break;
9730         case PF_INET6:
9731                 src = zone->notifysrc6;
9732                 isc_sockaddr_any6(&any);
9733                 break;
9734         default:
9735                 return (ISC_FALSE);
9736         }
9737
9738         /*
9739          * When sending from any the kernel will assign a source address
9740          * that matches the destination address.
9741          */
9742         if (isc_sockaddr_eqaddr(&any, &src))
9743                 src = *dst;
9744
9745         isc_netaddr_fromsockaddr(&dstaddr, dst);
9746         result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
9747         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
9748                 return (ISC_FALSE);
9749         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
9750                                 zone->isselfarg);
9751         if (key != NULL)
9752                 dns_tsigkey_detach(&key);
9753         return (isself);
9754 }
9755
9756 static void
9757 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
9758         isc_mem_t *mctx;
9759
9760         REQUIRE(DNS_NOTIFY_VALID(notify));
9761
9762         if (notify->zone != NULL) {
9763                 if (!locked)
9764                         LOCK_ZONE(notify->zone);
9765                 REQUIRE(LOCKED_ZONE(notify->zone));
9766                 if (ISC_LINK_LINKED(notify, link))
9767                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
9768                 if (!locked)
9769                         UNLOCK_ZONE(notify->zone);
9770                 if (locked)
9771                         zone_idetach(&notify->zone);
9772                 else
9773                         dns_zone_idetach(&notify->zone);
9774         }
9775         if (notify->find != NULL)
9776                 dns_adb_destroyfind(&notify->find);
9777         if (notify->request != NULL)
9778                 dns_request_destroy(&notify->request);
9779         if (dns_name_dynamic(&notify->ns))
9780                 dns_name_free(&notify->ns, notify->mctx);
9781         if (notify->key != NULL)
9782                 dns_tsigkey_detach(&notify->key);
9783         mctx = notify->mctx;
9784         isc_mem_put(notify->mctx, notify, sizeof(*notify));
9785         isc_mem_detach(&mctx);
9786 }
9787
9788 static isc_result_t
9789 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
9790         dns_notify_t *notify;
9791
9792         REQUIRE(notifyp != NULL && *notifyp == NULL);
9793
9794         notify = isc_mem_get(mctx, sizeof(*notify));
9795         if (notify == NULL)
9796                 return (ISC_R_NOMEMORY);
9797
9798         notify->mctx = NULL;
9799         isc_mem_attach(mctx, &notify->mctx);
9800         notify->flags = flags;
9801         notify->zone = NULL;
9802         notify->find = NULL;
9803         notify->request = NULL;
9804         notify->key = NULL;
9805         notify->event = NULL;
9806         isc_sockaddr_any(&notify->dst);
9807         dns_name_init(&notify->ns, NULL);
9808         ISC_LINK_INIT(notify, link);
9809         notify->magic = NOTIFY_MAGIC;
9810         *notifyp = notify;
9811         return (ISC_R_SUCCESS);
9812 }
9813
9814 /*
9815  * XXXAG should check for DNS_ZONEFLG_EXITING
9816  */
9817 static void
9818 process_adb_event(isc_task_t *task, isc_event_t *ev) {
9819         dns_notify_t *notify;
9820         isc_eventtype_t result;
9821
9822         UNUSED(task);
9823
9824         notify = ev->ev_arg;
9825         REQUIRE(DNS_NOTIFY_VALID(notify));
9826         INSIST(task == notify->zone->task);
9827         result = ev->ev_type;
9828         isc_event_free(&ev);
9829         if (result == DNS_EVENT_ADBMOREADDRESSES) {
9830                 dns_adb_destroyfind(&notify->find);
9831                 notify_find_address(notify);
9832                 return;
9833         }
9834         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
9835                 LOCK_ZONE(notify->zone);
9836                 notify_send(notify);
9837                 UNLOCK_ZONE(notify->zone);
9838         }
9839         notify_destroy(notify, ISC_FALSE);
9840 }
9841
9842 static void
9843 notify_find_address(dns_notify_t *notify) {
9844         isc_result_t result;
9845         unsigned int options;
9846
9847         REQUIRE(DNS_NOTIFY_VALID(notify));
9848         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
9849                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
9850
9851         if (notify->zone->view->adb == NULL)
9852                 goto destroy;
9853
9854         result = dns_adb_createfind(notify->zone->view->adb,
9855                                     notify->zone->task,
9856                                     process_adb_event, notify,
9857                                     &notify->ns, dns_rootname, 0,
9858                                     options, 0, NULL,
9859                                     notify->zone->view->dstport,
9860                                     &notify->find);
9861
9862         /* Something failed? */
9863         if (result != ISC_R_SUCCESS)
9864                 goto destroy;
9865
9866         /* More addresses pending? */
9867         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
9868                 return;
9869
9870         /* We have as many addresses as we can get. */
9871         LOCK_ZONE(notify->zone);
9872         notify_send(notify);
9873         UNLOCK_ZONE(notify->zone);
9874
9875  destroy:
9876         notify_destroy(notify, ISC_FALSE);
9877 }
9878
9879
9880 static isc_result_t
9881 notify_send_queue(dns_notify_t *notify, isc_boolean_t startup) {
9882         isc_event_t *e;
9883         isc_result_t result;
9884
9885         INSIST(notify->event == NULL);
9886         e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
9887                                notify_send_toaddr, notify, sizeof(isc_event_t));
9888         if (e == NULL)
9889                 return (ISC_R_NOMEMORY);
9890         if (startup)
9891                 notify->event = e;
9892         e->ev_arg = notify;
9893         e->ev_sender = NULL;
9894         result = isc_ratelimiter_enqueue(startup
9895                                           ? notify->zone->zmgr->startupnotifyrl
9896                                           : notify->zone->zmgr->notifyrl,
9897                                          notify->zone->task, &e);
9898         if (result != ISC_R_SUCCESS) {
9899                 isc_event_free(&e);
9900                 notify->event = NULL;
9901         }
9902         return (result);
9903 }
9904
9905 static void
9906 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
9907         dns_notify_t *notify;
9908         isc_result_t result;
9909         dns_message_t *message = NULL;
9910         isc_netaddr_t dstip;
9911         dns_tsigkey_t *key = NULL;
9912         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9913         isc_sockaddr_t src;
9914         int timeout;
9915         isc_boolean_t have_notifysource = ISC_FALSE;
9916
9917         notify = event->ev_arg;
9918         REQUIRE(DNS_NOTIFY_VALID(notify));
9919
9920         UNUSED(task);
9921
9922         LOCK_ZONE(notify->zone);
9923
9924         notify->event = NULL;
9925
9926         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
9927                 result = ISC_R_CANCELED;
9928                 goto cleanup;
9929         }
9930
9931         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
9932             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
9933             notify->zone->view->requestmgr == NULL ||
9934             notify->zone->db == NULL) {
9935                 result = ISC_R_CANCELED;
9936                 goto cleanup;
9937         }
9938
9939         /*
9940          * The raw IPv4 address should also exist.  Don't send to the
9941          * mapped form.
9942          */
9943         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
9944             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
9945                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9946                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
9947                            "notify: ignoring IPv6 mapped IPV4 address: %s",
9948                            addrbuf);
9949                 result = ISC_R_CANCELED;
9950                 goto cleanup;
9951         }
9952
9953         result = notify_createmessage(notify->zone, notify->flags, &message);
9954         if (result != ISC_R_SUCCESS)
9955                 goto cleanup;
9956
9957         if (notify->key != NULL) {
9958                 /* Transfer ownership of key */
9959                 key = notify->key;
9960                 notify->key = NULL;
9961         } else {
9962                 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
9963                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9964                 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
9965                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9966                         notify_log(notify->zone, ISC_LOG_ERROR,
9967                                    "NOTIFY to %s not sent. "
9968                                    "Peer TSIG key lookup failure.", addrbuf);
9969                         goto cleanup_message;
9970                 }
9971         }
9972
9973         /* XXX: should we log the tsig key too? */
9974         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
9975                    addrbuf);
9976         if (notify->zone->view->peers != NULL) {
9977                 dns_peer_t *peer = NULL;
9978                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
9979                                                  &dstip, &peer);
9980                 if (result == ISC_R_SUCCESS) {
9981                         result = dns_peer_getnotifysource(peer, &src);
9982                         if (result == ISC_R_SUCCESS)
9983                                 have_notifysource = ISC_TRUE;
9984                 }
9985         }
9986         switch (isc_sockaddr_pf(&notify->dst)) {
9987         case PF_INET:
9988                 if (!have_notifysource)
9989                         src = notify->zone->notifysrc4;
9990                 break;
9991         case PF_INET6:
9992                 if (!have_notifysource)
9993                         src = notify->zone->notifysrc6;
9994                 break;
9995         default:
9996                 result = ISC_R_NOTIMPLEMENTED;
9997                 goto cleanup_key;
9998         }
9999         timeout = 15;
10000         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
10001                 timeout = 30;
10002         result = dns_request_createvia2(notify->zone->view->requestmgr,
10003                                         message, &src, &notify->dst, 0, key,
10004                                         timeout * 3, timeout,
10005                                         notify->zone->task, notify_done,
10006                                         notify, &notify->request);
10007         if (result == ISC_R_SUCCESS) {
10008                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
10009                         inc_stats(notify->zone,
10010                                   dns_zonestatscounter_notifyoutv4);
10011                 } else {
10012                         inc_stats(notify->zone,
10013                                   dns_zonestatscounter_notifyoutv6);
10014                 }
10015         }
10016
10017  cleanup_key:
10018         if (key != NULL)
10019                 dns_tsigkey_detach(&key);
10020  cleanup_message:
10021         dns_message_destroy(&message);
10022  cleanup:
10023         UNLOCK_ZONE(notify->zone);
10024         isc_event_free(&event);
10025         if (result != ISC_R_SUCCESS)
10026                 notify_destroy(notify, ISC_FALSE);
10027 }
10028
10029 static void
10030 notify_send(dns_notify_t *notify) {
10031         dns_adbaddrinfo_t *ai;
10032         isc_sockaddr_t dst;
10033         isc_result_t result;
10034         dns_notify_t *new = NULL;
10035         unsigned int flags;
10036         isc_boolean_t startup;
10037
10038         /*
10039          * Zone lock held by caller.
10040          */
10041         REQUIRE(DNS_NOTIFY_VALID(notify));
10042         REQUIRE(LOCKED_ZONE(notify->zone));
10043
10044         for (ai = ISC_LIST_HEAD(notify->find->list);
10045              ai != NULL;
10046              ai = ISC_LIST_NEXT(ai, publink)) {
10047                 dst = ai->sockaddr;
10048                 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
10049                                     NULL))
10050                         continue;
10051                 if (notify_isself(notify->zone, &dst))
10052                         continue;
10053                 new = NULL;
10054                 flags = notify->flags & DNS_NOTIFY_NOSOA;
10055                 result = notify_create(notify->mctx, flags, &new);
10056                 if (result != ISC_R_SUCCESS)
10057                         goto cleanup;
10058                 zone_iattach(notify->zone, &new->zone);
10059                 ISC_LIST_APPEND(new->zone->notifies, new, link);
10060                 new->dst = dst;
10061                 startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
10062                 result = notify_send_queue(new, startup);
10063                 if (result != ISC_R_SUCCESS)
10064                         goto cleanup;
10065                 new = NULL;
10066         }
10067
10068  cleanup:
10069         if (new != NULL)
10070                 notify_destroy(new, ISC_TRUE);
10071 }
10072
10073 void
10074 dns_zone_notify(dns_zone_t *zone) {
10075         isc_time_t now;
10076
10077         REQUIRE(DNS_ZONE_VALID(zone));
10078
10079         LOCK_ZONE(zone);
10080         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10081
10082         TIME_NOW(&now);
10083         zone_settimer(zone, &now);
10084         UNLOCK_ZONE(zone);
10085 }
10086
10087 static void
10088 zone_notify(dns_zone_t *zone, isc_time_t *now) {
10089         dns_dbnode_t *node = NULL;
10090         dns_db_t *zonedb = NULL;
10091         dns_dbversion_t *version = NULL;
10092         dns_name_t *origin = NULL;
10093         dns_name_t master;
10094         dns_rdata_ns_t ns;
10095         dns_rdata_soa_t soa;
10096         isc_uint32_t serial;
10097         dns_rdata_t rdata = DNS_RDATA_INIT;
10098         dns_rdataset_t nsrdset;
10099         dns_rdataset_t soardset;
10100         isc_result_t result;
10101         unsigned int i;
10102         isc_sockaddr_t dst;
10103         isc_boolean_t isqueued;
10104         dns_notifytype_t notifytype;
10105         unsigned int flags = 0;
10106         isc_boolean_t loggednotify = ISC_FALSE;
10107         isc_boolean_t startup;
10108
10109         REQUIRE(DNS_ZONE_VALID(zone));
10110
10111         LOCK_ZONE(zone);
10112         startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10113         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10114         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
10115         notifytype = zone->notifytype;
10116         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
10117         UNLOCK_ZONE(zone);
10118
10119         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
10120                 return;
10121
10122         if (notifytype == dns_notifytype_no)
10123                 return;
10124
10125         if (notifytype == dns_notifytype_masteronly &&
10126             zone->type != dns_zone_master)
10127                 return;
10128
10129         origin = &zone->origin;
10130
10131         /*
10132          * If the zone is dialup we are done as we don't want to send
10133          * the current soa so as to force a refresh query.
10134          */
10135         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
10136                 flags |= DNS_NOTIFY_NOSOA;
10137
10138         /*
10139          * Record that this was a notify due to starting up.
10140          */
10141         if (startup)
10142                 flags |= DNS_NOTIFY_STARTUP;
10143
10144         /*
10145          * Get SOA RRset.
10146          */
10147         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10148         if (zone->db != NULL)
10149                 dns_db_attach(zone->db, &zonedb);
10150         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10151         if (zonedb == NULL)
10152                 return;
10153         dns_db_currentversion(zonedb, &version);
10154         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
10155         if (result != ISC_R_SUCCESS)
10156                 goto cleanup1;
10157
10158         dns_rdataset_init(&soardset);
10159         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
10160                                      dns_rdatatype_none, 0, &soardset, NULL);
10161         if (result != ISC_R_SUCCESS)
10162                 goto cleanup2;
10163
10164         /*
10165          * Find serial and master server's name.
10166          */
10167         dns_name_init(&master, NULL);
10168         result = dns_rdataset_first(&soardset);
10169         if (result != ISC_R_SUCCESS)
10170                 goto cleanup3;
10171         dns_rdataset_current(&soardset, &rdata);
10172         result = dns_rdata_tostruct(&rdata, &soa, NULL);
10173         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10174         dns_rdata_reset(&rdata);
10175         result = dns_name_dup(&soa.origin, zone->mctx, &master);
10176         serial = soa.serial;
10177         dns_rdataset_disassociate(&soardset);
10178         if (result != ISC_R_SUCCESS)
10179                 goto cleanup3;
10180
10181         /*
10182          * Enqueue notify requests for 'also-notify' servers.
10183          */
10184         LOCK_ZONE(zone);
10185         for (i = 0; i < zone->notifycnt; i++) {
10186                 dns_tsigkey_t *key = NULL;
10187                 dns_notify_t *notify = NULL;
10188
10189                 if ((zone->notifykeynames != NULL) &&
10190                     (zone->notifykeynames[i] != NULL)) {
10191                         dns_view_t *view = dns_zone_getview(zone);
10192                         dns_name_t *keyname = zone->notifykeynames[i];
10193                         (void)dns_view_gettsig(view, keyname, &key);
10194                 }
10195
10196                 dst = zone->notify[i];
10197                 if (notify_isqueued(zone, flags, NULL, &dst, key)) {
10198                         if (key != NULL)
10199                                 dns_tsigkey_detach(&key);
10200                         continue;
10201                 }
10202
10203                 result = notify_create(zone->mctx, flags, &notify);
10204                 if (result != ISC_R_SUCCESS) {
10205                         if (key != NULL)
10206                                 dns_tsigkey_detach(&key);
10207                         continue;
10208                 }
10209
10210                 zone_iattach(zone, &notify->zone);
10211                 notify->dst = dst;
10212
10213                 INSIST(notify->key == NULL);
10214
10215                 if (key != NULL) {
10216                         notify->key = key;
10217                         key = NULL;
10218                 }
10219
10220                 ISC_LIST_APPEND(zone->notifies, notify, link);
10221                 result = notify_send_queue(notify, startup);
10222                 if (result != ISC_R_SUCCESS)
10223                         notify_destroy(notify, ISC_TRUE);
10224                 if (!loggednotify) {
10225                         notify_log(zone, ISC_LOG_INFO,
10226                                    "sending notifies (serial %u)",
10227                                    serial);
10228                         loggednotify = ISC_TRUE;
10229                 }
10230         }
10231         UNLOCK_ZONE(zone);
10232
10233         if (notifytype == dns_notifytype_explicit)
10234                 goto cleanup3;
10235
10236         /*
10237          * Process NS RRset to generate notifies.
10238          */
10239
10240         dns_rdataset_init(&nsrdset);
10241         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
10242                                      dns_rdatatype_none, 0, &nsrdset, NULL);
10243         if (result != ISC_R_SUCCESS)
10244                 goto cleanup3;
10245
10246         result = dns_rdataset_first(&nsrdset);
10247         while (result == ISC_R_SUCCESS) {
10248                 dns_notify_t *notify = NULL;
10249
10250                 dns_rdataset_current(&nsrdset, &rdata);
10251                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
10252                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10253                 dns_rdata_reset(&rdata);
10254                 /*
10255                  * Don't notify the master server unless explicitly
10256                  * configured to do so.
10257                  */
10258                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
10259                     dns_name_compare(&master, &ns.name) == 0) {
10260                         result = dns_rdataset_next(&nsrdset);
10261                         continue;
10262                 }
10263
10264                 if (!loggednotify) {
10265                         notify_log(zone, ISC_LOG_INFO,
10266                                    "sending notifies (serial %u)",
10267                                    serial);
10268                         loggednotify = ISC_TRUE;
10269                 }
10270
10271                 LOCK_ZONE(zone);
10272                 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
10273                 UNLOCK_ZONE(zone);
10274                 if (isqueued) {
10275                         result = dns_rdataset_next(&nsrdset);
10276                         continue;
10277                 }
10278                 result = notify_create(zone->mctx, flags, &notify);
10279                 if (result != ISC_R_SUCCESS)
10280                         continue;
10281                 dns_zone_iattach(zone, &notify->zone);
10282                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
10283                 if (result != ISC_R_SUCCESS) {
10284                         LOCK_ZONE(zone);
10285                         notify_destroy(notify, ISC_TRUE);
10286                         UNLOCK_ZONE(zone);
10287                         continue;
10288                 }
10289                 LOCK_ZONE(zone);
10290                 ISC_LIST_APPEND(zone->notifies, notify, link);
10291                 UNLOCK_ZONE(zone);
10292                 notify_find_address(notify);
10293                 result = dns_rdataset_next(&nsrdset);
10294         }
10295         dns_rdataset_disassociate(&nsrdset);
10296
10297  cleanup3:
10298         if (dns_name_dynamic(&master))
10299                 dns_name_free(&master, zone->mctx);
10300  cleanup2:
10301         dns_db_detachnode(zonedb, &node);
10302  cleanup1:
10303         dns_db_closeversion(zonedb, &version, ISC_FALSE);
10304         dns_db_detach(&zonedb);
10305 }
10306
10307 /***
10308  *** Private
10309  ***/
10310
10311 static inline isc_result_t
10312 save_nsrrset(dns_message_t *message, dns_name_t *name,
10313              dns_db_t *db, dns_dbversion_t *version)
10314 {
10315         dns_rdataset_t *nsrdataset = NULL;
10316         dns_rdataset_t *rdataset = NULL;
10317         dns_dbnode_t *node = NULL;
10318         dns_rdata_ns_t ns;
10319         isc_result_t result;
10320         dns_rdata_t rdata = DNS_RDATA_INIT;
10321
10322         /*
10323          * Extract NS RRset from message.
10324          */
10325         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
10326                                       dns_rdatatype_ns, dns_rdatatype_none,
10327                                       NULL, &nsrdataset);
10328         if (result != ISC_R_SUCCESS)
10329                 goto fail;
10330
10331         /*
10332          * Add NS rdataset.
10333          */
10334         result = dns_db_findnode(db, name, ISC_TRUE, &node);
10335         if (result != ISC_R_SUCCESS)
10336                 goto fail;
10337         result = dns_db_addrdataset(db, node, version, 0,
10338                                     nsrdataset, 0, NULL);
10339         dns_db_detachnode(db, &node);
10340         if (result != ISC_R_SUCCESS)
10341                 goto fail;
10342         /*
10343          * Add glue rdatasets.
10344          */
10345         for (result = dns_rdataset_first(nsrdataset);
10346              result == ISC_R_SUCCESS;
10347              result = dns_rdataset_next(nsrdataset)) {
10348                 dns_rdataset_current(nsrdataset, &rdata);
10349                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
10350                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10351                 dns_rdata_reset(&rdata);
10352                 if (!dns_name_issubdomain(&ns.name, name))
10353                         continue;
10354                 rdataset = NULL;
10355                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10356                                               &ns.name, dns_rdatatype_aaaa,
10357                                               dns_rdatatype_none, NULL,
10358                                               &rdataset);
10359                 if (result == ISC_R_SUCCESS) {
10360                         result = dns_db_findnode(db, &ns.name,
10361                                                  ISC_TRUE, &node);
10362                         if (result != ISC_R_SUCCESS)
10363                                 goto fail;
10364                         result = dns_db_addrdataset(db, node, version, 0,
10365                                                     rdataset, 0, NULL);
10366                         dns_db_detachnode(db, &node);
10367                         if (result != ISC_R_SUCCESS)
10368                                 goto fail;
10369                 }
10370                 rdataset = NULL;
10371                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10372                                               &ns.name, dns_rdatatype_a,
10373                                               dns_rdatatype_none, NULL,
10374                                               &rdataset);
10375                 if (result == ISC_R_SUCCESS) {
10376                         result = dns_db_findnode(db, &ns.name,
10377                                                  ISC_TRUE, &node);
10378                         if (result != ISC_R_SUCCESS)
10379                                 goto fail;
10380                         result = dns_db_addrdataset(db, node, version, 0,
10381                                                     rdataset, 0, NULL);
10382                         dns_db_detachnode(db, &node);
10383                         if (result != ISC_R_SUCCESS)
10384                                 goto fail;
10385                 }
10386         }
10387         if (result != ISC_R_NOMORE)
10388                 goto fail;
10389
10390         return (ISC_R_SUCCESS);
10391
10392 fail:
10393         return (result);
10394 }
10395
10396 static void
10397 stub_callback(isc_task_t *task, isc_event_t *event) {
10398         const char me[] = "stub_callback";
10399         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10400         dns_stub_t *stub = NULL;
10401         dns_message_t *msg = NULL;
10402         dns_zone_t *zone = NULL;
10403         char master[ISC_SOCKADDR_FORMATSIZE];
10404         char source[ISC_SOCKADDR_FORMATSIZE];
10405         isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
10406         isc_result_t result;
10407         isc_time_t now;
10408         isc_boolean_t exiting = ISC_FALSE;
10409         isc_interval_t i;
10410         unsigned int j, soacount;
10411
10412         stub = revent->ev_arg;
10413         INSIST(DNS_STUB_VALID(stub));
10414
10415         UNUSED(task);
10416
10417         zone = stub->zone;
10418
10419         ENTER;
10420
10421         TIME_NOW(&now);
10422
10423         LOCK_ZONE(zone);
10424
10425         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10426                 zone_debuglog(zone, me, 1, "exiting");
10427                 exiting = ISC_TRUE;
10428                 goto next_master;
10429         }
10430
10431         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10432         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10433
10434         if (revent->result != ISC_R_SUCCESS) {
10435                 if (revent->result == ISC_R_TIMEDOUT &&
10436                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10437                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10438                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10439                                      "refreshing stub: timeout retrying "
10440                                      " without EDNS master %s (source %s)",
10441                                      master, source);
10442                         goto same_master;
10443                 }
10444                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
10445                                            &zone->sourceaddr, &now);
10446                 dns_zone_log(zone, ISC_LOG_INFO,
10447                              "could not refresh stub from master %s"
10448                              " (source %s): %s", master, source,
10449                              dns_result_totext(revent->result));
10450                 goto next_master;
10451         }
10452
10453         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10454         if (result != ISC_R_SUCCESS)
10455                 goto next_master;
10456
10457         result = dns_request_getresponse(revent->request, msg, 0);
10458         if (result != ISC_R_SUCCESS)
10459                 goto next_master;
10460
10461         /*
10462          * Unexpected rcode.
10463          */
10464         if (msg->rcode != dns_rcode_noerror) {
10465                 char rcode[128];
10466                 isc_buffer_t rb;
10467
10468                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10469                 (void)dns_rcode_totext(msg->rcode, &rb);
10470
10471                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10472                     (msg->rcode == dns_rcode_servfail ||
10473                      msg->rcode == dns_rcode_notimp ||
10474                      msg->rcode == dns_rcode_formerr)) {
10475                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10476                                      "refreshing stub: rcode (%.*s) retrying "
10477                                      "without EDNS master %s (source %s)",
10478                                      (int)rb.used, rcode, master, source);
10479                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10480                         goto same_master;
10481                 }
10482
10483                 dns_zone_log(zone, ISC_LOG_INFO,
10484                              "refreshing stub: "
10485                              "unexpected rcode (%.*s) from %s (source %s)",
10486                              (int)rb.used, rcode, master, source);
10487                 goto next_master;
10488         }
10489
10490         /*
10491          * We need complete messages.
10492          */
10493         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10494                 if (dns_request_usedtcp(revent->request)) {
10495                         dns_zone_log(zone, ISC_LOG_INFO,
10496                                      "refreshing stub: truncated TCP "
10497                                      "response from master %s (source %s)",
10498                                      master, source);
10499                         goto next_master;
10500                 }
10501                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10502                 goto same_master;
10503         }
10504
10505         /*
10506          * If non-auth log and next master.
10507          */
10508         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10509                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10510                              "non-authoritative answer from "
10511                              "master %s (source %s)", master, source);
10512                 goto next_master;
10513         }
10514
10515         /*
10516          * Sanity checks.
10517          */
10518         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10519         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
10520
10521         if (cnamecnt != 0) {
10522                 dns_zone_log(zone, ISC_LOG_INFO,
10523                              "refreshing stub: unexpected CNAME response "
10524                              "from master %s (source %s)", master, source);
10525                 goto next_master;
10526         }
10527
10528         if (nscnt == 0) {
10529                 dns_zone_log(zone, ISC_LOG_INFO,
10530                              "refreshing stub: no NS records in response "
10531                              "from master %s (source %s)", master, source);
10532                 goto next_master;
10533         }
10534
10535         /*
10536          * Save answer.
10537          */
10538         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
10539         if (result != ISC_R_SUCCESS) {
10540                 dns_zone_log(zone, ISC_LOG_INFO,
10541                              "refreshing stub: unable to save NS records "
10542                              "from master %s (source %s)", master, source);
10543                 goto next_master;
10544         }
10545
10546         /*
10547          * Tidy up.
10548          */
10549         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
10550         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
10551         if (zone->db == NULL)
10552                 zone_attachdb(zone, stub->db);
10553         result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
10554                                   &refresh, &retry, &expire, NULL, NULL);
10555         if (result == ISC_R_SUCCESS && soacount > 0U) {
10556                 zone->refresh = RANGE(refresh, zone->minrefresh,
10557                                       zone->maxrefresh);
10558                 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
10559                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
10560                                      DNS_MAX_EXPIRE);
10561                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10562         }
10563         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
10564         dns_db_detach(&stub->db);
10565
10566         dns_message_destroy(&msg);
10567         isc_event_free(&event);
10568         dns_request_destroy(&zone->request);
10569
10570         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10571         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10572         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10573         isc_interval_set(&i, zone->expire, 0);
10574         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10575
10576         if (zone->masterfile != NULL)
10577                 zone_needdump(zone, 0);
10578
10579         zone_settimer(zone, &now);
10580         goto free_stub;
10581
10582  next_master:
10583         if (stub->version != NULL)
10584                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
10585         if (stub->db != NULL)
10586                 dns_db_detach(&stub->db);
10587         if (msg != NULL)
10588                 dns_message_destroy(&msg);
10589         isc_event_free(&event);
10590         dns_request_destroy(&zone->request);
10591         /*
10592          * Skip to next failed / untried master.
10593          */
10594         do {
10595                 zone->curmaster++;
10596         } while (zone->curmaster < zone->masterscnt &&
10597                  zone->mastersok[zone->curmaster]);
10598         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10599         if (exiting || zone->curmaster >= zone->masterscnt) {
10600                 isc_boolean_t done = ISC_TRUE;
10601                 if (!exiting &&
10602                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10603                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10604                         /*
10605                          * Did we get a good answer from all the masters?
10606                          */
10607                         for (j = 0; j < zone->masterscnt; j++)
10608                                 if (zone->mastersok[j] == ISC_FALSE) {
10609                                         done = ISC_FALSE;
10610                                         break;
10611                                 }
10612                 } else
10613                         done = ISC_TRUE;
10614                 if (!done) {
10615                         zone->curmaster = 0;
10616                         /*
10617                          * Find the next failed master.
10618                          */
10619                         while (zone->curmaster < zone->masterscnt &&
10620                                zone->mastersok[zone->curmaster])
10621                                 zone->curmaster++;
10622                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10623                 } else {
10624                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10625
10626                         zone_settimer(zone, &now);
10627                         goto free_stub;
10628                 }
10629         }
10630         queue_soa_query(zone);
10631         goto free_stub;
10632
10633  same_master:
10634         if (msg != NULL)
10635                 dns_message_destroy(&msg);
10636         isc_event_free(&event);
10637         dns_request_destroy(&zone->request);
10638         ns_query(zone, NULL, stub);
10639         UNLOCK_ZONE(zone);
10640         goto done;
10641
10642  free_stub:
10643         UNLOCK_ZONE(zone);
10644         stub->magic = 0;
10645         dns_zone_idetach(&stub->zone);
10646         INSIST(stub->db == NULL);
10647         INSIST(stub->version == NULL);
10648         isc_mem_put(stub->mctx, stub, sizeof(*stub));
10649
10650  done:
10651         INSIST(event == NULL);
10652         return;
10653 }
10654
10655 /*
10656  * An SOA query has finished (successfully or not).
10657  */
10658 static void
10659 refresh_callback(isc_task_t *task, isc_event_t *event) {
10660         const char me[] = "refresh_callback";
10661         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10662         dns_zone_t *zone;
10663         dns_message_t *msg = NULL;
10664         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
10665         isc_time_t now;
10666         char master[ISC_SOCKADDR_FORMATSIZE];
10667         char source[ISC_SOCKADDR_FORMATSIZE];
10668         dns_rdataset_t *rdataset = NULL;
10669         dns_rdata_t rdata = DNS_RDATA_INIT;
10670         dns_rdata_soa_t soa;
10671         isc_result_t result;
10672         isc_uint32_t serial, oldserial = 0;
10673         unsigned int j;
10674         isc_boolean_t do_queue_xfrin = ISC_FALSE;
10675
10676         zone = revent->ev_arg;
10677         INSIST(DNS_ZONE_VALID(zone));
10678
10679         UNUSED(task);
10680
10681         ENTER;
10682
10683         TIME_NOW(&now);
10684
10685         LOCK_ZONE(zone);
10686
10687         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10688                 isc_event_free(&event);
10689                 dns_request_destroy(&zone->request);
10690                 goto detach;
10691         }
10692
10693         /*
10694          * if timeout log and next master;
10695          */
10696
10697         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10698         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10699
10700         if (revent->result != ISC_R_SUCCESS) {
10701                 if (revent->result == ISC_R_TIMEDOUT &&
10702                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10703                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10704                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10705                                      "refresh: timeout retrying without EDNS "
10706                                      "master %s (source %s)", master, source);
10707                         goto same_master;
10708                 }
10709                 if (revent->result == ISC_R_TIMEDOUT &&
10710                     !dns_request_usedtcp(revent->request)) {
10711                         dns_zone_log(zone, ISC_LOG_INFO,
10712                                      "refresh: retry limit for "
10713                                      "master %s exceeded (source %s)",
10714                                      master, source);
10715                         /* Try with slave with TCP. */
10716                         if ((zone->type == dns_zone_slave ||
10717                              zone->type == dns_zone_redirect) &&
10718                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
10719                                 if (!dns_zonemgr_unreachable(zone->zmgr,
10720                                                              &zone->masteraddr,
10721                                                              &zone->sourceaddr,
10722                                                              &now))
10723                                 {
10724                                         DNS_ZONE_SETFLAG(zone,
10725                                                      DNS_ZONEFLG_SOABEFOREAXFR);
10726                                         goto tcp_transfer;
10727                                 }
10728                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10729                                              "refresh: skipped tcp fallback "
10730                                              "as master %s (source %s) is "
10731                                              "unreachable (cached)",
10732                                               master, source);
10733                         }
10734                 } else
10735                         dns_zone_log(zone, ISC_LOG_INFO,
10736                                      "refresh: failure trying master "
10737                                      "%s (source %s): %s", master, source,
10738                                      dns_result_totext(revent->result));
10739                 goto next_master;
10740         }
10741
10742         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10743         if (result != ISC_R_SUCCESS)
10744                 goto next_master;
10745         result = dns_request_getresponse(revent->request, msg, 0);
10746         if (result != ISC_R_SUCCESS) {
10747                 dns_zone_log(zone, ISC_LOG_INFO,
10748                              "refresh: failure trying master "
10749                              "%s (source %s): %s", master, source,
10750                              dns_result_totext(result));
10751                 goto next_master;
10752         }
10753
10754         /*
10755          * Unexpected rcode.
10756          */
10757         if (msg->rcode != dns_rcode_noerror) {
10758                 char rcode[128];
10759                 isc_buffer_t rb;
10760
10761                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10762                 (void)dns_rcode_totext(msg->rcode, &rb);
10763
10764                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10765                     (msg->rcode == dns_rcode_servfail ||
10766                      msg->rcode == dns_rcode_notimp ||
10767                      msg->rcode == dns_rcode_formerr)) {
10768                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10769                                      "refresh: rcode (%.*s) retrying without "
10770                                      "EDNS master %s (source %s)",
10771                                      (int)rb.used, rcode, master, source);
10772                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10773                         goto same_master;
10774                 }
10775                 dns_zone_log(zone, ISC_LOG_INFO,
10776                              "refresh: unexpected rcode (%.*s) from "
10777                              "master %s (source %s)", (int)rb.used, rcode,
10778                              master, source);
10779                 /*
10780                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
10781                  */
10782                 if (msg->rcode == dns_rcode_refused &&
10783                     (zone->type == dns_zone_slave ||
10784                      zone->type == dns_zone_redirect))
10785                         goto tcp_transfer;
10786                 goto next_master;
10787         }
10788
10789         /*
10790          * If truncated punt to zone transfer which will query again.
10791          */
10792         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10793                 if (zone->type == dns_zone_slave ||
10794                     zone->type == dns_zone_redirect) {
10795                         dns_zone_log(zone, ISC_LOG_INFO,
10796                                      "refresh: truncated UDP answer, "
10797                                      "initiating TCP zone xfer "
10798                                      "for master %s (source %s)",
10799                                      master, source);
10800                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
10801                         goto tcp_transfer;
10802                 } else {
10803                         INSIST(zone->type == dns_zone_stub);
10804                         if (dns_request_usedtcp(revent->request)) {
10805                                 dns_zone_log(zone, ISC_LOG_INFO,
10806                                              "refresh: truncated TCP response "
10807                                              "from master %s (source %s)",
10808                                              master, source);
10809                                 goto next_master;
10810                         }
10811                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10812                         goto same_master;
10813                 }
10814         }
10815
10816         /*
10817          * if non-auth log and next master;
10818          */
10819         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10820                 dns_zone_log(zone, ISC_LOG_INFO,
10821                              "refresh: non-authoritative answer from "
10822                              "master %s (source %s)", master, source);
10823                 goto next_master;
10824         }
10825
10826         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10827         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
10828         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
10829         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
10830                                  dns_rdatatype_soa);
10831
10832         /*
10833          * There should not be a CNAME record at top of zone.
10834          */
10835         if (cnamecnt != 0) {
10836                 dns_zone_log(zone, ISC_LOG_INFO,
10837                              "refresh: CNAME at top of zone "
10838                              "in master %s (source %s)", master, source);
10839                 goto next_master;
10840         }
10841
10842         /*
10843          * if referral log and next master;
10844          */
10845         if (soacnt == 0 && soacount == 0 && nscount != 0) {
10846                 dns_zone_log(zone, ISC_LOG_INFO,
10847                              "refresh: referral response "
10848                              "from master %s (source %s)", master, source);
10849                 goto next_master;
10850         }
10851
10852         /*
10853          * if nodata log and next master;
10854          */
10855         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
10856                 dns_zone_log(zone, ISC_LOG_INFO,
10857                              "refresh: NODATA response "
10858                              "from master %s (source %s)", master, source);
10859                 goto next_master;
10860         }
10861
10862         /*
10863          * Only one soa at top of zone.
10864          */
10865         if (soacnt != 1) {
10866                 dns_zone_log(zone, ISC_LOG_INFO,
10867                              "refresh: answer SOA count (%d) != 1 "
10868                              "from master %s (source %s)",
10869                              soacnt, master, source);
10870                 goto next_master;
10871         }
10872
10873         /*
10874          * Extract serial
10875          */
10876         rdataset = NULL;
10877         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
10878                                       dns_rdatatype_soa, dns_rdatatype_none,
10879                                       NULL, &rdataset);
10880         if (result != ISC_R_SUCCESS) {
10881                 dns_zone_log(zone, ISC_LOG_INFO,
10882                              "refresh: unable to get SOA record "
10883                              "from master %s (source %s)", master, source);
10884                 goto next_master;
10885         }
10886
10887         result = dns_rdataset_first(rdataset);
10888         if (result != ISC_R_SUCCESS) {
10889                 dns_zone_log(zone, ISC_LOG_INFO,
10890                              "refresh: dns_rdataset_first() failed");
10891                 goto next_master;
10892         }
10893
10894         dns_rdataset_current(rdataset, &rdata);
10895         result = dns_rdata_tostruct(&rdata, &soa, NULL);
10896         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10897
10898         serial = soa.serial;
10899         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10900                 unsigned int dbsoacount;
10901                 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
10902                                           &oldserial, NULL, NULL, NULL, NULL,
10903                                           NULL);
10904                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10905                 RUNTIME_CHECK(dbsoacount > 0U);
10906                 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
10907                               serial, oldserial);
10908         } else
10909                 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
10910                               serial);
10911
10912         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
10913             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
10914             isc_serial_gt(serial, oldserial)) {
10915                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
10916                                             &zone->sourceaddr, &now))
10917                 {
10918                         dns_zone_log(zone, ISC_LOG_INFO,
10919                                      "refresh: skipping %s as master %s "
10920                                      "(source %s) is unreachable (cached)",
10921                                      (zone->type == dns_zone_slave ||
10922                                       zone->type == dns_zone_redirect) ?
10923                                      "zone transfer" : "NS query",
10924                                      master, source);
10925                         goto next_master;
10926                 }
10927  tcp_transfer:
10928                 isc_event_free(&event);
10929                 dns_request_destroy(&zone->request);
10930                 if (zone->type == dns_zone_slave ||
10931                     zone->type == dns_zone_redirect) {
10932                         do_queue_xfrin = ISC_TRUE;
10933                 } else {
10934                         INSIST(zone->type == dns_zone_stub);
10935                         ns_query(zone, rdataset, NULL);
10936                 }
10937                 if (msg != NULL)
10938                         dns_message_destroy(&msg);
10939         } else if (isc_serial_eq(soa.serial, oldserial)) {
10940                 if (zone->masterfile != NULL) {
10941                         result = ISC_R_FAILURE;
10942                         if (zone->journal != NULL)
10943                                 result = isc_file_settime(zone->journal, &now);
10944                         if (result == ISC_R_SUCCESS &&
10945                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10946                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10947                                 result = isc_file_settime(zone->masterfile,
10948                                                           &now);
10949                         } else if (result != ISC_R_SUCCESS)
10950                                 result = isc_file_settime(zone->masterfile,
10951                                                           &now);
10952                         /* Someone removed the file from underneath us! */
10953                         if (result == ISC_R_FILENOTFOUND) {
10954                                 zone_needdump(zone, DNS_DUMP_DELAY);
10955                         } else if (result != ISC_R_SUCCESS)
10956                                 dns_zone_log(zone, ISC_LOG_ERROR,
10957                                              "refresh: could not set file "
10958                                              "modification time of '%s': %s",
10959                                              zone->masterfile,
10960                                              dns_result_totext(result));
10961                 }
10962                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10963                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10964                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10965                 goto next_master;
10966         } else {
10967                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
10968                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
10969                                      "received from master %s < ours (%u)",
10970                                      soa.serial, master, oldserial);
10971                 else
10972                         zone_debuglog(zone, me, 1, "ahead");
10973                 zone->mastersok[zone->curmaster] = ISC_TRUE;
10974                 goto next_master;
10975         }
10976         if (msg != NULL)
10977                 dns_message_destroy(&msg);
10978         goto detach;
10979
10980  next_master:
10981         if (msg != NULL)
10982                 dns_message_destroy(&msg);
10983         isc_event_free(&event);
10984         dns_request_destroy(&zone->request);
10985         /*
10986          * Skip to next failed / untried master.
10987          */
10988         do {
10989                 zone->curmaster++;
10990         } while (zone->curmaster < zone->masterscnt &&
10991                  zone->mastersok[zone->curmaster]);
10992         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10993         if (zone->curmaster >= zone->masterscnt) {
10994                 isc_boolean_t done = ISC_TRUE;
10995                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
10996                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10997                         /*
10998                          * Did we get a good answer from all the masters?
10999                          */
11000                         for (j = 0; j < zone->masterscnt; j++)
11001                                 if (zone->mastersok[j] == ISC_FALSE) {
11002                                         done = ISC_FALSE;
11003                                         break;
11004                                 }
11005                 } else
11006                         done = ISC_TRUE;
11007                 if (!done) {
11008                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11009                         zone->curmaster = 0;
11010                         /*
11011                          * Find the next failed master.
11012                          */
11013                         while (zone->curmaster < zone->masterscnt &&
11014                                zone->mastersok[zone->curmaster])
11015                                 zone->curmaster++;
11016                         goto requeue;
11017                 }
11018                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11019                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
11020                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11021                         zone->refreshtime = now;
11022                 }
11023                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11024                 zone_settimer(zone, &now);
11025                 goto detach;
11026         }
11027
11028  requeue:
11029         queue_soa_query(zone);
11030         goto detach;
11031
11032  same_master:
11033         if (msg != NULL)
11034                 dns_message_destroy(&msg);
11035         isc_event_free(&event);
11036         dns_request_destroy(&zone->request);
11037         queue_soa_query(zone);
11038
11039  detach:
11040         UNLOCK_ZONE(zone);
11041         if (do_queue_xfrin)
11042                 queue_xfrin(zone);
11043         dns_zone_idetach(&zone);
11044         return;
11045 }
11046
11047 static void
11048 queue_soa_query(dns_zone_t *zone) {
11049         const char me[] = "queue_soa_query";
11050         isc_event_t *e;
11051         dns_zone_t *dummy = NULL;
11052         isc_result_t result;
11053
11054         ENTER;
11055         /*
11056          * Locked by caller
11057          */
11058         REQUIRE(LOCKED_ZONE(zone));
11059
11060         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11061                 cancel_refresh(zone);
11062                 return;
11063         }
11064
11065         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
11066                                soa_query, zone, sizeof(isc_event_t));
11067         if (e == NULL) {
11068                 cancel_refresh(zone);
11069                 return;
11070         }
11071
11072         /*
11073          * Attach so that we won't clean up
11074          * until the event is delivered.
11075          */
11076         zone_iattach(zone, &dummy);
11077
11078         e->ev_arg = zone;
11079         e->ev_sender = NULL;
11080         result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
11081         if (result != ISC_R_SUCCESS) {
11082                 zone_idetach(&dummy);
11083                 isc_event_free(&e);
11084                 cancel_refresh(zone);
11085         }
11086 }
11087
11088 static inline isc_result_t
11089 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
11090              dns_message_t **messagep)
11091 {
11092         dns_message_t *message = NULL;
11093         dns_name_t *qname = NULL;
11094         dns_rdataset_t *qrdataset = NULL;
11095         isc_result_t result;
11096
11097         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11098                                     &message);
11099         if (result != ISC_R_SUCCESS)
11100                 goto cleanup;
11101
11102         message->opcode = dns_opcode_query;
11103         message->rdclass = zone->rdclass;
11104
11105         result = dns_message_gettempname(message, &qname);
11106         if (result != ISC_R_SUCCESS)
11107                 goto cleanup;
11108
11109         result = dns_message_gettemprdataset(message, &qrdataset);
11110         if (result != ISC_R_SUCCESS)
11111                 goto cleanup;
11112
11113         /*
11114          * Make question.
11115          */
11116         dns_name_init(qname, NULL);
11117         dns_name_clone(&zone->origin, qname);
11118         dns_rdataset_init(qrdataset);
11119         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
11120         ISC_LIST_APPEND(qname->list, qrdataset, link);
11121         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
11122
11123         *messagep = message;
11124         return (ISC_R_SUCCESS);
11125
11126  cleanup:
11127         if (qname != NULL)
11128                 dns_message_puttempname(message, &qname);
11129         if (qrdataset != NULL)
11130                 dns_message_puttemprdataset(message, &qrdataset);
11131         if (message != NULL)
11132                 dns_message_destroy(&message);
11133         return (result);
11134 }
11135
11136 static isc_result_t
11137 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
11138         isc_result_t result;
11139         dns_rdataset_t *rdataset = NULL;
11140         dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
11141         int count = 0;
11142
11143         /* Set EDNS options if applicable */
11144         if (reqnsid) {
11145                 INSIST(count < DNS_EDNSOPTIONS);
11146                 ednsopts[count].code = DNS_OPT_NSID;
11147                 ednsopts[count].length = 0;
11148                 ednsopts[count].value = NULL;
11149                 count++;
11150         }
11151         result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
11152                                       ednsopts, count);
11153         if (result != ISC_R_SUCCESS)
11154                 return (result);
11155
11156         return (dns_message_setopt(message, rdataset));
11157 }
11158
11159 static void
11160 soa_query(isc_task_t *task, isc_event_t *event) {
11161         const char me[] = "soa_query";
11162         isc_result_t result = ISC_R_FAILURE;
11163         dns_message_t *message = NULL;
11164         dns_zone_t *zone = event->ev_arg;
11165         dns_zone_t *dummy = NULL;
11166         isc_netaddr_t masterip;
11167         dns_tsigkey_t *key = NULL;
11168         isc_uint32_t options;
11169         isc_boolean_t cancel = ISC_TRUE;
11170         int timeout;
11171         isc_boolean_t have_xfrsource, reqnsid;
11172         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11173
11174         REQUIRE(DNS_ZONE_VALID(zone));
11175
11176         UNUSED(task);
11177
11178         ENTER;
11179
11180         LOCK_ZONE(zone);
11181         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
11182             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11183             zone->view->requestmgr == NULL) {
11184                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11185                         cancel = ISC_FALSE;
11186                 goto cleanup;
11187         }
11188
11189  again:
11190         result = create_query(zone, dns_rdatatype_soa, &message);
11191         if (result != ISC_R_SUCCESS)
11192                 goto cleanup;
11193
11194         INSIST(zone->masterscnt > 0);
11195         INSIST(zone->curmaster < zone->masterscnt);
11196
11197         zone->masteraddr = zone->masters[zone->curmaster];
11198
11199         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11200         /*
11201          * First, look for a tsig key in the master statement, then
11202          * try for a server key.
11203          */
11204         if ((zone->masterkeynames != NULL) &&
11205             (zone->masterkeynames[zone->curmaster] != NULL)) {
11206                 dns_view_t *view = dns_zone_getview(zone);
11207                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11208                 result = dns_view_gettsig(view, keyname, &key);
11209                 if (result != ISC_R_SUCCESS) {
11210                         char namebuf[DNS_NAME_FORMATSIZE];
11211                         dns_name_format(keyname, namebuf, sizeof(namebuf));
11212                         dns_zone_log(zone, ISC_LOG_ERROR,
11213                                      "unable to find key: %s", namebuf);
11214                         goto skip_master;
11215                 }
11216         }
11217         if (key == NULL) {
11218                 result = dns_view_getpeertsig(zone->view, &masterip, &key);
11219                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11220                         char addrbuf[ISC_NETADDR_FORMATSIZE];
11221                         isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
11222                         dns_zone_log(zone, ISC_LOG_ERROR,
11223                                      "unable to find TSIG key for %s", addrbuf);
11224                         goto skip_master;
11225                 }
11226         }
11227
11228         have_xfrsource = ISC_FALSE;
11229         reqnsid = zone->view->requestnsid;
11230         if (zone->view->peers != NULL) {
11231                 dns_peer_t *peer = NULL;
11232                 isc_boolean_t edns;
11233                 result = dns_peerlist_peerbyaddr(zone->view->peers,
11234                                                  &masterip, &peer);
11235                 if (result == ISC_R_SUCCESS) {
11236                         result = dns_peer_getsupportedns(peer, &edns);
11237                         if (result == ISC_R_SUCCESS && !edns)
11238                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11239                         result = dns_peer_gettransfersource(peer,
11240                                                             &zone->sourceaddr);
11241                         if (result == ISC_R_SUCCESS)
11242                                 have_xfrsource = ISC_TRUE;
11243                         if (zone->view->resolver != NULL)
11244                                 udpsize =
11245                                   dns_resolver_getudpsize(zone->view->resolver);
11246                         (void)dns_peer_getudpsize(peer, &udpsize);
11247                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
11248                 }
11249         }
11250
11251         switch (isc_sockaddr_pf(&zone->masteraddr)) {
11252         case PF_INET:
11253                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11254                         if (isc_sockaddr_equal(&zone->altxfrsource4,
11255                                                &zone->xfrsource4))
11256                                 goto skip_master;
11257                         zone->sourceaddr = zone->altxfrsource4;
11258                 } else if (!have_xfrsource)
11259                         zone->sourceaddr = zone->xfrsource4;
11260                 break;
11261         case PF_INET6:
11262                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11263                         if (isc_sockaddr_equal(&zone->altxfrsource6,
11264                                                &zone->xfrsource6))
11265                                 goto skip_master;
11266                         zone->sourceaddr = zone->altxfrsource6;
11267                 } else if (!have_xfrsource)
11268                         zone->sourceaddr = zone->xfrsource6;
11269                 break;
11270         default:
11271                 result = ISC_R_NOTIMPLEMENTED;
11272                 goto cleanup;
11273         }
11274
11275         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
11276                   DNS_REQUESTOPT_TCP : 0;
11277
11278         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11279                 result = add_opt(message, udpsize, reqnsid);
11280                 if (result != ISC_R_SUCCESS)
11281                         zone_debuglog(zone, me, 1,
11282                                       "unable to add opt record: %s",
11283                                       dns_result_totext(result));
11284         }
11285
11286         zone_iattach(zone, &dummy);
11287         timeout = 15;
11288         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11289                 timeout = 30;
11290         result = dns_request_createvia2(zone->view->requestmgr, message,
11291                                         &zone->sourceaddr, &zone->masteraddr,
11292                                         options, key, timeout * 3, timeout,
11293                                         zone->task, refresh_callback, zone,
11294                                         &zone->request);
11295         if (result != ISC_R_SUCCESS) {
11296                 zone_idetach(&dummy);
11297                 zone_debuglog(zone, me, 1,
11298                               "dns_request_createvia4() failed: %s",
11299                               dns_result_totext(result));
11300                 goto skip_master;
11301         } else {
11302                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
11303                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
11304                 else
11305                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
11306         }
11307         cancel = ISC_FALSE;
11308
11309  cleanup:
11310         if (key != NULL)
11311                 dns_tsigkey_detach(&key);
11312         if (result != ISC_R_SUCCESS)
11313                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11314         if (message != NULL)
11315                 dns_message_destroy(&message);
11316         if (cancel)
11317                 cancel_refresh(zone);
11318         isc_event_free(&event);
11319         UNLOCK_ZONE(zone);
11320         dns_zone_idetach(&zone);
11321         return;
11322
11323  skip_master:
11324         if (key != NULL)
11325                 dns_tsigkey_detach(&key);
11326         dns_message_destroy(&message);
11327         /*
11328          * Skip to next failed / untried master.
11329          */
11330         do {
11331                 zone->curmaster++;
11332         } while (zone->curmaster < zone->masterscnt &&
11333                  zone->mastersok[zone->curmaster]);
11334         if (zone->curmaster < zone->masterscnt)
11335                 goto again;
11336         zone->curmaster = 0;
11337         goto cleanup;
11338 }
11339
11340 static void
11341 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
11342         const char me[] = "ns_query";
11343         isc_result_t result;
11344         dns_message_t *message = NULL;
11345         isc_netaddr_t masterip;
11346         dns_tsigkey_t *key = NULL;
11347         dns_dbnode_t *node = NULL;
11348         int timeout;
11349         isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
11350         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11351
11352         REQUIRE(DNS_ZONE_VALID(zone));
11353         REQUIRE(LOCKED_ZONE(zone));
11354         REQUIRE((soardataset != NULL && stub == NULL) ||
11355                 (soardataset == NULL && stub != NULL));
11356         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
11357
11358         ENTER;
11359
11360         if (stub == NULL) {
11361                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
11362                 if (stub == NULL)
11363                         goto cleanup;
11364                 stub->magic = STUB_MAGIC;
11365                 stub->mctx = zone->mctx;
11366                 stub->zone = NULL;
11367                 stub->db = NULL;
11368                 stub->version = NULL;
11369
11370                 /*
11371                  * Attach so that the zone won't disappear from under us.
11372                  */
11373                 zone_iattach(zone, &stub->zone);
11374
11375                 /*
11376                  * If a db exists we will update it, otherwise we create a
11377                  * new one and attach it to the zone once we have the NS
11378                  * RRset and glue.
11379                  */
11380                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11381                 if (zone->db != NULL) {
11382                         dns_db_attach(zone->db, &stub->db);
11383                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11384                 } else {
11385                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11386
11387                         INSIST(zone->db_argc >= 1);
11388                         result = dns_db_create(zone->mctx, zone->db_argv[0],
11389                                                &zone->origin, dns_dbtype_stub,
11390                                                zone->rdclass,
11391                                                zone->db_argc - 1,
11392                                                zone->db_argv + 1,
11393                                                &stub->db);
11394                         if (result != ISC_R_SUCCESS) {
11395                                 dns_zone_log(zone, ISC_LOG_ERROR,
11396                                              "refreshing stub: "
11397                                              "could not create "
11398                                              "database: %s",
11399                                              dns_result_totext(result));
11400                                 goto cleanup;
11401                         }
11402                         dns_db_settask(stub->db, zone->task);
11403                 }
11404
11405                 result = dns_db_newversion(stub->db, &stub->version);
11406                 if (result != ISC_R_SUCCESS) {
11407                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11408                                      "dns_db_newversion() failed: %s",
11409                                      dns_result_totext(result));
11410                         goto cleanup;
11411                 }
11412
11413                 /*
11414                  * Update SOA record.
11415                  */
11416                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
11417                                          &node);
11418                 if (result != ISC_R_SUCCESS) {
11419                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11420                                      "dns_db_findnode() failed: %s",
11421                                      dns_result_totext(result));
11422                         goto cleanup;
11423                 }
11424
11425                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
11426                                             soardataset, 0, NULL);
11427                 dns_db_detachnode(stub->db, &node);
11428                 if (result != ISC_R_SUCCESS) {
11429                         dns_zone_log(zone, ISC_LOG_INFO,
11430                                      "refreshing stub: "
11431                                      "dns_db_addrdataset() failed: %s",
11432                                      dns_result_totext(result));
11433                         goto cleanup;
11434                 }
11435         }
11436
11437         /*
11438          * XXX Optimisation: Create message when zone is setup and reuse.
11439          */
11440         result = create_query(zone, dns_rdatatype_ns, &message);
11441         INSIST(result == ISC_R_SUCCESS);
11442
11443         INSIST(zone->masterscnt > 0);
11444         INSIST(zone->curmaster < zone->masterscnt);
11445         zone->masteraddr = zone->masters[zone->curmaster];
11446
11447         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11448         /*
11449          * First, look for a tsig key in the master statement, then
11450          * try for a server key.
11451          */
11452         if ((zone->masterkeynames != NULL) &&
11453             (zone->masterkeynames[zone->curmaster] != NULL)) {
11454                 dns_view_t *view = dns_zone_getview(zone);
11455                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11456                 result = dns_view_gettsig(view, keyname, &key);
11457                 if (result != ISC_R_SUCCESS) {
11458                         char namebuf[DNS_NAME_FORMATSIZE];
11459                         dns_name_format(keyname, namebuf, sizeof(namebuf));
11460                         dns_zone_log(zone, ISC_LOG_ERROR,
11461                                      "unable to find key: %s", namebuf);
11462                 }
11463         }
11464         if (key == NULL)
11465                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
11466
11467         reqnsid = zone->view->requestnsid;
11468         if (zone->view->peers != NULL) {
11469                 dns_peer_t *peer = NULL;
11470                 isc_boolean_t edns;
11471                 result = dns_peerlist_peerbyaddr(zone->view->peers,
11472                                                  &masterip, &peer);
11473                 if (result == ISC_R_SUCCESS) {
11474                         result = dns_peer_getsupportedns(peer, &edns);
11475                         if (result == ISC_R_SUCCESS && !edns)
11476                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11477                         result = dns_peer_gettransfersource(peer,
11478                                                             &zone->sourceaddr);
11479                         if (result == ISC_R_SUCCESS)
11480                                 have_xfrsource = ISC_TRUE;
11481                         if (zone->view->resolver != NULL)
11482                                 udpsize =
11483                                   dns_resolver_getudpsize(zone->view->resolver);
11484                         (void)dns_peer_getudpsize(peer, &udpsize);
11485                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
11486                 }
11487
11488         }
11489         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11490                 result = add_opt(message, udpsize, reqnsid);
11491                 if (result != ISC_R_SUCCESS)
11492                         zone_debuglog(zone, me, 1,
11493                                       "unable to add opt record: %s",
11494                                       dns_result_totext(result));
11495         }
11496
11497         /*
11498          * Always use TCP so that we shouldn't truncate in additional section.
11499          */
11500         switch (isc_sockaddr_pf(&zone->masteraddr)) {
11501         case PF_INET:
11502                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11503                         zone->sourceaddr = zone->altxfrsource4;
11504                 else if (!have_xfrsource)
11505                         zone->sourceaddr = zone->xfrsource4;
11506                 break;
11507         case PF_INET6:
11508                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
11509                         zone->sourceaddr = zone->altxfrsource6;
11510                 else if (!have_xfrsource)
11511                         zone->sourceaddr = zone->xfrsource6;
11512                 break;
11513         default:
11514                 result = ISC_R_NOTIMPLEMENTED;
11515                 POST(result);
11516                 goto cleanup;
11517         }
11518         timeout = 15;
11519         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11520                 timeout = 30;
11521         result = dns_request_createvia2(zone->view->requestmgr, message,
11522                                         &zone->sourceaddr, &zone->masteraddr,
11523                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
11524                                         timeout, zone->task, stub_callback,
11525                                         stub, &zone->request);
11526         if (result != ISC_R_SUCCESS) {
11527                 zone_debuglog(zone, me, 1,
11528                               "dns_request_createvia() failed: %s",
11529                               dns_result_totext(result));
11530                 goto cleanup;
11531         }
11532         dns_message_destroy(&message);
11533         goto unlock;
11534
11535  cleanup:
11536         cancel_refresh(zone);
11537         if (stub != NULL) {
11538                 stub->magic = 0;
11539                 if (stub->version != NULL)
11540                         dns_db_closeversion(stub->db, &stub->version,
11541                                             ISC_FALSE);
11542                 if (stub->db != NULL)
11543                         dns_db_detach(&stub->db);
11544                 if (stub->zone != NULL)
11545                         zone_idetach(&stub->zone);
11546                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
11547         }
11548         if (message != NULL)
11549                 dns_message_destroy(&message);
11550  unlock:
11551         if (key != NULL)
11552                 dns_tsigkey_detach(&key);
11553         return;
11554 }
11555
11556 /*
11557  * Handle the control event.  Note that although this event causes the zone
11558  * to shut down, it is not a shutdown event in the sense of the task library.
11559  */
11560 static void
11561 zone_shutdown(isc_task_t *task, isc_event_t *event) {
11562         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
11563         isc_boolean_t free_needed, linked = ISC_FALSE;
11564         dns_zone_t *raw = NULL, *secure = NULL;
11565
11566         UNUSED(task);
11567         REQUIRE(DNS_ZONE_VALID(zone));
11568         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
11569         INSIST(isc_refcount_current(&zone->erefs) == 0);
11570
11571         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
11572
11573         /*
11574          * Stop things being restarted after we cancel them below.
11575          */
11576         LOCK_ZONE(zone);
11577         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
11578         UNLOCK_ZONE(zone);
11579
11580         /*
11581          * If we were waiting for xfrin quota, step out of
11582          * the queue.
11583          * If there's no zone manager, we can't be waiting for the
11584          * xfrin quota
11585          */
11586         if (zone->zmgr != NULL) {
11587                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11588                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
11589                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
11590                                         statelink);
11591                         linked = ISC_TRUE;
11592                         zone->statelist = NULL;
11593                 }
11594                 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
11595                         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
11596                                         statelink);
11597                         zone->statelist = NULL;
11598                         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
11599                 }
11600                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11601         }
11602
11603         /*
11604          * In task context, no locking required.  See zone_xfrdone().
11605          */
11606         if (zone->xfr != NULL)
11607                 dns_xfrin_shutdown(zone->xfr);
11608
11609         /* Safe to release the zone now */
11610         if (zone->zmgr != NULL)
11611                 dns_zonemgr_releasezone(zone->zmgr, zone);
11612
11613         LOCK_ZONE(zone);
11614         if (linked) {
11615                 INSIST(zone->irefs > 0);
11616                 zone->irefs--;
11617         }
11618         if (zone->request != NULL) {
11619                 dns_request_cancel(zone->request);
11620         }
11621
11622         if (zone->readio != NULL)
11623                 zonemgr_cancelio(zone->readio);
11624
11625         if (zone->lctx != NULL)
11626                 dns_loadctx_cancel(zone->lctx);
11627
11628         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11629             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11630                 if (zone->writeio != NULL)
11631                         zonemgr_cancelio(zone->writeio);
11632
11633                 if (zone->dctx != NULL)
11634                         dns_dumpctx_cancel(zone->dctx);
11635         }
11636
11637         notify_cancel(zone);
11638
11639         forward_cancel(zone);
11640
11641         if (zone->timer != NULL) {
11642                 isc_timer_detach(&zone->timer);
11643                 INSIST(zone->irefs > 0);
11644                 zone->irefs--;
11645         }
11646
11647         if (zone->view != NULL)
11648                 dns_view_weakdetach(&zone->view);
11649
11650         /*
11651          * We have now canceled everything set the flag to allow exit_check()
11652          * to succeed.  We must not unlock between setting this flag and
11653          * calling exit_check().
11654          */
11655         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
11656         free_needed = exit_check(zone);
11657         if (inline_secure(zone)) {
11658                 raw = zone->raw;
11659                 zone->raw = NULL;
11660         }
11661         if (inline_raw(zone)) {
11662                 secure = zone->secure;
11663                 zone->secure = NULL;
11664         }
11665         UNLOCK_ZONE(zone);
11666         if (raw != NULL)
11667                 dns_zone_detach(&raw);
11668         if (secure != NULL)
11669                 dns_zone_idetach(&secure);
11670         if (free_needed)
11671                 zone_free(zone);
11672 }
11673
11674 static void
11675 zone_timer(isc_task_t *task, isc_event_t *event) {
11676         const char me[] = "zone_timer";
11677         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
11678
11679         UNUSED(task);
11680         REQUIRE(DNS_ZONE_VALID(zone));
11681
11682         ENTER;
11683
11684         zone_maintenance(zone);
11685
11686         isc_event_free(&event);
11687 }
11688
11689 static void
11690 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
11691         const char me[] = "zone_settimer";
11692         isc_time_t next;
11693         isc_result_t result;
11694
11695         ENTER;
11696         REQUIRE(DNS_ZONE_VALID(zone));
11697         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11698                 return;
11699
11700         isc_time_settoepoch(&next);
11701
11702         switch (zone->type) {
11703         case dns_zone_redirect:
11704                 if (zone->masters != NULL)
11705                         goto treat_as_slave;
11706                 /* FALLTHROUGH */
11707
11708         case dns_zone_master:
11709                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11710                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
11711                         next = zone->notifytime;
11712                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11713                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11714                         INSIST(!isc_time_isepoch(&zone->dumptime));
11715                         if (isc_time_isepoch(&next) ||
11716                             isc_time_compare(&zone->dumptime, &next) < 0)
11717                                 next = zone->dumptime;
11718                 }
11719                 if (zone->type == dns_zone_redirect)
11720                         break;
11721                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
11722                     !isc_time_isepoch(&zone->refreshkeytime)) {
11723                         if (isc_time_isepoch(&next) ||
11724                             isc_time_compare(&zone->refreshkeytime, &next) < 0)
11725                                 next = zone->refreshkeytime;
11726                 }
11727                 if (!isc_time_isepoch(&zone->resigntime)) {
11728                         if (isc_time_isepoch(&next) ||
11729                             isc_time_compare(&zone->resigntime, &next) < 0)
11730                                 next = zone->resigntime;
11731                 }
11732                 if (!isc_time_isepoch(&zone->keywarntime)) {
11733                         if (isc_time_isepoch(&next) ||
11734                             isc_time_compare(&zone->keywarntime, &next) < 0)
11735                                 next = zone->keywarntime;
11736                 }
11737                 if (!isc_time_isepoch(&zone->signingtime)) {
11738                         if (isc_time_isepoch(&next) ||
11739                             isc_time_compare(&zone->signingtime, &next) < 0)
11740                                 next = zone->signingtime;
11741                 }
11742                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
11743                         if (isc_time_isepoch(&next) ||
11744                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
11745                                 next = zone->nsec3chaintime;
11746                 }
11747                 break;
11748
11749         case dns_zone_slave:
11750         treat_as_slave:
11751                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11752                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
11753                         next = zone->notifytime;
11754                 /* FALLTHROUGH */
11755
11756         case dns_zone_stub:
11757                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
11758                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
11759                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
11760                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
11761                         INSIST(!isc_time_isepoch(&zone->refreshtime));
11762                         if (isc_time_isepoch(&next) ||
11763                             isc_time_compare(&zone->refreshtime, &next) < 0)
11764                                 next = zone->refreshtime;
11765                 }
11766                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11767                     !isc_time_isepoch(&zone->expiretime)) {
11768                         if (isc_time_isepoch(&next) ||
11769                              isc_time_compare(&zone->expiretime, &next) < 0)
11770                                 next = zone->expiretime;
11771                 }
11772                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11773                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11774                         INSIST(!isc_time_isepoch(&zone->dumptime));
11775                         if (isc_time_isepoch(&next) ||
11776                             isc_time_compare(&zone->dumptime, &next) < 0)
11777                                 next = zone->dumptime;
11778                 }
11779                 break;
11780
11781         case dns_zone_key:
11782                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11783                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11784                         INSIST(!isc_time_isepoch(&zone->dumptime));
11785                         if (isc_time_isepoch(&next) ||
11786                             isc_time_compare(&zone->dumptime, &next) < 0)
11787                                 next = zone->dumptime;
11788                 }
11789                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
11790                         if (isc_time_isepoch(&next) ||
11791                             (!isc_time_isepoch(&zone->refreshkeytime) &&
11792                             isc_time_compare(&zone->refreshkeytime, &next) < 0))
11793                                 next = zone->refreshkeytime;
11794                 }
11795                 break;
11796
11797         default:
11798                 break;
11799         }
11800
11801         if (isc_time_isepoch(&next)) {
11802                 zone_debuglog(zone, me, 10, "settimer inactive");
11803                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
11804                                           NULL, NULL, ISC_TRUE);
11805                 if (result != ISC_R_SUCCESS)
11806                         dns_zone_log(zone, ISC_LOG_ERROR,
11807                                      "could not deactivate zone timer: %s",
11808                                      isc_result_totext(result));
11809         } else {
11810                 if (isc_time_compare(&next, now) <= 0)
11811                         next = *now;
11812                 result = isc_timer_reset(zone->timer, isc_timertype_once,
11813                                          &next, NULL, ISC_TRUE);
11814                 if (result != ISC_R_SUCCESS)
11815                         dns_zone_log(zone, ISC_LOG_ERROR,
11816                                      "could not reset zone timer: %s",
11817                                      isc_result_totext(result));
11818         }
11819 }
11820
11821 static void
11822 cancel_refresh(dns_zone_t *zone) {
11823         const char me[] = "cancel_refresh";
11824         isc_time_t now;
11825
11826         /*
11827          * 'zone' locked by caller.
11828          */
11829
11830         REQUIRE(DNS_ZONE_VALID(zone));
11831         REQUIRE(LOCKED_ZONE(zone));
11832
11833         ENTER;
11834
11835         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11836         TIME_NOW(&now);
11837         zone_settimer(zone, &now);
11838 }
11839
11840 static isc_result_t
11841 notify_createmessage(dns_zone_t *zone, unsigned int flags,
11842                      dns_message_t **messagep)
11843 {
11844         dns_db_t *zonedb = NULL;
11845         dns_dbnode_t *node = NULL;
11846         dns_dbversion_t *version = NULL;
11847         dns_message_t *message = NULL;
11848         dns_rdataset_t rdataset;
11849         dns_rdata_t rdata = DNS_RDATA_INIT;
11850
11851         dns_name_t *tempname = NULL;
11852         dns_rdata_t *temprdata = NULL;
11853         dns_rdatalist_t *temprdatalist = NULL;
11854         dns_rdataset_t *temprdataset = NULL;
11855
11856         isc_result_t result;
11857         isc_region_t r;
11858         isc_buffer_t *b = NULL;
11859
11860         REQUIRE(DNS_ZONE_VALID(zone));
11861         REQUIRE(messagep != NULL && *messagep == NULL);
11862
11863         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11864                                     &message);
11865         if (result != ISC_R_SUCCESS)
11866                 return (result);
11867
11868         message->opcode = dns_opcode_notify;
11869         message->flags |= DNS_MESSAGEFLAG_AA;
11870         message->rdclass = zone->rdclass;
11871
11872         result = dns_message_gettempname(message, &tempname);
11873         if (result != ISC_R_SUCCESS)
11874                 goto cleanup;
11875
11876         result = dns_message_gettemprdataset(message, &temprdataset);
11877         if (result != ISC_R_SUCCESS)
11878                 goto cleanup;
11879
11880         /*
11881          * Make question.
11882          */
11883         dns_name_init(tempname, NULL);
11884         dns_name_clone(&zone->origin, tempname);
11885         dns_rdataset_init(temprdataset);
11886         dns_rdataset_makequestion(temprdataset, zone->rdclass,
11887                                   dns_rdatatype_soa);
11888         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11889         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
11890         tempname = NULL;
11891         temprdataset = NULL;
11892
11893         if ((flags & DNS_NOTIFY_NOSOA) != 0)
11894                 goto done;
11895
11896         result = dns_message_gettempname(message, &tempname);
11897         if (result != ISC_R_SUCCESS)
11898                 goto soa_cleanup;
11899         result = dns_message_gettemprdata(message, &temprdata);
11900         if (result != ISC_R_SUCCESS)
11901                 goto soa_cleanup;
11902         result = dns_message_gettemprdataset(message, &temprdataset);
11903         if (result != ISC_R_SUCCESS)
11904                 goto soa_cleanup;
11905         result = dns_message_gettemprdatalist(message, &temprdatalist);
11906         if (result != ISC_R_SUCCESS)
11907                 goto soa_cleanup;
11908
11909         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11910         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
11911         dns_db_attach(zone->db, &zonedb);
11912         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11913
11914         dns_name_init(tempname, NULL);
11915         dns_name_clone(&zone->origin, tempname);
11916         dns_db_currentversion(zonedb, &version);
11917         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
11918         if (result != ISC_R_SUCCESS)
11919                 goto soa_cleanup;
11920
11921         dns_rdataset_init(&rdataset);
11922         result = dns_db_findrdataset(zonedb, node, version,
11923                                      dns_rdatatype_soa,
11924                                      dns_rdatatype_none, 0, &rdataset,
11925                                      NULL);
11926         if (result != ISC_R_SUCCESS)
11927                 goto soa_cleanup;
11928         result = dns_rdataset_first(&rdataset);
11929         if (result != ISC_R_SUCCESS)
11930                 goto soa_cleanup;
11931         dns_rdataset_current(&rdataset, &rdata);
11932         dns_rdata_toregion(&rdata, &r);
11933         result = isc_buffer_allocate(zone->mctx, &b, r.length);
11934         if (result != ISC_R_SUCCESS)
11935                 goto soa_cleanup;
11936         isc_buffer_putmem(b, r.base, r.length);
11937         isc_buffer_usedregion(b, &r);
11938         dns_rdata_init(temprdata);
11939         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
11940         dns_message_takebuffer(message, &b);
11941         result = dns_rdataset_next(&rdataset);
11942         dns_rdataset_disassociate(&rdataset);
11943         if (result != ISC_R_NOMORE)
11944                 goto soa_cleanup;
11945         temprdatalist->rdclass = rdata.rdclass;
11946         temprdatalist->type = rdata.type;
11947         temprdatalist->ttl = rdataset.ttl;
11948         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
11949
11950         dns_rdataset_init(temprdataset);
11951         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
11952         if (result != ISC_R_SUCCESS)
11953                 goto soa_cleanup;
11954
11955         ISC_LIST_APPEND(tempname->list, temprdataset, link);
11956         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
11957         temprdatalist = NULL;
11958         temprdataset = NULL;
11959         temprdata = NULL;
11960         tempname = NULL;
11961
11962  soa_cleanup:
11963         if (node != NULL)
11964                 dns_db_detachnode(zonedb, &node);
11965         if (version != NULL)
11966                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
11967         if (zonedb != NULL)
11968                 dns_db_detach(&zonedb);
11969         if (tempname != NULL)
11970                 dns_message_puttempname(message, &tempname);
11971         if (temprdata != NULL)
11972                 dns_message_puttemprdata(message, &temprdata);
11973         if (temprdataset != NULL)
11974                 dns_message_puttemprdataset(message, &temprdataset);
11975         if (temprdatalist != NULL)
11976                 dns_message_puttemprdatalist(message, &temprdatalist);
11977
11978  done:
11979         *messagep = message;
11980         return (ISC_R_SUCCESS);
11981
11982  cleanup:
11983         if (tempname != NULL)
11984                 dns_message_puttempname(message, &tempname);
11985         if (temprdataset != NULL)
11986                 dns_message_puttemprdataset(message, &temprdataset);
11987         dns_message_destroy(&message);
11988         return (result);
11989 }
11990
11991 isc_result_t
11992 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
11993                        dns_message_t *msg)
11994 {
11995         unsigned int i;
11996         dns_rdata_soa_t soa;
11997         dns_rdataset_t *rdataset = NULL;
11998         dns_rdata_t rdata = DNS_RDATA_INIT;
11999         isc_result_t result;
12000         char fromtext[ISC_SOCKADDR_FORMATSIZE];
12001         int match = 0;
12002         isc_netaddr_t netaddr;
12003         isc_sockaddr_t local, remote;
12004         dns_tsigkey_t *tsigkey;
12005         dns_name_t *tsig;
12006
12007         REQUIRE(DNS_ZONE_VALID(zone));
12008
12009         /*
12010          * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
12011          * ROLLOVER.
12012          *
12013          * SOA: RFC1996
12014          * Check that 'from' is a valid notify source, (zone->masters).
12015          *      Return DNS_R_REFUSED if not.
12016          *
12017          * If the notify message contains a serial number check it
12018          * against the zones serial and return if <= current serial
12019          *
12020          * If a refresh check is progress, if so just record the
12021          * fact we received a NOTIFY and from where and return.
12022          * We will perform a new refresh check when the current one
12023          * completes. Return ISC_R_SUCCESS.
12024          *
12025          * Otherwise initiate a refresh check using 'from' as the
12026          * first address to check.  Return ISC_R_SUCCESS.
12027          */
12028
12029         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
12030
12031         /*
12032          * Notify messages are processed by the raw zone.
12033          */
12034         LOCK_ZONE(zone);
12035         if (inline_secure(zone)) {
12036                 result = dns_zone_notifyreceive(zone->raw, from, msg);
12037                 UNLOCK_ZONE(zone);
12038                 return (result);
12039         }
12040         /*
12041          *  We only handle NOTIFY (SOA) at the present.
12042          */
12043         if (isc_sockaddr_pf(from) == PF_INET)
12044                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
12045         else
12046                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
12047         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
12048             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
12049                                  dns_rdatatype_soa, dns_rdatatype_none,
12050                                  NULL, NULL) != ISC_R_SUCCESS) {
12051                 UNLOCK_ZONE(zone);
12052                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
12053                         dns_zone_log(zone, ISC_LOG_NOTICE,
12054                                      "NOTIFY with no "
12055                                      "question section from: %s", fromtext);
12056                         return (DNS_R_FORMERR);
12057                 }
12058                 dns_zone_log(zone, ISC_LOG_NOTICE,
12059                              "NOTIFY zone does not match");
12060                 return (DNS_R_NOTIMP);
12061         }
12062
12063         /*
12064          * If we are a master zone just succeed.
12065          */
12066         if (zone->type == dns_zone_master) {
12067                 UNLOCK_ZONE(zone);
12068                 return (ISC_R_SUCCESS);
12069         }
12070
12071         isc_netaddr_fromsockaddr(&netaddr, from);
12072         for (i = 0; i < zone->masterscnt; i++) {
12073                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
12074                         break;
12075                 if (zone->view->aclenv.match_mapped &&
12076                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
12077                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
12078                         isc_netaddr_t na1, na2;
12079                         isc_netaddr_fromv4mapped(&na1, &netaddr);
12080                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
12081                         if (isc_netaddr_equal(&na1, &na2))
12082                                 break;
12083                 }
12084         }
12085
12086         /*
12087          * Accept notify requests from non masters if they are on
12088          * 'zone->notify_acl'.
12089          */
12090         tsigkey = dns_message_gettsigkey(msg);
12091         tsig = dns_tsigkey_identity(tsigkey);
12092         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
12093             dns_acl_match(&netaddr, tsig, zone->notify_acl,
12094                           &zone->view->aclenv,
12095                           &match, NULL) == ISC_R_SUCCESS &&
12096             match > 0)
12097         {
12098                 /* Accept notify. */
12099         } else if (i >= zone->masterscnt) {
12100                 UNLOCK_ZONE(zone);
12101                 dns_zone_log(zone, ISC_LOG_INFO,
12102                              "refused notify from non-master: %s", fromtext);
12103                 inc_stats(zone, dns_zonestatscounter_notifyrej);
12104                 return (DNS_R_REFUSED);
12105         }
12106
12107         /*
12108          * If the zone is loaded and there are answers check the serial
12109          * to see if we need to do a refresh.  Do not worry about this
12110          * check if we are a dialup zone as we use the notify request
12111          * to trigger a refresh check.
12112          */
12113         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
12114             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
12115             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
12116                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
12117                                               &zone->origin,
12118                                               dns_rdatatype_soa,
12119                                               dns_rdatatype_none, NULL,
12120                                               &rdataset);
12121                 if (result == ISC_R_SUCCESS)
12122                         result = dns_rdataset_first(rdataset);
12123                 if (result == ISC_R_SUCCESS) {
12124                         isc_uint32_t serial = 0, oldserial;
12125                         unsigned int soacount;
12126
12127                         dns_rdataset_current(rdataset, &rdata);
12128                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
12129                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12130                         serial = soa.serial;
12131                         /*
12132                          * The following should safely be performed without DB
12133                          * lock and succeed in this context.
12134                          */
12135                         result = zone_get_from_db(zone, zone->db, NULL,
12136                                                   &soacount, &oldserial, NULL,
12137                                                   NULL, NULL, NULL, NULL);
12138                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12139                         RUNTIME_CHECK(soacount > 0U);
12140                         if (isc_serial_le(serial, oldserial)) {
12141                                 dns_zone_log(zone,
12142                                              ISC_LOG_INFO,
12143                                              "notify from %s: "
12144                                              "zone is up to date",
12145                                              fromtext);
12146                                 UNLOCK_ZONE(zone);
12147                                 return (ISC_R_SUCCESS);
12148                         }
12149                 }
12150         }
12151
12152         /*
12153          * If we got this far and there was a refresh in progress just
12154          * let it complete.  Record where we got the notify from so we
12155          * can perform a refresh check when the current one completes
12156          */
12157         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
12158                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12159                 zone->notifyfrom = *from;
12160                 UNLOCK_ZONE(zone);
12161                 dns_zone_log(zone, ISC_LOG_INFO,
12162                              "notify from %s: refresh in progress, "
12163                              "refresh check queued",
12164                              fromtext);
12165                 return (ISC_R_SUCCESS);
12166         }
12167         zone->notifyfrom = *from;
12168         remote = zone->masteraddr;
12169         local = zone->sourceaddr;
12170         UNLOCK_ZONE(zone);
12171         dns_zonemgr_unreachabledel(zone->zmgr, &remote, &local);
12172         dns_zone_refresh(zone);
12173         return (ISC_R_SUCCESS);
12174 }
12175
12176 void
12177 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
12178
12179         REQUIRE(DNS_ZONE_VALID(zone));
12180
12181         LOCK_ZONE(zone);
12182         if (zone->notify_acl != NULL)
12183                 dns_acl_detach(&zone->notify_acl);
12184         dns_acl_attach(acl, &zone->notify_acl);
12185         UNLOCK_ZONE(zone);
12186 }
12187
12188 void
12189 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
12190
12191         REQUIRE(DNS_ZONE_VALID(zone));
12192
12193         LOCK_ZONE(zone);
12194         if (zone->query_acl != NULL)
12195                 dns_acl_detach(&zone->query_acl);
12196         dns_acl_attach(acl, &zone->query_acl);
12197         UNLOCK_ZONE(zone);
12198 }
12199
12200 void
12201 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
12202
12203         REQUIRE(DNS_ZONE_VALID(zone));
12204
12205         LOCK_ZONE(zone);
12206         if (zone->queryon_acl != NULL)
12207                 dns_acl_detach(&zone->queryon_acl);
12208         dns_acl_attach(acl, &zone->queryon_acl);
12209         UNLOCK_ZONE(zone);
12210 }
12211
12212 void
12213 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
12214
12215         REQUIRE(DNS_ZONE_VALID(zone));
12216
12217         LOCK_ZONE(zone);
12218         if (zone->update_acl != NULL)
12219                 dns_acl_detach(&zone->update_acl);
12220         dns_acl_attach(acl, &zone->update_acl);
12221         UNLOCK_ZONE(zone);
12222 }
12223
12224 void
12225 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
12226
12227         REQUIRE(DNS_ZONE_VALID(zone));
12228
12229         LOCK_ZONE(zone);
12230         if (zone->forward_acl != NULL)
12231                 dns_acl_detach(&zone->forward_acl);
12232         dns_acl_attach(acl, &zone->forward_acl);
12233         UNLOCK_ZONE(zone);
12234 }
12235
12236 void
12237 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
12238
12239         REQUIRE(DNS_ZONE_VALID(zone));
12240
12241         LOCK_ZONE(zone);
12242         if (zone->xfr_acl != NULL)
12243                 dns_acl_detach(&zone->xfr_acl);
12244         dns_acl_attach(acl, &zone->xfr_acl);
12245         UNLOCK_ZONE(zone);
12246 }
12247
12248 dns_acl_t *
12249 dns_zone_getnotifyacl(dns_zone_t *zone) {
12250
12251         REQUIRE(DNS_ZONE_VALID(zone));
12252
12253         return (zone->notify_acl);
12254 }
12255
12256 dns_acl_t *
12257 dns_zone_getqueryacl(dns_zone_t *zone) {
12258
12259         REQUIRE(DNS_ZONE_VALID(zone));
12260
12261         return (zone->query_acl);
12262 }
12263
12264 dns_acl_t *
12265 dns_zone_getqueryonacl(dns_zone_t *zone) {
12266
12267         REQUIRE(DNS_ZONE_VALID(zone));
12268
12269         return (zone->queryon_acl);
12270 }
12271
12272 dns_acl_t *
12273 dns_zone_getupdateacl(dns_zone_t *zone) {
12274
12275         REQUIRE(DNS_ZONE_VALID(zone));
12276
12277         return (zone->update_acl);
12278 }
12279
12280 dns_acl_t *
12281 dns_zone_getforwardacl(dns_zone_t *zone) {
12282
12283         REQUIRE(DNS_ZONE_VALID(zone));
12284
12285         return (zone->forward_acl);
12286 }
12287
12288 dns_acl_t *
12289 dns_zone_getxfracl(dns_zone_t *zone) {
12290
12291         REQUIRE(DNS_ZONE_VALID(zone));
12292
12293         return (zone->xfr_acl);
12294 }
12295
12296 void
12297 dns_zone_clearupdateacl(dns_zone_t *zone) {
12298
12299         REQUIRE(DNS_ZONE_VALID(zone));
12300
12301         LOCK_ZONE(zone);
12302         if (zone->update_acl != NULL)
12303                 dns_acl_detach(&zone->update_acl);
12304         UNLOCK_ZONE(zone);
12305 }
12306
12307 void
12308 dns_zone_clearforwardacl(dns_zone_t *zone) {
12309
12310         REQUIRE(DNS_ZONE_VALID(zone));
12311
12312         LOCK_ZONE(zone);
12313         if (zone->forward_acl != NULL)
12314                 dns_acl_detach(&zone->forward_acl);
12315         UNLOCK_ZONE(zone);
12316 }
12317
12318 void
12319 dns_zone_clearnotifyacl(dns_zone_t *zone) {
12320
12321         REQUIRE(DNS_ZONE_VALID(zone));
12322
12323         LOCK_ZONE(zone);
12324         if (zone->notify_acl != NULL)
12325                 dns_acl_detach(&zone->notify_acl);
12326         UNLOCK_ZONE(zone);
12327 }
12328
12329 void
12330 dns_zone_clearqueryacl(dns_zone_t *zone) {
12331
12332         REQUIRE(DNS_ZONE_VALID(zone));
12333
12334         LOCK_ZONE(zone);
12335         if (zone->query_acl != NULL)
12336                 dns_acl_detach(&zone->query_acl);
12337         UNLOCK_ZONE(zone);
12338 }
12339
12340 void
12341 dns_zone_clearqueryonacl(dns_zone_t *zone) {
12342
12343         REQUIRE(DNS_ZONE_VALID(zone));
12344
12345         LOCK_ZONE(zone);
12346         if (zone->queryon_acl != NULL)
12347                 dns_acl_detach(&zone->queryon_acl);
12348         UNLOCK_ZONE(zone);
12349 }
12350
12351 void
12352 dns_zone_clearxfracl(dns_zone_t *zone) {
12353
12354         REQUIRE(DNS_ZONE_VALID(zone));
12355
12356         LOCK_ZONE(zone);
12357         if (zone->xfr_acl != NULL)
12358                 dns_acl_detach(&zone->xfr_acl);
12359         UNLOCK_ZONE(zone);
12360 }
12361
12362 isc_boolean_t
12363 dns_zone_getupdatedisabled(dns_zone_t *zone) {
12364         REQUIRE(DNS_ZONE_VALID(zone));
12365         return (zone->update_disabled);
12366
12367 }
12368
12369 void
12370 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
12371         REQUIRE(DNS_ZONE_VALID(zone));
12372         zone->update_disabled = state;
12373 }
12374
12375 isc_boolean_t
12376 dns_zone_getzeronosoattl(dns_zone_t *zone) {
12377         REQUIRE(DNS_ZONE_VALID(zone));
12378         return (zone->zero_no_soa_ttl);
12379
12380 }
12381
12382 void
12383 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
12384         REQUIRE(DNS_ZONE_VALID(zone));
12385         zone->zero_no_soa_ttl = state;
12386 }
12387
12388 void
12389 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
12390
12391         REQUIRE(DNS_ZONE_VALID(zone));
12392
12393         zone->check_names = severity;
12394 }
12395
12396 dns_severity_t
12397 dns_zone_getchecknames(dns_zone_t *zone) {
12398
12399         REQUIRE(DNS_ZONE_VALID(zone));
12400
12401         return (zone->check_names);
12402 }
12403
12404 void
12405 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
12406
12407         REQUIRE(DNS_ZONE_VALID(zone));
12408
12409         zone->journalsize = size;
12410 }
12411
12412 isc_int32_t
12413 dns_zone_getjournalsize(dns_zone_t *zone) {
12414
12415         REQUIRE(DNS_ZONE_VALID(zone));
12416
12417         return (zone->journalsize);
12418 }
12419
12420 static void
12421 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
12422         isc_result_t result = ISC_R_FAILURE;
12423         isc_buffer_t buffer;
12424
12425         REQUIRE(buf != NULL);
12426         REQUIRE(length > 1U);
12427
12428         /*
12429          * Leave space for terminating '\0'.
12430          */
12431         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12432         if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
12433                 if (dns_name_dynamic(&zone->origin))
12434                         result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12435                 if (result != ISC_R_SUCCESS &&
12436                     isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12437                         isc_buffer_putstr(&buffer, "<UNKNOWN>");
12438
12439                 if (isc_buffer_availablelength(&buffer) > 0)
12440                         isc_buffer_putstr(&buffer, "/");
12441                 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
12442         }
12443
12444         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
12445             strcmp(zone->view->name, "_default") != 0 &&
12446             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
12447                 isc_buffer_putstr(&buffer, "/");
12448                 isc_buffer_putstr(&buffer, zone->view->name);
12449         }
12450         if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
12451                 isc_buffer_putstr(&buffer, " (signed)");
12452         if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
12453                 isc_buffer_putstr(&buffer, " (unsigned)");
12454
12455         buf[isc_buffer_usedlength(&buffer)] = '\0';
12456 }
12457
12458 static void
12459 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
12460         isc_result_t result = ISC_R_FAILURE;
12461         isc_buffer_t buffer;
12462
12463         REQUIRE(buf != NULL);
12464         REQUIRE(length > 1U);
12465
12466         /*
12467          * Leave space for terminating '\0'.
12468          */
12469         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12470         if (dns_name_dynamic(&zone->origin))
12471                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12472         if (result != ISC_R_SUCCESS &&
12473             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12474                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
12475
12476         buf[isc_buffer_usedlength(&buffer)] = '\0';
12477 }
12478
12479 static void
12480 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
12481         isc_buffer_t buffer;
12482
12483         REQUIRE(buf != NULL);
12484         REQUIRE(length > 1U);
12485
12486         /*
12487          * Leave space for terminating '\0'.
12488          */
12489         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12490         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
12491
12492         buf[isc_buffer_usedlength(&buffer)] = '\0';
12493 }
12494
12495 static void
12496 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
12497         isc_buffer_t buffer;
12498
12499         REQUIRE(buf != NULL);
12500         REQUIRE(length > 1U);
12501
12502
12503         /*
12504          * Leave space for terminating '\0'.
12505          */
12506         isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12507
12508         if (zone->view == NULL) {
12509                 isc_buffer_putstr(&buffer, "_none");
12510         } else if (strlen(zone->view->name)
12511                    < isc_buffer_availablelength(&buffer)) {
12512                 isc_buffer_putstr(&buffer, zone->view->name);
12513         } else {
12514                 isc_buffer_putstr(&buffer, "_toolong");
12515         }
12516
12517         buf[isc_buffer_usedlength(&buffer)] = '\0';
12518 }
12519
12520 void
12521 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
12522         REQUIRE(DNS_ZONE_VALID(zone));
12523         REQUIRE(buf != NULL);
12524         zone_namerd_tostr(zone, buf, length);
12525 }
12526
12527 void
12528 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
12529         REQUIRE(DNS_ZONE_VALID(zone));
12530         REQUIRE(buf != NULL);
12531         zone_name_tostr(zone, buf, length);
12532 }
12533
12534 static void
12535 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12536         va_list ap;
12537         char message[4096];
12538
12539         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12540                 return;
12541
12542         va_start(ap, fmt);
12543         vsnprintf(message, sizeof(message), fmt, ap);
12544         va_end(ap);
12545         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
12546                       level, "zone %s: %s", zone->strnamerd, message);
12547 }
12548
12549 void
12550 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
12551               int level, const char *fmt, ...) {
12552         va_list ap;
12553         char message[4096];
12554
12555         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12556                 return;
12557
12558         va_start(ap, fmt);
12559         vsnprintf(message, sizeof(message), fmt, ap);
12560         va_end(ap);
12561         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
12562                       level, "%s%s: %s", (zone->type == dns_zone_key) ?
12563                       "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12564                       "redirect-zone" : "zone ", zone->strnamerd, message);
12565 }
12566
12567 void
12568 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12569         va_list ap;
12570         char message[4096];
12571
12572         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12573                 return;
12574
12575         va_start(ap, fmt);
12576         vsnprintf(message, sizeof(message), fmt, ap);
12577         va_end(ap);
12578         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12579                       level, "%s%s: %s", (zone->type == dns_zone_key) ?
12580                       "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
12581                       "redirect-zone" : "zone ", zone->strnamerd, message);
12582 }
12583
12584 static void
12585 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
12586               const char *fmt, ...)
12587 {
12588         va_list ap;
12589         char message[4096];
12590         int level = ISC_LOG_DEBUG(debuglevel);
12591         const char *zstr;
12592
12593         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12594                 return;
12595
12596         va_start(ap, fmt);
12597         vsnprintf(message, sizeof(message), fmt, ap);
12598         va_end(ap);
12599
12600         switch (zone->type) {
12601         case dns_zone_key:
12602                 zstr = "managed-keys-zone";
12603                 break;
12604         case dns_zone_redirect:
12605                 zstr = "redirect-zone";
12606                 break;
12607         default:
12608                 zstr = "zone";
12609         }
12610
12611         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
12612                       level, "%s: %s %s: %s", me, zstr, zone->strnamerd,
12613                       message);
12614 }
12615
12616 static int
12617 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
12618 {
12619         isc_result_t result;
12620         dns_name_t *name;
12621         dns_rdataset_t *curr;
12622         int count = 0;
12623
12624         result = dns_message_firstname(msg, section);
12625         while (result == ISC_R_SUCCESS) {
12626                 name = NULL;
12627                 dns_message_currentname(msg, section, &name);
12628
12629                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
12630                      curr = ISC_LIST_PREV(curr, link)) {
12631                         if (curr->type == type)
12632                                 count++;
12633                 }
12634                 result = dns_message_nextname(msg, section);
12635         }
12636
12637         return (count);
12638 }
12639
12640 void
12641 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
12642         REQUIRE(DNS_ZONE_VALID(zone));
12643
12644         zone->maxxfrin = maxxfrin;
12645 }
12646
12647 isc_uint32_t
12648 dns_zone_getmaxxfrin(dns_zone_t *zone) {
12649         REQUIRE(DNS_ZONE_VALID(zone));
12650
12651         return (zone->maxxfrin);
12652 }
12653
12654 void
12655 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
12656         REQUIRE(DNS_ZONE_VALID(zone));
12657         zone->maxxfrout = maxxfrout;
12658 }
12659
12660 isc_uint32_t
12661 dns_zone_getmaxxfrout(dns_zone_t *zone) {
12662         REQUIRE(DNS_ZONE_VALID(zone));
12663
12664         return (zone->maxxfrout);
12665 }
12666
12667 dns_zonetype_t
12668 dns_zone_gettype(dns_zone_t *zone) {
12669         REQUIRE(DNS_ZONE_VALID(zone));
12670
12671         return (zone->type);
12672 }
12673
12674 dns_name_t *
12675 dns_zone_getorigin(dns_zone_t *zone) {
12676         REQUIRE(DNS_ZONE_VALID(zone));
12677
12678         return (&zone->origin);
12679 }
12680
12681 void
12682 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
12683         REQUIRE(DNS_ZONE_VALID(zone));
12684
12685         LOCK_ZONE(zone);
12686         if (zone->task != NULL)
12687                 isc_task_detach(&zone->task);
12688         isc_task_attach(task, &zone->task);
12689         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12690         if (zone->db != NULL)
12691                 dns_db_settask(zone->db, zone->task);
12692         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12693         UNLOCK_ZONE(zone);
12694 }
12695
12696 void
12697 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
12698         REQUIRE(DNS_ZONE_VALID(zone));
12699         isc_task_attach(zone->task, target);
12700 }
12701
12702 void
12703 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
12704         REQUIRE(DNS_ZONE_VALID(zone));
12705
12706         if (idlein == 0)
12707                 idlein = DNS_DEFAULT_IDLEIN;
12708         zone->idlein = idlein;
12709 }
12710
12711 isc_uint32_t
12712 dns_zone_getidlein(dns_zone_t *zone) {
12713         REQUIRE(DNS_ZONE_VALID(zone));
12714
12715         return (zone->idlein);
12716 }
12717
12718 void
12719 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
12720         REQUIRE(DNS_ZONE_VALID(zone));
12721
12722         zone->idleout = idleout;
12723 }
12724
12725 isc_uint32_t
12726 dns_zone_getidleout(dns_zone_t *zone) {
12727         REQUIRE(DNS_ZONE_VALID(zone));
12728
12729         return (zone->idleout);
12730 }
12731
12732 static void
12733 notify_done(isc_task_t *task, isc_event_t *event) {
12734         dns_requestevent_t *revent = (dns_requestevent_t *)event;
12735         dns_notify_t *notify;
12736         isc_result_t result;
12737         dns_message_t *message = NULL;
12738         isc_buffer_t buf;
12739         char rcode[128];
12740         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12741
12742         UNUSED(task);
12743
12744         notify = event->ev_arg;
12745         REQUIRE(DNS_NOTIFY_VALID(notify));
12746         INSIST(task == notify->zone->task);
12747
12748         isc_buffer_init(&buf, rcode, sizeof(rcode));
12749         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12750
12751         result = revent->result;
12752         if (result == ISC_R_SUCCESS)
12753                 result = dns_message_create(notify->zone->mctx,
12754                                             DNS_MESSAGE_INTENTPARSE, &message);
12755         if (result == ISC_R_SUCCESS)
12756                 result = dns_request_getresponse(revent->request, message,
12757                                         DNS_MESSAGEPARSE_PRESERVEORDER);
12758         if (result == ISC_R_SUCCESS)
12759                 result = dns_rcode_totext(message->rcode, &buf);
12760         if (result == ISC_R_SUCCESS)
12761                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12762                            "notify response from %s: %.*s",
12763                            addrbuf, (int)buf.used, rcode);
12764         else
12765                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
12766                            "notify to %s failed: %s", addrbuf,
12767                            dns_result_totext(result));
12768
12769         /*
12770          * Old bind's return formerr if they see a soa record.  Retry w/o
12771          * the soa if we see a formerr and had sent a SOA.
12772          */
12773         isc_event_free(&event);
12774         if (message != NULL && message->rcode == dns_rcode_formerr &&
12775             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
12776                 isc_boolean_t startup;
12777
12778                 notify->flags |= DNS_NOTIFY_NOSOA;
12779                 dns_request_destroy(&notify->request);
12780                 startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
12781                 result = notify_send_queue(notify, startup);
12782                 if (result != ISC_R_SUCCESS)
12783                         notify_destroy(notify, ISC_FALSE);
12784         } else {
12785                 if (result == ISC_R_TIMEDOUT)
12786                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
12787                                    "notify to %s: retries exceeded", addrbuf);
12788                 notify_destroy(notify, ISC_FALSE);
12789         }
12790         if (message != NULL)
12791                 dns_message_destroy(&message);
12792 }
12793
12794 struct secure_event {
12795         isc_event_t e;
12796         dns_db_t *db;
12797         isc_uint32_t serial;
12798 };
12799
12800 static void
12801 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
12802         UNUSED(arg);
12803         dns_zone_log(zone, level, "%s", message);
12804 }
12805
12806 static isc_result_t
12807 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
12808                     isc_uint32_t start, isc_uint32_t end,
12809                     dns_difftuple_t **soatuplep, dns_diff_t *diff)
12810 {
12811         isc_result_t result;
12812         dns_difftuple_t *tuple = NULL;
12813         dns_diffop_t op = DNS_DIFFOP_ADD;
12814         int n_soa = 0;
12815
12816         REQUIRE(soatuplep != NULL);
12817
12818         if (start == end)
12819                 return (DNS_R_UNCHANGED);
12820
12821         CHECK(dns_journal_iter_init(journal, start, end));
12822         for (result = dns_journal_first_rr(journal);
12823              result == ISC_R_SUCCESS;
12824              result = dns_journal_next_rr(journal))
12825         {
12826                 dns_name_t *name = NULL;
12827                 isc_uint32_t ttl;
12828                 dns_rdata_t *rdata = NULL;
12829                 dns_journal_current_rr(journal, &name, &ttl, &rdata);
12830
12831                 if (rdata->type == dns_rdatatype_soa) {
12832                         n_soa++;
12833                         if (n_soa == 2) {
12834                                 /*
12835                                  * Save the latest raw SOA record.
12836                                  */
12837                                 if (*soatuplep != NULL)
12838                                         dns_difftuple_free(soatuplep);
12839                                 CHECK(dns_difftuple_create(diff->mctx,
12840                                                            DNS_DIFFOP_ADD,
12841                                                            name, ttl, rdata,
12842                                                            soatuplep));
12843                         }
12844                         if (n_soa == 3)
12845                                 n_soa = 1;
12846                         continue;
12847                 }
12848
12849                 /* Sanity. */
12850                 if (n_soa == 0) {
12851                         dns_zone_log(raw, ISC_LOG_ERROR,
12852                                      "corrupt journal file: '%s'\n",
12853                                      raw->journal);
12854                         return (ISC_R_FAILURE);
12855                 }
12856
12857                 if (zone->privatetype != 0 &&
12858                     rdata->type == zone->privatetype)
12859                         continue;
12860
12861                 if (rdata->type == dns_rdatatype_nsec ||
12862                     rdata->type == dns_rdatatype_rrsig ||
12863                     rdata->type == dns_rdatatype_nsec3 ||
12864                     rdata->type == dns_rdatatype_dnskey ||
12865                     rdata->type == dns_rdatatype_nsec3param)
12866                         continue;
12867
12868                 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
12869
12870                 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
12871                                            &tuple));
12872                 dns_diff_appendminimal(diff, &tuple);
12873         }
12874         if (result == ISC_R_NOMORE)
12875                 result = ISC_R_SUCCESS;
12876
12877  failure:
12878         return(result);
12879 }
12880
12881 static isc_result_t
12882 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
12883                dns_dbversion_t *secver, dns_difftuple_t **soatuple,
12884                dns_diff_t *diff)
12885 {
12886         isc_result_t result;
12887         dns_db_t *rawdb = NULL;
12888         dns_dbversion_t *rawver = NULL;
12889         dns_difftuple_t *tuple = NULL, *next;
12890         dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
12891         dns_rdata_soa_t oldsoa, newsoa;
12892
12893         REQUIRE(DNS_ZONE_VALID(seczone));
12894         REQUIRE(soatuple != NULL && *soatuple == NULL);
12895
12896         if (!seczone->sourceserialset)
12897                 return (DNS_R_UNCHANGED);
12898
12899         dns_db_attach(raw->db, &rawdb);
12900         dns_db_currentversion(rawdb, &rawver);
12901         result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
12902         dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
12903         dns_db_detach(&rawdb);
12904
12905         if (result != ISC_R_SUCCESS)
12906                 return (result);
12907
12908         for (tuple = ISC_LIST_HEAD(diff->tuples);
12909              tuple != NULL;
12910              tuple = next)
12911         {
12912                 next = ISC_LIST_NEXT(tuple, link);
12913                 if (tuple->rdata.type == dns_rdatatype_nsec ||
12914                     tuple->rdata.type == dns_rdatatype_rrsig ||
12915                     tuple->rdata.type == dns_rdatatype_dnskey ||
12916                     tuple->rdata.type == dns_rdatatype_nsec3 ||
12917                     tuple->rdata.type == dns_rdatatype_nsec3param)
12918                 {
12919                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
12920                         dns_difftuple_free(&tuple);
12921                         continue;
12922                 }
12923                 if (tuple->rdata.type == dns_rdatatype_soa) {
12924                         if (tuple->op == DNS_DIFFOP_DEL) {
12925                                 INSIST(oldtuple == NULL);
12926                                 oldtuple = tuple;
12927                         }
12928                         if (tuple->op == DNS_DIFFOP_ADD) {
12929                                 INSIST(newtuple == NULL);
12930                                 newtuple = tuple;
12931                         }
12932                 }
12933         }
12934
12935         if (oldtuple != NULL && newtuple != NULL) {
12936
12937                 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
12938                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12939
12940                 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
12941                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12942
12943                 /*
12944                  * If the SOA records are the same except for the serial
12945                  * remove them from the diff.
12946                  */
12947                 if (oldsoa.refresh == newsoa.refresh &&
12948                     oldsoa.retry == newsoa.retry &&
12949                     oldsoa.minimum == newsoa.minimum &&
12950                     oldsoa.expire == newsoa.expire &&
12951                     dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
12952                     dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
12953                         ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12954                         dns_difftuple_free(&oldtuple);
12955                         ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12956                         dns_difftuple_free(&newtuple);
12957                 }
12958         }
12959
12960         if (ISC_LIST_EMPTY(diff->tuples))
12961                 return (DNS_R_UNCHANGED);
12962
12963         /*
12964          * If there are still SOA records in the diff they can now be removed
12965          * saving the new SOA record.
12966          */
12967         if (oldtuple != NULL) {
12968                 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
12969                 dns_difftuple_free(&oldtuple);
12970         }
12971
12972         if (newtuple != NULL) {
12973                 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
12974                 *soatuple = newtuple;
12975         }
12976
12977         return (ISC_R_SUCCESS);
12978 }
12979
12980 static void
12981 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
12982         static char me[] = "receive_secure_serial";
12983         isc_result_t result = ISC_R_SUCCESS;
12984         dns_journal_t *rjournal = NULL;
12985         dns_journal_t *sjournal = NULL;
12986         isc_uint32_t start, end;
12987         dns_zone_t *zone;
12988         dns_difftuple_t *tuple = NULL, *soatuple = NULL;
12989         dns_update_log_t log = { update_log_cb, NULL };
12990         isc_time_t timenow;
12991
12992         UNUSED(task);
12993
12994         zone = event->ev_arg;
12995         end = ((struct secure_event *)event)->serial;
12996
12997         ENTER;
12998
12999         LOCK_ZONE(zone);
13000
13001         /*
13002          * If we are already processing a receive secure serial event
13003          * for the zone, just queue the new one and exit.
13004          */
13005         if (zone->rss_event != NULL && zone->rss_event != event) {
13006                 ISC_LIST_APPEND(zone->rss_events, event, ev_link);
13007                 UNLOCK_ZONE(zone);
13008                 return;
13009         }
13010
13011  nextevent:
13012         if (zone->rss_event != NULL) {
13013                 INSIST(zone->rss_event == event);
13014                 UNLOCK_ZONE(zone);
13015         } else {
13016                 zone->rss_event = event;
13017                 dns_diff_init(zone->mctx, &zone->rss_diff);
13018
13019                 /*
13020                  * zone->db may be NULL, if the load from disk failed.
13021                  */
13022                 result = ISC_R_SUCCESS;
13023                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13024                 if (zone->db != NULL)
13025                         dns_db_attach(zone->db, &zone->rss_db);
13026                 else
13027                         result = ISC_R_FAILURE;
13028                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13029
13030                 if (result == ISC_R_SUCCESS && zone->raw != NULL)
13031                         dns_zone_attach(zone->raw, &zone->rss_raw);
13032                 else
13033                         result = ISC_R_FAILURE;
13034
13035                 UNLOCK_ZONE(zone);
13036
13037                 CHECK(result);
13038
13039                 /*
13040                  * We first attempt to sync the raw zone to the secure zone
13041                  * by using the raw zone's journal, applying all the deltas
13042                  * from the latest source-serial of the secure zone up to
13043                  * the current serial number of the raw zone.
13044                  *
13045                  * If that fails, then we'll fall back to a direct comparison
13046                  * between raw and secure zones.
13047                  */
13048                 CHECK(dns_journal_open(zone->rss_raw->mctx,
13049                                        zone->rss_raw->journal,
13050                                        DNS_JOURNAL_WRITE, &rjournal));
13051
13052                 result = dns_journal_open(zone->mctx, zone->journal,
13053                                           DNS_JOURNAL_READ, &sjournal);
13054                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
13055                         goto failure;
13056
13057                 if (!dns_journal_get_sourceserial(rjournal, &start)) {
13058                         start = dns_journal_first_serial(rjournal);
13059                         dns_journal_set_sourceserial(rjournal, start);
13060                 }
13061                 if (sjournal != NULL) {
13062                         isc_uint32_t serial;
13063                         /*
13064                          * We read the secure journal first, if that
13065                          * exists use its value provided it is greater
13066                          * that from the raw journal.
13067                          */
13068                         if (dns_journal_get_sourceserial(sjournal, &serial)) {
13069                                 if (isc_serial_gt(serial, start))
13070                                         start = serial;
13071                         }
13072                         dns_journal_destroy(&sjournal);
13073                 }
13074
13075                 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
13076                 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
13077
13078                 /*
13079                  * Try to apply diffs from the raw zone's journal to the secure
13080                  * zone.  If that fails, we recover by syncing up the databases
13081                  * directly.
13082                  */
13083                 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
13084                                              start, end, &soatuple,
13085                                              &zone->rss_diff);
13086                 if (result == DNS_R_UNCHANGED)
13087                         goto failure;
13088                 else if (result != ISC_R_SUCCESS)
13089                         CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
13090                                              zone->rss_oldver, &soatuple,
13091                                              &zone->rss_diff));
13092
13093                 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
13094                                      zone->rss_newver));
13095
13096                 if (soatuple != NULL) {
13097                         isc_uint32_t oldserial, newserial, desired;
13098
13099                         CHECK(dns_db_createsoatuple(zone->rss_db,
13100                                                     zone->rss_oldver,
13101                                                     zone->rss_diff.mctx,
13102                                                     DNS_DIFFOP_DEL, &tuple));
13103                         oldserial = dns_soa_getserial(&tuple->rdata);
13104                         newserial = desired =
13105                                     dns_soa_getserial(&soatuple->rdata);
13106                         if (!isc_serial_gt(newserial, oldserial)) {
13107                                 newserial = oldserial + 1;
13108                                 if (newserial == 0)
13109                                         newserial++;
13110                                 dns_soa_setserial(newserial, &soatuple->rdata);
13111                         }
13112                         CHECK(do_one_tuple(&tuple, zone->rss_db,
13113                                            zone->rss_newver, &zone->rss_diff));
13114                         CHECK(do_one_tuple(&soatuple, zone->rss_db,
13115                                            zone->rss_newver, &zone->rss_diff));
13116                         dns_zone_log(zone, ISC_LOG_INFO,
13117                                      "serial %u (unsigned %u)",
13118                                      newserial, desired);
13119                 } else
13120                         CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
13121                                                 &zone->rss_diff, zone->mctx,
13122                                                 zone->updatemethod));
13123
13124         }
13125         result = dns_update_signaturesinc(&log, zone, zone->rss_db,
13126                                           zone->rss_oldver, zone->rss_newver,
13127                                           &zone->rss_diff,
13128                                           zone->sigvalidityinterval,
13129                                           &zone->rss_state);
13130         if (result == DNS_R_CONTINUE) {
13131                 if (rjournal != NULL)
13132                         dns_journal_destroy(&rjournal);
13133                 isc_task_send(task, &event);
13134                 fprintf(stderr, "looping on dns_update_signaturesinc\n");
13135                 return;
13136         }
13137         if (result != ISC_R_SUCCESS)
13138                 goto failure;
13139
13140         if (rjournal == NULL)
13141                 CHECK(dns_journal_open(zone->rss_raw->mctx,
13142                                        zone->rss_raw->journal,
13143                                        DNS_JOURNAL_WRITE, &rjournal));
13144         CHECK(zone_journal(zone, &zone->rss_diff, &end,
13145                            "receive_secure_serial"));
13146
13147         dns_journal_set_sourceserial(rjournal, end);
13148         dns_journal_commit(rjournal);
13149
13150         LOCK_ZONE(zone);
13151         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13152
13153         zone->sourceserial = end;
13154         zone->sourceserialset = ISC_TRUE;
13155         zone_needdump(zone, DNS_DUMP_DELAY);
13156
13157         TIME_NOW(&timenow);
13158         zone_settimer(zone, &timenow);
13159         UNLOCK_ZONE(zone);
13160
13161         dns_db_closeversion(zone->rss_db, &zone->rss_oldver, ISC_FALSE);
13162         dns_db_closeversion(zone->rss_db, &zone->rss_newver, ISC_TRUE);
13163
13164  failure:
13165         isc_event_free(&zone->rss_event);
13166         event = ISC_LIST_HEAD(zone->rss_events);
13167
13168         if (zone->rss_raw != NULL)
13169                 dns_zone_detach(&zone->rss_raw);
13170         if (result != ISC_R_SUCCESS)
13171                 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
13172                              dns_result_totext(result));
13173         if (tuple != NULL)
13174                 dns_difftuple_free(&tuple);
13175         if (soatuple != NULL)
13176                 dns_difftuple_free(&soatuple);
13177         if (zone->rss_db != NULL) {
13178                 if (zone->rss_oldver != NULL)
13179                         dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
13180                                             ISC_FALSE);
13181                 if (zone->rss_newver != NULL)
13182                         dns_db_closeversion(zone->rss_db, &zone->rss_newver,
13183                                             ISC_FALSE);
13184                 dns_db_detach(&zone->rss_db);
13185         }
13186         INSIST(zone->rss_oldver == NULL);
13187         INSIST(zone->rss_newver == NULL);
13188         if (rjournal != NULL)
13189                 dns_journal_destroy(&rjournal);
13190         dns_diff_clear(&zone->rss_diff);
13191
13192         if (event != NULL) {
13193                 LOCK_ZONE(zone);
13194                 INSIST(zone->irefs > 1);
13195                 zone->irefs--;
13196                 goto nextevent;
13197         }
13198         dns_zone_idetach(&zone);
13199 }
13200
13201 static isc_result_t
13202 zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) {
13203         isc_event_t *e;
13204         dns_zone_t *dummy = NULL;
13205
13206         e = isc_event_allocate(zone->secure->mctx, zone,
13207                                DNS_EVENT_ZONESECURESERIAL,
13208                                receive_secure_serial, zone->secure,
13209                                sizeof(struct secure_event));
13210         if (e == NULL)
13211                 return (ISC_R_NOMEMORY);
13212         ((struct secure_event *)e)->serial = serial;
13213         INSIST(LOCKED_ZONE(zone->secure));
13214         zone_iattach(zone->secure, &dummy);
13215         isc_task_send(zone->secure->task, &e);
13216
13217         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
13218         return (ISC_R_SUCCESS);
13219 }
13220
13221 static isc_result_t
13222 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
13223                dns_rdataset_t *rdataset, isc_uint32_t oldserial)
13224 {
13225         dns_rdata_soa_t soa;
13226         dns_rdata_t rdata = DNS_RDATA_INIT;
13227         dns_rdatalist_t temprdatalist;
13228         dns_rdataset_t temprdataset;
13229         isc_buffer_t b;
13230         isc_result_t result;
13231         unsigned char buf[DNS_SOA_BUFFERSIZE];
13232
13233         result = dns_rdataset_first(rdataset);
13234         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13235         dns_rdataset_current(rdataset, &rdata);
13236         result = dns_rdata_tostruct(&rdata, &soa, NULL);
13237         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13238
13239         if (isc_serial_gt(soa.serial, oldserial))
13240                 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
13241                                            NULL));
13242         /*
13243          * Always bump the serial.
13244          */
13245         oldserial++;
13246         if (oldserial == 0)
13247                 oldserial++;
13248         soa.serial = oldserial;
13249
13250         /*
13251          * Construct a replacement rdataset.
13252          */
13253         dns_rdata_reset(&rdata);
13254         isc_buffer_init(&b, buf, sizeof(buf));
13255         result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
13256                                       dns_rdatatype_soa, &soa, &b);
13257         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13258         dns_rdatalist_init(&temprdatalist);
13259         temprdatalist.rdclass = rdata.rdclass;
13260         temprdatalist.type = rdata.type;
13261         temprdatalist.ttl = rdataset->ttl;
13262         ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
13263
13264         dns_rdataset_init(&temprdataset);
13265         result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
13266         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13267         return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
13268                                    0, NULL));
13269 }
13270
13271 /*
13272  * This function should populate an nsec3paramlist_t with the
13273  * nsecparam_t data from a zone.
13274  */
13275 static isc_result_t
13276 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
13277         isc_result_t result;
13278         dns_dbnode_t *node = NULL;
13279         dns_rdataset_t rdataset, prdataset;
13280         dns_dbversion_t *version = NULL;
13281         nsec3param_t *nsec3param = NULL;
13282         nsec3param_t *nsec3p = NULL;
13283         nsec3param_t *next;
13284         dns_db_t *db = NULL;
13285         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
13286
13287         REQUIRE(DNS_ZONE_VALID(zone));
13288         REQUIRE(nsec3list != NULL);
13289         REQUIRE(ISC_LIST_EMPTY(*nsec3list));
13290
13291         dns_rdataset_init(&rdataset);
13292         dns_rdataset_init(&prdataset);
13293
13294         dns_db_attach(zone->db, &db);
13295         CHECK(dns_db_getoriginnode(db, &node));
13296
13297         dns_db_currentversion(db, &version);
13298         result = dns_db_findrdataset(db, node, version,
13299                                      dns_rdatatype_nsec3param,
13300                                      dns_rdatatype_none, 0, &rdataset, NULL);
13301
13302         if (result != ISC_R_SUCCESS)
13303                 goto getprivate;
13304
13305         /*
13306          * walk nsec3param rdataset making a list of parameters (note that
13307          * multiple simultaneous nsec3 chains are annoyingly legal -- this
13308          * is why we use an nsec3list, even tho we will usually only have
13309          * one)
13310          */
13311         for (result = dns_rdataset_first(&rdataset);
13312              result == ISC_R_SUCCESS;
13313              result = dns_rdataset_next(&rdataset))
13314         {
13315                 dns_rdata_t rdata = DNS_RDATA_INIT;
13316                 dns_rdata_t private = DNS_RDATA_INIT;
13317
13318                 dns_rdataset_current(&rdataset, &rdata);
13319                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13320                               DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13321                               "looping through nsec3param data");
13322                 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13323                 if (nsec3param == NULL)
13324                         CHECK(ISC_R_NOMEMORY);
13325                 ISC_LINK_INIT(nsec3param, link);
13326
13327                 /*
13328                  * now transfer the data from the rdata to
13329                  * the nsec3param
13330                  */
13331                 dns_nsec3param_toprivate(&rdata, &private,
13332                                          zone->privatetype, nsec3param->data,
13333                                          sizeof(nsec3param->data));
13334                 nsec3param->length = private.length;
13335                 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13336         }
13337
13338  getprivate:
13339         result = dns_db_findrdataset(db, node, version, zone->privatetype,
13340                                      dns_rdatatype_none, 0, &prdataset, NULL);
13341         if (result != ISC_R_SUCCESS)
13342                 goto done;
13343
13344         /*
13345          * walk private type records, converting them to nsec3 parameters
13346          * using dns_nsec3param_fromprivate(), do the right thing based on
13347          * CREATE and REMOVE flags
13348          */
13349         for (result = dns_rdataset_first(&prdataset);
13350              result == ISC_R_SUCCESS;
13351              result = dns_rdataset_next(&prdataset))
13352         {
13353                 dns_rdata_t rdata = DNS_RDATA_INIT;
13354                 dns_rdata_t private = DNS_RDATA_INIT;
13355
13356                 dns_rdataset_current(&prdataset, &private);
13357                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13358                               DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13359                               "looping through nsec3param private data");
13360
13361                 /*
13362                  * Do we have a valid private record?
13363                  */
13364                 if (!dns_nsec3param_fromprivate(&private, &rdata,
13365                                                 buf, sizeof(buf)))
13366                         continue;
13367
13368                 /*
13369                  * Remove any NSEC3PARAM records scheduled to be removed.
13370                  */
13371                 if (NSEC3REMOVE(rdata.data[1])) {
13372                         /*
13373                          * Zero out the flags.
13374                          */
13375                         rdata.data[1] = 0;
13376
13377                         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13378                              nsec3p != NULL;
13379                              nsec3p = next)
13380                         {
13381                                 next = ISC_LIST_NEXT(nsec3p, link);
13382
13383                                 if (nsec3p->length == rdata.length + 1 &&
13384                                     memcmp(rdata.data, nsec3p->data + 1,
13385                                            nsec3p->length - 1) == 0) {
13386                                         ISC_LIST_UNLINK(*nsec3list,
13387                                                         nsec3p, link);
13388                                         isc_mem_put(zone->mctx, nsec3p,
13389                                                     sizeof(nsec3param_t));
13390                                 }
13391                         }
13392                         continue;
13393                 }
13394
13395                 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13396                 if (nsec3param == NULL)
13397                         CHECK(ISC_R_NOMEMORY);
13398                 ISC_LINK_INIT(nsec3param, link);
13399
13400                 /*
13401                  * Copy the remaining private records so the nsec/nsec3
13402                  * chain gets created.
13403                  */
13404                 INSIST(private.length <= sizeof(nsec3param->data));
13405                 memmove(nsec3param->data, private.data, private.length);
13406                 nsec3param->length = private.length;
13407                 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13408         }
13409
13410  done:
13411         if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
13412                 result = ISC_R_SUCCESS;
13413
13414  failure:
13415         if (node != NULL)
13416                 dns_db_detachnode(db, &node);
13417         if (version != NULL)
13418                 dns_db_closeversion(db, &version, ISC_FALSE);
13419         if (db != NULL)
13420                 dns_db_detach(&db);
13421         if (dns_rdataset_isassociated(&rdataset))
13422                 dns_rdataset_disassociate(&rdataset);
13423         if (dns_rdataset_isassociated(&prdataset))
13424                 dns_rdataset_disassociate(&prdataset);
13425         return (result);
13426 }
13427
13428 /*
13429  * Walk the list of the nsec3 chains desired for the zone, converting
13430  * parameters to private type records using dns_nsec3param_toprivate(),
13431  * and insert them into the new zone db.
13432  */
13433 static isc_result_t
13434 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
13435                    nsec3paramlist_t *nsec3list)
13436 {
13437         isc_result_t result;
13438         dns_diff_t diff;
13439         dns_rdata_t rdata;
13440         nsec3param_t *nsec3p = NULL;
13441         nsec3param_t *next;
13442
13443         REQUIRE(DNS_ZONE_VALID(zone));
13444         REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
13445
13446         dns_diff_init(zone->mctx, &diff);
13447
13448         /*
13449          * Loop through the list of private-type records, set the INITIAL
13450          * and CREATE flags, and the add the record to the apex of the tree
13451          * in db.
13452          */
13453         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13454              nsec3p != NULL;
13455              nsec3p = next)
13456         {
13457                 next = ISC_LIST_NEXT(nsec3p, link);
13458                 dns_rdata_init(&rdata);
13459                 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
13460                 rdata.length = nsec3p->length;
13461                 rdata.data = nsec3p->data;
13462                 rdata.type = zone->privatetype;
13463                 rdata.rdclass = zone->rdclass;
13464                 CHECK(update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
13465                                     &zone->origin, 0, &rdata));
13466         }
13467
13468         result = ISC_R_SUCCESS;
13469
13470 failure:
13471         for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13472              nsec3p != NULL;
13473              nsec3p = next)
13474         {
13475                 next = ISC_LIST_NEXT(nsec3p, link);
13476                 ISC_LIST_UNLINK(*nsec3list, nsec3p, link);
13477                 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
13478         }
13479
13480         dns_diff_clear(&diff);
13481         return (result);
13482 }
13483
13484 static void
13485 receive_secure_db(isc_task_t *task, isc_event_t *event) {
13486         isc_result_t result;
13487         dns_zone_t *zone;
13488         dns_db_t *rawdb, *db = NULL;
13489         dns_dbnode_t *rawnode = NULL, *node = NULL;
13490         dns_fixedname_t fname;
13491         dns_name_t *name;
13492         dns_dbiterator_t *dbiterator = NULL;
13493         dns_rdatasetiter_t *rdsit = NULL;
13494         dns_rdataset_t rdataset;
13495         dns_dbversion_t *version = NULL;
13496         isc_time_t loadtime;
13497         unsigned int oldserial = 0;
13498         isc_boolean_t have_oldserial = ISC_FALSE;
13499         nsec3paramlist_t nsec3list;
13500
13501         UNUSED(task);
13502
13503         ISC_LIST_INIT(nsec3list);
13504
13505         zone = event->ev_arg;
13506         rawdb = ((struct secure_event *)event)->db;
13507         isc_event_free(&event);
13508
13509         dns_fixedname_init(&fname);
13510         name = dns_fixedname_name(&fname);
13511         dns_rdataset_init(&rdataset);
13512
13513         LOCK_ZONE(zone);
13514         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
13515                 result = ISC_R_SHUTTINGDOWN;
13516                 goto failure;
13517         }
13518
13519         TIME_NOW(&loadtime);
13520         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13521         if (zone->db != NULL) {
13522                 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
13523                 if (result == ISC_R_SUCCESS)
13524                         have_oldserial = ISC_TRUE;
13525
13526                 /*
13527                  * assemble nsec3parameters from the old zone, and set a flag
13528                  * if any are found
13529                  */
13530                 result = save_nsec3param(zone, &nsec3list);
13531                 if (result != ISC_R_SUCCESS) {
13532                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13533                         goto failure;
13534                 }
13535         }
13536         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13537
13538         result = dns_db_create(zone->mctx, zone->db_argv[0],
13539                                &zone->origin, dns_dbtype_zone, zone->rdclass,
13540                                zone->db_argc - 1, zone->db_argv + 1, &db);
13541         if (result != ISC_R_SUCCESS)
13542                 goto failure;
13543
13544         result = dns_db_newversion(db, &version);
13545         if (result != ISC_R_SUCCESS)
13546                 goto failure;
13547
13548         result = dns_db_createiterator(rawdb, 0, &dbiterator);
13549         if (result != ISC_R_SUCCESS)
13550                 goto failure;
13551
13552         for (result = dns_dbiterator_first(dbiterator);
13553              result == ISC_R_SUCCESS;
13554              result = dns_dbiterator_next(dbiterator)) {
13555                 result = dns_dbiterator_current(dbiterator, &rawnode, name);
13556                 if (result != ISC_R_SUCCESS)
13557                         continue;
13558
13559                 result = dns_db_findnode(db, name, ISC_TRUE, &node);
13560                 if (result != ISC_R_SUCCESS)
13561                         goto failure;
13562
13563                 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
13564                 if (result != ISC_R_SUCCESS)
13565                         goto failure;
13566
13567                 for (result = dns_rdatasetiter_first(rdsit);
13568                      result == ISC_R_SUCCESS;
13569                      result = dns_rdatasetiter_next(rdsit)) {
13570                         dns_rdatasetiter_current(rdsit, &rdataset);
13571                         if (rdataset.type == dns_rdatatype_nsec ||
13572                             rdataset.type == dns_rdatatype_rrsig ||
13573                             rdataset.type == dns_rdatatype_nsec3 ||
13574                             rdataset.type == dns_rdatatype_dnskey ||
13575                             rdataset.type == dns_rdatatype_nsec3param) {
13576                                 dns_rdataset_disassociate(&rdataset);
13577                                 continue;
13578                         }
13579                         if (rdataset.type == dns_rdatatype_soa &&
13580                             have_oldserial) {
13581                                 result = checkandaddsoa(db, node, version,
13582                                                         &rdataset, oldserial);
13583                         } else
13584                                 result = dns_db_addrdataset(db, node, version,
13585                                                             0, &rdataset, 0,
13586                                                             NULL);
13587                         if (result != ISC_R_SUCCESS)
13588                                 goto failure;
13589
13590                         dns_rdataset_disassociate(&rdataset);
13591                 }
13592                 dns_rdatasetiter_destroy(&rdsit);
13593                 dns_db_detachnode(rawdb, &rawnode);
13594                 dns_db_detachnode(db, &node);
13595         }
13596
13597         /*
13598          * Call restore_nsec3param() to create private-type records from
13599          * the old nsec3 parameters and insert them into db
13600          */
13601         if (!ISC_LIST_EMPTY(nsec3list))
13602                 restore_nsec3param(zone, db, version, &nsec3list);
13603
13604         dns_db_closeversion(db, &version, ISC_TRUE);
13605
13606         /*
13607          * Lock hierarchy: zmgr, zone, raw.
13608          */
13609         INSIST(zone != zone->raw);
13610         LOCK_ZONE(zone->raw);
13611         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13612         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
13613         zone_needdump(zone, 0); /* XXXMPA */
13614         UNLOCK_ZONE(zone->raw);
13615
13616  failure:
13617         UNLOCK_ZONE(zone);
13618         if (result != ISC_R_SUCCESS)
13619                 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
13620                              dns_result_totext(result));
13621
13622         while (!ISC_LIST_EMPTY(nsec3list)) {
13623                 nsec3param_t *nsec3p;
13624                 nsec3p = ISC_LIST_HEAD(nsec3list);
13625                 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
13626                 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
13627         }
13628         if (dns_rdataset_isassociated(&rdataset))
13629                 dns_rdataset_disassociate(&rdataset);
13630         if (db != NULL) {
13631                 if (node != NULL)
13632                         dns_db_detachnode(db, &node);
13633                 if (version != NULL)
13634                         dns_db_closeversion(db, &version, ISC_FALSE);
13635                 dns_db_detach(&db);
13636         }
13637         if (rawnode != NULL)
13638                 dns_db_detachnode(rawdb, &rawnode);
13639         dns_db_detach(&rawdb);
13640         if (dbiterator != NULL)
13641                 dns_dbiterator_destroy(&dbiterator);
13642         dns_zone_idetach(&zone);
13643
13644         INSIST(version == NULL);
13645 }
13646
13647 static isc_result_t
13648 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
13649         isc_event_t *e;
13650         dns_db_t *dummy = NULL;
13651         dns_zone_t *secure = NULL;
13652
13653         e = isc_event_allocate(zone->secure->mctx, zone,
13654                                DNS_EVENT_ZONESECUREDB,
13655                                receive_secure_db, zone->secure,
13656                                sizeof(struct secure_event));
13657         if (e == NULL)
13658                 return (ISC_R_NOMEMORY);
13659         dns_db_attach(db, &dummy);
13660         ((struct secure_event *)e)->db = dummy;
13661         INSIST(LOCKED_ZONE(zone->secure));
13662         zone_iattach(zone->secure, &secure);
13663         isc_task_send(zone->secure->task, &e);
13664         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
13665         return (ISC_R_SUCCESS);
13666 }
13667
13668 isc_result_t
13669 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13670         isc_result_t result;
13671         dns_zone_t *secure = NULL;
13672
13673         REQUIRE(DNS_ZONE_VALID(zone));
13674  again:
13675         LOCK_ZONE(zone);
13676         if (inline_raw(zone)) {
13677                 secure = zone->secure;
13678                 INSIST(secure != zone);
13679                 TRYLOCK_ZONE(result, secure);
13680                 if (result != ISC_R_SUCCESS) {
13681                         UNLOCK_ZONE(zone);
13682                         secure = NULL;
13683 #if ISC_PLATFORM_USETHREADS
13684                         isc_thread_yield();
13685 #endif
13686                         goto again;
13687                 }
13688         }
13689         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13690         result = zone_replacedb(zone, db, dump);
13691         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13692         if (secure != NULL)
13693                 UNLOCK_ZONE(secure);
13694         UNLOCK_ZONE(zone);
13695         return (result);
13696 }
13697
13698 static isc_result_t
13699 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
13700         dns_dbversion_t *ver;
13701         isc_result_t result;
13702         unsigned int soacount = 0;
13703         unsigned int nscount = 0;
13704
13705         /*
13706          * 'zone' and 'zonedb' locked by caller.
13707          */
13708         REQUIRE(DNS_ZONE_VALID(zone));
13709         REQUIRE(LOCKED_ZONE(zone));
13710         if (inline_raw(zone))
13711                 REQUIRE(LOCKED_ZONE(zone->secure));
13712
13713         result = zone_get_from_db(zone, db, &nscount, &soacount,
13714                                   NULL, NULL, NULL, NULL, NULL, NULL);
13715         if (result == ISC_R_SUCCESS) {
13716                 if (soacount != 1) {
13717                         dns_zone_log(zone, ISC_LOG_ERROR,
13718                                      "has %d SOA records", soacount);
13719                         result = DNS_R_BADZONE;
13720                 }
13721                 if (nscount == 0 && zone->type != dns_zone_key) {
13722                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
13723                         result = DNS_R_BADZONE;
13724                 }
13725                 if (result != ISC_R_SUCCESS)
13726                         return (result);
13727         } else {
13728                 dns_zone_log(zone, ISC_LOG_ERROR,
13729                             "retrieving SOA and NS records failed: %s",
13730                             dns_result_totext(result));
13731                 return (result);
13732         }
13733
13734         result = check_nsec3param(zone, db);
13735         if (result != ISC_R_SUCCESS)
13736                 return (result);
13737
13738         ver = NULL;
13739         dns_db_currentversion(db, &ver);
13740
13741         /*
13742          * The initial version of a slave zone is always dumped;
13743          * subsequent versions may be journaled instead if this
13744          * is enabled in the configuration.
13745          */
13746         if (zone->db != NULL && zone->journal != NULL &&
13747             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
13748             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
13749         {
13750                 isc_uint32_t serial, oldserial;
13751
13752                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
13753
13754                 result = dns_db_getsoaserial(db, ver, &serial);
13755                 if (result != ISC_R_SUCCESS) {
13756                         dns_zone_log(zone, ISC_LOG_ERROR,
13757                                      "ixfr-from-differences: unable to get "
13758                                      "new serial");
13759                         goto fail;
13760                 }
13761
13762                 /*
13763                  * This is checked in zone_postload() for master zones.
13764                  */
13765                 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
13766                                           &oldserial, NULL, NULL, NULL, NULL,
13767                                           NULL);
13768                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13769                 RUNTIME_CHECK(soacount > 0U);
13770                 if ((zone->type == dns_zone_slave ||
13771                      (zone->type == dns_zone_redirect &&
13772                       zone->masters != NULL))
13773                     && !isc_serial_gt(serial, oldserial)) {
13774                         isc_uint32_t serialmin, serialmax;
13775                         serialmin = (oldserial + 1) & 0xffffffffU;
13776                         serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
13777                         dns_zone_log(zone, ISC_LOG_ERROR,
13778                                      "ixfr-from-differences: failed: "
13779                                      "new serial (%u) out of range [%u - %u]",
13780                                      serial, serialmin, serialmax);
13781                         result = ISC_R_RANGE;
13782                         goto fail;
13783                 }
13784
13785                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
13786                                      zone->journal);
13787                 if (result != ISC_R_SUCCESS)
13788                         goto fail;
13789                 if (dump)
13790                         zone_needdump(zone, DNS_DUMP_DELAY);
13791                 else if (zone->journalsize != -1) {
13792                         result = dns_journal_compact(zone->mctx, zone->journal,
13793                                                      serial, zone->journalsize);
13794                         switch (result) {
13795                         case ISC_R_SUCCESS:
13796                         case ISC_R_NOSPACE:
13797                         case ISC_R_NOTFOUND:
13798                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
13799                                              "dns_journal_compact: %s",
13800                                              dns_result_totext(result));
13801                                 break;
13802                         default:
13803                                 dns_zone_log(zone, ISC_LOG_ERROR,
13804                                              "dns_journal_compact failed: %s",
13805                                              dns_result_totext(result));
13806                                 break;
13807                         }
13808                 }
13809                 if (zone->type == dns_zone_master && inline_raw(zone))
13810                         zone_send_secureserial(zone, serial);
13811         } else {
13812                 if (dump && zone->masterfile != NULL) {
13813                         /*
13814                          * If DNS_ZONEFLG_FORCEXFER was set we don't want
13815                          * to keep the old masterfile.
13816                          */
13817                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
13818                             remove(zone->masterfile) < 0 && errno != ENOENT) {
13819                                 char strbuf[ISC_STRERRORSIZE];
13820                                 isc__strerror(errno, strbuf, sizeof(strbuf));
13821                                 isc_log_write(dns_lctx,
13822                                               DNS_LOGCATEGORY_GENERAL,
13823                                               DNS_LOGMODULE_ZONE,
13824                                               ISC_LOG_WARNING,
13825                                               "unable to remove masterfile "
13826                                               "'%s': '%s'",
13827                                               zone->masterfile, strbuf);
13828                         }
13829                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
13830                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
13831                         else
13832                                 zone_needdump(zone, 0);
13833                 }
13834                 if (dump && zone->journal != NULL) {
13835                         /*
13836                          * The in-memory database just changed, and
13837                          * because 'dump' is set, it didn't change by
13838                          * being loaded from disk.  Also, we have not
13839                          * journaled diffs for this change.
13840                          * Therefore, the on-disk journal is missing
13841                          * the deltas for this change.  Since it can
13842                          * no longer be used to bring the zone
13843                          * up-to-date, it is useless and should be
13844                          * removed.
13845                          */
13846                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13847                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13848                                       "removing journal file");
13849                         if (remove(zone->journal) < 0 && errno != ENOENT) {
13850                                 char strbuf[ISC_STRERRORSIZE];
13851                                 isc__strerror(errno, strbuf, sizeof(strbuf));
13852                                 isc_log_write(dns_lctx,
13853                                               DNS_LOGCATEGORY_GENERAL,
13854                                               DNS_LOGMODULE_ZONE,
13855                                               ISC_LOG_WARNING,
13856                                               "unable to remove journal "
13857                                               "'%s': '%s'",
13858                                               zone->journal, strbuf);
13859                         }
13860                 }
13861
13862                 if (inline_raw(zone))
13863                         zone_send_securedb(zone, db);
13864         }
13865
13866         dns_db_closeversion(db, &ver, ISC_FALSE);
13867
13868         dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
13869
13870         if (zone->db != NULL)
13871                 zone_detachdb(zone);
13872         zone_attachdb(zone, db);
13873         dns_db_settask(zone->db, zone->task);
13874         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
13875         return (ISC_R_SUCCESS);
13876
13877  fail:
13878         dns_db_closeversion(db, &ver, ISC_FALSE);
13879         return (result);
13880 }
13881
13882 /* The caller must hold the dblock as a writer. */
13883 static inline void
13884 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
13885         REQUIRE(zone->db == NULL && db != NULL);
13886
13887         dns_db_attach(db, &zone->db);
13888         if (zone->acache != NULL) {
13889                 isc_result_t result;
13890                 result = dns_acache_setdb(zone->acache, db);
13891                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
13892                         UNEXPECTED_ERROR(__FILE__, __LINE__,
13893                                          "dns_acache_setdb() failed: %s",
13894                                          isc_result_totext(result));
13895                 }
13896         }
13897 }
13898
13899 /* The caller must hold the dblock as a writer. */
13900 static inline void
13901 zone_detachdb(dns_zone_t *zone) {
13902         REQUIRE(zone->db != NULL);
13903
13904         if (zone->acache != NULL)
13905                 (void)dns_acache_putdb(zone->acache, zone->db);
13906         dns_db_detach(&zone->db);
13907 }
13908
13909 static void
13910 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
13911         isc_time_t now;
13912         isc_boolean_t again = ISC_FALSE;
13913         unsigned int soacount;
13914         unsigned int nscount;
13915         isc_uint32_t serial, refresh, retry, expire, minimum;
13916         isc_result_t xfrresult = result;
13917         isc_boolean_t free_needed;
13918         dns_zone_t *secure = NULL;
13919
13920         REQUIRE(DNS_ZONE_VALID(zone));
13921
13922         dns_zone_log(zone, ISC_LOG_DEBUG(1),
13923                      "zone transfer finished: %s", dns_result_totext(result));
13924
13925         /*
13926          * Obtaining a lock on the zone->secure (see zone_send_secureserial)
13927          * could result in a deadlock due to a LOR so we will spin if we
13928          * can't obtain the both locks.
13929          */
13930  again:
13931         LOCK_ZONE(zone);
13932         if (inline_raw(zone)) {
13933                 secure = zone->secure;
13934                 INSIST(secure != zone);
13935                 TRYLOCK_ZONE(result, secure);
13936                 if (result != ISC_R_SUCCESS) {
13937                         UNLOCK_ZONE(zone);
13938                         secure = NULL;
13939 #if ISC_PLATFORM_USETHREADS
13940                         isc_thread_yield();
13941 #endif
13942                         goto again;
13943                 }
13944         }
13945
13946         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
13947         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13948         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
13949
13950         TIME_NOW(&now);
13951         switch (result) {
13952         case ISC_R_SUCCESS:
13953                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13954                 /*FALLTHROUGH*/
13955         case DNS_R_UPTODATE:
13956                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13957                 /*
13958                  * Has the zone expired underneath us?
13959                  */
13960                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13961                 if (zone->db == NULL) {
13962                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13963                         goto same_master;
13964                 }
13965
13966                 /*
13967                  * Update the zone structure's data from the actual
13968                  * SOA received.
13969                  */
13970                 nscount = 0;
13971                 soacount = 0;
13972                 INSIST(zone->db != NULL);
13973                 result = zone_get_from_db(zone, zone->db, &nscount,
13974                                           &soacount, &serial, &refresh,
13975                                           &retry, &expire, &minimum, NULL);
13976                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13977                 if (result == ISC_R_SUCCESS) {
13978                         if (soacount != 1)
13979                                 dns_zone_log(zone, ISC_LOG_ERROR,
13980                                              "transferred zone "
13981                                              "has %d SOA record%s", soacount,
13982                                              (soacount != 0) ? "s" : "");
13983                         if (nscount == 0) {
13984                                 dns_zone_log(zone, ISC_LOG_ERROR,
13985                                              "transferred zone "
13986                                              "has no NS records");
13987                                 if (DNS_ZONE_FLAG(zone,
13988                                                   DNS_ZONEFLG_HAVETIMERS)) {
13989                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
13990                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
13991                                 }
13992                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13993                                 zone_unload(zone);
13994                                 goto next_master;
13995                         }
13996                         zone->refresh = RANGE(refresh, zone->minrefresh,
13997                                               zone->maxrefresh);
13998                         zone->retry = RANGE(retry, zone->minretry,
13999                                             zone->maxretry);
14000                         zone->expire = RANGE(expire,
14001                                              zone->refresh + zone->retry,
14002                                              DNS_MAX_EXPIRE);
14003                         zone->minimum = minimum;
14004                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
14005                 }
14006
14007                 /*
14008                  * Set our next update/expire times.
14009                  */
14010                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
14011                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
14012                         zone->refreshtime = now;
14013                         DNS_ZONE_TIME_ADD(&now, zone->expire,
14014                                           &zone->expiretime);
14015                 } else {
14016                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
14017                                             &zone->refreshtime);
14018                         DNS_ZONE_TIME_ADD(&now, zone->expire,
14019                                           &zone->expiretime);
14020                 }
14021                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
14022                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
14023                         if (zone->tsigkey != NULL) {
14024                                 char namebuf[DNS_NAME_FORMATSIZE];
14025                                 dns_name_format(&zone->tsigkey->name, namebuf,
14026                                                 sizeof(namebuf));
14027                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
14028                                          namebuf);
14029                         } else
14030                                 buf[0] = '\0';
14031                         dns_zone_log(zone, ISC_LOG_INFO,
14032                                      "transferred serial %u%s",
14033                                      serial, buf);
14034                         if (inline_raw(zone))
14035                                 zone_send_secureserial(zone, serial);
14036                 }
14037
14038                 /*
14039                  * This is not necessary if we just performed a AXFR
14040                  * however it is necessary for an IXFR / UPTODATE and
14041                  * won't hurt with an AXFR.
14042                  */
14043                 if (zone->masterfile != NULL || zone->journal != NULL) {
14044                         unsigned int delay = DNS_DUMP_DELAY;
14045
14046                         result = ISC_R_FAILURE;
14047                         if (zone->journal != NULL)
14048                                 result = isc_file_settime(zone->journal, &now);
14049                         if (result != ISC_R_SUCCESS &&
14050                             zone->masterfile != NULL)
14051                                 result = isc_file_settime(zone->masterfile,
14052                                                           &now);
14053
14054                         if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
14055                             result == ISC_R_FILENOTFOUND)
14056                                 delay = 0;
14057
14058                         if ((result == ISC_R_SUCCESS ||
14059                             result == ISC_R_FILENOTFOUND) &&
14060                             zone->masterfile != NULL)
14061                                 zone_needdump(zone, delay);
14062                         else if (result != ISC_R_SUCCESS)
14063                                 dns_zone_log(zone, ISC_LOG_ERROR,
14064                                              "transfer: could not set file "
14065                                              "modification time of '%s': %s",
14066                                              zone->masterfile,
14067                                              dns_result_totext(result));
14068                 }
14069                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
14070                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
14071                 break;
14072
14073         case DNS_R_BADIXFR:
14074                 /* Force retry with AXFR. */
14075                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
14076                 goto same_master;
14077
14078         default:
14079         next_master:
14080                 /*
14081                  * Skip to next failed / untried master.
14082                  */
14083                 do {
14084                         zone->curmaster++;
14085                 } while (zone->curmaster < zone->masterscnt &&
14086                          zone->mastersok[zone->curmaster]);
14087                 /* FALLTHROUGH */
14088         same_master:
14089                 if (zone->curmaster >= zone->masterscnt) {
14090                         zone->curmaster = 0;
14091                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
14092                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14093                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
14094                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14095                                 while (zone->curmaster < zone->masterscnt &&
14096                                        zone->mastersok[zone->curmaster])
14097                                         zone->curmaster++;
14098                                 again = ISC_TRUE;
14099                         } else
14100                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14101                 } else {
14102                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
14103                         again = ISC_TRUE;
14104                 }
14105                 inc_stats(zone, dns_zonestatscounter_xfrfail);
14106                 break;
14107         }
14108         zone_settimer(zone, &now);
14109
14110         /*
14111          * If creating the transfer object failed, zone->xfr is NULL.
14112          * Otherwise, we are called as the done callback of a zone
14113          * transfer object that just entered its shutting-down
14114          * state.  Since we are no longer responsible for shutting
14115          * it down, we can detach our reference.
14116          */
14117         if (zone->xfr != NULL)
14118                 dns_xfrin_detach(&zone->xfr);
14119
14120         if (zone->tsigkey != NULL)
14121                 dns_tsigkey_detach(&zone->tsigkey);
14122
14123         /*
14124          * Handle any deferred journal compaction.
14125          */
14126         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
14127                 result = dns_journal_compact(zone->mctx, zone->journal,
14128                                              zone->compact_serial,
14129                                              zone->journalsize);
14130                 switch (result) {
14131                 case ISC_R_SUCCESS:
14132                 case ISC_R_NOSPACE:
14133                 case ISC_R_NOTFOUND:
14134                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
14135                                      "dns_journal_compact: %s",
14136                                      dns_result_totext(result));
14137                         break;
14138                 default:
14139                         dns_zone_log(zone, ISC_LOG_ERROR,
14140                                      "dns_journal_compact failed: %s",
14141                                      dns_result_totext(result));
14142                         break;
14143                 }
14144                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
14145         }
14146
14147         if (secure != NULL)
14148                 UNLOCK_ZONE(secure);
14149         /*
14150          * This transfer finishing freed up a transfer quota slot.
14151          * Let any other zones waiting for quota have it.
14152          */
14153         if (zone->zmgr != NULL &&
14154             zone->statelist == &zone->zmgr->xfrin_in_progress) {
14155                 UNLOCK_ZONE(zone);
14156                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14157                 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
14158                 zone->statelist = NULL;
14159                 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
14160                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14161                 LOCK_ZONE(zone);
14162         }
14163
14164         /*
14165          * Retry with a different server if necessary.
14166          */
14167         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
14168                 queue_soa_query(zone);
14169
14170         INSIST(zone->irefs > 0);
14171         zone->irefs--;
14172         free_needed = exit_check(zone);
14173         UNLOCK_ZONE(zone);
14174         if (free_needed)
14175                 zone_free(zone);
14176 }
14177
14178 static void
14179 zone_loaddone(void *arg, isc_result_t result) {
14180         static char me[] = "zone_loaddone";
14181         dns_load_t *load = arg;
14182         dns_zone_t *zone;
14183         isc_result_t tresult;
14184         dns_zone_t *secure = NULL;
14185
14186         REQUIRE(DNS_LOAD_VALID(load));
14187         zone = load->zone;
14188
14189         ENTER;
14190
14191         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
14192         if (tresult != ISC_R_SUCCESS &&
14193             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
14194                 result = tresult;
14195
14196         /*
14197          * Lock hierarchy: zmgr, zone, raw.
14198          */
14199  again:
14200         LOCK_ZONE(zone);
14201         if (inline_secure(zone))
14202                 LOCK_ZONE(zone->raw);
14203         else if (inline_raw(zone)) {
14204                 secure = zone->secure;
14205                 TRYLOCK_ZONE(result, secure);
14206                 if (result != ISC_R_SUCCESS) {
14207                         UNLOCK_ZONE(zone);
14208                         secure = NULL;
14209 #if ISC_PLATFORM_USETHREADS
14210                         isc_thread_yield();
14211 #endif
14212                         goto again;
14213                 }
14214         }
14215         (void)zone_postload(zone, load->db, load->loadtime, result);
14216         zonemgr_putio(&zone->readio);
14217         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
14218         zone_idetach(&load->callbacks.zone);
14219         /*
14220          * Leave the zone frozen if the reload fails.
14221          */
14222         if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
14223              DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
14224                 zone->update_disabled = ISC_FALSE;
14225         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
14226         if (inline_secure(zone))
14227                 UNLOCK_ZONE(zone->raw);
14228         else if (secure != NULL)
14229                 UNLOCK_ZONE(secure);
14230         UNLOCK_ZONE(zone);
14231
14232         load->magic = 0;
14233         dns_db_detach(&load->db);
14234         if (load->zone->lctx != NULL)
14235                 dns_loadctx_detach(&load->zone->lctx);
14236         dns_zone_idetach(&load->zone);
14237         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
14238 }
14239
14240 void
14241 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
14242         REQUIRE(DNS_ZONE_VALID(zone));
14243         REQUIRE(table != NULL);
14244         REQUIRE(*table == NULL);
14245
14246         LOCK_ZONE(zone);
14247         if (zone->ssutable != NULL)
14248                 dns_ssutable_attach(zone->ssutable, table);
14249         UNLOCK_ZONE(zone);
14250 }
14251
14252 void
14253 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
14254         REQUIRE(DNS_ZONE_VALID(zone));
14255
14256         LOCK_ZONE(zone);
14257         if (zone->ssutable != NULL)
14258                 dns_ssutable_detach(&zone->ssutable);
14259         if (table != NULL)
14260                 dns_ssutable_attach(table, &zone->ssutable);
14261         UNLOCK_ZONE(zone);
14262 }
14263
14264 void
14265 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
14266         REQUIRE(DNS_ZONE_VALID(zone));
14267
14268         zone->sigvalidityinterval = interval;
14269 }
14270
14271 isc_uint32_t
14272 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
14273         REQUIRE(DNS_ZONE_VALID(zone));
14274
14275         return (zone->sigvalidityinterval);
14276 }
14277
14278 void
14279 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
14280         isc_time_t now;
14281
14282         REQUIRE(DNS_ZONE_VALID(zone));
14283
14284         LOCK_ZONE(zone);
14285         zone->sigresigninginterval = interval;
14286         set_resigntime(zone);
14287         if (zone->task != NULL) {
14288                 TIME_NOW(&now);
14289                 zone_settimer(zone, &now);
14290         }
14291         UNLOCK_ZONE(zone);
14292 }
14293
14294 isc_uint32_t
14295 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
14296         REQUIRE(DNS_ZONE_VALID(zone));
14297
14298         return (zone->sigresigninginterval);
14299 }
14300
14301 static void
14302 queue_xfrin(dns_zone_t *zone) {
14303         const char me[] = "queue_xfrin";
14304         isc_result_t result;
14305         dns_zonemgr_t *zmgr = zone->zmgr;
14306
14307         ENTER;
14308
14309         INSIST(zone->statelist == NULL);
14310
14311         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14312         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
14313         LOCK_ZONE(zone);
14314         zone->irefs++;
14315         UNLOCK_ZONE(zone);
14316         zone->statelist = &zmgr->waiting_for_xfrin;
14317         result = zmgr_start_xfrin_ifquota(zmgr, zone);
14318         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14319
14320         if (result == ISC_R_QUOTA) {
14321                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14322                               "zone transfer deferred due to quota");
14323         } else if (result != ISC_R_SUCCESS) {
14324                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
14325                               "starting zone transfer: %s",
14326                               isc_result_totext(result));
14327         }
14328 }
14329
14330 /*
14331  * This event callback is called when a zone has received
14332  * any necessary zone transfer quota.  This is the time
14333  * to go ahead and start the transfer.
14334  */
14335 static void
14336 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
14337         isc_result_t result = ISC_R_SUCCESS;
14338         dns_peer_t *peer = NULL;
14339         char master[ISC_SOCKADDR_FORMATSIZE];
14340         char source[ISC_SOCKADDR_FORMATSIZE];
14341         dns_rdatatype_t xfrtype;
14342         dns_zone_t *zone = event->ev_arg;
14343         isc_netaddr_t masterip;
14344         isc_sockaddr_t sourceaddr;
14345         isc_sockaddr_t masteraddr;
14346         isc_time_t now;
14347         const char *soa_before = "";
14348         isc_boolean_t loaded;
14349
14350         UNUSED(task);
14351
14352         INSIST(task == zone->task);
14353
14354         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14355                 result = ISC_R_CANCELED;
14356                 goto cleanup;
14357         }
14358
14359         TIME_NOW(&now);
14360
14361         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
14362         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
14363                                     &zone->sourceaddr, &now))
14364         {
14365                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14366                 dns_zone_log(zone, ISC_LOG_INFO,
14367                              "got_transfer_quota: skipping zone transfer as "
14368                              "master %s (source %s) is unreachable (cached)",
14369                              master, source);
14370                 result = ISC_R_CANCELED;
14371                 goto cleanup;
14372         }
14373
14374         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14375         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
14376
14377         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14378                 soa_before = "SOA before ";
14379         /*
14380          * Decide whether we should request IXFR or AXFR.
14381          */
14382         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14383         loaded = ISC_TF(zone->db != NULL);
14384         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14385
14386         if (!loaded) {
14387                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14388                              "no database exists yet, requesting AXFR of "
14389                              "initial version from %s", master);
14390                 xfrtype = dns_rdatatype_axfr;
14391         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
14392                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14393                              "forced reload, requesting AXFR of "
14394                              "initial version from %s", master);
14395                 xfrtype = dns_rdatatype_axfr;
14396         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
14397                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14398                              "retrying with AXFR from %s due to "
14399                              "previous IXFR failure", master);
14400                 xfrtype = dns_rdatatype_axfr;
14401                 LOCK_ZONE(zone);
14402                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
14403                 UNLOCK_ZONE(zone);
14404         } else {
14405                 isc_boolean_t use_ixfr = ISC_TRUE;
14406                 if (peer != NULL)
14407                         result = dns_peer_getrequestixfr(peer, &use_ixfr);
14408                 if (peer == NULL || result != ISC_R_SUCCESS)
14409                         use_ixfr = zone->requestixfr;
14410                 if (use_ixfr == ISC_FALSE) {
14411                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
14412                                      "IXFR disabled, requesting %sAXFR from %s",
14413                                      soa_before, master);
14414                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14415                                 xfrtype = dns_rdatatype_soa;
14416                         else
14417                                 xfrtype = dns_rdatatype_axfr;
14418                 } else {
14419                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
14420                                      "requesting IXFR from %s", master);
14421                         xfrtype = dns_rdatatype_ixfr;
14422                 }
14423         }
14424
14425         /*
14426          * Determine if we should attempt to sign the request with TSIG.
14427          */
14428         result = ISC_R_NOTFOUND;
14429         /*
14430          * First, look for a tsig key in the master statement, then
14431          * try for a server key.
14432          */
14433         if ((zone->masterkeynames != NULL) &&
14434             (zone->masterkeynames[zone->curmaster] != NULL)) {
14435                 dns_view_t *view = dns_zone_getview(zone);
14436                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14437                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
14438         }
14439         if (zone->tsigkey == NULL)
14440                 result = dns_view_getpeertsig(zone->view, &masterip,
14441                                               &zone->tsigkey);
14442
14443         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14444                 dns_zone_log(zone, ISC_LOG_ERROR,
14445                              "could not get TSIG key for zone transfer: %s",
14446                              isc_result_totext(result));
14447         }
14448
14449         LOCK_ZONE(zone);
14450         masteraddr = zone->masteraddr;
14451         sourceaddr = zone->sourceaddr;
14452         UNLOCK_ZONE(zone);
14453         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
14454         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
14455                                    zone->tsigkey, zone->mctx,
14456                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
14457                                    zone->task, zone_xfrdone, &zone->xfr);
14458         if (result == ISC_R_SUCCESS) {
14459                 LOCK_ZONE(zone);
14460                 if (xfrtype == dns_rdatatype_axfr) {
14461                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14462                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
14463                         else
14464                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
14465                 } else if (xfrtype == dns_rdatatype_ixfr) {
14466                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14467                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
14468                         else
14469                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
14470                 }
14471                 UNLOCK_ZONE(zone);
14472         }
14473  cleanup:
14474         /*
14475          * Any failure in this function is handled like a failed
14476          * zone transfer.  This ensures that we get removed from
14477          * zmgr->xfrin_in_progress.
14478          */
14479         if (result != ISC_R_SUCCESS)
14480                 zone_xfrdone(zone, result);
14481
14482         isc_event_free(&event);
14483 }
14484
14485 /*
14486  * Update forwarding support.
14487  */
14488
14489 static void
14490 forward_destroy(dns_forward_t *forward) {
14491
14492         forward->magic = 0;
14493         if (forward->request != NULL)
14494                 dns_request_destroy(&forward->request);
14495         if (forward->msgbuf != NULL)
14496                 isc_buffer_free(&forward->msgbuf);
14497         if (forward->zone != NULL) {
14498                 LOCK(&forward->zone->lock);
14499                 if (ISC_LINK_LINKED(forward, link))
14500                         ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
14501                 UNLOCK(&forward->zone->lock);
14502                 dns_zone_idetach(&forward->zone);
14503         }
14504         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
14505 }
14506
14507 static isc_result_t
14508 sendtomaster(dns_forward_t *forward) {
14509         isc_result_t result;
14510         isc_sockaddr_t src;
14511
14512         LOCK_ZONE(forward->zone);
14513
14514         if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
14515                 UNLOCK_ZONE(forward->zone);
14516                 return (ISC_R_CANCELED);
14517         }
14518
14519         if (forward->which >= forward->zone->masterscnt) {
14520                 UNLOCK_ZONE(forward->zone);
14521                 return (ISC_R_NOMORE);
14522         }
14523
14524         forward->addr = forward->zone->masters[forward->which];
14525         /*
14526          * Always use TCP regardless of whether the original update
14527          * used TCP.
14528          * XXX The timeout may but a bit small if we are far down a
14529          * transfer graph and the master has to try several masters.
14530          */
14531         switch (isc_sockaddr_pf(&forward->addr)) {
14532         case PF_INET:
14533                 src = forward->zone->xfrsource4;
14534                 break;
14535         case PF_INET6:
14536                 src = forward->zone->xfrsource6;
14537                 break;
14538         default:
14539                 result = ISC_R_NOTIMPLEMENTED;
14540                 goto unlock;
14541         }
14542         result = dns_request_createraw(forward->zone->view->requestmgr,
14543                                        forward->msgbuf,
14544                                        &src, &forward->addr,
14545                                        forward->options, 15 /* XXX */,
14546                                        forward->zone->task,
14547                                        forward_callback, forward,
14548                                        &forward->request);
14549         if (result == ISC_R_SUCCESS) {
14550                 if (!ISC_LINK_LINKED(forward, link))
14551                         ISC_LIST_APPEND(forward->zone->forwards, forward, link);
14552         }
14553
14554  unlock:
14555         UNLOCK_ZONE(forward->zone);
14556         return (result);
14557 }
14558
14559 static void
14560 forward_callback(isc_task_t *task, isc_event_t *event) {
14561         const char me[] = "forward_callback";
14562         dns_requestevent_t *revent = (dns_requestevent_t *)event;
14563         dns_message_t *msg = NULL;
14564         char master[ISC_SOCKADDR_FORMATSIZE];
14565         isc_result_t result;
14566         dns_forward_t *forward;
14567         dns_zone_t *zone;
14568
14569         UNUSED(task);
14570
14571         forward = revent->ev_arg;
14572         INSIST(DNS_FORWARD_VALID(forward));
14573         zone = forward->zone;
14574         INSIST(DNS_ZONE_VALID(zone));
14575
14576         ENTER;
14577
14578         isc_sockaddr_format(&forward->addr, master, sizeof(master));
14579
14580         if (revent->result != ISC_R_SUCCESS) {
14581                 dns_zone_log(zone, ISC_LOG_INFO,
14582                              "could not forward dynamic update to %s: %s",
14583                              master, dns_result_totext(revent->result));
14584                 goto next_master;
14585         }
14586
14587         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
14588         if (result != ISC_R_SUCCESS)
14589                 goto next_master;
14590
14591         result = dns_request_getresponse(revent->request, msg,
14592                                          DNS_MESSAGEPARSE_PRESERVEORDER |
14593                                          DNS_MESSAGEPARSE_CLONEBUFFER);
14594         if (result != ISC_R_SUCCESS)
14595                 goto next_master;
14596
14597         switch (msg->rcode) {
14598         /*
14599          * Pass these rcodes back to client.
14600          */
14601         case dns_rcode_noerror:
14602         case dns_rcode_yxdomain:
14603         case dns_rcode_yxrrset:
14604         case dns_rcode_nxrrset:
14605         case dns_rcode_refused:
14606         case dns_rcode_nxdomain: {
14607                 char rcode[128];
14608                 isc_buffer_t rb;
14609
14610                 isc_buffer_init(&rb, rcode, sizeof(rcode));
14611                 (void)dns_rcode_totext(msg->rcode, &rb);
14612                 dns_zone_log(zone, ISC_LOG_INFO,
14613                              "forwarded dynamic update: "
14614                              "master %s returned: %.*s",
14615                              master, (int)rb.used, rcode);
14616                 break;
14617         }
14618
14619         /* These should not occur if the masters/zone are valid. */
14620         case dns_rcode_notzone:
14621         case dns_rcode_notauth: {
14622                 char rcode[128];
14623                 isc_buffer_t rb;
14624
14625                 isc_buffer_init(&rb, rcode, sizeof(rcode));
14626                 (void)dns_rcode_totext(msg->rcode, &rb);
14627                 dns_zone_log(zone, ISC_LOG_WARNING,
14628                              "forwarding dynamic update: "
14629                              "unexpected response: master %s returned: %.*s",
14630                              master, (int)rb.used, rcode);
14631                 goto next_master;
14632         }
14633
14634         /* Try another server for these rcodes. */
14635         case dns_rcode_formerr:
14636         case dns_rcode_servfail:
14637         case dns_rcode_notimp:
14638         case dns_rcode_badvers:
14639         default:
14640                 goto next_master;
14641         }
14642
14643         /* call callback */
14644         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
14645         msg = NULL;
14646         dns_request_destroy(&forward->request);
14647         forward_destroy(forward);
14648         isc_event_free(&event);
14649         return;
14650
14651  next_master:
14652         if (msg != NULL)
14653                 dns_message_destroy(&msg);
14654         isc_event_free(&event);
14655         forward->which++;
14656         dns_request_destroy(&forward->request);
14657         result = sendtomaster(forward);
14658         if (result != ISC_R_SUCCESS) {
14659                 /* call callback */
14660                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
14661                              "exhausted dynamic update forwarder list");
14662                 (forward->callback)(forward->callback_arg, result, NULL);
14663                 forward_destroy(forward);
14664         }
14665 }
14666
14667 isc_result_t
14668 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
14669                        dns_updatecallback_t callback, void *callback_arg)
14670 {
14671         dns_forward_t *forward;
14672         isc_result_t result;
14673         isc_region_t *mr;
14674
14675         REQUIRE(DNS_ZONE_VALID(zone));
14676         REQUIRE(msg != NULL);
14677         REQUIRE(callback != NULL);
14678
14679         forward = isc_mem_get(zone->mctx, sizeof(*forward));
14680         if (forward == NULL)
14681                 return (ISC_R_NOMEMORY);
14682
14683         forward->request = NULL;
14684         forward->zone = NULL;
14685         forward->msgbuf = NULL;
14686         forward->which = 0;
14687         forward->mctx = 0;
14688         forward->callback = callback;
14689         forward->callback_arg = callback_arg;
14690         ISC_LINK_INIT(forward, link);
14691         forward->magic = FORWARD_MAGIC;
14692         forward->options = DNS_REQUESTOPT_TCP;
14693         /*
14694          * If we have a SIG(0) signed message we need to preserve the
14695          * query id as that is included in the SIG(0) computation.
14696          */
14697         if (msg->sig0 != NULL)
14698                 forward->options |= DNS_REQUESTOPT_FIXEDID;
14699
14700         mr = dns_message_getrawmessage(msg);
14701         if (mr == NULL) {
14702                 result = ISC_R_UNEXPECTEDEND;
14703                 goto cleanup;
14704         }
14705
14706         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
14707         if (result != ISC_R_SUCCESS)
14708                 goto cleanup;
14709         result = isc_buffer_copyregion(forward->msgbuf, mr);
14710         if (result != ISC_R_SUCCESS)
14711                 goto cleanup;
14712
14713         isc_mem_attach(zone->mctx, &forward->mctx);
14714         dns_zone_iattach(zone, &forward->zone);
14715         result = sendtomaster(forward);
14716
14717  cleanup:
14718         if (result != ISC_R_SUCCESS) {
14719                 forward_destroy(forward);
14720         }
14721         return (result);
14722 }
14723
14724 isc_result_t
14725 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
14726         REQUIRE(DNS_ZONE_VALID(zone));
14727         REQUIRE(next != NULL && *next == NULL);
14728
14729         *next = ISC_LIST_NEXT(zone, link);
14730         if (*next == NULL)
14731                 return (ISC_R_NOMORE);
14732         else
14733                 return (ISC_R_SUCCESS);
14734 }
14735
14736 isc_result_t
14737 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
14738         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14739         REQUIRE(first != NULL && *first == NULL);
14740
14741         *first = ISC_LIST_HEAD(zmgr->zones);
14742         if (*first == NULL)
14743                 return (ISC_R_NOMORE);
14744         else
14745                 return (ISC_R_SUCCESS);
14746 }
14747
14748 /***
14749  ***    Zone manager.
14750  ***/
14751
14752 isc_result_t
14753 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
14754                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
14755                    dns_zonemgr_t **zmgrp)
14756 {
14757         dns_zonemgr_t *zmgr;
14758         isc_result_t result;
14759
14760         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
14761         if (zmgr == NULL)
14762                 return (ISC_R_NOMEMORY);
14763         zmgr->mctx = NULL;
14764         zmgr->refs = 1;
14765         isc_mem_attach(mctx, &zmgr->mctx);
14766         zmgr->taskmgr = taskmgr;
14767         zmgr->timermgr = timermgr;
14768         zmgr->socketmgr = socketmgr;
14769         zmgr->zonetasks = NULL;
14770         zmgr->loadtasks = NULL;
14771         zmgr->mctxpool = NULL;
14772         zmgr->task = NULL;
14773         zmgr->notifyrl = NULL;
14774         zmgr->refreshrl = NULL;
14775         zmgr->startupnotifyrl = NULL;
14776         zmgr->startuprefreshrl = NULL;
14777         ISC_LIST_INIT(zmgr->zones);
14778         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
14779         ISC_LIST_INIT(zmgr->xfrin_in_progress);
14780         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
14781         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
14782         if (result != ISC_R_SUCCESS)
14783                 goto free_mem;
14784
14785         zmgr->transfersin = 10;
14786         zmgr->transfersperns = 2;
14787
14788         /* Unreachable lock. */
14789         result = isc_rwlock_init(&zmgr->urlock, 0, 0);
14790         if (result != ISC_R_SUCCESS)
14791                 goto free_rwlock;
14792
14793         /* Create a single task for queueing of SOA queries. */
14794         result = isc_task_create(taskmgr, 1, &zmgr->task);
14795         if (result != ISC_R_SUCCESS)
14796                 goto free_urlock;
14797
14798         isc_task_setname(zmgr->task, "zmgr", zmgr);
14799         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14800                                         &zmgr->notifyrl);
14801         if (result != ISC_R_SUCCESS)
14802                 goto free_task;
14803
14804         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14805                                         &zmgr->refreshrl);
14806         if (result != ISC_R_SUCCESS)
14807                 goto free_notifyrl;
14808
14809         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14810                                         &zmgr->startupnotifyrl);
14811         if (result != ISC_R_SUCCESS)
14812                 goto free_refreshrl;
14813
14814         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
14815                                         &zmgr->startuprefreshrl);
14816         if (result != ISC_R_SUCCESS)
14817                 goto free_startupnotifyrl;
14818
14819         /* default to 20 refresh queries / notifies per second. */
14820         setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
14821         setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
14822         setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
14823         setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
14824
14825         zmgr->iolimit = 1;
14826         zmgr->ioactive = 0;
14827         ISC_LIST_INIT(zmgr->high);
14828         ISC_LIST_INIT(zmgr->low);
14829
14830         result = isc_mutex_init(&zmgr->iolock);
14831         if (result != ISC_R_SUCCESS)
14832                 goto free_startuprefreshrl;
14833
14834         zmgr->magic = ZONEMGR_MAGIC;
14835
14836         *zmgrp = zmgr;
14837         return (ISC_R_SUCCESS);
14838
14839 #if 0
14840  free_iolock:
14841         DESTROYLOCK(&zmgr->iolock);
14842 #endif
14843  free_startuprefreshrl:
14844         isc_ratelimiter_detach(&zmgr->startuprefreshrl);
14845  free_startupnotifyrl:
14846         isc_ratelimiter_detach(&zmgr->startupnotifyrl);
14847  free_refreshrl:
14848         isc_ratelimiter_detach(&zmgr->refreshrl);
14849  free_notifyrl:
14850         isc_ratelimiter_detach(&zmgr->notifyrl);
14851  free_task:
14852         isc_task_detach(&zmgr->task);
14853  free_urlock:
14854         isc_rwlock_destroy(&zmgr->urlock);
14855  free_rwlock:
14856         isc_rwlock_destroy(&zmgr->rwlock);
14857  free_mem:
14858         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
14859         isc_mem_detach(&mctx);
14860         return (result);
14861 }
14862
14863 isc_result_t
14864 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
14865         isc_result_t result;
14866         isc_mem_t *mctx = NULL;
14867         dns_zone_t *zone = NULL;
14868         void *item;
14869
14870         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14871         REQUIRE(zonep != NULL && *zonep == NULL);
14872
14873         if (zmgr->mctxpool == NULL)
14874                 return (ISC_R_FAILURE);
14875
14876         item = isc_pool_get(zmgr->mctxpool);
14877         if (item == NULL)
14878                 return (ISC_R_FAILURE);
14879
14880         isc_mem_attach((isc_mem_t *) item, &mctx);
14881         result = dns_zone_create(&zone, mctx);
14882         isc_mem_detach(&mctx);
14883
14884         if (result == ISC_R_SUCCESS)
14885                 *zonep = zone;
14886
14887         return (result);
14888 }
14889
14890 isc_result_t
14891 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14892         isc_result_t result;
14893
14894         REQUIRE(DNS_ZONE_VALID(zone));
14895         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14896
14897         if (zmgr->zonetasks == NULL)
14898                 return (ISC_R_FAILURE);
14899
14900         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14901         LOCK_ZONE(zone);
14902         REQUIRE(zone->task == NULL);
14903         REQUIRE(zone->timer == NULL);
14904         REQUIRE(zone->zmgr == NULL);
14905
14906         isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
14907         isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
14908
14909         /*
14910          * Set the task name.  The tag will arbitrarily point to one
14911          * of the zones sharing the task (in practice, the one
14912          * to be managed last).
14913          */
14914         isc_task_setname(zone->task, "zone", zone);
14915         isc_task_setname(zone->loadtask, "loadzone", zone);
14916
14917         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
14918                                   NULL, NULL,
14919                                   zone->task, zone_timer, zone,
14920                                   &zone->timer);
14921
14922         if (result != ISC_R_SUCCESS)
14923                 goto cleanup_tasks;
14924
14925         /*
14926          * The timer "holds" a iref.
14927          */
14928         zone->irefs++;
14929         INSIST(zone->irefs != 0);
14930
14931         ISC_LIST_APPEND(zmgr->zones, zone, link);
14932         zone->zmgr = zmgr;
14933         zmgr->refs++;
14934
14935         goto unlock;
14936
14937  cleanup_tasks:
14938         isc_task_detach(&zone->loadtask);
14939         isc_task_detach(&zone->task);
14940
14941  unlock:
14942         UNLOCK_ZONE(zone);
14943         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14944         return (result);
14945 }
14946
14947 void
14948 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
14949         isc_boolean_t free_now = ISC_FALSE;
14950
14951         REQUIRE(DNS_ZONE_VALID(zone));
14952         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14953         REQUIRE(zone->zmgr == zmgr);
14954
14955         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14956         LOCK_ZONE(zone);
14957
14958         ISC_LIST_UNLINK(zmgr->zones, zone, link);
14959         zone->zmgr = NULL;
14960         zmgr->refs--;
14961         if (zmgr->refs == 0)
14962                 free_now = ISC_TRUE;
14963
14964         UNLOCK_ZONE(zone);
14965         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14966
14967         if (free_now)
14968                 zonemgr_free(zmgr);
14969         ENSURE(zone->zmgr == NULL);
14970 }
14971
14972 void
14973 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
14974         REQUIRE(DNS_ZONEMGR_VALID(source));
14975         REQUIRE(target != NULL && *target == NULL);
14976
14977         RWLOCK(&source->rwlock, isc_rwlocktype_write);
14978         REQUIRE(source->refs > 0);
14979         source->refs++;
14980         INSIST(source->refs > 0);
14981         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
14982         *target = source;
14983 }
14984
14985 void
14986 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
14987         dns_zonemgr_t *zmgr;
14988         isc_boolean_t free_now = ISC_FALSE;
14989
14990         REQUIRE(zmgrp != NULL);
14991         zmgr = *zmgrp;
14992         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
14993
14994         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14995         zmgr->refs--;
14996         if (zmgr->refs == 0)
14997                 free_now = ISC_TRUE;
14998         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14999
15000         if (free_now)
15001                 zonemgr_free(zmgr);
15002         *zmgrp = NULL;
15003 }
15004
15005 isc_result_t
15006 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
15007         dns_zone_t *p;
15008
15009         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15010
15011         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15012         for (p = ISC_LIST_HEAD(zmgr->zones);
15013              p != NULL;
15014              p = ISC_LIST_NEXT(p, link))
15015         {
15016                 dns_zone_maintenance(p);
15017         }
15018         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15019
15020         /*
15021          * Recent configuration changes may have increased the
15022          * amount of available transfers quota.  Make sure any
15023          * transfers currently blocked on quota get started if
15024          * possible.
15025          */
15026         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15027         zmgr_resume_xfrs(zmgr, ISC_TRUE);
15028         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15029         return (ISC_R_SUCCESS);
15030 }
15031
15032 void
15033 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
15034
15035         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15036
15037         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15038         zmgr_resume_xfrs(zmgr, ISC_TRUE);
15039         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15040 }
15041
15042 void
15043 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
15044         dns_zone_t *zone;
15045
15046         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15047
15048         isc_ratelimiter_shutdown(zmgr->notifyrl);
15049         isc_ratelimiter_shutdown(zmgr->refreshrl);
15050         isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
15051         isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
15052
15053         if (zmgr->task != NULL)
15054                 isc_task_destroy(&zmgr->task);
15055         if (zmgr->zonetasks != NULL)
15056                 isc_taskpool_destroy(&zmgr->zonetasks);
15057         if (zmgr->loadtasks != NULL)
15058                 isc_taskpool_destroy(&zmgr->loadtasks);
15059         if (zmgr->mctxpool != NULL)
15060                 isc_pool_destroy(&zmgr->mctxpool);
15061
15062         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15063         for (zone = ISC_LIST_HEAD(zmgr->zones);
15064              zone != NULL;
15065              zone = ISC_LIST_NEXT(zone, link))
15066         {
15067                 LOCK_ZONE(zone);
15068                 forward_cancel(zone);
15069                 UNLOCK_ZONE(zone);
15070         }
15071         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15072 }
15073
15074 static isc_result_t
15075 mctxinit(void **target, void *arg) {
15076         isc_result_t result;
15077         isc_mem_t *mctx = NULL;
15078
15079         UNUSED(arg);
15080
15081         REQUIRE(target != NULL && *target == NULL);
15082
15083         result = isc_mem_create(0, 0, &mctx);
15084         if (result != ISC_R_SUCCESS)
15085                 return (result);
15086         isc_mem_setname(mctx, "zonemgr-pool", NULL);
15087
15088         *target = mctx;
15089         return (ISC_R_SUCCESS);
15090 }
15091
15092 static void
15093 mctxfree(void **target) {
15094         isc_mem_t *mctx = *(isc_mem_t **) target;
15095         isc_mem_detach(&mctx);
15096         *target = NULL;
15097 }
15098
15099 #define ZONES_PER_TASK 100
15100 #define ZONES_PER_MCTX 1000
15101
15102 isc_result_t
15103 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
15104         isc_result_t result;
15105         int ntasks = num_zones / ZONES_PER_TASK;
15106         int nmctx = num_zones / ZONES_PER_MCTX;
15107         isc_taskpool_t *pool = NULL;
15108         isc_pool_t *mctxpool = NULL;
15109
15110         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15111
15112         /*
15113          * For anything fewer than 1000 zones we use 10 tasks in
15114          * the task pools.  More than that, and we'll scale at one
15115          * task per 100 zones.  Similarly, for anything smaller than
15116          * 2000 zones we use 2 memory contexts, then scale at 1:1000.
15117          */
15118         if (ntasks < 10)
15119                 ntasks = 10;
15120         if (nmctx < 2)
15121                 nmctx = 2;
15122
15123         /* Create or resize the zone task pools. */
15124         if (zmgr->zonetasks == NULL)
15125                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
15126                                              ntasks, 2, &pool);
15127         else
15128                 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
15129
15130         if (result == ISC_R_SUCCESS)
15131                 zmgr->zonetasks = pool;
15132
15133         pool = NULL;
15134         if (zmgr->loadtasks == NULL)
15135                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
15136                                              ntasks, 2, &pool);
15137         else
15138                 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
15139
15140         if (result == ISC_R_SUCCESS)
15141                 zmgr->loadtasks = pool;
15142
15143 #ifdef BIND9
15144         /*
15145          * We always set all tasks in the zone-load task pool to
15146          * privileged.  This prevents other tasks in the system from
15147          * running while the server task manager is in privileged
15148          * mode.
15149          *
15150          * NOTE: If we start using task privileges for any other
15151          * part of the system than zone tasks, then this will need to be
15152          * revisted.  In that case we'd want to turn on privileges for
15153          * zone tasks only when we were loading, and turn them off the
15154          * rest of the time.  For now, however, it's okay to just
15155          * set it and forget it.
15156          */
15157         isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
15158 #endif
15159
15160         /* Create or resize the zone memory context pool. */
15161         if (zmgr->mctxpool == NULL)
15162                 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
15163                                          mctxinit, NULL, &mctxpool);
15164         else
15165                 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
15166
15167         if (result == ISC_R_SUCCESS)
15168                 zmgr->mctxpool = mctxpool;
15169
15170         return (result);
15171 }
15172
15173 static void
15174 zonemgr_free(dns_zonemgr_t *zmgr) {
15175         isc_mem_t *mctx;
15176
15177         INSIST(zmgr->refs == 0);
15178         INSIST(ISC_LIST_EMPTY(zmgr->zones));
15179
15180         zmgr->magic = 0;
15181
15182         DESTROYLOCK(&zmgr->iolock);
15183         isc_ratelimiter_detach(&zmgr->notifyrl);
15184         isc_ratelimiter_detach(&zmgr->refreshrl);
15185         isc_ratelimiter_detach(&zmgr->startupnotifyrl);
15186         isc_ratelimiter_detach(&zmgr->startuprefreshrl);
15187
15188         isc_rwlock_destroy(&zmgr->urlock);
15189         isc_rwlock_destroy(&zmgr->rwlock);
15190         mctx = zmgr->mctx;
15191         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
15192         isc_mem_detach(&mctx);
15193 }
15194
15195 void
15196 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
15197         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15198
15199         zmgr->transfersin = value;
15200 }
15201
15202 isc_uint32_t
15203 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
15204         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15205
15206         return (zmgr->transfersin);
15207 }
15208
15209 void
15210 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
15211         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15212
15213         zmgr->transfersperns = value;
15214 }
15215
15216 isc_uint32_t
15217 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
15218         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15219
15220         return (zmgr->transfersperns);
15221 }
15222
15223 /*
15224  * Try to start a new incoming zone transfer to fill a quota
15225  * slot that was just vacated.
15226  *
15227  * Requires:
15228  *      The zone manager is locked by the caller.
15229  */
15230 static void
15231 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
15232         dns_zone_t *zone;
15233         dns_zone_t *next;
15234
15235         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
15236              zone != NULL;
15237              zone = next)
15238         {
15239                 isc_result_t result;
15240                 next = ISC_LIST_NEXT(zone, statelink);
15241                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
15242                 if (result == ISC_R_SUCCESS) {
15243                         if (multi)
15244                                 continue;
15245                         /*
15246                          * We successfully filled the slot.  We're done.
15247                          */
15248                         break;
15249                 } else if (result == ISC_R_QUOTA) {
15250                         /*
15251                          * Not enough quota.  This is probably the per-server
15252                          * quota, because we usually get called when a unit of
15253                          * global quota has just been freed.  Try the next
15254                          * zone, it may succeed if it uses another master.
15255                          */
15256                         continue;
15257                 } else {
15258                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
15259                                      "starting zone transfer: %s",
15260                                      isc_result_totext(result));
15261                         break;
15262                 }
15263         }
15264 }
15265
15266 /*
15267  * Try to start an incoming zone transfer for 'zone', quota permitting.
15268  *
15269  * Requires:
15270  *      The zone manager is locked by the caller.
15271  *
15272  * Returns:
15273  *      ISC_R_SUCCESS   There was enough quota and we attempted to
15274  *                      start a transfer.  zone_xfrdone() has been or will
15275  *                      be called.
15276  *      ISC_R_QUOTA     Not enough quota.
15277  *      Others          Failure.
15278  */
15279 static isc_result_t
15280 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15281         dns_peer_t *peer = NULL;
15282         isc_netaddr_t masterip;
15283         isc_uint32_t nxfrsin, nxfrsperns;
15284         dns_zone_t *x;
15285         isc_uint32_t maxtransfersin, maxtransfersperns;
15286         isc_event_t *e;
15287
15288         /*
15289          * If we are exiting just pretend we got quota so the zone will
15290          * be cleaned up in the zone's task context.
15291          */
15292         LOCK_ZONE(zone);
15293         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15294                 UNLOCK_ZONE(zone);
15295                 goto gotquota;
15296         }
15297
15298         /*
15299          * Find any configured information about the server we'd
15300          * like to transfer this zone from.
15301          */
15302         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
15303         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
15304         UNLOCK_ZONE(zone);
15305
15306         /*
15307          * Determine the total maximum number of simultaneous
15308          * transfers allowed, and the maximum for this specific
15309          * master.
15310          */
15311         maxtransfersin = zmgr->transfersin;
15312         maxtransfersperns = zmgr->transfersperns;
15313         if (peer != NULL)
15314                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
15315
15316         /*
15317          * Count the total number of transfers that are in progress,
15318          * and the number of transfers in progress from this master.
15319          * We linearly scan a list of all transfers; if this turns
15320          * out to be too slow, we could hash on the master address.
15321          */
15322         nxfrsin = nxfrsperns = 0;
15323         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15324              x != NULL;
15325              x = ISC_LIST_NEXT(x, statelink))
15326         {
15327                 isc_netaddr_t xip;
15328
15329                 LOCK_ZONE(x);
15330                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
15331                 UNLOCK_ZONE(x);
15332
15333                 nxfrsin++;
15334                 if (isc_netaddr_equal(&xip, &masterip))
15335                         nxfrsperns++;
15336         }
15337
15338         /* Enforce quota. */
15339         if (nxfrsin >= maxtransfersin)
15340                 return (ISC_R_QUOTA);
15341
15342         if (nxfrsperns >= maxtransfersperns)
15343                 return (ISC_R_QUOTA);
15344
15345  gotquota:
15346         /*
15347          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
15348          * list and send it an event to let it start the actual transfer in the
15349          * context of its own task.
15350          */
15351         e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
15352                                got_transfer_quota, zone, sizeof(isc_event_t));
15353         if (e == NULL)
15354                 return (ISC_R_NOMEMORY);
15355
15356         LOCK_ZONE(zone);
15357         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
15358         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
15359         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
15360         zone->statelist = &zmgr->xfrin_in_progress;
15361         isc_task_send(zone->task, &e);
15362         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
15363         UNLOCK_ZONE(zone);
15364
15365         return (ISC_R_SUCCESS);
15366 }
15367
15368 void
15369 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
15370
15371         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15372         REQUIRE(iolimit > 0);
15373
15374         zmgr->iolimit = iolimit;
15375 }
15376
15377 isc_uint32_t
15378 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
15379
15380         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15381
15382         return (zmgr->iolimit);
15383 }
15384
15385 /*
15386  * Get permission to request a file handle from the OS.
15387  * An event will be sent to action when one is available.
15388  * There are two queues available (high and low), the high
15389  * queue will be serviced before the low one.
15390  *
15391  * zonemgr_putio() must be called after the event is delivered to
15392  * 'action'.
15393  */
15394
15395 static isc_result_t
15396 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
15397               isc_task_t *task, isc_taskaction_t action, void *arg,
15398               dns_io_t **iop)
15399 {
15400         dns_io_t *io;
15401         isc_boolean_t queue;
15402
15403         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15404         REQUIRE(iop != NULL && *iop == NULL);
15405
15406         io = isc_mem_get(zmgr->mctx, sizeof(*io));
15407         if (io == NULL)
15408                 return (ISC_R_NOMEMORY);
15409
15410         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
15411                                        action, arg, sizeof(*io->event));
15412         if (io->event == NULL) {
15413                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
15414                 return (ISC_R_NOMEMORY);
15415         }
15416
15417         io->zmgr = zmgr;
15418         io->high = high;
15419         io->task = NULL;
15420         isc_task_attach(task, &io->task);
15421         ISC_LINK_INIT(io, link);
15422         io->magic = IO_MAGIC;
15423
15424         LOCK(&zmgr->iolock);
15425         zmgr->ioactive++;
15426         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
15427         if (queue) {
15428                 if (io->high)
15429                         ISC_LIST_APPEND(zmgr->high, io, link);
15430                 else
15431                         ISC_LIST_APPEND(zmgr->low, io, link);
15432         }
15433         UNLOCK(&zmgr->iolock);
15434         *iop = io;
15435
15436         if (!queue)
15437                 isc_task_send(io->task, &io->event);
15438         return (ISC_R_SUCCESS);
15439 }
15440
15441 static void
15442 zonemgr_putio(dns_io_t **iop) {
15443         dns_io_t *io;
15444         dns_io_t *next;
15445         dns_zonemgr_t *zmgr;
15446
15447         REQUIRE(iop != NULL);
15448         io = *iop;
15449         REQUIRE(DNS_IO_VALID(io));
15450
15451         *iop = NULL;
15452
15453         INSIST(!ISC_LINK_LINKED(io, link));
15454         INSIST(io->event == NULL);
15455
15456         zmgr = io->zmgr;
15457         isc_task_detach(&io->task);
15458         io->magic = 0;
15459         isc_mem_put(zmgr->mctx, io, sizeof(*io));
15460
15461         LOCK(&zmgr->iolock);
15462         INSIST(zmgr->ioactive > 0);
15463         zmgr->ioactive--;
15464         next = HEAD(zmgr->high);
15465         if (next == NULL)
15466                 next = HEAD(zmgr->low);
15467         if (next != NULL) {
15468                 if (next->high)
15469                         ISC_LIST_UNLINK(zmgr->high, next, link);
15470                 else
15471                         ISC_LIST_UNLINK(zmgr->low, next, link);
15472                 INSIST(next->event != NULL);
15473         }
15474         UNLOCK(&zmgr->iolock);
15475         if (next != NULL)
15476                 isc_task_send(next->task, &next->event);
15477 }
15478
15479 static void
15480 zonemgr_cancelio(dns_io_t *io) {
15481         isc_boolean_t send_event = ISC_FALSE;
15482
15483         REQUIRE(DNS_IO_VALID(io));
15484
15485         /*
15486          * If we are queued to be run then dequeue.
15487          */
15488         LOCK(&io->zmgr->iolock);
15489         if (ISC_LINK_LINKED(io, link)) {
15490                 if (io->high)
15491                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
15492                 else
15493                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
15494
15495                 send_event = ISC_TRUE;
15496                 INSIST(io->event != NULL);
15497         }
15498         UNLOCK(&io->zmgr->iolock);
15499         if (send_event) {
15500                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
15501                 isc_task_send(io->task, &io->event);
15502         }
15503 }
15504
15505 static void
15506 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
15507         char *buf;
15508         int buflen;
15509         isc_result_t result;
15510
15511         buflen = strlen(path) + strlen(templat) + 2;
15512
15513         buf = isc_mem_get(zone->mctx, buflen);
15514         if (buf == NULL)
15515                 return;
15516
15517         result = isc_file_template(path, templat, buf, buflen);
15518         if (result != ISC_R_SUCCESS)
15519                 goto cleanup;
15520
15521         result = isc_file_renameunique(path, buf);
15522         if (result != ISC_R_SUCCESS)
15523                 goto cleanup;
15524
15525         dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
15526                      "renaming file to '%s' for failure analysis and "
15527                      "retransferring.", path, buf);
15528
15529  cleanup:
15530         isc_mem_put(zone->mctx, buf, buflen);
15531 }
15532
15533 #if 0
15534 /* Hook for ondestroy notification from a database. */
15535
15536 static void
15537 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
15538         dns_db_t *db = event->sender;
15539         UNUSED(task);
15540
15541         isc_event_free(&event);
15542
15543         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15544                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15545                       "database (%p) destroyed", (void*) db);
15546 }
15547 #endif
15548
15549 static void
15550 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
15551         isc_interval_t interval;
15552         isc_uint32_t s, ns;
15553         isc_uint32_t pertic;
15554         isc_result_t result;
15555
15556         if (value == 0)
15557                 value = 1;
15558
15559         if (value == 1) {
15560                 s = 1;
15561                 ns = 0;
15562                 pertic = 1;
15563         } else if (value <= 10) {
15564                 s = 0;
15565                 ns = 1000000000 / value;
15566                 pertic = 1;
15567         } else {
15568                 s = 0;
15569                 ns = (1000000000 / value) * 10;
15570                 pertic = 10;
15571         }
15572
15573         isc_interval_set(&interval, s, ns);
15574
15575         result = isc_ratelimiter_setinterval(rl, &interval);
15576         RUNTIME_CHECK(result == ISC_R_SUCCESS);
15577         isc_ratelimiter_setpertic(rl, pertic);
15578
15579         *rate = value;
15580 }
15581
15582 void
15583 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
15584
15585         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15586
15587         setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
15588
15589         /* Seperately controlled in BIND 9.11.x */
15590         setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
15591         setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
15592
15593         /* XXXMPA seperate out once we have the code to support this. */
15594         setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
15595 }
15596
15597 unsigned int
15598 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
15599         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15600
15601         return (zmgr->serialqueryrate);
15602 }
15603
15604 isc_boolean_t
15605 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15606                         isc_sockaddr_t *local, isc_time_t *now)
15607 {
15608         unsigned int i;
15609         isc_rwlocktype_t locktype;
15610         isc_result_t result;
15611         isc_uint32_t seconds = isc_time_seconds(now);
15612         isc_uint32_t count = 0;
15613
15614         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15615
15616         locktype = isc_rwlocktype_read;
15617         RWLOCK(&zmgr->urlock, locktype);
15618         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15619                 if (zmgr->unreachable[i].expire >= seconds &&
15620                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15621                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
15622                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
15623                         if (result == ISC_R_SUCCESS) {
15624                                 locktype = isc_rwlocktype_write;
15625                                 zmgr->unreachable[i].last = seconds;
15626                                 count = zmgr->unreachable[i].count;
15627                         }
15628                         break;
15629                 }
15630         }
15631         RWUNLOCK(&zmgr->urlock, locktype);
15632         return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
15633 }
15634
15635 void
15636 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15637                            isc_sockaddr_t *local)
15638 {
15639         unsigned int i;
15640         isc_rwlocktype_t locktype;
15641         isc_result_t result;
15642
15643         char master[ISC_SOCKADDR_FORMATSIZE];
15644         char source[ISC_SOCKADDR_FORMATSIZE];
15645
15646         isc_sockaddr_format(remote, master, sizeof(master));
15647         isc_sockaddr_format(local, source, sizeof(source));
15648
15649         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15650
15651         locktype = isc_rwlocktype_read;
15652         RWLOCK(&zmgr->urlock, locktype);
15653         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15654                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15655                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
15656                         if (zmgr->unreachable[i].expire == 0)
15657                                 break;
15658                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
15659                         if (result == ISC_R_SUCCESS) {
15660                                 locktype = isc_rwlocktype_write;
15661                                 zmgr->unreachable[i].expire = 0;
15662                                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15663                                               DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
15664                                               "master %s (source %s) deleted "
15665                                               "from unreachable cache",
15666                                               master, source);
15667                         }
15668                         break;
15669                 }
15670         }
15671         RWUNLOCK(&zmgr->urlock, locktype);
15672 }
15673
15674 void
15675 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
15676                            isc_sockaddr_t *local, isc_time_t *now)
15677 {
15678         isc_uint32_t seconds = isc_time_seconds(now);
15679         isc_uint32_t last = seconds;
15680         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
15681
15682         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15683
15684         RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
15685         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
15686                 /* Existing entry? */
15687                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
15688                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
15689                         break;
15690                 /* Empty slot? */
15691                 if (zmgr->unreachable[i].expire < seconds)
15692                         slot = i;
15693                 /* Least recently used slot? */
15694                 if (zmgr->unreachable[i].last < last) {
15695                         last = zmgr->unreachable[i].last;
15696                         oldest = i;
15697                 }
15698         }
15699         if (i < UNREACH_CHACHE_SIZE) {
15700                 /*
15701                  * Found a existing entry.  Update the expire timer and
15702                  * last usage timestamps.
15703                  */
15704                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
15705                 zmgr->unreachable[i].last = seconds;
15706                 if (zmgr->unreachable[i].expire < seconds)
15707                         zmgr->unreachable[i].count = 1;
15708                 else
15709                         zmgr->unreachable[i].count++;
15710         } else if (slot != UNREACH_CHACHE_SIZE) {
15711                 /*
15712                  * Found a empty slot. Add a new entry to the cache.
15713                  */
15714                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
15715                 zmgr->unreachable[slot].last = seconds;
15716                 zmgr->unreachable[slot].remote = *remote;
15717                 zmgr->unreachable[slot].local = *local;
15718                 zmgr->unreachable[slot].count = 1;
15719         } else {
15720                 /*
15721                  * Replace the least recently used entry in the cache.
15722                  */
15723                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
15724                 zmgr->unreachable[oldest].last = seconds;
15725                 zmgr->unreachable[oldest].remote = *remote;
15726                 zmgr->unreachable[oldest].local = *local;
15727                 zmgr->unreachable[oldest].count = 1;
15728         }
15729         RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
15730 }
15731
15732 void
15733 dns_zone_forcereload(dns_zone_t *zone) {
15734         REQUIRE(DNS_ZONE_VALID(zone));
15735
15736         if (zone->type == dns_zone_master ||
15737             (zone->type == dns_zone_redirect && zone->masters == NULL))
15738                 return;
15739
15740         LOCK_ZONE(zone);
15741         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
15742         UNLOCK_ZONE(zone);
15743         dns_zone_refresh(zone);
15744 }
15745
15746 isc_boolean_t
15747 dns_zone_isforced(dns_zone_t *zone) {
15748         REQUIRE(DNS_ZONE_VALID(zone));
15749
15750         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
15751 }
15752
15753 isc_result_t
15754 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
15755         /*
15756          * This function is obsoleted.
15757          */
15758         UNUSED(zone);
15759         UNUSED(on);
15760         return (ISC_R_NOTIMPLEMENTED);
15761 }
15762
15763 isc_uint64_t *
15764 dns_zone_getstatscounters(dns_zone_t *zone) {
15765         /*
15766          * This function is obsoleted.
15767          */
15768         UNUSED(zone);
15769         return (NULL);
15770 }
15771
15772 void
15773 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
15774         REQUIRE(DNS_ZONE_VALID(zone));
15775         REQUIRE(zone->stats == NULL);
15776
15777         LOCK_ZONE(zone);
15778         zone->stats = NULL;
15779         isc_stats_attach(stats, &zone->stats);
15780         UNLOCK_ZONE(zone);
15781 }
15782
15783 void
15784 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
15785
15786         REQUIRE(DNS_ZONE_VALID(zone));
15787
15788         LOCK_ZONE(zone);
15789         if (zone->requeststats_on && stats == NULL)
15790                 zone->requeststats_on = ISC_FALSE;
15791         else if (!zone->requeststats_on && stats != NULL) {
15792                 if (zone->requeststats == NULL) {
15793                         isc_stats_attach(stats, &zone->requeststats);
15794                         zone->requeststats_on = ISC_TRUE;
15795                 }
15796         }
15797         UNLOCK_ZONE(zone);
15798 }
15799
15800 #ifdef NEWSTATS
15801 void
15802 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
15803
15804         REQUIRE(DNS_ZONE_VALID(zone));
15805
15806         LOCK_ZONE(zone);
15807         if (zone->requeststats_on && stats != NULL) {
15808                 if (zone->rcvquerystats == NULL) {
15809                         dns_stats_attach(stats, &zone->rcvquerystats);
15810                         zone->requeststats_on = ISC_TRUE;
15811                 }
15812         }
15813         UNLOCK_ZONE(zone);
15814 }
15815 #endif
15816
15817 isc_stats_t *
15818 dns_zone_getrequeststats(dns_zone_t *zone) {
15819         /*
15820          * We don't lock zone for efficiency reason.  This is not catastrophic
15821          * because requeststats must always be valid when requeststats_on is
15822          * true.
15823          * Some counters may be incremented while requeststats_on is becoming
15824          * false, or some cannot be incremented just after the statistics are
15825          * installed, but it shouldn't matter much in practice.
15826          */
15827         if (zone->requeststats_on)
15828                 return (zone->requeststats);
15829         else
15830                 return (NULL);
15831 }
15832
15833 #ifdef NEWSTATS
15834 /*
15835  * Return the received query stats bucket
15836  * see note from dns_zone_getrequeststats()
15837  */
15838 dns_stats_t *
15839 dns_zone_getrcvquerystats(dns_zone_t *zone) {
15840         if (zone->requeststats_on)
15841                 return (zone->rcvquerystats);
15842         else
15843                 return (NULL);
15844 }
15845 #endif
15846
15847 void
15848 dns_zone_dialup(dns_zone_t *zone) {
15849
15850         REQUIRE(DNS_ZONE_VALID(zone));
15851
15852         zone_debuglog(zone, "dns_zone_dialup", 3,
15853                       "notify = %d, refresh = %d",
15854                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
15855                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
15856
15857         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
15858                 dns_zone_notify(zone);
15859         if (zone->type != dns_zone_master && zone->masters != NULL &&
15860             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
15861                 dns_zone_refresh(zone);
15862 }
15863
15864 void
15865 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
15866         REQUIRE(DNS_ZONE_VALID(zone));
15867
15868         LOCK_ZONE(zone);
15869         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
15870                          DNS_ZONEFLG_DIALREFRESH |
15871                          DNS_ZONEFLG_NOREFRESH);
15872         switch (dialup) {
15873         case dns_dialuptype_no:
15874                 break;
15875         case dns_dialuptype_yes:
15876                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
15877                                  DNS_ZONEFLG_DIALREFRESH |
15878                                  DNS_ZONEFLG_NOREFRESH));
15879                 break;
15880         case dns_dialuptype_notify:
15881                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15882                 break;
15883         case dns_dialuptype_notifypassive:
15884                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
15885                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15886                 break;
15887         case dns_dialuptype_refresh:
15888                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
15889                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15890                 break;
15891         case dns_dialuptype_passive:
15892                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
15893                 break;
15894         default:
15895                 INSIST(0);
15896         }
15897         UNLOCK_ZONE(zone);
15898 }
15899
15900 isc_result_t
15901 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
15902         isc_result_t result = ISC_R_SUCCESS;
15903
15904         REQUIRE(DNS_ZONE_VALID(zone));
15905
15906         LOCK_ZONE(zone);
15907         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
15908         UNLOCK_ZONE(zone);
15909
15910         return (result);
15911 }
15912
15913 const char *
15914 dns_zone_getkeydirectory(dns_zone_t *zone) {
15915         REQUIRE(DNS_ZONE_VALID(zone));
15916
15917         return (zone->keydirectory);
15918 }
15919
15920 unsigned int
15921 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
15922         dns_zone_t *zone;
15923         unsigned int count = 0;
15924
15925         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15926
15927         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15928         switch (state) {
15929         case DNS_ZONESTATE_XFERRUNNING:
15930                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15931                      zone != NULL;
15932                      zone = ISC_LIST_NEXT(zone, statelink))
15933                         count++;
15934                 break;
15935         case DNS_ZONESTATE_XFERDEFERRED:
15936                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
15937                      zone != NULL;
15938                      zone = ISC_LIST_NEXT(zone, statelink))
15939                         count++;
15940                 break;
15941         case DNS_ZONESTATE_SOAQUERY:
15942                 for (zone = ISC_LIST_HEAD(zmgr->zones);
15943                      zone != NULL;
15944                      zone = ISC_LIST_NEXT(zone, link))
15945                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
15946                                 count++;
15947                 break;
15948         case DNS_ZONESTATE_ANY:
15949                 for (zone = ISC_LIST_HEAD(zmgr->zones);
15950                      zone != NULL;
15951                      zone = ISC_LIST_NEXT(zone, link)) {
15952                         dns_view_t *view = zone->view;
15953                         if (view != NULL && strcmp(view->name, "_bind") == 0)
15954                                 continue;
15955                         count++;
15956                 }
15957                 break;
15958         default:
15959                 INSIST(0);
15960         }
15961
15962         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15963
15964         return (count);
15965 }
15966
15967 isc_result_t
15968 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
15969         isc_boolean_t ok = ISC_TRUE;
15970         isc_boolean_t fail = ISC_FALSE;
15971         char namebuf[DNS_NAME_FORMATSIZE];
15972         char namebuf2[DNS_NAME_FORMATSIZE];
15973         char typebuf[DNS_RDATATYPE_FORMATSIZE];
15974         int level = ISC_LOG_WARNING;
15975         dns_name_t bad;
15976
15977         REQUIRE(DNS_ZONE_VALID(zone));
15978
15979         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
15980             rdata->type != dns_rdatatype_nsec3)
15981                 return (ISC_R_SUCCESS);
15982
15983         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
15984             rdata->type == dns_rdatatype_nsec3) {
15985                 level = ISC_LOG_ERROR;
15986                 fail = ISC_TRUE;
15987         }
15988
15989         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
15990         if (!ok) {
15991                 dns_name_format(name, namebuf, sizeof(namebuf));
15992                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
15993                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
15994                              dns_result_totext(DNS_R_BADOWNERNAME));
15995                 if (fail)
15996                         return (DNS_R_BADOWNERNAME);
15997         }
15998
15999         dns_name_init(&bad, NULL);
16000         ok = dns_rdata_checknames(rdata, name, &bad);
16001         if (!ok) {
16002                 dns_name_format(name, namebuf, sizeof(namebuf));
16003                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
16004                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
16005                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
16006                              namebuf2, dns_result_totext(DNS_R_BADNAME));
16007                 if (fail)
16008                         return (DNS_R_BADNAME);
16009         }
16010
16011         return (ISC_R_SUCCESS);
16012 }
16013
16014 void
16015 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
16016         REQUIRE(DNS_ZONE_VALID(zone));
16017         zone->checkmx = checkmx;
16018 }
16019
16020 void
16021 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
16022         REQUIRE(DNS_ZONE_VALID(zone));
16023         zone->checksrv = checksrv;
16024 }
16025
16026 void
16027 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
16028         REQUIRE(DNS_ZONE_VALID(zone));
16029         zone->checkns = checkns;
16030 }
16031
16032 void
16033 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
16034         REQUIRE(DNS_ZONE_VALID(zone));
16035
16036         LOCK_ZONE(zone);
16037         zone->isself = isself;
16038         zone->isselfarg = arg;
16039         UNLOCK_ZONE(zone);
16040 }
16041
16042 void
16043 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
16044         REQUIRE(DNS_ZONE_VALID(zone));
16045
16046         LOCK_ZONE(zone);
16047         zone->notifydelay = delay;
16048         UNLOCK_ZONE(zone);
16049 }
16050
16051 isc_uint32_t
16052 dns_zone_getnotifydelay(dns_zone_t *zone) {
16053         REQUIRE(DNS_ZONE_VALID(zone));
16054
16055         return (zone->notifydelay);
16056 }
16057
16058 isc_result_t
16059 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
16060                      isc_uint16_t keyid, isc_boolean_t delete)
16061 {
16062         isc_result_t result;
16063         REQUIRE(DNS_ZONE_VALID(zone));
16064
16065         dns_zone_log(zone, ISC_LOG_NOTICE,
16066                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
16067                      algorithm, keyid);
16068         LOCK_ZONE(zone);
16069         result = zone_signwithkey(zone, algorithm, keyid, delete);
16070         UNLOCK_ZONE(zone);
16071
16072         return (result);
16073 }
16074
16075 static const char *hex = "0123456789ABCDEF";
16076
16077 isc_result_t
16078 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
16079         isc_result_t result;
16080         char salt[255*2+1];
16081         unsigned int i, j;
16082
16083         REQUIRE(DNS_ZONE_VALID(zone));
16084
16085         if (nsec3param->salt_length != 0) {
16086                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
16087                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
16088                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
16089                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
16090                 }
16091                 salt[j] = '\0';
16092         } else
16093                 strcpy(salt, "-");
16094         dns_zone_log(zone, ISC_LOG_NOTICE,
16095                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
16096                      nsec3param->hash, nsec3param->iterations,
16097                      salt);
16098         LOCK_ZONE(zone);
16099         result = zone_addnsec3chain(zone, nsec3param);
16100         UNLOCK_ZONE(zone);
16101
16102         return (result);
16103 }
16104
16105 void
16106 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
16107         REQUIRE(DNS_ZONE_VALID(zone));
16108
16109         if (nodes == 0)
16110                 nodes = 1;
16111         zone->nodes = nodes;
16112 }
16113
16114 void
16115 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
16116         REQUIRE(DNS_ZONE_VALID(zone));
16117
16118         /*
16119          * We treat signatures as a signed value so explicitly
16120          * limit its range here.
16121          */
16122         if (signatures > ISC_INT32_MAX)
16123                 signatures = ISC_INT32_MAX;
16124         else if (signatures == 0)
16125                 signatures = 1;
16126         zone->signatures = signatures;
16127 }
16128
16129 isc_uint32_t
16130 dns_zone_getsignatures(dns_zone_t *zone) {
16131         REQUIRE(DNS_ZONE_VALID(zone));
16132         return (zone->signatures);
16133 }
16134
16135 void
16136 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
16137         REQUIRE(DNS_ZONE_VALID(zone));
16138         zone->privatetype = type;
16139 }
16140
16141 dns_rdatatype_t
16142 dns_zone_getprivatetype(dns_zone_t *zone) {
16143         REQUIRE(DNS_ZONE_VALID(zone));
16144         return (zone->privatetype);
16145 }
16146
16147 static isc_result_t
16148 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
16149                  isc_boolean_t delete)
16150 {
16151         dns_signing_t *signing;
16152         dns_signing_t *current;
16153         isc_result_t result = ISC_R_SUCCESS;
16154         isc_time_t now;
16155         dns_db_t *db = NULL;
16156
16157         signing = isc_mem_get(zone->mctx, sizeof *signing);
16158         if (signing == NULL)
16159                 return (ISC_R_NOMEMORY);
16160
16161         signing->magic = 0;
16162         signing->db  = NULL;
16163         signing->dbiterator = NULL;
16164         signing->algorithm = algorithm;
16165         signing->keyid = keyid;
16166         signing->delete = delete;
16167         signing->done = ISC_FALSE;
16168
16169         TIME_NOW(&now);
16170
16171         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16172         if (zone->db != NULL)
16173                 dns_db_attach(zone->db, &db);
16174         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16175
16176         if (db == NULL) {
16177                 result = ISC_R_NOTFOUND;
16178                 goto cleanup;
16179         }
16180
16181         dns_db_attach(db, &signing->db);
16182
16183         for (current = ISC_LIST_HEAD(zone->signing);
16184              current != NULL;
16185              current = ISC_LIST_NEXT(current, link)) {
16186                 if (current->db == signing->db &&
16187                     current->algorithm == signing->algorithm &&
16188                     current->keyid == signing->keyid) {
16189                         if (current->delete != signing->delete)
16190                                 current->done = ISC_TRUE;
16191                         else
16192                                 goto cleanup;
16193                 }
16194         }
16195
16196         result = dns_db_createiterator(signing->db, 0,
16197                                        &signing->dbiterator);
16198
16199         if (result == ISC_R_SUCCESS)
16200                 result = dns_dbiterator_first(signing->dbiterator);
16201         if (result == ISC_R_SUCCESS) {
16202                 dns_dbiterator_pause(signing->dbiterator);
16203                 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
16204                 signing = NULL;
16205                 if (isc_time_isepoch(&zone->signingtime)) {
16206                         zone->signingtime = now;
16207                         if (zone->task != NULL)
16208                                 zone_settimer(zone, &now);
16209                 }
16210         }
16211
16212  cleanup:
16213         if (signing != NULL) {
16214                 if (signing->db != NULL)
16215                         dns_db_detach(&signing->db);
16216                 if (signing->dbiterator != NULL)
16217                         dns_dbiterator_destroy(&signing->dbiterator);
16218                 isc_mem_put(zone->mctx, signing, sizeof *signing);
16219         }
16220         if (db != NULL)
16221                 dns_db_detach(&db);
16222         return (result);
16223 }
16224
16225 static void
16226 logmsg(const char *format, ...) {
16227         va_list args;
16228         va_start(args, format);
16229         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
16230                        ISC_LOG_DEBUG(1), format, args);
16231         va_end(args);
16232 }
16233
16234 static void
16235 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
16236         dns_dnsseckey_t *key;
16237         while (!ISC_LIST_EMPTY(*list)) {
16238                 key = ISC_LIST_HEAD(*list);
16239                 ISC_LIST_UNLINK(*list, key, link);
16240                 dns_dnsseckey_destroy(mctx, &key);
16241         }
16242 }
16243
16244 /* Called once; *timep should be set to the current time. */
16245 static isc_result_t
16246 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
16247         isc_result_t result;
16248         isc_stdtime_t now, then = 0, event;
16249         int i;
16250
16251         now = *timep;
16252
16253         for (i = 0; i <= DST_MAX_TIMES; i++) {
16254                 result = dst_key_gettime(key, i, &event);
16255                 if (result == ISC_R_SUCCESS && event > now &&
16256                     (then == 0 || event < then))
16257                         then = event;
16258         }
16259
16260         if (then != 0) {
16261                 *timep = then;
16262                 return (ISC_R_SUCCESS);
16263         }
16264
16265         return (ISC_R_NOTFOUND);
16266 }
16267
16268 static isc_result_t
16269 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
16270           const dns_rdata_t *rdata, isc_boolean_t *flag)
16271 {
16272         dns_rdataset_t rdataset;
16273         dns_dbnode_t *node = NULL;
16274         isc_result_t result;
16275
16276         dns_rdataset_init(&rdataset);
16277         if (rdata->type == dns_rdatatype_nsec3)
16278                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
16279         else
16280                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
16281         result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
16282                                      (isc_stdtime_t) 0, &rdataset, NULL);
16283         if (result == ISC_R_NOTFOUND) {
16284                 *flag = ISC_FALSE;
16285                 result = ISC_R_SUCCESS;
16286                 goto failure;
16287         }
16288
16289         for (result = dns_rdataset_first(&rdataset);
16290              result == ISC_R_SUCCESS;
16291              result = dns_rdataset_next(&rdataset)) {
16292                 dns_rdata_t myrdata = DNS_RDATA_INIT;
16293                 dns_rdataset_current(&rdataset, &myrdata);
16294                 if (!dns_rdata_compare(&myrdata, rdata))
16295                         break;
16296         }
16297         dns_rdataset_disassociate(&rdataset);
16298         if (result == ISC_R_SUCCESS) {
16299                 *flag = ISC_TRUE;
16300         } else if (result == ISC_R_NOMORE) {
16301                 *flag = ISC_FALSE;
16302                 result = ISC_R_SUCCESS;
16303         }
16304
16305  failure:
16306         if (node != NULL)
16307                 dns_db_detachnode(db, &node);
16308         return (result);
16309 }
16310
16311 /*
16312  * Add records to signal the state of signing or of key removal.
16313  */
16314 static isc_result_t
16315 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
16316                     dns_dbversion_t *ver, dns_diff_t *diff,
16317                     isc_boolean_t sign_all)
16318 {
16319         dns_difftuple_t *tuple, *newtuple = NULL;
16320         dns_rdata_dnskey_t dnskey;
16321         dns_rdata_t rdata = DNS_RDATA_INIT;
16322         isc_boolean_t flag;
16323         isc_region_t r;
16324         isc_result_t result = ISC_R_SUCCESS;
16325         isc_uint16_t keyid;
16326         unsigned char buf[5];
16327         dns_name_t *name = dns_db_origin(db);
16328
16329         for (tuple = ISC_LIST_HEAD(diff->tuples);
16330              tuple != NULL;
16331              tuple = ISC_LIST_NEXT(tuple, link)) {
16332                 if (tuple->rdata.type != dns_rdatatype_dnskey)
16333                         continue;
16334
16335                 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
16336                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16337                 if ((dnskey.flags &
16338                      (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
16339                          != DNS_KEYOWNER_ZONE)
16340                         continue;
16341
16342                 dns_rdata_toregion(&tuple->rdata, &r);
16343
16344                 keyid = dst_region_computeid(&r, dnskey.algorithm);
16345
16346                 buf[0] = dnskey.algorithm;
16347                 buf[1] = (keyid & 0xff00) >> 8;
16348                 buf[2] = (keyid & 0xff);
16349                 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
16350                 buf[4] = 0;
16351                 rdata.data = buf;
16352                 rdata.length = sizeof(buf);
16353                 rdata.type = privatetype;
16354                 rdata.rdclass = tuple->rdata.rdclass;
16355
16356                 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
16357                         CHECK(rr_exists(db, ver, name, &rdata, &flag));
16358                         if (flag)
16359                                 continue;
16360                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
16361                                                    name, 0, &rdata, &newtuple));
16362                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
16363                         INSIST(newtuple == NULL);
16364                 }
16365
16366                 /*
16367                  * Remove any record which says this operation has already
16368                  * completed.
16369                  */
16370                 buf[4] = 1;
16371                 CHECK(rr_exists(db, ver, name, &rdata, &flag));
16372                 if (flag) {
16373                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
16374                                                    name, 0, &rdata, &newtuple));
16375                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
16376                         INSIST(newtuple == NULL);
16377                 }
16378         }
16379  failure:
16380         return (result);
16381 }
16382
16383 static isc_result_t
16384 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16385           dns_diff_t *diff, zonediff_t *zonediff)
16386 {
16387         isc_result_t result;
16388         isc_stdtime_t now, inception, soaexpire;
16389         isc_boolean_t check_ksk, keyset_kskonly;
16390         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
16391         unsigned int nkeys = 0, i;
16392         dns_difftuple_t *tuple;
16393
16394         result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
16395                                 zone_keys, &nkeys);
16396         if (result != ISC_R_SUCCESS) {
16397                 dns_zone_log(zone, ISC_LOG_ERROR,
16398                              "sign_apex:find_zone_keys -> %s",
16399                              dns_result_totext(result));
16400                 return (result);
16401         }
16402
16403         isc_stdtime_get(&now);
16404         inception = now - 3600; /* Allow for clock skew. */
16405         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
16406
16407         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16408         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
16409
16410         /*
16411          * See if update_sigs will update DNSKEY signature and if not
16412          * cause them to sign so that so that newly activated keys
16413          * are used.
16414          */
16415         for (tuple = ISC_LIST_HEAD(diff->tuples);
16416              tuple != NULL;
16417              tuple = ISC_LIST_NEXT(tuple, link)) {
16418                 if (tuple->rdata.type == dns_rdatatype_dnskey &&
16419                     dns_name_equal(&tuple->name, &zone->origin))
16420                         break;
16421         }
16422
16423         if (tuple == NULL) {
16424                 result = del_sigs(zone, db, ver, &zone->origin,
16425                                   dns_rdatatype_dnskey, zonediff,
16426                                   zone_keys, nkeys, now, ISC_FALSE);
16427                 if (result != ISC_R_SUCCESS) {
16428                         dns_zone_log(zone, ISC_LOG_ERROR,
16429                                      "sign_apex:del_sigs -> %s",
16430                                      dns_result_totext(result));
16431                         goto failure;
16432                 }
16433                 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
16434                                   zonediff->diff, zone_keys, nkeys, zone->mctx,
16435                                   inception, soaexpire, check_ksk,
16436                                   keyset_kskonly);
16437                 if (result != ISC_R_SUCCESS) {
16438                         dns_zone_log(zone, ISC_LOG_ERROR,
16439                                      "sign_apex:add_sigs -> %s",
16440                                      dns_result_totext(result));
16441                         goto failure;
16442                 }
16443         }
16444
16445         result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
16446                              inception, soaexpire, now, check_ksk,
16447                              keyset_kskonly, zonediff);
16448
16449         if (result != ISC_R_SUCCESS) {
16450                 dns_zone_log(zone, ISC_LOG_ERROR,
16451                              "sign_apex:update_sigs -> %s",
16452                              dns_result_totext(result));
16453                 goto failure;
16454         }
16455
16456  failure:
16457         for (i = 0; i < nkeys; i++)
16458                 dst_key_free(&zone_keys[i]);
16459         return (result);
16460 }
16461
16462 /*
16463  * Prevent the zone entering a inconsistent state where
16464  * NSEC only DNSKEYs are present with NSEC3 chains.
16465  * See update.c:check_dnssec()
16466  */
16467 static isc_boolean_t
16468 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16469             dns_diff_t *diff)
16470 {
16471         isc_result_t result;
16472         dns_difftuple_t *tuple;
16473         isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
16474         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
16475
16476         /* Scan the tuples for an NSEC-only DNSKEY */
16477         for (tuple = ISC_LIST_HEAD(diff->tuples);
16478              tuple != NULL;
16479              tuple = ISC_LIST_NEXT(tuple, link)) {
16480                 isc_uint8_t alg;
16481                 if (tuple->rdata.type != dns_rdatatype_dnskey ||
16482                     tuple->op != DNS_DIFFOP_ADD)
16483                         continue;
16484
16485                 alg = tuple->rdata.data[3];
16486                 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
16487                     alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
16488                         nseconly = ISC_TRUE;
16489                         break;
16490                 }
16491         }
16492
16493         /* Check existing DB for NSEC-only DNSKEY */
16494         if (!nseconly) {
16495                 result = dns_nsec_nseconly(db, ver, &nseconly);
16496                 if (result == ISC_R_NOTFOUND)
16497                         result = ISC_R_SUCCESS;
16498                 CHECK(result);
16499         }
16500
16501         /* Check existing DB for NSEC3 */
16502         if (!nsec3)
16503                 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
16504                                         privatetype, &nsec3));
16505
16506         /* Refuse to allow NSEC3 with NSEC-only keys */
16507         if (nseconly && nsec3) {
16508                 dns_zone_log(zone, ISC_LOG_ERROR,
16509                            "NSEC only DNSKEYs and NSEC3 chains not allowed");
16510                 goto failure;
16511         }
16512
16513         return (ISC_TRUE);
16514
16515  failure:
16516         return (ISC_FALSE);
16517 }
16518
16519 static isc_result_t
16520 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16521                  dns_diff_t *diff)
16522 {
16523         isc_result_t result;
16524         dns_dbnode_t *node = NULL;
16525         dns_rdataset_t rdataset;
16526
16527         dns_rdataset_init(&rdataset);
16528         CHECK(dns_db_getoriginnode(db, &node));
16529
16530         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16531                                      dns_rdatatype_none, 0, &rdataset, NULL);
16532         if (dns_rdataset_isassociated(&rdataset))
16533                 dns_rdataset_disassociate(&rdataset);
16534         if (result != ISC_R_NOTFOUND)
16535                 goto failure;
16536
16537         result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
16538
16539  failure:
16540         if (node != NULL)
16541                 dns_db_detachnode(db, &node);
16542         return (result);
16543 }
16544
16545 /*
16546  * Given an RRSIG rdataset and an algorithm, determine whether there
16547  * are any signatures using that algorithm.
16548  */
16549 static isc_boolean_t
16550 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
16551         dns_rdata_t rdata = DNS_RDATA_INIT;
16552         dns_rdata_rrsig_t rrsig;
16553         isc_result_t result;
16554
16555         REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
16556         if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
16557                 return (ISC_FALSE);
16558         }
16559
16560         for (result = dns_rdataset_first(rdataset);
16561              result == ISC_R_SUCCESS;
16562              result = dns_rdataset_next(rdataset))
16563         {
16564                 dns_rdataset_current(rdataset, &rdata);
16565                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
16566                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16567                 dns_rdata_reset(&rdata);
16568                 if (rrsig.algorithm == alg)
16569                         return (ISC_TRUE);
16570         }
16571
16572         return (ISC_FALSE);
16573 }
16574
16575 static isc_result_t
16576 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16577            dns_diff_t *diff)
16578 {
16579         dns_name_t *origin;
16580         isc_boolean_t build_nsec3;
16581         isc_result_t result;
16582
16583         origin = dns_db_origin(db);
16584         CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
16585                                  &build_nsec3));
16586         if (build_nsec3)
16587                 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
16588                                            ISC_FALSE, zone->privatetype, diff));
16589         CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
16590
16591  failure:
16592         return (result);
16593 }
16594
16595 static void
16596 zone_rekey(dns_zone_t *zone) {
16597         isc_result_t result;
16598         dns_db_t *db = NULL;
16599         dns_dbnode_t *node = NULL;
16600         dns_dbversion_t *ver = NULL;
16601         dns_rdataset_t soaset, soasigs, keyset, keysigs;
16602         dns_dnsseckeylist_t dnskeys, keys, rmkeys;
16603         dns_dnsseckey_t *key;
16604         dns_diff_t diff, _sig_diff;
16605         zonediff_t zonediff;
16606         isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
16607         isc_boolean_t newalg = ISC_FALSE;
16608         isc_boolean_t fullsign;
16609         dns_ttl_t ttl = 3600;
16610         const char *dir;
16611         isc_mem_t *mctx;
16612         isc_stdtime_t now;
16613         isc_time_t timenow;
16614         isc_interval_t ival;
16615         char timebuf[80];
16616
16617         REQUIRE(DNS_ZONE_VALID(zone));
16618
16619         ISC_LIST_INIT(dnskeys);
16620         ISC_LIST_INIT(keys);
16621         ISC_LIST_INIT(rmkeys);
16622         dns_rdataset_init(&soaset);
16623         dns_rdataset_init(&soasigs);
16624         dns_rdataset_init(&keyset);
16625         dns_rdataset_init(&keysigs);
16626         dir = dns_zone_getkeydirectory(zone);
16627         mctx = zone->mctx;
16628         dns_diff_init(mctx, &diff);
16629         dns_diff_init(mctx, &_sig_diff);
16630         zonediff_init(&zonediff, &_sig_diff);
16631
16632         CHECK(dns_zone_getdb(zone, &db));
16633         CHECK(dns_db_newversion(db, &ver));
16634         CHECK(dns_db_getoriginnode(db, &node));
16635
16636         TIME_NOW(&timenow);
16637         now = isc_time_seconds(&timenow);
16638
16639         dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
16640
16641         /* Get the SOA record's TTL */
16642         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
16643                                   dns_rdatatype_none, 0, &soaset, &soasigs));
16644         ttl = soaset.ttl;
16645         dns_rdataset_disassociate(&soaset);
16646
16647         /* Get the DNSKEY rdataset */
16648         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16649                                      dns_rdatatype_none, 0, &keyset, &keysigs);
16650         if (result == ISC_R_SUCCESS) {
16651                 ttl = keyset.ttl;
16652                 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
16653                                                      mctx, &keyset,
16654                                                      &keysigs, &soasigs,
16655                                                      ISC_FALSE, ISC_FALSE,
16656                                                      &dnskeys));
16657         } else if (result != ISC_R_NOTFOUND)
16658                 goto failure;
16659
16660         /*
16661          * True when called from "rndc sign".  Indicates the zone should be
16662          * fully signed now.
16663          */
16664         fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
16665
16666         result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
16667         if (result == ISC_R_SUCCESS) {
16668                 isc_boolean_t check_ksk;
16669                 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16670
16671                 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
16672                                                &zone->origin, ttl, &diff,
16673                                                ISC_TF(!check_ksk),
16674                                                mctx, logmsg);
16675
16676                 /* Keys couldn't be updated for some reason;
16677                  * try again later. */
16678                 if (result != ISC_R_SUCCESS) {
16679                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
16680                                      "couldn't update zone keys: %s",
16681                                      isc_result_totext(result));
16682                         goto failure;
16683                 }
16684
16685                 /*
16686                  * See if any pre-existing keys have newly become active;
16687                  * also, see if any new key is for a new algorithm, as in that
16688                  * event, we need to sign the zone fully.  (If there's a new
16689                  * key, but it's for an already-existing algorithm, then
16690                  * the zone signing can be handled incrementally.)
16691                  */
16692                 for (key = ISC_LIST_HEAD(dnskeys);
16693                      key != NULL;
16694                      key = ISC_LIST_NEXT(key, link)) {
16695                         if (!key->first_sign)
16696                                 continue;
16697
16698                         newactive = ISC_TRUE;
16699
16700                         if (!dns_rdataset_isassociated(&keysigs)) {
16701                                 newalg = ISC_TRUE;
16702                                 break;
16703                         }
16704
16705                         if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
16706                                 /*
16707                                  * This isn't a new algorithm; clear
16708                                  * first_sign so we won't sign the
16709                                  * whole zone with this key later
16710                                  */
16711                                 key->first_sign = ISC_FALSE;
16712                         } else {
16713                                 newalg = ISC_TRUE;
16714                                 break;
16715                         }
16716                 }
16717
16718                 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
16719                     dnskey_sane(zone, db, ver, &diff)) {
16720                         CHECK(dns_diff_apply(&diff, db, ver));
16721                         CHECK(clean_nsec3param(zone, db, ver, &diff));
16722                         CHECK(add_signing_records(db, zone->privatetype,
16723                                                   ver, &diff,
16724                                                   ISC_TF(newalg || fullsign)));
16725                         CHECK(update_soa_serial(db, ver, &diff, mctx,
16726                                                 zone->updatemethod));
16727                         CHECK(add_chains(zone, db, ver, &diff));
16728                         CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
16729                         CHECK(zone_journal(zone, zonediff.diff, NULL,
16730                                            "zone_rekey"));
16731                         commit = ISC_TRUE;
16732                 }
16733         }
16734
16735         dns_db_closeversion(db, &ver, ISC_TRUE);
16736
16737         if (commit) {
16738                 dns_difftuple_t *tuple;
16739
16740                 LOCK_ZONE(zone);
16741                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16742
16743                 zone_needdump(zone, DNS_DUMP_DELAY);
16744
16745                 zone_settimer(zone, &timenow);
16746
16747                 /* Remove any signatures from removed keys.  */
16748                 if (!ISC_LIST_EMPTY(rmkeys)) {
16749                         for (key = ISC_LIST_HEAD(rmkeys);
16750                              key != NULL;
16751                              key = ISC_LIST_NEXT(key, link)) {
16752                                 result = zone_signwithkey(zone,
16753                                                           dst_key_alg(key->key),
16754                                                           dst_key_id(key->key),
16755                                                           ISC_TRUE);
16756                                 if (result != ISC_R_SUCCESS) {
16757                                         dns_zone_log(zone, ISC_LOG_ERROR,
16758                                              "zone_signwithkey failed: %s",
16759                                              dns_result_totext(result));
16760                                 }
16761                         }
16762                 }
16763
16764                 if (fullsign) {
16765                         /*
16766                          * "rndc sign" was called, so we now sign the zone
16767                          * with all active keys, whether they're new or not.
16768                          */
16769                         for (key = ISC_LIST_HEAD(dnskeys);
16770                              key != NULL;
16771                              key = ISC_LIST_NEXT(key, link)) {
16772                                 if (!key->force_sign && !key->hint_sign)
16773                                         continue;
16774
16775                                 result = zone_signwithkey(zone,
16776                                                           dst_key_alg(key->key),
16777                                                           dst_key_id(key->key),
16778                                                           ISC_FALSE);
16779                                 if (result != ISC_R_SUCCESS) {
16780                                         dns_zone_log(zone, ISC_LOG_ERROR,
16781                                              "zone_signwithkey failed: %s",
16782                                              dns_result_totext(result));
16783                                 }
16784                         }
16785                 } else if (newalg) {
16786                         /*
16787                          * We haven't been told to sign fully, but a new
16788                          * algorithm was added to the DNSKEY.  We sign
16789                          * the full zone, but only with newly active
16790                          * keys.
16791                          */
16792                         for (key = ISC_LIST_HEAD(dnskeys);
16793                              key != NULL;
16794                              key = ISC_LIST_NEXT(key, link)) {
16795                                 if (!key->first_sign)
16796                                         continue;
16797
16798                                 result = zone_signwithkey(zone,
16799                                                           dst_key_alg(key->key),
16800                                                           dst_key_id(key->key),
16801                                                           ISC_FALSE);
16802                                 if (result != ISC_R_SUCCESS) {
16803                                         dns_zone_log(zone, ISC_LOG_ERROR,
16804                                              "zone_signwithkey failed: %s",
16805                                              dns_result_totext(result));
16806                                 }
16807                         }
16808                 }
16809
16810                 /*
16811                  * Clear fullsign flag, if it was set, so we don't do
16812                  * another full signing next time
16813                  */
16814                 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
16815
16816                 /*
16817                  * Cause the zone to add/delete NSEC3 chains for the
16818                  * deferred NSEC3PARAM changes.
16819                  */
16820                 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
16821                      tuple != NULL;
16822                      tuple = ISC_LIST_NEXT(tuple, link)) {
16823                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16824                         dns_rdata_t rdata = DNS_RDATA_INIT;
16825                         dns_rdata_nsec3param_t nsec3param;
16826
16827                         if (tuple->rdata.type != zone->privatetype ||
16828                             tuple->op != DNS_DIFFOP_ADD)
16829                                 continue;
16830
16831                         if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
16832                                                         buf, sizeof(buf)))
16833                                 continue;
16834                         result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
16835                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
16836                         if (nsec3param.flags == 0)
16837                                 continue;
16838
16839                         result = zone_addnsec3chain(zone, &nsec3param);
16840                         if (result != ISC_R_SUCCESS) {
16841                                 dns_zone_log(zone, ISC_LOG_ERROR,
16842                                              "zone_addnsec3chain failed: %s",
16843                                              dns_result_totext(result));
16844                         }
16845                 }
16846
16847                 /*
16848                  * Activate any NSEC3 chain updates that may have
16849                  * been scheduled before this rekey.
16850                  */
16851                 if (fullsign || newalg)
16852                         resume_addnsec3chain(zone);
16853
16854                 /*
16855                  * Schedule the next resigning event
16856                  */
16857                 set_resigntime(zone);
16858                 UNLOCK_ZONE(zone);
16859         }
16860
16861         isc_time_settoepoch(&zone->refreshkeytime);
16862
16863         /*
16864          * If we're doing key maintenance, set the key refresh timer to
16865          * the next scheduled key event or to 'dnssec-loadkeys-interval'
16866          * seconds in the future, whichever is sooner.
16867          */
16868         if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
16869                 isc_time_t timethen;
16870                 isc_stdtime_t then;
16871
16872                 LOCK_ZONE(zone);
16873                 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
16874                                   &timethen);
16875                 zone->refreshkeytime = timethen;
16876                 UNLOCK_ZONE(zone);
16877
16878                 for (key = ISC_LIST_HEAD(dnskeys);
16879                      key != NULL;
16880                      key = ISC_LIST_NEXT(key, link)) {
16881                         then = now;
16882                         result = next_keyevent(key->key, &then);
16883                         if (result != ISC_R_SUCCESS)
16884                                 continue;
16885
16886                         DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
16887                         LOCK_ZONE(zone);
16888                         if (isc_time_compare(&timethen,
16889                                              &zone->refreshkeytime) < 0) {
16890                                 zone->refreshkeytime = timethen;
16891                         }
16892                         UNLOCK_ZONE(zone);
16893                 }
16894
16895                 zone_settimer(zone, &timenow);
16896
16897                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
16898                 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
16899         }
16900
16901  done:
16902         dns_diff_clear(&diff);
16903         dns_diff_clear(&_sig_diff);
16904
16905         clear_keylist(&dnskeys, mctx);
16906         clear_keylist(&keys, mctx);
16907         clear_keylist(&rmkeys, mctx);
16908
16909         if (ver != NULL)
16910                 dns_db_closeversion(db, &ver, ISC_FALSE);
16911         if (dns_rdataset_isassociated(&keyset))
16912                 dns_rdataset_disassociate(&keyset);
16913         if (dns_rdataset_isassociated(&keysigs))
16914                 dns_rdataset_disassociate(&keysigs);
16915         if (dns_rdataset_isassociated(&soasigs))
16916                 dns_rdataset_disassociate(&soasigs);
16917         if (node != NULL)
16918                 dns_db_detachnode(db, &node);
16919         if (db != NULL)
16920                 dns_db_detach(&db);
16921
16922         INSIST(ver == NULL);
16923         return;
16924
16925  failure:
16926         /*
16927          * Something went wrong; try again in ten minutes or
16928          * after a key refresh interval, whichever is shorter.
16929          */
16930         isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
16931         isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
16932         goto done;
16933 }
16934
16935 void
16936 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
16937         isc_time_t now;
16938
16939         if (zone->type == dns_zone_master && zone->task != NULL) {
16940                 LOCK_ZONE(zone);
16941
16942                 if (fullsign)
16943                         zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
16944
16945                 TIME_NOW(&now);
16946                 zone->refreshkeytime = now;
16947                 zone_settimer(zone, &now);
16948
16949                 UNLOCK_ZONE(zone);
16950         }
16951 }
16952
16953 isc_result_t
16954 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
16955                  unsigned int *errors)
16956 {
16957         isc_result_t result;
16958         dns_dbnode_t *node = NULL;
16959
16960         REQUIRE(DNS_ZONE_VALID(zone));
16961         REQUIRE(errors != NULL);
16962
16963         result = dns_db_getoriginnode(db, &node);
16964         if (result != ISC_R_SUCCESS)
16965                 return (result);
16966         result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
16967                                   ISC_FALSE);
16968         dns_db_detachnode(db, &node);
16969         return (result);
16970 }
16971
16972 isc_result_t
16973 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
16974         isc_result_t result;
16975         dns_dbnode_t *node = NULL;
16976         dns_rdataset_t dnskey, cds, cdnskey;
16977         unsigned char buffer[DNS_DS_BUFFERSIZE];
16978         unsigned char algorithms[256];
16979         unsigned int i;
16980
16981         REQUIRE(DNS_ZONE_VALID(zone));
16982
16983         result = dns_db_getoriginnode(db, &node);
16984         if (result != ISC_R_SUCCESS)
16985                 return (result);
16986
16987         dns_rdataset_init(&cds);
16988         dns_rdataset_init(&dnskey);
16989         dns_rdataset_init(&cdnskey);
16990
16991         result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
16992                                      dns_rdatatype_none, 0, &cds, NULL);
16993         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
16994                 goto failure;
16995
16996         result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
16997                                      dns_rdatatype_none, 0, &cdnskey, NULL);
16998         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
16999                 goto failure;
17000
17001         if (!dns_rdataset_isassociated(&cds) &&
17002             !dns_rdataset_isassociated(&cdnskey)) {
17003                 result = ISC_R_SUCCESS;
17004                 goto failure;
17005         }
17006
17007         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
17008                                      dns_rdatatype_none, 0, &dnskey, NULL);
17009         if (result == ISC_R_NOTFOUND) {
17010                 if (dns_rdataset_isassociated(&cds))
17011                         result = DNS_R_BADCDS;
17012                 else
17013                         result = DNS_R_BADCDNSKEY;
17014                 goto failure;
17015         }
17016         if (result != ISC_R_SUCCESS)
17017                 goto failure;
17018
17019         /*
17020          * For each DNSSEC algorithm in the CDS RRset there must be
17021          * a matching DNSKEY record.
17022          */
17023         if (dns_rdataset_isassociated(&cds)) {
17024                 memset(algorithms, 0, sizeof(algorithms));
17025                 for (result = dns_rdataset_first(&cds);
17026                      result == ISC_R_SUCCESS;
17027                      result = dns_rdataset_next(&cds)) {
17028                         dns_rdata_t crdata = DNS_RDATA_INIT;
17029                         dns_rdata_cds_t structcds;
17030
17031                         dns_rdataset_current(&cds, &crdata);
17032                         CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
17033                         if (algorithms[structcds.algorithm] == 0)
17034                                 algorithms[structcds.algorithm] = 1;
17035                         for (result = dns_rdataset_first(&dnskey);
17036                              result == ISC_R_SUCCESS;
17037                              result = dns_rdataset_next(&dnskey)) {
17038                                 dns_rdata_t rdata = DNS_RDATA_INIT;
17039                                 dns_rdata_t dsrdata = DNS_RDATA_INIT;
17040
17041                                 dns_rdataset_current(&dnskey, &rdata);
17042                                 CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
17043                                                         structcds.digest_type,
17044                                                         buffer, &dsrdata));
17045                                 if (crdata.length == dsrdata.length &&
17046                                     memcmp(crdata.data, dsrdata.data,
17047                                            dsrdata.length) == 0) {
17048                                         algorithms[structcds.algorithm] = 2;
17049                                 }
17050                         }
17051                         if (result != ISC_R_NOMORE)
17052                                 goto failure;
17053                 }
17054                 for (i = 0; i < sizeof(algorithms); i++) {
17055                         if (algorithms[i] == 1) {
17056                                 result = DNS_R_BADCDNSKEY;
17057                                 goto failure;
17058                         }
17059                 }
17060         }
17061
17062         /*
17063          * For each DNSSEC algorithm in the CDNSKEY RRset there must be
17064          * a matching DNSKEY record.
17065          */
17066         if (dns_rdataset_isassociated(&cdnskey)) {
17067                 memset(algorithms, 0, sizeof(algorithms));
17068                 for (result = dns_rdataset_first(&cdnskey);
17069                      result == ISC_R_SUCCESS;
17070                      result = dns_rdataset_next(&cdnskey)) {
17071                         dns_rdata_t crdata = DNS_RDATA_INIT;
17072                         dns_rdata_cdnskey_t structcdnskey;
17073
17074                         dns_rdataset_current(&cdnskey, &crdata);
17075                         CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
17076                                                  NULL));
17077                         if (algorithms[structcdnskey.algorithm] == 0)
17078                                 algorithms[structcdnskey.algorithm] = 1;
17079                         for (result = dns_rdataset_first(&dnskey);
17080                              result == ISC_R_SUCCESS;
17081                              result = dns_rdataset_next(&dnskey)) {
17082                                 dns_rdata_t rdata = DNS_RDATA_INIT;
17083
17084                                 dns_rdataset_current(&dnskey, &rdata);
17085                                 if (crdata.length == rdata.length &&
17086                                     memcmp(crdata.data, rdata.data,
17087                                            rdata.length) == 0) {
17088                                         algorithms[structcdnskey.algorithm] = 2;
17089                                 }
17090                         }
17091                         if (result != ISC_R_NOMORE)
17092                                 goto failure;
17093                 }
17094                 for (i = 0; i < sizeof(algorithms); i++) {
17095                         if (algorithms[i] == 1) {
17096                                 result = DNS_R_BADCDS;
17097                                 goto failure;
17098                         }
17099                 }
17100         }
17101         result = ISC_R_SUCCESS;
17102
17103  failure:
17104         if (dns_rdataset_isassociated(&cds))
17105                 dns_rdataset_disassociate(&cds);
17106         if (dns_rdataset_isassociated(&dnskey))
17107                 dns_rdataset_disassociate(&dnskey);
17108         if (dns_rdataset_isassociated(&cdnskey))
17109                 dns_rdataset_disassociate(&cdnskey);
17110         dns_db_detachnode(db, &node);
17111         return (result);
17112 }
17113
17114 void
17115 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
17116         REQUIRE(DNS_ZONE_VALID(zone));
17117         LOCK_ZONE(zone);
17118         zone->added = added;
17119         UNLOCK_ZONE(zone);
17120 }
17121
17122 isc_boolean_t
17123 dns_zone_getadded(dns_zone_t *zone) {
17124         REQUIRE(DNS_ZONE_VALID(zone));
17125         return (zone->added);
17126 }
17127
17128 isc_result_t
17129 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
17130 {
17131         isc_time_t loadtime;
17132         isc_result_t result;
17133         dns_zone_t *secure = NULL;
17134
17135         TIME_NOW(&loadtime);
17136
17137         /*
17138          * Lock hierarchy: zmgr, zone, raw.
17139          */
17140  again:
17141         LOCK_ZONE(zone);
17142         if (inline_secure(zone))
17143                 LOCK_ZONE(zone->raw);
17144         else if (inline_raw(zone)) {
17145                 secure = zone->secure;
17146                 TRYLOCK_ZONE(result, secure);
17147                 if (result != ISC_R_SUCCESS) {
17148                         UNLOCK_ZONE(zone);
17149                         secure = NULL;
17150 #if ISC_PLATFORM_USETHREADS
17151                         isc_thread_yield();
17152 #endif
17153                         goto again;
17154                 }
17155         }
17156         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
17157         if (inline_secure(zone))
17158                 UNLOCK_ZONE(zone->raw);
17159         else if (secure != NULL)
17160                 UNLOCK_ZONE(secure);
17161         UNLOCK_ZONE(zone);
17162         return result;
17163 }
17164
17165 isc_result_t
17166 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
17167         REQUIRE(DNS_ZONE_VALID(zone));
17168         if (interval == 0)
17169                 return (ISC_R_RANGE);
17170         /* Maximum value: 24 hours (3600 minutes) */
17171         if (interval > (24 * 60))
17172                 interval = (24 * 60);
17173         /* Multiply by 60 for seconds */
17174         zone->refreshkeyinterval = interval * 60;
17175         return (ISC_R_SUCCESS);
17176 }
17177
17178 void
17179 dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) {
17180         REQUIRE(DNS_ZONE_VALID(zone));
17181         zone->requestixfr = flag;
17182 }
17183
17184 isc_boolean_t
17185 dns_zone_getrequestixfr(dns_zone_t *zone) {
17186         REQUIRE(DNS_ZONE_VALID(zone));
17187         return (zone->requestixfr);
17188 }
17189
17190 void
17191 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
17192         REQUIRE(DNS_ZONE_VALID(zone));
17193         zone->updatemethod = method;
17194 }
17195
17196 dns_updatemethod_t
17197 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
17198         REQUIRE(DNS_ZONE_VALID(zone));
17199         return(zone->updatemethod);
17200 }
17201
17202 /*
17203  * Lock hierarchy: zmgr, zone, raw.
17204  */
17205 isc_result_t
17206 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
17207         isc_result_t result;
17208         dns_zonemgr_t *zmgr;
17209
17210         REQUIRE(DNS_ZONE_VALID(zone));
17211         REQUIRE(zone->zmgr != NULL);
17212         REQUIRE(zone->task != NULL);
17213         REQUIRE(zone->loadtask != NULL);
17214         REQUIRE(zone->raw == NULL);
17215
17216         REQUIRE(DNS_ZONE_VALID(raw));
17217         REQUIRE(raw->zmgr == NULL);
17218         REQUIRE(raw->task == NULL);
17219         REQUIRE(raw->loadtask == NULL);
17220         REQUIRE(raw->secure == NULL);
17221
17222         /*
17223          * Lock hierarchy: zmgr, zone, raw.
17224          */
17225         zmgr = zone->zmgr;
17226         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17227         LOCK_ZONE(zone);
17228         LOCK_ZONE(raw);
17229
17230         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
17231                                   NULL, NULL, zone->task, zone_timer, raw,
17232                                   &raw->timer);
17233         if (result != ISC_R_SUCCESS)
17234                 goto unlock;
17235
17236         /*
17237          * The timer "holds" a iref.
17238          */
17239         raw->irefs++;
17240         INSIST(raw->irefs != 0);
17241
17242
17243         /* dns_zone_attach(raw, &zone->raw); */
17244         isc_refcount_increment(&raw->erefs, NULL);
17245         zone->raw = raw;
17246
17247         /* dns_zone_iattach(zone,  &raw->secure); */
17248         zone_iattach(zone, &raw->secure);
17249
17250         isc_task_attach(zone->task, &raw->task);
17251         isc_task_attach(zone->loadtask, &raw->loadtask);
17252
17253         ISC_LIST_APPEND(zmgr->zones, raw, link);
17254         raw->zmgr = zmgr;
17255         zmgr->refs++;
17256
17257  unlock:
17258         UNLOCK_ZONE(raw);
17259         UNLOCK_ZONE(zone);
17260         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17261         return (result);
17262 }
17263
17264 void
17265 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
17266         REQUIRE(DNS_ZONE_VALID(zone));
17267         REQUIRE(raw != NULL && *raw == NULL);
17268
17269         LOCK(&zone->lock);
17270         if (zone->raw != NULL)
17271                 dns_zone_attach(zone->raw, raw);
17272         UNLOCK(&zone->lock);
17273 }
17274
17275 struct keydone {
17276         isc_event_t event;
17277         isc_boolean_t all;
17278         unsigned char data[5];
17279 };
17280
17281 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
17282
17283 static void
17284 keydone(isc_task_t *task, isc_event_t *event) {
17285         const char *me = "keydone";
17286         isc_boolean_t commit = ISC_FALSE;
17287         isc_result_t result;
17288         dns_rdata_t rdata = DNS_RDATA_INIT;
17289         dns_dbversion_t *oldver = NULL, *newver = NULL;
17290         dns_zone_t *zone;
17291         dns_db_t *db = NULL;
17292         dns_dbnode_t *node = NULL;
17293         dns_rdataset_t rdataset;
17294         dns_diff_t diff;
17295         struct keydone *kd = (struct keydone *)event;
17296         dns_update_log_t log = { update_log_cb, NULL };
17297         isc_boolean_t clear_pending = ISC_FALSE;
17298
17299         UNUSED(task);
17300
17301         zone = event->ev_arg;
17302         INSIST(DNS_ZONE_VALID(zone));
17303
17304         ENTER;
17305
17306         dns_rdataset_init(&rdataset);
17307         dns_diff_init(zone->mctx, &diff);
17308
17309         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17310         if (zone->db != NULL) {
17311                 dns_db_attach(zone->db, &db);
17312                 dns_db_currentversion(db, &oldver);
17313                 result = dns_db_newversion(db, &newver);
17314                 if (result != ISC_R_SUCCESS) {
17315                         dns_zone_log(zone, ISC_LOG_ERROR,
17316                                      "keydone:dns_db_newversion -> %s",
17317                                      dns_result_totext(result));
17318                         goto failure;
17319                 }
17320         }
17321         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17322         if (db == NULL)
17323                 goto failure;
17324
17325         result = dns_db_getoriginnode(db, &node);
17326         if (result != ISC_R_SUCCESS)
17327                 goto failure;
17328
17329         result = dns_db_findrdataset(db, node, newver, zone->privatetype,
17330                                      dns_rdatatype_none, 0, &rdataset, NULL);
17331         if (result == ISC_R_NOTFOUND) {
17332                 INSIST(!dns_rdataset_isassociated(&rdataset));
17333                 goto failure;
17334         }
17335         if (result != ISC_R_SUCCESS) {
17336                 INSIST(!dns_rdataset_isassociated(&rdataset));
17337                 goto failure;
17338         }
17339
17340         for (result = dns_rdataset_first(&rdataset);
17341              result == ISC_R_SUCCESS;
17342              result = dns_rdataset_next(&rdataset)) {
17343                 isc_boolean_t found = ISC_FALSE;
17344
17345                 dns_rdataset_current(&rdataset, &rdata);
17346
17347                 if (kd->all) {
17348                         if (rdata.length == 5 && rdata.data[0] != 0 &&
17349                                rdata.data[3] == 0 && rdata.data[4] == 1)
17350                                 found = ISC_TRUE;
17351                         else if (rdata.data[0] == 0 &&
17352                                  (rdata.data[2] & PENDINGFLAGS) != 0) {
17353                                 found = ISC_TRUE;
17354                                 clear_pending = ISC_TRUE;
17355                         }
17356                 } else if (rdata.length == 5 &&
17357                            memcmp(rdata.data, kd->data, 5) == 0)
17358                         found = ISC_TRUE;
17359
17360                 if (found)
17361                         CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
17362                                             &zone->origin, rdataset.ttl,
17363                                             &rdata));
17364                 dns_rdata_reset(&rdata);
17365         }
17366
17367         if (!ISC_LIST_EMPTY(diff.tuples)) {
17368                 /* Write changes to journal file. */
17369                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
17370                                         zone->updatemethod));
17371
17372                 result = dns_update_signatures(&log, zone, db,
17373                                                oldver, newver, &diff,
17374                                                zone->sigvalidityinterval);
17375                 if (!clear_pending)
17376                         CHECK(result);
17377
17378                 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
17379                 commit = ISC_TRUE;
17380
17381                 LOCK_ZONE(zone);
17382                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
17383                 zone_needdump(zone, 30);
17384                 UNLOCK_ZONE(zone);
17385         }
17386
17387  failure:
17388         if (dns_rdataset_isassociated(&rdataset))
17389                 dns_rdataset_disassociate(&rdataset);
17390         if (db != NULL) {
17391                 if (node != NULL)
17392                         dns_db_detachnode(db, &node);
17393                 if (oldver != NULL)
17394                         dns_db_closeversion(db, &oldver, ISC_FALSE);
17395                 if (newver != NULL)
17396                         dns_db_closeversion(db, &newver, commit);
17397                 dns_db_detach(&db);
17398         }
17399         dns_diff_clear(&diff);
17400         isc_event_free(&event);
17401         dns_zone_idetach(&zone);
17402
17403         INSIST(oldver == NULL);
17404         INSIST(newver == NULL);
17405 }
17406
17407 isc_result_t
17408 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
17409         isc_result_t result = ISC_R_SUCCESS;
17410         isc_event_t *e;
17411         isc_buffer_t b;
17412         dns_zone_t *dummy = NULL;
17413         struct keydone *kd;
17414
17415         REQUIRE(DNS_ZONE_VALID(zone));
17416
17417         LOCK_ZONE(zone);
17418
17419         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
17420                                zone, sizeof(struct keydone));
17421         if (e == NULL) {
17422                 result = ISC_R_NOMEMORY;
17423                 goto failure;
17424         }
17425
17426         kd = (struct keydone *) e;
17427         if (strcasecmp(keystr, "all") == 0)
17428                 kd->all = ISC_TRUE;
17429         else {
17430                 isc_textregion_t r;
17431                 char *algstr;
17432                 dns_keytag_t keyid;
17433                 dns_secalg_t alg;
17434                 size_t n;
17435
17436                 kd->all = ISC_FALSE;
17437
17438                 n = sscanf(keystr, "%hd/", &keyid);
17439                 if (n == 0U)
17440                         CHECK(ISC_R_FAILURE);
17441
17442                 algstr = strchr(keystr, '/');
17443                 if (algstr != NULL)
17444                         algstr++;
17445                 else
17446                         CHECK(ISC_R_FAILURE);
17447
17448                 n = sscanf(algstr, "%hhd", &alg);
17449                 if (n == 0U) {
17450                         DE_CONST(algstr, r.base);
17451                         r.length = strlen(algstr);
17452                         CHECK(dns_secalg_fromtext(&alg, &r));
17453                 }
17454
17455                 /* construct a private-type rdata */
17456                 isc_buffer_init(&b, kd->data, sizeof(kd->data));
17457                 isc_buffer_putuint8(&b, alg);
17458                 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
17459                 isc_buffer_putuint8(&b, (keyid & 0xff));
17460                 isc_buffer_putuint8(&b, 0);
17461                 isc_buffer_putuint8(&b, 1);
17462         }
17463
17464         zone_iattach(zone, &dummy);
17465         isc_task_send(zone->task, &e);
17466
17467  failure:
17468         if (e != NULL)
17469                 isc_event_free(&e);
17470         UNLOCK_ZONE(zone);
17471         return (result);
17472 }
17473
17474 static void
17475 setnsec3param(isc_task_t *task, isc_event_t *event) {
17476         const char *me = "setnsec3param";
17477         isc_boolean_t commit = ISC_FALSE;
17478         isc_result_t result;
17479         dns_dbversion_t *oldver = NULL, *newver = NULL;
17480         dns_zone_t *zone;
17481         dns_db_t *db = NULL;
17482         dns_dbnode_t *node = NULL;
17483         dns_rdataset_t prdataset, nrdataset;
17484         dns_diff_t diff;
17485         struct np3event *npe = (struct np3event *)event;
17486         nsec3param_t *np;
17487         dns_update_log_t log = { update_log_cb, NULL };
17488         dns_rdata_t rdata;
17489         isc_boolean_t nseconly;
17490         isc_boolean_t exists = ISC_FALSE;
17491
17492         UNUSED(task);
17493
17494         zone = event->ev_arg;
17495         INSIST(DNS_ZONE_VALID(zone));
17496
17497         ENTER;
17498
17499         np = &npe->params;
17500
17501         dns_rdataset_init(&prdataset);
17502         dns_rdataset_init(&nrdataset);
17503         dns_diff_init(zone->mctx, &diff);
17504
17505         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17506         if (zone->db != NULL) {
17507                 dns_db_attach(zone->db, &db);
17508                 dns_db_currentversion(db, &oldver);
17509                 result = dns_db_newversion(db, &newver);
17510                 if (result != ISC_R_SUCCESS) {
17511                         dns_zone_log(zone, ISC_LOG_ERROR,
17512                                      "setnsec3param:dns_db_newversion -> %s",
17513                                      dns_result_totext(result));
17514                         goto failure;
17515                 }
17516         }
17517         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17518         if (db == NULL)
17519                 goto failure;
17520
17521         CHECK(dns_db_getoriginnode(db, &node));
17522
17523         /*
17524          * Does a private-type record already exist for this chain?
17525          */
17526         result = dns_db_findrdataset(db, node, newver, zone->privatetype,
17527                                      dns_rdatatype_none, 0, &prdataset, NULL);
17528         if (result == ISC_R_SUCCESS) {
17529                 for (result = dns_rdataset_first(&prdataset);
17530                      result == ISC_R_SUCCESS;
17531                      result = dns_rdataset_next(&prdataset)) {
17532                         dns_rdata_init(&rdata);
17533                         dns_rdataset_current(&prdataset, &rdata);
17534
17535                         if (np->length == rdata.length &&
17536                             memcmp(rdata.data, np->data, np->length) == 0) {
17537                                 exists = ISC_TRUE;
17538                                 break;
17539                         }
17540                 }
17541         } else if (result != ISC_R_NOTFOUND) {
17542                 INSIST(!dns_rdataset_isassociated(&prdataset));
17543                 goto failure;
17544         }
17545
17546         /*
17547          * Does the chain already exist?
17548          */
17549         result = dns_db_findrdataset(db, node, newver,
17550                                      dns_rdatatype_nsec3param,
17551                                      dns_rdatatype_none, 0, &nrdataset, NULL);
17552         if (result == ISC_R_SUCCESS) {
17553                 for (result = dns_rdataset_first(&nrdataset);
17554                      result == ISC_R_SUCCESS;
17555                      result = dns_rdataset_next(&nrdataset)) {
17556                         dns_rdata_init(&rdata);
17557                         dns_rdataset_current(&nrdataset, &rdata);
17558
17559                         if (np->length == (rdata.length + 1) &&
17560                             memcmp(rdata.data, np->data + 1,
17561                                    np->length - 1) == 0)
17562                         {
17563                                 exists = ISC_TRUE;
17564                                 break;
17565                         }
17566                 }
17567         } else if (result != ISC_R_NOTFOUND) {
17568                 INSIST(!dns_rdataset_isassociated(&nrdataset));
17569                 goto failure;
17570         }
17571
17572
17573         /*
17574          * We need to remove any existing NSEC3 chains.
17575          */
17576         if (!exists && np->replace && (np->length != 0 || np->nsec))
17577                 CHECK(dns_nsec3param_deletechains(db, newver, zone,
17578                                                   !np->nsec, &diff));
17579
17580         if (!exists && np->length != 0) {
17581                 /*
17582                  * We're creating an NSEC3 chain.
17583                  *
17584                  * If the zone is not currently capable of supporting
17585                  * an NSEC3 chain, add the INITIAL flag, so these
17586                  * parameters can be used later when NSEC3 becomes
17587                  * available.
17588                  */
17589                 dns_rdata_init(&rdata);
17590
17591                 np->data[2] |= DNS_NSEC3FLAG_CREATE;
17592                 result = dns_nsec_nseconly(db, newver, &nseconly);
17593                 if (result == ISC_R_NOTFOUND || nseconly)
17594                         np->data[2] |= DNS_NSEC3FLAG_INITIAL;
17595
17596                 rdata.length = np->length;
17597                 rdata.data = np->data;
17598                 rdata.type = zone->privatetype;
17599                 rdata.rdclass = zone->rdclass;
17600                 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
17601                                     &zone->origin, 0, &rdata));
17602         }
17603
17604         if (!ISC_LIST_EMPTY(diff.tuples)) {
17605                 /* Write changes to journal file. */
17606                 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
17607                                         zone->updatemethod));
17608                 result = dns_update_signatures(&log, zone, db,
17609                                                oldver, newver, &diff,
17610                                                zone->sigvalidityinterval);
17611                 if (result != ISC_R_NOTFOUND)
17612                         CHECK(result);
17613                 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
17614                 commit = ISC_TRUE;
17615
17616                 LOCK_ZONE(zone);
17617                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
17618                 zone_needdump(zone, 30);
17619                 UNLOCK_ZONE(zone);
17620         }
17621
17622  failure:
17623         if (dns_rdataset_isassociated(&prdataset))
17624                 dns_rdataset_disassociate(&prdataset);
17625         if (dns_rdataset_isassociated(&nrdataset))
17626                 dns_rdataset_disassociate(&nrdataset);
17627         if (node != NULL)
17628                 dns_db_detachnode(db, &node);
17629         if (oldver != NULL)
17630                 dns_db_closeversion(db, &oldver, ISC_FALSE);
17631         if (newver != NULL)
17632                 dns_db_closeversion(db, &newver, commit);
17633         if (db != NULL)
17634                 dns_db_detach(&db);
17635         if (commit)
17636                 resume_addnsec3chain(zone);
17637         dns_diff_clear(&diff);
17638         isc_event_free(&event);
17639         dns_zone_idetach(&zone);
17640
17641         INSIST(oldver == NULL);
17642         INSIST(newver == NULL);
17643 }
17644
17645 isc_result_t
17646 dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
17647                        isc_uint16_t iter, isc_uint8_t saltlen,
17648                        unsigned char *salt, isc_boolean_t replace)
17649 {
17650         isc_result_t result = ISC_R_SUCCESS;
17651         dns_rdata_nsec3param_t param;
17652         dns_rdata_t nrdata = DNS_RDATA_INIT;
17653         dns_rdata_t prdata = DNS_RDATA_INIT;
17654         unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
17655         struct np3event *npe;
17656         nsec3param_t *np;
17657         dns_zone_t *dummy = NULL;
17658         isc_buffer_t b;
17659         isc_event_t *e;
17660
17661         REQUIRE(DNS_ZONE_VALID(zone));
17662         REQUIRE(salt != NULL);
17663
17664         LOCK_ZONE(zone);
17665
17666         e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
17667                                setnsec3param, zone, sizeof(struct np3event));
17668         if (e == NULL) {
17669                 result = ISC_R_NOMEMORY;
17670                 goto failure;
17671         }
17672
17673         npe = (struct np3event *) e;
17674         np = &npe->params;
17675
17676         np->replace = replace;
17677         if (hash == 0) {
17678                 np->length = 0;
17679                 np->nsec = ISC_TRUE;
17680         } else {
17681                 param.common.rdclass = zone->rdclass;
17682                 param.common.rdtype = dns_rdatatype_nsec3param;
17683                 ISC_LINK_INIT(&param.common, link);
17684                 param.mctx = NULL;
17685                 param.hash = hash;
17686                 param.flags = flags;
17687                 param.iterations = iter;
17688                 param.salt_length = saltlen;
17689                 param.salt = salt;
17690                 isc_buffer_init(&b, nbuf, sizeof(nbuf));
17691                 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
17692                                            dns_rdatatype_nsec3param,
17693                                            &param, &b));
17694                 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
17695                                          np->data, sizeof(np->data));
17696                 np->length = prdata.length;
17697         }
17698
17699         zone_iattach(zone, &dummy);
17700         isc_task_send(zone->task, &e);
17701
17702  failure:
17703         if (e != NULL)
17704                 isc_event_free(&e);
17705         UNLOCK_ZONE(zone);
17706         return (result);
17707 }
17708
17709 void
17710 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
17711         REQUIRE(DNS_ZONE_VALID(zone));
17712
17713         zone->statlevel = level;
17714 }
17715
17716 dns_zonestat_level_t
17717 dns_zone_getstatlevel(dns_zone_t *zone) {
17718         REQUIRE(DNS_ZONE_VALID(zone));
17719
17720         return (zone->statlevel);
17721 }